Cutoff frequency variable LPF by 160th-order FIR filter designed by window method usin Hamming window for ST Nucleo F401RE.

Dependencies:   UIT_ACM1602NI UIT_ADDA mbed

main.cpp

Committer:
MikamiUitOpen
Date:
2014-12-08
Revision:
6:ccd700fb3f3a
Parent:
5:9dd178ff6239

File content as of revision 6:ccd700fb3f3a:

//------------------------------------------------------------------
// Cutoff frequency variable LPF by FIR 160th-order filter
//      A0: Signal to be filtered
//      A2: Value which controls cutoff frequency
//
// 2014/12/08, Copyright (c) 2014 MIKAMI, Naoki
//------------------------------------------------------------------

#include "mbed.h"

#include "ADC_Interrupt.hpp"    // for ADC using interrupt
#include "DAC_MCP4922.hpp"      // for DAC MCP4922
#include "ACM1602NI.hpp"        // for LCD display

#include "WindowingDesignLH.hpp"    // for design of FIR filter

using namespace Mikami;

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

const int ORDER_ = 160;
float hm_[ORDER_/2+1];
float xn_[ORDER_+1];

DigitalIn sw1_(D2, PullDown);   // 0: disable filter
                                // 1: enable filter
WindowingDesign design_(ORDER_, FS_);
DigitalOut dOut_(D7);

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

// Interrupt service routine for ADC
void AdcIsr()
{   
    dOut_.write(1);
    xn_[0] = myAdc_.Read();   // Read from A0

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

    //-----------------------------------------
    // Execute FIR filter
        float yn = hm_[ORDER_/2]*xn_[ORDER_/2];
        for (int k=0; k<ORDER_/2; k++)
            yn = yn + hm_[k]*(xn_[k] + xn_[ORDER_-k]);

        for (int k=ORDER_; k>0; k--)
            xn_[k] = xn_[k-1];  // move input signals
    //-----------------------------------------

    if (sw1_ == 0) myDac_.Write(xn_[0]);    // 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
    dOut_.write(0);
}

int main()
{
    myDac_.ScfClockTim3(670000);    // cutoff frequency: 6.7 kHz

    WindowingDesign lpfDsgn(ORDER_, FS_);
    Acm1602Ni lcd;  // objetc for display using LCD

    // Clear buffer in FIR filter
    for (int n=0; n<=ORDER_; n++)
        xn_[n] = 0;
    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)
            {
                printf("fc = %4d\r\n", int(fc+0.5f));
                char str[18];
                sprintf(str, "fc = %4d Hz", int(fc+0.5f));
                lcd.WriteStringXY(str, 0, 0);
                fc1 = fc;
                // Design new coefficients based on new fc
                design_.Design(ORDER_, WindowingDesign::LPF, fc1, hm_);
            }
        }
        wait(0.1f);
    }
}