ファンクション・ジェネレータ
Dependencies: mbed SerialTxRxIntr MyTicker7 Array_Matrix
Diff: main.cpp
- 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