//-----------------------------------------------------------------------------
//	ファンクション･ジェネレータ
//
//		マイコン側プログラム：TrG_FunctionGenerator
//		ボーレート：9600 baud
//
//		作成者：三上直樹，2022/05/15 作成，©三上直樹 2022
//-----------------------------------------------------------------------------

using System;
using System.Windows.Forms;
using System.Threading;
using System.IO.Ports;
using Mikami.Application;
using Mikami.WindowsApplication;

namespace CQ_FunctionGenerator
{
	public partial class Form1 : Form
	{
		private const int FRQ_MIN_ = 10;		// 最小の周波数 [Hz]
		private const int FRQ_MAX_ = 10000;		// 最大の周波数 [Hz]

		// シリアルポートと関連して使うクラスのオブジェクト
		private readonly MySerialPort sp_;
		// COM ポートの自動選択で使うクラスのオブジェクト
		private readonly AutoSelect comAuto_;

		public Form1()
		{
			InitializeComponent();

			CommonProc.Disable(button2, panel1, panel2, trackBar4, label10);
			ResetCtrl();
			sp_ = new MySerialPort(serialPort1);
			comAuto_ = new AutoSelect("FG", sp_, toolStripLabel1);
		}

		// リセット
		private void button1_Click(object sender, EventArgs e)
		{
			sp_.Break();		// ブレーク信号送出
			Thread.Sleep(50);	// 時間を少し空ける
			ResetCtrl();
			toolStripLabel1.Text = "リセットしました．出力は Off です．";
		}

		// 周波数微調整用 TrackBar をリセット
		private void button2_Click(object sender, EventArgs e)
		{
			trackBar3.Value = 0;
			label9.Text = "±0 Hz";

			trackBar2.Value = int.Parse(textBox1.Text);
			button2.Enabled = false;
		}

		// 出力する信号の種類を送信する（radioButton1，２，３）
		private void radioButton1_Click(object sender, EventArgs e)
		{
			if ((RadioButton)sender == radioButton1) sp_.SendTo("Sin");
			if ((RadioButton)sender == radioButton2) sp_.SendTo("Rect");
			if ((RadioButton)sender == radioButton3) sp_.SendTo("Syn");
		}

		// "On"/"Off" を送信する（radioButton4，5）
		private void radioButton4_Click(object sender, EventArgs e)
		{
			string str = ((RadioButton)sender == radioButton4) ?
						 "On" : "Off";
			sp_.SendTo(str);
			toolStripLabel1.Text = "出力は " + str + " です．";
		}

		// ノイズ付加あり，なしを送信する
		private void checkBox1_CheckedChanged(object sender, EventArgs e)
		{
			if (checkBox1.Checked)
			{
				sp_.SendTo("NsOn");		// ノイズ付加あり
				CommonProc.Enable(trackBar4, label10);
			}
			else
			{
				sp_.SendTo("NsOff");	// ノイズ付加なし
				CommonProc.Disable(trackBar4, label10);
			}
		}

		// 出力の振幅のコントロール
		private void trackBar1_Scroll(object sender, EventArgs e)
		{
			label1.Text = (trackBar1.Value*0.01).ToString("0.##");
			sp_.SendTo("#"+label1.Text);	// 振幅を送信する．先頭が "#"
		}

		// 周波数のコントロール
		private void trackBar2_Scroll(object sender, EventArgs e)
		{
			// 周波数の最小値の制限
			if (trackBar2.Value < FRQ_MIN_) trackBar2.Value = FRQ_MIN_;

			textBox1.Text = trackBar2.Value.ToString();
			sp_.SendTo("$"+textBox1.Text);	// 周波数を送信する．先頭が "$"
		}

		// 周波数の微調整
		private void trackBar3_Scroll(object sender, EventArgs e)
		{
			// 周波数微調整範囲の制限
			int max = FRQ_MAX_ - trackBar2.Value;
			if (trackBar3.Value > max) trackBar3.Value =max;	// 最大値の制限
			int min = FRQ_MIN_ - trackBar2.Value;
			if (trackBar3.Value < min) trackBar3.Value =min;	// 最小値の制限

			// trackBar3 の値を表示
			int tb3 = trackBar3.Value;
			if (tb3 > 0) label9.Text = "＋" + tb3.ToString() + " Hz";
			if (tb3 < 0) label9.Text = "ー" + (-tb3).ToString() + " Hz";
			if (tb3 == 0) label9.Text = "±0 Hz";

			textBox1.Text = (trackBar2.Value + tb3).ToString();
			sp_.SendTo("$"+textBox1.Text);	// 周波数を送信する．先頭が "$"

			button2.Enabled = (tb3 == 0) ? false : true;
		}

		// ノイズの大きさのコントロール
		private void trackBar4_Scroll(object sender, EventArgs e)
		{
			label10.Text = (trackBar4.Value*0.01).ToString("0.##");
			sp_.SendTo("%"+label10.Text);	// ノイズの振幅を送信する．先頭が "%"
		}

		// textBox1 から周波数のコントロール
		private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == (char)Keys.Escape) e.Handled = true;	// Esc のビープ音禁止
			if (e.KeyChar != (char)Keys.Enter) return;

			e.Handled = true;	// Enter のビープ音禁止
			if (!textBox1.ToDouble(
						out double x,
						v => (v >= FRQ_MIN_) && (v <= FRQ_MAX_),
						FRQ_MIN_.ToString() + " 以上 " +
						FRQ_MAX_.ToString() + " 以下にしてください．"))
				return;
			trackBar2.Value = (int)Math.Round(x+0.0001);
			trackBar2_Scroll(null, null);
		}

		// データ受信イベントに対応するハンドラ
		private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
		{
			string data = sp_.ReadLine();
			if (data == "ACK")
			{
				comAuto_.StopTimer();	// タイムアウト監視タイマを停止
				toolStripLabel1.Text = "マイコン側の準備ができました．出力は Off です．";
				toolStripLabel2.Text = " " + sp_.PortName + " ";
				Invoke(() => CommonProc.Enable(panel1, panel2));
			}
		}

		// アプリ終了の際の処理
		private void Form1_FormClosing(object sender, FormClosingEventArgs e)
		{
			sp_.Break();
			sp_.Close();
		}
	}
}
