Ulf@538
|
1 #include "AGC.h"
|
pfh1976@554
|
2 #include <cmath>
|
pfh1976@554
|
3 #include <stdlib.h>
|
pfh1976@554
|
4 #include <stdio.h>
|
Ulf@538
|
5
|
Ulf@586
|
6 AGC_parameters::AGC_parameters():
|
Ulf@586
|
7 n_stages_(4),
|
Ulf@586
|
8 time_constants_({0.002*1, 0.002*4, 0.002*16, 0.002*64}),
|
Ulf@586
|
9 agc_stage_gain_(2),
|
Ulf@586
|
10 decimation_({8, 2, 2, 2}),
|
Ulf@586
|
11 agc1_scales_({1.0, 1.4, 2.0, 2.8}),
|
Ulf@586
|
12 agc2_scales_({1.6, 2.25, 3.2, 4.5}),
|
Ulf@586
|
13 detect_scale_(0.25),
|
Ulf@586
|
14 agc_mix_coeff_(0.5)
|
Ulf@586
|
15 {
|
Ulf@586
|
16 // do nothing more
|
Ulf@586
|
17 }
|
Ulf@586
|
18
|
Ulf@564
|
19 AGC_coefficients::AGC_coefficients(AGC_parameters* AGC_params_p,
|
Ulf@545
|
20 float fs, int n_ch){
|
pfh1976@554
|
21 float decim = 1.0;
|
pfh1976@554
|
22 float total_DC_gain = 0.0;
|
pfh1976@554
|
23 float tau, ntimes, delay, spread_sq, u, p, dp;
|
pfh1976@554
|
24 int n_taps = 0, n_iterations = 1;
|
Ulf@557
|
25
|
pfh1976@554
|
26 n_ch_ = n_ch;
|
Ulf@564
|
27 n_agc_stages_ = AGC_params_p->n_stages_;
|
Ulf@564
|
28 agc_stage_gain_ = AGC_params_p->agc_stage_gain_;
|
pfh1976@554
|
29
|
pfh1976@554
|
30 // FloatArray initialization using assign method - dont know if this is good enough
|
pfh1976@554
|
31 agc_epsilon_.assign(n_agc_stages_, 0.0); //the 1/(tau*fs) roughly
|
pfh1976@554
|
32 agc_polez1_ = agc_epsilon_;
|
pfh1976@554
|
33 agc_polez2_ = agc_epsilon_;
|
pfh1976@554
|
34 agc_spatial_iterations_ = agc_epsilon_;
|
pfh1976@554
|
35 agc_spatial_n_taps_ = agc_epsilon_;
|
pfh1976@554
|
36 agc_mix_coeffs_ = agc_epsilon_;
|
Ulf@564
|
37 FloatArray agc1_scales = AGC_params_p->agc1_scales_;
|
Ulf@564
|
38 FloatArray agc2_scales = AGC_params_p->agc2_scales_;
|
pfh1976@554
|
39 FloatArray agc_spatial_FIR;
|
Ulf@564
|
40 decimation_ = AGC_params_p->decimation_;
|
pfh1976@554
|
41
|
pfh1976@554
|
42 for(int stage=0; stage < n_agc_stages_; stage++){
|
Ulf@564
|
43 tau = AGC_params_p->time_constants_[stage];
|
Ulf@564
|
44 decim *= AGC_params_p->decimation_[stage];
|
pfh1976@554
|
45 agc_epsilon_[stage] = 1.0 - exp(-decim/(tau*fs));
|
pfh1976@554
|
46 ntimes = tau * (fs/decim);
|
pfh1976@554
|
47 delay = (agc2_scales[stage]-agc1_scales[stage])/ntimes;
|
pfh1976@554
|
48 spread_sq = (agc1_scales[stage]*agc1_scales[stage] + agc2_scales[stage]*agc2_scales[stage])/ntimes;
|
pfh1976@554
|
49
|
pfh1976@554
|
50 u = 1.0 + 1.0/spread_sq;
|
pfh1976@554
|
51 p = u - sqrt(u*u-1);
|
pfh1976@554
|
52 dp = delay*(1 - 2*p + p*p)*0.5;
|
pfh1976@554
|
53 agc_polez1_[stage] = p - dp;
|
pfh1976@554
|
54 agc_polez2_[stage] = p + dp;
|
Ulf@557
|
55
|
Ulf@557
|
56 agc_spatial_FIR = Build_FIR_coeffs(spread_sq, delay, &n_iterations, &n_taps);
|
Ulf@557
|
57
|
pfh1976@554
|
58 agc_spatial_iterations_[stage] = (float) n_iterations;
|
pfh1976@554
|
59 agc_spatial_n_taps_[stage] = (float) n_taps;
|
pfh1976@554
|
60 agc_spatial_fir_.push_back(FloatArray());
|
pfh1976@554
|
61
|
pfh1976@554
|
62 for(int i =0; i < 3; i++)
|
pfh1976@554
|
63 agc_spatial_fir_[stage].push_back(agc_spatial_FIR[i]);
|
pfh1976@554
|
64
|
Ulf@564
|
65 total_DC_gain += pow(AGC_params_p->agc_stage_gain_,stage);
|
pfh1976@554
|
66
|
pfh1976@554
|
67 if(stage == 0)
|
pfh1976@554
|
68 agc_mix_coeffs_[stage] = 0.0;
|
pfh1976@554
|
69 else
|
Ulf@564
|
70 agc_mix_coeffs_[stage] = AGC_params_p->agc_mix_coeff_/(tau * (fs/decim));
|
pfh1976@554
|
71 }
|
pfh1976@554
|
72 agc_gain_ = total_DC_gain;
|
Ulf@564
|
73 detect_scale_ = AGC_params_p->detect_scale_/total_DC_gain;
|
Ulf@538
|
74 }
|
pfh1976@554
|
75
|
Ulf@557
|
76 FloatArray AGC_coefficients::Build_FIR_coeffs(float var, float mn, int* ptr_iters, int* ptr_taps){
|
pfh1976@554
|
77 float a, b;
|
pfh1976@554
|
78 FloatArray FIR(3);
|
Ulf@557
|
79
|
Ulf@557
|
80 // Try with 3 FIR taps
|
Ulf@557
|
81 a = (var + mn*mn - mn)/2;
|
Ulf@557
|
82 b = (var + mn*mn + mn)/2;
|
Ulf@557
|
83 FIR[0] = a;
|
Ulf@557
|
84 FIR[1] = 1.0 - a - b;
|
Ulf@557
|
85 FIR[2] = b;
|
Ulf@557
|
86
|
Ulf@557
|
87 if(FIR[1] >= 0.2){
|
Ulf@557
|
88 *ptr_taps = 3;
|
Ulf@557
|
89 return FIR;
|
pfh1976@554
|
90 }
|
Ulf@557
|
91 else //Try with 5 FIR taps
|
Ulf@557
|
92 {
|
Ulf@557
|
93 for(int n_iter = 1; n_iter<16; n_iter++){
|
Ulf@557
|
94 mn /= n_iter;
|
Ulf@557
|
95 var /= n_iter;
|
Ulf@557
|
96
|
Ulf@557
|
97 a = ((var + mn*mn)*2/5 - mn*2/3)/2;
|
Ulf@557
|
98 b = ((var + mn*mn)*2/5 + mn*2/3)/2;
|
Ulf@557
|
99 FIR[0] = a/2;
|
Ulf@557
|
100 FIR[1] = 1.0 - a - b;
|
Ulf@557
|
101 FIR[2] = b;
|
Ulf@557
|
102
|
Ulf@557
|
103 *ptr_iters = n_iter;
|
Ulf@557
|
104
|
Ulf@557
|
105 if(FIR[1] >= 0.1){
|
Ulf@557
|
106 *ptr_taps = 5;
|
Ulf@557
|
107 return FIR;
|
Ulf@557
|
108 }
|
Ulf@557
|
109 }
|
Ulf@557
|
110 //TODO: discuss how we handle errors
|
Ulf@557
|
111 printf("Too many iterations in FIR_coeffs\n");
|
Ulf@557
|
112 FIR = {0, 0, 0};
|
Ulf@557
|
113 return FIR;
|
Ulf@557
|
114 }
|
pfh1976@554
|
115 }
|