#ifndef _MICRO_PERIODIC_HANDLER_H
#define _MICRO_PERIODIC_HANDLER_H


#include "ostask.h"
#include "errorhandler.h"
#include "callback.h"
#include "dynamicarray.h"
#include "eventobject.h"

class MicroApp;
class TaskSynchronizer;

/*
CLASS 
MicroPeriodicHandler

DESCRIPTION
Periodic sample and process data from micro

AUTHOR
Tom O'Reilly
Modified by Danelle Cline for the Genosensor project
Modifications not required for the LRS project.
*/
class MicroPeriodicHandler  : public ErrorHandler, public TaskBase
{
  public:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: application name
  // [input] tasksync: TaskSynchronizer  
  // throws NullArg exception is tasksync is NULL
  MicroPeriodicHandler(const char *name, TaskSynchronizer *tasksync); 

  ///////////////////////////////////////////////////////////////////
  // Destructor
  ~MicroPeriodicHandler();
  
  ///////////////////////////////////////////////////////////////////
  // Run sampling loop  
  void *run();    

  // Call this to end the run() method. This will set the shutdown event  
  // and call the appropriate taskSynchronizer shutdown methods. Use this
  // to close the EventHandler as a standalone module(such as for module
  // tests). Returns -1 on error
  // [input] waitmillisecs: Seconds to wait for task to shutdown
  int shutdown(int waitmillisecs = 1);

  // Reset periodic loop.  Is used to reset the runEventLoop() method 
  // Must be used with TaskSynchronizer to do a system reset.
  void reset();
 
  ///////////////////////////////////////////////////////////////////
  // Register a callback function for given sampling frequency
  // [input] sampleHertz: Rate at which to invoke callback 
  // [input] callback: callback function
  void addCallback(float sampleHertz, CallbackObject *callback);

  ///////////////////////////////////////////////////////////////////
  // Register a callback function for given sampling period
  // [input] millisec: Period at which to invoke callback
  // [input] callback: callback function
  void addCallback(Nat32 millisec, CallbackObject *callback);


  void disableCallback(CallbackObject *callback);


  void enableCallback(CallbackObject *callback);

  protected:

  char *_name;

  TaskSynchronizer *_taskSync;

  //TODO: comment
  BinarySemaphore _wakeupSem;

  private:
  // TODO: comment
  int invokeCallbacks();
  
  // TODO: comment
  int computeSampleTicks();

  // TODO: comment
  struct CallbackList
  {
    int sampleTicks;
    DynamicArray callbacks;
  };

  // TODO: comment
  DynamicArray _callbackLists;

  // Period of timing loop
  int _sampleTicks;

  // Greatest period requested
  int _maxTicks;

  // Ticks accumulated so far before start of next cycle
  int _accumulatedTicks;

  // Clocks per sec, used to convert sampleTicks to msec
  static Nat32 _clksPerSec;

};

#endif

