CQエレクトロニクス・セミナで使用する遮断周波数可変の LPF/HPF のプログラム

Dependencies:   mbed SerialTxRxIntr DSP_MultirateLinearphase

Committer:
MikamiUitOpen
Date:
Fri Feb 25 02:26:41 2022 +0000
Revision:
0:f1e2a221b526
Child:
1:2d08a91b6bf2
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:f1e2a221b526 1 //------------------------------------------------------------------
MikamiUitOpen 0:f1e2a221b526 2 // 遮断周波数可変 IIR フィルタ(LPF, HPF)
MikamiUitOpen 0:f1e2a221b526 3 // DA 出力はアップサンプリング使用
MikamiUitOpen 0:f1e2a221b526 4 //
MikamiUitOpen 0:f1e2a221b526 5 // PC 側のプログラム: F446_VariableLHpfB
MikamiUitOpen 0:f1e2a221b526 6 //
MikamiUitOpen 0:f1e2a221b526 7 // 2022/02/21, Copyright (c) 2022 MIKAMI, Naoki
MikamiUitOpen 0:f1e2a221b526 8 //------------------------------------------------------------------
MikamiUitOpen 0:f1e2a221b526 9
MikamiUitOpen 0:f1e2a221b526 10 #include "MultirateLiPh.hpp" // DA でアップサンプリング
MikamiUitOpen 0:f1e2a221b526 11 #include "SerialRxTxIntr.hpp"
MikamiUitOpen 0:f1e2a221b526 12 #include "IirVariable.hpp"
MikamiUitOpen 0:f1e2a221b526 13 #include <cctype> // isalpha(), isdigit() で使用
MikamiUitOpen 0:f1e2a221b526 14 using namespace Mikami;
MikamiUitOpen 0:f1e2a221b526 15
MikamiUitOpen 0:f1e2a221b526 16 const float FS_ = 44.1f; // 入力の標本化周波数: 44.1 kHz
MikamiUitOpen 0:f1e2a221b526 17 MultirateLiPh myAdDa_(FS_); // 出力標本化周波数を4倍にするオブジェクト
MikamiUitOpen 0:f1e2a221b526 18
MikamiUitOpen 0:f1e2a221b526 19 // 縦続形 IIR フィルタによる可変フィルタのオブジェクト, 次数: 10 次
MikamiUitOpen 0:f1e2a221b526 20 VariableIir filter_;
MikamiUitOpen 0:f1e2a221b526 21
MikamiUitOpen 0:f1e2a221b526 22 void Select(string str); // 有効,無効,出力 On/Off に対応する処理の選択
MikamiUitOpen 0:f1e2a221b526 23 void NumericCtrl(string str); // フィルタ係数の更新
MikamiUitOpen 0:f1e2a221b526 24
MikamiUitOpen 0:f1e2a221b526 25 // LPF/HPF の信号処理
MikamiUitOpen 0:f1e2a221b526 26 void AdcIsr()
MikamiUitOpen 0:f1e2a221b526 27 {
MikamiUitOpen 0:f1e2a221b526 28 float xn = myAdDa_.Input(); // 入力
MikamiUitOpen 0:f1e2a221b526 29 float yn = filter_.Execute(xn); // IIR フィルタの実行
MikamiUitOpen 0:f1e2a221b526 30 myAdDa_.Output(yn); // 出力
MikamiUitOpen 0:f1e2a221b526 31 }
MikamiUitOpen 0:f1e2a221b526 32
MikamiUitOpen 0:f1e2a221b526 33 int main()
MikamiUitOpen 0:f1e2a221b526 34 {
MikamiUitOpen 0:f1e2a221b526 35 SerialRxTxIntr rx(150); // PC との通信用,バッファサイズ:150,9600 baud
MikamiUitOpen 0:f1e2a221b526 36
MikamiUitOpen 0:f1e2a221b526 37 NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高
MikamiUitOpen 0:f1e2a221b526 38 NVIC_SetPriority(USART2_IRQn, 1);
MikamiUitOpen 0:f1e2a221b526 39
MikamiUitOpen 0:f1e2a221b526 40 myAdDa_.Start(&AdcIsr); // 標本化を開始する
MikamiUitOpen 0:f1e2a221b526 41 while (true)
MikamiUitOpen 0:f1e2a221b526 42 {
MikamiUitOpen 0:f1e2a221b526 43 if (rx.IsEol()) // PC からの指令に対応する処理
MikamiUitOpen 0:f1e2a221b526 44 {
MikamiUitOpen 0:f1e2a221b526 45 string str = rx.GetBuffer();
MikamiUitOpen 0:f1e2a221b526 46 if (str == "VrFcB")
MikamiUitOpen 0:f1e2a221b526 47 {
MikamiUitOpen 0:f1e2a221b526 48 rx.TxString("ACK\n"); // "ACK" を送り返す
MikamiUitOpen 0:f1e2a221b526 49 wait_ms(10);
MikamiUitOpen 0:f1e2a221b526 50 rx.Baud(115300); // 以降は 115,300 baud
MikamiUitOpen 0:f1e2a221b526 51 }
MikamiUitOpen 0:f1e2a221b526 52 else
MikamiUitOpen 0:f1e2a221b526 53 {
MikamiUitOpen 0:f1e2a221b526 54 if (isalpha(str[0])) Select(str);
MikamiUitOpen 0:f1e2a221b526 55 else NumericCtrl(str);
MikamiUitOpen 0:f1e2a221b526 56 }
MikamiUitOpen 0:f1e2a221b526 57 }
MikamiUitOpen 0:f1e2a221b526 58 }
MikamiUitOpen 0:f1e2a221b526 59 }
MikamiUitOpen 0:f1e2a221b526 60
MikamiUitOpen 0:f1e2a221b526 61 // 有効,無効,出力 On/Off に対応する処理の選択
MikamiUitOpen 0:f1e2a221b526 62 void Select(string str)
MikamiUitOpen 0:f1e2a221b526 63 {
MikamiUitOpen 0:f1e2a221b526 64 if (str == "ACTIVE") filter_.Validate(); // フィルタ処理有効
MikamiUitOpen 0:f1e2a221b526 65 if (str == "THROUGH") filter_.Invalidate(); // フィルタ処理無効
MikamiUitOpen 0:f1e2a221b526 66 if (str == "ON") filter_.SetOn(); // 出力を On
MikamiUitOpen 0:f1e2a221b526 67 if (str == "OFF") filter_.SetOff(); // 出力を Off
MikamiUitOpen 0:f1e2a221b526 68 }
MikamiUitOpen 0:f1e2a221b526 69
MikamiUitOpen 0:f1e2a221b526 70 // フィルタ係数の設定
MikamiUitOpen 0:f1e2a221b526 71 void NumericCtrl(string str)
MikamiUitOpen 0:f1e2a221b526 72 {
MikamiUitOpen 0:f1e2a221b526 73 static char typeOld = 'L'; // 最初は LPF
MikamiUitOpen 0:f1e2a221b526 74 char type; // LPF/HPF の区別
MikamiUitOpen 0:f1e2a221b526 75
MikamiUitOpen 0:f1e2a221b526 76 const int N = 5; // 次数の 1/2
MikamiUitOpen 0:f1e2a221b526 77 const int L0 = 13; // 一つの係数当たりの文字数
MikamiUitOpen 0:f1e2a221b526 78 float a1, a2;
MikamiUitOpen 0:f1e2a221b526 79 Biquad::Coefs cfs[N]; // 転送された文字列から変換された係数
MikamiUitOpen 0:f1e2a221b526 80
MikamiUitOpen 0:f1e2a221b526 81 float b1 = atof(str.substr(0, 2).c_str());
MikamiUitOpen 0:f1e2a221b526 82 type = (b1 > 0)? 'L' : 'H';
MikamiUitOpen 0:f1e2a221b526 83
MikamiUitOpen 0:f1e2a221b526 84 for (int n=0; n<N; n++)
MikamiUitOpen 0:f1e2a221b526 85 {
MikamiUitOpen 0:f1e2a221b526 86 a1 = atof(str.substr(n*2*L0+2, L0).c_str());
MikamiUitOpen 0:f1e2a221b526 87 a2 = atof(str.substr((n*2+1)*L0+2, L0).c_str());
MikamiUitOpen 0:f1e2a221b526 88 cfs[n] = (Biquad::Coefs){a1, a2, b1, 1};
MikamiUitOpen 0:f1e2a221b526 89 }
MikamiUitOpen 0:f1e2a221b526 90 float g0 = atof(str.substr(N*2*L0+2, L0).c_str());
MikamiUitOpen 0:f1e2a221b526 91 filter_.SetCoefficients(2*N, cfs, g0); // 係数設定
MikamiUitOpen 0:f1e2a221b526 92
MikamiUitOpen 0:f1e2a221b526 93 // LPF と HPF が切り替わった場合フィルタの遅延器をクリア
MikamiUitOpen 0:f1e2a221b526 94 if (type != typeOld) filter_.Clear();
MikamiUitOpen 0:f1e2a221b526 95 typeOld = type;
MikamiUitOpen 0:f1e2a221b526 96 }