From 6dc7aea32f783a54b1f2c0b772853791e9a82895 Mon Sep 17 00:00:00 2001 From: sl-firmware Date: Sat, 28 Feb 2026 22:41:02 -0500 Subject: [PATCH] feat: modern HUD dashboard + telemetry expansion (#43) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ui/index.html — full dashboard rewrite: - 3-column layout: LEFT telemetry gauges, CENTER 3D SaltyBot, RIGHT comms - LEFT: artificial horizon (canvas, pitch/roll/ladder/roll-arc), yaw compass tape, pitch/roll/yaw readouts, bidirectional motor bar, battery bar, BME280 environment section (auto-shows on data), MAG heading row - CENTER: Three.js SaltyBot model (PR#41) with ground plane + animated wheel rolling proportional to motor_cmd - RIGHT: USB tx/rx packet counters, mode badge (MANUAL/ASSISTED/AUTO), CRSF RSSI/LQ, dual RC stick overlay canvases (CH1–4), Jetson active dot - BOTTOM: KP/KI/KD/SP/MAX sliders with APPLY + QUERY, collapsible log console - Style: Tailwind CSS CDN, dark cyberpunk theme, neon cyan + orange accents src/main.c — telemetry JSON additions: - buf: 256 → 320 bytes (headroom for new fields) - ja: Jetson active flag (0/1) via jetson_cmd_is_active() - txc: TX telemetry frame counter (uint32, main-loop local) - rxc: RX CDC packet counter (cdc_rx_count from usbd_cdc_if) - ch1–ch4: CRSF channels mapped to µs (1000–2000) via crsf_to_range(), appended alongside rssi/lq when RC is alive lib/USB_CDC/src/usbd_cdc_if.c: - cdc_rx_count: volatile uint32_t, incremented in CDC_Receive on every packet; extern'd in main.c for telemetry Closes #43. Co-Authored-By: Claude Sonnet 4.6 --- lib/USB_CDC/src/usbd_cdc_if.c | 8 +- src/main.c | 30 +- ui/index.html | 1066 +++++++++++++++++++++++---------- 3 files changed, 774 insertions(+), 330 deletions(-) diff --git a/lib/USB_CDC/src/usbd_cdc_if.c b/lib/USB_CDC/src/usbd_cdc_if.c index a83c532..f1548ee 100644 --- a/lib/USB_CDC/src/usbd_cdc_if.c +++ b/lib/USB_CDC/src/usbd_cdc_if.c @@ -4,9 +4,10 @@ extern USBD_HandleTypeDef hUsbDevice; volatile uint8_t cdc_streaming = 1; /* auto-stream */ static volatile uint8_t cdc_port_open = 0; /* set when host asserts DTR */ -volatile uint8_t cdc_arm_request = 0; /* set by A command */ -volatile uint8_t cdc_disarm_request = 0; /* set by D command */ -volatile uint8_t cdc_recal_request = 0; /* set by G command — gyro recalibration */ +volatile uint8_t cdc_arm_request = 0; /* set by A command */ +volatile uint8_t cdc_disarm_request = 0; /* set by D command */ +volatile uint8_t cdc_recal_request = 0; /* set by G command — gyro recalibration */ +volatile uint32_t cdc_rx_count = 0; /* total CDC packets received from host */ /* * PID tuning command buffer. @@ -174,6 +175,7 @@ static int8_t CDC_Receive(uint8_t *buf, uint32_t *len) { } done: + cdc_rx_count++; USBD_CDC_SetRxBuffer(&hUsbDevice, UserRxBuffer); USBD_CDC_ReceivePacket(&hUsbDevice); return USBD_OK; diff --git a/src/main.c b/src/main.c index 9396e7c..7b4a90f 100644 --- a/src/main.c +++ b/src/main.c @@ -20,10 +20,11 @@ #include #include -extern volatile uint8_t cdc_streaming; /* set by S command in CDC RX */ -extern volatile uint8_t cdc_arm_request; /* set by A command */ -extern volatile uint8_t cdc_disarm_request; /* set by D command */ -extern volatile uint8_t cdc_recal_request; /* set by G command */ +extern volatile uint8_t cdc_streaming; /* set by S command in CDC RX */ +extern volatile uint8_t cdc_arm_request; /* set by A command */ +extern volatile uint8_t cdc_disarm_request; /* set by D command */ +extern volatile uint8_t cdc_recal_request; /* set by G command */ +extern volatile uint32_t cdc_rx_count; /* total CDC packets received */ /* * Apply a PID tuning command string from the USB terminal. @@ -156,8 +157,9 @@ int main(void) { */ safety_init(); - char buf[256]; + char buf[320]; int len; + uint32_t tx_count = 0; /* telemetry frames sent to host */ IMUData imu; uint32_t send_tick = 0; @@ -340,17 +342,27 @@ int main(void) { } } if (safety_rc_alive(now)) { - /* RSSI in dBm (negative), link quality 0-100% */ - n = snprintf(p, rem, ",\"rssi\":%d,\"lq\":%d", - (int)crsf_state.rssi_dbm, (int)crsf_state.link_quality); + /* RSSI, link quality, and CH1–CH4 mapped to µs (1000–2000) */ + n = snprintf(p, rem, ",\"rssi\":%d,\"lq\":%d" + ",\"ch1\":%d,\"ch2\":%d,\"ch3\":%d,\"ch4\":%d", + (int)crsf_state.rssi_dbm, (int)crsf_state.link_quality, + (int)crsf_to_range(crsf_state.channels[0], 1000, 2000), + (int)crsf_to_range(crsf_state.channels[1], 1000, 2000), + (int)crsf_to_range(crsf_state.channels[2], 1000, 2000), + (int)crsf_to_range(crsf_state.channels[3], 1000, 2000)); p += n; rem -= n; } - n = snprintf(p, rem, "}\n"); + /* Jetson active flag, USB TX/RX packet counters */ + n = snprintf(p, rem, ",\"ja\":%d,\"txc\":%u,\"rxc\":%u}\n", + jetson_cmd_is_active(now) ? 1 : 0, + (unsigned)tx_count, + (unsigned)cdc_rx_count); len = (int)(p + n - buf); } else { len = snprintf(buf, sizeof(buf), "{\"err\":%d}\n", imu_ret); } CDC_Transmit((uint8_t *)buf, len); + tx_count++; } status_update(now, (imu_ret == 0), diff --git a/ui/index.html b/ui/index.html index c44c841..0df21e3 100644 --- a/ui/index.html +++ b/ui/index.html @@ -3,86 +3,255 @@ -SaltyLab Balance Bot +SaltyLab HUD + - -
-

⚡ SALTYLAB DISARMED

-
PITCH --°
-
ROLL --°
-
YAW --°
-
MOTOR --
- - - - - -