Cutoff frequency variable LPF and HPF by IIR 6th-order Butterworth filter for ST Nucleo F401RE.
Dependencies: UITDSP_ADDA UIT_ACM1602NI UIT_AQM1602 UIT_IIR_Filter mbed
BilinearDesignLpfHpf/BilinearDesignLH.cpp@0:33908268d9ea, 2015-09-11 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Fri Sep 11 09:54:45 2015 +0000
- Revision:
- 0:33908268d9ea
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:33908268d9ea | 1 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:33908268d9ea | 2 | // Design of Butterworth LPF and HPF using bilinear transform |
MikamiUitOpen | 0:33908268d9ea | 3 | // |
MikamiUitOpen | 0:33908268d9ea | 4 | // 2014/06/29, Copyright (c) 2014 MIKAMI, Naoki |
MikamiUitOpen | 0:33908268d9ea | 5 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:33908268d9ea | 6 | |
MikamiUitOpen | 0:33908268d9ea | 7 | #include "BilinearDesignLH.hpp" |
MikamiUitOpen | 0:33908268d9ea | 8 | |
MikamiUitOpen | 0:33908268d9ea | 9 | namespace Mikami |
MikamiUitOpen | 0:33908268d9ea | 10 | { |
MikamiUitOpen | 0:33908268d9ea | 11 | // Execute design |
MikamiUitOpen | 0:33908268d9ea | 12 | // input |
MikamiUitOpen | 0:33908268d9ea | 13 | // fc: Cutoff frequency |
MikamiUitOpen | 0:33908268d9ea | 14 | // output |
MikamiUitOpen | 0:33908268d9ea | 15 | // c : Coefficients for cascade structure |
MikamiUitOpen | 0:33908268d9ea | 16 | // g : Gain factor for cascade structure |
MikamiUitOpen | 0:33908268d9ea | 17 | void BilinearDesign::Execute(float fc, Coefs c[], float& g) |
MikamiUitOpen | 0:33908268d9ea | 18 | { |
MikamiUitOpen | 0:33908268d9ea | 19 | Butterworth(); |
MikamiUitOpen | 0:33908268d9ea | 20 | Bilinear(fc); |
MikamiUitOpen | 0:33908268d9ea | 21 | ToCascade(); |
MikamiUitOpen | 0:33908268d9ea | 22 | GetGain(); |
MikamiUitOpen | 0:33908268d9ea | 23 | GetCoefs(c, g); |
MikamiUitOpen | 0:33908268d9ea | 24 | } |
MikamiUitOpen | 0:33908268d9ea | 25 | |
MikamiUitOpen | 0:33908268d9ea | 26 | // Get poles for Butterworth characteristics |
MikamiUitOpen | 0:33908268d9ea | 27 | void BilinearDesign::Butterworth() |
MikamiUitOpen | 0:33908268d9ea | 28 | { |
MikamiUitOpen | 0:33908268d9ea | 29 | float pi_2order = PI_/(2.0f*ORDER_); |
MikamiUitOpen | 0:33908268d9ea | 30 | for (int j=0; j<ORDER_/2; j++) // Pole with imaginary part >= 0 |
MikamiUitOpen | 0:33908268d9ea | 31 | { |
MikamiUitOpen | 0:33908268d9ea | 32 | float theta = (2.0f*j + 1.0f)*pi_2order; |
MikamiUitOpen | 0:33908268d9ea | 33 | sP_[j] = Complex(-cosf(theta), sinf(theta)); |
MikamiUitOpen | 0:33908268d9ea | 34 | } |
MikamiUitOpen | 0:33908268d9ea | 35 | } |
MikamiUitOpen | 0:33908268d9ea | 36 | |
MikamiUitOpen | 0:33908268d9ea | 37 | // Bilinear transform |
MikamiUitOpen | 0:33908268d9ea | 38 | // fc: Cutoff frequency |
MikamiUitOpen | 0:33908268d9ea | 39 | void BilinearDesign::Bilinear(float fc) |
MikamiUitOpen | 0:33908268d9ea | 40 | { |
MikamiUitOpen | 0:33908268d9ea | 41 | float wc = tanf(fc*PI_FS_); |
MikamiUitOpen | 0:33908268d9ea | 42 | for (int k=0; k<ORDER_/2; k++) |
MikamiUitOpen | 0:33908268d9ea | 43 | zP_[k] = (1.0f + wc*sP_[k])/(1.0f - wc*sP_[k]); |
MikamiUitOpen | 0:33908268d9ea | 44 | } |
MikamiUitOpen | 0:33908268d9ea | 45 | |
MikamiUitOpen | 0:33908268d9ea | 46 | // Convert to coefficients for cascade structure |
MikamiUitOpen | 0:33908268d9ea | 47 | void BilinearDesign::ToCascade() |
MikamiUitOpen | 0:33908268d9ea | 48 | { |
MikamiUitOpen | 0:33908268d9ea | 49 | for (int j=0; j<ORDER_/2; j++) |
MikamiUitOpen | 0:33908268d9ea | 50 | { |
MikamiUitOpen | 0:33908268d9ea | 51 | ck_[j].a1 = 2.0f*real(zP_[j]); // a1m |
MikamiUitOpen | 0:33908268d9ea | 52 | ck_[j].a2 = -norm(zP_[j]); // a2m |
MikamiUitOpen | 0:33908268d9ea | 53 | ck_[j].b1 = (PB_ == LPF) ? 2.0f : -2.0f; // b1m |
MikamiUitOpen | 0:33908268d9ea | 54 | } |
MikamiUitOpen | 0:33908268d9ea | 55 | } |
MikamiUitOpen | 0:33908268d9ea | 56 | |
MikamiUitOpen | 0:33908268d9ea | 57 | // Calculate gain factor |
MikamiUitOpen | 0:33908268d9ea | 58 | void BilinearDesign::GetGain(){ |
MikamiUitOpen | 0:33908268d9ea | 59 | float u = (PB_ == LPF) ? 1.0f : -1.0f; |
MikamiUitOpen | 0:33908268d9ea | 60 | float g0 = 1.0f; |
MikamiUitOpen | 0:33908268d9ea | 61 | for (int k=0; k<ORDER_/2; k++) |
MikamiUitOpen | 0:33908268d9ea | 62 | g0 = g0*(1.0f - (ck_[k].a1 + ck_[k].a2*u)*u)/ |
MikamiUitOpen | 0:33908268d9ea | 63 | (1.0f + (ck_[k].b1 + u)*u); |
MikamiUitOpen | 0:33908268d9ea | 64 | gain_ = g0; |
MikamiUitOpen | 0:33908268d9ea | 65 | } |
MikamiUitOpen | 0:33908268d9ea | 66 | |
MikamiUitOpen | 0:33908268d9ea | 67 | // Get coefficients |
MikamiUitOpen | 0:33908268d9ea | 68 | void BilinearDesign::GetCoefs(Coefs c[], float& gain) |
MikamiUitOpen | 0:33908268d9ea | 69 | { |
MikamiUitOpen | 0:33908268d9ea | 70 | for (int k=0; k<ORDER_/2; k++) |
MikamiUitOpen | 0:33908268d9ea | 71 | { |
MikamiUitOpen | 0:33908268d9ea | 72 | c[k].a1 = ck_[k].a1; |
MikamiUitOpen | 0:33908268d9ea | 73 | c[k].a2 = ck_[k].a2; |
MikamiUitOpen | 0:33908268d9ea | 74 | c[k].b1 = ck_[k].b1; |
MikamiUitOpen | 0:33908268d9ea | 75 | } |
MikamiUitOpen | 0:33908268d9ea | 76 | gain = gain_; |
MikamiUitOpen | 0:33908268d9ea | 77 | } |
MikamiUitOpen | 0:33908268d9ea | 78 | } |
MikamiUitOpen | 0:33908268d9ea | 79 | |
MikamiUitOpen | 0:33908268d9ea | 80 | |
MikamiUitOpen | 0:33908268d9ea | 81 |