CQエレクトロニクス・セミナで使用する遮断周波数可変の LPF/HPF のプログラム
Dependencies: mbed SerialTxRxIntr DSP_MultirateLinearphase
main.cpp@2:3955cb401851, 2022-03-30 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Wed Mar 30 05:00:14 2022 +0000
- Revision:
- 2:3955cb401851
- Parent:
- 1:2d08a91b6bf2
3
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 | 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 | } |