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_LPF_HPF_Variable Demo_F446_AD_DA_Multirate Demo_F446_AD_DA_Ctrl

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Thu Oct 11 11:42:48 2018 +0000
Parent:
6:a14d7f0bc3f5
Commit message:
8

Changed in this revision

Biquad.hpp Show annotated file Show diff for this revision Revisions of this file
F446_ADC.cpp Show annotated file Show diff for this revision Revisions of this file
F446_Multirate.cpp Show annotated file Show diff for this revision Revisions of this file
F446_Multirate.hpp Show annotated file Show diff for this revision Revisions of this file
IIR_Cascade.hpp Show annotated file Show diff for this revision Revisions of this file
--- a/Biquad.hpp	Mon Jul 09 03:48:50 2018 +0000
+++ b/Biquad.hpp	Thu Oct 11 11:42:48 2018 +0000
@@ -2,7 +2,7 @@
 // 縦続形 IIR フィルタの構成要素として使う 2 次の IIR フィルタ
 //      b0 は 1 と仮定している
 //
-// 2018/04/19, Copyright (c) 2017 MIKAMI, Naoki
+// 2018/10/11, Copyright (c) 2017 MIKAMI, Naoki
 //--------------------------------------------------------------
 
 #ifndef IIR_BIQUAD_HPP
@@ -11,55 +11,55 @@
 #include "mbed.h"
 
 // 2 次の IIR フィルタ
-class Biquad
+namespace Mikami
 {
-public:
-    // フィルタの係数をまとめて扱うための構造体
-    struct Coefs { float a1, a2, b1, b2; };
-
-    // デフォルト・コンストラクタ
-    //      係数は構造体 Ceofs で与える
-    Biquad(const Coefs ck = (Coefs){0, 0, 0, 0})
-        : a1_(ck.a1), a2_(ck.a2), b1_(ck.b1), b2_(ck.b2)
-    { Clear(); }       
+    class Biquad
+    {
+    public:
+        // フィルタの係数をまとめて扱うための構造体
+        struct Coefs { float a1, a2, b1, b2; };
 
-    // 係数を個別に与えるコンストラクタ
-    Biquad(float a1, float a2, float b1, float b2)
-        : a1_(a1), a2_(a2), b1_(b1), b2_(b2)
-    { Clear(); }       
+        // デフォルト・コンストラクタ
+        //      係数は構造体 Ceofs で与える
+        Biquad(const Coefs ck = (Coefs){0, 0, 0, 0})
+            : a1_(ck.a1), a2_(ck.a2), b1_(ck.b1), b2_(ck.b2)
+        { Clear(); }       
 
-    // 2 次のフィルタを実行する
-    float Execute(float xn)
-    {
-        float un = xn + a1_*un1_ + a2_*un2_;
-        float yn = un + b1_*un1_ + b2_*un2_;
-        
-        un2_ = un1_;
-        un1_ = un;
+        // 係数を個別に与えるコンストラクタ
+        Biquad(float a1, float a2, float b1, float b2)
+            : a1_(a1), a2_(a2), b1_(b1), b2_(b2)
+        { Clear(); }       
+
+        // 2 次のフィルタを実行する
+        float Execute(float xn)
+        {
+            float un = xn + a1_*un1_ + a2_*un2_;
+            float yn = un + b1_*un1_ + b2_*un2_;
         
-        return yn;
-    }
-
-    // 係数を設定する
-    void SetCoefs(const Coefs ck)
-    {
-        a1_ = ck.a1;
-        a2_ = ck.a2;
-        b1_ = ck.b1;
-        b2_ = ck.b2;
-    }
+            un2_ = un1_;
+            un1_ = un;
+        
+            return yn;
+        }
 
-    // 内部変数(遅延器)のクリア
-    void Clear() { un1_ = un2_ = 0; }
-
-private:
-    float a1_, a2_, b1_, b2_;
-    float un1_, un2_;
+        // 係数を設定する
+        void SetCoefs(const Coefs ck)
+        {
+            a1_ = ck.a1;
+            a2_ = ck.a2;
+            b1_ = ck.b1;
+            b2_ = ck.b2;
+        }
 
-    // コピー・コンストラクタ禁止
-    Biquad(const Biquad&);
-    // 代入禁止
-    Biquad& operator=(const Biquad&);     
-};
+        // 内部変数(遅延器)のクリア
+        void Clear() { un1_ = un2_ = 0; }
 
+    private:
+        float a1_, a2_, b1_, b2_;
+        float un1_, un2_;
+
+        // コピー・コンストラクタ禁止
+        Biquad(const Biquad&);
+    };
+}
 #endif  // IIR_BIQUAD_HPP
--- a/F446_ADC.cpp	Mon Jul 09 03:48:50 2018 +0000
+++ b/F446_ADC.cpp	Thu Oct 11 11:42:48 2018 +0000
@@ -4,7 +4,7 @@
 //  STM32F446 の ADC2 または ADC3 を使って割込みによりアナログ信号を
 //  入力するクラス ― マルチ・レート処理用
 //
-//  2018/04/18, Copyright (c) 2018 MIKAMI, Naoki
+//  2018/10/11, Copyright (c) 2018 MIKAMI, Naoki
 //----------------------------------------------------------------
 
 #include "F446_ADC.hpp"
@@ -45,9 +45,6 @@
                	  | ADC_CR2_ADON;                   // ADC を有効にする
         adc_->CR1 = ADC_CR1_EOCIE;					// ADC の変換終了割り込みを有効にする
 
-        // ADC 共通の設定
-        ADC->CCR = 0x0;     // 念のため
-
         // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
         // 標本化周波数としてアップサンプリングに対応する値を設定する
         SetTim8(frequency);
--- 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;
+}
--- a/F446_Multirate.hpp	Mon Jul 09 03:48:50 2018 +0000
+++ b/F446_Multirate.hpp	Thu Oct 11 11:42:48 2018 +0000
@@ -12,7 +12,7 @@
 //      ● メンバ関数 Start() を実行した後に,printf() のような重い
 //        処理を実行すると正常に動かないことがある.
 //
-//  2018/07/09, Copyright (c) 2018 MIKAMI, Naoki
+//  2018/10/11, Copyright (c) 2018 MIKAMI, Naoki
 //-----------------------------------------------------------
 
 #include "mbed.h"
@@ -31,7 +31,7 @@
         // コンストラクタ
         //      コンストラクタの引数を与えない場合はデフォルトのフィルタを使用
         //      order = 0 にすると,補間フィルタなしの状態になる
-        F446_Multirate(int order = -1, const Biquad::Coefs ck[] = NULL,
+        F446_Multirate(int order = -1, const Biquad hk[] = NULL,
                        float g0 = 1);
         
         virtual ~F446_Multirate()
@@ -67,9 +67,9 @@
         static __IO bool okIn_;     // AD変換されたデータが使える場合に true となる
 
         // 補間用フィルタ用のメンバ
-        static const Biquad::Coefs HK_[];   // biquad 部の係数
-        static const float G0_;             // 利得定数
-        IirCascade *interpolator_;          // 補間用フィルタのポインタ
+        static const Biquad HK_[];  // biquad 部の係数
+        static const float G0_;     // 利得定数
+        IirCascade *interpolator_;  // 補間用フィルタのポインタ
 
         // 引数を 0 ~ (アップサンプリング倍率-1) の間でカウントアップ
         static inline int ModCounter(int &index)
--- a/IIR_Cascade.hpp	Mon Jul 09 03:48:50 2018 +0000
+++ b/IIR_Cascade.hpp	Thu Oct 11 11:42:48 2018 +0000
@@ -1,7 +1,7 @@
 //---------------------------------------------------
 //  縦続形 IIR フィルタ
 //
-//  2018/05/19, Copyright (c) 2018 MIKAMI, Naoki
+//  2018/10/11, Copyright (c) 2018 MIKAMI, Naoki
 //---------------------------------------------------
 
 #ifndef IIR_CASCADE_HPP
@@ -9,46 +9,44 @@
 
 #include "Biquad.hpp"
 #include "Array.hpp"    // Array クラスが定義されている
-using namespace Mikami;
 
-class IirCascade
+namespace Mikami
 {
-public:
-    // コンストラクタ
-    IirCascade(int order = 0, const Biquad::Coefs ck[] = NULL, float g0 = 1)
-        : order_(order), hn_((order+1)/2), g0_(g0)
+    class IirCascade
     {
-        for (int k=0; k<(order+1)/2; k++) hn_[k].SetCoefs(ck[k]);
-        Clear();
-    }
+    public:
+        // コンストラクタ
+        IirCascade(int order = 0, const Biquad hk[] = NULL, float g0 = 1)
+            : order_(order), hn_((order+1)/2, hk), g0_(g0) {}
 
-    // フィルタ処理を実行する
-    float Execute(float xn)
-    {
-        float yn = g0_*xn;
-        for (int k=0; k<(order_+1)/2; k++) yn = hn_[k].Execute(yn);
-        return yn;
-    }
+        // フィルタ処理を実行する
+        float Execute(float xn)
+        {
+            float yn = g0_*xn;
+            for (int k=0; k<(order_+1)/2; k++) yn = hn_[k].Execute(yn);
+            return yn;
+        }
 
-    // 係数の設定
-    void SetCoefs(int order, const Biquad::Coefs ck[], float g0)
-    {
-        if (order_ != order)
+        // 係数の設定
+        void SetCoefs(int order, const Biquad::Coefs ck[], float g0)
         {
-            order_ = order;
-            hn_.SetSize((order+1)/2);
+            if (order_ != order)
+            {
+                order_ = order;
+                hn_.SetSize((order+1)/2);
+            }
+            g0_ = g0;
+            for (int k=0; k<(order+1)/2; k++) hn_[k].SetCoefs(ck[k]);
         }
-        g0_ = g0;
-        for (int k=0; k<(order+1)/2; k++) hn_[k].SetCoefs(ck[k]);
-    }
-    
-    // 内部変数(遅延器)のクリア
-    void Clear()
-    {   for (int k=0; k<(order_+1)/2; k++) hn_[k].Clear(); }
+
+        // 内部変数(遅延器)のクリア
+        void Clear()
+        {   for (int k=0; k<(order_+1)/2; k++) hn_[k].Clear(); }
 
-private:
-    int order_;         // 次数
-    Array<Biquad> hn_;  // Biquad クラスのオブジェクトの配列
-    float g0_;          // 利得定数
-};
+    private:
+        int order_;         // 次数
+        Array<Biquad> hn_;  // Biquad クラスのオブジェクトの配列
+        float g0_;          // 利得定数
+    };
+}
 #endif  // IIR_CASCADE_HPP