3 This file is part of a program that implements a Software-Defined Radio.
5 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
7 We appreciate the contributions to this subroutine by Gerald Youngblood,
8 AC5OG and Phil Harman, VK6APH.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 The authors can be reached by email at
32 The DTTS Microwave Society
40 DigitalAgc(DIGITALAGC a, int tick) {
42 if (a->mode == agcOFF) {
44 for (i = 0; i < CXBsize(a->buff); i++)
45 CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.fix);
51 hang = tick < a->over ? a->rcov : a->hang;
54 for (i = 0; i < CXBsize(a->buff); i++)
55 peak = max(peak, Cmag(CXBdata(a->buff, i)));
58 a->hist[a->indx] = a->gain.lim / peak;
59 for (i = 1, a->gain.now = a->hist[0]; i < hang; i++)
60 a->gain.now = min(a->hist[i], a->gain.now);
62 a->gain.raw = a->gain.now;
63 a->gain.now = min(a->gain.now, a->gain.top);
65 for (i = 0, k = (a->sndx + a->ramp) % a->mask;
67 i++, k = (k + 1) % a->mask)
68 a->circ[k] = CXBdata(a->buff, i);
70 if (a->gain.now != a->gain.old) {
71 REAL step = (a->gain.now - a->gain.old) / a->ramp;
72 for (i = 0, k = a->sndx;
74 i++, k = (k + 1) % a->mask)
75 CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.old + i * step);
76 for (; i < CXBsize(a->buff); i++, k = (k + 1) % a->mask)
77 CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.now);
78 a->gain.old = a->gain.now;
81 for (i = 0, k = a->sndx;
83 i++, k = (k + 1) % a->mask)
84 CXBdata(a->buff, i) = Cscl(a->circ[k], a->gain.now);
87 a->sndx = (a->sndx + CXBsize(a->buff)) % a->mask;
88 a->indx = ((a->indx + 1) % hang);
93 * Mode is gross agc mode: off, slow, med, fast; just info
94 * Hang is basic hang time
95 * Size is max hang time
96 * Over is recover period after TRX switch
97 * Rcov is hang value used during recovery period
98 * BufSize is length of sample buffer
102 newDigitalAgc(int Mode,
108 REAL MaxGain, REAL Limit, REAL CurGain, COMPLEX * Vec) {
109 DIGITALAGC a = (DIGITALAGC) safealloc(1,
110 sizeof(digital_agc_state),
111 "new digital agc state");
112 assert((Ramp >= 2) && (Ramp < BufSize));
118 a->gain.top = MaxGain;
120 a->gain.old = a->gain.now = CurGain;
121 a->buff = newCXB(BufSize, Vec, "agc buffer");
122 a->mask = 2 * CXBsize(a->buff);
123 a->circ = newvec_COMPLEX(2 * BufSize, "circular agc buffer");
124 memset((void *) a->hist, 0, sizeof(a->hist));
126 a->sndx = a->mask - Ramp;
132 delDigitalAgc(DIGITALAGC a) {
135 delvec_COMPLEX(a->circ);
136 safefree((void *) a);