]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/digitalagc.c
352ebb2a6914b3d05e70a592a534aae99b9bf27c
[dttsp.git] / jDttSP / digitalagc.c
1 /* digitalagc.c
2
3 This file is part of a program that implements a Software-Defined Radio.
4
5 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
6
7 We appreciate the contributions to this subroutine by Gerald Youngblood,
8 AC5OG and Phil Harman, VK6APH.
9
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.
14
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.
19
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
23
24 The authors can be reached by email at
25
26 ab2kt@arrl.net
27 or
28 rwmcgwier@comcast.net
29
30 or by paper mail at
31
32 The DTTS Microwave Society
33 6 Kathleen Place
34 Bridgewater, NJ 08807
35 */
36
37 #include <common.h>
38
39 /*
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
46  */
47
48 DIGITALAGC
49 newDigitalAgc(int Mode,
50               int Hang,
51               int Size,
52               int Over,
53               int Rcov,
54               int Ramp,
55               int BufSize,
56               REAL MaxGain,
57               REAL Limit,
58               REAL CurGain,
59               COMPLEX *Vec) {
60   DIGITALAGC a = (DIGITALAGC) safealloc(1,
61                                         sizeof(digital_agc_state),
62                                         "new digital agc state");
63   assert((Ramp >= 2) && (Ramp < BufSize));
64   a->mode = Mode;
65   a->hang = Hang;
66   a->size = Size;
67   a->over = Over;
68   a->rcov = Rcov;
69   a->ramp = Ramp;
70   a->gain.top = MaxGain;
71   a->gain.lim = Limit;
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));
75   a->indx = 0;
76   a->gain.fix = 1000.0;
77   return a;
78 }
79
80 void
81 delDigitalAgc(DIGITALAGC a) {
82   if (a) {
83     delCXB(a->buff);
84     safefree((void *) a);
85   }
86 }
87
88 void
89 DigitalAgc(DIGITALAGC a, int tick) {
90   
91   if (a->mode == agcOFF) {
92     int i;
93     for (i = 0; i < CXBsize(a->buff); i++)
94       CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.fix);
95     
96   } else {
97     int i,
98         k = a->indx,
99         hang = tick < a->over ? a->rcov : a->hang;
100     REAL peak = 0.0;
101     
102     for (i = 0; i < CXBsize(a->buff); i++)
103       peak = max(peak, Cmag(CXBdata(a->buff, i)));
104     
105     if (peak != 0) {
106       a->size = hang;
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);
110     }
111     a->gain.now = min(a->gain.now, a->gain.top);
112     
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;
120       
121     } else
122       for (i = 0; i < CXBsize(a->buff); i++)
123         CXBdata(a->buff, i) = Cscl(CXBdata(a->buff, i), a->gain.now);
124     
125     a->indx = ++k % a->size;
126   }
127 }