mirror of
https://github.com/ruvnet/RuView
synced 2026-07-21 17:13:19 +00:00
88be283ab0
After 5 systematic experiments confirmed the 802.15.4 RX path is
unfixable from user code in this IDF v5.4 + C6 combination (D1), add a
parallel sync transport over ESP-NOW. Same TS_BEACON protocol, same
public API (c6_sync_espnow_get_epoch_us / is_valid / is_leader), but
runs on the WiFi MAC layer that ESP-IDF fully supports across every
ESP32 family.
The 802.15.4 code stays in source for when the IDF driver is fixed.
ESP-NOW is the working primary today.
Empirical (single-board COM9 — other 3 boards dropped off USB during
the experiment):
- c6_sync_espnow_init() succeeds: "init done local_id=… leader=
yes(candidate) period=100ms"
- TX path 100% reliable: tx#101 fail=0 over ~15s at 100ms cadence
- RX awaiting cross-board test once USB-enumeration is restored
Trade vs. 802.15.4 design:
- Loses: "frees WiFi airtime for CSI" property
- Gains: known-working RX path, cross-target (S3 and C6 both)
- Same API surface — consumers swap transports without code change
Files:
- main/c6_sync_espnow.{h,c} — new module, ~210 lines
- main/CMakeLists.txt — add to SRCS (always built, used on any target)
- main/main.c — init after WiFi STA up, skip on QEMU mock
- test/capture-3board-experiment.py — surface c6_espnow log lines
- docs/WITNESS-LOG-110.md — new §D-workaround documenting the pivot
Ref: ruvnet/RuView#762 / D1 known-issue / draft PR #764
Co-Authored-By: claude-flow <ruv@ruv.net>
60 lines
1.8 KiB
C
60 lines
1.8 KiB
C
/**
|
|
* @file c6_sync_espnow.h
|
|
* @brief ESP-NOW based cross-node time-sync — ADR-110 D1 workaround.
|
|
*
|
|
* After 4 systematic experiments confirmed the 802.15.4 RX path is broken
|
|
* in this user-code + IDF v5.4 combination (see WITNESS-LOG-110 §D1), the
|
|
* cross-node sync claim was unblocked by switching transport from IEEE
|
|
* 802.15.4 to ESP-NOW (WiFi-based peer-to-peer, runs on the same 2.4 GHz
|
|
* radio but uses the WiFi MAC layer that ESP-IDF's 802.11 driver fully
|
|
* supports).
|
|
*
|
|
* Trade vs. 802.15.4:
|
|
* - Loses the "frees WiFi airtime for CSI" property (uses WiFi for sync)
|
|
* - Gains a known-working RX path on every ESP32 family
|
|
* - Same API surface (epoch_us, is_valid, is_leader) so call sites that
|
|
* used to depend on c6_timesync drop in unchanged
|
|
*
|
|
* Works on both ESP32-S3 and ESP32-C6 — the cross-node sync becomes a
|
|
* cross-target feature, not C6-only.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "esp_err.h"
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
/**
|
|
* Initialize the ESP-NOW sync module. Must be called AFTER WiFi STA is
|
|
* connected (ESP-NOW needs the WiFi driver active).
|
|
*
|
|
* @return ESP_OK on success.
|
|
*/
|
|
esp_err_t c6_sync_espnow_init(void);
|
|
|
|
/**
|
|
* Returns the synced wall-clock estimate in microseconds.
|
|
* If no leader heard within the timeout, returns the local
|
|
* esp_timer_get_time() value unchanged (offset = 0).
|
|
*/
|
|
uint64_t c6_sync_espnow_get_epoch_us(void);
|
|
|
|
bool c6_sync_espnow_is_leader(void);
|
|
bool c6_sync_espnow_is_valid(void);
|
|
int64_t c6_sync_espnow_get_offset_us(void);
|
|
|
|
/* Counters for the witness harness — exposed for tests/diagnostics. */
|
|
uint32_t c6_sync_espnow_tx_count(void);
|
|
uint32_t c6_sync_espnow_tx_fail(void);
|
|
uint32_t c6_sync_espnow_rx_count(void);
|
|
uint32_t c6_sync_espnow_rx_magic_match(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|