#include "Arduino.h"
#include <MsTimer2.h> // Timer
#include <Ethernet2.h>
#include <avr/wdt.h>  // ??
#include "Wire.h"     // I2C
#include "DFRobot_GP8403.h"

#define CR "\r"
#define FIN "\n"
#define CRLF "\r\n"
#define RcvOK "OK\r"
#define RcvErr "ER\r"
#define MODE_DEBUG  false

String IdeSerial;
const int BUFF_SIZE = 512;
char Buff_Eth_Rd[BUFF_SIZE] = {0};
char Buff_485_Wr[BUFF_SIZE] = {0};
char Buff_485_Rd[BUFF_SIZE] = {0};
String latest_sent_msg;
int numOf485 = 0;
int returnTime = 0;

// ========== ========== Periodic Flags
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;

// ========== ========== Communication
// ---------- Ethernet

// 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;


// ---------- 485
String Buf_485;
bool Wait_485;
int Wait_485_cnt;

// ---------- I2C (Analog Output, DAC)
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);

int voltOffset = 185;
int RngAO[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// ========== ========== Processing

// Read Datas
const int DoPin[] = { 26, 27, 28, 29, 30, 31, 32, 33,
                      34, 35, 36, 37, 38, 39, 40, 41};
const int DiPin[] = { 2, 3, 4, 5, 6, 7, 8, 9};   
const int AiPin[] = { A0, A1, A2, A3, A4, A5, A6, A7, 
                      A8, A9, A10, A11, A12, A13, A14, A15};

int Size_DO = 16;
int Size_DI = 8;
int Values_DI;
int Size_AI = 16;
int Values_AI[16];

bool rcv_10_PV;
int Size_PV = 8;
int Values_10_PV[8];

bool rcv_10_SV;
int Size_SV = 8;
int Values_10_SV[8];

int msCnt = 0;
unsigned long timer = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Start!");
  
  // modules setup (init.)
  Ethernet_setup();
  GPIO_setup();
  //MC9_setup();
  RS485_setup();
  //GP8403_setup();

  // Timer set
  MsTimer2::set(10, timer_10ms);
  MsTimer2::start();

  
}

void loop() {
  
  // wait for a new client:
  //webReponse();
  client = server.available();

  if (client) {
    String Buf_eth;
    String message;
    String cmd;
    String cmdData;
    unsigned int data[32];        
    int dataSize;

    // check if client is connected
    Serial.println("Client Connected!!!");

    // Do What Message Command
    while(client.connected()){

      // read data check
      if(client.available() > 0) {
        char c ;//= client.read();

        while((c = client.read())) {

          if((c == '\n') && (Buff_Eth_Rd[strlen(Buff_Eth_Rd)-1] == '\r')){
            write_buff_c(Buff_Eth_Rd, c);
            break;
          }else{
            write_buff_c(Buff_Eth_Rd, c);
          }
          
        }
        // 데이터를 수신했으므로 타임아웃 타이머 초기화
        lastDataReceivedTime = millis();
      }

      message = read_buff(Buff_Eth_Rd);
      // If data read
      if(message != ""){
        cmd = demuxCMD(message, &cmdData);
        message = "";
        
        //Serial.println(cmd);
        if(cmd=="ALL?"){
          client.print(Prcss_ALL_Read());

        }
        // GPIO
        else if(cmd=="DO!"){
          dataSize = demuxNum(cmdData, data);
          client.print(Prcss_DO_Write(data, dataSize));

        }else if(cmd=="DI?"){
          client.print(Prcss_DI_Read());

        }else if(cmd=="AO!"){
          dataSize = demuxNum(cmdData, data);
          client.print(Prcss_AO_Write(data, dataSize));

        }else if(cmd=="AI?"){
          client.print(Prcss_AI_Read());

        }
        // MC9
        else if(cmd=="SV!"){
          dataSize = demuxNum(cmdData, data);
          client.print(Prcss_SV_Write(data, dataSize));

        }else if(cmd=="SV?"){
          client.print(Prcss_SV_Read());

        }else if(cmd=="PV?"){
          client.print(Prcss_PV_Read());

        }else if(cmd=="ATon!"){
          client.print(Prcss_AT_Write(true));

        }else if(cmd=="AToff!"){
          client.print(Prcss_AT_Write(false));

        }
        // Init
        else if(cmd=="State?"){

        }else if(cmd=="RngAO!"){
          dataSize = demuxNum(cmdData, data);
          client.print(Prcss_RngAO(data, dataSize));

        }else if(cmd=="ChMC9!"){
          dataSize = demuxNum(cmdData, data);
          //client.print(Prcss_ChMC9(data, dataSize));

        }

        //else if(cmd==""){

        //}
        else{
          client.print(cmd + " " + RcvErr + FIN);
        }
        message = "";
      }
      
      // Debug
      if(MODE_DEBUG){
        //Serial.print("Received command: ");
        //Serial.println(command);
      }

      // check Timeout
      if (millis() - lastDataReceivedTime > timeoutPeriod) {
        Serial.println("Client Disconnected... (Timeout)");
        client.stop();
      }
      Periodic_run();
    }
    Serial.println("Client Disconnected...");
  }
  Periodic_run();
}





void AnalogIn_Print(){
  for (int i = 0; i < Size_AI; i++) {
    Serial.print(Values_AI[i]);
    Serial.print("\t");
  }
  Serial.println();
}



