//
// $Id: TtmConfigurationData.hh,v 1.1 2008/06/27 10:34:05 meyern Exp $
//

#ifndef TtmConfigurationData_HH
#define TtmConfigurationData_HH

#include <string>
#include <iostream>
#include <stdint.h>

#include "UtlPack.hh"


class TtmConfigurationData {

public:
  enum {
    versionNumber=0
  };
  
  enum Signal {
    trigger=1,
    tcal=2,
    reset=4
  };
  
  TtmConfigurationData();
  
  void vcs(unsigned v);
  void tcs(unsigned t);
  
  unsigned vmeFirmware() const;
  void vmeFirmware(unsigned v);
  
  unsigned tdFirmware() const;
  void tdFirmware(unsigned t);
  
  unsigned triggerDelay() const;
  void triggerDelay(unsigned d);

  bool tcsRamSignal() const;
  void tcsRamSignal(bool b);

  bool tcsInternalReset() const;
  void tcsInternalReset(bool b);

  bool tcsInternalTcal() const;
  void tcsInternalTcal(bool b);

  bool tcsInternalTrigger() const;
  void tcsInternalTrigger(bool b);

  bool tcsEnableTriggerDelay() const;
  void tcsEnableTriggerDelay(bool b);

  unsigned ramDepth() const;
  void     ramDepth(unsigned n);

  const unsigned* ramData() const;
  unsigned*       ramData();

  void     ramLoad(unsigned n);

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

private:
  unsigned FirmwareMonth(UtlPack r) const;
  unsigned FirmwareDay(UtlPack r) const;
  unsigned FirmwareYearMsb(UtlPack r) const;
  unsigned FirmwareYearLsb(UtlPack r) const;
  unsigned FirmwareVersion(UtlPack r) const;
  unsigned FirmwareRevision(UtlPack r) const;

private:
  UtlPack _vcs;
  uint32_t _oscUnlockCounter;
  uint32_t _gpsUnlockCounter;
  UtlPack _vmeFirmware;
  UtlPack _tdFirmware;
  uint32_t _gpsTransfer;
  uint32_t _gpsReceive;
  UtlPack _tcs;
  uint32_t _triggerDelay;
  UtlPack _manualSignals;
  uint32_t _ramLoopCount;
  uint32_t _ramDepth;
  uint32_t _ramData[8];
};

TtmConfigurationData::TtmConfigurationData() {
  _ramDepth=8;
  memset(_ramData,0,sizeof(_ramData));
}

void TtmConfigurationData::vcs(unsigned v) {
  _vcs.word(v);
}

void TtmConfigurationData::tcs(unsigned t) {
  _tcs.word(t);
}

unsigned TtmConfigurationData::vmeFirmware() const {
  return _vmeFirmware.word();
}

void TtmConfigurationData::vmeFirmware(unsigned v) {
  _vmeFirmware.word(v);
}

unsigned TtmConfigurationData::tdFirmware() const {
  return _tdFirmware.word();
}

void TtmConfigurationData::tdFirmware(unsigned t) {
  _tdFirmware.word(t);
}

unsigned TtmConfigurationData::triggerDelay() const {
  return _triggerDelay;
}

void TtmConfigurationData::triggerDelay(unsigned d) {
  _triggerDelay=d;
}

bool TtmConfigurationData::tcsRamSignal() const {
  return _tcs.bit(7);
}

void TtmConfigurationData::tcsRamSignal(bool b) {
  _tcs.bit(7,b);
}

bool TtmConfigurationData::tcsInternalReset() const {
  return _tcs.bit(4);
}

void TtmConfigurationData::tcsInternalReset(bool b) {
  _tcs.bit(4,b);
}

bool TtmConfigurationData::tcsInternalTcal() const {
  return _tcs.bit(3);
}

void TtmConfigurationData::tcsInternalTcal(bool b) {
  _tcs.bit(3,b);
}

bool TtmConfigurationData::tcsInternalTrigger() const {
  return _tcs.bit(2);
}

void TtmConfigurationData::tcsInternalTrigger(bool b) {
  _tcs.bit(2,b);
}

bool TtmConfigurationData::tcsEnableTriggerDelay() const {
  return _tcs.bit(10);
}

void TtmConfigurationData::tcsEnableTriggerDelay(bool b) {
  _tcs.bit(10,b);
}


unsigned TtmConfigurationData::FirmwareMonth(UtlPack r) const {
  return r.bits(28,31);
}

unsigned TtmConfigurationData::FirmwareDay(UtlPack r) const {
  return r.bits(23,27);
}

unsigned TtmConfigurationData::FirmwareYearMsb(UtlPack r) const {
  return r.bits(19,22);
}

unsigned TtmConfigurationData::FirmwareYearLsb(UtlPack r) const {
  return r.bits(15,18);
}

unsigned TtmConfigurationData::FirmwareVersion(UtlPack r) const {
  return r.bits(12,14);
}

unsigned TtmConfigurationData::FirmwareRevision(UtlPack r) const {
  return r.bits(9,11);
}

unsigned TtmConfigurationData::ramDepth() const {
  return _ramDepth;
}

void TtmConfigurationData::ramDepth(unsigned n) {
  assert(n<=sizeof(_ramData)/sizeof(uint32_t));
  _ramDepth = n;
}

const unsigned* TtmConfigurationData::ramData() const {
  return _ramData;
}

unsigned* TtmConfigurationData::ramData() {
  return _ramData;
}

void TtmConfigurationData::ramLoad(unsigned n) {
  assert((n+2)<=ramDepth());

  // initialize
  memset(_ramData,0,sizeof(_ramData));

  // set TCAL signal
  _ramData[1]=reset;

  // set Trigger signal
  _ramData[n]=tcal|trigger;
}

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

  o << s << " VME Firmware Version "
    << FirmwareVersion(_vmeFirmware) << " Rev " << FirmwareRevision(_vmeFirmware) << " "
    << FirmwareDay(_vmeFirmware) << "-" << FirmwareMonth(_vmeFirmware) << "-"
    << FirmwareYearMsb(_vmeFirmware) << FirmwareYearLsb(_vmeFirmware);
  o << s << std::endl;
  o << s << " TD Firmware Version "
    << FirmwareVersion(_tdFirmware) << " Rev " << FirmwareRevision(_tdFirmware) << " "
    << FirmwareDay(_tdFirmware) << "-" << FirmwareMonth(_tdFirmware) << "-"
    << FirmwareYearMsb(_tdFirmware) << FirmwareYearLsb(_tdFirmware);
  o << s << std::endl;
  o << s << " Trigger Source is " << (tcsInternalTrigger() ? "Internal" : "External");
  o << s << std::endl;
  o << s << " Reset Source is " << (tcsInternalReset() ? "Internal" : "Oscillator");
  o << s << std::endl;
  o << s << " TCAL Source is " << (tcsInternalTcal() ? "Internal" : "External");
  o << s << std::endl;
  o << s << " Signal Source is " << (tcsRamSignal() ? "RAM" : "Register");
  o << s << std::endl;
  o << s << " Trigger Delay is " << (tcsEnableTriggerDelay() ? "Enabled" : "Disabled");
  if (tcsEnableTriggerDelay())
    o << s << ": " << triggerDelay()*100 << " ns" ;
  o << s << std::endl;
  o << s << " RAM depth is " << ramDepth();
  o << s << std::endl;
  if (ramDepth()) {
    const unsigned* ram(ramData());
    o << s << " RAM     = ";
    for(unsigned i(0); i<ramDepth(); i++)
      o << s << std::setfill('0') << std::setw(2)
	<< std::hex << static_cast<unsigned int>(ram[i]) << std::dec;
  }
  o << s << std::setfill(' ');
  o << s << std::endl;

  return o;
}

#endif // TtmConfigurationData_HH
