CQエレクトロニクス・セミナで使用する遮断周波数可変の LPF/HPF のプログラム
Dependencies: mbed SerialTxRxIntr DSP_MultirateLinearphase
main.cpp@0:f1e2a221b526, 2022-02-25 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Fri Feb 25 02:26:41 2022 +0000
- Revision:
- 0:f1e2a221b526
- Child:
- 1:2d08a91b6bf2
1
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 | 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 | } |