10 Commits

Author SHA1 Message Date
ac2e9d00d6 fix: call gc9a01_init() in app_main to initialize display
Display was black because gc9a01_init() was never called — driver compiled
but never invoked. Init before vesc_can_init so SPI/register init completes
before TWAI claims GPIO2 (BL pin); TWAI idle=recessive=high keeps BL on.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:05:50 -04:00
d1e3a3cbd1 fix: commit idf_component.yml so managed cjson component fetches on clean builds
Without this file, idf.py build fails after fullclean with 'Failed to resolve
component cJSON' because the component manager has no manifest to fetch from.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 16:03:08 -04:00
cd84ee82fa fix: use espressif__cjson component name to match managed_components dir
CMakeLists.txt REQUIRES 'cJSON' fails on IDF v5.2 — component manager
installs it as 'espressif__cjson'. Update the require name to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 15:55:04 -04:00
98494a98c7 fix: add missing gc9a01 display driver to main build (bd-1yr8)
gc9a01.c and gc9a01.h were never committed to main despite ota_display.c
depending on their display_fill_rect/draw_string/draw_arc functions.
Also:
- CMakeLists.txt: add gc9a01.c to SRCS
- config.h: restore DISP_* GPIO defs (DC=8 CS=9 SCK=10 MOSI=11 RST=14 BL=2)
  for Waveshare ESP32-S3-Touch-LCD-1.28
- ota_display.c: fix snprintf buffer too small (verline[32]→[48]) which
  GCC 13.2.0 rejects as -Werror=format-truncation

Confirmed builds clean and boots on bd-66hx hardware (mbpi5 /dev/ttyACM0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 15:40:46 -04:00
1ae600ead4 feat: Orin serial OTA_CHECK + OTA_UPDATE commands, version reporting (bd-1s1s)
Extends the bd-66hx serial protocol with two new Orin→ESP32 commands:
  CMD_OTA_CHECK  (0x10): triggers gitea_ota_check_now(), responds with
    TELEM_VERSION_INFO (0x84) for Balance and IO (current + available ver).
  CMD_OTA_UPDATE (0x11): uint8 target (0=balance, 1=io, 2=both) — triggers
    uart_ota_trigger() for IO or ota_self_trigger() for Balance.
    NACK with ERR_OTA_BUSY or ERR_OTA_NO_UPDATE on failure.
New telemetry: TELEM_OTA_STATUS (0x83, target+state+progress+err),
  TELEM_VERSION_INFO (0x84, target+current[16]+available[16]).
Wires OTA stack into app_main: ota_self_health_check on boot,
  gitea_ota_init + ota_display_init after peripherals ready.
CMakeLists updated with all OTA component dependencies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
e73674f161 feat: GC9A01 OTA notification badge + progress ring UI (bd-1yr8)
Adds ota_display_task (5 Hz) on GC9A01 240×240 round LCD:
- Idle: orange dot badge at top-right when update available, version text
- Progress: arc sweeping 0→360° around display perimeter with phase label
- States: Downloading/Verifying/Applying/Rebooting (Balance) and
  Downloading/Sending/Done (IO via UART)
- Error: red arc + "FAILED RETRY?" prompt
Display primitives (fill_rect, draw_string, draw_arc) are stubs called
from the GC9A01 SPI driver layer (separate driver bead).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
972db16635 feat: UART OTA protocol Balance→IO board, 1 KB chunk + ACK (bd-21hv)
Balance side (uart_ota.c): downloads io-firmware.bin from Gitea to RAM,
computes SHA256, then streams to IO over UART1 (GPIO17/18, 460800 baud)
as OTA_BEGIN/OTA_DATA/OTA_END frames with CRC8 + per-chunk ACK/retry (×3).
IO side (uart_ota_recv.c): receives frames, writes to inactive OTA partition
via esp_ota_write, verifies SHA256 on OTA_END, sets boot partition, reboots.
IO board main.c + CMakeLists.txt scaffold included.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
5250ce67ad feat: Balance self-OTA download, SHA256 verify, rollback (bd-18nb)
Downloads balance-firmware.bin from Gitea release URL to inactive OTA
partition, streams SHA256 verification via mbedTLS, sets boot partition
and reboots. Auto-rollback via CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE if
ota_self_health_check() not called within 30 s of boot. Progress 0-100%
in g_ota_self_progress for display task.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
d2175bf7d0 feat: Gitea release version checker with WiFi (bd-3hte)
Adds gitea_ota_check_task on Balance board: fetches Gitea releases API
every 30 min and on boot, filters by esp32-balance/ and esp32-io/ tag
prefixes, compares semver against embedded FW version, stores update info
(version string, download URL, SHA256) in g_balance_update / g_io_update.
WiFi credentials read from NVS namespace "wifi"; falls back to compile-time
DEFAULT_WIFI_SSID/PASS if NVS is empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
b830420efc feat: add UART/USB serial protocol for Orin comms, proxy VESC CAN (bd-66hx)
Replaces Orin↔ESP32-S3 BALANCE CAN comms (0x300-0x303 / 0x400-0x401)
with binary serial framing over CH343 USB-CDC at 460800 baud.

Protocol matches bd-wim1 (sl-perception) exactly:
  Frame: [0xAA][LEN][TYPE][PAYLOAD][CRC8-SMBUS]
  CRC covers LEN+TYPE+PAYLOAD, big-endian multi-byte fields.

Commands (Orin→ESP32): HEARTBEAT/DRIVE/ESTOP/ARM/PID
Telemetry (ESP32→Orin): TELEM_STATUS, TELEM_VESC_LEFT (ID 56),
                         TELEM_VESC_RIGHT (ID 68), ACK/NACK

VESC CAN TWAI kept for motor control; drive commands from Orin
forwarded to VESCs via SET_RPM. Hardware note: SN65HVD230
rewired from IO43/44 to IO2/IO1 to free IO43/44 for CH343.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:09:12 -04:00