Cutoff frequency variable LPF and HPF 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 Dec 08 05:46:37 2014 +0000
Revision:
7:46327dcab1bf
Parent:
6:e4b8e25573f3
7

Who changed what in which revision?

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