Nucleo-F446 によるグラフィック・イコライザ.DA変換器にデータを送る際は 4 倍にアップ・サンプリング.

Dependencies:   mbed SerialTxRxIntr F446_AD_DA_Multirate

main.cpp

Committer:
MikamiUitOpen
Date:
2019-01-31
Revision:
6:7dd696fe86c8
Parent:
5:a4f15be9afb7

File content as of revision 6:7dd696fe86c8:

//----------------------------------------------------------------------
//  グラフィック・イコライザ
//
//  PC 側のプログラム: F446_GraphicEqualizer 
//
//  2019/01/31, Copyright (c) 2019 MIKAMI, Naoki
//----------------------------------------------------------------------

#include "main.hpp"
using namespace Mikami;

// 出力標本化周波数を4倍にするオブジェクト
F446_Multirate myAdDa_(ORDER_SM_, HK_SM_, G0_SM_);
// Serial クラスの受信割込み用オブジェクト
SerialRxTxIntr rx_;
                          
int main()
{
    myAdDa_.Start(FS_);     // ADC 変換終了割り込みを使えるようにする

    // 以下の割り込み優先順位の設定を忘れないこと
    NVIC_SetPriority(ADC_IRQn, 0);      // ADC 終了割り込み:最優先
    NVIC_SetPriority(USART2_IRQn, 1);   // USART2 割り込み:次に優先    
    
    // グラフィック・イコライザ用パラメータ等の定義
    const int BANDS = 9;
    const float Q_VAL = 1.0f/sqrtf(2.0f);   // フィルタの Q 値
    GrEqParams params(BANDS, FS_);  // グラフィック・イコライザで使うフィルタの
                                    // 係数を計算するオブジェクト
    BiquadGrEq biquad[BANDS];       // グラフィック・イコライザで使うフィルタ
    float f0[BANDS];                // 中心周波数(ピーキング・フィルタの場合)
    for (int n=0; n<BANDS; n++) f0[n] = 62.5f*powf(2, n);
    for (int n=0; n<BANDS; n++)
        biquad[n].SetCoefficients(params.Get(n, f0[n], 0, Q_VAL));
    
    bool on = true;         // フィルタ処理の有効/無効を決める変数
    
    while (true)
    {
        //------------------------------------------------------------
        // ここにディジタルフィルタ等の処理を記述する
        float xn = myAdDa_.Input()*0.25f;     // 入力
        float yn = xn;
        for (int n=0; n<BANDS; n++) yn =biquad[n].Execute(yn);
        // 実行時間:約 7 μs
        myAdDa_.Output(on ? yn : xn);   // 出力
        //------------------------------------------------------------

        //------------------------------------------------------------   
        // PC からの指令に対応する処理
        if (rx_.IsEol())        // 受信バッファのデータが有効になった場合の処理
        {
            string str = rx_.GetBuffer();
            if (str == "GrEq")
                rx_.Tx("ACK\n");    // "ACK" を送り返す
            else if (str == "ACTIVE")
                on = true;          // フィルタ処理を有効にする
            else if (str == "THROUGH")
                on = false;         // フィルタ処理を無効にする
            else if (str == "FLAT")
                for (int n=0; n<BANDS; n++) // フィルタの特性を平坦にする
                    biquad[n].SetCoefficients(params.Get(n, f0[n], 0, Q_VAL));
            // "GrEq", "ON", "OFF", "FLAT" 以外は float 型の数値に対応する文字列とし
            // て処理を行う
            else    
            {
                // 最初の文字はフィルタの番号
                int k = atoi(str.substr(0, 1).c_str());     // フィルタの番号
                // 次の文字からは dB 値
                str.erase(0, 1);
                float db = atof(str.c_str());
                biquad[k].SetCoefficients(params.Get(k, f0[k], db, Q_VAL));
            }
        }
        // PC からの指令に対応する処理はここまで
        //------------------------------------------------------------       
    }
}