/*
* Copyright (c) 2012, Benjamin BALET http://benjamin-balet.info
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * The name Benjamin BALET may not be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdlib.h>
#include <string.h>

#define NB_COMMANDS 5
#define MAX_ARGS 8
#define MAX_ARGS_LEN 40
//#define MAX_CMD_LEN 2048
#define MAX_CMD_LEN 40

//Command Identifiers. Amend this list with your own command ids
enum Command_IDs { 
  CReadAnalog = 0,
  CWriteAnalog = 1,
  CWriteDigital = 2,
  CReadDigital = 3,
  CEcho = 4
};

//Presentation names of the Commands. Amend this list with your own command names
char* Command_List[NB_COMMANDS] = { 
  "ReadAnalog",
  "WriteAnalog",
  "WriteDigital",
  "ReadDigital",
  "Echo"
};

//Received Command
int Command_ID;
char arg_list[MAX_ARGS][MAX_ARGS_LEN];
char incomingByte;
int index;
char command_line[MAX_CMD_LEN];

//This function execute a command. Amend this function with your own commands
void exec_command()
{
  char user_feedback[512];
    switch (Command_ID)
    {
      case CReadAnalog: 
        Serial.println(analogRead(atoi(arg_list[1])));
	      break;
      case CWriteAnalog:
        analogWrite(atoi(arg_list[1]), atoi(arg_list[2]));
	      sprintf(user_feedback, "done : Inputs %i,%i", atoi(arg_list[1]), atoi(arg_list[2]));
        break;
      case CReadDigital: 
        Serial.println(digitalRead(atoi(arg_list[1])));
        break;
      case CWriteDigital:
        digitalWrite(atoi(arg_list[1]), atoi(arg_list[2]));
        sprintf(user_feedback, "done : Inputs %i,%i", atoi(arg_list[1]), atoi(arg_list[2]));
        break;
      case CEcho:
        Serial.println(arg_list[1]);
        break;
     
      default : 
        Serial.print("Unknown Command");
        Serial.println(command_line);
    }
}

//this function parses the command so as to identify the command and its arguments
void parse_command()
{
  char *pch;
  int ii = 0;
 
  //Identify the command attributes

  pch = strtok (command_line,"|");
  while (pch != NULL)
  {
    sprintf(arg_list[ii],"%s", pch);//Write in argument table    
    pch = strtok (NULL, "|");
    ii++;
  }

  //Identify the command ID
  for (ii=0; ii<NB_COMMANDS; ii++)
  {
    if (strcmp(Command_List[ii], arg_list[0]) == 0)
    {
      Command_ID = ii;
      break;
    }
  }
}

//Basic setup. Adapt the content according to your sket
void setup() {
   
   ///////////// ARDUINO UNO/////////////
    for(int i = 0; i < 6; i++)
    {
     pinMode((i+2), INPUT); // pin #0 et #1 indisponibles, communication série rx tx
     pinMode((13 - i), OUTPUT); 
    }
    Serial.begin(9600);    
}

//Wait for input commands
void loop() {

  if (Serial.available()) {
    incomingByte = Serial.read();
    switch (incomingByte)
    {
      case '<': //start acquisition of a new command
        index = 0;
        memset(command_line, 0, MAX_CMD_LEN - 1);//Set command to 0
        break;
      case '>': // finish acquisition of current command
        command_line[index+1] = 0;
        parse_command();
        exec_command();
        break;
      default : // command acquisition
        command_line[index++] = incomingByte;
    }
  }
}
