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