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

Dependencies:   mbed SerialTxRxIntr DSP_MultirateLinearphase

Committer:
MikamiUitOpen
Date:
Wed Mar 30 05:00:14 2022 +0000
Revision:
2:3955cb401851
Parent:
1:2d08a91b6bf2
3

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