Cutoff frequency variable LPF, HPF, BPF, and BRF by FIR 160th-order filter.
Dependencies: UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602
main.cpp@3:24b6aa1a19ba, 2015-07-25 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sat Jul 25 06:36:06 2015 +0000
- Revision:
- 3:24b6aa1a19ba
- Parent:
- 1:58271fae2e01
4
Who changed what in which revision?
User | Revision | Line number | New 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 | } |