#ifndef BmlCaen767StatusRegister_HH
#define BmlCaen767StatusRegister_HH

#include <iostream>
#include <fstream>

#include "UtlPack.hh"


class BmlCaen767StatusRegister {

public:
  BmlCaen767StatusRegister();

  UtlPack statusRegister() const;
  void    statusRegister(unsigned h, unsigned short r);

  bool       dataReady() const;
  bool globalDataReady() const;

  bool       busy() const;
  bool globalBusy() const;

  bool bufferEmpty() const;
  bool bufferFull() const;
  bool bufferAlmostFull() const;

  bool tdcError() const;
  bool tdcError(unsigned t) const;

  std::ostream& print(std::ostream &o, std::string s="") const;


private:
  UtlPack _statusRegister;
};


#ifdef CALICE_DAQ_ICC

#include <cstring>

#include "UtlPrintHex.hh"


BmlCaen767StatusRegister::BmlCaen767StatusRegister() {
  memset(this,0,sizeof(BmlCaen767StatusRegister));
}

UtlPack BmlCaen767StatusRegister::statusRegister() const {
  return _statusRegister;
}

void BmlCaen767StatusRegister::statusRegister(unsigned h, unsigned short r) {
  assert(h<2);
  _statusRegister.halfWord(h,r);
}

bool BmlCaen767StatusRegister::dataReady() const {
  return _statusRegister.bit(0);
}

bool BmlCaen767StatusRegister::globalDataReady() const {
  return _statusRegister.bit(1);
}

bool BmlCaen767StatusRegister::busy() const {
  return _statusRegister.bit(2);
}

bool BmlCaen767StatusRegister::globalBusy() const {
  return _statusRegister.bit(3);
}

bool BmlCaen767StatusRegister::bufferEmpty() const {
  return _statusRegister.bit(16);
}

bool BmlCaen767StatusRegister::bufferFull() const {
  return _statusRegister.bit(17);
}

bool BmlCaen767StatusRegister::bufferAlmostFull() const {
  return _statusRegister.bit(18);
}

bool BmlCaen767StatusRegister::tdcError() const {
  return _statusRegister.bit(19);
}

bool BmlCaen767StatusRegister::tdcError(unsigned t) const {
  assert(t<4);
  return _statusRegister.bit(28+t);
}

std::ostream& BmlCaen767StatusRegister::print(std::ostream &o, std::string s) const {
  o << s << "BmlCaen767StatusRegister::print()" << std::endl;

  o << s << " Status register = " << printHex(_statusRegister) << std::endl;

  if(dataReady())       o << s << "  This module has data ready" << std::endl;
  else                  o << s << "  This module has no data ready" << std::endl;
  if(globalDataReady()) o << s << "  At least one module has data ready" << std::endl;
  else                  o << s << "  All modules have no data ready" << std::endl;

  if(busy())       o << s << "  This module is busy" << std::endl;
  else             o << s << "  This module is not busy" << std::endl;
  if(globalBusy()) o << s << "  At least one module is busy" << std::endl;
  else             o << s << "  All modules are not busy" << std::endl;

  // Manual appears to be incorrect for termination bit logic
  if(_statusRegister.bits(6,7)==1)      o << s << "  Control bus termination on" << std::endl;
  else if(_statusRegister.bits(6,7)==2) o << s << "  Control bus termination off" << std::endl;
  else                                  o << s << "  Control bus termination unknown" << std::endl;

  if(_statusRegister.bit(16)) o << s << "  Output buffer empty" << std::endl;
  else                        o << s << "  Output buffer not empty" << std::endl;
  if(_statusRegister.bit(17)) o << s << "  Output buffer full" << std::endl;
  else                        o << s << "  Output buffer not full" << std::endl;
  if(_statusRegister.bit(18)) o << s << "  Output buffer almost full" << std::endl;
  else                        o << s << "  Output buffer not almost full" << std::endl;
  if(_statusRegister.bit(19)) o << s << "  At least one TDC has an error" << std::endl;
  else                        o << s << "  All TDCs have no error" << std::endl;
  if(_statusRegister.bit(28)) o << s << "  TDC 0 has an error" << std::endl;
  else                        o << s << "  TDC 0 has no error" << std::endl;
  if(_statusRegister.bit(29)) o << s << "  TDC 1 has an error" << std::endl;
  else                        o << s << "  TDC 1 has no error" << std::endl;
  if(_statusRegister.bit(30)) o << s << "  TDC 2 has an error" << std::endl;
  else                        o << s << "  TDC 2 has no error" << std::endl;
  if(_statusRegister.bit(31)) o << s << "  TDC 3 has an error" << std::endl;
  else                        o << s << "  TDC 3 has no error" << std::endl;

  return o;
}

#endif
#endif
