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

Dependencies:   mbed SerialTxRxIntr F446_AD_DA_Multirate

Revision:
0:0312aa1893cf
Child:
1:4c6a67b336d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 05 11:14:21 2018 +0000
@@ -0,0 +1,80 @@
+//----------------------------------------------------------------------
+//  遮断周波数可変 IIR フィルタ(LPF, HPF)
+//
+//  PC 側のプログラム: F446_LPF_HPF_Variable: 
+//  周波数特性が PC の画面に表示され,その上のカーソルをマウスでドラッグすることで,
+//  遮断周波数を変えられる
+//
+//  2018/06/04, Copyright (c) 2018 MIKAMI, Naoki
+//----------------------------------------------------------------------
+
+#include "main.hpp"
+using namespace Mikami;
+
+// 出力標本化周波数を4倍にするオブジェクト
+F446_Multirate myAdDa_(ORDER_SM_, HK_SM_, G0_SM_);
+// Serial クラスの受信割込み用オブジェクト
+SerialRxIntr 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.find("ENQ") != string::npos)
+                rx_.Tx("ACK");      // "ACK" を送り返す
+            else if (str.find("ON") != string::npos)
+                on = true;          // フィルタ処理を有効にする
+            else if (str.find("OFF") != string::npos)
+                on = false;         // フィルタ処理を無効にする
+            else if (str.find("FLAT") != string::npos)
+                for (int n=0; n<BANDS; n++) // フィルタの特性を平坦にする
+                    biquad[n].SetCoefficients(params.Get(n, f0[n], 0, Q_VAL));
+            // "ENQ", "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 からの指令に対応する処理はここまで
+        //------------------------------------------------------------       
+    }
+}