Audio Path¶
Audio path code owns path selection behavior after app_control chooses a boot
mode. PROP is treated as a packet service here; radio/TDD internals are in
PROP TDD.
Purpose¶
Provide three path implementations over shared buffer-state names, FLL state, and codec-clock control:
| File | Ownership |
|---|---|
firmware/src/audio/path_common.* |
Shared path state names, warning helper, PI controller, global FLL fixed/auto state, PROP audio packet-size symbols. |
firmware/src/audio/path_wired.c |
Direct USB audio to codec path. |
firmware/src/audio/path_dongle.c |
USB audio to PROP path for the dongle. |
firmware/src/audio/path_headset.c |
PROP audio to codec path for the headset. |
Path Matrix¶
| Mode | Path | Speaker flow | Mic flow | Buffer/FLL |
|---|---|---|---|---|
usb |
path_wired |
USB EP OUT FIFO -> I2S TX | I2S RX left mono -> USB EP IN FIFO | Uses BUFFERING / PLAYING and FLL PI control. |
prop_dongle |
path_dongle |
USB EP OUT FIFO -> PROP TX queue | PROP RX queue -> USB EP IN FIFO | No I2S, codec, buffering state, or FLL control. |
prop_headset |
path_headset |
PROP RX queue -> speaker FIFO -> I2S TX | I2S RX left mono -> mic FIFO -> PROP TX queue | Uses BUFFERING / PLAYING and FLL PI control. |
Buffer States¶
Buffer states are only used by the I2S-backed paths: path_wired and
path_headset. path_dongle does not maintain BUFFERING / PLAYING; it
moves USB and PROP payloads as soon as work is available. If the dongle has a complete USB
speaker payload, it sends it to PROP. If it receives a complete PROP mic packet,
it writes the audio payload back to the USB IN endpoint.
| State | Meaning |
|---|---|
PATH_STATE_BUFFERING |
Path is waiting for enough speaker data before activating I2S. |
PATH_STATE_PLAYING |
Path has activated I2S and is feeding speaker blocks. |
Wired and headset paths use the same state rule shape: start playback when the speaker FIFO plus pending I2S bytes reaches the path-local start threshold, and return to buffering when submitted I2S data has drained and the speaker FIFO no longer contains a full block. The exact thresholds live next to each path implementation.
Inputs and Outputs¶
| Boundary | Input | Output |
|---|---|---|
| USB audio | TinyUSB EP OUT speaker FIFO | TinyUSB EP IN mic FIFO |
| PROP | prop_session_rx_dequeue() |
prop_session_tx_enqueue() |
| I2S/TDM | TX FIFO supplies speaker data to audio_i2s_activate() |
RX FIFO receives mic data from I2S |
| CLI/status | path_*_get_status() |
#A status lines from cli.c |
Ownership¶
| Owner | Resources |
|---|---|
path_common |
Shared state names, controller math, packet-size symbols, global fixed/auto FLL state. |
path_wired |
One path thread and wired playback status. |
path_dongle |
One path thread and dongle overflow counter. |
path_headset |
One path thread, local speaker/mic FIFOs, headset playback status. |
Runtime Behavior¶
path_wired:
- Waits for TinyUSB audio EP OUT and EP IN FIFOs.
- Polls on a short sleep loop.
- Starts I2S when USB speaker level plus I2S pending bytes reaches the wired start threshold.
- Stops I2S and increments
spk_underrun_eventswhen playback drains below one I2S block. - Retunes the codec FLL while playing.
path_dongle:
- Waits for TinyUSB audio EP OUT and EP IN FIFOs.
- Does not start or stop a stream state machine.
- Sends complete USB speaker payloads to PROP.
- Writes complete received PROP mic payloads back to the USB IN endpoint.
- Counts speaker bytes consumed from USB after a PROP TX enqueue failure in
overflow_bytes.
path_headset:
- Creates local TinyUSB FIFOs for speaker and mic buffering.
- Starts I2S when speaker FIFO plus pending I2S bytes reaches the headset start threshold.
- Moves PROP speaker packets into the local speaker FIFO.
- Moves complete mic payloads from the local mic FIFO to PROP TX.
- Retunes the codec FLL while playing.
FLL Controller¶
codec_clock_controller() runs a shared EMA + PI loop:
| Input | Use |
|---|---|
target |
Desired total speaker level in bytes. |
fifo |
Current software speaker FIFO level. |
pending |
Bytes already submitted to the I2S pipeline. |
filter, i_sum |
Per-path controller state. |
The active I2S-backed path implementation (path_wired or path_headset)
computes target_rate = AUDIO_I2S_SAMPLE_RATE_HZ - adjust_hz and calls
nau88l21_set_fll_target_rate_hz(). fll_set_fixed() pauses automatic path
updates by setting a global fixed target; fll_set_auto() resumes automatic
control.
Constraints¶
- Audio format is fixed by the I2S/USB constants; it is not negotiated per path.
- Speaker samples are stereo; captured I2S samples are reduced to mono by keeping the left channel in the I2S layer.
- The active path is selected only at boot; the CLI persists a new mode and reboots.
- The PROP audio path uses fixed packet sizes and no audio-layer stream ID.
- Path modules do not implement packet-loss concealment.