Skip to content

Struct dp_burst_capture_state_t

ClassList > dp_burst_capture_state_t

BurstCapture state. More...

  • #include <burst_capture_core.h>

Public Attributes

Type Name
dp_burst_acq_state_t * acq
size_t acq_blob_max
int backed
size_t burst_len
double _Complex * cell_buf
double * cell_f
size_t chunk_max
double cn0_dbhz_est
size_t code_period
size_t corr_len
burst_capture_detection_t * det
size_t det_cap
size_t det_len
double doppler_hz_est
double doppler_rate_hz_s
double doppler_res_hz
uint64_t dropped
burst_capture_event_t * ev
size_t ev_cap
size_t ev_len
dp_f32_t * hist
uint64_t horizon
size_t k_hi
size_t k_lo
size_t max_cells
size_t min_gap
uint64_t n_bursts
size_t pending
uint64_t preamble_start
burst_capture_pending_t * q
size_t q_cap
size_t q_head
double _Complex * rate_ph
size_t rate_ph_n
int recovered
size_t refine_span
uint8_t * released
size_t reps
size_t retain_span
uint64_t samples_fed
uint64_t suppress_base
uint64_t suppress_until
int underpowered
float _Complex * win
size_t win_cap

Detailed Description

Allocate with dp_burst_capture_create().

Public Attributes Documentation

variable acq

dp_burst_acq_state_t* dp_burst_capture_state_t::acq;

Search stage, certified separately.


variable acq_blob_max

size_t dp_burst_capture_state_t::acq_blob_max;

Fixed upper bound on the acquisition child's blob. state_bytes() must be a pure function of CONFIGURATION jm's binding compares an incoming blob's length against it yet both the retained look-back and acq's own unconsumed ring vary with the stream. Both are therefore written into fixed-size regions with a length prefix.


variable backed

int dp_burst_capture_state_t::backed;

Non-zero when the ring's pages are a FILE's. Fixed at create(), so state_bytes() stays a pure function of configuration a backed blob and an in-RAM one are different sizes on purpose, and neither restores into the other.


variable burst_len

size_t dp_burst_capture_state_t::burst_len;

Samples in one emitted window. Acquisition has no notion of this dp_acq_create_burst() takes search parameters only which is exactly why it is a parameter HERE: for a capture, the burst length is what gets captured.


variable cell_buf

double _Complex* dp_burst_capture_state_t::cell_buf;

Refine's cells: dp_acq_cell_corr_grid() of every candidate preamble POSITION (one code period each) at every Doppler cell inside the detecting engine's bin, position-major, corr_len * max_cells. Computed once; each candidate sums reps consecutive rows of one cell coherently. The statistic is ACQUISITION'S, evaluated at the settled code phase: refine resolves which repetition, nothing else (doppler#1502).


variable cell_f

double* dp_burst_capture_state_t::cell_f;

Those cells' frequencies, Hz: max_cells.


variable chunk_max

size_t dp_burst_capture_state_t::chunk_max;

Largest slice of one push processed at a time, so any block size is accepted without the ring overrunning its own retention.


variable cn0_dbhz_est

double dp_burst_capture_state_t::cn0_dbhz_est;

C/N0 lower bound, dB-Hz (saturating).


variable code_period

size_t dp_burst_capture_state_t::code_period;

One preamble repetition, in SAMPLES. The modulus acq's code_phase is a residue of, so every epoch ambiguity in this object is stated against it.


variable corr_len

size_t dp_burst_capture_state_t::corr_len;

Candidate positions refine can score.


variable det

burst_capture_detection_t* dp_burst_capture_state_t::det;

Raw hits of the LAST push what the SEARCH found, before the claim rule and the suppression window.


variable det_cap

size_t dp_burst_capture_state_t::det_cap;

Allocated records.


variable det_len

size_t dp_burst_capture_state_t::det_len;

Records the last push wrote.


variable doppler_hz_est

double dp_burst_capture_state_t::doppler_hz_est;

Signed coarse Doppler, Hz.


variable doppler_rate_hz_s

double dp_burst_capture_state_t::doppler_rate_hz_s;

Refine's winning rate hypothesis, Hz/s.


variable doppler_res_hz

double dp_burst_capture_state_t::doppler_res_hz;

Width of that estimate.


variable dropped

uint64_t dp_burst_capture_state_t::dropped;

Samples of look-back discarded while a queued detection still needed them the part of a dead detection's span (one whose history is gone, so it can never be emitted) behind the ring's tail. push() never refuses input. A LOST BURST each, not a statistic lifetime, survives reset().


variable ev

burst_capture_event_t* dp_burst_capture_state_t::ev;

One record per window returned.


variable ev_cap

size_t dp_burst_capture_state_t::ev_cap;

Allocated records.


variable ev_len

size_t dp_burst_capture_state_t::ev_len;

Records the last push() wrote.


variable hist

dp_f32_t* dp_burst_capture_state_t::hist;

History ring. Double-mapped, so a window that spans the wrap is ONE contiguous pointer. This object keeps its own rather than borrowing acq's, which consumes every frame it processes and has therefore released what is still needed.


variable horizon

uint64_t dp_burst_capture_state_t::horizon;

Scratch, inside push(): the stream position a window must END by to count as arrived. Claiming a detection first emits what was complete when that detection was MADE, so what a push returns follows stream time rather than the caller's block size (doppler#1527). UINT64_MAX outside the claim loop; never serialized.


variable k_hi

size_t dp_burst_capture_state_t::k_hi;

...and AFTER: reps. The detecting frame can start before the preamble, so the anchor can be up to coherent_bins - 1 periods early. It was 2, and at reps=10 refine returned one period early with a resolved-looking margin (doppler#1181).


variable k_lo

size_t dp_burst_capture_state_t::k_lo;

Whole code periods searched BEFORE the anchor: 3*reps + 2, the detection lag's bound.


variable max_cells

size_t dp_burst_capture_state_t::max_cells;

Doppler cells refine can need: the most an engine bin spans at depth reps, which is at D = 1 2 * ceil(reps * BURST_CAPTURE_REFINE_INTERP / 2) + 3, plus the cells a rate hypothesis shifts the preamble's Doppler by, per side, when the engine searches rates.


variable min_gap

size_t dp_burst_capture_state_t::min_gap;

Dead air a caller must leave BETWEEN bursts, in samples edge to edge, not start to start.

DERIVED, and the derivation is the point. A detection's anchor is the code epoch of whichever frame detected, and acquisition's framing is not aligned to the preamble, so the last frame that can detect sits up to reps * code_period past the true start (the detection lag, docs/design/dsss-burst-receiver.md ยง7.1). CLAIM merges two anchors closer than refine_span, so with the first burst detected LATE and the second EARLY the pair survives only when

gap >= refine_span + reps*P - burst_len

ZERO is a real answer a burst longer than refine_span + reps*P needs no gap for the claim rule's sake. It does not mean zero is wise: a zero gap is a continuous stream rather than a burst link (the design's own non-goal), and it measures 88% at a geometry where this reads 0.

The prose this replaces said max(0, refine_span - burst_len) and was short by the whole detection-lag term 32 samples against 528 at the C suite's geometry (doppler#1172).


variable n_bursts

uint64_t dp_burst_capture_state_t::n_bursts;

Windows emitted, lifetime.


variable pending

size_t dp_burst_capture_state_t::pending;

Detections held because their burst window has NOT fully arrived the caller-facing "there is not enough data yet" read-back. push() deliberately emits nothing for these: a window is returned when it is complete, not when it is guessed at. What it exists for is the other end a caller closing a file while this is non-zero is discarding a burst that would have been captured.


variable preamble_start

uint64_t dp_burst_capture_state_t::preamble_start;

Stream-absolute preamble start. Never late.


variable q

burst_capture_pending_t* dp_burst_capture_state_t::q;

Detections, anchor order; q_cap long.


variable q_cap

size_t dp_burst_capture_state_t::q_cap;

DERIVED, not a constant. Entries sit about refine_span apart inside the history trim keeps, so the count scales with burst_len/refine_span about 1 at a short-burst test geometry but 5.5x at a real link. A fixed 8 silently dropped the hit AND the rest of the batch on anything else.


variable q_head

size_t dp_burst_capture_state_t::q_head;

Index of the oldest entry.


variable rate_ph

double _Complex* dp_burst_capture_state_t::rate_ph;

Refine's rate hypotheses as phasors over the preamble's periods, rate_ph_n * reps, built once at create.


variable rate_ph_n

size_t dp_burst_capture_state_t::rate_ph_n;

Rows of rate_ph; 1 without hypotheses.


variable recovered

int dp_burst_capture_state_t::recovered;

Non-zero when create() found the backing file already holding a ring of exactly this geometry, so its samples ARE the look-back. Zero when the file was created or resized, which zeroes it and then a blob claiming retained history has nothing to reach back into, which set_state() refuses rather than resuming into silence.


variable refine_span

size_t dp_burst_capture_state_t::refine_span;

Candidate offsets searched, in samples: (k_lo + k_hi + reps) * code_period. Read it rather than restating the formula the design doc's own prose for it was 2.4x low at reps=5 until it was measured.

The merge test compares two resolved code epochs burst START against burst START so it bounds start-to-start separation, NOT the dead air between bursts (doppler#1085). The gap actually required is NOT max(0, refine_span - burst_len) either: swept, a pair needs about two code periods of dead air, against the 32 samples that formula gives at the test geometry (doppler#1172).


variable released

uint8_t* dp_burst_capture_state_t::released;

Per row of ev: the consumer said "not a burst". Scratch, like the rows.


variable reps

size_t dp_burst_capture_state_t::reps;

Preamble repetitions. The preamble itself is not kept: the acquisition engine holds it, at unit RMS, as its reference row, and that is all refine reads.


variable retain_span

size_t dp_burst_capture_state_t::retain_span;

Samples that must stay reachable: refine span + one whole burst. Also the caller-facing minimum TRAILING context a burst closer than this to the end of what has been pushed is not emitted until more samples arrive.


variable samples_fed

uint64_t dp_burst_capture_state_t::samples_fed;

Stream position: total samples ever pushed. What makes an epoch stream-ABSOLUTE, and the reason preamble_start is a quantity only this object can compute.


variable suppress_base

uint64_t dp_burst_capture_state_t::suppress_base;

suppress_until as the last push() began: what EARLIER pushes' windows own, which a release() of this push's window must not give back.


variable suppress_until

uint64_t dp_burst_capture_state_t::suppress_until;

Detections below this stream position fall inside a burst already EMITTED, so they are the payload firing against the acquisition code rather than new bursts. Armed when a window is emitted refine resolved a start here and this object handed out the whole span, which is the fact it owns. Arming it on every DETECTION instead let one spurious hit blind the search for a whole burst and discard the next real one (doppler#1004). Coalescing the several frames of ONE preamble is a separate job, done by refine_span proximity plus a greatest-of tie-break.


variable underpowered

int dp_burst_capture_state_t::underpowered;

The search cannot meet the requested pd at this cn0_dbhz and geometry. It still builds a best-effort grid, so the symptom is bursts that are never captured rather than an error.


variable win

float _Complex* dp_burst_capture_state_t::win;

Emitted windows, burst_len apart.


variable win_cap

size_t dp_burst_capture_state_t::win_cap;

Allocated samples.



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