-
Notifications
You must be signed in to change notification settings - Fork 7
/
fir.cpp
133 lines (119 loc) · 3.56 KB
/
fir.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
#include <Audio.h>
#include <arm_math.h>
#include <arm_const_structs.h>
#include "LMS_NR.h"
#undef PI
#undef HALF_PI
#undef TWO_PI
#define PI 3.1415926535897932384626433832795f
#define HALF_PI 1.5707963267948966192313216916398f
#define TWO_PI 6.283185307179586476925286766559f
#define TPI TWO_PI
#define PIH HALF_PI
#define FOURPI (2.0f * TPI)
#define SIXPI (3.0f * TPI)
float32_t Izero (float32_t x)
{
float32_t x2 = x / 2.0;
float32_t summe = 1.0;
float32_t ds = 1.0;
float32_t di = 1.0;
float32_t errorlimit = 1e-9;
float32_t tmp;
do
{
tmp = x2 / di;
tmp *= tmp;
ds *= tmp;
summe += ds;
di += 1.0;
} while (ds >= errorlimit * summe);
return (summe);
} // END Izero
float m_sinc(int m, float fc)
{ // fc is f_cut/(Fsamp/2)
// m is between -M and M step 2
//
float x = m * PIH;
if (m == 0)
return 1.0f;
else
return sinf(x * fc) / (fc * x);
}
void calc_FIR_coeffs (float * coeffs_I, int numCoeffs, float32_t fc, float32_t Astop, int type, float dfc, float Fsamprate)
// pointer to coefficients variable, no. of coefficients to calculate, frequency where it happens, stopband attenuation in dB,
// filter type, half-filter bandwidth (only for bandpass and notch)
{ // modified by WMXZ and DD4WH after
// Wheatley, M. (2011): CuteSDR Technical Manual. www.metronix.com, pages 118 - 120, FIR with Kaiser-Bessel Window
// assess required number of coefficients by
// numCoeffs = (Astop - 8.0) / (2.285 * TPI * normFtrans);
// selecting high-pass, numCoeffs is forced to an even number for better frequency response
float32_t Beta;
float32_t izb;
float fcf = fc;
int nc = numCoeffs;
fc = fc / Fsamprate;
dfc = dfc / Fsamprate;
// calculate Kaiser-Bessel window shape factor beta from stop-band attenuation
if (Astop < 20.96)
Beta = 0.0;
else if (Astop >= 50.0)
Beta = 0.1102 * (Astop - 8.71);
else
Beta = 0.5842 * powf((Astop - 20.96), 0.4) + 0.07886 * (Astop - 20.96);
for (int i = 0; i < numCoeffs; i++) //zero pad entire coefficient buffer, important for variables from DMAMEM
{
coeffs_I[i] = 0.0;
}
izb = Izero (Beta);
if (type == 0) // low pass filter
// { fcf = fc;
{ fcf = fc * 2.0;
nc = numCoeffs;
}
else if (type == 1) // high-pass filter
{ fcf = -fc;
nc = 2 * (numCoeffs / 2);
}
else if ((type == 2) || (type == 3)) // band-pass filter
{
fcf = dfc;
nc = 2 * (numCoeffs / 2); // maybe not needed
}
else if (type == 4) // Hilbert transform
{
nc = 2 * (numCoeffs / 2);
// clear coefficients
for (int ii = 0; ii < 2 * (nc - 1); ii++) coeffs_I[ii] = 0;
// set real delay
coeffs_I[nc] = 1;
// set imaginary Hilbert coefficients
for (int ii = 1; ii < (nc + 1); ii += 2)
{
if (2 * ii == nc) continue;
float x = (float)(2 * ii - nc) / (float)nc;
float w = Izero(Beta * sqrtf(1.0f - x * x)) / izb; // Kaiser window
coeffs_I[2 * ii + 1] = 1.0f / (PIH * (float)(ii - nc / 2)) * w ;
}
return;
}
for (int ii = - nc, jj = 0; ii < nc; ii += 2, jj++)
{
float x = (float)ii / (float)nc;
float w = Izero(Beta * sqrtf(1.0f - x * x)) / izb; // Kaiser window
coeffs_I[jj] = fcf * m_sinc(ii, fcf) * w;
}
if (type == 1)
{
coeffs_I[nc / 2] += 1;
}
else if (type == 2)
{
for (int jj = 0; jj < nc + 1; jj++) coeffs_I[jj] *= 2.0f * cosf(PIH * (2 * jj - nc) * fc);
}
else if (type == 3)
{
for (int jj = 0; jj < nc + 1; jj++) coeffs_I[jj] *= -2.0f * cosf(PIH * (2 * jj - nc) * fc);
coeffs_I[nc / 2] += 1;
}
} // END calc_FIR_coeffs