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 MyTicker7
Revision 1:0430f1ed6c2c, committed 2021-10-06
- Comitter:
- MikamiUitOpen
- Date:
- Wed Oct 06 12:20:04 2021 +0000
- Parent:
- 0:53c0fa8a9aa2
- Commit message:
- 2
Changed in this revision
| MSeq16.hpp | 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 |
--- a/MSeq16.hpp Thu Sep 09 08:50:21 2021 +0000
+++ b/MSeq16.hpp Wed Oct 06 12:20:04 2021 +0000
@@ -1,7 +1,7 @@
//---------------------------------------------------------
-// M 系列信号発生器(N = 16)
+// M 系列信号発生器(N = 16)
//
-// 2021/08/23, Copyright (c) 2020 MIKAMI, Naoki
+// 2021/09/28, Copyright (c) 2021 MIKAMI, Naoki
//---------------------------------------------------------
#include "mbed.h"
@@ -11,32 +11,25 @@
namespace Mikami
{
- class MSeq16
- {
- public:
- MSeq16() : reg_(1) {}
+ class MSeq16
+ {
+ public:
+ MSeq16() : reg_(1) {}
- // 戻り値: 1 => 1, 0 => -1
- float Execute()
- {
- if ((reg_ & B_M_) == B_M_)
- {
- reg_ = ((reg_ ^ XOR_) << 1) | 1; // 1 の場合の処理
- return 0.5f;
- }
- else
- {
- reg_ = reg_ << 1; // 0 の場合の処理
- return -0.5f;
- }
- }
- private:
- static const uint16_t XOR_ = (1 << (2-1))
- | (1 << (3-1))
- | (1 << (5-1)); // XOR の位置に対応する定数
- static const uint16_t B_M_ = 1 << (16-1); // 16 段目に相当するビットを調べる
-
- uint16_t reg_;
- };
+ // 戻り値: 0 => -0.5, 1 => 0.5
+ float Execute()
+ {
+ msb_ = reg_ >> 15;
+ reg_ = ((reg_ ^ XOR_[msb_]) << 1) | msb_;
+ return RET_[msb_];
+ }
+ private:
+ static const uint16_t XOR_[2]; // XOR の一方の入力
+ static const float RET_[2]; // 戻り値として使用
+ uint16_t reg_; // 16 段の D フリップ・フロップに対応
+ uint16_t msb_; // 16 段目に相当するビット
+ };
+ const uint16_t MSeq16::XOR_[2] = { 0, 0x16 };
+ const float MSeq16::RET_[2] = { -0.5f, 0.5f };
}
-#endif // MSEQ16_HPP
\ No newline at end of file
+#endif // MSEQ16_HPP
\ No newline at end of file
--- a/main.cpp Thu Sep 09 08:50:21 2021 +0000
+++ b/main.cpp Wed Oct 06 12:20:04 2021 +0000
@@ -1,140 +1,144 @@
//----------------------------------------------------------------------
-// ファンクション・ジェネレータ (Nucleo-F446RE 用)
-// COM ポートの自動検出に対応(9600 baud)
+// ファンクション・ジェネレータ (Nucleo-F446RE 用)
+// COM ポートの自動検出に対応(9600 baud)
//
-// 設定できる項目
-// 波形の種類: 正弦波,矩形波,合成矩形波(フーリエ級数の5倍波までの和)
-// 振幅: 0.00 ~ 1.00 倍
-// 周波数: 10 Hz ~ 10 kHz
-// ノイズ付加の有無
-// 標本化間隔:2.5 μs
-// 使用タイマ:TIM7
-// 信号出力のピン: A2
+// 設定できる項目
+// 波形の種類: 正弦波,方形波,合成方形波(フーリエ級数の5倍波までの和)
+// 振幅: 0.00 ~ 1.00 倍
+// 周波数: 10 Hz ~ 10 kHz
+// ノイズ付加の有無
+// 標本化間隔:2.5 μs
+// 使用タイマ:TIM7
+// 信号出力のピン: A2
+// 同期信号出力のピン: A5
//
-// PC 側のプログラム
-// CQ_FunctionGenerator
+// PC 側のプログラム
+// CQ_FunctionGenerator
//
-// 2021/09/05, Copyright (c) 2021 MIKAMI, Naoki
+// 2021/09/29, Copyright (c) 2021 MIKAMI, Naoki
//----------------------------------------------------------------------
-#include "F446_DAC.hpp" // DA 変換器用
-#include "SerialRxTxIntr.hpp" // シリアル通信用
-#include "MyTicker7.hpp" // タイマ用
-#include "FastSin.hpp" // 高速低精度 sin 関数
-#include "MSeq16.hpp" // ノイズ発生器で使う M 系列信号発生器
-#include "IirCascade.hpp" // ノイズ発生器で使う低域通過フィルタ
-#include "CoefficientsLp4.hpp" // 低域通過フィルタの係数
-#include <cctype> // isalpha() で使用
+#include "F446_DAC.hpp" // DA 変換器用
+#include "SerialRxTxIntr.hpp" // シリアル通信用
+#include "MyTicker7.hpp" // タイマ用
+#include "FastSin.hpp" // 高速低精度 sin 関数
+#include "MSeq16.hpp" // ノイズ発生器で使う M 系列信号発生器
+#include "IirCascade.hpp" // ノイズ発生器で使う低域通過フィルタ
+#include "CoefficientsLp4.hpp" // 低域通過フィルタの係数
+#include <cctype> // isalpha() で使用
using namespace Mikami;
#ifndef __STM32F446xx_H
#error "Use Nucleo-F446RE"
#endif
-const float T0_ = 2.5f; // 出力の標本化間隔: 2.5 μs
+const float T0_ = 2.5f; // 出力の標本化間隔: 2.5 μs
const float C0_ = 4.0f;
const float C0_2_ = C0_/2.0f;
const float C0T0_ = C0_*T0_*1.0e-6f;
-MyTicker7 timer_(T0_); // タイマ割り込み用クラスのオブジェクト,TIM7 を利用
+MyTicker7 timer_(T0_); // タイマ割り込み用クラスのオブジェクト,TIM7 を利用
+DigitalOut sync_(A5); // 同期信号出力用
float phi_ = 0;
-float dPhi_ = C0T0_*1000; // 周波数決める変数,開始時は 1 kHz;
-float volume_ = 0.9f*0.5f; // 出力の振幅を決める変数,開始時は 0.45
-float volNoise_ = 0.5f; // ノイズの大きさを決める変数
+float dPhi_ = C0T0_*1000; // 周波数決める変数,開始時は 1 kHz;
+float volume_ = 0.9f*0.5f; // 出力の振幅を決める変数,開始時は 0.45
+float volNoise_ = 0.5f; // ノイズの大きさを決める変数
// DA 変換器に関する関数等
-DacF446 dac_; // DA 変換器オブジェクト
-void DacOut(float x) { dac_.Write(x); } // 引数の値を出力
+DacF446 dac_; // DA 変換器オブジェクト
+void DacOut(float x) { dac_.Write(x); } // 引数の値を出力
void DacZero(float x) { dac_.Write(0.0f); } // 0 を出力
-void (*fpDa)(float) = DacZero; // 起動時は 0 を出力
+void (*fpDa)(float) = DacZero; // 起動時は 0 を出力
// ノイズ付加に関する関数等
-MSeq16 mSeq_; // M 系列発生器
-IirCascade filter_(ORDER_, hk_, G0_); // 低域通過フィルタ
+MSeq16 mSeq_; // M 系列発生器
+IirCascade filter_(ORDER_, hk_, G0_); // 低域通過フィルタ
float Noise() { return volNoise_*filter_.Execute(mSeq_.Execute()); }
float NoiseFree() { return 0; }
-float (*fpN)() = NoiseFree; // 起動時はノイズなし
+float (*fpN)() = NoiseFree; // 起動時はノイズなし
// 発生する信号を定義する関数
// 正弦波
float Sin(float sinx) { return volume_*sinx + fpN(); }
-// 矩形波
+// 方形波
float Rect(float sinx)
{
- float x = (sinx >= 0) ? volume_ : -volume_;
- return x + fpN();
+ float x = (sinx >= 0) ? volume_ : -volume_;
+ return x + fpN();
}
-// 矩形波(合成,5倍波まで)
+// 合成方形波(5倍波まで)
float Syn(float sinx)
{
- static const float ONE_3 = 1.0f/3.0f; // フーリエ合成で使用
- static const float ONE_5 = 0.2f; // フーリエ合成で使用
+ 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;
+ 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();
+ return volume_*(sinx + ONE_3*sin3x + ONE_5*sin5x) + fpN();
}
-float (*fpS)(float) = Sin; // 起動時は正弦波
+float (*fpS)(float) = Sin; // 起動時は正弦波
// ラジオボタン,チェックボックスに対応する処理
void Select(string str)
{
- if (str == "On") fpDa = DacOut; // 選択された信号の出力
- if (str == "Off") fpDa = DacZero; // 0 を出力
+ if (str == "On") fpDa = DacOut; // 選択された信号の出力
+ if (str == "Off") fpDa = DacZero; // 0 を出力
- if (str == "Sin") fpS = Sin; // 正弦波
- if (str == "Rect") fpS = Rect; // 矩形波
- if (str == "Syn") fpS = Syn; // 矩形波(5倍波まで)
+ if (str == "Sin") fpS = Sin; // 正弦波
+ if (str == "Rect") fpS = Rect; // 方形波
+ if (str == "Syn") fpS = Syn; // 合成方形波
- if (str == "NsOn") fpN = Noise; // ノイズ付加
- if (str == "NsOff") fpN = NoiseFree; // ノイズなし
+ if (str == "NsOn") fpN = Noise; // ノイズ付加
+ if (str == "NsOff") fpN = NoiseFree; // ノイズなし
}
// スライダ(TrackBar)に対応する処理
void NumericCtrl(string str)
{
- char c1 = str[0]; // 先頭の文字を取得
- float x = atof(str.substr(1).c_str());
+ char c1 = str[0]; // 先頭の文字を取得
+ float x = atof(str.substr(1).c_str());
- if (c1 == '#') volume_ = x*0.9f; // 出力振幅の変更
- if (c1 == '$') dPhi_ = C0T0_*x; // 周波数の変更
- if (c1 == '%') volNoise_ = x; // ノイズの大きさの変更
+ if (c1 == '#') volume_ = x*0.9f; // 出力振幅の変更
+ if (c1 == '$') dPhi_ = C0T0_*x; // 周波数の変更
+ if (c1 == '%') volNoise_ = x; // ノイズの大きさの変更
}
// タイマ割り込みに対する割込みサービス・ルーチン
void TimerIsr()
{
- float sinx = FastSin(phi_); // 基本波発生
- fpDa(fpS(sinx)); // 指定された信号を出力
+ float sinx = FastSin(phi_); // 基本波発生
+ fpDa(fpS(sinx)); // 指定された信号を出力
+ GPIOC->BSRR = (sinx >= 0) ? // 同期信号を出力
+ 0x1 : 0x10000;
- phi_ += dPhi_;
- if (phi_ >= C0_2_) phi_ -= C0_; // オーバーフロー防止
+ phi_ += dPhi_;
+ if (phi_ >= C0_2_) phi_ -= C0_; // オーバーフロー防止
}
int main()
{
- SerialRxTxIntr rxTx; // PC との通信用,9600 baud
- // 以下の割り込み優先順位の設定を忘れないこと
- NVIC_SetPriority(TIM7_IRQn, 0); // 最優先
- NVIC_SetPriority(USART2_IRQn, 1); // USART2 割り込み:次に優先
+ SerialRxTxIntr rxTx; // PC との通信用,9600 baud
+ // 以下の割り込み優先順位の設定を忘れないこと
+ NVIC_SetPriority(TIM7_IRQn, 0); // 最優先
+ NVIC_SetPriority(USART2_IRQn, 1); // USART2 割り込み:次に優先
- timer_.Attach(&TimerIsr); // タイマ割り込み設定
-
- while (true) // PC からの指令に対応する処理
- {
- if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理
- {
- string str = rxTx.GetBuffer();
- if (str == "FG")
- rxTx.TxString("ACK\n"); // PC からの "FG" に対して "ACK" を送信する
- else
- if (isalpha(str[0])) // 先頭が A ~ Z, a ~ z の場合
- Select(str);
- else // 先頭が A ~ Z, a ~ z 以外の場合
- NumericCtrl(str);
- }
- }
+ timer_.Attach(&TimerIsr); // タイマ割り込み設定
+
+ while (true) // PC からの指令に対応する処理
+ {
+ if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理
+ {
+ string str = rxTx.GetBuffer();
+ if (str == "FG")
+ rxTx.TxString("ACK\n"); // PC からの "FG" に対して "ACK" を送信する
+ else
+ if (isalpha(str[0])) // 先頭が A ~ Z, a ~ z の場合
+ Select(str);
+ else // 先頭が A ~ Z, a ~ z 以外の場合
+ NumericCtrl(str);
+ }
+ }
}
\ No newline at end of file