//-------------------------------------------------------------------------
//	遮断周波数可変 LPF/HPF
//
//	マイコン側のプログラム： DSP_VariableLHpf
//		ボーレート：9600 baud
//
//		作成者：三上直樹，2022/12/17 作成，©三上直樹 2022
//-------------------------------------------------------------------------

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;

using Mikami.Application;
using Mikami.WindowsApplication;

namespace 遮断周波数可変IIRフィルタ
{
	public partial class Form1 : Form
	{
		private const float F_LOWEST_ = 100.0f;		// 遮断周波数の最小値
		private const float F_HIGHEST_ = 20000.0f;	// 遮断周波数の最大値
		private const float SAMPLING_FRQ_ = 44100;	// 標本化周波数, 44.1 kHz
		private const int	ORDER_ = 10;			// フィルタの次数

		private readonly Pen cursor_ = Pens.Magenta;	// 遮断周波数のカーソル用 Pen

		// シリアルポートと関連して使うクラスのオブジェクト
		private readonly MySerialPort sp_;
		// COM ポートの自動選択で使うクラスのオブジェクト
		private readonly AutoSelect comAuto_;
		// 周波数特性を描画するクラスのオブジェクト
		private readonly FrqResponsePlotter plotter_;

		private BiliearDesign iir_ = new BiliearDesign();
		private BiliearDesign.Type pb_;

		private bool paintOk_ = false;
		private float fC_ = 1000;			// 遮断周波数の初期値：1 kHz
		private bool mouseDown_ = false;	// マウスボタンを押した状態で true

		public Form1()
		{
			InitializeComponent();

			sp_ = new MySerialPort(serialPort1);
			comAuto_ = new AutoSelect("VrFc", sp_, toolStripLabel1);

			plotter_ = new FrqResponsePlotter(
						   pictureBox1,		// 表示される PictureBox
						   F_LOWEST_,		// 100 Hz から表示
						   F_HIGHEST_,		// 20 kHz まで表示
						   -60,				// -60 dB まで表示
						   SAMPLING_FRQ_);	// 標本化周波数
			pb_ = BiliearDesign.Type.LPF;	// 通過域のタイプの初期設定

			CommonProc.Disable(label1, groupBox1, panel1);

			// フィルタの設計，遮断周波数： 1 kHz
			iir_.Design(ORDER_, pb_, SAMPLING_FRQ_, fC_);

			// マウスのイベントハンドラを登録（簡単なもののみ）
			pictureBox1.MouseDown += (s, e) => mouseDown_ = true;
			pictureBox1.MouseUp += (s, e) => mouseDown_ = false;
		}

		// LPF と HPF の切り替え
		private void radioButton1_Click(object sender, EventArgs e)
		{
			pb_ = radioButton1.Checked ? BiliearDesign.Type.LPF : BiliearDesign.Type.HPF;
			RedesignDisplay();
			if (pb_ == BiliearDesign.Type.LPF) SendInt("L", fC_);
			else							   SendInt("H", fC_);
		}

		// フィルタ処理を有効/無効にする
		private void radioButton3_Click(object sender, EventArgs e)
		{
			if ((RadioButton)sender == radioButton3) sp_.SendTo("ACTIVE");
			else									 sp_.SendTo("THROUGH");
		}

		// 目盛値，軸のタイトルの描画
		private void Form1_Paint(object sender, PaintEventArgs e)
		{
			plotter_.DrawCharacters(e.Graphics);
		}

		// 周波数特性のカーブ，グラフの目盛線などの描画
		private void pictureBox1_Paint(object sender, PaintEventArgs e)
		{
			plotter_.DrawAxis(e.Graphics);	// 目盛線の描画
			if (!paintOk_) return;

			// 遮断周波数に対応するカーソルの描画
			plotter_.DrawVerticalLine(e.Graphics, cursor_, fC_);
			// 周波数特性のカーブの描画
			plotter_.DrawCurve(e.Graphics, Pens.Blue, iir_.GetResponse);
		}

		// データ受信イベントに対応するハンドラ
		private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
		{
			if (!sp_.IsOpen) return;
			string data = sp_.ReadLine();
			if (data == "ACK")
			{
				comAuto_.StopTimer();
				System.Threading.Thread.Sleep(50);	// 50 ms 待つ
				toolStripLabel1.Text = "マイコン側の準備ができました．";
				toolStripLabel2.Text = " " + sp_.PortName + " ";
				Invoke(() => CommonProc.Enable(label1, groupBox1, panel1));
				Invoke(() => label1.Text = "遮断周波数："
							+ (fC_/1000).ToString() + " kHz");

				Invoke(() => radioButton3.Checked = true);
				paintOk_ = true;
				Invoke(() => pictureBox1.Invalidate());
				sp_.SendTo("ACTIVE");	// フィルタ処理を有効にする指令
				SendInt("L", fC_);		// 最初は遮断周波数 1 kHz の LFP
			}
		}

		// マウスの移動で発生するイベントに対するイベントハンドラ
		private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
		{
			float frq = plotter_.ToFrequency(e.X);
			if ((frq < F_LOWEST_) || (frq > F_HIGHEST_)) return;

			MouseDrag(frq);
		}

		// 終了時の確認
		private void Form1_FormClosing(object sender, FormClosingEventArgs e)
		{
			ClosingCancel.Ok(sp_, e);
		}
	}
}
