Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Array_Matrix mbed SerialTxRxIntr F446_AD_DA UIT_FFT_Real
Revision 7:5ba884060d3b, committed 2019-11-24
- Comitter:
 - MikamiUitOpen
 - Date:
 - Sun Nov 24 11:14:01 2019 +0000
 - Parent:
 - 6:c38ec7939609
 - Commit message:
 - 8
 
Changed in this revision
diff -r c38ec7939609 -r 5ba884060d3b Array_Matrix.lib --- a/Array_Matrix.lib Sun Nov 04 10:41:02 2018 +0000 +++ b/Array_Matrix.lib Sun Nov 24 11:14:01 2019 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/MikamiUitOpen/code/Array_Matrix/#a25dba17218c +https://os.mbed.com/users/MikamiUitOpen/code/Array_Matrix/#d9dea7748b27
diff -r c38ec7939609 -r 5ba884060d3b DoubleBufferMatrix.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DoubleBufferMatrix.hpp	Sun Nov 24 11:14:01 2019 +0000
@@ -0,0 +1,59 @@
+//--------------------------------------------------------
+//  ダブル・バッファの template クラス
+//      バッファに2次元配列(Matrix クラス)を使用
+//
+//  2019/11/22, Copyright (c) 2019 MIKAMI, Naoki
+//--------------------------------------------------------
+
+#ifndef DOUBLE_BUFFER_MATRIX_HPP
+#define DOUBLE_BUFFER_MATRIX_HPP
+
+#include "Matrix.hpp"
+using namespace Mikami;
+
+template<class T> class DoubleBuffer
+{
+public:
+    // コンストラクタ
+    explicit DoubleBuffer(int size, T initialValue = 0)
+        : N_(size), buf_(2, size, initialValue), ping_(0), pong_(1),
+          index_(0), full_(false) {}
+    
+    // データを格納
+    void Store(T data)  { buf_[ping_][index_++] = data; }
+    
+    // 出力バッファからデータの取り出し
+    T Get(int n) const { return buf_[pong_][n]; }
+
+    // バッファが満杯でバッファを切り替える
+    bool IsFullSwitch()
+    {
+        if (index_ < N_) return false;
+
+        ping_ ^= 0x1;   // バッファ切換えのため
+        pong_ ^= 0x1;   // バッファ切換えのため
+        index_ = 0;
+        full_ = true;
+        return true;
+    }
+
+    // バッファが満杯で,true を返す
+    bool IsFull()
+    {
+        bool temp = full_;
+        if (full_) full_ = false;
+        return temp;
+    }
+
+private:
+    const int N_;       // バッファのサイズ
+    Matrix<T> buf_;     // バッファ
+    int ping_, pong_;   // バッファ切替用
+    int index_;         // 入力データのカウンタ
+    bool full_;         // 満杯の場合 true
+
+    // コピー・コンストラクタおよび代入演算子の禁止のため
+    DoubleBuffer(const DoubleBuffer&);
+    DoubleBuffer& operator=(const DoubleBuffer&);
+};
+#endif  // DOUBLE_BUFFER_MATRIX_HPP
diff -r c38ec7939609 -r 5ba884060d3b MySpectrogram/FFT_Analyzer.cpp
--- a/MySpectrogram/FFT_Analyzer.cpp	Sun Nov 04 10:41:02 2018 +0000
+++ b/MySpectrogram/FFT_Analyzer.cpp	Sun Nov 24 11:14:01 2019 +0000
@@ -1,7 +1,7 @@
 //-------------------------------------------------------
 //  Class for spectrum analysis using FFT
 //
-//  2018/11/04, Copyright (c) 2018 MIKAMI, Naoki
+//  2018/11/24, Copyright (c) 2018 MIKAMI, Naoki
 //-------------------------------------------------------
 
 #include "FFT_Analyzer.hpp"
@@ -17,7 +17,7 @@
         fft_.Execute(xn, yFft_);    // Execute FFT
         
         // Translate to dB
-        for (int n=2; n<=N_FFT_/2; n++)
+        for (int n=0; n<=N_FFT_/2; n++)
             yn[n] = 10.0f*log10f(Norm(yFft_[n]));
     }
 }
diff -r c38ec7939609 -r 5ba884060d3b SerialTxRxIntr.lib --- a/SerialTxRxIntr.lib Sun Nov 04 10:41:02 2018 +0000 +++ b/SerialTxRxIntr.lib Sun Nov 24 11:14:01 2019 +0000 @@ -1,1 +1,1 @@ -http://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#190d94fba10d +https://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#a90a9abeaea0
diff -r c38ec7939609 -r 5ba884060d3b Xfer.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Xfer.hpp	Sun Nov 24 11:14:01 2019 +0000
@@ -0,0 +1,58 @@
+//---------------------------------------------------------------------
+//  スペクトル解析の結果を PC へ転送するためのクラス
+//
+//  2019/11/24, Copyright (c) 2019 MIKAMI, Naoki
+//---------------------------------------------------------------------
+
+#include <string>
+#include "Array.hpp"
+#include "SerialRxTxIntr.hpp"
+using namespace Mikami;
+
+#ifndef XFER_CONVERT_TOPC_HPP
+#define XFER_CONVERT_TOPC_HPP
+
+class Xfer
+{
+public:
+    // コンストラクタ
+    Xfer(SerialRxTxIntr& rxTx, int size)
+        : SIZE_(size), xn_(size), rxTx_(rxTx) {}
+        
+    // スペクトル解析の結果を転送する形式に変換
+    void Convert(const float db[], float levelShift)
+    {
+        static const float FACTOR = 10000.0f/80.0f; // 表示範囲: 0 ~ 80 dB
+        for (int n=0; n<SIZE_; n++)
+        {
+            float xDb = FACTOR*(db[n] + 30.0f + levelShift);
+            if (xDb > 10000) xDb = 10000;
+            if (xDb < 0) xDb = 0;
+            xn_[n] = (uint16_t)xDb;
+        }
+    }
+    
+    // データを PC へ転送(0 ~ 10,000 の範囲の値を 2 文字で表すコード化を利用)
+    void ToPC()
+    {
+        string str = "";
+        for (int n=0; n<SIZE_; n++)
+        {
+            div_t a = div(xn_[n], 100);
+            str += a.quot + 0x10;
+            str += a.rem + 0x10;
+        }
+        rxTx_.Tx(str+"\n");
+        rxTx_.Tx("EOT\n");
+    }
+    
+private:
+    const int SIZE_;        // PC に送るデータ数
+    Array<uint16_t> xn_;    // PC に送るデータ
+    SerialRxTxIntr& rxTx_;
+
+    // コピー・コンストラクタおよび代入演算子の禁止のため
+    Xfer(const Xfer&);
+    Xfer& operator=(const Xfer&);
+};
+#endif  // XFER_CONVERT_TOPC_HPP
diff -r c38ec7939609 -r 5ba884060d3b main.cpp
--- a/main.cpp	Sun Nov 04 10:41:02 2018 +0000
+++ b/main.cpp	Sun Nov 24 11:14:01 2019 +0000
@@ -14,16 +14,17 @@
 //      ● 出力  A2: 左チャンネル,D13 右チャンネル
 //             入力をそのまま出力する
 //
-//  2018/11/04, Copyright (c) 2018 MIKAMI, Naoki
+//  2018/11/24, Copyright (c) 2018 MIKAMI, Naoki
 //---------------------------------------------------------------------
 
 #include "mbed.h"
 #include <string>
-#include "myFunction.hpp"
 #include "Array.hpp"
 #include "F446_ADC_Interrupt.hpp"
 #include "FFT_Analyzer.hpp"
 #include "LPC_Analyzer.hpp"
+#include "DoubleBufferMatrix.hpp"
+#include "Xfer.hpp"
 using namespace Mikami;
 
 #ifndef __STM32F446xx_H
@@ -34,30 +35,11 @@
 const int N_DATA_ = N_FFT_ + 1;     // スペクトル解析に使うデータ数(差分処理を考慮)
 const int N_FRAME_ = N_FFT_/2 + 1;  // 1フレーム当たり標本化するデータ数
 const int N_FFT_2_ = N_FFT_/2;      // FFT の点数の半分
-const float AMP_ = 1.0f/2048.0f;    // uint16_t 型のデータを float 型に変換する際の定数
-
-uint16_t xPing_[N_FRAME_];  // 標本化したデータのバッファ1
-uint16_t xPong_[N_FRAME_];  // 標本化したデータのバッファ2
-uint16_t *inPtr_ = xPing_;  // AD 変換データの格納先を指すポインタ
-uint16_t *outPtr_ = xPing_; // 取り出すデータを指すポインタ
-
-__IO int inCount_ = 0;      // 入力データのカウンタ
-__IO int pingPong_ = 0;     // 入力データの格納先,0: xPing_[], 1: xPong_[]
-__IO bool full_ = false;    // AD 変換データが満杯のとき true
 
 const int FS_ = 16000;      // 標本化周波数: 16 kHz
 AdcDual_Intr myAdc_(FS_);   // "F446_ADC_Interrupt.hpp" で定義
 DacDual myDac_;             // "F446_DAC.cpp/hpp" で定義
-
-// FFT によるスペクトル解析オブジェクトの生成
-FftAnalyzer *fftAnlz_ = new FftAnalyzer(N_DATA_, N_FFT_);
-// 線形予測法 によるスペクトル解析オブジェクトの生成
-LpcAnalyzer *lpcAnlz_ = new LpcAnalyzer(N_DATA_, N_FFT_, 20);
-AnalyzerBase *analyzer_ = fftAnlz_;     // 最初は FFT を使う
-
-SerialRxTxIntr rxTx_(32, 115200*4);     // PC との通信用
-
-float empha_ = 1.0f;        // 高域強調器の係数
+DoubleBuffer<float> buf_(N_FRAME_); // AD の結果を保存するダブル・バッファ
 
 // 入力チャンネルを選択する関数とそれを割り当てる関数ポインタ
 float InputL(float x1, float x2) { return x1; }
@@ -70,50 +52,48 @@
 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
 void AdcIsr()
 {
-    uint16_t sn1, sn2;
+    float sn1, sn2;
     myAdc_.Read(sn1, sn2);
-    uint16_t xn = InputCurrent(sn1, sn2);
-    inPtr_[inCount_] = xn;
+    float xn = InputCurrent(sn1, sn2);
+    buf_.Store(xn);     // バッファへ格納
     myDac_.Write(xn, xn);
 
-    if (++inCount_ >= N_FRAME_) // データが満杯か調べる
-    {
-        full_ = true;           // データが満杯
-        inCount_ = 0;           // 以降のデータ取得のため
-        pingPong_ = (pingPong_+1) & 0x01;               // バッファの切り替えのため
-        inPtr_ = (pingPong_ == 0) ? xPing_ : xPong_;    // バッファのポインタ指定
-        InputCurrent = InputNew;                // 入力の切り替え
-        analyzer_->SetHighEmphasizer(empha_);   // 高域強調の有無の指令
-    }
+    if (buf_.IsFullSwitch())        // バッファが満杯であればバッファを切り替える
+        InputCurrent = InputNew;    // 入力の切り替え
 }
 
 int main()
 {
-    const int DATA_SIZE = N_FFT_/2 + 1;
-    Array<uint16_t> txData(DATA_SIZE);     // 送信用データ
-    float sn[N_DATA_];      // スペクトル解析の対象となるデータ
-    float db[N_FRAME_];     // 解析結果である対数スペクトル [dB]
-    for (int n=0; n<N_DATA_; n++) sn[n] = 0;
-    for (int n=0; n<N_FRAME_; n++) xPong_[n] = 2048;    // uint16_t 型の 0 に対応
+    // FFT によるスペクトル解析オブジェクトの生成
+    FftAnalyzer *fftAnlz_ = new FftAnalyzer(N_DATA_, N_FFT_);
+    // 線形予測法 によるスペクトル解析オブジェクトの生成
+    LpcAnalyzer *lpcAnlz_ = new LpcAnalyzer(N_DATA_, N_FFT_, 20);
+    AnalyzerBase *analyzer = fftAnlz_;  // 最初は FFT を使う
+    float empha = 1.0f;                 // 高域強調器の係数
+
+    SerialRxTxIntr rxTx(32, 115200*4);  // PC との通信用
+    Xfer tx(rxTx, N_FFT_/2+1);          // PC に転送するためのオブジェクトの生成
+
+    Array<float> sn(N_FFT_, 0.0f);  // スペクトル解析の対象となるデータ
+    Array<float> db(N_FRAME_);      // 解析結果:対数スペクトル [dB]
 
     NVIC_SetPriority(ADC_IRQn, 0);      // AD変換終了割り込みの優先度が最高
     NVIC_SetPriority(USART2_IRQn, 1);
 
     float levelShift = 20;  // dB 計算の際のシフト量の初期値
 
-    full_ = false;
-    __IO bool ready = false;    // スペクトルの計算終了で true
-    __IO bool okGo = false;     // "GO" を受信したら true
+    bool ready = false;     // スペクトルの計算終了で true
+    bool okGo = false;      // "GO" を受信したら true
 
     myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
     while (true)
     {
         // PC からのコマンドの解析
-        if (rxTx_.IsEol())      // 受信バッファのデータが有効になった場合の処理
+        if (rxTx.IsEol())       // 受信バッファのデータが有効になった場合の処理
         {
-            string str = rxTx_.GetBuffer();
+            string str = rxTx.GetBuffer();
             if (str == "Spectrogram")
-                rxTx_.Tx("ACK\n");  // PC からの "Spectrogram" に対して "ACK" を送信する
+                rxTx.Tx("ACK\n");   // PC からの "Spectrogram" に対して "ACK" を送信する
             else if (str.substr(0, 2) == "GO")
             {
                 // str の内容
@@ -134,46 +114,35 @@
 
                 levelShift = (float)(str[3] - ' ');     // dB 計算の際のシフト量
 
-                if (str[4] == 'Y') empha_ = 1.0f;       // 高域強調器は有
-                else               empha_ = 0;          // 高域強調器は無
+                if (str[4] == 'Y') empha = 1.0f;        // 高域強調器は有
+                else               empha = 0;           // 高域強調器は無
 
-                if (str[5] == 'F') analyzer_ = fftAnlz_;    // FFT
-                else               analyzer_ = lpcAnlz_;    // 線形予測法
+                if (str[5] == 'F') analyzer = fftAnlz_; // FFT
+                else               analyzer = lpcAnlz_; // 線形予測法
  
                 okGo = true;            // データの転送要求あり
             }
         }
 
-        if (full_)  // 入力データが満杯かどうか調べる
+        if (buf_.IsFull())  // 入力データが満杯の場合,以下の処理を行う
         {
-            full_ = false;
-
-            outPtr_ = (pingPong_ == 1) ? xPing_ : xPong_;
             // フレームの後半のデータを前半に移動する
             for (int n=0; n<N_FFT_2_; n++)
                 sn[n] = sn[n+N_FRAME_];
             // フレームの後半には新しいデータを格納する
             for (int n=0; n<N_FRAME_; n++)
-                sn[n+N_FFT_2_] = AMP_*(outPtr_[n] - 2048);
-
-            analyzer_->Execute(sn, db); // スペクトル解析の実行
+                sn[n+N_FFT_2_] = buf_.Get(n);
 
-            const float FACTOR = 10000.0f/80.0f;     // 表示範囲: 0 ~ 80 dB
-            for (int n=0; n<DATA_SIZE; n++)
-            {
-                float xDb = FACTOR*(db[n] + 30.0f + levelShift);
-                if (xDb > 10000.0f) xDb = 10000.0f;
-                if (xDb < 0.0f) xDb = 0.0f;
-                uint16_t spc = (uint16_t)xDb;
-                txData[n] = spc;
-            }
-            ready = true;       // スペクトル解析終了
+            analyzer->SetHighEmphasizer(empha); // 高域強調の有無の指令
+            analyzer->Execute(sn, db);  // スペクトル解析の実行
+            tx.Convert(db, levelShift); // スペクトル解析の結果を転送する形式に変換
+            ready = true;               // スペクトル解析終了
         }
 
         // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
         if (okGo && ready)
         {
-            Xfer(txData);       // データを PC へ転送
+            tx.ToPC();      // データを PC へ転送
             ready = false;
             okGo = false;
         }
diff -r c38ec7939609 -r 5ba884060d3b mbed.bld --- a/mbed.bld Sun Nov 04 10:41:02 2018 +0000 +++ b/mbed.bld Sun Nov 24 11:14:01 2019 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/a7c7b631e539 \ No newline at end of file +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file
diff -r c38ec7939609 -r 5ba884060d3b myFunction.hpp
--- a/myFunction.hpp	Sun Nov 04 10:41:02 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-//---------------------------------------------------------------------
-//  データを PC へ転送
-//
-//  2018/10/07, Copyright (c) 2018 MIKAMI, Naoki
-//---------------------------------------------------------------------
-
-#include <string>
-#include "Array.hpp"
-#include "SerialRxTxIntr.hpp"
-using namespace Mikami;
-
-#ifndef MY_FUNCTION_XFER_HPP
-#define MY_FUNCTION_XFER_HPP
-
-extern SerialRxTxIntr rxTx_;
-
-// データを PC へ転送(0 ~ 10,000 の範囲の値を 2 文字で表すコード化を利用)
-void Xfer(Array<uint16_t> &xn)
-{
-    string str = "";
-    for (int n=0; n<xn.Length(); n++)
-    {
-        div_t a = div(xn[n], 100);
-        str += a.quot + 0x10;
-        str += a.rem + 0x10;
-    }
-    rxTx_.Tx(str+"\n");
-    rxTx_.Tx("EOT\n");
-}
-
-#endif  // MY_FUNCTION_XFER_HPP