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
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2014-11-10
- Revision:
- 0:b8bffbcb85fd
- Child:
- 1:24c33c8719b2
File content as of revision 0:b8bffbcb85fd:
//------------------------------------------------------------------ // Cutoff frequency variable LPF and HPF by FIR 160th-order filter // A0: Signal to be filtered // A2: Value which controls cutoff frequency // // 2014/11/10, Copyright (c) 2014 MIKAMI, Naoki //------------------------------------------------------------------ #include "mbed.h" #include "ADC_Interrupt.hpp" // for ADC using interrupt #include "DAC_MCP4922.hpp" // for DAC MCP4922 #include "ScfClockTim3.hpp" // for clock supplied to SCF #include "ACM1602NI.hpp" // for LCD display #include "WindowingDesignLH.hpp" // for design of IIR filter using namespace Mikami; const int FS_ = 16000; // Sampling frequency: 16 kHz ADC_Intr myAdc_(A0, FS_, A1, A2); DAC_MCP4922 myDac_; const int ORDER_ = 160; float hm_[ORDER_/2+1]; float xn_[ORDER_+1]; DigitalIn sw1_(D2, PullDown); // 0: disable filter // 1: enable filter DigitalIn sw2_(D3, PullDown); // 0: LPF // 1: HPF WindowingDesign design_(ORDER_, FS_); DigitalOut dOut_(D7); uint16_t a2_ = 0; // Inputted data from A2 pin // Interrupt service routine for ADC void AdcIsr() { dOut_.write(1); xn_[0] = myAdc_.Read(); // Read from A0 myAdc_.Select3rdChannel(); // Select A2 myAdc_.SoftStart(); // ADC start for A2 input //----------------------------------------- // Execute FIR filter float yn = hm_[ORDER_/2]*xn_[ORDER_/2]; for (int k=0; k<ORDER_/2; k++) yn = yn + hm_[k]*(xn_[k] + xn_[ORDER_-k]); for (int k=ORDER_; k>0; k--) xn_[k] = xn_[k-1]; // move input signals //----------------------------------------- if (sw1_ == 0) myDac_.Write(xn_[0]); // Using no filter else myDac_.Write(yn); // Using filter // Read value which controls cutoff frequency a2_ = myAdc_.ReadWait_u16(); myAdc_.Select1stChannel(); // Select A0 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt // and enable ADC_IRQn dOut_.write(0); } int main() { ScfClockTim3(670000); // cutoff frequency: 6.7 kHz WindowingDesign lpfDsgn(ORDER_, FS_); Acm1602Ni lcd; // objetc for display using LCD // Clear buffer in FIR filter for (int n=0; n<=ORDER_; n++) xn_[n] = 0; myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt float fc1 = 0; WindowingDesign::Type pb = WindowingDesign::LPF; while (true) { // fc: cutoff frequency, 100 -- 2000 Hz float fc = 1900.0f*(a2_/4095.6f) + 100.0f; if (sw1_ == 0) { printf("Through\r\n"); lcd.ClearLine(1); lcd.WriteStringXY("Through ", 0, 0); wait(0.2f); lcd.ClearLine(0); fc1 = 0; } else { if (fabs(fc - fc1) > 10.0f) { printf("fc = %4d\r\n", int(fc+0.5f)); char str[18]; sprintf(str, "fc = %4d Hz", int(fc+0.5f)); lcd.WriteStringXY(str, 0, 0); if (sw2_ == 0) { pb = WindowingDesign::LPF; printf("LPF\r\n"); lcd.WriteStringXY("LPF", 0, 1); } else { pb = WindowingDesign::HPF; printf("HPF\r\n"); lcd.WriteStringXY("HPF", 0, 1); } fc1 = fc; // Design new coefficients based on new fc design_.Design(ORDER_, pb, fc1, hm_); } } wait(0.1f); } }