AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年4月号に掲載

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Sat Aug 29 11:19:03 2020 +0000
Parent:
1:30d9fb51dec1
Child:
3:878a48f15e89
Commit message:
3

Changed in this revision

SDR_Library/Cic3Stage.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/F446_ADC.cpp Show diff for this revision Revisions of this file
SDR_Library/F446_ADC.hpp Show diff for this revision Revisions of this file
SDR_Library/F446_ADC_Base.cpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/F446_ADC_Base.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/F446_ADC_Intr.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/F446_DAC.cpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/F446_DAC.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/FastATan.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/FirFastSymmetry.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/Iir1st.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/IirDcCut.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/InitialMessage.hpp Show annotated file Show diff for this revision Revisions of this file
SDR_Library/QuadOscIir.hpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SDR_Library/Cic3Stage.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/Cic3Stage.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -1,7 +1,7 @@
 //-------------------------------------------------------------
 //  ダウンサンプリングで使う3段の CIC フィルタ用クラス
 //
-//  2019/04/30, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/08/02, Copyright (c) 2020 MIKAMI, Naoki
 //-------------------------------------------------------------
 
 #include "mbed.h"
@@ -15,43 +15,42 @@
     {
     public:
         // コンストラクタ
-        //      rate    ダウンサンプリングの率,1/10 にダウンサンプリングする場合は 10
-        //      amp     二相発振器の出力の振幅
+        //      rate ダウンサンプリングの率,1/10 にダウンサンプリングする場合は 10
+        //      amp  直交信号発生器の出力の振幅
         Cic3Stage(int rate, float amp)
             : G0_(1.0f/(amp*rate*rate*rate)), 
               vn1_(0), vn2_(0), vn3_(0), vn3M1_(0), yn1M1_(0), yn2M1_(0) {}
         
-        // 累算
-        void Accumulate(int16_t xn)
+        // 積分器
+        void Integrate(int16_t xn)
         {
-            vn1_ += xn;     // 累算1段目
-            vn2_ += vn1_;   // 累算2段目
-            vn3_ += vn2_;   // 累算3段目
+            vn1_ += xn;     // 積分器1段目
+            vn2_ += vn1_;   // 積分器2段目
+            vn3_ += vn2_;   // 積分器3段目
         }
 
-        // 差分
-        float Difference()
+        // くし形フィルタ
+        float CombFilter()
         {
-            int32_t yn1 = vn3_ - vn3M1_;    // 差分1段目
-            int32_t yn2 = yn1 - yn1M1_;     // 差分2段目
-            int32_t yn3 = yn2 - yn2M1_;     // 差分3段目
+            int32_t yn1 = vn3_ - vn3M1_;    // くし形フィルタ1段目
+            int32_t yn2 = yn1 - yn1M1_;     // くし形フィルタ2段目
+            int32_t yn3 = yn2 - yn2M1_;     // くし形フィルタ3段目
 
-            vn3M1_ = vn3_;  // 現在の値を保存,差分1段目
-            yn1M1_ = yn1;   // 現在の値を保存,差分2段目
-            yn2M1_ = yn2;   // 現在の値を保存,差分3段目
+            vn3M1_ = vn3_;  // 現在の値を保存,くし形フィルタ1段目
+            yn1M1_ = yn1;   // 現在の値を保存,くし形フィルタ2段目
+            yn2M1_ = yn2;   // 現在の値を保存,くし形フィルタ3段目
 
             return G0_*yn3;
         }
 
     private:
         const float G0_;
-        int32_t vn1_, vn2_, vn3_;       // 累算で使う変数
-        int32_t vn3M1_, yn1M1_, yn2M1_; // 差分で使う変数
+        int32_t vn1_, vn2_, vn3_;       // 積分器で使う変数
+        int32_t vn3M1_, yn1M1_, yn2M1_; // くし形フィルタで使う変数
 
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子の禁止のため
         Cic3Stage(const Cic3Stage&);
-        // 代入演算子禁止のため
         Cic3Stage& operator=(const Cic3Stage&);
     };
 }
-#endif  // CIC3_FILTER_CLASS_HPP
+#endif  // CIC3_FILTER_CLASS_HPP
\ No newline at end of file
--- a/SDR_Library/F446_ADC.cpp	Mon Sep 23 07:32:10 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC をポーリング方式で使うためのクラス
-//      ADC2 を使用(固定)
-//
-//  2019/07/15, Copyright (c) 2019 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "F446_ADC.hpp"
-#include "PeripheralPins.h" // PinMap_ADC を使う場合に必要
-#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
-// PeripheralPins.c は以下よりたどって行けば取得可能
-// https://gitlab.exmachina.fr/fw-libs/mbed-os/tree/5.8.1
-
-namespace Mikami
-{
-    // コンストラクタ
-    AdcF446::AdcF446(float fSampling, PinName pin) : myAdc_(ADC2)
-    {
-        AnalogIn adc_(pin);     // GPIO を ADC 用に切り替えるために必要
-        // この時点で ADC1 の CR2 の ADON ビットは 0 になっている
-        __HAL_RCC_ADC1_CLK_DISABLE();   // ADC1 に供給されているクロックを停止する
-
-        __HAL_RCC_ADC2_CLK_ENABLE();    // ADC2 にクロックを供給する
-        // __HAL_RCC_ADC2_CLK_ENABLE() の定義:stm32f4xx_hal_rcc_ex.h
-
-        // pin に対応するチャンネルを使うための設定
-        myAdc_->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC));
-        // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h
-        // STM_PIN_CHANNEL() の定義:PinNamesTypes.h
-
-        // ADC の CR1 の設定
-        myAdc_->CR1 = 0x0;      // AD 変換終了割り込みを禁止
-        // ADC の CR2 の設定
-        myAdc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING   // 外部トリガの立ち上がりで開始される
-                    | ADC_EXTERNALTRIGCONV_T8_TRGO      // 外部トリガ: Timer8 TRGO event
-                    | ADC_CR2_ADON;                     // ADC を有効にする
-
-        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-        SetTim8(fSampling);
-    }
-
-    // AD 変換された値を読み込む
-    float AdcF446::Read()
-    {
-        while ((ADC2->SR & ADC_SR_EOC) != ADC_SR_EOC) {}
-        return ToFloat(myAdc_->DR);
-    }
-
-    // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-    //      fSampling 標本化周波数 [kHz]
-    void AdcF446::SetTim8(float fSampling)
-    {
-        __HAL_RCC_TIM8_CLK_ENABLE();    // クロック供給. "stm32f4xx_hal_rcc.h" 参照
-        TIM_TypeDef* const TIM = TIM8;
-
-        TIM->CR2 = TIM_TRGO_UPDATE;     // Update event を TRGO (trigger output) とする
-
-        float arrF = (SystemCoreClock/fSampling)/1000.0f;
-        if (arrF >65535)
-        {
-            fprintf(stderr, "%8.2f kHz : 標本化周波数が低すぎます.\r\n", fSampling);
-            while (true) {}
-        }
-        TIM->ARR = floor(arrF + 0.5f) - 1;  // Auto-reload レジスタの設定
-        TIM->PSC = 0;                   // Prescaler の設定
-        TIM->CR1 = TIM_CR1_CEN;         // TIM8 を有効にする
-    }
-}
--- a/SDR_Library/F446_ADC.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC をポーリング方式で使うためのクラス(ヘッダ)
-//
-//  2019/07/15, Copyright (c) 2019 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "mbed.h"
-
-#ifndef ADC_F446_POLLING_HPP
-#define ADC_F446_POLLING_HPP
-
-namespace Mikami
-{
-    class AdcF446
-    {
-    public:
-        // コンストラクタ
-        //      fSampling 標本化周波数 [kHz]
-        //      pin     入力ピンの名前
-        AdcF446(float fSampling, PinName pin);
-
-        virtual ~AdcF446() {}
-
-        // AD 変換された値を読み込む
-        //      -1.0f <= AD変換された値 < 1.0f
-        virtual float Read();
-
-    protected:
-        ADC_TypeDef* const myAdc_;  // AD 変換器に対応するポインタ
-
-        float ToFloat(uint16_t x) { return AMP_*(x - 2048); }
-    
-    private:
-        static const float AMP_ = 1.0f/2048.0f;
-        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-        //      fSampling 標本化周波数 [kHz]
-        void SetTim8(float fSampling);
-
-        // コピー・コンストラクタ禁止のため
-        AdcF446(const AdcF446&);
-        // 代入演算子禁止のため
-        AdcF446& operator=(const AdcF446&);
-    };
-}
-#endif  // ADC_F446_POLLING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDR_Library/F446_ADC_Base.cpp	Sat Aug 29 11:19:03 2020 +0000
@@ -0,0 +1,65 @@
+//-------------------------------------------------------------
+//  F446 内蔵 用抽象基底クラス
+//      ADC2 を使用(固定)
+//
+//  2020/07/24, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "F446_ADC_Base.hpp"
+#include "PeripheralPins.h" // PinMap_ADC を使う場合に必要
+#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
+// PeripheralPins.c は以下よりたどって行けば取得可能
+// https://gitlab.exmachina.fr/fw-libs/mbed-os/tree/5.8.1
+
+namespace Mikami
+{
+    // コンストラクタ
+    AdcF446_Base::AdcF446_Base(float fSampling, PinName pin) : myAdc_(ADC2)
+    {
+        // pin に対応する GPIOx_MODER をアナログ・モードに設定する
+        pin_function(pin, STM_MODE_ANALOG);
+        // pin_function() が定義されている pinmap.c が含まれるディレクトリ:
+        // mbed-dev\targets\TARGET_STM
+
+        __HAL_RCC_ADC2_CLK_ENABLE();    // ADC2 にクロックを供給する
+        // __HAL_RCC_ADC2_CLK_ENABLE() の定義:stm32f4xx_hal_rcc_ex.h
+
+        // 1 チャンネルのみ使用の設定
+        myAdc_->SQR1 &= ~ADC_SQR1_L;
+
+        // pin に対応するチャンネルを使うための設定
+        myAdc_->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC));
+        // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h
+        // STM_PIN_CHANNEL() の定義:PinNamesTypes.h
+
+        // ADC の CR1 の設定
+        myAdc_->CR1 = 0x0;      // AD 変換終了割り込みを禁止
+        // ADC の CR2 の設定
+        myAdc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING   // 外部トリガの立ち上がりで開始される
+                    | ADC_EXTERNALTRIGCONV_T8_TRGO      // 外部トリガ: Timer8 TRGO event
+                    | ADC_CR2_ADON;                     // ADC を有効にする
+
+        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+        SetTim8(fSampling);
+    }
+
+    // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+    //      fSampling  標本化周波数 [kHz]
+    void AdcF446_Base::SetTim8(float fSampling)
+    {
+        __HAL_RCC_TIM8_CLK_ENABLE();    // クロック供給. "stm32f4xx_hal_rcc.h" 参照
+        TIM_TypeDef* const TIM = TIM8;
+
+        TIM->CR2 = TIM_TRGO_UPDATE;     // Update event を TRGO (trigger output) とする
+
+        float arrF = (SystemCoreClock/fSampling)/1000.0f;
+        if (arrF >65535)
+        {
+            fprintf(stderr, "%8.2f kHz : 標本化周波数が低すぎます.\r\n", fSampling);
+            while (true) {}
+        }
+        TIM->ARR = floor(arrF + 0.5f) - 1;  // Auto-reload レジスタの設定
+        TIM->PSC = 0;                   // Prescaler の設定
+        TIM->CR1 = TIM_CR1_CEN;         // TIM8 を有効にする
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDR_Library/F446_ADC_Base.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -0,0 +1,44 @@
+//-------------------------------------------------------------
+//  F446 内蔵 ADC 用抽象基底クラス(ヘッダ)
+//
+//  2020/07/24, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef ADC_F446_POLLING_HPP
+#define ADC_F446_POLLING_HPP
+
+namespace Mikami
+{
+    class AdcF446_Base
+    {
+    public:
+        // コンストラクタ
+        //      fSampling  標本化周波数 [kHz]
+        //      pin        入力ピンの名前
+        AdcF446_Base(float fSampling, PinName pin);
+
+        virtual ~AdcF446_Base() {}
+
+        // AD 変換された値を読み込む(純粋仮想関数)
+        virtual float Read() = 0;
+
+    protected:
+        ADC_TypeDef* const myAdc_;  // AD 変換器に対応するポインタ
+
+        float ToFloat(uint16_t x) { return AMP_*(x - 2048); }
+    
+    private:
+        static const float AMP_ = 1.0f/2048.0f;
+
+        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+        //      fSampling  標本化周波数 [kHz]
+        void SetTim8(float fSampling);
+
+        // コピー・コンストラクタ,代入演算子の禁止のため
+        AdcF446_Base(const AdcF446_Base&);
+        AdcF446_Base& operator=(const AdcF446_Base&);
+    };
+}
+#endif  // ADC_F446_POLLING_HPP
\ No newline at end of file
--- a/SDR_Library/F446_ADC_Intr.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/F446_ADC_Intr.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -1,25 +1,25 @@
 //-------------------------------------------------------------
 //  F446 内蔵 ADC を割込み方式で使うための派生クラス
-//      基底クラス: AdcF446
+//      基底クラス: AdcF446_Base
 //
-//  2019/07/16, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/07/24, Copyright (c) 2020 MIKAMI, Naoki
 //-------------------------------------------------------------
 
-#include "F446_ADC.hpp"
+#include "F446_ADC_Base.hpp"
 
 #ifndef ADC_F446_INTERRUPT_HPP
 #define ADC_F446_INTERRUPT_HPP
 
 namespace Mikami
 {
-    class AdcF446_Intr : public AdcF446
+    class AdcF446_Intr : public AdcF446_Base
     {
     public:
         // コンストラクタ
-        //      fSampling 標本化周波数 [kHz]
-        //      pin     入力ピンの名前
+        //      fSampling   標本化周波数 [kHz]
+        //      pin       入力ピンの名前
         AdcF446_Intr(float fSampling, PinName pin)
-            : AdcF446(fSampling, pin)
+            : AdcF446_Base(fSampling, pin)
         {   myAdc_->CR1 |= ADC_CR1_EOCIE; }     // AD 変換終了割り込みを許可
 
         virtual ~AdcF446_Intr() {}
@@ -36,10 +36,9 @@
         virtual float Read() { return ToFloat(myAdc_->DR); }
 
     private:
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子禁止の禁止のため
         AdcF446_Intr(const AdcF446_Intr&);
-        // 代入演算子禁止のため
         AdcF446_Intr& operator=(const AdcF446_Intr&);
     };
 }
-#endif  // ADC_F446_INTERRUPT_HPP
+#endif  // ADC_F446_INTERRUPT_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDR_Library/F446_DAC.cpp	Sat Aug 29 11:19:03 2020 +0000
@@ -0,0 +1,24 @@
+//--------------------------------------------------------
+//  STM32F446 内蔵の DAC 用のクラス
+//      出力端子:   A2 (PA_4) に固定
+//
+//  2020/07/23, Copyright (c) 2020 MIKAMI, Naoki
+//--------------------------------------------------------
+
+#include "F446_DAC.hpp"
+#include "pinmap.h"         // pin_function() で使用
+
+namespace Mikami
+{
+    // コンストラクタ
+    DacF446::DacF446() : DAC_(DAC)
+    {
+        // A2 に対応する GPIOx_MODER をアナログ・モードに設定する
+        pin_function(A2, STM_MODE_ANALOG);
+
+        __HAL_RCC_DAC_CLK_ENABLE(); // DAC にクロックを供給する
+        // __HAL_RCC_DAC_CLK_ENABLE() の定義:stm32f4xx_hal_rcc_ex.h
+        
+        DAC_->CR = DAC_CR_EN1;      // DAC を有効にする
+    }
+}
\ No newline at end of file
--- a/SDR_Library/F446_DAC.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/F446_DAC.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -1,8 +1,8 @@
 //--------------------------------------------------------
-//  STM32F446 内蔵の DAC 用のクラス
-//      出力端子:   A2  (PA_4)
+//  STM32F446 内蔵の DAC 用のクラス(ヘッダ)
+//      出力端子:   A2 (PA_4) に固定
 //
-//  2019/02/18, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/07/23, Copyright (c) 2020 MIKAMI, Naoki
 //--------------------------------------------------------
 
 #include "mbed.h"
@@ -16,31 +16,27 @@
     {
     public:
         // コンストラクタ, A2 に接続される CH1 のみを有効にする
-        DacF446() : da_(A2) { DAC->CR = DAC_CR_EN1; }
+        DacF446();
 
         virtual ~DacF446() {}
 
         // -1.0f <= data <= 1.0f
         void Write(float data) { WriteDac1(ToUint16(data)); }
 
-        // 0 <= data <= 4095
-        void Write(uint16_t data) { WriteDac1(__USAT(data, BIT_WIDTH_)); }
-
     private:
         static const int BIT_WIDTH_ = 12;
-        AnalogOut da_;
+        DAC_TypeDef* const DAC_;    // DA 変換器に対応する構造体のポインタ
 
         // DAC の CH1 へ右詰めで出力する
-        void WriteDac1(uint16_t val) { DAC->DHR12R1 = val; }
+        void WriteDac1(uint16_t val) { DAC_->DHR12R1 = val; }
 
         // 飽和処理を行い uint16_t 型のデータを戻り値とする
         uint16_t ToUint16(float val)
         {   return __USAT((val + 1.0f)*2048.0f, BIT_WIDTH_); }
 
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子の禁止のため
         DacF446(const DacF446&);
-        // 代入演算子禁止のため
         DacF446& operator=(const DacF446&);
     };
 }
-#endif  // DAC_F446_SINGLE_HPP
+#endif  // DAC_F446_SINGLE_HPP
\ No newline at end of file
--- a/SDR_Library/FastATan.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/FastATan.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -3,7 +3,7 @@
 //      係数はミニマックス近似で求めたもの
 //      ただし,誤差は絶対誤差で評価した
 //
-//  2019/09/18, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/08/12, Copyright (c) 2020 MIKAMI, Naoki
 //--------------------------------------------------------------
 
 #include "mbed.h"
@@ -24,40 +24,27 @@
         static const float PI_2  = PI/2.0f;        // π/2
 
         if ( (x == 0.0f) && (y == 0.0f) ) return 0.0f;
-        if (y == 0.0f)
-        {
-            if (x > 0.0f) return 0.0f;      // 0
-            else          return PI;        // π
-        }
+        if (y == 0.0f) return (x > 0.0f) ? 0.0f : PI;
+
         float abs_x = fabsf(x);
         float abs_y = fabsf(y);
 
         if (abs_x == abs_y)
         {
-            if (x > 0.0f)
-            {
-                if (y > 0.0f) return PI_4;  // π/4
-                else          return -PI_4; // -π/4
-            }
-            else
-            {
-                if (y > 0.0f) return PI3_4;  // 3π/4
-                else          return -PI3_4; // -3π/4
-            }
+            if (x > 0.0f) return (y > 0.0f) ?  PI_4 : -PI_4;
+            else          return (y > 0.0f) ? PI3_4 : -PI3_4;
         }
 
         if (abs_x > abs_y)  // |θ|< π/4,3π/4<|θ|<π
         {
             float u = ATanPoly(y/x);
             if (x > 0.0f) return u;
-            if (y > 0.0f) return u + PI;
-            else          return u - PI;
+            else          return (y > 0.0f) ? u + PI : u - PI;
         }
         else                // π/4 <|θ|<3π/4
         {
             float u = ATanPoly(x/y);
-            if (y > 0.0f) return -u + PI_2;
-            else          return -u - PI_2;
+            return (y > 0.0f) ? -u + PI_2 : -u - PI_2;
         }
     }
 
@@ -74,4 +61,4 @@
         return atanx;
     }
 }
-#endif  // FAST_ARCTAN_LOW_PRECISION_HPP
+#endif  // FAST_ARCTAN_LOW_PRECISION_HPP
\ No newline at end of file
--- a/SDR_Library/FirFastSymmetry.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/FirFastSymmetry.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -1,12 +1,12 @@
-//-----------------------------------------------------------------
+//----------------------------------------------------------------------------
 // SDR で使う FIR フィルタ,係数:対称
 //      ● 処理の高速化のため,入力信号のバッファのサイズを 256,データを指す
 //        インデックスを uint8_t 型としてリング・バッファを実現している.
 //      ● さらに,係数が対称であることを利用して,先に x[k] + x[ORDER-k] と
 //        いう加算を行ってから,係数の乗算を行うようにした.
 //
-// 2019/03/03, Copyright (c) 2019 MIKAMI, Naoki
-//-----------------------------------------------------------------
+// 2020/07/28, Copyright (c) 2020 MIKAMI, Naoki
+//----------------------------------------------------------------------------
 
 #include "mbed.h"
 
@@ -18,10 +18,10 @@
     {
     public:
         // コンストラクタ
-        //      order   フィルタの次数
+        //      order   フィルタの次数,次数は偶数とする
         //      hk[]    フィルタの係数
-        FirFastSymmetry(int order, const float hk[])
-            : ORDER_(order), hm_(hk), index_(255)
+        FirFastSymmetry(uint8_t order, const float hk[])
+            : ORDER_(order), ORDER2_(order/2), hm_(hk), index_(255)
         {   for (int k=0; k<SIZE_; k++) un_[k] = 0; }
 
         // 入力信号をバッファへ書き込む
@@ -33,23 +33,23 @@
             __IO uint8_t ptrM = index_;
             __IO uint8_t ptrP = index_ - ORDER_;
             float acc = 0;
-            for (int k=0; k<ORDER_/2; k++)
+            for (int k=0; k<ORDER2_; k++)
                 acc += hm_[k]*(un_[ptrM--] + un_[ptrP++]);
-            acc += hm_[ORDER_/2]*un_[ptrM];
+            acc += hm_[ORDER2_]*un_[ptrM];
             return acc;
         }
 
     private:
         static const int SIZE_ = 256;   // 入力信号のバッファのサイズ
-        const int ORDER_;               // フィルタの次数
+        const uint8_t ORDER_;           // フィルタの次数
+        const uint8_t ORDER2_;          // フィルタの次数の半分
         const float *const hm_;         // フィルタの係数
         float un_[SIZE_];               // 入力信号のバッファ
         __IO uint8_t index_;            // 最新の入力信号を示すインデックス
 
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子の禁止のため
         FirFastSymmetry(const FirFastSymmetry&);
-        // 代入演算子禁止のため
         FirFastSymmetry& operator=(const FirFastSymmetry&);
     };
 }
-#endif  // FIR_DIRECT_FAST_SYMMETRY_HPP
+#endif  // FIR_DIRECT_FAST_SYMMETRY_HPP
\ No newline at end of file
--- a/SDR_Library/Iir1st.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/Iir1st.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -2,7 +2,7 @@
 // 一次の IIR フィルタ
 //      y[n] = a1*y[n-1] + (1 - a1)*x[n]
 //
-// 2019/09/21, Copyright (c) 2019 MIKAMI, Naoki
+// 2020/08/05, Copyright (c) 2020 MIKAMI, Naoki
 //-----------------------------------------------------------------
 
 #include "mbed.h"
@@ -16,7 +16,7 @@
     public:
         // コンストラクタ
         //      a1  フィルタの係数
-        Iir1st(float a1) : A1_(a1), B0_(1.0f - a1) { yn_ = 0; }
+        Iir1st(float a1) : A1_(a1), B0_(1.0f - a1), yn_(0) {}
 
         // フィルタの実行
         float Execute(float xn)
@@ -30,10 +30,9 @@
         const float B0_;    // フィルタ係数
         float yn_;          // 出力
 
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子の禁止のため
         Iir1st(const Iir1st&);
-        // 代入演算子禁止のため
         Iir1st& operator=(const Iir1st&);
     };
 }
-#endif  // IIR_1ST_HPP
+#endif  // IIR_1ST_HPP
\ No newline at end of file
--- a/SDR_Library/IirDcCut.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/IirDcCut.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -3,7 +3,7 @@
 //      u[n] = a1*u[n-1] + x[n]
 //      y[n] = g0*(u[n] - u[n-1])
 //
-// 2019/09/21, Copyright (c) 2019 MIKAMI, Naoki
+// 2020/08/17, Copyright (c) 2020 MIKAMI, Naoki
 //-----------------------------------------------------------------
 
 #include "mbed.h"
@@ -19,7 +19,7 @@
         //      a1  フィルタの係数
         //      g0  利得定数
         IirDcCut(float a1, float g0)
-            : A1_(a1), G0_(g0) { un1_ = 0; }
+            : A1_(a1), G0_(g0), un1_(0) {}
 
         // フィルタの実行
         float Execute(float xn)
@@ -33,12 +33,11 @@
     private:
         const float A1_;        // フィルタ係数
         const float G0_;        // 利得定数
-        float un1_;             // 中間の値
+        float un1_;             // 遅延器の値
 
-        // コピー・コンストラクタ禁止のため
+        // コピー・コンストラクタ,代入演算子の禁止のため
         IirDcCut(const IirDcCut&);
-        // 代入演算子禁止のため
         IirDcCut& operator=(const IirDcCut&);
     };
 }
-#endif  // IIR_DC_CUT_HPP
+#endif  // IIR_DC_CUT_HPP
\ No newline at end of file
--- a/SDR_Library/InitialMessage.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/InitialMessage.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -6,11 +6,8 @@
 
 #include "mbed.h"
 #pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
-
 #include <string>
 
-#ifndef INITIAL_MESSAGE_HPP
-#define INITIAL_MESSAGE_HPP
 enum AmFm { AM, FM };   // メッセージが AM 用か FM 用かを指定する
 
 //      str     2行目に表示するメッセージ
@@ -38,5 +35,4 @@
     
     sp.printf("'Enter' キーは CR/LF するだけです.\r\n\n");
     sp.putc('0');
-}
-#endif  // INITIAL_MESSAGE_HPP
+}
\ No newline at end of file
--- a/SDR_Library/QuadOscIir.hpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/SDR_Library/QuadOscIir.hpp	Sat Aug 29 11:19:03 2020 +0000
@@ -1,7 +1,7 @@
 //--------------------------------------------------------------
-//  IIR フィルタを利用する二相発振器のクラス
+//  IIR フィルタを利用する直交信号発生器のクラス
 //
-//  2019/04/11, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/07/30, Copyright (c) 2020 MIKAMI, Naoki
 //--------------------------------------------------------------
 
 #include "mbed.h"
@@ -15,59 +15,44 @@
     {
     public:
         // コンストラクタ
-        //      f0:     周波数,単位:Hz
-        //      ts:     標本化間隔,単位:μs
-        //      amp:    振幅
+        //      f0  周波数,単位:Hz
+        //      ts  標本化間隔,単位:μs
+        //      amp 振幅
         QuadOscIir(float f0, float ts, float amp = 1)
             : TS_(ts*1.0E-6f), A0_(amp) { Set(f0); }
 
-        // sin/cos 発生,実行時間の実測値:91 ns
+        // sin/cos 発生
         void Generate(float &sinX, float &cosX)
         {
-            RecursivePart();
-            sinX = b1S_*un2_;
-            cosX = A0_*un1_ + b1C_*un2_;
-        }
-    
-        // sin 発生,実行時間の実測値:69 ns
-        float GenerateSin()
-        {
-            RecursivePart();
-            return b1S_*un2_;
-        }
+            float vn = a1_*vn1_ - vn2_;
+            sinX = b1S_*vn1_;
+            cosX = A0_*vn + b1C_*vn1_;
 
-        // cis 発生,実行時間の実測値:80 ns
-        float GenerateCos()
-        {
-            RecursivePart();
-            return A0_*un1_ + b1C_*un2_;
+            vn2_ = vn1_;    // v[n-2] ← v[n-1]
+            vn1_ = vn;      // v[n-1] ← v[n]
         }
 
         // 出力周波数の設定,周波数を変更し再スタートする場合も使える
         //      f0:周波数,単位:Hz
         void Set(float f0)
         {
-            static const float pi2 = 6.283185f;
-            a1_ = 2.0f*cosf(pi2*f0*TS_);
-            b1S_ = A0_*sinf(pi2*f0*TS_);
-            b1C_ = -A0_*cosf(pi2*f0*TS_);
-            un1_ = 1.0f;
-            un2_ = 0.0f;
+            static const float PI2 = 6.283185f;
+            a1_ = 2.0f*cosf(PI2*f0*TS_);
+            b1S_ = A0_*sinf(PI2*f0*TS_);
+            b1C_ = -A0_*cosf(PI2*f0*TS_);
+            vn1_ = 1.0f;
+            vn2_ = 0.0f;
         }
 
     private:
         const float TS_;        // 標本化間隔
         const float A0_;        // 振幅
         float a1_, b1S_, b1C_;
-        float un1_, un2_;
+        float vn1_, vn2_;
 
-        // u[n] = a1*u[n-1] - u[n-2] の計算
-        void RecursivePart()
-        {
-            float un = a1_*un1_ - un2_;
-            un2_ = un1_;    // u[n-2] ← u[n-1]
-            un1_ = un;      // u[n-1] ← u[n]
-        }
+        // コピー・コンストラクタ,代入演算子の禁止のため
+        QuadOscIir(const QuadOscIir&);
+        QuadOscIir& operator=(const QuadOscIir&);
     };
 }
-#endif  // QUAD_PHASE_OSC_IIR_HPP
+#endif  // QUAD_PHASE_OSC_IIR_HPP
\ No newline at end of file
--- a/main.cpp	Mon Sep 23 07:32:10 2019 +0000
+++ b/main.cpp	Sat Aug 29 11:19:03 2020 +0000
@@ -6,12 +6,12 @@
 //      入力ピン: A1
 //      出力ピン: A2
 //
-//  2019/09/18, Copyright (c) 2019 MIKAMI, Naoki
+//  2020/08/17, Copyright (c) 2020 MIKAMI, Naoki
 //-------------------------------------------------------------
 
 #include "F446_ADC_Intr.hpp"    // ADC
 #include "F446_DAC.hpp"         // DAC
-#include "QuadOscIir.hpp"       // 二相発振器
+#include "QuadOscIir.hpp"       // 直交信号発生器
 #include "Cic3Stage.hpp"        // 3段 CIC フィルタ
 #include "Iir1st.hpp"           // 一次の IIR フィルタ
 #include "InitialMessage.hpp"   // 最初のメーッセージ
@@ -20,9 +20,9 @@
 
 const float FS_ = 900.0f;       // 標本化周波数,単位: kHz
 const float T0_ = 1000/FS_;     // 標本化間隔,単位:μs
-const float A0_ = 8192;         // 二相発振器の出力の振幅
+const float A0_ = 8192;         // 直交信号発生器の出力の振幅
 
-// 各放送局の搬送波の周波数,単位: kHz
+// 各放送局の搬送波の周波数,単位: Hz
 const float F_C_[] = {  594.0e3f,   // NHK 第1
                         693.0e3f,   // NHK 第2
                         810.0e3f,   // AFN Tokyo
@@ -53,9 +53,9 @@
     float sinX, cosX;
     nco_.Generate(sinX, cosX);  // sin, cos 発生
 
-    // cos/sin を乗算したデータに対する CIC フィルタの累算処理
-    cic3I_.Accumulate((int16_t)(xn*cosX));  // I 信号用
-    cic3Q_.Accumulate((int16_t)(xn*sinX));  // Q 信号用
+    // cos/sin を乗算したデータに対する CIC フィルタの積分処理
+    cic3I_.Integrate((int16_t)(xn*cosX));   // I 信号用
+    cic3Q_.Integrate((int16_t)(xn*sinX));   // Q 信号用
 
     if (++count >= DS_RATE_)
     {
@@ -67,22 +67,22 @@
 // ダウンサンプラより後の処理に対する割り込みサービス・ルーチン
 void SwiIsr()
 {
-    // CIC フィルタの差分処理
-    float yI_n = cic3I_.Difference();   // 差分処理で I 信号を生成
-    float yQ_n = cic3Q_.Difference();   // 差分処理で Q 信号を生成
+    // CIC フィルタのくし形フィルタの部分による処理
+    float yI_n = cic3I_.CombFilter();   // くし形フィルタ処理で I 信号を生成
+    float yQ_n = cic3Q_.CombFilter();   // くし形フィルタ処理で Q 信号を生成
 
     float yn = sqrtf(yI_n*yI_n + yQ_n*yQ_n);    // 包絡線成分を求める
     yn = comp_.Execute(yn);             // 補償フィルタ
     float dc = averaging_.Execute(yn);  // 直流分を求める
+    yn = yn - dc;   // 直流分除去
 
     float gain = 0.8f/dc;               // AGC 処理の準備
     if (gain > 200.0f) gain = 200.0f;
 
-    // DAC への出力は,直流分を除去し,AGC 処理をしたもの
-    dac_.Write(gain*(yn - dc));
+    dac_.Write(gain*yn);
 }
 
-// シリアル・ポートの受信割込みに対する処理
+// シリアル・ポートの受信割込みに対する割り込みサービス・ルーチン
 void RxIsr()
 {
     unsigned char chr = pc_.getc();
@@ -97,11 +97,11 @@
 
 int main()
 {
-    InitialMessage("ダウンサンプリングに CIC フィルタ使用.", AM, pc_);
+    InitialMessage("ダウンサンプリングに CIC フィルタを使用.", AM, pc_);
 
     NVIC_SetPriority(ADC_IRQn,    0);   // 最優先
     NVIC_SetPriority(EXTI4_IRQn,  1);   // 2番目に優先
-    NVIC_SetPriority(USART2_IRQn, 2);
+    NVIC_SetPriority(USART2_IRQn, 2);   // 3番目に優先
 
     // ADC に対する割り込みサービス・ルーチンの設定
     adc_.SetIntrVec(&AdcIsr);
@@ -115,4 +115,4 @@
     pc_.attach(&RxIsr);
 
     while (true) {}
-}
+}
\ No newline at end of file