Archive STM32 firmware to legacy/stm32/: - src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py - test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c - USB_CDC_BUG.md Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol, stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params, stm32_cmd.launch.py → esp32_cmd.launch.py, test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node Content cleanup across all files: - Mamba F722S → ESP32-S3 BALANCE - BlackPill → ESP32-S3 IO - STM32F722/F7xx → ESP32-S3 - stm32Mode/Version/Port → esp32Mode/Version/Port - STM32 State/Mode labels → ESP32 State/Mode - Jetson Nano → Jetson Orin Nano Super - /dev/stm32 → /dev/esp32 - stm32_bridge → esp32_bridge - STM32 HAL → ESP-IDF docs/SALTYLAB.md: - Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28) - Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF No new functionality — cleanup only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
102 lines
2.9 KiB
C
102 lines
2.9 KiB
C
#ifndef LED_H
|
||
#define LED_H
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
|
||
/*
|
||
* led.h — WS2812B NeoPixel status indicator driver (Issue #193)
|
||
*
|
||
* Hardware: TIM3_CH1 PWM on PB4 at 800 kHz (1.25 µs per bit).
|
||
* Controls an 8-LED ring with state-based animations:
|
||
* - Boot: Blue chase (startup sequence)
|
||
* - Armed: Solid green
|
||
* - Error: Red blinking (visual alert)
|
||
* - Low Battery: Yellow pulsing (warning)
|
||
* - Charging: Green breathing (soft indication)
|
||
* - E-Stop: Red strobe (immediate action required)
|
||
*
|
||
* State transitions are non-blocking via a 1 ms timer callback (led_tick).
|
||
* Each state defines its own animation envelope: color, timing, and brightness.
|
||
*
|
||
* WS2812 protocol (NRZ):
|
||
* - Bit "0": High 350 ns, Low 800 ns (1.25 µs total)
|
||
* - Bit "1": High 700 ns, Low 600 ns (1.25 µs total)
|
||
* - Reset: Low > 50 µs
|
||
*
|
||
* PWM-based implementation via DMA:
|
||
* - 10 levels: [350 ns, 400, 450, 500, 550, 600, 650, 700, 750, 800]
|
||
* - Bit "0" → High 350-400 ns Bit "1" → High 650-800 ns
|
||
* - Each bit requires one PWM cycle; 24 bits/LED × 8 LEDs = 192 cycles
|
||
* - DMA rings through buffer, auto-reloads on update events
|
||
*/
|
||
|
||
/* LED state enumeration */
|
||
typedef enum {
|
||
LED_STATE_BOOT = 0, /* Blue chase (startup) */
|
||
LED_STATE_ARMED = 1, /* Solid green */
|
||
LED_STATE_ERROR = 2, /* Red blinking */
|
||
LED_STATE_LOW_BATT = 3, /* Yellow pulsing */
|
||
LED_STATE_CHARGING = 4, /* Green breathing */
|
||
LED_STATE_ESTOP = 5, /* Red strobe */
|
||
LED_STATE_COUNT
|
||
} LEDState;
|
||
|
||
/* RGB color (8-bit per channel) */
|
||
typedef struct {
|
||
uint8_t r;
|
||
uint8_t g;
|
||
uint8_t b;
|
||
} RGBColor;
|
||
|
||
/*
|
||
* led_init()
|
||
*
|
||
* Configure TIM3_CH1 PWM on PB4 at 800 kHz, set up DMA for bit streaming,
|
||
* and initialize the LED buffer. Call once at startup, after buzzer_init()
|
||
* but before the main loop.
|
||
*/
|
||
void led_init(void);
|
||
|
||
/*
|
||
* led_set_state(state)
|
||
*
|
||
* Change the LED display state. The animation runs non-blocking via led_tick().
|
||
* Valid states: LED_STATE_BOOT, LED_STATE_ARMED, LED_STATE_ERROR, etc.
|
||
*/
|
||
void led_set_state(LEDState state);
|
||
|
||
/*
|
||
* led_get_state()
|
||
*
|
||
* Return the current LED state.
|
||
*/
|
||
LEDState led_get_state(void);
|
||
|
||
/*
|
||
* led_set_color(r, g, b)
|
||
*
|
||
* Manually set the LED ring to a solid color. Overrides the current state
|
||
* animation until led_set_state() is called again.
|
||
*/
|
||
void led_set_color(uint8_t r, uint8_t g, uint8_t b);
|
||
|
||
/*
|
||
* led_tick(now_ms)
|
||
*
|
||
* Advance animation state machine. Must be called every 1 ms from the main loop.
|
||
* Handles state-specific animations: chase timing, pulse envelope, strobe phase, etc.
|
||
* Updates the DMA buffer with new LED values without blocking.
|
||
*/
|
||
void led_tick(uint32_t now_ms);
|
||
|
||
/*
|
||
* led_is_animating()
|
||
*
|
||
* Returns true if the current state is actively animating (e.g., chase, pulse, strobe).
|
||
* Returns false for static states (armed, error solid).
|
||
*/
|
||
bool led_is_animating(void);
|
||
|
||
#endif /* LED_H */
|