#pragma once
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "Converter.h"
#include "ConvNorm.h"

struct PointG { double Latitude; double Longitude; };

float GPS_LocalDistance(PointG p1, PointG p2, float& dx, float& dy) // light formula
{
	const float pi = 3.14159265359;
	const float er = 6371000; // Radius of the earth in m

	float lat = p1.Latitude - p2.Latitude;
	float lon = p1.Longitude - p2.Longitude;

	float y = er / 360 * (lat * pi * 2); // lat
	dy = y;

	float l = ((float)(p1.Latitude + p2.Latitude)) / 2;
	float r = cosf(l * pi / 180) * er;
	float x = r / 360 * (lon * pi * 2); // long
	dx = x;

	float d = sqrtf(x * x + y * y);
	return d;
}
//------------------------------------------------------------------------------

float PlotsData[7];
bool PlotsReady = false;

HANDLE PortCOM;
HANDLE FileLOG;
HANDLE MainThread;

void SaveLogFile(HANDLE file, unsigned char data[28], unsigned long size)
{
	float table[7];
	memcpy(table, data, size);
	memcpy(PlotsData, data, size);
	PlotsReady = true;

	if (!file) return;

	char buf[1024];
	sprintf(buf, "%d|%f|%f|%f|%f|%f|%f\r\n", (int)table[0], table[1], table[2], table[3], table[4], table[5], table[6]);

	WriteFile(file, buf, strlen(buf), 0, 0);
}

unsigned long __stdcall RecvThread(void*)
{
	long wait = 0;

	private enum class RecvModeEnum : char { Begin, Data };

	bool mode = false;

	unsigned char data[29];
	unsigned long size;

	unsigned long len;

	while (1)
	{
		if (!PortCOM)
		{
			CloseHandle(MainThread);
			CloseHandle(FileLOG);
			MainThread = 0;
			return 0;
		}

		if (wait < GetTickCount()) mode = false;

		if(!mode)
		{
			wait = GetTickCount() + 20;
			
			ReadFile(PortCOM, data, 1, &len, 0);
			if (!len) continue;
			if (data[0] == 'Z') mode = true;
			size = 0;
		}

		if(mode)
		{
			ReadFile(PortCOM, data + size, sizeof(data) - size, &len, 0);
			if (!len) continue;
			size += len;
			if (size < sizeof(data)) continue;

			if (data[28] == 'V') SaveLogFile(FileLOG, data, sizeof(data) - 1);

			mode = false;
		}
		
	}
}

namespace HexapodControl
{

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::IO;

	/// <summary>
	/// Summary for Form1
	///
	/// WARNING: If you change the name of this class, you will need to change the
	///          'Resource File Name' property for the managed resource compiler tool
	///          associated with all .resx files this class depends on.  Otherwise,
	///          the designers will not be able to interact properly with localized
	///          resources associated with this form.
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
			//

		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		
		String^ RecordsFolder = "";
	private: System::Windows::Forms::OpenFileDialog^ openFileDialog_Open;
	private: System::Windows::Forms::Button^ button_File;
	private: System::Windows::Forms::GroupBox^ groupBox1;
	private: System::Windows::Forms::CheckedListBox^ checkedListBox_List;
	private: System::Windows::Forms::CheckBox^ checkBox_Auto;
	private: System::Windows::Forms::Label^ label2;
	private: System::Windows::Forms::Label^ label1;
	private: System::Windows::Forms::NumericUpDown^ numericUpDown_Graph_MinY;
	private: System::Windows::Forms::NumericUpDown^ numericUpDown_Track;
	private: System::Windows::Forms::Label^ label3;
	private: System::Windows::Forms::Panel^ panel_Opt;

	private: System::Windows::Forms::NumericUpDown^ numericUpDown_Gain;

	private: System::Windows::Forms::Label^ label4;
	private: System::Windows::Forms::Button^ button_Gain_Clear;
	private: System::Windows::Forms::NumericUpDown^ numericUpDown_Shift;
	private: System::Windows::Forms::Label^ label5;


	private: System::Windows::Forms::NumericUpDown^ numericUpDown_Graph_MaxY;

	protected:

	protected:
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::DataVisualization::Charting::Chart^ chart_Graph;
	protected:


	private: System::Windows::Forms::Panel^ panel1;
	private: System::Windows::Forms::Timer^ timer_Tick;

	private: System::Windows::Forms::Button^ button_Start;
	private: System::Windows::Forms::GroupBox^ groupBox_P1;
	private: System::Windows::Forms::ComboBox^ comboBox_Port;

	private: System::Windows::Forms::Button^ button_Connect;




	private: System::ComponentModel::IContainer^ components;
	private:
		/// <summary>
		/// Required designer variable.
		/// </summary>


#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->components = (gcnew System::ComponentModel::Container());
			System::Windows::Forms::DataVisualization::Charting::ChartArea^ chartArea1 = (gcnew System::Windows::Forms::DataVisualization::Charting::ChartArea());
			System::Windows::Forms::DataVisualization::Charting::Legend^ legend1 = (gcnew System::Windows::Forms::DataVisualization::Charting::Legend());
			System::Windows::Forms::DataVisualization::Charting::Series^ series1 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			System::Windows::Forms::DataVisualization::Charting::Series^ series2 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			System::Windows::Forms::DataVisualization::Charting::Series^ series3 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			System::Windows::Forms::DataVisualization::Charting::Series^ series4 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			System::Windows::Forms::DataVisualization::Charting::Series^ series5 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			System::Windows::Forms::DataVisualization::Charting::Series^ series6 = (gcnew System::Windows::Forms::DataVisualization::Charting::Series());
			this->chart_Graph = (gcnew System::Windows::Forms::DataVisualization::Charting::Chart());
			this->panel1 = (gcnew System::Windows::Forms::Panel());
			this->button_File = (gcnew System::Windows::Forms::Button());
			this->comboBox_Port = (gcnew System::Windows::Forms::ComboBox());
			this->button_Connect = (gcnew System::Windows::Forms::Button());
			this->button_Start = (gcnew System::Windows::Forms::Button());
			this->timer_Tick = (gcnew System::Windows::Forms::Timer(this->components));
			this->groupBox_P1 = (gcnew System::Windows::Forms::GroupBox());
			this->openFileDialog_Open = (gcnew System::Windows::Forms::OpenFileDialog());
			this->groupBox1 = (gcnew System::Windows::Forms::GroupBox());
			this->panel_Opt = (gcnew System::Windows::Forms::Panel());
			this->numericUpDown_Shift = (gcnew System::Windows::Forms::NumericUpDown());
			this->label5 = (gcnew System::Windows::Forms::Label());
			this->button_Gain_Clear = (gcnew System::Windows::Forms::Button());
			this->numericUpDown_Gain = (gcnew System::Windows::Forms::NumericUpDown());
			this->label4 = (gcnew System::Windows::Forms::Label());
			this->numericUpDown_Track = (gcnew System::Windows::Forms::NumericUpDown());
			this->label3 = (gcnew System::Windows::Forms::Label());
			this->label2 = (gcnew System::Windows::Forms::Label());
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->numericUpDown_Graph_MinY = (gcnew System::Windows::Forms::NumericUpDown());
			this->numericUpDown_Graph_MaxY = (gcnew System::Windows::Forms::NumericUpDown());
			this->checkBox_Auto = (gcnew System::Windows::Forms::CheckBox());
			this->checkedListBox_List = (gcnew System::Windows::Forms::CheckedListBox());
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->chart_Graph))->BeginInit();
			this->panel1->SuspendLayout();
			this->groupBox_P1->SuspendLayout();
			this->groupBox1->SuspendLayout();
			this->panel_Opt->SuspendLayout();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Shift))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Gain))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Track))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Graph_MinY))->BeginInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Graph_MaxY))->BeginInit();
			this->SuspendLayout();
			// 
			// chart_Graph
			// 
			chartArea1->Name = L"ChartArea1";
			this->chart_Graph->ChartAreas->Add(chartArea1);
			this->chart_Graph->Dock = System::Windows::Forms::DockStyle::Fill;
			legend1->Name = L"Legend1";
			this->chart_Graph->Legends->Add(legend1);
			this->chart_Graph->Location = System::Drawing::Point(3, 16);
			this->chart_Graph->Name = L"chart_Graph";
			series1->BorderWidth = 2;
			series1->ChartArea = L"ChartArea1";
			series1->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series1->Color = System::Drawing::Color::Red;
			series1->Legend = L"Legend1";
			series1->Name = L"gX";
			series1->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series1->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series2->BorderWidth = 2;
			series2->ChartArea = L"ChartArea1";
			series2->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series2->Color = System::Drawing::Color::Blue;
			series2->Legend = L"Legend1";
			series2->Name = L"gY";
			series2->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series2->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series3->BorderWidth = 2;
			series3->ChartArea = L"ChartArea1";
			series3->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series3->Color = System::Drawing::Color::Green;
			series3->Legend = L"Legend1";
			series3->Name = L"gZ";
			series3->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series3->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series4->ChartArea = L"ChartArea1";
			series4->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series4->Legend = L"Legend1";
			series4->Name = L"iX";
			series4->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series4->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series5->ChartArea = L"ChartArea1";
			series5->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series5->Legend = L"Legend1";
			series5->Name = L"iY";
			series5->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series5->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series6->ChartArea = L"ChartArea1";
			series6->ChartType = System::Windows::Forms::DataVisualization::Charting::SeriesChartType::FastLine;
			series6->Legend = L"Legend1";
			series6->Name = L"iZ";
			series6->XValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			series6->YValueType = System::Windows::Forms::DataVisualization::Charting::ChartValueType::Double;
			this->chart_Graph->Series->Add(series1);
			this->chart_Graph->Series->Add(series2);
			this->chart_Graph->Series->Add(series3);
			this->chart_Graph->Series->Add(series4);
			this->chart_Graph->Series->Add(series5);
			this->chart_Graph->Series->Add(series6);
			this->chart_Graph->Size = System::Drawing::Size(689, 669);
			this->chart_Graph->TabIndex = 1;
			this->chart_Graph->Text = L"chart1";
			// 
			// panel1
			// 
			this->panel1->Controls->Add(this->button_File);
			this->panel1->Controls->Add(this->comboBox_Port);
			this->panel1->Controls->Add(this->button_Connect);
			this->panel1->Controls->Add(this->button_Start);
			this->panel1->Dock = System::Windows::Forms::DockStyle::Left;
			this->panel1->Location = System::Drawing::Point(0, 0);
			this->panel1->Name = L"panel1";
			this->panel1->Size = System::Drawing::Size(135, 688);
			this->panel1->TabIndex = 2;
			// 
			// button_File
			// 
			this->button_File->Location = System::Drawing::Point(29, 611);
			this->button_File->Name = L"button_File";
			this->button_File->Size = System::Drawing::Size(75, 23);
			this->button_File->TabIndex = 4;
			this->button_File->Text = L"File";
			this->button_File->UseVisualStyleBackColor = true;
			this->button_File->Click += gcnew System::EventHandler(this, &Form1::button_File_Click);
			// 
			// comboBox_Port
			// 
			this->comboBox_Port->FormattingEnabled = true;
			this->comboBox_Port->Location = System::Drawing::Point(8, 12);
			this->comboBox_Port->Name = L"comboBox_Port";
			this->comboBox_Port->Size = System::Drawing::Size(121, 21);
			this->comboBox_Port->TabIndex = 3;
			this->comboBox_Port->DropDown += gcnew System::EventHandler(this, &Form1::comboBox_Port_DropDown);
			// 
			// button_Connect
			// 
			this->button_Connect->Location = System::Drawing::Point(8, 39);
			this->button_Connect->Name = L"button_Connect";
			this->button_Connect->Size = System::Drawing::Size(121, 23);
			this->button_Connect->TabIndex = 2;
			this->button_Connect->Text = L"Connect";
			this->button_Connect->UseVisualStyleBackColor = true;
			this->button_Connect->Click += gcnew System::EventHandler(this, &Form1::button_Connect_Click);
			// 
			// button_Start
			// 
			this->button_Start->Dock = System::Windows::Forms::DockStyle::Bottom;
			this->button_Start->Location = System::Drawing::Point(0, 653);
			this->button_Start->Name = L"button_Start";
			this->button_Start->Size = System::Drawing::Size(135, 35);
			this->button_Start->TabIndex = 1;
			this->button_Start->Text = L"Start";
			this->button_Start->UseVisualStyleBackColor = true;
			this->button_Start->Click += gcnew System::EventHandler(this, &Form1::button_Start_Click);
			// 
			// timer_Tick
			// 
			this->timer_Tick->Interval = 10;
			this->timer_Tick->Tick += gcnew System::EventHandler(this, &Form1::timer_Tick_Tick);
			// 
			// groupBox_P1
			// 
			this->groupBox_P1->Controls->Add(this->chart_Graph);
			this->groupBox_P1->Dock = System::Windows::Forms::DockStyle::Fill;
			this->groupBox_P1->Location = System::Drawing::Point(135, 0);
			this->groupBox_P1->MinimumSize = System::Drawing::Size(676, 688);
			this->groupBox_P1->Name = L"groupBox_P1";
			this->groupBox_P1->Size = System::Drawing::Size(695, 688);
			this->groupBox_P1->TabIndex = 3;
			this->groupBox_P1->TabStop = false;
			// 
			// openFileDialog_Open
			// 
			this->openFileDialog_Open->FileName = L"openFileDialog1";
			this->openFileDialog_Open->Multiselect = true;
			// 
			// groupBox1
			// 
			this->groupBox1->Controls->Add(this->panel_Opt);
			this->groupBox1->Controls->Add(this->numericUpDown_Track);
			this->groupBox1->Controls->Add(this->label3);
			this->groupBox1->Controls->Add(this->label2);
			this->groupBox1->Controls->Add(this->label1);
			this->groupBox1->Controls->Add(this->numericUpDown_Graph_MinY);
			this->groupBox1->Controls->Add(this->numericUpDown_Graph_MaxY);
			this->groupBox1->Controls->Add(this->checkBox_Auto);
			this->groupBox1->Controls->Add(this->checkedListBox_List);
			this->groupBox1->Dock = System::Windows::Forms::DockStyle::Right;
			this->groupBox1->Location = System::Drawing::Point(830, 0);
			this->groupBox1->Name = L"groupBox1";
			this->groupBox1->Size = System::Drawing::Size(128, 688);
			this->groupBox1->TabIndex = 4;
			this->groupBox1->TabStop = false;
			this->groupBox1->Text = L" options ";
			// 
			// panel_Opt
			// 
			this->panel_Opt->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
			this->panel_Opt->Controls->Add(this->numericUpDown_Shift);
			this->panel_Opt->Controls->Add(this->label5);
			this->panel_Opt->Controls->Add(this->button_Gain_Clear);
			this->panel_Opt->Controls->Add(this->numericUpDown_Gain);
			this->panel_Opt->Controls->Add(this->label4);
			this->panel_Opt->Dock = System::Windows::Forms::DockStyle::Bottom;
			this->panel_Opt->Enabled = false;
			this->panel_Opt->Location = System::Drawing::Point(3, 245);
			this->panel_Opt->Name = L"panel_Opt";
			this->panel_Opt->Size = System::Drawing::Size(122, 440);
			this->panel_Opt->TabIndex = 8;
			// 
			// numericUpDown_Shift
			// 
			this->numericUpDown_Shift->DecimalPlaces = 3;
			this->numericUpDown_Shift->Increment = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1, 0, 0, 65536 });
			this->numericUpDown_Shift->Location = System::Drawing::Point(36, 8);
			this->numericUpDown_Shift->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, 0 });
			this->numericUpDown_Shift->Minimum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, System::Int32::MinValue });
			this->numericUpDown_Shift->Name = L"numericUpDown_Shift";
			this->numericUpDown_Shift->Size = System::Drawing::Size(75, 20);
			this->numericUpDown_Shift->TabIndex = 6;
			this->numericUpDown_Shift->ValueChanged += gcnew System::EventHandler(this, &Form1::numericUpDown_Gain_ValueChanged);
			// 
			// label5
			// 
			this->label5->AutoSize = true;
			this->label5->Location = System::Drawing::Point(6, 10);
			this->label5->Name = L"label5";
			this->label5->Size = System::Drawing::Size(31, 13);
			this->label5->TabIndex = 5;
			this->label5->Text = L"Shift:";
			// 
			// button_Gain_Clear
			// 
			this->button_Gain_Clear->Location = System::Drawing::Point(9, 60);
			this->button_Gain_Clear->Name = L"button_Gain_Clear";
			this->button_Gain_Clear->Size = System::Drawing::Size(102, 23);
			this->button_Gain_Clear->TabIndex = 4;
			this->button_Gain_Clear->Text = L"clean";
			this->button_Gain_Clear->UseVisualStyleBackColor = true;
			this->button_Gain_Clear->Click += gcnew System::EventHandler(this, &Form1::button_Gain_Clear_Click);
			// 
			// numericUpDown_Gain
			// 
			this->numericUpDown_Gain->DecimalPlaces = 3;
			this->numericUpDown_Gain->Increment = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1, 0, 0, 131072 });
			this->numericUpDown_Gain->Location = System::Drawing::Point(36, 34);
			this->numericUpDown_Gain->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1000, 0, 0, 0 });
			this->numericUpDown_Gain->Minimum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1, 0, 0, 196608 });
			this->numericUpDown_Gain->Name = L"numericUpDown_Gain";
			this->numericUpDown_Gain->Size = System::Drawing::Size(75, 20);
			this->numericUpDown_Gain->TabIndex = 3;
			this->numericUpDown_Gain->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1, 0, 0, 0 });
			this->numericUpDown_Gain->ValueChanged += gcnew System::EventHandler(this, &Form1::numericUpDown_Gain_ValueChanged);
			// 
			// label4
			// 
			this->label4->AutoSize = true;
			this->label4->Location = System::Drawing::Point(6, 36);
			this->label4->Name = L"label4";
			this->label4->Size = System::Drawing::Size(32, 13);
			this->label4->TabIndex = 0;
			this->label4->Text = L"Gain:";
			// 
			// numericUpDown_Track
			// 
			this->numericUpDown_Track->Location = System::Drawing::Point(41, 219);
			this->numericUpDown_Track->Minimum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1, 0, 0, 0 });
			this->numericUpDown_Track->Name = L"numericUpDown_Track";
			this->numericUpDown_Track->Size = System::Drawing::Size(57, 20);
			this->numericUpDown_Track->TabIndex = 7;
			this->numericUpDown_Track->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) { 10, 0, 0, 0 });
			// 
			// label3
			// 
			this->label3->AutoSize = true;
			this->label3->Location = System::Drawing::Point(3, 221);
			this->label3->Name = L"label3";
			this->label3->Size = System::Drawing::Size(38, 13);
			this->label3->TabIndex = 6;
			this->label3->Text = L"Track:";
			// 
			// label2
			// 
			this->label2->AutoSize = true;
			this->label2->Location = System::Drawing::Point(6, 187);
			this->label2->Name = L"label2";
			this->label2->Size = System::Drawing::Size(37, 13);
			this->label2->TabIndex = 5;
			this->label2->Text = L"Min Y:";
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->Location = System::Drawing::Point(3, 161);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(40, 13);
			this->label1->TabIndex = 4;
			this->label1->Text = L"Max Y:";
			// 
			// numericUpDown_Graph_MinY
			// 
			this->numericUpDown_Graph_MinY->Location = System::Drawing::Point(50, 185);
			this->numericUpDown_Graph_MinY->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, 0 });
			this->numericUpDown_Graph_MinY->Minimum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, System::Int32::MinValue });
			this->numericUpDown_Graph_MinY->Name = L"numericUpDown_Graph_MinY";
			this->numericUpDown_Graph_MinY->Size = System::Drawing::Size(75, 20);
			this->numericUpDown_Graph_MinY->TabIndex = 3;
			this->numericUpDown_Graph_MinY->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1000, 0, 0, System::Int32::MinValue });
			this->numericUpDown_Graph_MinY->ValueChanged += gcnew System::EventHandler(this, &Form1::numericUpDown_Graph_MaxY_ValueChanged);
			// 
			// numericUpDown_Graph_MaxY
			// 
			this->numericUpDown_Graph_MaxY->Location = System::Drawing::Point(50, 159);
			this->numericUpDown_Graph_MaxY->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, 0 });
			this->numericUpDown_Graph_MaxY->Minimum = System::Decimal(gcnew cli::array< System::Int32 >(4) { 32000, 0, 0, System::Int32::MinValue });
			this->numericUpDown_Graph_MaxY->Name = L"numericUpDown_Graph_MaxY";
			this->numericUpDown_Graph_MaxY->Size = System::Drawing::Size(75, 20);
			this->numericUpDown_Graph_MaxY->TabIndex = 2;
			this->numericUpDown_Graph_MaxY->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) { 1000, 0, 0, 0 });
			this->numericUpDown_Graph_MaxY->ValueChanged += gcnew System::EventHandler(this, &Form1::numericUpDown_Graph_MaxY_ValueChanged);
			// 
			// checkBox_Auto
			// 
			this->checkBox_Auto->AutoSize = true;
			this->checkBox_Auto->Location = System::Drawing::Point(17, 134);
			this->checkBox_Auto->Name = L"checkBox_Auto";
			this->checkBox_Auto->Size = System::Drawing::Size(47, 17);
			this->checkBox_Auto->TabIndex = 1;
			this->checkBox_Auto->Text = L"auto";
			this->checkBox_Auto->UseVisualStyleBackColor = true;
			this->checkBox_Auto->CheckedChanged += gcnew System::EventHandler(this, &Form1::checkBox_Auto_CheckedChanged);
			// 
			// checkedListBox_List
			// 
			this->checkedListBox_List->Dock = System::Windows::Forms::DockStyle::Top;
			this->checkedListBox_List->FormattingEnabled = true;
			this->checkedListBox_List->Location = System::Drawing::Point(3, 16);
			this->checkedListBox_List->Name = L"checkedListBox_List";
			this->checkedListBox_List->Size = System::Drawing::Size(122, 109);
			this->checkedListBox_List->TabIndex = 0;
			this->checkedListBox_List->SelectedIndexChanged += gcnew System::EventHandler(this, &Form1::checkedListBox_List_SelectedIndexChanged);
			this->checkedListBox_List->DoubleClick += gcnew System::EventHandler(this, &Form1::checkedListBox_List_SelectedIndexChanged);
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(958, 688);
			this->Controls->Add(this->groupBox_P1);
			this->Controls->Add(this->groupBox1);
			this->Controls->Add(this->panel1);
			this->MinimumSize = System::Drawing::Size(974, 727);
			this->Name = L"Form1";
			this->Text = L"Telemetry";
			this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->chart_Graph))->EndInit();
			this->panel1->ResumeLayout(false);
			this->groupBox_P1->ResumeLayout(false);
			this->groupBox1->ResumeLayout(false);
			this->groupBox1->PerformLayout();
			this->panel_Opt->ResumeLayout(false);
			this->panel_Opt->PerformLayout();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Shift))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Gain))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Track))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Graph_MinY))->EndInit();
			(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown_Graph_MaxY))->EndInit();
			this->ResumeLayout(false);

		}
#pragma endregion

		private: void ToCharString(String^ str1, char* str2)
		{
			for (int a = 0; a < str1->Length; a++) *str2++ = str1[a];
			*str2 = '\0';
		}

		private: System::Void button_Connect_Click(System::Object^ sender, System::EventArgs^ e) 
		{
			if (button_Connect->Text == "Connect")
			{
				char text[128] = "\\\\.\\";

				ToCharString(comboBox_Port->Text, text + 4);

				PortCOM = CreateFileA(text, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
				if (PortCOM == INVALID_HANDLE_VALUE)
				{
					PortCOM = 0;
					MessageBox::Show("Error to connect", "Error", MessageBoxButtons::OK, MessageBoxIcon::Error);
					return;
				}
				//---
				DCB serial = { sizeof(serial) };
				GetCommState(PortCOM, &serial);
				serial.BaudRate = 460800;
				serial.ByteSize = 8;
				serial.StopBits = ONESTOPBIT;
				serial.Parity = NOPARITY;
				SetCommState(PortCOM, &serial);
				//---
				COMMTIMEOUTS tim;
				GetCommTimeouts(PortCOM, &tim);
				tim.ReadIntervalTimeout = 1;
				tim.ReadTotalTimeoutConstant = 1;
				tim.ReadTotalTimeoutMultiplier = 1;
				SetCommTimeouts(PortCOM, &tim);
				//---
				timer_Tick->Enabled = true;
				button_Connect->Text = "Disonnect";
				//---
				for (int a = 0; a < chart_Graph->Series->Count; a++) chart_Graph->Series[a]->Points->Clear();
				//---
				MainThread = CreateThread(0, 0, RecvThread, 0, 0, 0);
			}
			else
			{
				CloseHandle(PortCOM);
				PortCOM = 0;
			  timer_Tick->Enabled = false;
				button_Connect->Text = "Connect";
			}
		}

		private: System::Void comboBox_Port_DropDown(System::Object^ sender, System::EventArgs^ e)
		{
			comboBox_Port->Items->Clear();
			for each (String ^ p in System::IO::Ports::SerialPort::GetPortNames())
			{
				comboBox_Port->Items->Add(p);
			}
		}

		private: System::Void timer_Tick_Tick(System::Object^ sender, System::EventArgs^ e) 
		{
			if (!PlotsReady) return;
			PlotsReady = false;

			for (int a = 0; a < chart_Graph->Series->Count; a++)
			{
				chart_Graph->Series[a]->Points->AddY((double)PlotsData[a + 1]);
				while (chart_Graph->Series[a]->Points->Count > numericUpDown_Track->Value * 100) chart_Graph->Series[a]->Points->RemoveAt(0);
			}
		}

	  private: System::Void button_Start_Click(System::Object^ sender, System::EventArgs^ e)
		{
			if (button_Start->Text=="Stop")
			{
				if (FileLOG) CloseHandle(FileLOG);
				FileLOG = 0;
				button_Start->Text = "Start";
				return;
			}

			DateTime dt = DateTime::Now;
			String^ file = Path::Combine(RecordsFolder, "record=" + dt.ToString("yyyy-MM-dd+HH_mm_ss") + ".tel");
			try
			{
				char text[256];

				ToCharString(file, text);

				FileLOG = CreateFileA(text, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
				if (FileLOG == INVALID_HANDLE_VALUE)
				{
					FileLOG = 0;
					MessageBox::Show("Error to create file", "Error", MessageBoxButtons::OK, MessageBoxIcon::Error); 
					return;
				}
				button_Start->Text = "Stop";
			}
			catch(...)
			{
				MessageBox::Show("Incorrect save file!", "Error", MessageBoxButtons::OK, MessageBoxIcon::Error);
			}
	  }

    private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) 
		{
			try
			{
				String^ folder = Environment::GetFolderPath(Environment::SpecialFolder::ApplicationData);
				String^ specificFolder = Path::Combine(folder, "Telem");
				//---
				RecordsFolder = Path::Combine(specificFolder, "Records");
				Directory::CreateDirectory(RecordsFolder);

				openFileDialog_Open->InitialDirectory = RecordsFolder;
			}
			catch(...) { }

			for each (auto s in chart_Graph->Series)
			{
				checkedListBox_List->Items->Add(s->Name, true);
			}

			MainDataRecord->Clear();
			for (int a = 0; a < 6; a++) { MainDataGain[a] = 1; MainDataShift[a] = 0; }

			numericUpDown_Graph_MaxY_ValueChanged(sender, e);
    }

		private: System::Collections::Generic::List<array<double>^>^ MainDataRecord = gcnew System::Collections::Generic::List<array<double>^>();
		private: array<double>^ MainDataGain = gcnew array<double>(6);
	  private: array<double>^ MainDataShift = gcnew array<double>(6);

	  private: System::Void button_File_Click(System::Object^ sender, System::EventArgs^ e)
		{
			if (openFileDialog_Open->ShowDialog() != System::Windows::Forms::DialogResult::OK) return;

			CloseHandle(PortCOM);
			PortCOM = 0;
			timer_Tick->Enabled = false;
			button_Connect->Text = "Connect";

			for (int a = 0; a < chart_Graph->Series->Count; a++)
			{
				chart_Graph->Series[a]->Points->Clear();
			}

			MainDataRecord->Clear();
			for (int a = 0; a < 6; a++) { MainDataGain[a] = 1; MainDataShift[a] = 0; }
			panel_Opt->Enabled = true;

			System::Globalization::CultureInfo^ nonInvariantCulture = gcnew System::Globalization::CultureInfo("en-US");
			nonInvariantCulture->NumberFormat->NumberDecimalSeparator = ".";
			System::Threading::Thread::CurrentThread->CurrentCulture = nonInvariantCulture;

			array<String^>^ text = File::ReadAllLines(openFileDialog_Open->FileName);

			static bool first = false;
			static PointG fff = { 47.31941467, 38.78046767 };

			static int counter = 0;

			for each (String ^ line in text)
			{
				array<String^>^ elems =line->Split(',');
				if (elems->Length < 6) continue;
				if (elems[0][0] == 'G')
				{
					PointG g;

					for (int a = 3, b=0; a < 6; a++, b++)
					{
						double v = Convert::ToDouble(elems[a]);
						if (b == 1) g.Latitude = v;
						if (b == 2) g.Longitude = v;
					}

					if (!first)
					{
						first = true;
						fff = g;
					}

					static float ldx=0, ldy=0;

					float dx, dy;

					static float cdx = 0, cdy = 0;

					float dis = GPS_LocalDistance(fff, g, dx, dy);

					/*if (counter > 1)
					{
						cdx = (cdx*2 + (dx - ldx)) / 3;
						cdy = (cdy*2 + (dy - ldy)) / 3;

						chart_Graph->Series[0]->Points->AddY(cdx);
						chart_Graph->Series[1]->Points->AddY(cdy);
						ldx = dx;
						ldy = dy;
						counter = 0;
					}
					else counter++;*/
					
					chart_Graph->Series[0]->Points->AddY(dx);
					chart_Graph->Series[1]->Points->AddY(dy);
					chart_Graph->Series[2]->Points->AddY(dis);
				}
			}
	  }

	  private: System::Void checkedListBox_List_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e) 
		{
			for (int a = 0; a < checkedListBox_List->Items->Count; a++)
			{
				chart_Graph->Series[a]->Enabled = checkedListBox_List->GetItemChecked(a);
			}
			int index = checkedListBox_List->SelectedIndex;
			if (index == -1) return;
			numericUpDown_Gain->Value = (Decimal)MainDataGain[index];
			numericUpDown_Shift->Value = (Decimal)MainDataShift[index];
	  }
    private: System::Void checkBox_Auto_CheckedChanged(System::Object^ sender, System::EventArgs^ e)
		{
			if (checkBox_Auto->Checked)
			{
				chart_Graph->ChartAreas[0]->AxisY->Minimum = double::NaN;
				chart_Graph->ChartAreas[0]->AxisY->Maximum = double::NaN;
				numericUpDown_Graph_MinY->Enabled = false;
				numericUpDown_Graph_MaxY->Enabled = false;
			}
			else
			{
				numericUpDown_Graph_MaxY_ValueChanged(sender, e);
				numericUpDown_Graph_MinY->Enabled = true;
				numericUpDown_Graph_MaxY->Enabled = true;

			}
    }
    private: System::Void numericUpDown_Graph_MaxY_ValueChanged(System::Object^ sender, System::EventArgs^ e)
		{
			chart_Graph->ChartAreas[0]->AxisY->Minimum = (double)numericUpDown_Graph_MinY->Value;
			chart_Graph->ChartAreas[0]->AxisY->Maximum = (double)numericUpDown_Graph_MaxY->Value;
    }

    private: System::Void numericUpDown_Gain_ValueChanged(System::Object^ sender, System::EventArgs^ e)
		{
			int index = checkedListBox_List->SelectedIndex;
			if (index == -1) return;
			chart_Graph->Series[index]->Points->Clear();
			for (int a = 0; a < MainDataRecord->Count; a++)
			{
				array<double>^ values = MainDataRecord[a];
				chart_Graph->Series[index]->Points->AddY((Convert::ToDouble(numericUpDown_Shift->Value) + values[index]) * Convert::ToDouble(numericUpDown_Gain->Value));
			}
			MainDataGain[index] = Convert::ToDouble(numericUpDown_Gain->Value);
			MainDataShift[index] = Convert::ToDouble(numericUpDown_Shift->Value);
    }

	  private: System::Void button_Gain_Clear_Click(System::Object^ sender, System::EventArgs^ e)
		{
			for (int a = 0; a < 6; a++)
			{
				MainDataGain[a] = 1;
				MainDataShift[a] = 0;
				chart_Graph->Series[a]->Points->Clear();
			}

			for (int a = 0; a < 6; a++)
			{
				for (int b = 0; b < MainDataRecord->Count; b++)
				{
					array<double>^ values = MainDataRecord[b];
					chart_Graph->Series[a]->Points->AddY(values[a]);
				}
			}

			numericUpDown_Gain->Value = 1;
			numericUpDown_Shift->Value = 0;
	  }
};
}

