Nucleo-F446 による遮断周波数可変 LPF/HPF .DA変換器にデータを送る際は 4 倍にアップ・サンプリング.

Dependencies:   mbed SerialTxRxIntr F446_AD_DA_MultirateSWI

main.cpp

Committer:
MikamiUitOpen
Date:
2019-06-30
Revision:
8:da8bdc49f7ad
Parent:
6:02743f6a1595

File content as of revision 8:da8bdc49f7ad:

//----------------------------------------------------------------------
//  遮断周波数可変 IIR フィルタ(LPF, HPF)
//
//  PC 側のプログラム: F446_LPF_HPF_Variable 
//  周波数特性が PC の画面に表示され,その上のカーソルをマウスでドラッグすることで,
//  遮断周波数を変えられる
//
//  2019/06/30, Copyright (c) 2019 MIKAMI, Naoki
//----------------------------------------------------------------------

#include "main.hpp"
using namespace Mikami;

// 出力標本化周波数を4倍にするオブジェクト
F446_MultirateSWI myAdDa_(ORDER_SM_, HK_SM_, G0_SM_);
// Serial クラスの受信割込み用オブジェクト
SerialRxTxIntr rx_;

// 10 次の IIR フィルタ
const int ORDER_ = 10;
Biquad myBiquad_[ORDER_/2];
IirCascade iir8_(ORDER_, myBiquad_);    // IIR 縦続形のオブジェクト

bool on_ = true;    // フィルタ処理の有効/無効を決める変数
                          
// LPF/HPF の処理(割り込みサービス・ルーチン)
void LpfHpf()
{
    float xn = myAdDa_.Input();     // 入力
    float yn = iir8_.Execute(xn);   // IIR フィルタの実行
    myAdDa_.Output(on_ ? yn : xn);  // 出力
}

int main()
{
    // 次の割り込み優先順位の設定を忘れないこと
    NVIC_SetPriority(USART2_IRQn, 2);   // USART2 割り込み:SWI の次に優先    
    
    BilinearDesign design(ORDER_, FS_); // フィルタ設計用オブジェクト生成
    Biquad::Coefs coefs[ORDER_/2];      // 設計された係数の格納用
    float g0;               // 利得定数
    float fc = 1000.0f;     // 最初に実行される LPF の遮断周波数
    design.Execute(fc, BilinearDesign::LPF, coefs, g0); // LPF

    iir8_.SetCoefs(ORDER_, coefs, g0);  // 最初に実行される LPF の係数を設定
    float fcOld = fc;                   // 更新する前の遮断周波数
    
    myAdDa_.Start(FS_, &LpfHpf);        // 標本化を開始する

    while (true)
    {
        // PC からの指令に対応する処理
        if (rx_.IsEol())        // 受信バッファのデータが有効になった場合の処理
        {
            string str = rx_.GetBuffer();
            if (str == "VrFc")
                rx_.Tx("ACK\n");    // "ACK" を送り返す
            else if (str == "ACTIVE")
                on_ = true;         // フィルタ処理を有効にする
            else if (str == "THROUGH")
                on_ = false;        // フィルタ処理を無効にする
            else    // "VrFc", "ACTIVE", "THROUGH" 以外は
            {       // int 型の数値に対応する文字列として処理を行う
                // PC から送信された遮断周波数を fc に保存
                fc =  atoi(str.c_str());
                // フィルタの係数設計
                if (fc > 0) // LPF の係数を設計
                    design.Execute(fc, BilinearDesign::LPF, coefs, g0);
                else        // HPF の係数を設計
                    design.Execute(-fc, BilinearDesign::HPF, coefs, g0);

                // 設計されたフィルタ係数の設定
                iir8_.SetCoefs(ORDER_, coefs, g0);
                
                if (fc*fcOld < 0.0f)    // LPF と HPF が切り替わった場合
                    iir8_.Clear();      // フィルタの遅延器をクリア
                fcOld = fc;
            }
        }
    }
}