#include "Arduino.h"
#include <MsTimer2.h>   // MsTimer2 v1.1
#include <Ethernet2.h>  // Ethernet2 v1.0.4
#include "GP8403.h"

/* ---------- Periodics ---------- */
// Flags
bool T_1ms = false;
bool T_2ms = false;
bool T_5ms = false;
bool T_10ms = false;
bool T_20ms = false;
bool T_50ms = false;
bool T_100ms = false;
bool T_200ms = false;
bool T_500ms = false;
bool T_1000ms = false;
bool T_2000ms = false;
bool T_5000ms = false;

// Datas
int msCnt = 0;
unsigned long timer = 0;
#define AI_AVG_SIZE 50
#define AI_RANGE  8

/* ---------- Arduino Mega 2560 Basic IO ---------- */
// Pins
const int DoPin[] = { 34, 35, 36, 37, 38, 39, 40, 41,
                      42, 43, 44, 45, 46, 47, 48, 49};
const int DiPin[] = { 26, 27, 28, 29, 30, 31, 32, 33};   
const int AiPin[] = { A0, A1, A2, A3, A4, A5, A6, A7, 
                      A8, A9, A10, A11, A12, A13, A14, A15};

// Data Storages
int Size_DO = 16;
int Size_DI = 8;
int Size_AI = AI_RANGE;
int index_AI = 0;

int Values_DI;    // digit values to a number
int Values_AI[AI_RANGE];
int Recent_AI[AI_RANGE][AI_AVG_SIZE];

/* ---------- I2C (Analog Output, DAC) ---------- */
// Addresses
DFRobot_GP8403 AO_0(&Wire,0x58);
DFRobot_GP8403 AO_2(&Wire,0x59);
DFRobot_GP8403 AO_4(&Wire,0x5A);
DFRobot_GP8403 AO_6(&Wire,0x5B);
DFRobot_GP8403 AO_8(&Wire,0x5C);
DFRobot_GP8403 AO_10(&Wire,0x5D);
DFRobot_GP8403 AO_12(&Wire,0x5E);
DFRobot_GP8403 AO_14(&Wire,0x5F);

// Data Storage
int RngAO[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

/* ---------- Ethernet (Ethernet Sheld2) ---------- */
// Ethernet Client
EthernetClient client;
// SCPI defaults to port 5025
EthernetServer server(5025);
// HTTP defaults to port 5025
EthernetServer web(80);

unsigned long lastDataReceivedTime;
unsigned long timeoutPeriod = 5000;  // 이더넷 타임아웃 시간 (5초)

bool State_eth = false;

HardwareSerial* Serials[] = {&Serial1, &Serial2};

const int BUFF_SIZE = 1024;
char Buff_Eth_Rd[BUFF_SIZE] = {0};
char Buff_485_1_Wr[BUFF_SIZE] = {0};
char Buff_485_1_Rd[BUFF_SIZE] = {0};
char Buff_485_2_Wr[BUFF_SIZE] = {0};
char Buff_485_2_Rd[BUFF_SIZE] = {0};

String latest_sent_msg;
int numOf485 = 0;
int returnTime = 0;

/* ---------- RS485 ---------- */
// 485 CH 1
bool Wait_485_1;
int Wait_485_1_cnt;
int RS485_1_Addr[2] = {0,0};
bool RS485_1_Rcv_PV[2] = {false, false};
bool RS485_1_Rcv_SV[2] = {false, false};
int RS485_1_Rcv_size = 8;
int RS485_1_Values_PV[8*2];
int RS485_1_Values_SV[8*2];

// 485 CH 2
bool Wait_485_2;
int Wait_485_2_cnt;
int RS485_2_Addr[2];
bool RS485_2_Rcv_PV[2];
bool RS485_2_Rcv_SV[2];
int RS485_2_Rcv_size = 8;
int RS485_2_Values_PV[8*2];
int RS485_2_Values_SV[8*2];


//Processes
String Prcss_ALL_Read();
String Prcss_DO_Write(unsigned int data[], int dataSize);
String Prcss_DI_Read();
String Prcss_AI_Read();
String Prcss_AO_Write(unsigned int data[], int dataSize);
String Prcss_PV_Read();
String Prcss_SV_Read();
String Prcss_SV_Write(unsigned int data[], int dataSize);
String Prcss_AT_Write(unsigned int data[], int dataSize);
String Prcss_RngAO(unsigned int data[], int dataSize);
String Prcss_ChMC9(unsigned int data[], int dataSize);

//Ethernet
void Ethernet_setup();
void webReponse();
String demuxCMD(String command, String* rightPart);
int demuxNum(String rightPart, unsigned int data[]);

//RS485
void RS485_setup();
void send_485();
int recieve_485();
void recieve_485_0();

//GPIO
void GPIO_setup();
void read_analog();
void read_digital();

//MC9
void setupMC9_1(int i, int data);
String msg_MC9_PV(int addr);
String msg_MC9_SV(int addr);
int saveMC9(String message);
int timeoutMC9();
int parseMC9(const String& message, int& addr, String& mode, int data[8], int& crc);
String sumMC9(String input);

//Utils
int write_buff_c(char* buff, char c);
int write_buff(char* buff, String str);
int write_buff_first(char* buff, String str);
String read_buff(char* buff);

// Periodics
void Periodic_run();
void timer_10ms();

// Analog_Out
void AO_setup(int i, int Rng);
void AO_Write(int i, int volt);



void timer_10ms();
int write_buff_c(char* buff, char c);