/*
 * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
 * Date: 08/2016
 * License: GPLv3
 */

/*****************************************************************************/

#include "command_ctrl.h"

#include "command_config.h"

// include user specific command control configuration and function definition
#include "command_config.h"
#include "command_functions.c"

/*****************************************************************************/

uint8_t cc_state = CC_STATE_READ_SOM1;

uint8_t cc_cmd_to_call = CC_CMD_NO_CMD;

uint8_t cc_cmd_received_correct = MSG_INCOMPLETE;

uint8_t cc_cmd_data_read_cnt = 0;

/*****************************************************************************/

void cc_init()
{
  cc_state                = CC_STATE_READ_SOM1;
  cc_cmd_to_call          = CC_CMD_NO_CMD;
  cc_cmd_data_read_cnt    = 0;
  cc_cmd_received_correct = MSG_INCOMPLETE;
}

/*****************************************************************************/

void cc_abort()
{
  // send abort message, then init
  char* tmp = "     ";
  sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2,
                             MSG_TYPE_ANSWER_NOK,
                             MSG_EOM1, MSG_EOM2);
  USB_serialStreamWriteC(tmp, strlen(tmp));
  cc_init();
}

/*****************************************************************************/

void cc_processData(uint8_t c)
{
  switch (cc_state)
  {
    //*********************************//
    case CC_STATE_READ_SOM1:;
      if (c == MSG_SOM1)
        cc_state = CC_STATE_READ_SOM2;
      else
        cc_abort();
      break;

    //*********************************//
    case CC_STATE_READ_SOM2:;
      if (c == MSG_SOM2)
        cc_state = CC_STATE_READ_CMD;
      else
        cc_abort();
      break;

    //*********************************//
    case CC_STATE_READ_CMD:;
      for (uint8_t i = 0; i < sizeof(cc_commands)/sizeof(uint8_t); i++)
      {
        if (cc_commands[i] == c)
        {
          if (cc_cmd_data_to_read[i] > 0)
            cc_state = CC_STATE_READ_DATA;
          else
            cc_state = CC_STATE_READ_EOM1;

          cc_cmd_to_call = i; // remember the index of command to call

          break; // break the loop
        }
      }
      break;

    //*********************************//
    case CC_STATE_READ_DATA:;
      // write the variable c to the input buffer
      cc_read_data[cc_cmd_data_read_cnt] = c;

      if (cc_cmd_data_read_cnt >= cc_cmd_data_to_read[cc_cmd_to_call]-1)
      {
        cc_state = CC_STATE_READ_EOM1;
      }

      cc_cmd_data_read_cnt++;

      break;

    //*********************************//
    case CC_STATE_READ_EOM1:;
      if (c == MSG_EOM1)
        cc_state = CC_STATE_READ_EOM2;
      else
        cc_abort();
      break;

    //*********************************//
    case CC_STATE_READ_EOM2:;
      if (c == MSG_EOM2)
      {
        cc_cmd_received_correct = MSG_COMPLETE;
      } else
        cc_abort();
      break;

    default:
      cc_abort();
  }

  //*********************************//
  if (cc_cmd_received_correct == MSG_COMPLETE)
  {
    // call the function using the received data
    (*cc_cmd_functions[cc_cmd_to_call])();
    // clear the read buffer
    cc_clearReadDataBuffer();
    cc_init();
  }
}

/*****************************************************************************/

void cc_clearReadDataBuffer()
{
  for (uint8_t i = 0; i < CC_READ_DATA_MAX; i++)
  {
    cc_read_data[i] = 0x00;
  }
}

/*****************************************************************************/
