Skip to content

File specan_core.h

FileList > doppler > specan > specan_core.h

Go to the source code of this file

Specan — natural-parameter spectrum analyzer (DDC + averaging PSD). More...

  • #include "doppler/ddc/ddc_core.h"
  • #include "doppler/psd/psd_core.h"
  • #include "doppler/dp_state.h"
  • #include "doppler/dp_complex.h"
  • #include <stddef.h>
  • #include "doppler/lo/lo_core.h"
  • #include "doppler/RateConverter/RateConverter_core.h"
  • #include "doppler/resamp/resamp_core.h"
  • #include "doppler/hbdecim/hbdecim_core.h"
  • #include "doppler/cic/cic_core.h"
  • #include "doppler/fir/fir_core.h"
  • #include "doppler/resample/resample_core.h"
  • #include "doppler/acc_trace/acc_trace_core.h"
  • #include "doppler/fft/fft_core.h"
  • #include "doppler/spectral/spectral_core.h"
  • #include "doppler/agc/agc_core.h"
  • #include "doppler/dp_tlm/dp_tlm_core.h"

Classes

Type Name
struct dp_specan_state_t
Specan state. Allocate with dp_specan_create() .

Public Functions

Type Name
dp_specan_state_t * dp_specan_create (double fs, double span, double rbw, double src_center, double center, double offset_db, double full_scale, size_t bits, size_t navg)
Create a natural-parameter spectrum analyzer.
void dp_specan_destroy (dp_specan_state_t * state)
Destroy a Specan instance and release all memory.
size_t dp_specan_execute (dp_specan_state_t * state, const float _Complex * x, size_t x_len, float * out, size_t max_out)
Mix, decimate, average and return one display spectrum, or nothing.
size_t dp_specan_execute_max_out (dp_specan_state_t * state)
Output capacity hint for dp_specan_execute() ; equals disp_n.
void dp_specan_get_state (const dp_specan_state_t * state, void * blob)
void dp_specan_reset (dp_specan_state_t * state)
Drop pending samples and the running average; LO/filter history zero.
void dp_specan_retune (dp_specan_state_t * state, double center)
Retune the display center without rebuilding the chain.
int dp_specan_set_state (dp_specan_state_t * state, const void * blob)
size_t dp_specan_state_bytes (const dp_specan_state_t * state)

Macros

Type Name
define SPECAN_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('S','P','A','N')
define SPECAN_STATE_VERSION 1u

Detailed Description

A streaming spectrum analyzer that speaks the instrument parameters an operator already knows — center frequency, span, resolution bandwidth (RBW), and reference level — instead of the DSP knobs (transform length, Kaiser beta) underneath them. It is the C-first home for the mapping that doppler.specan's engine used to hand-roll in Python.

It composes the existing library, re-implementing nothing:

cf32 in (fs_in)  →  Ddc  (mix center→DC, decimate to fs_out = span·1.28)
                 →  PSD (Kaiser window → FFT → cg²-normalised power,
                           averaged over `navg` segments)
                 →  crop to the central ±span/2 display band
                 →  dB + ref offset  →  float display spectrum
  • dp_ddc_state_t is the tuner/decimator (LO mix + RateConverter cascade); retuning the center is a cheap, seamless LO phase change.
  • dp_psd_state_t is the one averaging-PSD core shared with the measurement suite; navg = 1 gives a responsive single-periodogram frame, larger navg trades update rate for a smoother, lower-variance trace.

The display band length and the bin→frequency map are fixed at create time: bin i of the returned spectrum maps to center + (i − disp_n/2)·fs_out/nfft Hz. Peaks are intentionally NOT computed here — compose dp_find_peaks_f32 on the returned trace.

Lifecycle: create → (execute / retune / reset)* → destroy.

// 200 kHz span, 500 Hz RBW around DC of a 2.048 MHz cf32 stream
dp_specan_state_t *sa = dp_specan_create(2.048e6, 200e3, 500.0, 0.0, 0.0,
                                   0.0, 1.0, 0, 1);
float disp[8192];
size_t n = dp_specan_execute(sa, iq, 65536, disp, 8192);  // 0 until a frame
dp_specan_destroy(sa);

Public Functions Documentation

function dp_specan_create

Create a natural-parameter spectrum analyzer.

dp_specan_state_t * dp_specan_create (
    double fs,
    double span,
    double rbw,
    double src_center,
    double center,
    double offset_db,
    double full_scale,
    size_t bits,
    size_t navg
) 

Derives the DSP from the instrument parameters (docs/design/specan.md):

  • fs_out = 1.28·span, so ±span/2 lands exactly on bin ±nfft/2.56. A span the input cannot supply is clamped to fs/1.28.
  • The window n is the smallest power of two (at least 16) whose narrowest RBW, 2·fs_out/n (a Kaiser ENBW of 2 bins, beta ~12, sidelobes ~-90 dB), does not exceed rbw. The transform is nfft = max(n, 512): zero-padded only when the window is shorter than the 512 points the display needs (401 bins).
  • Kaiser beta widens the ENBW, from 2 up to 4 bins, to meet rbw. The widest RBW is 4 bins of the shortest window, fs_out/4; wider is clamped. Auto (rbw 0) is span/100.

dp_specan_state_t::rbw and dp_specan_state_t::span hold what was realised, which a clamp can make differ from the request.

Parameters:

  • fs Input sample rate (Hz). Must be > 0.
  • span Display span (Hz). 0 = auto, the whole input band (fs/1.28); negative is refused.
  • rbw Resolution bandwidth (Hz). 0 = auto (span/100); negative is refused.
  • src_center Source center frequency (Hz); the input band is centred here, so the analyzer mixes (center − src_center) to DC.
  • center Desired display center frequency (Hz).
  • offset_db Additive dB offset on the display spectrum, applied on top of dBFS (e.g. a dBm calibration the application computes from a reference level).
  • full_scale Amplitude that reads 0 dBFS (> 0). Ignored if bits > 0.
  • bits ADC depth: bits>0 sets the 0-dBFS reference to 2^(bits-1) in the shared PSD core (the single source of truth for the dBFS reference).
  • navg Segments averaged per emitted frame (>= 1).

Returns:

Heap-allocated state, or NULL on invalid argument or OOM.

Note:

Caller must call dp_specan_destroy() when done. Argument order keeps the required parameters (fs, span, rbw) first, matching the generated constructor's hoisting of jm required init params.

>>> from doppler.analyzer import Specan
>>> sa = Specan(fs=2.048e6, span=200e3, rbw=500.0)
>>> sa.fs_out
256000.0
>>> sa.nfft, sa.display_size
(1024, 801)
>>> round(sa.rbw)
500

function dp_specan_destroy

Destroy a Specan instance and release all memory.

void dp_specan_destroy (
    dp_specan_state_t * state
) 

Parameters:

  • state May be NULL (no-op).

function dp_specan_execute

Mix, decimate, average and return one display spectrum, or nothing.

size_t dp_specan_execute (
    dp_specan_state_t * state,
    const float _Complex * x,
    size_t x_len,
    float * out,
    size_t max_out
) 

Feeds x through the Ddc, buffers the decimated output, and once n·navg decimated samples are available windows + FFTs + averages them into a fresh frame, crops the central ±span/2 band and writes it in dB (+ ref_db). Returns 0 (writing nothing) until a frame is ready — the binding maps that to Python None.

Parameters:

  • state Must be non-NULL.
  • x cf32 input block (C-only; the binding passes it).
  • x_len Number of input samples (C-only).
  • out Display-spectrum buffer, dB (C-only).
  • max_out Capacity of out (C-only); >= disp_n is sufficient.

Returns:

Display bins written (disp_n), or 0 if no frame is ready yet.

>>> from doppler.analyzer import Specan
>>> import numpy as np
>>> sa = Specan(fs=2.048e6, span=200e3, rbw=500.0, navg=1)
>>> sa.execute(np.zeros(64, dtype=np.complex64)) is None  # too few
True
>>> frame = sa.execute(np.zeros(65536, dtype=np.complex64))
>>> frame.shape, frame.dtype
((801,), dtype('float32'))

function dp_specan_execute_max_out

Output capacity hint for dp_specan_execute() ; equals disp_n.

size_t dp_specan_execute_max_out (
    dp_specan_state_t * state
) 


function dp_specan_get_state

void dp_specan_get_state (
    const dp_specan_state_t * state,
    void * blob
) 

function dp_specan_reset

Drop pending samples and the running average; LO/filter history zero.

void dp_specan_reset (
    dp_specan_state_t * state
) 

Parameters:

  • state Must be non-NULL.

function dp_specan_retune

Retune the display center without rebuilding the chain.

void dp_specan_retune (
    dp_specan_state_t * state,
    double center
) 

Updates the Ddc LO phase increment (seamless across blocks — no resampler or window reset) and drops pending samples so the next frame reflects only the new tuning. Changing the span or RBW requires a destroy + create (the decimation rate and window length change).

Parameters:

  • state Must be non-NULL.
  • center New display center frequency (Hz).

function dp_specan_set_state

int dp_specan_set_state (
    dp_specan_state_t * state,
    const void * blob
) 

function dp_specan_state_bytes

size_t dp_specan_state_bytes (
    const dp_specan_state_t * state
) 

Macro Definition Documentation

define SPECAN_STATE_MAGIC

#define SPECAN_STATE_MAGIC `DP_FOURCC ('S','P','A','N')`

define SPECAN_STATE_VERSION

#define SPECAN_STATE_VERSION `1u`


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