ノイズを付加した正弦波発生器 Sinusoidal wave generator with noise.
Dependencies: F746_GUI F746_SAI_IO Random mbed
Revision 0:31361b0fcdad, committed 2018-11-04
- Comitter:
- MikamiUitOpen
- Date:
- Sun Nov 04 02:41:21 2018 +0000
- Commit message:
- 1
Changed in this revision
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