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

F446_Multirate.cpp

Committer:
MikamiUitOpen
Date:
2018-10-11
Revision:
7:6275fe158ae8
Parent:
5:4800dd3838d6

File content as of revision 7:6275fe158ae8:

//-----------------------------------------------------------
//  出力を 4 倍にアップサンプリングするクラス:高域の補正を行う場合
//  Nucleo-F446RE 専用
//  補間処理で使うフィルタとして,縦続形構成の IIR フィルタを使用
//  
//  2018/10/11, Copyright (c) 2018 MIKAMI, Naoki
//-----------------------------------------------------------

#include "F446_Multirate.hpp"

namespace Mikami
{
    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::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()
    {
        while (!okIn_) {}   // AD変換の結果を取り出せるまで待つ
        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 値とする
        }
    }

    // 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_;
    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 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;
}