#include <blinker.h>
#include <lilParser.h>

#define ON_LED_PIN  13    // Signal active when lit.
#define SIGNAL_PIN  3     // Signal seen here.
#define DEF_HZ      3     // Default Freq in Hz.
#define DEF_PERCENT 50    // Default Duty cycle.


blinker theSignal(3);     // Blinker object, basically a square wave generator.
lilParser ourParser;      // A parser so we can type commands it it. NON BLOCKINGLY
float     freq;           // The last frequency it's been set to.
float     percent;        // The last duty cycle it's been set to.


// Current list of commands the parser will understand.
enum commands { noCommand, signalOff, signalOn, setHz };

void setup() {
  
  Serial.begin(115200);                       // Fire up serial.
  Serial.println("Type ? for command list."); // Give the user a hint.
  pinMode(ON_LED_PIN,OUTPUT);                 // Setup indicator LED pin.
  digitalWrite(ON_LED_PIN,LOW);               // And make sure it's off.
  ourParser.addCmd(signalOff,"off");          // Add our commands to the parser.
  ourParser.addCmd(signalOn,"on");            //
  ourParser.addCmd(setHz,"set");              //
  setSignal(DEF_HZ,DEF_PERCENT);              // Set the defaults into the blinker.
}


// If the parser can't understand what your typing. I'll respond with this.
void showList(void) {

  Serial.println();
  Serial.println("Numerical values are real numbers. Not just ints.");
  Serial.println("on\t\t- turns on the signal.");
  Serial.println("off\t\t- turns off the signal.");
  Serial.println("set (0 Params)\t- returns last settings.");
  Serial.println("set (1 Param)\t- Sets new freq in Hz.");
  Serial.println("set (2 Params)\t- Sets new freq in Hz. & Duty cycle in percent.");

}


// Sets the frequency and duty cycle of the blinker and saves off the values.
void setSignal(float newHz,float newPercent) {

  theSignal.setPeriod(1000/newHz);
  theSignal.setPercent(newPercent);
  freq = newHz;
  percent = newPercent;
}


// Handler for the set command.
void handleSet(void) {

  float newHz;
  float newPercent;

  switch(ourParser.numParams()) {                   // Get the param count.
    case 0  :                                       // We got no params?
      Serial.print("Last set values : ");           // We return the last values set.
      Serial.print(freq,2);
      Serial.print(" Hz, ");
      Serial.print(percent,2);
      Serial.println(" %");
    break;
    case 1  :                                       // One param?
      newHz = atof(ourParser.getNextParam());       // Grab that param. Decode as a float.
      setSignal(newHz,percent);                     // Set the new frequency in there.
      Serial.print("Signal set to : ");             // Tell user what we did. 
      Serial.print(newHz,2);                        // Are processors (we/them? Seems so.)
      Serial.println(" Hz");
    break;
    case 2  :                                       // Got tow of 'em?
      newHz = atof(ourParser.getNextParam());       // Grab first as freq.
      newPercent = atof(ourParser.getNextParam());  // Grab the second as percent duty cycle.
      setSignal(newHz,newPercent);                  // Set the new values into the blnker.
      Serial.print("Signal set to : ");             // And tell the user what we did.
      Serial.print(newHz,2);
      Serial.print(" Hz, ");
      Serial.print(newPercent,2);
      Serial.println(" %");
    break;
    default :                                       // Anything else? Just bail with message.
      Serial.print("Sorry no idea what you want with the extra params.");
  }
}


void loop() {
   
   char  inChar;
   int   command;
   
  idle();                                         // Runs the signal.
  if (Serial.available()) {                       // If serial has some data..
    inChar = Serial.read();                       // Read out a charactor.
    Serial.print(inChar);                         // *Optional* echo the charactor.
    command = ourParser.addChar(inChar);          // Try parsing what we have.
      switch (command) {                          // Check the results.
        case noCommand : break;                   // Nothing to report, move along.
        case signalOff :                          // Turn the thing off.
          theSignal.setOnOff(false);              // Shut down the machine.
          digitalWrite(ON_LED_PIN,LOW);           // Turn off the indicator LED.
        break;                                    // Bolt!
        case signalOn  :                          // Turn the thing on
          theSignal.setOnOff(true);               // Fire up the machine.
          digitalWrite(ON_LED_PIN,HIGH);          // Turn on the indicator LED.
        break;                                    // We are done!
        case setHz     : handleSet(); break;      // Handle the set command.
        case -2        : Serial.println("Config error. Parser could not start.");
        case -3        : Serial.println("Param error. Paramiter buffer was too small.");
        default        : showList();     break;   // No idea. Show list.
      }
   }
}