// Last updated: March 15th, 2012 - 8:40PM GMT
// Using state machine pattern - based on Nick Gammon code

typedef enum {  NONE, GOT_I, GOT_O, GOT_R, GOT_o, GOT_T, GOT_S, GOT_B, GOT_H, GOT_b, GOT_h, GOT_P, GOT_F, GOT_A, GOT_W, GOT_V, GOT_w, GOT_r, GOT_k, GOT_a } states;
states state = NONE;
unsigned int currentValue;

void setup ()
{
  Serial.begin (115200);
  TCCR4B = (TCCR4B & 0xF8) | 0x01 ;
  state = NONE;
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(25, OUTPUT);
  pinMode(26, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(34, OUTPUT);
} 

// Lights

void Read_BusStopLight(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(22,HIGH);
  }
  else
  {
        digitalWrite(22,LOW);
  }
}

void Read_Blinker(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(24,HIGH);
  }
  else
  {
        digitalWrite(24,LOW);
  }
}

void Read_Highbeam(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(25,HIGH);
  }
  else
  {
        digitalWrite(25,LOW);
  }
}

void Read_Battery(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(26,HIGH);
  }
  else
  {
        digitalWrite(26,LOW);
  }
}

void Read_Handbrake(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(27,HIGH);
  }
  else
  {
        digitalWrite(27,LOW);
  }
}

void Read_LowPressure(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(28,HIGH);
  }
  else
  {
        digitalWrite(28,LOW);
  }
}

void Read_ABS(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(29,HIGH);
  }
  else
  {
        digitalWrite(29,LOW);
  }
}

void Read_RearDoor(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(30,HIGH);
  }
  else
  {
        digitalWrite(30,LOW);
  }
}

void Read_RetarderDirect(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(31,HIGH);
  }
  else
  {
        digitalWrite(31,LOW);
  }
}

void Read_FourFlasher(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(32,HIGH);
  }
  else
  {
        digitalWrite(32,LOW);
  }
}

void Read_Backlight(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(33,HIGH);
  }
  else
  {
        digitalWrite(33,LOW);
  }
}

void Read_ASR(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(34,HIGH);
  }
  else
  {
        digitalWrite(34,LOW);
  }
}

// Gauges

void Read_Temperature(const unsigned int value)
{
  analogWrite(7,map(value,0,100,255,0));
}

void Read_Rpm(const unsigned int value)
{
  tone(9, map(value,0,5700,55,423));
}

void Read_Oil(const unsigned int value)
{
  analogWrite(8,map(value,0,50,0,255));
}

void Read_Fuel(const unsigned int value)
{
  analogWrite(6,map(value,0,100,255,0));
}

void Read_Velocity(const unsigned int value)
{
  tone(10, map(value,0,1250,55,423));
}


void handlePreviousState()
{
  switch (state)
  {
  case GOT_R:
    Read_Rpm(currentValue);
    break;
  case GOT_o:
    Read_Oil(currentValue);
    break;
  case GOT_T:
    Read_Temperature(currentValue);
    break;
  case GOT_S:
	Read_BusStopLight(currentValue);
	break;
  case GOT_B:
	Read_Blinker(currentValue);
	break;
  case GOT_H:
	Read_Highbeam(currentValue);
	break;
  case GOT_b:
	Read_Battery(currentValue);
	break;
  case GOT_h:
	Read_Handbrake(currentValue);
	break;
  case GOT_P:
	Read_LowPressure(currentValue);
	break;
  case GOT_F:
	Read_Fuel(currentValue);
	break;
  case GOT_A:
	Read_ABS(currentValue);
	break;
  case GOT_W:
	Read_RearDoor(currentValue);
	break;
  case GOT_V:
	Read_Velocity(currentValue);
	break;
  case GOT_w:
	Read_FourFlasher(currentValue);
	break;
  case GOT_r:
	Read_RetarderDirect(currentValue);
	break;
  case GOT_k:
	Read_Backlight(currentValue);
	break;
  case GOT_a:
	Read_ASR(currentValue);
	break;
  case GOT_I:
	digitalWrite(23,HIGH);
	break;
  case GOT_O:
	digitalWrite(23,LOW);
	break;
  }
  currentValue = 0; 
}

void processIncomingByte (const byte c)
{
  if (isdigit (c))
  {
    currentValue *= 10;
    currentValue += c - '0';
  }
  else 
  {

    handlePreviousState ();
    switch (c)
    {
    case 'I':
      state = GOT_I;
      break;
    case 'O':
      state = GOT_O;
      break;
    case 'R':
      state = GOT_R;
      break;
    case 'o':
      state = GOT_o;
      break;
    case 'T':
      state = GOT_T;
      break;
    case 'S':
      state = GOT_S;
      break;
    case 'B':
      state = GOT_B;
      break;
    case 'H':
      state = GOT_H;
      break;
    case 'b':
      state = GOT_b;
      break;
    case 'h':
      state = GOT_h;
      break;
	case 'P':
	  state = GOT_P;
	  break;
	case 'F':
	  state = GOT_F;
	  break;
	case 'A':
	  state = GOT_A;
	  break;
	case 'W':
	  state = GOT_W;
	  break;
	case 'V':
	  state = GOT_V;
	  break;
	case 'w':
	  state = GOT_w;
	  break;
	case 'r':
	  state = GOT_r;
	  break;
	case 'k':
	  state = GOT_k;
	  break;
	case 'a':
	  state = GOT_a;
	  break;
    default:
      state = NONE;
      break;
    }
  }  
  
}

void loop()
{
	if (Serial.available())
		processIncomingByte (Serial.read());
}