/***************************************************************
 * PrTRCBoard.cpp
 *
 * This is an implementation of the TRC board class.
 *
 ****************************************************************/

/*
 * modification history
 *----------------------
 *
 * 03/31/98: K.C. Chang: added handOpen and handClose.
 * 12/12/97: K.C. Chang: created.
 */

#include "PrTRCBoard.h"
#include "PrTRCDefn.h"
#include "PrEncoderTRC.h"
#include "PrDACTRC.h"
#include "PrADCTRC.h"

PrTRCBoard::PrTRCBoard()
{
    dac_ = new PrDACTRC;
    discreteReg_ = 0x0000;
    if (calibrationCheck() == PR_TRCBOARD_OK)
      discreteReg_ |= TRC_DISCRETE_OUT_CALIBRATION_BIT;
    discreteReg_ |= TRC_HAND_CLOSE;

    enc_ = new PrEncoderTRC;
    adc_ = new PrADCTRC(discreteReg_);

    if (enc_->flag() != PR_DRIVER_OK
	|| dac_->flag() != PR_DRIVER_OK
	|| adc_->flag() != PR_DRIVER_OK)
      flag_ = PR_TRCBOARD_ERROR;
    flag_ = PR_TRCBOARD_OK;
}

PrTRCBoard::~PrTRCBoard()
{
    delete enc_;
    delete dac_;
    delete adc_;
}

int PrTRCBoard::zero()
{
    if (dac_->zero() != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;

    if (adc_->zero() != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;

    if (calibrationCheck() != PR_TRCBOARD_OK)
      {
	if (enc_->zero() != PR_DRIVER_OK)
	  return PR_TRCBOARD_ERROR;
	else
	  return calibrationSet();
      }

    return PR_TRCBOARD_OK;
}

int PrTRCBoard::valueDAC(int channel,Float &volt)
{
    if (dac_->value(channel,volt) != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;
    return PR_TRCBOARD_OK;
}

int PrTRCBoard::valueADC(int channel,Float &volt)
{
    if (adc_->value(channel,volt) != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;
    return PR_TRCBOARD_OK;
}

int PrTRCBoard::valuesENC(Float *data)
{
    if (enc_->values(data) != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;
    return PR_TRCBOARD_OK;
}

int PrTRCBoard::valuesPresetENC(const int *data)
{
    if (enc_->valuesPreset(data) != PR_DRIVER_OK)
      return PR_TRCBOARD_ERROR;
    return PR_TRCBOARD_OK;
}

int PrTRCBoard::powerOn()
{
  discreteReg_ |= TRC_DISCRETE_OUT_POWER_BIT;
  return WriteDiscreteOutReg();
}

int PrTRCBoard::powerOff()
{
    discreteReg_ &= ~TRC_DISCRETE_OUT_POWER_BIT;
    return WriteDiscreteOutReg();
}

int PrTRCBoard::calibrationSet()
{
  discreteReg_ |= TRC_DISCRETE_OUT_CALIBRATION_BIT;
  return WriteDiscreteOutReg();
}

int PrTRCBoard::calibrationCheck()
{
  if ((ReadStatusInReg() & TRC_STATUS_IN_CALIBRATION_BIT) == 0)
    return PR_TRCBOARD_ERROR;
  return PR_TRCBOARD_OK;
}

int PrTRCBoard::thermostat()
{
  if ((ReadStatusInReg() & TRC_STATUS_IN_THERMO_MASK) != 0)
    return PR_TRCBOARD_ERROR;
  return PR_TRCBOARD_OK;
}

int PrTRCBoard::handOpen()
{
  discreteReg_ = (discreteReg_ & ~TRC_HAND_CLOSE) | TRC_HAND_OPEN;
  return WriteDiscreteOutReg();
}

int PrTRCBoard::handClose()
{
  discreteReg_ = (discreteReg_ & ~TRC_HAND_OPEN) | TRC_HAND_CLOSE;
  return WriteDiscreteOutReg();
}


// private method

inline int PrTRCBoard::WriteDiscreteOutReg()
{
    // discrete output register is 2 bytes
    if (dac_->hwIO().output2B(TRC_BASE_ADDR + TRC_DISCRETE_OUT_REG,
                        discreteReg_ & TRC_DISCRETE_OUT_REG_BITS_MASK) 
	!= discreteReg_)
      return PR_TRCBOARD_ERROR;
    return PR_TRCBOARD_OK;
}

inline int PrTRCBoard::ReadStatusInReg()
{
  return dac_->hwIO().input2B(TRC_BASE_ADDR + TRC_STATUS_IN_REG); 
}

