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

Dependencies:   UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

Committer:
MikamiUitOpen
Date:
Sat Jul 25 06:36:06 2015 +0000
Revision:
3:24b6aa1a19ba
Parent:
1:58271fae2e01
4

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 3:24b6aa1a19ba 7 // 2015/07/25, Copyright (c) 2015 MIKAMI, Naoki
MikamiUitOpen 0:ca94cfc90365 8 //------------------------------------------------------------------------------
MikamiUitOpen 0:ca94cfc90365 9
MikamiUitOpen 0:ca94cfc90365 10 #include "ADC_Interrupt.hpp" // for ADC using interrupt
MikamiUitOpen 3:24b6aa1a19ba 11 #include "DAC_MCP4921.hpp" // for DAC MCP4921, MCP4922
MikamiUitOpen 3:24b6aa1a19ba 12 using namespace Mikami;
MikamiUitOpen 0:ca94cfc90365 13
MikamiUitOpen 0:ca94cfc90365 14 #include "WindowingDesign.hpp" // for design of FIR filter
MikamiUitOpen 0:ca94cfc90365 15
MikamiUitOpen 3:24b6aa1a19ba 16 // ACM1602Ni を使う場合は次の define 文をコメントにすること
MikamiUitOpen 3:24b6aa1a19ba 17 #define AQM1602
MikamiUitOpen 3:24b6aa1a19ba 18
MikamiUitOpen 3:24b6aa1a19ba 19 #ifdef AQM1602
MikamiUitOpen 3:24b6aa1a19ba 20 #include "AQM1602.hpp"
MikamiUitOpen 3:24b6aa1a19ba 21 Aqm1602 Lcd_;
MikamiUitOpen 3:24b6aa1a19ba 22 #else
MikamiUitOpen 3:24b6aa1a19ba 23 #include "ACM1602NI.hpp"
MikamiUitOpen 3:24b6aa1a19ba 24 Acm1602Ni Lcd_;
MikamiUitOpen 3:24b6aa1a19ba 25 #endif
MikamiUitOpen 0:ca94cfc90365 26
MikamiUitOpen 0:ca94cfc90365 27 const int FS_ = 16000; // Sampling frequency: 16 kHz
MikamiUitOpen 0:ca94cfc90365 28 ADC_Intr myAdc_(A0, FS_, A1, A2);
MikamiUitOpen 3:24b6aa1a19ba 29 DAC_MCP4921 myDac_;
MikamiUitOpen 0:ca94cfc90365 30
MikamiUitOpen 0:ca94cfc90365 31 const int ORDER_ = 160;
MikamiUitOpen 0:ca94cfc90365 32 float hm_[ORDER_/2+1];
MikamiUitOpen 0:ca94cfc90365 33 float xn_[ORDER_+1];
MikamiUitOpen 0:ca94cfc90365 34
MikamiUitOpen 3:24b6aa1a19ba 35 BusIn sws_(D2, D3, D4, D5);
MikamiUitOpen 3:24b6aa1a19ba 36 int sw_;
MikamiUitOpen 0:ca94cfc90365 37 WindowingDesign design_(ORDER_, FS_);
MikamiUitOpen 0:ca94cfc90365 38
MikamiUitOpen 0:ca94cfc90365 39 uint16_t a2_ = 0; // Inputted data from A2 pin
MikamiUitOpen 0:ca94cfc90365 40
MikamiUitOpen 0:ca94cfc90365 41 // Interrupt service routine for ADC
MikamiUitOpen 0:ca94cfc90365 42 void AdcIsr()
MikamiUitOpen 0:ca94cfc90365 43 {
MikamiUitOpen 1:58271fae2e01 44 xn_[0] = myAdc_.Read(); // Read from A0
MikamiUitOpen 0:ca94cfc90365 45
MikamiUitOpen 0:ca94cfc90365 46 myAdc_.Select3rdChannel(); // Select A2
MikamiUitOpen 0:ca94cfc90365 47 myAdc_.SoftStart(); // ADC start for A2 input
MikamiUitOpen 0:ca94cfc90365 48
MikamiUitOpen 0:ca94cfc90365 49 //-----------------------------------------
MikamiUitOpen 0:ca94cfc90365 50 // Execute FIR filter
MikamiUitOpen 0:ca94cfc90365 51 float yn = hm_[ORDER_/2]*xn_[ORDER_/2];
MikamiUitOpen 0:ca94cfc90365 52 for (int k=0; k<ORDER_/2; k++)
MikamiUitOpen 0:ca94cfc90365 53 yn = yn + hm_[k]*(xn_[k] + xn_[ORDER_-k]);
MikamiUitOpen 0:ca94cfc90365 54
MikamiUitOpen 0:ca94cfc90365 55 for (int k=ORDER_; k>0; k--)
MikamiUitOpen 0:ca94cfc90365 56 xn_[k] = xn_[k-1]; // move input signals
MikamiUitOpen 0:ca94cfc90365 57 //-----------------------------------------
MikamiUitOpen 0:ca94cfc90365 58
MikamiUitOpen 3:24b6aa1a19ba 59 if ((sw_ & 0x01) == 0)
MikamiUitOpen 3:24b6aa1a19ba 60 myDac_.Write(xn_[0]); // Using no filter
MikamiUitOpen 3:24b6aa1a19ba 61 else
MikamiUitOpen 3:24b6aa1a19ba 62 myDac_.Write(yn); // Using filter
MikamiUitOpen 0:ca94cfc90365 63
MikamiUitOpen 0:ca94cfc90365 64 // Read value which controls cutoff frequency
MikamiUitOpen 0:ca94cfc90365 65 a2_ = myAdc_.ReadWait_u16();
MikamiUitOpen 0:ca94cfc90365 66
MikamiUitOpen 0:ca94cfc90365 67 myAdc_.Select1stChannel(); // Select A0
MikamiUitOpen 0:ca94cfc90365 68 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt
MikamiUitOpen 0:ca94cfc90365 69 // and enable ADC_IRQn
MikamiUitOpen 0:ca94cfc90365 70 }
MikamiUitOpen 0:ca94cfc90365 71
MikamiUitOpen 3:24b6aa1a19ba 72 void printfLcdDesign(WindowingDesign::Type pb, char str[], int f1, int f2 = 0);
MikamiUitOpen 3:24b6aa1a19ba 73
MikamiUitOpen 0:ca94cfc90365 74 int main()
MikamiUitOpen 0:ca94cfc90365 75 {
MikamiUitOpen 0:ca94cfc90365 76 myDac_.ScfClockTim3(670000); // cutoff frequency: 6.7 kHz
MikamiUitOpen 3:24b6aa1a19ba 77 sws_.mode(PullDown);
MikamiUitOpen 0:ca94cfc90365 78
MikamiUitOpen 0:ca94cfc90365 79 // Clear buffer in FIR filter
MikamiUitOpen 0:ca94cfc90365 80 for (int n=0; n<=ORDER_; n++)
MikamiUitOpen 0:ca94cfc90365 81 xn_[n] = 0;
MikamiUitOpen 0:ca94cfc90365 82 myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt
MikamiUitOpen 0:ca94cfc90365 83
MikamiUitOpen 0:ca94cfc90365 84 float fc1 = 0;
MikamiUitOpen 0:ca94cfc90365 85 while (true)
MikamiUitOpen 0:ca94cfc90365 86 {
MikamiUitOpen 3:24b6aa1a19ba 87 sw_ = sws_.read();
MikamiUitOpen 3:24b6aa1a19ba 88 if ((sw_ & 0x01) == 0)
MikamiUitOpen 0:ca94cfc90365 89 {
MikamiUitOpen 0:ca94cfc90365 90 printf("Through\r\n");
MikamiUitOpen 3:24b6aa1a19ba 91 Lcd_.ClearLine(1);
MikamiUitOpen 3:24b6aa1a19ba 92 Lcd_.WriteStringXY("Through ", 0, 0);
MikamiUitOpen 0:ca94cfc90365 93 wait(0.2f);
MikamiUitOpen 3:24b6aa1a19ba 94 Lcd_.ClearLine(0);
MikamiUitOpen 0:ca94cfc90365 95 fc1 = 0;
MikamiUitOpen 0:ca94cfc90365 96 }
MikamiUitOpen 0:ca94cfc90365 97 else
MikamiUitOpen 0:ca94cfc90365 98 {
MikamiUitOpen 1:58271fae2e01 99 // fc: cutoff or center frequency, 200 -- 2000 Hz
MikamiUitOpen 1:58271fae2e01 100 float fc = 1800.0f*(a2_/4095.6f) + 200.0f;
MikamiUitOpen 1:58271fae2e01 101
MikamiUitOpen 0:ca94cfc90365 102 if (fabs(fc - fc1) > 10.0f)
MikamiUitOpen 0:ca94cfc90365 103 {
MikamiUitOpen 1:58271fae2e01 104 fc1 = fc;
MikamiUitOpen 0:ca94cfc90365 105
MikamiUitOpen 3:24b6aa1a19ba 106 switch (sw_)
MikamiUitOpen 0:ca94cfc90365 107 {
MikamiUitOpen 3:24b6aa1a19ba 108 case 1: printfLcdDesign(design_.LPF, "LPF", fc+0.5f);
MikamiUitOpen 1:58271fae2e01 109 break;
MikamiUitOpen 3:24b6aa1a19ba 110 case 3: printfLcdDesign(design_.HPF, "HPF", fc+0.5f);
MikamiUitOpen 1:58271fae2e01 111 break;
MikamiUitOpen 3:24b6aa1a19ba 112 case 5: printfLcdDesign(design_.BPF, "BPF", fc-100, fc+100);
MikamiUitOpen 1:58271fae2e01 113 break;
MikamiUitOpen 3:24b6aa1a19ba 114 case 7: printfLcdDesign(design_.BRF, "BRF", fc-150, fc+150);
MikamiUitOpen 1:58271fae2e01 115 break;
MikamiUitOpen 0:ca94cfc90365 116 }
MikamiUitOpen 0:ca94cfc90365 117 }
MikamiUitOpen 0:ca94cfc90365 118 }
MikamiUitOpen 0:ca94cfc90365 119 wait(0.1f);
MikamiUitOpen 0:ca94cfc90365 120 }
MikamiUitOpen 0:ca94cfc90365 121 }
MikamiUitOpen 3:24b6aa1a19ba 122
MikamiUitOpen 3:24b6aa1a19ba 123 void printfLcdDesign(WindowingDesign::Type pb, char str[], int f1, int f2)
MikamiUitOpen 3:24b6aa1a19ba 124 {
MikamiUitOpen 3:24b6aa1a19ba 125 printf(((string)str+"\r\n").c_str());
MikamiUitOpen 3:24b6aa1a19ba 126 Lcd_.WriteStringXY(str, 0, 0);
MikamiUitOpen 3:24b6aa1a19ba 127 char strFc[17];
MikamiUitOpen 3:24b6aa1a19ba 128 if (f2 == 0)
MikamiUitOpen 3:24b6aa1a19ba 129 {
MikamiUitOpen 3:24b6aa1a19ba 130 printf("fc = %4d Hz\r\n", f1);
MikamiUitOpen 3:24b6aa1a19ba 131 sprintf(strFc, "fc: %4d Hz", f1);
MikamiUitOpen 3:24b6aa1a19ba 132 }
MikamiUitOpen 3:24b6aa1a19ba 133 else
MikamiUitOpen 3:24b6aa1a19ba 134 {
MikamiUitOpen 3:24b6aa1a19ba 135 printf("fc = %4d, %4d Hz\r\n", f1, f2);
MikamiUitOpen 3:24b6aa1a19ba 136 sprintf(strFc, "fc: %4d,%4d Hz", f1, f2);
MikamiUitOpen 3:24b6aa1a19ba 137 }
MikamiUitOpen 3:24b6aa1a19ba 138 Lcd_.WriteStringXY(strFc, 0, 1);
MikamiUitOpen 3:24b6aa1a19ba 139
MikamiUitOpen 3:24b6aa1a19ba 140 design_.Design(ORDER_, pb, f1, f2, hm_);
MikamiUitOpen 3:24b6aa1a19ba 141 }