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

Committer:
MikamiUitOpen
Date:
Wed Nov 28 12:45:18 2018 +0000
Revision:
1:cd42ecc1e174
Parent:
0:ad30ac2b412b
2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:ad30ac2b412b 1 //-----------------------------------------------------------
MikamiUitOpen 0:ad30ac2b412b 2 // 出力を 4 倍にアップサンプリングするクラス
MikamiUitOpen 0:ad30ac2b412b 3 // Nucleo-F446RE 専用
MikamiUitOpen 0:ad30ac2b412b 4 // 補間処理で使うフィルタとして,直線位相 FIR フィルタを使用
MikamiUitOpen 0:ad30ac2b412b 5 //
MikamiUitOpen 0:ad30ac2b412b 6 // 2018/07/03, Copyright (c) 2018 MIKAMI, Naoki
MikamiUitOpen 0:ad30ac2b412b 7 //-----------------------------------------------------------
MikamiUitOpen 0:ad30ac2b412b 8
MikamiUitOpen 0:ad30ac2b412b 9 #include "F446_LinearPhase.hpp"
MikamiUitOpen 0:ad30ac2b412b 10 using namespace Mikami;
MikamiUitOpen 0:ad30ac2b412b 11
MikamiUitOpen 0:ad30ac2b412b 12 F446_LinearPhase::F446_LinearPhase(int order, const float hk1[],
MikamiUitOpen 0:ad30ac2b412b 13 const float hk2[], const float hk3[])
MikamiUitOpen 0:ad30ac2b412b 14 : indexW_(0), ORDER_(order), FIR_COUNT_(order/4),
MikamiUitOpen 0:ad30ac2b412b 15 CENTER_(order/(FACTOR_*2)), un_(order/4, 0.0f),
MikamiUitOpen 0:ad30ac2b412b 16 h1_(order/4), h2_(order/4), h3_(order/4)
MikamiUitOpen 0:ad30ac2b412b 17 {
MikamiUitOpen 0:ad30ac2b412b 18 if (hk1 == NULL)
MikamiUitOpen 0:ad30ac2b412b 19 {
MikamiUitOpen 0:ad30ac2b412b 20 h1_.Assign(HK1_);
MikamiUitOpen 0:ad30ac2b412b 21 h2_.Assign(HK2_);
MikamiUitOpen 0:ad30ac2b412b 22 h3_.Assign(HK3_);
MikamiUitOpen 0:ad30ac2b412b 23 }
MikamiUitOpen 0:ad30ac2b412b 24 else // デフォルト以外の補間用フィルタの係数を使用する
MikamiUitOpen 0:ad30ac2b412b 25 {
MikamiUitOpen 0:ad30ac2b412b 26 h1_.Assign(hk1);
MikamiUitOpen 0:ad30ac2b412b 27 h2_.Assign(hk2);
MikamiUitOpen 0:ad30ac2b412b 28 h3_.Assign(hk3);
MikamiUitOpen 0:ad30ac2b412b 29 }
MikamiUitOpen 0:ad30ac2b412b 30 }
MikamiUitOpen 0:ad30ac2b412b 31
MikamiUitOpen 0:ad30ac2b412b 32 // 標本化の実行開始
MikamiUitOpen 0:ad30ac2b412b 33 void F446_LinearPhase::Start(int frequency, PinName pin)
MikamiUitOpen 0:ad30ac2b412b 34 {
MikamiUitOpen 0:ad30ac2b412b 35 adc_ = new AdcF446(frequency*FACTOR_, pin); // AD変換器の初期化
MikamiUitOpen 0:ad30ac2b412b 36 wait_us(1000); // ある程度の待ち時間が必要
MikamiUitOpen 0:ad30ac2b412b 37 adc_->SetIntrVec(&F446_LinearPhase::AdcIsr); // ISR の設定
MikamiUitOpen 0:ad30ac2b412b 38 }
MikamiUitOpen 0:ad30ac2b412b 39
MikamiUitOpen 0:ad30ac2b412b 40 // AD変換の結果を取り出す
MikamiUitOpen 0:ad30ac2b412b 41 float F446_LinearPhase::Input()
MikamiUitOpen 0:ad30ac2b412b 42 {
MikamiUitOpen 0:ad30ac2b412b 43 while (!okIn_) {} // AD変換の結果を取り出せるまで待つ
MikamiUitOpen 0:ad30ac2b412b 44 okIn_ = false;
MikamiUitOpen 0:ad30ac2b412b 45 return xn_;
MikamiUitOpen 0:ad30ac2b412b 46 }
MikamiUitOpen 0:ad30ac2b412b 47
MikamiUitOpen 0:ad30ac2b412b 48 // 補間用フィルタを実行し,処理結果を出力用バッファへ書き込む
MikamiUitOpen 0:ad30ac2b412b 49 void F446_LinearPhase::Output(float yn)
MikamiUitOpen 0:ad30ac2b412b 50 {
MikamiUitOpen 0:ad30ac2b412b 51 un_[0] = yn; // 補間フィルタ用バッファの先頭に書き込む
MikamiUitOpen 0:ad30ac2b412b 52
MikamiUitOpen 0:ad30ac2b412b 53 buf_[ModCounter(indexW_)] = un_[CENTER_];
MikamiUitOpen 0:ad30ac2b412b 54 buf_[ModCounter(indexW_)] = Interpolator(h1_);
MikamiUitOpen 0:ad30ac2b412b 55 buf_[ModCounter(indexW_)] = Interpolator(h2_);
MikamiUitOpen 0:ad30ac2b412b 56 buf_[ModCounter(indexW_)] = Interpolator(h3_);
MikamiUitOpen 0:ad30ac2b412b 57
MikamiUitOpen 0:ad30ac2b412b 58 for (int k=FIR_COUNT_-1; k>0; k--) un_[k] = un_[k-1];
MikamiUitOpen 0:ad30ac2b412b 59 }
MikamiUitOpen 0:ad30ac2b412b 60
MikamiUitOpen 0:ad30ac2b412b 61 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
MikamiUitOpen 0:ad30ac2b412b 62 void F446_LinearPhase::AdcIsr()
MikamiUitOpen 0:ad30ac2b412b 63 {
MikamiUitOpen 0:ad30ac2b412b 64 static int count = 0;
MikamiUitOpen 0:ad30ac2b412b 65
MikamiUitOpen 0:ad30ac2b412b 66 xn_ = adc_->Read(); // AD変換器の値を読み込む
MikamiUitOpen 0:ad30ac2b412b 67 dac_.Write(buf_[ModCounter(indexR_)]); // 出力バッファの内容を DAC へ書き込む
MikamiUitOpen 0:ad30ac2b412b 68
MikamiUitOpen 0:ad30ac2b412b 69 if (count == 0) okIn_ = true; // AD変換器からの入力信号は4回に1回使う
MikamiUitOpen 0:ad30ac2b412b 70 count = ++count & MASK_FACTOR_; // 出力時に4倍にアップサンプリングするので,
MikamiUitOpen 0:ad30ac2b412b 71 // 入力を4回に1回行うための処理
MikamiUitOpen 0:ad30ac2b412b 72 }
MikamiUitOpen 0:ad30ac2b412b 73
MikamiUitOpen 0:ad30ac2b412b 74 // 補間用 FIR フィルタ
MikamiUitOpen 0:ad30ac2b412b 75 float F446_LinearPhase::Interpolator(float hk[])
MikamiUitOpen 0:ad30ac2b412b 76 {
MikamiUitOpen 0:ad30ac2b412b 77 float y = 0;
MikamiUitOpen 0:ad30ac2b412b 78 for (int n=0; n<FIR_COUNT_; n++) y = y + un_[n]*hk[n];
MikamiUitOpen 0:ad30ac2b412b 79 return y;
MikamiUitOpen 0:ad30ac2b412b 80 }
MikamiUitOpen 0:ad30ac2b412b 81
MikamiUitOpen 0:ad30ac2b412b 82 // static メンバの実体の宣言/初期化
MikamiUitOpen 0:ad30ac2b412b 83 AdcF446 *F446_LinearPhase::adc_;
MikamiUitOpen 0:ad30ac2b412b 84 DacF446 F446_LinearPhase::dac_;
MikamiUitOpen 0:ad30ac2b412b 85 Array<float> F446_LinearPhase::buf_(2*FACTOR_, 0.0f);
MikamiUitOpen 0:ad30ac2b412b 86 int F446_LinearPhase::indexR_ = FACTOR_;
MikamiUitOpen 0:ad30ac2b412b 87 float F446_LinearPhase::xn_;
MikamiUitOpen 0:ad30ac2b412b 88 __IO bool F446_LinearPhase::okIn_ = false;
MikamiUitOpen 0:ad30ac2b412b 89
MikamiUitOpen 0:ad30ac2b412b 90 // デフォルトの補間用フィルタの係数(AD 変換器の標本化周波数は 10 kHz を想定している)
MikamiUitOpen 0:ad30ac2b412b 91 // 使用窓関数 Kaiser 窓
MikamiUitOpen 0:ad30ac2b412b 92 // 標本化周波数 (kHz) 40.000000
MikamiUitOpen 0:ad30ac2b412b 93 // 次数 72
MikamiUitOpen 0:ad30ac2b412b 94 // 種類 LPF
MikamiUitOpen 0:ad30ac2b412b 95 // 遮断周波数 (kHz) 5.000000
MikamiUitOpen 0:ad30ac2b412b 96 // 減衰量 (dB) 40.00
MikamiUitOpen 0:ad30ac2b412b 97 const float F446_LinearPhase::HK1_[] = {
MikamiUitOpen 0:ad30ac2b412b 98 4.431256E-03f, -8.146596E-03f, 1.341366E-02f, -2.077330E-02f,
MikamiUitOpen 0:ad30ac2b412b 99 3.116614E-02f, -4.650688E-02f, 7.151836E-02f, -1.218529E-01f,
MikamiUitOpen 0:ad30ac2b412b 100 2.971602E-01f, 8.993316E-01f, -1.751857E-01f, 9.144896E-02f,
MikamiUitOpen 0:ad30ac2b412b 101 -5.727932E-02f, 3.802786E-02f, -2.550498E-02f, 1.678651E-02f,
MikamiUitOpen 0:ad30ac2b412b 102 -1.055827E-02f, 6.120216E-03f};
MikamiUitOpen 0:ad30ac2b412b 103 const float F446_LinearPhase::HK2_[] = {
MikamiUitOpen 0:ad30ac2b412b 104 7.405152E-03f, -1.315348E-02f, 2.125564E-02f, -3.257789E-02f,
MikamiUitOpen 0:ad30ac2b412b 105 4.868468E-02f, -7.290120E-02f, 1.139337E-01f, -2.039652E-01f,
MikamiUitOpen 0:ad30ac2b412b 106 6.338376E-01f, 6.338376E-01f, -2.039652E-01f, 1.139337E-01f,
MikamiUitOpen 0:ad30ac2b412b 107 -7.290120E-02f, 4.868468E-02f, -3.257789E-02f, 2.125564E-02f,
MikamiUitOpen 0:ad30ac2b412b 108 -1.315348E-02f, 7.405152E-03f};
MikamiUitOpen 0:ad30ac2b412b 109 const float F446_LinearPhase::HK3_[] = {
MikamiUitOpen 0:ad30ac2b412b 110 6.120216E-03f, -1.055827E-02f, 1.678651E-02f, -2.550498E-02f,
MikamiUitOpen 0:ad30ac2b412b 111 3.802786E-02f, -5.727932E-02f, 9.144896E-02f, -1.751857E-01f,
MikamiUitOpen 0:ad30ac2b412b 112 8.993316E-01f, 2.971602E-01f, -1.218529E-01f, 7.151836E-02f,
MikamiUitOpen 0:ad30ac2b412b 113 -4.650688E-02f, 3.116614E-02f, -2.077330E-02f, 1.341366E-02f,
MikamiUitOpen 0:ad30ac2b412b 114 -8.146596E-03f, 4.431256E-03f};