mirror of
https://github.com/ruvnet/RuView
synced 2026-08-01 19:01:42 +00:00
feat(c6): ESP-NOW cross-node sync — D1 workaround for broken 15.4 RX
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>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @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
|
||||
Reference in New Issue
Block a user