CQエレクトロニクス・セミナで使用する遮断周波数可変の LPF/HPF のプログラム
Dependencies: mbed SerialTxRxIntr DSP_MultirateLinearphase
main.cpp
00001 //------------------------------------------------------------------ 00002 // 遮断周波数可変 IIR フィルタ(LPF, HPF) 00003 // DA 出力はアップサンプリング使用 00004 // フィルタの係数は PC で計算し,それをマイコン側に転送するタイプ 00005 // 00006 // ● PC 側のプログラム: F446_VariableLHpfB 00007 // ● ボーレート: 最初: 9600 baud 00008 // 通信確立後: 115200 baud 00009 // ● 入力: A1 00010 // ● 出力: A2 00011 // 00012 // 2022/03/30, Copyright (c) 2022 MIKAMI, Naoki 00013 //------------------------------------------------------------------ 00014 00015 #include "MultirateLiPh.hpp" // DA でアップサンプリング 00016 #include "SerialRxTxIntr.hpp" 00017 #include "IirVariable.hpp" 00018 #include <cctype> // isalpha(), isdigit() で使用 00019 using namespace Mikami; 00020 00021 const float FS_ = 44.1f; // 入力の標本化周波数: 44.1 kHz 00022 MultirateLiPh myAdDa_(FS_); // 出力標本化周波数を4倍にするオブジェクト 00023 00024 // 縦続形 IIR フィルタによる可変フィルタのオブジェクト, 次数: 10 次 00025 VariableIir filter_; 00026 00027 void Select(string str); // 有効,無効,出力 On/Off に対応する処理の選択 00028 void NumericCtrl(string str); // フィルタ係数の更新 00029 00030 // LPF/HPF の信号処理 00031 void AdcIsr() 00032 { 00033 float xn = myAdDa_.Input(); // 入力 00034 float yn = filter_.Execute(xn); // IIR フィルタの実行 00035 myAdDa_.Output(yn); // 出力 00036 } 00037 00038 int main() 00039 { 00040 SerialRxTxIntr rx(150); // PC との通信用,バッファサイズ:150,9600 baud 00041 00042 NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 00043 NVIC_SetPriority(USART2_IRQn, 1); 00044 00045 myAdDa_.Start(&AdcIsr); // 標本化を開始する 00046 while (true) 00047 { 00048 if (rx.IsEol()) // PC からの指令に対応する処理 00049 { 00050 string str = rx.GetBuffer(); 00051 if (str == "VrFcB") 00052 { 00053 rx.TxString("ACK\n"); // "ACK" を送り返す 00054 wait_ms(10); 00055 rx.Baud(115200); // 以降は 115,200 baud 00056 } 00057 else 00058 { 00059 if (isalpha(str[0])) Select(str); 00060 else NumericCtrl(str); 00061 } 00062 } 00063 } 00064 } 00065 00066 // 有効,無効,出力 On/Off に対応する処理の選択 00067 void Select(string str) 00068 { 00069 if (str == "ACTIVE") filter_.Validate(); // フィルタ処理有効 00070 if (str == "THROUGH") filter_.Invalidate(); // フィルタ処理無効 00071 if (str == "ON") filter_.SetOn(); // 出力を On 00072 if (str == "OFF") filter_.SetOff(); // 出力を Off 00073 } 00074 00075 // フィルタ係数の設定 00076 void NumericCtrl(string str) 00077 { 00078 static char typeOld = 'L'; // 最初は LPF 00079 char type; // LPF/HPF の区別 00080 00081 const int N = 5; // 次数の 1/2 00082 const int L0 = 13; // 一つの係数当たりの文字数 00083 float a1, a2; 00084 Biquad::Coefs cfs[N]; // 転送された文字列から変換された係数 00085 00086 float b1 = atof(str.substr(0, 2).c_str()); 00087 type = (b1 > 0)? 'L' : 'H'; 00088 00089 for (int n=0; n<N; n++) 00090 { 00091 a1 = atof(str.substr(n*2*L0+2, L0).c_str()); 00092 a2 = atof(str.substr((n*2+1)*L0+2, L0).c_str()); 00093 cfs[n] = (Biquad::Coefs){a1, a2, b1, 1}; 00094 } 00095 float g0 = atof(str.substr(N*2*L0+2, L0).c_str()); 00096 filter_.SetCoefficients(2*N, cfs, g0); // 係数設定 00097 00098 // LPF と HPF が切り替わった場合フィルタの遅延器をクリア 00099 if (type != typeOld) filter_.Clear(); 00100 typeOld = type; 00101 }
Generated on Sat Jul 23 2022 01:01:05 by 1.7.2