Cutoff frequency variable LPF and HPF by IIR 6th-order Butterworth filter for ST Nucleo F401RE.

Dependencies:   UITDSP_ADDA UIT_ACM1602NI UIT_AQM1602 UIT_IIR_Filter mbed

Revision:
0:33908268d9ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Sep 11 09:54:45 2015 +0000
@@ -0,0 +1,119 @@
+//--------------------------------------------------------------
+// Cutoff frequency variable LPF and HPF by IIR 8th-order filter
+//      A0: Signal to be filtered
+//      A2: Value which controls cutoff frequency
+//
+//      sw: 0, 2  Through
+//          1: LPF
+//          3: HPF
+// 2015/09/11, Copyright (c) 2015 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "ADC_Interrupt.hpp"    // for ADC using interrupt
+#include "DAC_MCP4921.hpp"      // for DAC MCP4921, MCP4922
+using namespace Mikami;
+
+#include "BilinearDesignLH.hpp" // for design of IIR filter
+#include "IIR_Cascade.hpp"      // for IIR filter of cascade structure
+
+// ACM1602Ni を使う場合は次の define 文をコメントにすること
+#define AQM1602
+
+#ifdef AQM1602
+#include "AQM1602.hpp"
+Aqm1602 Lcd_;
+#else
+#include "ACM1602NI.hpp"
+Acm1602Ni Lcd_;
+#endif
+
+const int FS_ = 24000;          // Sampling frequency: 24 kHz
+ADC_Intr myAdc_(A0, FS_, A2);
+DAC_MCP4921 myDac_;
+
+const int ORDER_ = 8;
+IirCascade<ORDER_> iirLH_;      // IIR filter object
+
+DigitalIn sw1_(D2, PullDown);   // 0: disable filter
+                                // 1: enable filter
+DigitalIn sw2_(D3, PullDown);                                
+
+uint16_t a2_ = 0;   // Inputted data from A2 pin
+
+// Interrupt service routine for ADC
+void AdcIsr()
+{   
+    float xn = myAdc_.Read();   // Read from A0
+
+    myAdc_.Select2ndChannel();  // Select A2   
+    myAdc_.SoftStart();         // ADC start for A2 input
+
+    // Execute IIR filter
+    float yn = iirLH_.Execute(xn);
+
+    if (sw1_ == 0) myDac_.Write(xn);    // 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
+}
+
+int main()
+{
+    myDac_.ScfClockTim3(1000000);   // cutoff frequency: 10 kHz
+
+    BilinearDesign lpfDsgn(ORDER_, FS_, BilinearDesign::LPF);
+    BilinearDesign hpfDsgn(ORDER_, FS_, BilinearDesign::HPF);
+
+    myAdc_.SetIntrVec(AdcIsr);  // Assign ISR for ADC interrupt
+
+    float fc1 = 0;
+    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_.WriteStringXY("Through         ", 0, 0);
+            wait(0.2f);
+            Lcd_.ClearLine(0);
+            fc1 = 0;
+        }
+        else
+        {
+            if (fabs(fc - fc1) > 10.0f)
+            {
+                char str[18];
+                if (sw2_ == 0) sprintf(str, "LPF: fc=%4d Hz", int(fc+0.5f));
+                else           sprintf(str, "HPF: fc=%4d Hz", int(fc+0.5f));
+
+                printf("%s\r\n", str);
+                Lcd_.WriteStringXY(str, 0, 0);
+                fc1 = fc;
+
+                // Design new coefficients based on new fc
+                BilinearDesign::Coefs coefs[ORDER_/2];
+                float g0;
+                if (sw2_ == 0) lpfDsgn.Execute(fc, coefs, g0);
+                else           hpfDsgn.Execute(fc, coefs, g0);
+                Biquad::Coefs coefsIir[ORDER_/2];
+                // Update new coefficients
+                for (int n=0; n<ORDER_/2; n++)
+                {
+                    coefsIir[n].a1 = coefs[n].a1;
+                    coefsIir[n].a2 = coefs[n].a2;
+                    coefsIir[n].b1 = coefs[n].b1;
+                    coefsIir[n].b2 = 1.0f;
+                }
+                iirLH_.SetCoefs(g0, coefsIir);
+            }
+        }
+        wait(0.1f);
+    }
+}