Cutoff frequency variable LPF by 160th-order FIR filter designed by window method usin Hamming window for ST Nucleo F401RE.

Dependencies:   UIT_ACM1602NI UIT_ADDA mbed

Committer:
MikamiUitOpen
Date:
Mon Nov 10 02:45:18 2014 +0000
Revision:
0:b8bffbcb85fd
Child:
1:24c33c8719b2
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:b8bffbcb85fd 1 //------------------------------------------------------------------
MikamiUitOpen 0:b8bffbcb85fd 2 // Cutoff frequency variable LPF and HPF by FIR 160th-order filter
MikamiUitOpen 0:b8bffbcb85fd 3 // A0: Signal to be filtered
MikamiUitOpen 0:b8bffbcb85fd 4 // A2: Value which controls cutoff frequency
MikamiUitOpen 0:b8bffbcb85fd 5 //
MikamiUitOpen 0:b8bffbcb85fd 6 // 2014/11/10, Copyright (c) 2014 MIKAMI, Naoki
MikamiUitOpen 0:b8bffbcb85fd 7 //------------------------------------------------------------------
MikamiUitOpen 0:b8bffbcb85fd 8
MikamiUitOpen 0:b8bffbcb85fd 9 #include "mbed.h"
MikamiUitOpen 0:b8bffbcb85fd 10
MikamiUitOpen 0:b8bffbcb85fd 11 #include "ADC_Interrupt.hpp" // for ADC using interrupt
MikamiUitOpen 0:b8bffbcb85fd 12 #include "DAC_MCP4922.hpp" // for DAC MCP4922
MikamiUitOpen 0:b8bffbcb85fd 13 #include "ScfClockTim3.hpp" // for clock supplied to SCF
MikamiUitOpen 0:b8bffbcb85fd 14 #include "ACM1602NI.hpp" // for LCD display
MikamiUitOpen 0:b8bffbcb85fd 15
MikamiUitOpen 0:b8bffbcb85fd 16 #include "WindowingDesignLH.hpp" // for design of IIR filter
MikamiUitOpen 0:b8bffbcb85fd 17
MikamiUitOpen 0:b8bffbcb85fd 18 using namespace Mikami;
MikamiUitOpen 0:b8bffbcb85fd 19
MikamiUitOpen 0:b8bffbcb85fd 20 const int FS_ = 16000; // Sampling frequency: 16 kHz
MikamiUitOpen 0:b8bffbcb85fd 21 ADC_Intr myAdc_(A0, FS_, A1, A2);
MikamiUitOpen 0:b8bffbcb85fd 22 DAC_MCP4922 myDac_;
MikamiUitOpen 0:b8bffbcb85fd 23
MikamiUitOpen 0:b8bffbcb85fd 24 const int ORDER_ = 160;
MikamiUitOpen 0:b8bffbcb85fd 25 float hm_[ORDER_/2+1];
MikamiUitOpen 0:b8bffbcb85fd 26 float xn_[ORDER_+1];
MikamiUitOpen 0:b8bffbcb85fd 27
MikamiUitOpen 0:b8bffbcb85fd 28 DigitalIn sw1_(D2, PullDown); // 0: disable filter
MikamiUitOpen 0:b8bffbcb85fd 29 // 1: enable filter
MikamiUitOpen 0:b8bffbcb85fd 30 DigitalIn sw2_(D3, PullDown); // 0: LPF
MikamiUitOpen 0:b8bffbcb85fd 31 // 1: HPF
MikamiUitOpen 0:b8bffbcb85fd 32 WindowingDesign design_(ORDER_, FS_);
MikamiUitOpen 0:b8bffbcb85fd 33 DigitalOut dOut_(D7);
MikamiUitOpen 0:b8bffbcb85fd 34
MikamiUitOpen 0:b8bffbcb85fd 35 uint16_t a2_ = 0; // Inputted data from A2 pin
MikamiUitOpen 0:b8bffbcb85fd 36
MikamiUitOpen 0:b8bffbcb85fd 37 // Interrupt service routine for ADC
MikamiUitOpen 0:b8bffbcb85fd 38 void AdcIsr()
MikamiUitOpen 0:b8bffbcb85fd 39 {
MikamiUitOpen 0:b8bffbcb85fd 40 dOut_.write(1);
MikamiUitOpen 0:b8bffbcb85fd 41 xn_[0] = myAdc_.Read(); // Read from A0
MikamiUitOpen 0:b8bffbcb85fd 42
MikamiUitOpen 0:b8bffbcb85fd 43 myAdc_.Select3rdChannel(); // Select A2
MikamiUitOpen 0:b8bffbcb85fd 44 myAdc_.SoftStart(); // ADC start for A2 input
MikamiUitOpen 0:b8bffbcb85fd 45
MikamiUitOpen 0:b8bffbcb85fd 46 //-----------------------------------------
MikamiUitOpen 0:b8bffbcb85fd 47 // Execute FIR filter
MikamiUitOpen 0:b8bffbcb85fd 48 float yn = hm_[ORDER_/2]*xn_[ORDER_/2];
MikamiUitOpen 0:b8bffbcb85fd 49 for (int k=0; k<ORDER_/2; k++)
MikamiUitOpen 0:b8bffbcb85fd 50 yn = yn + hm_[k]*(xn_[k] + xn_[ORDER_-k]);
MikamiUitOpen 0:b8bffbcb85fd 51
MikamiUitOpen 0:b8bffbcb85fd 52 for (int k=ORDER_; k>0; k--)
MikamiUitOpen 0:b8bffbcb85fd 53 xn_[k] = xn_[k-1]; // move input signals
MikamiUitOpen 0:b8bffbcb85fd 54 //-----------------------------------------
MikamiUitOpen 0:b8bffbcb85fd 55
MikamiUitOpen 0:b8bffbcb85fd 56 if (sw1_ == 0) myDac_.Write(xn_[0]); // Using no filter
MikamiUitOpen 0:b8bffbcb85fd 57 else myDac_.Write(yn); // Using filter
MikamiUitOpen 0:b8bffbcb85fd 58
MikamiUitOpen 0:b8bffbcb85fd 59 // Read value which controls cutoff frequency
MikamiUitOpen 0:b8bffbcb85fd 60 a2_ = myAdc_.ReadWait_u16();
MikamiUitOpen 0:b8bffbcb85fd 61
MikamiUitOpen 0:b8bffbcb85fd 62 myAdc_.Select1stChannel(); // Select A0
MikamiUitOpen 0:b8bffbcb85fd 63 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt
MikamiUitOpen 0:b8bffbcb85fd 64 // and enable ADC_IRQn
MikamiUitOpen 0:b8bffbcb85fd 65 dOut_.write(0);
MikamiUitOpen 0:b8bffbcb85fd 66 }
MikamiUitOpen 0:b8bffbcb85fd 67
MikamiUitOpen 0:b8bffbcb85fd 68 int main()
MikamiUitOpen 0:b8bffbcb85fd 69 {
MikamiUitOpen 0:b8bffbcb85fd 70 ScfClockTim3(670000); // cutoff frequency: 6.7 kHz
MikamiUitOpen 0:b8bffbcb85fd 71
MikamiUitOpen 0:b8bffbcb85fd 72 WindowingDesign lpfDsgn(ORDER_, FS_);
MikamiUitOpen 0:b8bffbcb85fd 73 Acm1602Ni lcd; // objetc for display using LCD
MikamiUitOpen 0:b8bffbcb85fd 74
MikamiUitOpen 0:b8bffbcb85fd 75 // Clear buffer in FIR filter
MikamiUitOpen 0:b8bffbcb85fd 76 for (int n=0; n<=ORDER_; n++)
MikamiUitOpen 0:b8bffbcb85fd 77 xn_[n] = 0;
MikamiUitOpen 0:b8bffbcb85fd 78 myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt
MikamiUitOpen 0:b8bffbcb85fd 79
MikamiUitOpen 0:b8bffbcb85fd 80 float fc1 = 0;
MikamiUitOpen 0:b8bffbcb85fd 81 WindowingDesign::Type pb = WindowingDesign::LPF;
MikamiUitOpen 0:b8bffbcb85fd 82 while (true)
MikamiUitOpen 0:b8bffbcb85fd 83 {
MikamiUitOpen 0:b8bffbcb85fd 84 // fc: cutoff frequency, 100 -- 2000 Hz
MikamiUitOpen 0:b8bffbcb85fd 85 float fc = 1900.0f*(a2_/4095.6f) + 100.0f;
MikamiUitOpen 0:b8bffbcb85fd 86
MikamiUitOpen 0:b8bffbcb85fd 87 if (sw1_ == 0)
MikamiUitOpen 0:b8bffbcb85fd 88 {
MikamiUitOpen 0:b8bffbcb85fd 89 printf("Through\r\n");
MikamiUitOpen 0:b8bffbcb85fd 90 lcd.ClearLine(1);
MikamiUitOpen 0:b8bffbcb85fd 91 lcd.WriteStringXY("Through ", 0, 0);
MikamiUitOpen 0:b8bffbcb85fd 92 wait(0.2f);
MikamiUitOpen 0:b8bffbcb85fd 93 lcd.ClearLine(0);
MikamiUitOpen 0:b8bffbcb85fd 94 fc1 = 0;
MikamiUitOpen 0:b8bffbcb85fd 95 }
MikamiUitOpen 0:b8bffbcb85fd 96 else
MikamiUitOpen 0:b8bffbcb85fd 97 {
MikamiUitOpen 0:b8bffbcb85fd 98 if (fabs(fc - fc1) > 10.0f)
MikamiUitOpen 0:b8bffbcb85fd 99 {
MikamiUitOpen 0:b8bffbcb85fd 100 printf("fc = %4d\r\n", int(fc+0.5f));
MikamiUitOpen 0:b8bffbcb85fd 101 char str[18];
MikamiUitOpen 0:b8bffbcb85fd 102 sprintf(str, "fc = %4d Hz", int(fc+0.5f));
MikamiUitOpen 0:b8bffbcb85fd 103 lcd.WriteStringXY(str, 0, 0);
MikamiUitOpen 0:b8bffbcb85fd 104 if (sw2_ == 0)
MikamiUitOpen 0:b8bffbcb85fd 105 {
MikamiUitOpen 0:b8bffbcb85fd 106 pb = WindowingDesign::LPF;
MikamiUitOpen 0:b8bffbcb85fd 107 printf("LPF\r\n");
MikamiUitOpen 0:b8bffbcb85fd 108 lcd.WriteStringXY("LPF", 0, 1);
MikamiUitOpen 0:b8bffbcb85fd 109 }
MikamiUitOpen 0:b8bffbcb85fd 110 else
MikamiUitOpen 0:b8bffbcb85fd 111 {
MikamiUitOpen 0:b8bffbcb85fd 112 pb = WindowingDesign::HPF;
MikamiUitOpen 0:b8bffbcb85fd 113 printf("HPF\r\n");
MikamiUitOpen 0:b8bffbcb85fd 114 lcd.WriteStringXY("HPF", 0, 1);
MikamiUitOpen 0:b8bffbcb85fd 115 }
MikamiUitOpen 0:b8bffbcb85fd 116 fc1 = fc;
MikamiUitOpen 0:b8bffbcb85fd 117
MikamiUitOpen 0:b8bffbcb85fd 118 // Design new coefficients based on new fc
MikamiUitOpen 0:b8bffbcb85fd 119 design_.Design(ORDER_, pb, fc1, hm_);
MikamiUitOpen 0:b8bffbcb85fd 120 }
MikamiUitOpen 0:b8bffbcb85fd 121 }
MikamiUitOpen 0:b8bffbcb85fd 122 wait(0.1f);
MikamiUitOpen 0:b8bffbcb85fd 123 }
MikamiUitOpen 0:b8bffbcb85fd 124 }
MikamiUitOpen 0:b8bffbcb85fd 125