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

Dependencies:   UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

main.cpp

Committer:
MikamiUitOpen
Date:
2014-12-09
Revision:
1:58271fae2e01
Parent:
0:ca94cfc90365
Child:
3:24b6aa1a19ba

File content as of revision 1:58271fae2e01:

//------------------------------------------------------------------------------
// Cutoff frequency variable LPF, HPF, BPF and BRF by FIR 160th-order filter
//      A0: Signal to be filtered
//      A2: Value which controls cutoff frequency
//
//      1: LPF, 3: HPF, 5: BPF, 7: BRF, even: through
// 2014/12/09, 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 "WindowingDesign.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);
DigitalIn sw2_(D3, PullDown);
DigitalIn sw4_(D4, PullDown);
DigitalIn sw8_(D5, PullDown);

WindowingDesign design_(ORDER_, FS_);

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

// Interrupt service routine for ADC
void AdcIsr()
{   
    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
}

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

    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)
    {
        int sw = (sw8_ << 3) | (sw4_ << 2) | (sw2_ << 1) | sw1_;
        if (sw1_ == 0)
        {
            printf("Through\r\n");
            lcd.ClearLine(1);
            lcd.WriteStringXY("Through         ", 0, 0);
            wait(0.2f);
            lcd.ClearLine(0);           
            fc1 = 0;
        }
        else
        {
            // fc: cutoff or center frequency, 200 -- 2000 Hz
            float fc = 1800.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.WriteStringXY(str, 0, 1);
                fc1 = fc;

                switch (sw)
                {
                    case 1: printf("LPF\r\n");
                            lcd.WriteStringXY("LPF", 0, 0);
                            design_.Design(ORDER_, design_.LPF, fc, 0, hm_);
                            break;
                    case 3: printf("HPF\r\n");
                            lcd.WriteStringXY("HPF", 0, 0);
                            design_.Design(ORDER_, design_.HPF, fc, 0, hm_);
                            break;
                    case 5: printf("BPF\r\n");
                            lcd.WriteStringXY("BPF", 0, 0);
                            design_.Design(ORDER_, design_.BPF, fc-100, fc+100, hm_);
                            break;
                    case 7: printf("BRF\r\n");
                            lcd.WriteStringXY("BRF", 0, 0);
                            design_.Design(ORDER_, design_.BRF, fc-100, fc+100, hm_);
                            break;
                }
            }
        }
        wait(0.1f);
    }
}