Skip to content

File adc_core.h

FileList > adc > adc_core.h

Go to the source code of this file

Signed two's-complement ADC model. More...

  • #include "clib_common.h"
  • #include "dp_state.h"
  • #include "jm_perf.h"
  • #include <math.h>

Classes

Type Name
struct adc_state_t
ADC state.

Public Functions

Type Name
adc_state_t * adc_create (int bits, float dbfs, int dithering)
Create an ADC instance.
void adc_destroy (adc_state_t * state)
Destroy an ADC instance and release all memory.
void adc_get_state (const adc_state_t * state, void * blob)
void adc_reset (adc_state_t * state)
Reset ADC to its post-create state.
int adc_set_state (adc_state_t * state, const void * blob)
size_t adc_state_bytes (const adc_state_t * state)
JM_FORCEINLINE JM_HOT int64_t adc_step (adc_state_t * state, float x)
Process one input sample.
void adc_steps (adc_state_t * state, const float * input, int64_t * output, size_t n)
Process a block of float samples to int64.

Macros

Type Name
define ADC_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('A','D','C',' ')
define ADC_STATE_VERSION 1u

Detailed Description

Models an N-bit ADC with configurable full-scale reference (dBFS) and optional TPDF dither. A normalised float input is scaled by the pre-computed double-precision factor, optionally dithered with a triangular-PDF noise source, rounded, clamped to the signed integer range [-(2^(bits-1)), 2^(bits-1)-1], and returned as int64_t.

Scale derivation:

scale = 2^(bits-1) * 10^(-dbfs / 20)

An input of amplitude 10^(dbfs/20) uses the full ADC code range. With the default dbfs=-10.0 a signal at -10 dBFS fills the converter exactly. double precision is used throughout so converters wider than 23 bits (float32 mantissa limit) are modelled without rounding artefacts.

TPDF dither (dithering != 0): two xorshift32 uniform draws are summed to produce a triangular PDF over [-1, +1] LSB before rounding. This breaks correlated quantisation noise patterns at the cost of a slight noise-floor increase. The PRNG state is part of the object; reset() re-seeds it.

Lifecycle: create -> (step / steps / reset)* -> destroy

>>> from doppler.cvt import ADC
>>> import numpy as np
>>> obj = ADC(bits=8, dbfs=0.0, dithering=0)
>>> obj.scale
128.0
>>> obj.bits
8
>>> obj.step(0.0)
0
>>> obj.step(-1.0)
-128
>>> obj.clipped
False
>>> obj.step(1.0)
127
>>> obj.clipped
True
>>> obj.reset()
>>> obj.clipped
False
>>> x = np.array([-1.0, -0.5, 0.0, 0.5, 1.0], dtype=np.float32)
>>> obj.steps(x).tolist()
[-128, -64, 0, 64, 127]

Public Functions Documentation

function adc_create

Create an ADC instance.

adc_state_t * adc_create (
    int bits,
    float dbfs,
    int dithering
) 

Computes scale = 2^(bits-1) * 10^(-dbfs/20), sets the clip bounds, and seeds the xorshift32 PRNG to a fixed constant. Returns NULL if bits is outside [1, 64] or on allocation failure.

Parameters:

  • bits ADC resolution in bits (1..64).
  • dbfs Full-scale reference level in dBFS (typically negative, e.g. -10.0). A signal with amplitude 10^(dbfs/20) fills the converter's integer range exactly.
  • dithering 0 = no dither; non-zero = TPDF dither before rounding.

Returns:

Heap-allocated state, or NULL on invalid args or allocation failure.

Note:

Caller must call adc_destroy() when done.


function adc_destroy

Destroy an ADC instance and release all memory.

void adc_destroy (
    adc_state_t * state
) 

Parameters:

  • state May be NULL.

function adc_get_state

void adc_get_state (
    const adc_state_t * state,
    void * blob
) 

function adc_reset

Reset ADC to its post-create state.

void adc_reset (
    adc_state_t * state
) 

Clears the sticky clipped flag and re-seeds the xorshift32 PRNG to its initial value so dithered runs are reproducible after reset.

Parameters:

  • state Must be non-NULL.

function adc_set_state

int adc_set_state (
    adc_state_t * state,
    const void * blob
) 

function adc_state_bytes

size_t adc_state_bytes (
    const adc_state_t * state
) 

function adc_step

Process one input sample.

JM_FORCEINLINE  JM_HOT int64_t adc_step (
    adc_state_t * state,
    float x
) 

Multiplies x by the pre-computed double-precision scale, optionally adds TPDF dither, rounds with llround, and clamps to [clip_min, clip_max]. Sets the sticky clipped flag if clamping occurred.

Parameters:

  • state Must be non-NULL.
  • x Normalised float input sample (typically in [-1, +1]).

Returns:

Quantised signed integer in [-(2^(bits-1)), 2^(bits-1)-1].


function adc_steps

Process a block of float samples to int64.

void adc_steps (
    adc_state_t * state,
    const float * input,
    int64_t * output,
    size_t n
) 

When dithering is disabled the float-to-double multiply can use SIMD widening (jm_simd.h); the int64_t conversion and clamp remain scalar. When dithering is enabled the loop is scalar to preserve sequential PRNG state. Accepts an optional pre-allocated output array; allocates a fresh one when output is NULL.

Parameters:

  • state Must be non-NULL.
  • input Input float32 array; must contain at least n elements.
  • output Output int64 array; must contain at least n elements.
  • n Number of samples to process.
>>> from doppler.cvt import ADC
>>> import numpy as np
>>> # ideal 12-bit ADC: full scale spans +-2**11 codes
>>> ADC(12, 0.0, 0).steps(np.array([0.0, 0.5, 0.999, -1.0],
...                                dtype=np.float32)).tolist()
[0, 1024, 2046, -2048]

Macro Definition Documentation

define ADC_STATE_MAGIC

#define ADC_STATE_MAGIC `DP_FOURCC ('A','D','C',' ')`

define ADC_STATE_VERSION

#define ADC_STATE_VERSION `1u`


The documentation for this class was generated from the following file native/inc/adc/adc_core.h