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>
107 lines
3.4 KiB
C
107 lines
3.4 KiB
C
#ifndef AUDIO_H
|
||
#define AUDIO_H
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
|
||
/*
|
||
* audio.h — I2S audio output driver (Issue #143)
|
||
*
|
||
* Hardware: SPI3 repurposed as I2S3 master TX (blackbox flash not used
|
||
* on balance bot). Supports MAX98357A (I2S class-D amp) and PCM5102A
|
||
* (I2S DAC + external amp) — both use standard Philips I2S.
|
||
*
|
||
* Pin assignment (SPI3 / I2S3, defined in config.h):
|
||
* PC10 I2S3_CK (BCLK) AF6
|
||
* PA15 I2S3_WS (LRCLK) AF6
|
||
* PB5 I2S3_SD (DIN) AF6
|
||
* PC5 AUDIO_MUTE (GPIO) active-high = enabled; low = muted/shutdown
|
||
*
|
||
* PLLI2S: N=192, R=2 → 96 MHz I2S clock → 22058 Hz (< 0.04% from 22050)
|
||
* DMA1 Stream7 Channel0 (SPI3_TX), circular, double-buffer ping-pong.
|
||
*
|
||
* Mixer priority (highest to lowest):
|
||
* 1. PCM audio chunks from Jetson (via JLINK_CMD_AUDIO, written to FIFO)
|
||
* 2. Notification tones (queued by audio_play_tone)
|
||
* 3. Silence
|
||
*
|
||
* Volume applies to all sources via integer sample scaling (0–100).
|
||
*/
|
||
|
||
/* Maximum int16_t samples per JLINK_CMD_AUDIO frame (252-byte payload / 2) */
|
||
#define AUDIO_CHUNK_MAX_SAMPLES 126u
|
||
|
||
/* Pre-defined notification tones */
|
||
typedef enum {
|
||
AUDIO_TONE_BEEP_SHORT = 0, /* 880 Hz, 100 ms — acknowledge / UI feedback */
|
||
AUDIO_TONE_BEEP_LONG = 1, /* 880 Hz, 500 ms — generic warning */
|
||
AUDIO_TONE_STARTUP = 2, /* C5→E5→G5 arpeggio (3 × 120 ms) */
|
||
AUDIO_TONE_ARM = 3, /* 880 Hz→1047 Hz two-beep ascending */
|
||
AUDIO_TONE_DISARM = 4, /* 880 Hz→659 Hz two-beep descending */
|
||
AUDIO_TONE_FAULT = 5, /* 200 Hz buzz, 500 ms — tilt/safety fault */
|
||
AUDIO_TONE_COUNT
|
||
} AudioTone;
|
||
|
||
/*
|
||
* audio_init()
|
||
*
|
||
* Configure PLLI2S, GPIO, DMA1 Stream7, and SPI3/I2S3.
|
||
* Pre-fills DMA buffer with silence, starts circular DMA TX, then
|
||
* unmutes the amp. Call once before safety_init().
|
||
*/
|
||
void audio_init(void);
|
||
|
||
/*
|
||
* audio_mute(mute)
|
||
*
|
||
* Drive AUDIO_MUTE_PIN: false = hardware-muted (SD/XSMT low),
|
||
* true = active (amp enabled). Does NOT stop DMA; allows instant
|
||
* un-mute without DMA restart clicks.
|
||
*/
|
||
void audio_mute(bool active);
|
||
|
||
/*
|
||
* audio_set_volume(vol)
|
||
*
|
||
* Software volume 0–100. Applied in ISR fill path via integer scaling.
|
||
* 0 = silence, 100 = full scale (±16384 for square wave, passthrough for PCM).
|
||
*/
|
||
void audio_set_volume(uint8_t vol);
|
||
|
||
/*
|
||
* audio_play_tone(tone)
|
||
*
|
||
* Queue a pre-defined notification tone. The tone plays after any tones
|
||
* already in the queue. Returns false if the tone queue is full (depth 4).
|
||
* Tones are pre-empted by incoming PCM audio from the Jetson.
|
||
*/
|
||
bool audio_play_tone(AudioTone tone);
|
||
|
||
/*
|
||
* audio_write_pcm(samples, n)
|
||
*
|
||
* Write mono 16-bit 22050 Hz PCM samples into the Jetson PCM FIFO.
|
||
* Called from jlink_process() dispatch on JLINK_CMD_AUDIO (main-loop context).
|
||
* Returns the number of samples actually accepted (0 if FIFO is full).
|
||
*/
|
||
uint16_t audio_write_pcm(const int16_t *samples, uint16_t n);
|
||
|
||
/*
|
||
* audio_tick(now_ms)
|
||
*
|
||
* Advance the tone sequencer state machine. Must be called every 1 ms
|
||
* from the main loop. Manages step transitions and gap timing; updates
|
||
* the volatile active-tone parameters read by the ISR fill path.
|
||
*/
|
||
void audio_tick(uint32_t now_ms);
|
||
|
||
/*
|
||
* audio_is_playing()
|
||
*
|
||
* Returns true if the DMA is running (always true after audio_init()
|
||
* unless the amp is hardware-muted or the I2S peripheral has an error).
|
||
*/
|
||
bool audio_is_playing(void);
|
||
|
||
#endif /* AUDIO_H */
|