Cutoff frequency variable LPF, HPF, BPF, and BRF by FIR 160th-order filter.

Dependencies:   UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

Committer:
MikamiUitOpen
Date:
Mon Dec 08 08:14:48 2014 +0000
Revision:
0:ca94cfc90365
Child:
1:58271fae2e01
1

Who changed what in which revision?

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