-
Notifications
You must be signed in to change notification settings - Fork 214
/
Copy pathqf_blinch.cpp
146 lines (112 loc) · 3.83 KB
/
qf_blinch.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "qf_common.h"
#include "qf_poly.h"
#include "qf_comp.h"
#include "qf_capacity.h"
#include "qf_filter.h"
#include "qf_blinch.h"
/* BLINCHIKOFF BANDPASS FILTERS
These filters are the equivalent of Bessel filters but for bandpass
response: they have a nearly flat delay in the passband (in the sense
of least squares minimization).
Ref: H. Blinchikoff, M. Savetman: Least-Squares Approximation to
Wide-Band Constant Delay. IEEE ...
*/
// Some restrictions apply to Blinchikoff : order = 2 or 4 and fractional
// bandwidth is limited by the published tables
bool blval (qf_spec *Pspec) {
Pspec -> th = Pspec -> bw / Pspec -> fc; // Compute fractional bdwth
switch (Pspec -> ord) {
case 2:
if ((Pspec -> th < 0.1) || (Pspec -> th > 0.9)) return false;
return true;
case 4:
if ((Pspec -> th < 0.3) || (Pspec -> th > 0.7)) return false;
return true;
}
// Avoids a warning
return false;
}
// Linear interpolation functions to extrapolate coeffs.
inline qf_double_t qf_blinch::interp2 (qf_double_t x, unsigned i) {
if (x == 0) return blc_o2 [i];
else return blc_o2 [i] + 10 * x * (blc_o2 [i + 5] - blc_o2 [i]);
}
inline qf_double_t qf_blinch::interp4 (qf_double_t x, unsigned i) {
if (x == 0) return blc_o4 [i];
else return blc_o4 [i] + 10 * x * (blc_o4 [i + 9] - blc_o4 [i]);
}
// Direct synthesis out of the published tables
qf_blinch::qf_blinch (qf_spec *P) : qf_filter (P) {
unsigned idx;
qf_double_t val;
Pspec -> th = Pspec -> bw / Pspec -> fc; // Compute fractional bdwth
qf_double_t offset = (Pspec -> th) - floor (Pspec -> th * 10) / 10;
qf_double_t dnrml = Pspec -> r1 / Pspec -> fc;
qf_double_t dnrmc = 1 / (Pspec -> r1 * Pspec -> fc);
switch (Pspec -> ord) {
case 2: // Filter of order 2. Minimum inductor type
idx = 5 * static_cast <unsigned> (floor ((Pspec -> th - 0.1) * 10));
// Serial L
val = interp2 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, false, false));
idx ++;
// Serial C
val = interp2 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, false, false));
idx ++;
// Parallel C
val = interp2 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, true, true));
idx ++;
// Serial C
val = interp2 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, false, false));
idx ++;
// Serial L
val = interp2 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, false, false));
idx ++;
lcmp. insert (new qf_end ());
return ;
case 4:
idx = 9 * static_cast <unsigned> (floor ((Pspec -> th - 0.3) * 10));
// Serial L
val = interp4 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, false, false));
idx ++;
// Serial C
val = interp4 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, false, false));
idx ++;
// Parallel C
val = interp4 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, true, true));
idx ++;
// Serial L
val = interp4 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, false, false));
idx++ ;
// Serial C
val = interp4 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, false, false));
idx ++;
// Parallel L
val = interp4 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, true, true));
idx ++;
// Parallel C
val = interp4 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, true, true));
idx ++;
// Serial L
val = interp4 (offset, idx);
lcmp. insert (new qf_ind (val * dnrml, false, false));
idx++ ;
// Parallel C
val = interp4 (offset, idx);
lcmp. insert (new qf_cap (val * dnrmc, true, true));
idx ++;
lcmp. insert (new qf_end ());
return;
}
}