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

Dependencies:   UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

Committer:
MikamiUitOpen
Date:
Tue Dec 09 06:04:35 2014 +0000
Revision:
1:58271fae2e01
Parent:
0:ca94cfc90365
Child:
3:24b6aa1a19ba
2

Who changed what in which revision?

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