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.

Dependencies:   Array_Matrix

Dependents:   F446_UpSampling_GraphicEqualizer F446_UpSampling_ReverbSystem F446_UpSampling_FrqShifter_Weaver Demo_F446_AD_DA_Multirate ... more

Revision:
0:2447a7d225b1
Child:
1:abd7e93549b2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_Multirate.cpp	Wed May 16 01:40:50 2018 +0000
@@ -0,0 +1,97 @@
+//-----------------------------------------------------------
+//  出力を 4 倍にアップサンプリングするクラス:高域の補正を行う場合
+//  Nucleo-F446RE 専用
+//  
+//  2018/05/15, Copyright (c) 2018 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#include "F446_Multirate.hpp"
+
+F446_Multirate::F446_Multirate() : indexW_(0)
+{
+// 補間用フィルタの設定
+// 全体は 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 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 G0 = FACTOR_*3.016500E-02f*3.918621E-01f*sqrtf(2);  // 利得定数
+    interpolator_ = new IirCascade(8, HK, G0);  // 補間用フィルタの初期化
+
+    NVIC_SetPriority(ADC_IRQn, 0);      // ADC 終了割り込み:最優先
+    NVIC_SetPriority(USART2_IRQn, 1);   // USART2 割り込み:次に優先    
+}
+
+// AD 変換終了割り込みを使えるようにする
+void F446_Multirate::SetIntr(int frequency)
+{
+    adc_ = new AdcF446(frequency*FACTOR_);      // AD変換器の初期化
+    wait_us(1000);    // ある程度の待ち時間が必要
+    adc_->SetIntrVec(&F446_Multirate::AdcIsr);  // ISR の設定
+}
+
+// AD変換の結果を取り出す
+float F446_Multirate::Input()
+{
+    while (!okIn_) {}               // AD変換の結果を取り出せるまで待つ
+    NVIC_DisableIRQ(USART2_IRQn);   // Output() を実行するまで USART2 割込みを禁止
+    okIn_ = false;
+    return xn_;
+}
+
+// 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む
+void F446_Multirate::Output(float yn)
+{
+    for (int n=0; n<FACTOR_; n++)
+    {
+        buf_[ModCounter(indexW_)] = interpolator_->Execute(yn);
+        yn = 0;     // 2回目からは補間用フィルタの入力を 0 値とする
+    }
+    NVIC_EnableIRQ(USART2_IRQn);    // USART2 割込みを有効にする
+}
+
+// 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回行うための処理
+}
+
+// static メンバの実体の宣言/初期化
+AdcF446 *F446_Multirate::adc_;
+DacF446 F446_Multirate::dac_;
+Array<float> F446_Multirate::buf_(2*FACTOR_, 0.0f);
+int F446_Multirate::indexR_ = FACTOR_ - 1;
+float F446_Multirate::xn_;
+__IO bool F446_Multirate::okIn_ = false;