feat(firmware): gate LED gamma viz behind CONFIG_LED_GAMMA_VIZ (ADR-183 follow-up) (#1129)
The 40 Hz gamma flicker is now Kconfig-gated (default y, unchanged behaviour). Set CONFIG_LED_GAMMA_VIZ=n for a dark, lower-power boot (the LED is simply cleared) — important for photosensitive deployments, no source edit needed. The colormap saturation point is now operator-tunable via CONFIG_LED_MOTION_FULLSCALE_MILLI (default 250 = 0.25). Build + flash confirmed on ESP32-S3 N16R8 (COM8): default y still arms the gamma timer, CSI flows. ADR-183 updated (gate moved from follow-up to done).
This commit is contained in:
parent
a4c2935a2f
commit
4bf88e1283
|
|
@ -74,11 +74,13 @@ therefore provably `ruv-neural-viz`'s, and the motion is provably real.
|
||||||
- Confirms #962's GPIO-48 fix visually (the LED lights on N16R8).
|
- Confirms #962's GPIO-48 fix visually (the LED lights on N16R8).
|
||||||
|
|
||||||
**Negative / risks**
|
**Negative / risks**
|
||||||
- Changes *default* firmware behaviour: the onboard LED now animates instead of staying
|
- Changes the *default* firmware behaviour: the onboard LED animates instead of staying
|
||||||
off (minor power + a visible flicker some may not want). Gate behind a Kconfig
|
off. Now **gated by `CONFIG_LED_GAMMA_VIZ`** (default `y`); set it `n` for a dark,
|
||||||
(`CONFIG_LED_GAMMA_VIZ`) if a dark default is preferred — follow-up.
|
lower-power boot (the LED is just cleared) — no source change needed.
|
||||||
- A 40 Hz flicker can be an issue for photosensitive users; document on the enclosure.
|
- A 40 Hz flicker can be an issue for photosensitive users; document on the enclosure
|
||||||
- `LED_MOTION_FULLSCALE` (0.25) is hand-tuned, not calibrated per-environment.
|
and disable `CONFIG_LED_GAMMA_VIZ` in those deployments.
|
||||||
|
- The saturation point is now `CONFIG_LED_MOTION_FULLSCALE_MILLI` (default 250 = 0.25),
|
||||||
|
operator-tunable; still not auto-calibrated per-environment.
|
||||||
- The colour uses a baked LUT, not the live Rust `ColorMap` (FFI path deferred — needs
|
- The colour uses a baked LUT, not the live Rust `ColorMap` (FFI path deferred — needs
|
||||||
the ESP Rust/xtensa toolchain, not yet in CI).
|
the ESP Rust/xtensa toolchain, not yet in CI).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -468,3 +468,29 @@ menu "Mock CSI (QEMU Testing)"
|
||||||
depends on CSI_MOCK_ENABLED
|
depends on CSI_MOCK_ENABLED
|
||||||
default n
|
default n
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "Onboard LED (ADR-183)"
|
||||||
|
|
||||||
|
config LED_GAMMA_VIZ
|
||||||
|
bool "Onboard WS2812: 40 Hz gamma flicker + CSI-motion colour"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Drive the onboard WS2812 as a GENUS-style 40 Hz gamma square wave
|
||||||
|
(12.5 ms on / 12.5 ms off, 50% duty). The ON-phase colour is live
|
||||||
|
CSI motion (edge motion_energy) mapped through the ruv-neural-viz
|
||||||
|
viridis colormap (still=purple, moving=yellow).
|
||||||
|
|
||||||
|
Disable to leave the LED off at boot — lower power, no flicker.
|
||||||
|
NOTE: a 40 Hz flicker can affect photosensitive users; disable or
|
||||||
|
shield the LED in those environments. Not a medical device.
|
||||||
|
|
||||||
|
config LED_MOTION_FULLSCALE_MILLI
|
||||||
|
int "Motion value (x1000) that saturates the colormap to yellow"
|
||||||
|
depends on LED_GAMMA_VIZ
|
||||||
|
default 250
|
||||||
|
range 1 100000
|
||||||
|
help
|
||||||
|
edge motion_energy that maps to the top (yellow) of the viridis
|
||||||
|
colormap, in milli-units (250 = 0.25). Lower = more sensitive
|
||||||
|
(reaches yellow with less motion).
|
||||||
|
endmenu
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ static void wifi_init_sta(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_LED_GAMMA_VIZ
|
||||||
/* Viridis colormap (60 steps), generated from ruv-neural-viz::ColorMap::viridis()
|
/* Viridis colormap (60 steps), generated from ruv-neural-viz::ColorMap::viridis()
|
||||||
* — the rUv-Neural brain-topology colormap, now no_std (ruvnet/ruv-neural#3 /
|
* — the rUv-Neural brain-topology colormap, now no_std (ruvnet/ruv-neural#3 /
|
||||||
* RuView#1126). Used as the ON-phase colour of the 40 Hz gamma flicker below:
|
* RuView#1126). Used as the ON-phase colour of the 40 Hz gamma flicker below:
|
||||||
|
|
@ -164,8 +165,8 @@ static const uint8_t VIRIDIS_LUT[60][3] = {
|
||||||
};
|
};
|
||||||
static led_strip_handle_t s_viz_led;
|
static led_strip_handle_t s_viz_led;
|
||||||
|
|
||||||
/* motion_energy that saturates the colormap to yellow (tunable). */
|
/* motion_energy that saturates the colormap to yellow (CONFIG, milli-units). */
|
||||||
#define LED_MOTION_FULLSCALE 0.25f
|
#define LED_MOTION_FULLSCALE ((float)CONFIG_LED_MOTION_FULLSCALE_MILLI / 1000.0f)
|
||||||
|
|
||||||
/* GENUS-style 40 Hz gamma flicker: full on/off square wave, 50% duty (toggled
|
/* GENUS-style 40 Hz gamma flicker: full on/off square wave, 50% duty (toggled
|
||||||
* every 12.5 ms → 40 Hz). The ON colour is live CSI motion (edge motion_energy)
|
* every 12.5 ms → 40 Hz). The ON colour is live CSI motion (edge motion_energy)
|
||||||
|
|
@ -189,6 +190,7 @@ static void led_gamma_40hz_cb(void *arg)
|
||||||
}
|
}
|
||||||
led_strip_refresh(s_viz_led);
|
led_strip_refresh(s_viz_led);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_LED_GAMMA_VIZ */
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
|
|
@ -219,10 +221,11 @@ void app_main(void)
|
||||||
ESP_LOGI(TAG, "%s CSI Node (ADR-018 / ADR-110) — v%s — Node ID: %d",
|
ESP_LOGI(TAG, "%s CSI Node (ADR-018 / ADR-110) — v%s — Node ID: %d",
|
||||||
target_name, app_desc->version, g_nvs_config.node_id);
|
target_name, app_desc->version, g_nvs_config.node_id);
|
||||||
|
|
||||||
/* Onboard WS2812: sweep the ruv-neural-viz viridis colormap at 40 Hz.
|
/* Onboard WS2812. C6 wires the LED to GPIO 8; S3 to GPIO 38 (DevKitC-1 v1.0)
|
||||||
* C6 dev boards wire the LED to GPIO 8; S3 boards to GPIO 38 (DevKitC-1 v1.0)
|
|
||||||
* or GPIO 48 (DevKitC-1 v1.1 / N16R8 — see #962). On S3 we drive 48 (the
|
* or GPIO 48 (DevKitC-1 v1.1 / N16R8 — see #962). On S3 we drive 48 (the
|
||||||
* common module). On C6, GPIO 38/48 don't exist (only 0-30) — gate by target. */
|
* common module). On C6, GPIO 38/48 don't exist (only 0-30) — gate by target.
|
||||||
|
* Behaviour is set by CONFIG_LED_GAMMA_VIZ (ADR-183): on = 40 Hz gamma flicker
|
||||||
|
* coloured by CSI motion; off = clear the LED at boot. */
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C6)
|
#if defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||||
const int led_gpio = 8;
|
const int led_gpio = 8;
|
||||||
#else
|
#else
|
||||||
|
|
@ -239,6 +242,7 @@ void app_main(void)
|
||||||
.resolution_hz = 10 * 1000 * 1000, // 10MHz
|
.resolution_hz = 10 * 1000 * 1000, // 10MHz
|
||||||
.flags.with_dma = false,
|
.flags.with_dma = false,
|
||||||
};
|
};
|
||||||
|
#if CONFIG_LED_GAMMA_VIZ
|
||||||
if (led_strip_new_rmt_device(&strip_config, &rmt_config, &s_viz_led) == ESP_OK) {
|
if (led_strip_new_rmt_device(&strip_config, &rmt_config, &s_viz_led) == ESP_OK) {
|
||||||
const esp_timer_create_args_t viz_args = {
|
const esp_timer_create_args_t viz_args = {
|
||||||
.callback = &led_gamma_40hz_cb,
|
.callback = &led_gamma_40hz_cb,
|
||||||
|
|
@ -250,6 +254,14 @@ void app_main(void)
|
||||||
ESP_LOGI(TAG, "Onboard WS2812: 40 Hz gamma flicker (GENUS), colour=CSI motion via ruv-neural-viz, GPIO %d", led_gpio);
|
ESP_LOGI(TAG, "Onboard WS2812: 40 Hz gamma flicker (GENUS), colour=CSI motion via ruv-neural-viz, GPIO %d", led_gpio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/* Viz disabled — clear the onboard LED at boot and release the RMT channel. */
|
||||||
|
led_strip_handle_t led_strip;
|
||||||
|
if (led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip) == ESP_OK) {
|
||||||
|
led_strip_clear(led_strip);
|
||||||
|
led_strip_del(led_strip);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_LED_GAMMA_VIZ */
|
||||||
|
|
||||||
/* ADR-110 P4: 802.15.4 mesh time-sync (C6 only).
|
/* ADR-110 P4: 802.15.4 mesh time-sync (C6 only).
|
||||||
* Initialized BEFORE WiFi so it's available even when WiFi STA can't
|
* Initialized BEFORE WiFi so it's available even when WiFi STA can't
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue