STM32F446 内蔵の DAC から出力する際に,補間フィルタを利用し,標本化周波数を入力の際の4倍の標本化周波数で出力するためのライブラリ.このライブラリを登録した際のプログラム: Demo_DSP_ADDA_Multirate. Library for outputting from built-in DAC in STM32F446 using interpolation filter at sampling frequency of 4 times in case of input.
Dependencies: Array_Matrix DSP_ADDA
Dependents: Demo_DSP_ADDA_Multirate DSP_AD_DA_Multirate DSP_GraphicEqualizerB DSP_VariableLHpfB ... more
Diff: MultirateLiPh.cpp
- Revision:
- 0:79c0b1e2fd10
- Child:
- 2:aa092bbc8877
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MultirateLiPh.cpp Mon May 25 06:13:53 2020 +0000 @@ -0,0 +1,74 @@ +//----------------------------------------------------------- +// 出力を 4 倍にアップサンプリングするクラス +// 補間処理で使うフィルタとして,直線位相 FIR フィルタを使用 +// +// 2020/05/25, Copyright (c) 2020 MIKAMI, Naoki +//----------------------------------------------------------- + +#include "MultirateLiPh.hpp" +using namespace Mikami; + +MultirateLiPh::MultirateLiPh() + : indexW_(0), FIR_LOOP_(ORDER_/4), CENTER_(ORDER_/(FACTOR_*2)), + un_(ORDER_/4, 0.0f), + h1_(ORDER_/4, HK1_), h2_(ORDER_/4, HK2_), h3_(ORDER_/4, HK3_) +{ + // 割り込み優先順位の設定 + NVIC_SetPriority(ADC_IRQn, 0); // ADC 終了割り込み:最優先 + NVIC_SetPriority(CAN2_TX_IRQn, 1); // ソフトウェア割り込みで使用:2番目に優先 +} + +// 標本化の実行開始 +void MultirateLiPh::Start(float fSampling, void (*Func)(), + PinName pin, ADC_TypeDef* const adc) +{ + // CAN2_TX によるソフトウェア割り込みに対応する設定 + NVIC_SetVector(CAN2_TX_IRQn, (uint32_t)Func); + NVIC_EnableIRQ(CAN2_TX_IRQn); + + // AD 変換器を使うための準備 + adc_ = new DspAdc_Intr(fSampling*FACTOR_, pin, adc); + wait_us(1000); // ある程度の待ち時間が必要 + adc_->SetIntrVec(&MultirateLiPh::AdcIsr); // AD 変換終了に対応する ISR の設定 +} + +// 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む +void MultirateLiPh::Output(float yn) +{ + un_[0] = yn; // 補間フィルタ用バッファの先頭に書き込む + + buf_[ModIndex(indexW_)] = un_[CENTER_]; + buf_[ModIndex(indexW_)] = Interpolator(h1_); + buf_[ModIndex(indexW_)] = Interpolator(h2_); + buf_[ModIndex(indexW_)] = Interpolator(h3_); + + for (int k=FIR_LOOP_-1; k>0; k--) un_[k] = un_[k-1]; +} + +// ADC 変換終了割り込みに対する割り込みサービス・ルーチン +void MultirateLiPh::AdcIsr() +{ + static int count = 0; + + xn_ = adc_->Read(); // AD変換器の値を読み込む + dac_.Write(buf_[ModIndex(indexR_)]); // 出力バッファの内容を DAC へ書き込む + + if (count == 0) // AD変換器からの入力信号は4回に1回使う + NVIC->STIR = CAN2_TX_IRQn; // ソフトウェア割込み発生,信号処理を起動 + count = ++count & MASK_FACTOR_; // 入力を4回に1回行うための処理 +} + +// 補間用 FIR フィルタ +float MultirateLiPh::Interpolator(const float hk[]) const +{ + float y = 0; + for (int n=0; n<FIR_LOOP_; n++) y += un_[n]*hk[n]; + return y; +} + +// static メンバの実体の宣言/初期化 +DspAdc_Intr *MultirateLiPh::adc_; // AD変換器のオブジェクトのポインタ +DspDac MultirateLiPh::dac_; // DA変換器のオブジェクト +Array<float> MultirateLiPh::buf_(2*FACTOR_, 0.0f); +int MultirateLiPh::indexR_ = FACTOR_; +float MultirateLiPh::xn_; \ No newline at end of file