Nucleo-F446RE 内蔵の AD/DA を使うためのライブラリ.DA からの出力は,標本化周波数の4倍のレートで行う. このライブラリを登録した際のプログラム: Demo_F446_AD_DA_Multirate. Library for built-in ADC and DAC in Nucleo-F446RE. Sampling rate for DAC is four times of that for ADC.
Dependents: F446_UpSampling_GraphicEqualizer F446_UpSampling_ReverbSystem F446_UpSampling_FrqShifter_Weaver Demo_F446_AD_DA_Multirate ... more
Diff: F446_Multirate.cpp
- Revision:
- 7:6275fe158ae8
- Parent:
- 5:4800dd3838d6
--- a/F446_Multirate.cpp Mon Jul 09 03:48:50 2018 +0000 +++ b/F446_Multirate.cpp Thu Oct 11 11:42:48 2018 +0000 @@ -3,99 +3,102 @@ // Nucleo-F446RE 専用 // 補間処理で使うフィルタとして,縦続形構成の IIR フィルタを使用 // -// 2018/06/15, Copyright (c) 2018 MIKAMI, Naoki +// 2018/10/11, Copyright (c) 2018 MIKAMI, Naoki //----------------------------------------------------------- #include "F446_Multirate.hpp" -F446_Multirate::F446_Multirate(int order, const Biquad::Coefs ck[], float g0) - : indexW_(0) -{ - // 補間用フィルタの初期化 - if (order == -1) // デフォルトの補間用フィルタを使用 - interpolator_ = new IirCascade(8, HK_, G0_); - else // コンストラクタの引数で与えられた係数の補間用フィルタを使用 - interpolator_ = new IirCascade(order, ck, g0); -} - -// 標本化の実行開始 -void F446_Multirate::Start(int frequency, PinName pin) -{ - adc_ = new AdcF446(frequency*FACTOR_, pin); // AD変換器の初期化 - wait_us(1000); // ある程度の待ち時間が必要 - adc_->SetIntrVec(&F446_Multirate::AdcIsr); // ISR の設定 -} - -// AD変換の結果を取り出す -float F446_Multirate::Input() +namespace Mikami { - while (!okIn_) {} // AD変換の結果を取り出せるまで待つ - okIn_ = false; - return xn_; -} + F446_Multirate::F446_Multirate(int order, const Biquad hk[], float g0) + : indexW_(0) + { + // 補間用フィルタの初期化 + if (order == -1) // デフォルトの補間用フィルタを使用 + interpolator_ = new IirCascade(8, HK_, G0_); + else // コンストラクタの引数で与えられた係数の補間用フィルタを使用 + interpolator_ = new IirCascade(order, hk, g0); + } -// 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む -void F446_Multirate::Output(float yn) -{ - for (int n=0; n<FACTOR_; n++) + // 標本化の実行開始 + void F446_Multirate::Start(int frequency, PinName pin) + { + adc_ = new AdcF446(frequency*FACTOR_, pin); // AD変換器の初期化 + wait_us(1000); // ある程度の待ち時間が必要 + adc_->SetIntrVec(&F446_Multirate::AdcIsr); // ISR の設定 + } + + // AD変換の結果を取り出す + float F446_Multirate::Input() { - buf_[ModCounter(indexW_)] = interpolator_->Execute(yn); - yn = 0; // 2回目からは補間用フィルタの入力を 0 値とする + while (!okIn_) {} // AD変換の結果を取り出せるまで待つ + okIn_ = false; + return xn_; } -} -// ADC 変換終了割り込みに対する割り込みサービス・ルーチン -void F446_Multirate::AdcIsr() -{ - static int count = 0; + // 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む + void F446_Multirate::Output(float yn) + { + for (int n=0; n<FACTOR_; n++) + { + buf_[ModCounter(indexW_)] = interpolator_->Execute(yn); + yn = 0; // 2回目からは補間用フィルタの入力を 0 値とする + } + } - xn_ = adc_->Read(); // AD変換器の値を読み込む - dac_.Write(buf_[ModCounter(indexR_)]); // 出力バッファの内容を DAC へ書き込む + // ADC 変換終了割り込みに対する割り込みサービス・ルーチン + void F446_Multirate::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回行うための処理 -} + if (count == 0) okIn_ = true; // AD変換器からの入力信号は4回に1回使う + count = ++count & MASK_FACTOR_; // 出力時に4倍にアップサンプリングするので, + // 入力を4回に1回行うための処理 + } -// static メンバの実体の宣言/初期化 -AdcF446 *F446_Multirate::adc_; -DacF446 F446_Multirate::dac_; -Array<float> F446_Multirate::buf_(2*FACTOR_, 0.0f); -int F446_Multirate::indexR_ = FACTOR_; -float F446_Multirate::xn_; -__IO bool F446_Multirate::okIn_ = false; + // static メンバの実体の宣言/初期化 + AdcF446 *F446_Multirate::adc_; + DacF446 F446_Multirate::dac_; + Array<float> F446_Multirate::buf_(2*FACTOR_, 0.0f); + int F446_Multirate::indexR_ = FACTOR_; + float F446_Multirate::xn_; + __IO bool F446_Multirate::okIn_ = false; -// 補間用フィルタの係数(AD 変換器の標本化周波数は 10 kHz を想定している) -// -// 補間用フィルタ全体は biquad フィルタ4段とする. -// 最初の3段は 6 次の LPF を使用し,最後の1段は,外付けの 1 次のアナログフィル -// タによる,高域の低下分を補正するための 2 次の LPF を使用. -// 利得定数は,両者の利得定数の積に sqrt(2) を乗算した.これは 2 次のフィルタの -// 利得の最大値が 1 倍のため,この利得の最大値を sqrt(2) 倍にするため -//-------------------------------- -// 1 ~ 3 段目 -// 低域通過フィルタ -// 連立チェビシェフ特性 -// 次数 : 6 次 -// 標本化周波数: 40.00 kHz -// 遮断周波数 : 4.80 kHz -// 通過域のリップル: 0.50 dB -// 阻止域の減衰量 :35.00 dB -//-------------------------------- -const Biquad::Coefs F446_Multirate::HK_[] = { - {1.370091E+00f, -5.353523E-01f, 2.500437E-01f, 1.0f}, // 1段目 - {1.402004E+00f, -8.228448E-01f, -1.182903E+00f, 1.0f}, // 2段目 - {1.426447E+00f, -9.646314E-01f, -1.362836E+00f, 1.0f}, // 3段目 -//-------------------------------- -// 4 段目:高域補正用フィルタ -// 低域通過フィルタ -// 連立チェビシェフ特性 -// 次数 : 2 次 -// 標本化周波数: 40.00 kHz -// 遮断周波数 : 5.20 kHz -// 通過域のリップル: 3.00 dB -// 阻止域の減衰量 : 8.00 dB -//-------------------------------- - {1.240986E+00f, -7.647923E-01f, -1.053681E+00f, 1.0f}}; // 4段目 -// 利得定数 -const float F446_Multirate::G0_ = FACTOR_*3.016500E-02f*3.918621E-01f*1.41421f; + // 補間用フィルタの係数(AD 変換器の標本化周波数は 10 kHz を想定している) + // + // 補間用フィルタ全体は biquad フィルタ4段とする. + // 最初の3段は 6 次の LPF を使用し,最後の1段は,外付けの 1 次のアナログフィル + // タによる,高域の低下分を補正するための 2 次の LPF を使用. + // 利得定数は,両者の利得定数の積に sqrt(2) を乗算した.これは 2 次のフィルタの + // 利得の最大値が 1 倍のため,この利得の最大値を sqrt(2) 倍にするため + //-------------------------------- + // 1 ~ 3 段目 + // 低域通過フィルタ + // 連立チェビシェフ特性 + // 次数 : 6 次 + // 標本化周波数: 40.00 kHz + // 遮断周波数 : 4.80 kHz + // 通過域のリップル: 0.50 dB + // 阻止域の減衰量 :35.00 dB + //-------------------------------- + const Biquad F446_Multirate::HK_[] = { + Biquad(1.370091E+00f, -5.353523E-01f, 2.500437E-01f, 1.0f), // 1段目 + Biquad(1.402004E+00f, -8.228448E-01f, -1.182903E+00f, 1.0f), // 2段目 + Biquad(1.426447E+00f, -9.646314E-01f, -1.362836E+00f, 1.0f), // 3段目 + //-------------------------------- + // 4 段目:高域補正用フィルタ + // 低域通過フィルタ + // 連立チェビシェフ特性 + // 次数 : 2 次 + // 標本化周波数: 40.00 kHz + // 遮断周波数 : 5.20 kHz + // 通過域のリップル: 3.00 dB + // 阻止域の減衰量 : 8.00 dB + //-------------------------------- + Biquad(1.240986E+00f, -7.647923E-01f, -1.053681E+00f, 1.0f)}; // 4段目 + // 利得定数 + const float F446_Multirate::G0_ = FACTOR_*3.016500E-02f*3.918621E-01f*1.41421f; +}