ノイズを付加した正弦波発生器 Sinusoidal wave generator with noise.

Dependencies:   F746_GUI F746_SAI_IO Random mbed

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Sun Nov 04 02:41:21 2018 +0000
Commit message:
1

Changed in this revision

F746_GUI.lib Show annotated file Show diff for this revision Revisions of this file
F746_SAI_IO.lib Show annotated file Show diff for this revision Revisions of this file
MyFiles/LcdPanelFrq.hpp Show annotated file Show diff for this revision Revisions of this file
MyFiles/Trigger.hpp Show annotated file Show diff for this revision Revisions of this file
MyFiles/WaveformDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
MyFiles/WaveformDisplay.hpp Show annotated file Show diff for this revision Revisions of this file
MyFiles/Zoom.hpp Show annotated file Show diff for this revision Revisions of this file
Random.lib 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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 31361b0fcdad F746_GUI.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F746_GUI.lib	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/F746_GUI/#50b8f7654c36
diff -r 000000000000 -r 31361b0fcdad F746_SAI_IO.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F746_SAI_IO.lib	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/F746_SAI_IO/#61e2c3cc79a3
diff -r 000000000000 -r 31361b0fcdad MyFiles/LcdPanelFrq.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFiles/LcdPanelFrq.hpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,122 @@
+//-----------------------------------------------------------
+//  ディジタルフィルタ実験のためのプラットフォームの
+//  LCD パネル表示と入力信号の周波数設定で使う
+//
+//  2018/11/03, Copyright (c) 2017 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef PANEL_MANIPULATOR_HPP
+#define PANEL_MANIPULATOR_HPP
+
+#include "F746_GUI.hpp"
+#include "NumericUpDown.hpp"
+#include "Zoom.hpp"
+#include "WaveformDisplay.hpp"
+#include "Trigger.hpp"
+
+namespace Mikami
+{
+    class LcdPanel
+    {
+    public:
+        //  ts  : 標本化間隔(単位:μs)
+        LcdPanel(float ts)
+            : TS_(ts), lcd_(GuiBase::GetLcd()),
+              xnD_(N_DISP_BUF_), frq_(1000),
+              dPhi_(PI2_*frq_*TS_), phi_(0), factor_(1),
+              noiseLevel_(0)
+        {
+            Label title(240, 10, "Sin+Noise Generator", Label::CENTER, Font16);
+
+            // 表示するデータ数: 400個
+            waveDisp_ = new WaveformDisplay(lcd_, 30, 90, xnD_, 400, 8,
+                                            AXIS_COLOR_,
+                                            LINE_COLOR1_, LINE_COLOR2_,
+                                            BACK_COLOR_);
+
+            // GUI 設定
+            ud_ = new NumericUpDown(4, 0, 271, frq_, 9999, 100, "Hz");
+            bar_ = new SeekBar(230, 250, 230,
+                               log10f(MIN_FRQ_), log10f(MAX_FRQ_), log10f(1000),
+                               "0.1", "1.0", "10.0");
+            // ノイズ・レベルの設定用
+            nLevel_ = new SeekBar(270, 185, 190, 0, 1.0f, 0, "0", "0.5", "1.0");
+
+            // 時間軸の拡大率は 8 倍まで
+            zmButton_ = new ZoomButton(180, 170, 30, 30, 8);
+        }
+
+        // 正弦波の発生で使う値の更新し,取得する
+        float GetPhi()
+        {
+            if ((phi_ += dPhi_) > PI2_) phi_ -= PI2_;
+            return phi_;
+        }
+
+        // 周波数設定の更新とズームイン/アウト・ボタンの処理
+        void Update()
+        {        
+            if (bar_->Slide())  // 周波数設定用 SeekBar をスライドした場合の処理
+            {
+                frq_ = (int)(powf(10, bar_->GetValue())+0.5f);
+                if (frq_ >= MAX_FRQ_) frq_ = MAX_FRQ_ - 1;
+                ud_->Set(frq_); // SeekBar の数値を NumericUpDown に表示する
+                dPhi_ = PI2_*frq_*TS_;
+            }
+
+            if (nLevel_->Slide())  // ノイズ・レベル設定用 SeekBar をスライドした場合の処理
+                noiseLevel_ = nLevel_->GetValue();
+
+            if (ud_->Touched())     // NumericUpDown をタッチした場合の処理
+            {
+                frq_ = ud_->Get();
+                bar_->Draw(log10f(frq_));  // NumericUpDown の数値で SeekBar のツマミの位置を設定
+                dPhi_ = PI2_*frq_*TS_;
+            }
+
+            zmButton_->Touched(factor_);   // ズームインとズームアウト
+        }
+
+        // 入出力信号のデータを表示用バッファへ格納
+        void Store(int16_t xn, int n)
+        {
+            // N_DISP_BUF_ (= 1000) 個を越えたデータは格納しない
+            if (n >= N_DISP_BUF_) return;
+
+            xnD_[n] = xn;
+        }
+        
+        // 入出力信号の波形の表示(トリガ条件を満足したところから表示する)
+        void Display() { waveDisp_->Execute(Trigger(xnD_, 1), factor_); }
+
+        // ノイズの大きさの取得
+        float GetNoiseLevel() { return noiseLevel_; }
+
+    private:
+        static const float PI_ = 3.1415926536f;
+        static const float PI2_ = 2.0f*PI_;
+        static const int MIN_FRQ_ = 100;        // 発生する周波数の最小値
+        static const int MAX_FRQ_ = 10000;      // 発生する周波数の最大値
+        static const uint32_t BACK_COLOR_ = GuiBase::ENUM_BACK;
+        static const uint32_t AXIS_COLOR_ = 0xFFCCFFFF;
+        static const uint32_t LINE_COLOR1_ = LCD_COLOR_CYAN;
+        static const uint32_t LINE_COLOR2_ = LCD_COLOR_MAGENTA;
+        static const int N_DISP_BUF_ = 1000;    // 波形表示用のバッファのサイズ
+
+        const float TS_;    // 標本化間隔
+
+        LCD_DISCO_F746NG &lcd_;
+        WaveformDisplay *waveDisp_;
+        NumericUpDown *ud_;     // 入力信号の周波数設定用(1 Hz 単位での設定用)
+        SeekBar *bar_;          // 入力信号の周波数設定用(概略の設定用)
+        SeekBar *nLevel_;       // ノイズの大きさの設定用
+        ZoomButton *zmButton_;  // 波形表示:ズームイン/アウト用
+
+        Array<int16_t> xnD_;    // 波形表示で使うバッファ(入力信号用)
+        int frq_;               // 現在の入力信号の周波数,初期値は 1 kHz
+        float dPhi_, phi_;      // 入力信号の生成で使う変数
+        int factor_;            // 波形表示の際の標本化間隔に対応するピクセル数
+        float noiseLevel_;      // ノイズの大きさ
+    };
+}
+#endif  // PANEL_MANIPULATOR_HPP
diff -r 000000000000 -r 31361b0fcdad MyFiles/Trigger.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFiles/Trigger.hpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,25 @@
+//---------------------------------------------------------------
+//  トリガの条件を満足する点を探す
+//
+//  2017/07/24, Copyright (c) 2017 MIKAMI, Naoki
+//---------------------------------------------------------------
+
+#ifndef F746_TRIGGER_HPP
+#define F746_TRIGGER_HPP
+
+#include "mbed.h"
+#include "Array.hpp"
+
+namespace Mikami
+{
+    int Trigger(const Array<int16_t>& xn,   // 対象とするデータ
+                int th)                     // トリガの基準値
+    {
+        int n;
+        for (n=1; n<xn.Length()/2; n++)
+            if ((xn[n-1] < -th) && (xn[n] > th))
+                return n;
+        return 0;
+    }
+}
+#endif  // F746_TRIGGER_HPP
diff -r 000000000000 -r 31361b0fcdad MyFiles/WaveformDisplay.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFiles/WaveformDisplay.cpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------
+//  Class for waveform display
+//
+//  2018/11/03, Copyright (c) 2018 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#include "WaveformDisplay.hpp"
+
+namespace Mikami
+{
+    void WaveformDisplay::Execute(int start, int factor)
+    {
+        Axis();
+        dt_ = factor;
+        Draw(xn_, start, LINE_COLOR1_);
+        lcd_.SetTextColor(BACK_COLOR_);
+    }
+        
+    // Clipping
+    uint16_t WaveformDisplay::Clip(int16_t xn)
+    {
+        int16_t x = xn >> R_SHIFT_;
+        if (x >  LIMIT_ ) x =  LIMIT2_;
+        if (x < -LIMIT_ ) x = -LIMIT2_ ;
+        return Y0_ - x;
+    }
+    
+    void WaveformDisplay::Draw(const Array<int16_t>& xn, int start, uint32_t color)
+    {
+        lcd_.SetTextColor(color);
+        uint16_t x1 = X0_;
+        uint16_t y1 = Clip(xn[start]);
+        for (int n=1; n<N_DATA_/dt_; n++)
+        {
+            uint16_t x2 = X0_ + n*dt_;
+            uint16_t y2 = Clip(xn[start+n]);
+            lcd_.DrawLine(x1, y1, x2, y2);
+
+            x1 = x2;
+            y1 = y2;
+        }
+    }
+
+    void WaveformDisplay::Axis()
+    {
+        lcd_.SetTextColor(BACK_COLOR_);
+        lcd_.FillRect(X0_, Y0_-LIMIT2_, N_DATA_, LIMIT2_*2+1);
+
+        lcd_.SetTextColor(AXIS_COLOR_);
+        lcd_.DrawLine(X0_-5, Y0_, X0_+N_DATA_+5, Y0_);
+    }        
+}
diff -r 000000000000 -r 31361b0fcdad MyFiles/WaveformDisplay.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFiles/WaveformDisplay.hpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,61 @@
+//-----------------------------------------------------------
+//  Class for waveform display ---- Header
+//
+//  2018/11/03, Copyright (c) 2018 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef F746_WAVEFORM_DISPLAY_HPP
+#define F746_WAVEFORM_DISPLAY_HPP
+
+#include "mbed.h"
+#include "LCD_DISCO_F746NG.h"
+#include "Array.hpp"
+
+namespace Mikami
+{
+    class WaveformDisplay
+    {
+    public:
+        WaveformDisplay(LCD_DISCO_F746NG &lcd,
+                        uint16_t x0, uint16_t y0,
+                        const Array<int16_t>& xn,
+                        uint16_t nData,
+                        uint16_t rShift,
+                        uint32_t axisColor,
+                        uint32_t lineColor1,
+                        uint32_t lineColor2,
+                        uint32_t backColor)
+            : X0_(x0), Y0_(y0), xn_(xn), N_DATA_(nData), R_SHIFT_(rShift),
+              AXIS_COLOR_(axisColor),
+              LINE_COLOR1_(lineColor1), LINE_COLOR2_(lineColor2),
+              BACK_COLOR_(backColor),
+              lcd_(lcd), dt_(1) { Axis(); }
+        
+        void Execute(int start, int factor);
+        
+    private:
+        const uint16_t X0_, Y0_;
+        const Array<int16_t>& xn_;
+        const int N_DATA_;
+        const uint16_t R_SHIFT_;
+        const uint32_t AXIS_COLOR_;
+        const uint32_t LINE_COLOR1_;
+        const uint32_t LINE_COLOR2_;
+        const uint32_t BACK_COLOR_;
+        static const int LIMIT_ = 64;
+        static const int LIMIT2_ = LIMIT_ + 1;
+
+        LCD_DISCO_F746NG &lcd_;
+
+        int dt_;
+
+        uint16_t Clip(int16_t xn);  // Clipping
+        void Draw(const Array<int16_t>& xn, int start, uint32_t color);
+        void Axis();
+
+        // disallow copy constructor and assignment operator
+        WaveformDisplay(const WaveformDisplay& );
+        WaveformDisplay& operator=(const WaveformDisplay& );
+    };
+}
+#endif  // F746_WAVEFORM_DISPLAY_HPP
diff -r 000000000000 -r 31361b0fcdad MyFiles/Zoom.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFiles/Zoom.hpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,62 @@
+//-----------------------------------------------------------
+//  時間軸の Zoom ボタン
+//
+//  2017/08/09, Copyright (c) 2017 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef ZOOM_BUTTON_HPP
+#define ZOOM_BUTTON_HPP
+
+#include "F746_GUI.hpp"
+#include "DelayedEnabler.hpp"
+
+namespace Mikami
+{
+    class ZoomButton
+    {
+    public:
+        // delay: ZoomButton がタッチされた後に再び有効になるまでの時間(単位:秒)
+        ZoomButton(uint16_t x0, uint16_t y0, uint16_t w0, uint16_t h0,
+                   uint32_t max, uint32_t min = 1, float delay = 0.2f)
+            : X0_(x0), Y0_(y0), W0_(w0), H0_(h0), 
+              MAX_(max), MIN_(min), delay_(delay), factor_(1)
+        {
+            zoom_ = new ButtonGroup(x0, y0, w0, h0, 2, (string[]){"-", "+"},
+                                    5, 0, 2);
+            zoom_->Inactivate(0);   // ズームアウトボタンは無効にする
+        }
+
+        // タッチした場合は factor を *2 または /2 する
+        bool Touched(int &factor)
+        {
+            if (!delay_.IsEnabled()) return false;
+            int num;
+            if (!zoom_->GetTouchedNumber(num)) return false;
+
+            // タッチ後一定の時間が経過してから,再びタッチの検出を有効にするため
+            delay_.Disable();
+
+            factor_ = (num == 1) ? factor_*2 : factor_/2;
+            if (factor_ > MAX_) factor_ = MAX_;
+            if (factor_ < MIN_) factor_ = MIN_;
+
+            zoom_->ActivateAll();
+            if (factor_ == MAX_) zoom_->Inactivate(num);
+            if (factor_ == MIN_) zoom_->Inactivate(num);
+
+            factor = factor_;
+
+            return true;
+        }
+
+    private:
+        const int X0_, Y0_, W0_, H0_;
+        const uint32_t MAX_;    // 最大値
+        const uint32_t MIN_;    // 最小値
+
+        ButtonGroup *zoom_;
+        DelayedEnabler delay_;
+        int factor_;
+    };
+}
+#endif  // ZOOM_BUTTON_HPP
diff -r 000000000000 -r 31361b0fcdad Random.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Random.lib	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/Random/#9a89ea736473
diff -r 000000000000 -r 31361b0fcdad main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,50 @@
+//-----------------------------------------------------------------
+//  正弦波+ノイズの発生器(標本化周波数:48 kHz)
+//      ノイズの大きさは SeekBar で変えられる
+//
+//  使用しているライブラリのリビジョン:
+//          F746_GUI            Rev.33
+//          F746_SAI_IO         Rev.12
+//          mbed                Rev.170
+//
+//  2018/11/04, Copyright (c) 2018 MIKAMI, Naoki
+//-----------------------------------------------------------------
+
+#include "SAI_InOut.hpp"
+#include "LcdPanelFrq.hpp"
+#include "GaussRand.hpp"
+
+int main()
+{
+    const int FS = I2S_AUDIOFREQ_48K;       // 標本化周波数:48 kHz
+    SaiIO mySai(SaiIO::OUTPUT, 2048, FS);   // オーディオ信号出力用
+    LcdPanel myPanel(1.0f/(float)FS);       // LCD パネル表示用
+    GaussRand rnd(0.5f, 0);                 // ガウス性ノイズ発生器
+
+    mySai.PlayOut();    // オーディオ信号出力開始
+
+    const float MAX_AMP = 8192.0f;
+    while (true)        // 無限ループ
+    {
+        // 出力バッファへの転送が完了したら以下の処理を行う
+        if (mySai.IsXferred())
+        {
+            for (int n=0; n<mySai.GetLength(); n++)
+            {
+                // 入力信号の生成
+                float phi = myPanel.GetPhi();
+                float sn = sinf(phi); // 入力信号となる正弦波を発生
+                float noize = myPanel.GetNoiseLevel()*rnd.Next();
+
+                int16_t xn = (int16_t)(MAX_AMP*sn);
+                int16_t yn = (int16_t)(MAX_AMP*(sn + noize));
+                mySai.Output(xn, yn);       // xn:ノイズなし(左チャンネル)
+                                            // yn:ノイズ付加(右チャンネル)
+                myPanel.Store(yn, n);       // 表示用として格納
+            }
+
+            myPanel.Display();  // 入出力信号の波形表示
+        }
+        myPanel.Update();   // パネルの状態を読み取り必要なパラメータなどを更新する
+    }
+}
diff -r 000000000000 -r 31361b0fcdad mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Nov 04 02:41:21 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/e95d10626187
\ No newline at end of file