esp-sdr-zephyr
Raw I/Q receive and transmit on the ESP32-S3/C6 Wi-Fi radio, for Zephyr
Loading...
Searching...
No Matches
esp_sdr_paced.h File Reference

ESP-SDR CPU-paced streaming (ESP32-C6, ESP32-C5): continuous receive and transmit, one sample at a time from the caller's loop. More...

#include <stdbool.h>
#include <stdint.h>

Go to the source code of this file.

Data Structures

struct  esp_sdr_paced_stats

Macros

#define ESP_SDR_PACED_INPUT_HZ   80000000U

Typedefs

typedef bool(* esp_sdr_tx_paced_input_t) (void *user, int16_t *i, int16_t *q)

Functions

int esp_sdr_rx_paced_start (uint32_t rate_hz)
 Start receiving at rate_hz.
bool esp_sdr_rx_paced_poll (int32_t *i, int32_t *q)
 Produce the next receive sample if it is due.
uint32_t esp_sdr_rx_paced_slack (void)
 CPU cycles until the next receive sample is due, 0 when it is.
void esp_sdr_rx_paced_stop (void)
 Stop receiving and release the radio; no-op when stopped.
int esp_sdr_tx_paced_start (uint32_t rate_hz, unsigned int interp, unsigned int power, esp_sdr_tx_paced_input_t input, void *user)
 Turn the transmit chain on at the current frequency and start playing input at rate_hz.
bool esp_sdr_tx_paced_poll (void)
 Write the next DAC value if it is due, then compute the one after.
uint32_t esp_sdr_tx_paced_slack (void)
 CPU cycles until the next DAC value is due, 0 when it is.
void esp_sdr_tx_paced_stop (void)
 Turn the transmit chain off and release the radio; no-op when stopped.
unsigned int esp_sdr_tx_paced_power_max (void)
 Highest power step: 2 dB per step of the vendor tone's backoff (none on the C5).
void esp_sdr_tx_paced_range (uint32_t *min_mhz, uint32_t *max_mhz)
 Transmit range in MHz: what the vendor tone path tunes (C6 2.4 GHz, C5 also 5 GHz).
static uint32_t esp_sdr_paced_cycles (void)
 The CPU cycle counter the paced streams run on.
uint32_t esp_sdr_paced_deadline (void)
 When the running stream's next sample is due, on esp_sdr_paced_cycles().
void esp_sdr_paced_sync (void)
 Restart the running stream's clock: the next sample is due one period from now. Call once interrupts are locked, after the start.
void esp_sdr_paced_get_stats (struct esp_sdr_paced_stats *stats)
 Statistics of the running or last stream.

Detailed Description

ESP-SDR CPU-paced streaming (ESP32-C6, ESP32-C5): continuous receive and transmit, one sample at a time from the caller's loop.

The C6 has no dump path that runs gapless at a low rate and no DAC buffer the CPU can refill while it plays, so the CPU paces both directions:

  • Receive differences the running sums of the modem's IQ estimator, which adds up the 80 MHz baseband samples in hardware: each output is the sum of the 80 MHz / rate samples since the previous one (a boxcar decimator). Gapless up to about 4.7 MS/s with nothing else in the loop.
  • Transmit writes the TX DC value register, which drives the DAC directly once the vendor tone path has turned the transmit chain on, at the rate times an interpolation factor, through an 8-tap-per-phase FIR.

Between start and stop the caller polls in a tight loop with interrupts locked and serves its own I/O between polls. A poll that comes late moves that sample's instant; the stats count it. One direction at a time.

Macro Definition Documentation

◆ ESP_SDR_PACED_INPUT_HZ

#define ESP_SDR_PACED_INPUT_HZ   80000000U

Input rate of the estimator: each receive output sums 80 MHz / rate of its samples.

Typedef Documentation

◆ esp_sdr_tx_paced_input_t

typedef bool(* esp_sdr_tx_paced_input_t) (void *user, int16_t *i, int16_t *q)

Transmit input: store the next sample (full scale +-32767) and return true, or return false when none is available (played as 0). Called from the poll, once per input sample: must not block.

Function Documentation

◆ esp_sdr_paced_deadline()

uint32_t esp_sdr_paced_deadline ( void )

When the running stream's next sample is due, on esp_sdr_paced_cycles().

For I/O between polls: stop it while (int32_t)(deadline - now) is small.

◆ esp_sdr_rx_paced_poll()

bool esp_sdr_rx_paced_poll ( int32_t * i,
int32_t * q )

Produce the next receive sample if it is due.

Parameters
i,qThe sums over this sample's window of 80 MHz / rate inputs, each input within -512 to 511.
Returns
true when a sample was produced.

◆ esp_sdr_rx_paced_slack()

uint32_t esp_sdr_rx_paced_slack ( void )

CPU cycles until the next receive sample is due, 0 when it is.

I/O between polls that may take longer than this delays the sample.

◆ esp_sdr_rx_paced_start()

int esp_sdr_rx_paced_start ( uint32_t rate_hz)

Start receiving at rate_hz.

Takes the radio until esp_sdr_rx_paced_stop(). The receiver keeps its frequency, gain and filter.

Parameters
rate_hzA divisor of both the CPU clock and 80 MHz, from 10 kHz.
Returns
0, -EINVAL for an unsupported rate, -EAGAIN before esp_sdr_init().

◆ esp_sdr_tx_paced_poll()

bool esp_sdr_tx_paced_poll ( void )

Write the next DAC value if it is due, then compute the one after.

Returns
true when a value was written.

◆ esp_sdr_tx_paced_start()

int esp_sdr_tx_paced_start ( uint32_t rate_hz,
unsigned int interp,
unsigned int power,
esp_sdr_tx_paced_input_t input,
void * user )

Turn the transmit chain on at the current frequency and start playing input at rate_hz.

Parameters
rate_hzInput rate; rate times interp must divide the CPU clock.
interpInterpolation factor: 1 (input straight to the DAC), 2, 4 or 8.
powerPower step, 0 weakest to esp_sdr_tx_paced_power_max(). No effect on the ESP32-C5, whose level follows the samples only (doc/hardware-quirks.md).
inputCalled once per input sample from esp_sdr_tx_paced_poll().
userPassed to input.
Returns
0, -EINVAL, -ERANGE outside the transmit range, -EAGAIN before esp_sdr_init().