Skip to content

Feat/v1.2 companion#6

Merged
prat96 merged 7 commits into
mainfrom
feat/v1.2-companion
Jun 22, 2026
Merged

Feat/v1.2 companion#6
prat96 merged 7 commits into
mainfrom
feat/v1.2-companion

Conversation

@prat96

@prat96 prat96 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

No description provided.

prat96 added 7 commits June 22, 2026 20:54
Add the v1.2 "Companion" (CyberBrick-kit accessory) building blocks, all
feature-gated so the default build (HG_NEOPIXEL_COUNT=1, button/joystick OFF)
is behaviourally identical to v1.1:

  - neopixel_anim.{c,h}  pure WS2812 mood renderer (off/idle/rx/warn/fault/
                         pet/rainbow), deterministic -> host-tested
  - input_logic.{c,h}    pure button debounce + joystick direction decode
  - ads1115.{c,h}        I2C ADS1115 ADC, every transfer timeout-bounded so a
                         missing/half-wired module returns false, never wedges
  - hg_input.{c,h}       button (GP16) + joystick HW glue; no-op unless built

Plus the host unit tests for the two pure modules and the CMake/build_fork.sh
feature flags (HG_NEOPIXEL_COUNT / HG_BUTTON / HG_JOYSTICK).

The new modules link but stay dormant until the later commits wire them in.
R1: all of this is designed to run on the +0 tasks only — nothing here is
reachable from the DAP/USB/UART/watchdog paths.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
Generalise the single onboard NeoPixel to a chain of HG_NEOPIXEL_COUNT pixels
on GP12 (onboard = index 0, then an external strip soldered to the GP12
castellation). Add an animated MOOD path (feedback_mood) that renders via
neopixel_anim each service tick, plus feedback_fill for the whole chain.

HG_NEOPIXEL_COUNT defaults to 1, in which case the manual single-pixel path is
unchanged from v1.1 (np_show pushes exactly one word). Manual sets switch out of
anim mode so the existing {"q":"pixel"}/{"q":"led"} test commands still work.

R1 unchanged: the NeoPixel is still driven only from the +0 SD task via
feedback_service; the CPU just pushes N words to the PIO (hardware clocks the
800 kHz waveform) — never blocking or masking IRQs on the DAP path.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
Wire the input subsystem into the +0 tasks (no new mutex):
  - button (GP16) polled on the SD task (20 ms, GPIO only) -> dash_nav_step /
    dash_pet, next to feedback_service
  - joystick (ADS1115) polled on the dashboard task (250 ms) — deliberately the
    SAME task as the OLED so I2C1 keeps a single owner and needs no lock
  - drive_feedback maps recorder state to a reactive MOOD when HG_NEOPIXEL_COUNT>1
    (fault > recent-traffic > logging > off); the single-pixel path is kept for
    the default count=1 build
  - i2c1_bus.h drops the bus to 400 kHz when HG_JOYSTICK is built (ADS1115 max);
    the OLED flush slows ~9->23 ms, fine on +0

R1: button/joystick/mood all run on the +0 SD and dashboard tasks. Nothing is
added at or above the DAP/USB/UART/watchdog priorities, and no DAP-needed lock
is taken. Default (button/joystick OFF) keeps every call a no-op.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
Add the v1.2 control surface (reply buffers stay static per the TUD-stack rule):
  {"q":"fill","r":,"g":,"b":}    whole WS2812 chain to one colour
  {"q":"mood","n":0..6,"i":0..255}  animated mood
  {"q":"btn"}                    button readback (held + taps since boot)
  {"q":"joy"}                    joystick readback (present + raw X/Y + dir)
and extend {"q":"status"} with px/btn/joy so a flashed board self-reports its
chain length + input state. Documented in the README command table.

R1: this runs in the CDC1 handler (TUD task); all of it just latches requests or
reads telemetry — no DAP-path work.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
companion_hil.py drives the new surface over CDC1: REQUIRED machine checks
(status carries px/btn/joy; fill/mood/btn/joy answer well-formed JSON) plus an
interactive button/joystick liveness witness. Hardware-blind-safe (exit 2 with
no probe). Run against the v1.1 image it correctly FAILs ("err":"unknown"), so
it is not a silent pass.

M_UI_RESULTS.md records: host tests PASS; default+companion builds clean;
analyze.sh PASS for both; DAP/USB hot path still SRAM-pinned. Open HIL items
(flash 1.2.0-companion -> companion_hil PASS, then a Gate-1 0-stall coexist soak
with the strip + ADS1115 on the 400 kHz bus) are listed before shipping any
feature ON.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
Add the fill / mood / btn / joy commands to the control-channel table and note
that {"q":"pixel"} drives pixel 0 of the chain.

Signed-off-by: Pratheek Balakrishna <pratheekb96@gmail.com>
@prat96 prat96 self-assigned this Jun 22, 2026
@prat96 prat96 added the enhancement New feature or request label Jun 22, 2026
@prat96 prat96 merged commit 555662d into main Jun 22, 2026
9 checks passed
@prat96 prat96 deleted the feat/v1.2-companion branch June 22, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant