// serialStr manages a serial port for you. When it recieves a
// complete string, it calls your choosen function to deal with it.
// And, it does all this, NON-BLOCKINGLY.
//
//                  Hide the mess of millis!
//

#include <serialStr.h>  // You will need to install LC_baseTools to compile this.
#include <blinker.h>
#include <mapper.h>
#include <strTools.h>


enum waveTypes { sinType, sawType, pwmType };

class mutiWave : public blinker {

  public:
          mutiWave(int inPin);
          ~mutiWave(void);

          void setType(waveTypes inType);
  virtual void idle(void);

          waveTypes waveType;
          mapper    pwmMapper;
          mapper    angleMapper;
};



mutiWave::mutiWave(int inPin)
  : blinker(inPin) {
  
  pwmMapper.setValues(0,1,0,255); 
  angleMapper.setValues(0,1,0,2*PI);
}


mutiWave::~mutiWave(void) {  }


void mutiWave::setType(waveTypes inType) { waveType = inType; }

void mutiWave::idle(void) {

  float fract;
  float angle;

  squareWave::idle();
  switch (waveType) {
    case sinType : 
      fract = mPeriod.getFraction();
      angle = angleMapper.map(fract);
      analogWrite(pin,sin(angle));
    break;
    case sawType :
      fract = mPeriod.getFraction();
      analogWrite(pin,pwmMapper.map(fract));
    break;
    case pwmType  : break;
  }
}



#define MIN_FREQ  1
#define MAX_FREQ  20000 
#define WAVE_PIN  9  

serialStr serialManager;
mutiWave  ourWaveGen(WAVE_PIN);

void setup() {

   Serial.begin(115200);                        // Fire up serial.
   Serial.println("Type command and number.");  // Tell user to type a word & number.
   Serial.println("Ex: Freq 4000\tWhere number is HZ.");
   Serial.println("Ex: Type 2   \tWhere SIN = 1 SAW = 2 & PWM = 3");
   serialManager.setCallback(gotCom);           // Tell serial manager it's callback function.
   ourWaveGen.setPeriod(500);
   ourWaveGen.setType(1);
   ourWaveGen.setOnOff(true);
}


// This is the function that is called when the serial manager recieves complete string.
void gotCom(char* inStr) {

    char  command[20];
    int   value;

  lwrCase(inStr);
  sscanf(inStr, "%s %d", command, &value);            // Looking for text & int
  Serial.print("Command: ");Serial.println(command);  // Output the text portion we found.
  Serial.print("Value: ");Serial.println(value);      // Output the int portion we found.
  if (!strcmp(command,"type")) {
    switch(value) {
      case 1  : 
        ourWaveGen.setType(sinType); 
        Serial.println("SIN Type set.");
      break;
      case 2  : 
        ourWaveGen.setType(sawType);
        Serial.println("SAW Type set.");
      break;
      case 3  : 
        ourWaveGen.setType(pwmType);
        Serial.println("PWM Type set.");
      break;
      default : Serial.println("No, SIN = 1 SAW = 2 & PWM = 3");
    }
  } else if (!strcmp(command,"freq")) {
    float temp;
    temp = value/1000.0;
    ourWaveGen.setPeriod(1.0/temp);
    ourWaveGen.setPercent(50);
    Serial.print("Setting freq to ");
    Serial.print(value);
    Serial.println(" HZ");
  } else {
    Serial.println("Unknown command try type or freq then an integer value.");
  }
}


// In this case we only need to call idle();
void loop() {
  
  idle();   // idle() runs stuff in the background. LC_baseTools has a lot of things that use this.
            // If you need other loop() kinda' things, they can go here. 
            // Instead of delay(ms); You can now use sleep(ms); and loop will stop, idle() will still run.
}