Nucleo-F446RE 内蔵の AD/DA を使うためのライブラリ.DA からの出力は,標本化周波数の4倍のレートで行う.出力の補間フィルタには直線位相の FIR フィルタを使用. このライブラリを登録した際のプログラム: Demo_F446_AD_DA_MultirateLinearPhase. Library for built-in ADC and DAC in Nucleo-F446RE. Sampling rate for DAC is four times of that for ADC. Interpolation filter for output is linear-phase FIR filter.
Dependents: Demo_F446_AD_DA_MultirateLinearPhase
F446_LinearPhase.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2018-07-03
- Revision:
- 0:ad30ac2b412b
File content as of revision 0:ad30ac2b412b:
//----------------------------------------------------------- // 出力を 4 倍にアップサンプリングするクラス // Nucleo-F446RE 専用 // 補間処理で使うフィルタとして,直線位相 FIR フィルタを使用 // // 2018/07/03, Copyright (c) 2018 MIKAMI, Naoki //----------------------------------------------------------- #include "F446_LinearPhase.hpp" using namespace Mikami; F446_LinearPhase::F446_LinearPhase(int order, const float hk1[], const float hk2[], const float hk3[]) : indexW_(0), ORDER_(order), FIR_COUNT_(order/4), CENTER_(order/(FACTOR_*2)), un_(order/4, 0.0f), h1_(order/4), h2_(order/4), h3_(order/4) { if (hk1 == NULL) { h1_.Assign(HK1_); h2_.Assign(HK2_); h3_.Assign(HK3_); } else // デフォルト以外の補間用フィルタの係数を使用する { h1_.Assign(hk1); h2_.Assign(hk2); h3_.Assign(hk3); } } // 標本化の実行開始 void F446_LinearPhase::Start(int frequency, PinName pin) { adc_ = new AdcF446(frequency*FACTOR_, pin); // AD変換器の初期化 wait_us(1000); // ある程度の待ち時間が必要 adc_->SetIntrVec(&F446_LinearPhase::AdcIsr); // ISR の設定 } // AD変換の結果を取り出す float F446_LinearPhase::Input() { while (!okIn_) {} // AD変換の結果を取り出せるまで待つ okIn_ = false; return xn_; } // 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む void F446_LinearPhase::Output(float yn) { un_[0] = yn; // 補間フィルタ用バッファの先頭に書き込む buf_[ModCounter(indexW_)] = un_[CENTER_]; buf_[ModCounter(indexW_)] = Interpolator(h1_); buf_[ModCounter(indexW_)] = Interpolator(h2_); buf_[ModCounter(indexW_)] = Interpolator(h3_); for (int k=FIR_COUNT_-1; k>0; k--) un_[k] = un_[k-1]; } // ADC 変換終了割り込みに対する割り込みサービス・ルーチン void F446_LinearPhase::AdcIsr() { static int count = 0; xn_ = adc_->Read(); // AD変換器の値を読み込む dac_.Write(buf_[ModCounter(indexR_)]); // 出力バッファの内容を DAC へ書き込む if (count == 0) okIn_ = true; // AD変換器からの入力信号は4回に1回使う count = ++count & MASK_FACTOR_; // 出力時に4倍にアップサンプリングするので, // 入力を4回に1回行うための処理 } // 補間用 FIR フィルタ float F446_LinearPhase::Interpolator(float hk[]) { float y = 0; for (int n=0; n<FIR_COUNT_; n++) y = y + un_[n]*hk[n]; return y; } // static メンバの実体の宣言/初期化 AdcF446 *F446_LinearPhase::adc_; DacF446 F446_LinearPhase::dac_; Array<float> F446_LinearPhase::buf_(2*FACTOR_, 0.0f); int F446_LinearPhase::indexR_ = FACTOR_; float F446_LinearPhase::xn_; __IO bool F446_LinearPhase::okIn_ = false; // デフォルトの補間用フィルタの係数(AD 変換器の標本化周波数は 10 kHz を想定している) // 使用窓関数 Kaiser 窓 // 標本化周波数 (kHz) 40.000000 // 次数 72 // 種類 LPF // 遮断周波数 (kHz) 5.000000 // 減衰量 (dB) 40.00 const float F446_LinearPhase::HK1_[] = { 4.431256E-03f, -8.146596E-03f, 1.341366E-02f, -2.077330E-02f, 3.116614E-02f, -4.650688E-02f, 7.151836E-02f, -1.218529E-01f, 2.971602E-01f, 8.993316E-01f, -1.751857E-01f, 9.144896E-02f, -5.727932E-02f, 3.802786E-02f, -2.550498E-02f, 1.678651E-02f, -1.055827E-02f, 6.120216E-03f}; const float F446_LinearPhase::HK2_[] = { 7.405152E-03f, -1.315348E-02f, 2.125564E-02f, -3.257789E-02f, 4.868468E-02f, -7.290120E-02f, 1.139337E-01f, -2.039652E-01f, 6.338376E-01f, 6.338376E-01f, -2.039652E-01f, 1.139337E-01f, -7.290120E-02f, 4.868468E-02f, -3.257789E-02f, 2.125564E-02f, -1.315348E-02f, 7.405152E-03f}; const float F446_LinearPhase::HK3_[] = { 6.120216E-03f, -1.055827E-02f, 1.678651E-02f, -2.550498E-02f, 3.802786E-02f, -5.727932E-02f, 9.144896E-02f, -1.751857E-01f, 8.993316E-01f, 2.971602E-01f, -1.218529E-01f, 7.151836E-02f, -4.650688E-02f, 3.116614E-02f, -2.077330E-02f, 1.341366E-02f, -8.146596E-03f, 4.431256E-03f};