/***************************************************************
 * PrDriverIntf.h
 *
 * This is an abstract class providing the interface
 * for derived driver classes.
 *
 ****************************************************************/

/*
 * modification history
 *----------------------
 *
 * 10/26/97: K.C. Chang: created.
 */

#ifndef _PrDriverIntf_h
#define _PrDriverIntf_h

#include <assert.h>
#include "PrGlobalDefn.h"
#include "PrIOWrap.h"

#define PR_DRIVER_OK    1
#define PR_DRIVER_ERROR 0

// abstract class
class PrDriverIntf
{
  public:
    PrDriverIntf(int channelCount=0,int bitCount=0);

    // abstract class needs virtual desctructor
    virtual ~PrDriverIntf() {}

    // indicates error and etc.
    int flag() const { return flag_; }
    void flag(int num) { flag_ = num; }

    // hardware IO methods
    PrIOWrap &hwIO() { return hwIO_; }

    // number of channels for the driver
    int channelCount() const { return channelCount_; }

    // number of bits for the driver
    int bitCount() const { return bitCount_; }

    // mask for the register
    int bitMask() const { return bitMask_; }

    // calls value() channelCount() times
    virtual int values(Float *data);

    // derived classes should provide zero() and value()

    // hardware reset
    virtual int zero()=0;

    // read(write) a value to(from) a channel
    virtual int value(int channel,Float &)=0;

    // default selfTest(): checks the flag and print messages
    virtual int selfTest();

  private:
    int flag_;
    const int channelCount_;
    const int bitCount_;
    int bitMask_;
    PrIOWrap hwIO_;

    // copy is not allowed
    PrDriverIntf(const PrDriverIntf &) : channelCount_(0), bitCount_(0) {}
};

// constructor calculates bitMask
inline PrDriverIntf::PrDriverIntf( int channelCount,int bitCount)
    : channelCount_(channelCount), bitCount_(bitCount), flag_(PR_DRIVER_ERROR)
{    
    assert(bitCount_ > 0);
    bitMask_ = (1<<bitCount_) - 1;   // = 2^(bitCount) - 1 > 0
}

// calls value() channelCount_ times
inline int PrDriverIntf::values(Float *data)
{
    for(int i=0;i<channelCount_;i++)
      {
	  if (value(i,data[i]) != PR_DRIVER_OK)
	    return PR_DRIVER_ERROR;
      }
    return PR_DRIVER_OK;
}


// default selfTest(): checks the flag and print messages
inline int PrDriverIntf::selfTest()
{
    printf("PrDriverIntf::selfTest(): starts\n");
    if (flag()!=PR_DRIVER_OK)
      {
	  printf("PrDriverIntf::error: constructor\n");
	  return PR_DRIVER_ERROR; 
      }
    printf("PrDriverIntf::selfTest(): done\n");
    return PR_DRIVER_OK;
}

#endif // _PrDriverIntf_h



