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.

Dependencies:   Array_Matrix

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