#include <common.h>
+void
+DigitalAgc(DIGITALAGC a, int tick) {
+
+ if (a->mode == agcOFF) {
+ int i;
+ for (i = 0; i < CXBsize(a->buff); i++)
+ CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.fix);
+
+ } else {
+ int i, k, hang;
+ REAL peak = 0.0;
+
+ hang = tick < a->over ? a->rcov : a->hang;
+ k = a->indx;
+
+ for (i = 0; i < CXBsize(a->buff); i++)
+ peak = max(peak, Cmag(CXBdata(a->buff, i)));
+
+ if (peak != 0) {
+ a->hist[a->indx] = a->gain.lim / peak;
+ for (i = 1, a->gain.now = a->hist[0]; i < hang; i++)
+ a->gain.now = min(a->hist[i], a->gain.now);
+ }
+ a->gain.raw = a->gain.now;
+ a->gain.now = min(a->gain.now, a->gain.top);
+
+ for (i = 0, k = (a->sndx + a->ramp) % a->mask;
+ i < CXBsize(a->buff);
+ i++, k = (k + 1) % a->mask)
+ a->circ[k] = CXBdata(a->buff, i);
+
+ if (a->gain.now != a->gain.old) {
+ REAL step = (a->gain.now - a->gain.old) / a->ramp;
+ for (i = 0, k = a->sndx;
+ i < a->ramp;
+ i++, k = (k + 1) % a->mask)
+ CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.old + i * step);
+ for (; i < CXBsize(a->buff); i++, k = (k + 1) % a->mask)
+ CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.now);
+ a->gain.old = a->gain.now;
+
+ } else {
+ for (i = 0, k = a->sndx;
+ i < CXBsize(a->buff);
+ i++, k = (k + 1) % a->mask)
+ CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.now);
+ }
+
+ a->sndx = (a->sndx + CXBsize(a->buff)) % a->mask;
+ a->indx = ((a->indx + 1) % hang);
+ }
+}
+
/*
* Mode is gross agc mode: off, slow, med, fast; just info
* Hang is basic hang time
DIGITALAGC
newDigitalAgc(int Mode,
int Hang,
- int Size,
+ int Ramp,
int Over,
int Rcov,
- int Ramp,
int BufSize,
- REAL MaxGain,
- REAL Limit,
- REAL CurGain,
- COMPLEX *Vec) {
+ REAL MaxGain, REAL Limit, REAL CurGain, COMPLEX * Vec) {
DIGITALAGC a = (DIGITALAGC) safealloc(1,
sizeof(digital_agc_state),
"new digital agc state");
assert((Ramp >= 2) && (Ramp < BufSize));
a->mode = Mode;
a->hang = Hang;
- a->size = Size;
a->over = Over;
a->rcov = Rcov;
a->ramp = Ramp;
a->gain.lim = Limit;
a->gain.old = a->gain.now = CurGain;
a->buff = newCXB(BufSize, Vec, "agc buffer");
+ a->mask = 2 * CXBsize(a->buff);
+ a->circ = newvec_COMPLEX(2 * BufSize, "circular agc buffer");
memset((void *) a->hist, 0, sizeof(a->hist));
a->indx = 0;
- a->gain.fix = 1000.0;
+ a->sndx = a->mask - Ramp;
+ a->gain.fix = 10.0;
return a;
}
delDigitalAgc(DIGITALAGC a) {
if (a) {
delCXB(a->buff);
+ delvec_COMPLEX(a->circ);
safefree((void *) a);
}
}
-
-void
-DigitalAgc(DIGITALAGC a, int tick) {
-
- if (a->mode == agcOFF) {
- int i;
- for (i = 0; i < CXBsize(a->buff); i++)
- CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.fix);
-
- } else {
- int i,
- k = a->indx,
- hang = tick < a->over ? a->rcov : a->hang;
- REAL peak = 0.0;
-
- for (i = 0; i < CXBsize(a->buff); i++)
- peak = max(peak, Cmag(CXBdata(a->buff, i)));
-
- if (peak != 0) {
- a->size = hang;
- a->hist[k] = a->gain.lim / peak;
- for (i = 1, a->gain.now = a->hist[0]; i < hang; i++)
- a->gain.now = max(a->hist[i], a->gain.now);
- }
- a->gain.now = min(a->gain.now, a->gain.top);
-
- if (a->gain.now != a->gain.old) {
- REAL step = (a->gain.now - a->gain.old) / (a->ramp - 1);
- for (i = 0; i < a->ramp; i++)
- CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.old + i * step);
- for (; i < CXBsize(a->buff); i++)
- CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.now);
- a->gain.old = a->gain.now;
-
- } else
- for (i = 0; i < CXBsize(a->buff); i++)
- CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.now);
-
- a->indx = ++k % a->size;
- }
-}