Dither Calibration#
The public interfaces consume aligned observables; probe injection and device
simulation stay with the caller. Use DitherGainTracker for a single-probe,
gain-only stage and DitherHDCTracker for the three-PN, nominal-gain-2 HDC
stage. Their input conventions differ. The class notes below state each
tracker's observability requirements and accuracy trade-offs; theory,
references and complete experiments are in Dither mechanisms.
The HDC tracker runs a per-sample loop. For long captures, install the optional
Numba acceleration with pip install "adctoolbox[accel]".
- class adctoolbox.DitherGainTracker(*, probe_amplitude, initial_gain, backend_bits, gain_bounds, learning_rate=0.08)[源代码]#
基类:
objectBlockwise PN-correlation gain estimate followed by exponential averaging.
The known probe
probe_amplitude * pnmust be injected after the coarse decision and amplified together with the residue. Each block estimates the gain as cov(pn, backend) / (probe_amplitude * var(pn)) and moves the active estimate toward it bylearning_rate. No ideal input, true gain, frequency or foreground label is accepted. A block is held, leaving the estimate unchanged, on any backend rail code (selecting only non-clipped samples can bias the correlation), on insufficient probe excitation, or when its estimate lies outsidegain_bounds. Unknown injection amplitude is inseparable from gain; statistical bias, noise and excitation limits remain architecture-dependent.Use
process()for each contiguous block: it corrects with the active estimate and then updates from that block.apply()andupdate()expose the two steps separately.- 参数:
probe_amplitude (float) -- Known probe amplitude, in the input-referred units of
coarse.initial_gain (float) -- Starting residue gain: the design value or a foreground estimate.
backend_bits (int) -- Backend resolution;
backend_codemust lie in [0, 2**backend_bits).gain_bounds (tuple of float) -- (low, high) range containing
initial_gainand the true gain. Block estimates outside it are held, so too narrow a range stops tracking.learning_rate (float, default 0.08) -- Exponential-averaging weight in (0, 1].
- update(backend, pn, backend_code)[源代码]#
Return gain_next, observed_gain and status; a hold preserves state.
Each call is one averaging window. Changing block size changes the estimator dynamics even for the same total number of samples.
- process(coarse, backend, pn, backend_code, *, learn=True)[源代码]#
Correct one block with the active gain, then learn from that block.
Returns
calibrated_signalandgain_usedfromapply(), plusgain_next,observed_gainandstatusfromupdate().learn=Falsefreezes the estimate, ignoresbackend_codeand reports status"frozen".
- adctoolbox.apply_dither_gain(coarse, backend, pn, *, gain_estimate, probe_amplitude)[源代码]#
Apply q + r/G_est - a*p using a frozen positive gain estimate.
Inputs are aligned 1D observable arrays in consistent voltage/code units.
pnis the normalized known probe; amplitude is in input-referred units. Returnscalibrated_signalandgain_used. The known probe must pass through the residue gain, after the coarse decision. This function only reconstructs the digital output; it does not inject a probe.
- class adctoolbox.DitherHDCTracker(*, fixed=False, window_log2=24, dither_peak=0.2, estimate_memory=True, estimate_dac_mismatch=True, initial_coefficients=None, fraction=24, bits=28, accumulator_bits=None, controller_latency=512)[源代码]#
基类:
objectStreaming three-PN Pipeline HDC in floating or fixed-point arithmetic.
The stage uses signed codes {-1, 0, 1}, nominal gain 2, DAC levels
stage_code/2, and a normalized backend range [-1, 1]. Three independent PN signs injectdither_peak/3 * sum(pn_signs)before the amplifier. This is the model in HDC_FIXED.md: published gain/cubic HDC plus two extensions, a one-tap memory inverse and a two-element DAC mismatch whose roles are swapped according toselection.Each update uses one averaging window only and replaces the active coefficients
controller_latencysamples later; windows are not averaged together, so estimator spread falls only with window length, by about half for every +2 inwindow_log2. On the HDC_FIXED.md model, 2^20-sample windows gave about 51 dB SNDR and 2^24 about 56 dB, close to the limit of the cubic inverse itself; at 2^24 the cubic coefficient error still exceeded 10% for two of three seeds. A 2^24 window lasts 0.17 s at 100 MS/s.selectionmust be a balanced random sign sequence independent of the input, such as an LFSR. With constant tags the mismatch estimate is out of range, so onlydac_mismatchis held (counted inheld_dac_mismatch) while the other coefficients keep learning. A tag mean m over nonzero stage codes biases the mismatch estimate by about -2*m*mean(abs(input)) over those codes. For a stage without role swapping, useestimate_dac_mismatch=False; with a zerodac_mismatchcoefficient,selectionmay then be None.Arbitrary contiguous block partitions give the same result.
learn=Falsefreezes active coefficients, cancels a pending update and discards partial estimation windows, but retains signal history. Callreset()for an independent capture. The estimator keeps the documented HDC moment approximation; a public interface does not remove finite-record bias or expand physical validity. Without the optionalaccelextra (Numba), the per-sample loop runs in pure Python at roughly 10^5 samples per second.- 参数:
fixed (bool, default False) -- Use the bit-accurate fixed-point datapath of HDC_FIXED.md instead of floating arithmetic.
window_log2 (int, default 24) -- log2 of the samples in each estimation window, in [8, 30].
dither_peak (float, default 0.2) -- Peak of the summed probe in stage-input units, in (0, 1). It must match the analog injection.
estimate_memory (bool, default True) -- Learn the memory or DAC-mismatch extension. When False, that coefficient keeps its initial value.
estimate_dac_mismatch (bool, default True) -- Learn the memory or DAC-mismatch extension. When False, that coefficient keeps its initial value.
initial_coefficients (dict, optional) -- Exactly
linear,cubic,memoryanddac_mismatch, default 1, 0, 0, 0. These digital inverse coefficients c1, k3, h, delta are not physical device parameters: for r = backend/2, w = c1*r - k3*(c1*r)**3, v = w - h*v_previous and output = stage_code/2 + v - probe + delta*selection*stage_code/2.fraction (int, default 24 and 28) -- Fixed-point fractional and total word bits. Validated in both modes, but used in arithmetic only when
fixedis True.bits (int, default 24 and 28) -- Fixed-point fractional and total word bits. Validated in both modes, but used in arithmetic only when
fixedis True.accumulator_bits (int, optional) -- Fixed-point correlation accumulator width, default
bits + window_log2.controller_latency (int, default 512) -- Samples from the end of a window to the commit of its coefficients.
- property coefficients#
A detached dict of active digital correction coefficients.
- process(backend, pn_signs, stage_code, selection, backend_rails, *, learn=True)[源代码]#
Correct one contiguous block and optionally learn from its moments.
- 参数:
backend (array_like, shape (N,)) -- Finite normalized backend samples in [-1, 1], not integer codes.
pn_signs (array_like, shape (N, 3)) -- Aligned signs {-1, +1} for the three injected PN streams.
stage_code (array_like, shape (N,)) -- Signed coarse decisions {-1, 0, 1}, before Dither injection.
selection (array_like, shape (N,), or None) -- Observable DAC role-selection tags {-1, +1}, balanced and random (see the class notes). None is allowed only when
estimate_dac_mismatchis False anddac_mismatchis zero.backend_rails (array_like, shape (N,)) -- Boolean rail flags; any flag rejects its entire estimation window.
learn (bool) -- False freezes coefficients while advancing correction history.
- 返回:
calibrated_signalin stage input units; activecoefficientsafter the block;updates(accepted, possibly pending) andheld_updatescumulative counts;held_dac_mismatch, the accepted updates that kept the previousdac_mismatch;pending_updateflag; and cumulativesaturationsfor datapath, accumulator and controller. A block may span coefficient commits; the returned coefficients are not necessarily those used for every sample in that block.- 返回类型: