#include <timeObj.h>
#include <idlers.h>

// Mixing idlers with timeObj. Creating a new class that
// calls a user defined callback repeately. And, as
// always, All of this is totally NON BLOCKING. 
//
//           Hide the mess of millis.
//
// You will need to install LC_baseTools to compile
// this on your machine.



//*********************************************
// timedCallback class. Give it a time, then
// give it a function to call. This'll call
// that function for you whenever the time
// expires.
//
//*********************************************


//****************
// The .h stuff..
//****************

class timedCallback : public timeObj,
                      public idler {

  public:
            timedCallback(float inMs=10,bool startNow=true);
    virtual ~timedCallback(void);

    virtual void  idle(void);
            void  setCallback(void(*funct)(void));

            void  (*callback)(void);
};


//****************
// The .cpp stuff..
//****************

// Our constructor. Sets the period in ms of the repeted callbacks.
// And if it starts now, or you will start it later.
timedCallback::timedCallback(float inMs,bool startNow)
  :  timeObj(inMs,startNow),
  idler() { callback = NULL; }


// Destructor, but realy there's nothing for it to do.
timedCallback::~timedCallback(void) {  }


// This is the inherited call from idler that is called every time
// through we go through loop(). In this case it's a piece of code
// that watches the time, and does the actual callback call when the
// time expires.
void timedCallback::idle(void) {

  if (ding()) {       // If the time has expired..
    if (callback) {   // If we have a callback..
      callback();     // Call the callback.
    }                 //
    stepTime();       // Reset the timer for the next callback.
  }
}


// The method to call to set the callback function.
void timedCallback::setCallback(void(*funct)(void)) {

  callback = funct; // Point to the calback function.
  hookup();         // The hookup call to get ourseves into the idle queue.
}



//*********************************************
// The Demo .ino
//*********************************************


timedCallback callbackObj(1000);  // HERE Create the callback object. (Set for every second.)
int           callbackNum = 1;    // A number to show how many callbacks have happened.

void setup() {
  
  Serial.begin(115200);
  Serial.println("Setting up to call the callback & blink the LED.");
  pinMode(13,OUTPUT);
  callbackObj.setCallback(myFunction);    // HERE we are setting the callback function.
}


// HERE The callback function.
void myFunction(void) {
  
  Serial.print("callback called #");
  Serial.println(callbackNum++);
}

// Showing A) The callback object is non-blocking and B) We give you sleep() to replace
// delay(). Sleep stops the main loop but leaves the idlers all running.
void loop() { 
  
  idle();                 // HERE the idle function call. Runs all idlers.
  digitalWrite(13,HIGH);  // LED on
  sleep(200);             // HERE in your main loop sleep() replaces delay().
  digitalWrite(13,LOW);   // LED off
  sleep(250);             // HERE Sleep again. Loop sleeps idlers don't
}