#ifndef _MICROSAMPLER_H
#define _MICROSAMPLER_H

#include "ErrorHandler.h"
#include <mbariTypes.h>

#ifdef UNIX
# include "VxStubs.h"
#else 
  extern "C"
  {
#   include "vxWorks.h"
#   include "msgQLib.h"
#   include "semLib.h"
#   include "taskLib.h"
#   include "lstLib.h"
#   include "datamgr.h"
#   include "sio32.h"
#   include "sio32Server.h"
#   include "sio32Client.h"
#   include "microCmd.h"
#   include "microcmd.h"
#   include "applic.h"
  };
# endif

#include "DynamicArray.h"

class MicroApp;

/*
CLASS 
MicroSampler

DESCRIPTION
Periodic sample and process data from micro

AUTHOR
Tom O'Reilly
*/
class MicroSampler : public ErrorHandler
{
  public:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: application name
  // [input] app: Parent MicroApp
  MicroSampler(const char *name, MicroApp *app); 

  ~MicroSampler();
  
  ///////////////////////////////////////////////////////////////////
  // Run sampling loop  
  void run();

  protected:
  
  typedef void (MicroSampler::*CallbackMethod)();

  ///////////////////////////////////////////////////////////////////
  // Register a callback function for given sampling frequency
  // [input] sampleHertz: Rate at which to invoke callback 
  // [input] callback: callback function
  void addCallback(float sampleHertz, CallbackMethod 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, CallbackMethod callback);

  ///////////////////////////////////////////////////////////////////
  // Start DM providers, etc
  virtual void startSampling();
  
  char *_name;
  MicroApp *_app;
  SEM_ID _wakeupSem;

  private:

  int invokeCallbacks();
  int computeSampleTicks();
  
  struct CallbackObj
  {
    CallbackObj(void (MicroSampler::*callback)())
    {
      _callback = callback;
    }
    
    void (MicroSampler::*_callback)();
  };
  
  
  struct CallbackList
  {
    int sampleTicks;
    DynamicArray callbacks;
  };

  DynamicArray _callbackLists;

  // Period of timing loop
  int _sampleTicks;

  // Greatest period requested
  int _maxTicks;

  // Ticks accumulated so far before start of next cycle
  int _accumulatedTicks;
};


#endif

