Skip to content

File dsss_burst_receiver_core.h

FileList > doppler > dsss_burst_receiver > dsss_burst_receiver_core.h

Go to the source code of this file

DsssBurstReceiver — the burst chain composed in C. More...

  • #include "doppler/clib_common.h"
  • #include "doppler/jm_perf.h"
  • #include "doppler/buffer/buffer.h"
  • #include "doppler/dp_state.h"
  • #include "doppler/burst_capture/burst_capture_core.h"
  • #include "doppler/burst_acq/burst_acq_core.h"
  • #include "doppler/acq/acq_core.h"
  • #include "doppler/burst_demod/burst_demod_core.h"
  • #include "doppler/burst_despreader/burst_despreader_core.h"
  • #include "doppler/ppe/ppe_core.h"
  • #include "doppler/corr/corr_core.h"
  • #include "doppler/corr2d/corr2d_core.h"
  • #include "doppler/fft2d/fft2d_core.h"
  • #include "doppler/spectral/spectral_core.h"
  • #include "doppler/loop_filter/loop_filter_core.h"
  • #include "doppler/detection/detection_core.h"
  • #include "doppler/fft/fft_core.h"
  • #include "doppler/pn/pn_core.h"
  • #include "doppler/conv/conv_core.h"
  • #include "doppler/rs/rs_core.h"
  • #include "doppler/gold/gold_core.h"
  • #include "doppler/mpsk/mpsk_core.h"
  • #include "doppler/cvt/cvt_core.h"
  • #include "doppler/wfm/wfm_frame.h"

Classes

Type Name
struct dp_dsss_burst_receiver_state_t
DsssBurstReceiver state.
struct dsss_br_event_t
One completed burst's event, as events() hands it back.

Public Functions

Type Name
int dp_dsss_burst_receiver_configure_search_raw (dp_dsss_burst_receiver_state_t * state, size_t doppler_bins, size_t n_noncoh)
Pin the acquisition search grid, bypassing the auto-sizing.
dp_dsss_burst_receiver_state_t * dp_dsss_burst_receiver_create_desc (const uint8_t * acq_code, size_t acq_code_len, const uint8_t * data_code, size_t data_code_len, const wfm_frame_desc_t * frame, size_t reps, size_t spc, double chip_rate, double cn0_dbhz, double doppler_uncertainty, double pfa, double pd, double carrier_hz, double max_rate, size_t est_segments, const char ** why)
Create a receiver from the frame DESCRIPTION the transmitter spread, and no hand-counted frame length.
dp_dsss_burst_receiver_state_t * dp_dsss_burst_receiver_create_frame (const uint8_t * acq_code, size_t acq_code_len, const uint8_t * data_code, size_t data_code_len, const wfm_frame_desc_t * frame, size_t reps, size_t spc, double chip_rate, double cn0_dbhz, double doppler_uncertainty, double pfa, double pd, double carrier_hz, double max_rate, size_t est_segments)
The Python binding's constructor: dp_dsss_burst_receiver_create_desc without thewhy out-parameter.
void dp_dsss_burst_receiver_destroy (dp_dsss_burst_receiver_state_t * state)
Destroy a dsss_burst_receiver instance and release all memory.
size_t dp_dsss_burst_receiver_events (dp_dsss_burst_receiver_state_t * state, size_t n, dsss_br_event_t * out, size_t max_out)
The event record for each burst the last push() returned.
size_t dp_dsss_burst_receiver_events_max_out (dp_dsss_burst_receiver_state_t * state)
Max records events() writes: one per burst the last push() returned.
double dp_dsss_burst_receiver_get_cn0_dbhz_est (const dp_dsss_burst_receiver_state_t * state)
double dp_dsss_burst_receiver_get_demod_cn0_dbhz (const dp_dsss_burst_receiver_state_t * state)
double dp_dsss_burst_receiver_get_demod_timing_chips (const dp_dsss_burst_receiver_state_t * state)
double dp_dsss_burst_receiver_get_doppler_hz_est (const dp_dsss_burst_receiver_state_t * state)
double dp_dsss_burst_receiver_get_doppler_res_hz (const dp_dsss_burst_receiver_state_t * state)
uint64_t dp_dsss_burst_receiver_get_dropped (const dp_dsss_burst_receiver_state_t * state)
Samples of look-back the capture discarded while a queued burst still needed them never refused input, which push() does not do. A LOST BURST, not a statistic a lifetime count that survives reset().
double dp_dsss_burst_receiver_get_est_freq_hz (const dp_dsss_burst_receiver_state_t * state)
double dp_dsss_burst_receiver_get_est_rate_hz (const dp_dsss_burst_receiver_state_t * state)
bool dp_dsss_burst_receiver_get_frame_valid (const dp_dsss_burst_receiver_state_t * state)
size_t dp_dsss_burst_receiver_get_min_gap (const dp_dsss_burst_receiver_state_t * state)
uint64_t dp_dsss_burst_receiver_get_n_bursts (const dp_dsss_burst_receiver_state_t * state)
size_t dp_dsss_burst_receiver_get_pending (const dp_dsss_burst_receiver_state_t * state)
uint64_t dp_dsss_burst_receiver_get_preamble_start (const dp_dsss_burst_receiver_state_t * state)
size_t dp_dsss_burst_receiver_get_refine_span (const dp_dsss_burst_receiver_state_t * state)
size_t dp_dsss_burst_receiver_get_retain_span (const dp_dsss_burst_receiver_state_t * state)
void dp_dsss_burst_receiver_get_state (const dp_dsss_burst_receiver_state_t * state, void * blob)
Serialize state's cross-call state intoblob (caller-owned,dp_dsss_burst_receiver_state_bytes() long).
size_t dp_dsss_burst_receiver_llrs (dp_dsss_burst_receiver_state_t * state, size_t n, float * out, size_t max_out)
The SOFT bits of every burst the last push() returned.
size_t dp_dsss_burst_receiver_llrs_max_out (dp_dsss_burst_receiver_state_t * state, size_t n)
Max LLRs llrs() writes: frame bits x the bursts the last push returned.
size_t dp_dsss_burst_receiver_push (dp_dsss_burst_receiver_state_t * state, const float _Complex * x, size_t x_len, uint8_t * out, size_t max_out)
Stream samples; return the payload of EVERY burst that completed.
size_t dp_dsss_burst_receiver_push_max_out (dp_dsss_burst_receiver_state_t * state, size_t x_len)
Max bits push() can write for an input of x_len samples.
void dp_dsss_burst_receiver_reset (dp_dsss_burst_receiver_state_t * state)
Return to searching: drop the history and clear every read-back.
int dp_dsss_burst_receiver_set_state (dp_dsss_burst_receiver_state_t * state, const void * blob)
Restore cross-call state from blob (replacing it).
size_t dp_dsss_burst_receiver_state_bytes (const dp_dsss_burst_receiver_state_t * state)
Byte size of state's blob (envelope + payload + child).

Macros

Type Name
define DSSS_BURST_RECEIVER_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc)('D', 'B', 'R', 'X')
Per-object envelope tag: "DBRX" (DsssBurstReceiver).
define DSSS_BURST_RECEIVER_STATE_VERSION 7u

Detailed Description

Composes the three certified burst objects behind one push(): acquisition SEARCHES the stream, a refine stage recovers the exact preamble start, and the demodulator produces the payload. It owns the hand-off between them the epoch, the fold, and the look-back reaching back to a burst start that has already gone past which is the part every caller previously redid by hand. See docs/design/dsss-burst-receiver.md.

Lifecycle: create, then push() repeatedly, then destroy. There is no step()/steps(): a burst is a frame, not a sample.

uint8_t acq[31] = { 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0,
                    0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0 };
uint8_t data[8] = { 1, 0, 1, 1, 0, 0, 1, 0 }, sb[13] = { 0 };
const wfm_seq_t sync = { .kind = WFM_SEQ_LITERAL, .bits = sb, .len = 13 };
const wfm_seq_t body = { .kind = WFM_SEQ_DATA, .len = 32 };
wfm_frame_desc_t f;
dp_wfm_frame_fixed (&f, NULL, 0, &sync, &body, 1);  // sync|data:32|crc16
dp_dsss_burst_receiver_state_t *rx = dp_dsss_burst_receiver_create_desc (
    acq, 31, data, 8, &f, 4, 4, 1.0e6, 55.0, 0.0, 1e-3, 0.9, 0.0, 0.0, 10,
    NULL);
if (!rx)
  return 1;
float _Complex samples[256] = { 0 };   // the stream goes here
uint8_t bits[(13 + 32 + 16) * 4];      // frame_syms per burst: sync|payload|CRC
size_t n = dp_dsss_burst_receiver_push (rx, samples, 256, bits,
                                        sizeof bits);
(void)n;                               // the bits are the FRAME as received
dp_dsss_burst_receiver_destroy (rx);

Public Functions Documentation

function dp_dsss_burst_receiver_configure_search_raw

Pin the acquisition search grid, bypassing the auto-sizing.

int dp_dsss_burst_receiver_configure_search_raw (
    dp_dsss_burst_receiver_state_t * state,
    size_t doppler_bins,
    size_t n_noncoh
) 

The escape hatch for a caller who wants a specific (doppler_bins, n_noncoh) rather than the grid the cn0_dbhz/pfa/pd sizing chooses. Forwards to the embedded engine unchanged.

Parameters:

  • state Must be non-NULL.
  • doppler_bins Coherent depth to pin, in [1, reps].
  • n_noncoh Non-coherent looks to combine.

Returns:

0 on success, non-zero if the grid is out of range.

>>> import numpy as np
>>> from doppler.dsss import DsssBurstReceiver
>>> from doppler.wfm import Frame
>>> rng = np.random.default_rng(0)
>>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
...              crc="crc16")     # 13 + 3 + 16 = 32 symbols a burst
>>> rx = DsssBurstReceiver(
...     rng.integers(0, 2, 31).astype(np.uint8),
...     rng.integers(0, 2, 8).astype(np.uint8), desc, reps=4, spc=4)
>>> rx.configure_search_raw(doppler_bins=1, n_noncoh=1)


function dp_dsss_burst_receiver_create_desc

Create a receiver from the frame DESCRIPTION the transmitter spread, and no hand-counted frame length.

dp_dsss_burst_receiver_state_t * dp_dsss_burst_receiver_create_desc (
    const uint8_t * acq_code,
    size_t acq_code_len,
    const uint8_t * data_code,
    size_t data_code_len,
    const wfm_frame_desc_t * frame,
    size_t reps,
    size_t spc,
    double chip_rate,
    double cn0_dbhz,
    double doppler_uncertainty,
    double pfa,
    double pd,
    double carrier_hz,
    double max_rate,
    size_t est_segments,
    const char ** why
) 

The sync word is the description's field 0, frame_syms its layout's length (both from dp_wfm_frame_desc_rx), and a frame's verdict is dp_wfm_frame_desc_crc_ok over the description, so a frame with no CRC stage is never valid (decision D3 of docs/design/rx-frame-description.md). The description is copied (without its sequences), so the caller may free it at once. This is the one constructor: acquisition, refine and demodulation composed behind one push(), with the look-back span DERIVED from the geometry rather than asked of the caller.

Parameters:

  • acq_code preamble code, 0/1 chips.
  • acq_code_len its length, chips.
  • data_code payload spreading code, 0/1 chips.
  • data_code_len its length, chips.
  • frame the description (const wfm_frame_desc_t *).
  • reps preamble code repetitions.
  • spc samples per chip.
  • chip_rate chips per second.
  • cn0_dbhz design C/N0 for the acquisition, dB-Hz (or NaN).
  • doppler_uncertainty the Doppler span to search, cycles/sample.
  • pfa false-alarm probability, in (0, 1).
  • pd detection probability, in (0, 1).
  • carrier_hz the carrier the baseband is offset by, Hz.
  • max_rate the Doppler rate expected, cycles/sample^2.
  • est_segments partials per acquisition period.
  • why on a NULL return, a static sentence naming the fix; may be NULL.

Returns:

the receiver, or NULL with why set.

const uint8_t   sb[3] = { 1, 0, 1 }, acq[7] = { 1, 1, 1, 0, 1, 0, 0 };
const uint8_t   dcode[4] = { 1, 0, 1, 1 };
const wfm_seq_t sync = { .kind = WFM_SEQ_LITERAL, .bits = sb, .len = 3 };
const wfm_seq_t data = { .kind = WFM_SEQ_DATA, .len = 8 };
wfm_frame_desc_t f;
dp_wfm_frame_fixed (&f, NULL, 0, &sync, &data, 1); // sync|data:8|crc16
const char *why = NULL;
dp_dsss_burst_receiver_state_t *rx = dp_dsss_burst_receiver_create_desc (
    acq, 7, dcode, 4, &f, 3, 2, 1e6, 60.0, 0.0, 1e-3, 0.9, 0.0, 0.0, 10,
    &why);
if (!rx || rx->frame_syms != 3 + 8 + 16)
  return 1;
dp_dsss_burst_receiver_destroy (rx);

function dp_dsss_burst_receiver_create_frame

The Python binding's constructor: dp_dsss_burst_receiver_create_desc without thewhy out-parameter.

dp_dsss_burst_receiver_state_t * dp_dsss_burst_receiver_create_frame (
    const uint8_t * acq_code,
    size_t acq_code_len,
    const uint8_t * data_code,
    size_t data_code_len,
    const wfm_frame_desc_t * frame,
    size_t reps,
    size_t spc,
    double chip_rate,
    double cn0_dbhz,
    double doppler_uncertainty,
    double pfa,
    double pd,
    double carrier_hz,
    double max_rate,
    size_t est_segments
) 

An object's generated constructor has no channel for a reason, so a refused description surfaces as the manifest's create_error_message, which names the rules. C callers that want the reason call the _desc form.

Parameters:

  • acq_code preamble code, 0/1 chips.
  • acq_code_len its length, chips.
  • data_code payload spreading code, 0/1 chips.
  • data_code_len its length, chips.
  • frame the description (const wfm_frame_desc_t *).
  • reps preamble code repetitions.
  • spc samples per chip.
  • chip_rate chips per second.
  • cn0_dbhz design C/N0 for the acquisition, dB-Hz (or NaN).
  • doppler_uncertainty the Doppler span to search, cycles/sample.
  • pfa false-alarm probability, in (0, 1).
  • pd detection probability, in (0, 1).
  • carrier_hz the carrier the baseband is offset by, Hz.
  • max_rate the Doppler rate expected, cycles/sample^2.
  • est_segments partials per acquisition period.

Returns:

the receiver, or NULL.

>>> import numpy as np
>>> from doppler.dsss import DsssBurstReceiver
>>> from doppler.wfm import Frame
>>> rng = np.random.default_rng(0)
>>> acq = rng.integers(0, 2, 31).astype(np.uint8)
>>> dat = rng.integers(0, 2, 8).astype(np.uint8)
>>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
...              crc="crc16")     # the 32-symbol frame the burst carries
>>> rx = DsssBurstReceiver(acq, dat, desc, reps=4, spc=4)
>>> rx.n_bursts
0

function dp_dsss_burst_receiver_destroy

Destroy a dsss_burst_receiver instance and release all memory.

void dp_dsss_burst_receiver_destroy (
    dp_dsss_burst_receiver_state_t * state
) 

Parameters:

  • state May be NULL.

function dp_dsss_burst_receiver_events

The event record for each burst the last push() returned.

size_t dp_dsss_burst_receiver_events (
    dp_dsss_burst_receiver_state_t * state,
    size_t n,
    dsss_br_event_t * out,
    size_t max_out
) 

Row i describes the payload at out[i*frame_syms ...] of that push. A single push can complete many bursts and each needs its own event, so these are a list rather than the scalar read-backs those still exist and still describe the LAST burst, but they cannot speak for the others.

Valid until the next push(), reset() or set_state(). Deliberately not serialized: it describes one call, and keeping it out of the blob is what holds state_bytes() to a pure function of configuration.

Parameters:

  • state Must be non-NULL.
  • n Ignored. The record count is whatever the last push() produced, not something a caller chooses; this parameter exists because every variable-output method carries one, and the binding uses it only as a floor on the buffer it allocates.
  • out Records, caller-owned, max_out long.
  • max_out Capacity of out; see events_max_out().

Returns:

Records written to out min(events_max_out(), max_out).

>>> import numpy as np
>>> from doppler.dsss import DsssBurstReceiver
>>> from doppler.wfm import Frame
>>> rng = np.random.default_rng(0)
>>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
...              crc="crc16")     # 13 + 3 + 16 = 32 symbols a burst
>>> rx = DsssBurstReceiver(
...     rng.integers(0, 2, 31).astype(np.uint8),
...     rng.integers(0, 2, 8).astype(np.uint8), desc, reps=4, spc=4)
>>> bits = rx.push(np.zeros(4096, dtype=np.complex64))
>>> len(rx.events()) == bits.size // 32   # one record per payload
True


function dp_dsss_burst_receiver_events_max_out

Max records events() writes: one per burst the last push() returned.

size_t dp_dsss_burst_receiver_events_max_out (
    dp_dsss_burst_receiver_state_t * state
) 

Parameters:

  • state Must be non-NULL.

Returns:

The number of bursts the most recent push() completed.


function dp_dsss_burst_receiver_get_cn0_dbhz_est

double dp_dsss_burst_receiver_get_cn0_dbhz_est (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_demod_cn0_dbhz

double dp_dsss_burst_receiver_get_demod_cn0_dbhz (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_demod_timing_chips

double dp_dsss_burst_receiver_get_demod_timing_chips (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_doppler_hz_est

double dp_dsss_burst_receiver_get_doppler_hz_est (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_doppler_res_hz

double dp_dsss_burst_receiver_get_doppler_res_hz (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_dropped

Samples of look-back the capture discarded while a queued burst still needed them never refused input, which push() does not do. A LOST BURST, not a statistic a lifetime count that survives reset().

uint64_t dp_dsss_burst_receiver_get_dropped (
    const dp_dsss_burst_receiver_state_t * state
) 


function dp_dsss_burst_receiver_get_est_freq_hz

double dp_dsss_burst_receiver_get_est_freq_hz (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_est_rate_hz

double dp_dsss_burst_receiver_get_est_rate_hz (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_frame_valid

bool dp_dsss_burst_receiver_get_frame_valid (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_min_gap

size_t dp_dsss_burst_receiver_get_min_gap (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_n_bursts

uint64_t dp_dsss_burst_receiver_get_n_bursts (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_pending

size_t dp_dsss_burst_receiver_get_pending (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_preamble_start

uint64_t dp_dsss_burst_receiver_get_preamble_start (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_refine_span

size_t dp_dsss_burst_receiver_get_refine_span (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_retain_span

size_t dp_dsss_burst_receiver_get_retain_span (
    const dp_dsss_burst_receiver_state_t * state
) 

function dp_dsss_burst_receiver_get_state

Serialize state's cross-call state intoblob (caller-owned,dp_dsss_burst_receiver_state_bytes() long).

void dp_dsss_burst_receiver_get_state (
    const dp_dsss_burst_receiver_state_t * state,
    void * blob
) 


function dp_dsss_burst_receiver_llrs

The SOFT bits of every burst the last push() returned.

size_t dp_dsss_burst_receiver_llrs (
    dp_dsss_burst_receiver_state_t * state,
    size_t n,
    float * out,
    size_t max_out
) 

crealf(sym * derot) IS the log-likelihood ratio up to a scale, and the demodulator used to compute it, slice it to one bit and free it. A hard decision throws away roughly 2 dB of the coding gain a soft-input decoder exists to deliver (mpsk_soft_demap's own docstring), which is what makes a coded burst worth coding.

Concatenated the same way push()'s payloads are, one row of frame_syms per burst: burst i starts at i * frame_syms, in the order events() reports. The convention is mpsk_soft_demap's — positive means bit 0, so L < 0 reproduces exactly the bits push() returned. Spans the WHOLE frame rather than the payload alone, because a code covers what its description says it covers.

Valid until the next push(), reset() or set_state(); deliberately not serialized, for the same reason events() is not: it describes one call.

Parameters:

  • state Receiver handle.
  • n Ignored — the count is the last push's, not a request.
  • out Receives the LLRs.
  • max_out Capacity of out; see llrs_max_out().

Returns:

LLRs written.

>>> import numpy as np
>>> from doppler.dsss import DsssBurstReceiver
>>> from doppler.wfm import Frame
>>> rng = np.random.default_rng(0)
>>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
...              crc="crc16")     # 13 + 3 + 16 = 32 symbols a burst
>>> rx = DsssBurstReceiver(
...     rng.integers(0, 2, 31).astype(np.uint8),
...     rng.integers(0, 2, 8).astype(np.uint8), desc, reps=4, spc=4)
>>> bits = rx.push(np.zeros(4096, dtype=np.complex64))
>>> len(bits), len(rx.llrs(rx.llrs_max_out(1)))   # nothing decoded
(0, 0)


function dp_dsss_burst_receiver_llrs_max_out

Max LLRs llrs() writes: frame bits x the bursts the last push returned.

size_t dp_dsss_burst_receiver_llrs_max_out (
    dp_dsss_burst_receiver_state_t * state,
    size_t n
) 

Parameters:

  • state Receiver handle.
  • n Ignored, as in llrs().

function dp_dsss_burst_receiver_push

Stream samples; return the payload of EVERY burst that completed.

size_t dp_dsss_burst_receiver_push (
    dp_dsss_burst_receiver_state_t * state,
    const float _Complex * x,
    size_t x_len,
    uint8_t * out,
    size_t max_out
) 

Retains x in the history ring and feeds the embedded acquisition. When a detection fires, the refine stage correlates the whole preamble to recover the exact preamble start the quantity acquisition structurally cannot report, its code phase being a lag modulo one code period and the burst is demodulated once its last sample has arrived.

EVERY SAMPLE OF x IS CONSUMED, and every burst that completes is returned by the call that completed it. Payloads are concatenated, so burst i occupies out from i*frame_syms, and events() returns the matching record for each. Returning 0 is normal, not an error: it means no burst completed in this call.

This is the contract doppler#1008 broke. push() used to return at most one burst per call AND abandon the rest of its input to do it, so a block carrying several bursts lost all but the first measured at 6/6 decoded with 333-sample blocks against 1/6 with one large one. The history ring is a contiguous window over the stream and is never reset between bursts, so a payload whose tail falls outside one call is completed by a later one.

Parameters:

  • state Must be non-NULL.
  • x Input samples (cf32), x_len long.
  • x_len Number of input samples.
  • out Payload bits, caller-owned, max_out long.
  • max_out Capacity of out; see push_max_out().

Returns:

Bits written to out n_bursts_returned * frame_syms.

>>> import numpy as np
>>> from doppler.dsss import DsssBurstReceiver
>>> from doppler.wfm import Frame
>>> rng = np.random.default_rng(0)
>>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
...              crc="crc16")     # 13 + 3 + 16 = 32 symbols a burst
>>> rx = DsssBurstReceiver(
...     rng.integers(0, 2, 31).astype(np.uint8),
...     rng.integers(0, 2, 8).astype(np.uint8), desc, reps=4, spc=4)
>>> bits = rx.push(np.zeros(4096, dtype=np.complex64))
>>> bits.size            # silence carries no burst
0


function dp_dsss_burst_receiver_push_max_out

Max bits push() can write for an input of x_len samples.

size_t dp_dsss_burst_receiver_push_max_out (
    dp_dsss_burst_receiver_state_t * state,
    size_t x_len
) 

push() returns EVERY burst it completed, so the bound scales with the input: distinct bursts cannot overlap, so they are at least burst_len apart, and a push of x_len samples can complete at most x_len/burst_len + 1 of them plus every detection already queued from an earlier call, which is q_cap.

Parameters:

  • state Must be non-NULL.
  • x_len Number of input samples the caller is about to push.

Returns:

(x_len/burst_len + 1 + q_cap) * frame_syms.


function dp_dsss_burst_receiver_reset

Return to searching: drop the history and clear every read-back.

void dp_dsss_burst_receiver_reset (
    dp_dsss_burst_receiver_state_t * state
) 

Resets the embedded acquisition, discards the retained look-back, and clears all the event fields, so a fresh stream cannot inherit the previous burst's verdict. The lifetime counters (n_bursts, dropped) deliberately survive a reset that zeroed them could hide that this receiver had already lost samples. Construction parameters are untouched.

Parameters:

  • state Must be non-NULL.
    >>> import numpy as np
    >>> from doppler.dsss import DsssBurstReceiver
    >>> from doppler.wfm import Frame
    >>> rng = np.random.default_rng(0)
    >>> desc = Frame(sync=np.zeros(13, np.uint8), payload=np.zeros(3, np.uint8),
    ...              crc="crc16")     # 13 + 3 + 16 = 32 symbols a burst
    >>> rx = DsssBurstReceiver(
    ...     rng.integers(0, 2, 31).astype(np.uint8),
    ...     rng.integers(0, 2, 8).astype(np.uint8), desc, reps=4, spc=4)
    >>> _ = rx.push(np.zeros(1024, dtype=np.complex64))
    >>> rx.reset()
    

function dp_dsss_burst_receiver_set_state

Restore cross-call state from blob (replacing it).

int dp_dsss_burst_receiver_set_state (
    dp_dsss_burst_receiver_state_t * state,
    const void * blob
) 

Returns:

DP_OK, or DP_ERR_INVALID if the envelope or any child rejects.


function dp_dsss_burst_receiver_state_bytes

Byte size of state's blob (envelope + payload + child).

size_t dp_dsss_burst_receiver_state_bytes (
    const dp_dsss_burst_receiver_state_t * state
) 


Macro Definition Documentation

define DSSS_BURST_RECEIVER_STATE_MAGIC

Per-object envelope tag: "DBRX" (DsssBurstReceiver).

#define DSSS_BURST_RECEIVER_STATE_MAGIC `DP_FOURCC ('D', 'B', 'R', 'X')`


define DSSS_BURST_RECEIVER_STATE_VERSION

#define DSSS_BURST_RECEIVER_STATE_VERSION `7u`


The documentation for this class was generated from the following file native/inc/doppler/dsss_burst_receiver/dsss_burst_receiver_core.h