mirror of
https://github.com/ruvnet/RuView
synced 2026-07-20 17:03:24 +00:00
948768bdda
ADR-110 P9 — software-only unblocks for the WITNESS-LOG-110 §B
hardware-blocked items. Two new modules, both default-off so v0.6.6 fleets
see no behavior change.
LP-core (B4 path):
- New firmware/esp32-csi-node/main/lp_core/main.c: real RISC-V LP-core
motion-gate program with debounce + monotonic motion_count counter.
- c6_lp_core.c rewritten to load + run the LP binary via ulp_lp_core_run
when CONFIG_C6_LP_CORE_ENABLE=y; falls back to the v0.6.6 ext1 GPIO-wake
path otherwise (keeps regression surface small).
- ulp_embed_binary() wired in main/CMakeLists.txt, gated on the Kconfig.
- New Kconfig knobs: C6_LP_POLL_PERIOD_US (default 10 ms),
C6_LP_DEBOUNCE_SAMPLES (default 3).
- Exposes c6_lp_core_motion_count() / c6_lp_core_poll_count() for the
witness harness — once an INA/Joulescope is on the bench, B4 is one
capture away from a measured number.
Soft-AP HE (B1/B2 unblock):
- New c6_softap_he.{h,c}: brings up the C6 in AP+STA mode with WPA2-PSK
+ HE advertisement, so a second C6 in STA mode can negotiate real
iTWT against a known-cooperative AP without buying an 11ax router.
- main.c calls c6_softap_he_start() right before esp_wifi_start() when
CONFIG_C6_SOFTAP_HE_ENABLE=y.
- New Kconfig knobs: C6_SOFTAP_HE_{SSID,PSK,CHANNEL} with NVS overrides
via softap_ssid / softap_psk / softap_chan in the ruview namespace.
Build artifacts (IDF v5.4, both green, RC=0):
- S3 8 MB: 1093 KB (47% partition slack)
- C6 4 MB: 1019 KB (45% partition slack)
- SHA-256 sums in dist/firmware-v0.6.7/SHA256SUMS.txt
Doc updates: CHANGELOG wave-3 entry, ADR-110 phase table gets P5
upgrade note + new P9 row, WITNESS-LOG-110 gets new A0 section
recording the v0.6.7 build evidence.
Co-Authored-By: claude-flow <ruv@ruv.net>
76 lines
2.8 KiB
C
76 lines
2.8 KiB
C
/**
|
|
* @file lp_core/main.c
|
|
* @brief LP RISC-V coprocessor motion-gate — ADR-110 Phase 5 (full).
|
|
*
|
|
* Polls a single LP-IO GPIO at LP_TIMER cadence (default 10 ms / 100 Hz),
|
|
* debounces N consecutive samples, and wakes the HP core when a confirmed
|
|
* transition matches the configured active-edge polarity. Counter +
|
|
* last-level are exported as shared symbols so the HP side can inspect
|
|
* them on wake.
|
|
*
|
|
* Shared symbols (HP-visible as `ulp_<name>` after `ulp_embed_binary`):
|
|
* - wake_gpio_num (input) : LP-IO index 0..7 on ESP32-C6
|
|
* - wake_active_high (input) : 1 = wake on rising stable, 0 = falling
|
|
* - debounce_samples (input) : consecutive matches required, default 3
|
|
* - motion_count (output) : monotonic wake-trigger counter
|
|
* - last_gpio_level (output) : level latched at the most recent wake
|
|
* - poll_count (output) : total LP-timer ticks observed (sanity)
|
|
*
|
|
* Defaults are written by HP via the `ulp_*` symbols before `ulp_lp_core_run()`,
|
|
* so the program is parameterised at boot without recompiling the LP binary.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "ulp_lp_core.h"
|
|
#include "ulp_lp_core_utils.h"
|
|
#include "ulp_lp_core_gpio.h"
|
|
|
|
/* --- Shared (HP/LP) state --- */
|
|
volatile uint32_t wake_gpio_num = 4; /* LP-IO 4 by default */
|
|
volatile uint32_t wake_active_high = 1; /* rising edge */
|
|
volatile uint32_t debounce_samples = 3;
|
|
volatile uint32_t motion_count = 0;
|
|
volatile uint32_t last_gpio_level = 0;
|
|
volatile uint32_t poll_count = 0;
|
|
|
|
/* --- Local state (persists across LP-timer wake cycles via .data) --- */
|
|
static uint32_t stable_run = 0;
|
|
static uint32_t prev_level = 0;
|
|
|
|
int main(void)
|
|
{
|
|
poll_count++;
|
|
|
|
/* LP-IO read returns 0/1 directly. The Kconfig-selected GPIO index maps
|
|
* 1:1 to LP_IO on C6 for indices 0..7. */
|
|
uint32_t level = (uint32_t)ulp_lp_core_gpio_get_level((lp_io_num_t)wake_gpio_num);
|
|
|
|
if (level == prev_level) {
|
|
if (stable_run < 0xFFFFu) stable_run++;
|
|
} else {
|
|
stable_run = 1;
|
|
prev_level = level;
|
|
}
|
|
|
|
/* Trigger when level matches the configured active polarity AND has been
|
|
* stable for `debounce_samples` consecutive reads. After firing, hold off
|
|
* until level returns to the inactive state to avoid re-triggering on
|
|
* the same continuous edge. */
|
|
static uint32_t armed = 1;
|
|
uint32_t want = wake_active_high ? 1 : 0;
|
|
|
|
if (armed && level == want && stable_run >= debounce_samples) {
|
|
motion_count++;
|
|
last_gpio_level = level;
|
|
armed = 0;
|
|
ulp_lp_core_wakeup_main_processor();
|
|
} else if (!armed && level != want && stable_run >= debounce_samples) {
|
|
/* Re-arm once the line has cleanly returned to the inactive state. */
|
|
armed = 1;
|
|
}
|
|
|
|
/* ulp_lp_core_halt() is called automatically when main returns. */
|
|
return 0;
|
|
}
|