Skip to content

AGC — Step Response

AGC convergence

What you're seeing

A 6000-sample complex tone that steps from −10 dBm to +10 dBm at sample 3000. Three curves overlay almost perfectly because all three use the same loop_bw = 0.00125; only the decimation factor changes how often the loop ticks.

  • decim=1 — loop updates every sample; fastest per-sample cost.
  • decim=8 — loop updates every 8 samples; ×8 cheaper, identical trajectory.
  • decim=32 — coarsest timing; still converges within ~350 samples of the 20 dB step.

The gain trace is output power in dBFS. All three curves converge to 0 dBFS before the step and recover to 0 dBFS within ~350 samples after it.

How it works

agc_steps() rescales the loop coefficients by decim so that loop_bw keeps its per-sample meaning regardless of how coarsely the detector ticks.

from doppler.agc import AGC
import numpy as np

n = np.arange(6000)
amp = np.where(n < 3000, 10**(-10/20), 10**(10/20))
x = (amp * np.exp(2j * np.pi * 0.02 * n)).astype(np.complex64)

agc = AGC(ref_db=0.0, loop_bw=0.00125, alpha=0.02)
agc.decim = 8          # update loop every 8 samples
y = agc.steps(x)       # normalised output, power → 0 dBm

alpha controls the exponential moving-average window for the power detector; loop_bw sets the first-order loop bandwidth. Wider loop_bw → faster tracking but more noise at steady state.

python examples/python/agc_demo.py   # → agc_convergence.png

See AGC API walkthrough for the full parameter reference and decimated-loop derivation.