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

Dependencies:   UIT_IIR_Filter UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

main.cpp

Committer:
MikamiUitOpen
Date:
2014-10-23
Revision:
0:a9412b9e85b7
Child:
1:e9b451a71ebf

File content as of revision 0:a9412b9e85b7:

//--------------------------------------------------------------
// Cutoff frequency variable LPF by IIR 6th-order filter
//      A0: Signal to be filtered
//      A2: Value which controls cutoff frequency
//
// 2014/10/23, Copyright (c) 2014 MIKAMI, Naoki
//--------------------------------------------------------------

#include "mbed.h"

#include "ADC_Interrupt.hpp"    // for ADC using interrupt
#include "DAC_MCP4922.hpp"      // for DAC MCP4922
#include "ScfClockTim3.hpp"     // for clock supplied to SCF
#include "ACM1602NI.hpp"        // for LCD display

#include "BilinearDesignLH.hpp" // for design of IIR filter
#include "IIR_Cascade.hpp"      // for IIR filter of cascade structure

using namespace Mikami;

const int FS_ = 24000;          // Sampling frequency: 24 kHz
ADC_Intr myAdc_(A0, FS_, A1, A2);
DAC_MCP4922 myDac_;

const int ORDER_ = 6;
IirCascade<ORDER_/2> iirLpf_;   // IIR filter object

DigitalIn sw1_(D2, PullDown);   // 0: disable filter
                                // 1: enable filter

uint16_t a2_ = 0;   // Inputted data from A2 pin

// Interrupt service routine for ADC
void AdcIsr()
{   
    float xn = myAdc_.Read();   // Read from A0

    myAdc_.Select3rdChannel();  // Select A2   
    myAdc_.SoftStart();         // ADC start for A2 input

    // Execute IIR filter
    float yn = iirLpf_.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()
{
    const int ORDER = 6;
    ScfClockTim3(1000000);      // cutoff frequency: 10 kHz

    BiliearDesign lpfDsgn(ORDER, FS_, BiliearDesign::LPF);
    Acm1602Ni lcd;  // objetc for display using LCD

    myAdc_.SetIntrVec(AdcIsr);  // Assign ISR for ADC interrupt

    float fc1 = 0;
    while (true)
    {
        // fc: cutoff frequency, 200 -- 1000 Hz
        float fc = 800.0f*(a2_/4095.6f) + 200.0f;

        if (fabs(fc - fc1) > 10.0f)
        {
            printf("fc = %4d\r\n", int(fc+0.5f));
            char str[18];
            sprintf(str, "fc = %4d Hz", int(fc+0.5f));
            lcd.SetXY(0, 0);
            lcd.WriteString(str);
            fc1 = fc;

            // Design new coefficients based on new fc
            BiliearDesign::Coefs coefsLpf[ORDER/2];
            float g0;
            lpfDsgn.Execute(fc, coefsLpf, g0);

            // Update new coefficients
            Biquad::Coefs coefsIir[ORDER/2];
            for (int n=0; n<ORDER/2; n++)
            {
                coefsIir[n].a1 = coefsLpf[n].a1;
                coefsIir[n].a2 = coefsLpf[n].a2;
                coefsIir[n].b1 = coefsLpf[n].b1;
                coefsIir[n].b2 = 1.0f;
            }
            iirLpf_.SetCoefs(g0, coefsIir);
        }
        wait(0.1f);
    }
}