ファンクション・ジェネレータ

Dependencies:   mbed SerialTxRxIntr MyTicker7 Array_Matrix

Revision:
0:17c762b41fc7
Child:
1:ea5aa7f3d68c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Oct 17 10:05:58 2020 +0000
@@ -0,0 +1,151 @@
+//----------------------------------------------------------------------
+//  ファンクション・ジェネレータ (Nucleo-F446RE 用)
+//
+//  設定できる項目
+//      波形の種類:  正弦波,矩形波,合成矩形波(フーリエ級数の5倍波までの和)
+//      振幅:         0.00 ~ 1.00 倍
+//      周波数:       10 Hz ~ 10 kHz
+//      ノイズ付加の有無
+//  標本化間隔:2.5 μs
+//  使用タイマ:TIM7
+//  信号出力のピン:      A2
+//  同期信号出力のピン:  A5
+//
+//  このプログラムの前のバージョン:F446_FunctionGenerator_7
+//
+//  PC 側のプログラム
+//      F446_FunctionGenerator
+//
+//  注意
+//      PC から送信されるコマンド等が不正かどうかはチェックしていない
+//
+//  2020/10/17, Copyright (c) 2020 MIKAMI, Naoki
+//----------------------------------------------------------------------
+
+#include "F446_DAC.hpp"
+#include "SerialRxTxIntr.hpp"
+#include "MyTicker7.hpp"
+#include "FastSin.hpp"
+#include "MSeq16.hpp"
+#include "IIR_Cascade.hpp"
+#include "CoefficientsIIR_Cascade.hpp"
+#include  <cctype>          // isalpha() で使用
+#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
+
+using namespace Mikami;
+                        
+const float T0_ = 2.5f;         // 出力の標本化間隔: 2.5 μs
+const float TS_ = T0_*1.0e-6f;
+const float C0_ = 4.0f;
+const float C0_2_ = C0_/2.0f;
+
+DacF446 dac_;                   // DA 変換器オブジェクト
+MyTicker7 timer_(T0_);          // タイマ割り込み用クラスのオブジェクト,TIM7 を利用
+SerialRxTxIntr rxTx_;           // Serial クラスの受送信割込み用オブジェクト
+DigitalOut syncOut_(A5);        // 同期信号出力用
+
+float phi_ = 0;
+float dPhi_ = C0_*1000*TS_;     // 周波数決める変数,開始時は 1 kHz;
+float volume_ = 0.5f;           // 出力の振幅を決める変数,開始時は 0.5
+bool sw_ = false;               // 出力 ON/OFF のスイッチ,開始時は off
+float volNoize_ = 0.5f;         // ノイズの大きさを決める変数
+
+// ノイズ付加に関する関数等
+MSeq16 mSeq_;
+IirCascade filter_(ORDER_, hk_, G0_);
+float Noise() { return volNoize_*filter_.Execute(0.5f*mSeq_.Execute()); }
+float NoiseFree() { return 0; }
+float (*fpNoize[])() = { Noise, NoiseFree };
+float (*fpN)() = fpNoize[1];    // 起動時はノイズなし 
+
+// 発生する信号を定義する関数
+// 正弦波
+float Sin(float sinx) { return volume_*sinx + fpN(); }
+// 矩形波
+float Rect(float sinx)
+{
+    float x = (sinx >= 0) ? volume_ : -volume_;
+    return x + volNoize_*fpN();
+}
+// 矩形波(5倍波まで)
+float Compo(float sinx)
+{
+    static const float ONE_3 = 1.0f/3.0f;   // フーリエ合成で使用
+    static const float ONE_5 = 0.2f;        // フーリエ合成で使用
+
+    float sinx2 = sinx*sinx;
+    float sin3x = (-4.0f*sinx2 + 3.0f)*sinx;
+    float sin5x = ((16.0f*sinx2 - 20.0f)*sinx2 + 5.0f)*sinx;
+
+    return volume_*(sinx + ONE_3*sin3x + ONE_5*sin5x) + fpN();
+}
+
+float (*fp[])(float x) = { Sin, Rect, Compo };
+float (*fpS)(float x) = fp[0];  // 起動時は正弦波
+
+// タイマ割り込みに対する割込みサービス・ルーチン
+void TimerIsr()
+{
+    float sinx = FastSin(phi_); // 基本波発生
+    float yn = fpS(sinx);       // 指定した信号を発生
+    
+    // 同期信号出力
+    syncOut_ = (sinx >= 0) ? 1 : 0;
+
+    if (sw_) dac_.Write(yn);    // 出力:ON
+    else     dac_.Write(0.0f);  // 出力:OFF
+
+    phi_ += dPhi_;
+    if (phi_ >= C0_2_) phi_ = phi_ - C0_;   // オーバーフロー防止
+}
+
+int main()
+{
+    // 以下の割り込み優先順位の設定を忘れないこと
+    NVIC_SetPriority(TIM7_IRQn, 0);
+    NVIC_SetPriority(USART2_IRQn, 1);   // USART2 割り込み:次に優先
+
+    timer_.Attach(&TimerIsr);       // タイマ割り込み設定
+    
+    while (true)    // PC からの指令に対応する処理
+    {
+        if (rxTx_.IsEol())          // 受信バッファのデータが有効になった場合の処理
+        {
+            string str = rxTx_.GetBuffer();
+            for (int n=0; n<str.size(); n++) str[n] = toupper(str[n]);
+            if (isalpha(str[0]))    // 先頭が A ~ Z, a ~ z の場合
+            {
+                if (str == "FG")
+                    rxTx_.TxString("ACK\n");    // PC からの "FG" に対して "ACK" を送信する
+
+                if (str == "ON")    sw_ = true;
+                if (str == "OFF")   sw_ = false;  
+
+                if (str == "SIN")   fpS = fp[0];
+                if (str == "RECT")  fpS = fp[1];
+                if (str == "COMPO") fpS = fp[2];
+
+                if (str == "NSON")  fpN = fpNoize[0];
+                if (str == "NSOFF") fpN = fpNoize[1];
+            }
+            else                    // 先頭が A ~ Z, a ~ z 以外の場合
+            {
+                char c1 = str[0];   // 先頭の文字を取得
+                float x = atof(str.substr(1, str.size()-1).c_str());
+                if (x >= 0.0f)
+                {
+                    if (c1 == '#')              // 出力振幅の変更
+                        volume_ = x*0.9f;
+                    if (c1 == '$')              // 周波数の変更
+                    {
+                        x = (x < 10) ? 10 : x;
+                        x = (x > 10000) ? 10000 : x;
+                        dPhi_ = C0_*x*TS_;
+                    }
+                    if (c1 == '%')              // ノイズの大きさの変更
+                        volNoize_ = (x < 1.0f) ? x : 1.0f;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file