CQエレクトロニクス・セミナで使用する遮断周波数可変の LPF/HPF のプログラム
Dependencies: mbed SerialTxRxIntr DSP_MultirateLinearphase
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2022-03-30
- Revision:
- 2:3955cb401851
- Parent:
- 1:2d08a91b6bf2
File content as of revision 2:3955cb401851:
//------------------------------------------------------------------ // 遮断周波数可変 IIR フィルタ(LPF, HPF) // DA 出力はアップサンプリング使用 // フィルタの係数は PC で計算し,それをマイコン側に転送するタイプ // // ● PC 側のプログラム: F446_VariableLHpfB // ● ボーレート: 最初: 9600 baud // 通信確立後: 115200 baud // ● 入力: A1 // ● 出力: A2 // // 2022/03/30, Copyright (c) 2022 MIKAMI, Naoki //------------------------------------------------------------------ #include "MultirateLiPh.hpp" // DA でアップサンプリング #include "SerialRxTxIntr.hpp" #include "IirVariable.hpp" #include <cctype> // isalpha(), isdigit() で使用 using namespace Mikami; const float FS_ = 44.1f; // 入力の標本化周波数: 44.1 kHz MultirateLiPh myAdDa_(FS_); // 出力標本化周波数を4倍にするオブジェクト // 縦続形 IIR フィルタによる可変フィルタのオブジェクト, 次数: 10 次 VariableIir filter_; void Select(string str); // 有効,無効,出力 On/Off に対応する処理の選択 void NumericCtrl(string str); // フィルタ係数の更新 // LPF/HPF の信号処理 void AdcIsr() { float xn = myAdDa_.Input(); // 入力 float yn = filter_.Execute(xn); // IIR フィルタの実行 myAdDa_.Output(yn); // 出力 } int main() { SerialRxTxIntr rx(150); // PC との通信用,バッファサイズ:150,9600 baud NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 NVIC_SetPriority(USART2_IRQn, 1); myAdDa_.Start(&AdcIsr); // 標本化を開始する while (true) { if (rx.IsEol()) // PC からの指令に対応する処理 { string str = rx.GetBuffer(); if (str == "VrFcB") { rx.TxString("ACK\n"); // "ACK" を送り返す wait_ms(10); rx.Baud(115200); // 以降は 115,200 baud } else { if (isalpha(str[0])) Select(str); else NumericCtrl(str); } } } } // 有効,無効,出力 On/Off に対応する処理の選択 void Select(string str) { if (str == "ACTIVE") filter_.Validate(); // フィルタ処理有効 if (str == "THROUGH") filter_.Invalidate(); // フィルタ処理無効 if (str == "ON") filter_.SetOn(); // 出力を On if (str == "OFF") filter_.SetOff(); // 出力を Off } // フィルタ係数の設定 void NumericCtrl(string str) { static char typeOld = 'L'; // 最初は LPF char type; // LPF/HPF の区別 const int N = 5; // 次数の 1/2 const int L0 = 13; // 一つの係数当たりの文字数 float a1, a2; Biquad::Coefs cfs[N]; // 転送された文字列から変換された係数 float b1 = atof(str.substr(0, 2).c_str()); type = (b1 > 0)? 'L' : 'H'; for (int n=0; n<N; n++) { a1 = atof(str.substr(n*2*L0+2, L0).c_str()); a2 = atof(str.substr((n*2+1)*L0+2, L0).c_str()); cfs[n] = (Biquad::Coefs){a1, a2, b1, 1}; } float g0 = atof(str.substr(N*2*L0+2, L0).c_str()); filter_.SetCoefficients(2*N, cfs, g0); // 係数設定 // LPF と HPF が切り替わった場合フィルタの遅延器をクリア if (type != typeOld) filter_.Clear(); typeOld = type; }