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 * Mode is gross agc mode: off, slow, med, fast; just info
41 * Hang is basic hang time
42 * Size is max hang time
43 * Over is recover period after TRX switch
44 * Rcov is hang value used during recovery period
45 * BufSize is length of sample buffer
49 newDigitalAgc(int Mode,
60 DIGITALAGC a = (DIGITALAGC) safealloc(1,
61 sizeof(digital_agc_state),
62 "new digital agc state");
63 assert((Ramp >= 2) && (Ramp < BufSize));
70 a->gain.top = MaxGain;
72 a->gain.old = a->gain.now = CurGain;
73 a->buff = newCXB(BufSize, Vec, "agc buffer");
74 memset((void *) a->hist, 0, sizeof(a->hist));
81 delDigitalAgc(DIGITALAGC a) {
89 DigitalAgc(DIGITALAGC a, int tick) {
91 if (a->mode == agcOFF) {
93 for (i = 0; i < CXBsize(a->buff); i++)
94 CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.fix);
99 hang = tick < a->over ? a->rcov : a->hang;
102 for (i = 0; i < CXBsize(a->buff); i++)
103 peak = max(peak, Cmag(CXBdata(a->buff, i)));
107 a->hist[k] = a->gain.lim / peak;
108 for (i = 1, a->gain.now = a->hist[0]; i < hang; i++)
109 a->gain.now = max(a->hist[i], a->gain.now);
111 a->gain.now = min(a->gain.now, a->gain.top);
113 if (a->gain.now != a->gain.old) {
114 REAL step = (a->gain.now - a->gain.old) / (a->ramp - 1);
115 for (i = 0; i < a->ramp; i++)
116 CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.old + i * step);
117 for (; i < CXBsize(a->buff); i++)
118 CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.now);
119 a->gain.old = a->gain.now;
122 for (i = 0; i < CXBsize(a->buff); i++)
123 CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.now);
125 a->indx = ++k % a->size;