File cic_core.h¶
FileList > cic > cic_core.h
Go to the source code of this file
CIC decimation filter — 4-stage, M=1, UQ16 integer pipeline. More...
#include "clib_common.h"#include "jm_perf.h"
Classes¶
| Type | Name |
|---|---|
| struct | cic_state_t CIC filter state. |
Public Functions¶
| Type | Name |
|---|---|
| cic_state_t * | cic_create (uint32_t R) Create a 4-stage, M=1 CIC decimation filter. Allocates the state struct on the heap and pre-computes the normalisation right-shift (CIC_N * log2(R) bits). All integrator and comb accumulators are zeroed; the first output arrives after R input samples. Returns NULL for invalid R or OOM. |
| JM_FORCEINLINE JM_HOT size_t | cic_decimate (cic_state_t * state, const float complex * in, size_t n_in, float complex * out) Decimate a block of CF32 samples through the CIC pipeline. Each sample is converted to offset-binary UQ16, pushed through CIC_N integrators (unsigned wrapping), and when the phase counter reaches R the integrated value is passed through CIC_N M=1 comb stages and converted back to CF32. State persists between calls. Feeding blocks that are multiples of R gives predictable output counts (exactly n_in/R samples per block). |
| size_t | cic_decimate_max_out (cic_state_t * state) Upper bound on decimate output — returns 0 (lazy-alloc signal). |
| void | cic_destroy (cic_state_t * state) |
| void | cic_reconfigure (cic_state_t * state, uint32_t R) Change the decimation ratio in place and reset all filter state. Recomputes the normalisation shift (CIC_N * log2(R)) and zeros all accumulators so the filter behaves exactly like a freshly created one with the new R. Silently ignores R values that are not a power-of-two in [2, 4096] — the state is left unchanged in that case. |
| void | cic_reset (cic_state_t * state) Zero all integrator and comb accumulators; preserve R and shift. The first output sample after reset arrives after R more input samples, matching post-create behaviour. Use between signal bursts to eliminate transient artefacts caused by residual pipeline state. |
Macros¶
| Type | Name |
|---|---|
| define | CIC_N 4 |
Detailed Description¶
Fixed design parameters: N = 4 stages (~77 dB alias rejection at f_p = 0.1 * f_out) M = 1 (differential delay — one-sample comb) R = power-of-two decimation ratio (enforced at create time)
Input/output boundary: CF32 (float _Complex), matching the doppler default signal type. Internally, each sample is converted to UQ16 — offset-binary: v_q15 + 32768 → [0, 65535] in a uint64_t — giving 48 bits of headroom for the pipeline gain of N * log2(R) bits. For R <= 4096 (log2 = 12) the gain is 48 bits; max accumulation = 65535 * R^N = (2^16 - 1) * 2^48 = 2^64 - 2^48 < 2^64, so no overflow occurs.
All arithmetic is unsigned: inputs are non-negative [0, 65535], wrapping is defined (mod 2^64), and the output decode subtracts the offset in floating-point — no signed integer casts anywhere in the hot path.
The unsigned modular-arithmetic CIC property guarantees exact outputs: every intermediate overflow in the integrators cancels in the comb stages, provided the true result fits in 64 bits. No saturation, no range checks, no floating-point in the inner loop.
With M=1 and N fixed, the entire comb state is four uint64_t values per channel — no heap allocation beyond the state struct itself.
Alias rejection : ~77 dB at f_p = 0.1 * f_out (independent of R) Passband droop : ~0.57 dB at f_p = 0.1 * f_out (independent of R) Output precision: 16-bit Q15 (independent of R and N)
cic_state_t *cic = cic_create(16); // R=16, N=4, M=1
size_t n_out = cic_decimate(cic, in, 1024, out);
cic_destroy(cic);
Public Functions Documentation¶
function cic_create¶
Create a 4-stage, M=1 CIC decimation filter. Allocates the state struct on the heap and pre-computes the normalisation right-shift (CIC_N * log2(R) bits). All integrator and comb accumulators are zeroed; the first output arrives after R input samples. Returns NULL for invalid R or OOM.
Parameters:
RDecimation ratio. Must be a power of two in [2, 4096]. Returns NULL for R=0, non-power-of-two, or R > 4096.
Returns:
Heap-allocated state, or NULL on invalid R or OOM.
function cic_decimate¶
Decimate a block of CF32 samples through the CIC pipeline. Each sample is converted to offset-binary UQ16, pushed through CIC_N integrators (unsigned wrapping), and when the phase counter reaches R the integrated value is passed through CIC_N M=1 comb stages and converted back to CF32. State persists between calls. Feeding blocks that are multiples of R gives predictable output counts (exactly n_in/R samples per block).
JM_FORCEINLINE JM_HOT size_t cic_decimate (
cic_state_t * state,
const float complex * in,
size_t n_in,
float complex * out
)
Parameters:
statePointer to a valid cic_state_t.inCF32 input block.n_inNumber of input samples.outOutput buffer; must hold at least n_in elements.
Returns:
CF32 output array; length is floor((phase + n_in) / R).
>>> from doppler.resample import CIC
>>> import numpy as np
>>> cic = CIC(R=16)
>>> for _ in range(4):
... _ = cic.decimate(np.zeros(16, dtype=np.complex64))
>>> y = cic.decimate(np.zeros(16, dtype=np.complex64))
>>> y.tolist(), y.dtype
([0j], dtype('complex64'))
function cic_decimate_max_out¶
Upper bound on decimate output — returns 0 (lazy-alloc signal).
The Python extension allocates n_in elements on the first call. Since n_in >= ceil(n_in/R) = n_out for all R >= 1, the buffer is always large enough as long as block size stays consistent.
function cic_destroy¶
Free resources. NULL is a no-op.
function cic_reconfigure¶
Change the decimation ratio in place and reset all filter state. Recomputes the normalisation shift (CIC_N * log2(R)) and zeros all accumulators so the filter behaves exactly like a freshly created one with the new R. Silently ignores R values that are not a power-of-two in [2, 4096] — the state is left unchanged in that case.
Parameters:
statePointer to a valid cic_state_t.RNew decimation ratio. Same constraints as cic_create().
>>> from doppler.resample import CIC
>>> cic = CIC(R=4)
>>> cic.reconfigure(8)
>>> cic.R, cic.shift
(8, 12)
function cic_reset¶
Zero all integrator and comb accumulators; preserve R and shift. The first output sample after reset arrives after R more input samples, matching post-create behaviour. Use between signal bursts to eliminate transient artefacts caused by residual pipeline state.
Macro Definition Documentation¶
define CIC_N¶
Fixed stage count. Alias rejection ~19.2 dB/stage at f_p=0.1.
The documentation for this class was generated from the following file native/inc/cic/cic_core.h