#ifndef MpsPcb1ConfigurationData_HH
#define MpsPcb1ConfigurationData_HH

#include <iostream>
#include <fstream>

#include "UtlPack.hh"


class MpsPcb1ConfigurationData {

public:
  enum {
    versionNumber=0
  };

  MpsPcb1ConfigurationData();
  
  unsigned short debugVthPos() const;
  void           debugVthPos(unsigned short d);

  unsigned short debugVthNeg() const;
  void           debugVthNeg(unsigned short d);
  
  int  debugVth() const;
  void debugVth(int d);
  
  unsigned short vth12Pos() const;
  void           vth12Pos(unsigned short d);

  unsigned short vth34Pos() const;
  void           vth34Pos(unsigned short d);

  int  vth12() const;
  void vth12(int d);

  unsigned short vth34Neg() const;
  void           vth34Neg(unsigned short d);

  unsigned short vth12Neg() const;
  void           vth12Neg(unsigned short d);

  int  vth34() const;
  void vth34(int d);
  
  unsigned short vRst() const;
  void           vRst(unsigned short d);
  
  unsigned short iSenseColRef() const;
  void           iSenseColRef(unsigned short d);

  unsigned short preAmp34VCasc() const;
  void           preAmp34VCasc(unsigned short d);

  unsigned short iSenseBias() const;
  void           iSenseBias(unsigned short d);

  unsigned short i12Comp1Bias() const;
  void           i12Comp1Bias(unsigned short d);

  unsigned short i12Comp2Bias() const;
  void           i12Comp2Bias(unsigned short d);

  unsigned short iSenseIoutBias() const;
  void           iSenseIoutBias(unsigned short d);

  unsigned short iSenseCompBias() const;
  void           iSenseCompBias(unsigned short d);

  unsigned short i12IoutBias() const;
  void           i12IoutBias(unsigned short d);

  unsigned short i12PreAmpBias() const;
  void           i12PreAmpBias(unsigned short d);

  unsigned short i12ShaperBias() const;
  void           i12ShaperBias(unsigned short d);

  unsigned short i12CompBiasTrim() const;
  void           i12CompBiasTrim(unsigned short d);

  unsigned short i34CompBiasTrim() const;
  void           i34CompBiasTrim(unsigned short d);
  
  unsigned short i34DebugSFBias() const;
  void           i34DebugSFBias(unsigned short d);

  unsigned short i34SFBias() const;
  void           i34SFBias(unsigned short d);

  unsigned short i34CompBias1() const;
  void           i34CompBias1(unsigned short d);

  unsigned short i34CompBias2() const;
  void           i34CompBias2(unsigned short d);

  unsigned short i34MSOBias1() const;
  void           i34MSOBias1(unsigned short d);

  unsigned short i34MSOBias2() const;
  void           i34MSOBias2(unsigned short d);

  unsigned short i34PreAmpBias() const;
  void           i34PreAmpBias(unsigned short d);

  unsigned short i34OutBias() const;
  void           i34OutBias(unsigned short d);

  unsigned short i34OutSFBias() const;
  void           i34OutSFBias(unsigned short d);

  unsigned short i12MSOBias1() const;
  void           i12MSOBias1(unsigned short d);
  
  unsigned short shaper12VCasc() const;
  void           shaper12VCasc(unsigned short d);

  unsigned short preAmp12VCasc() const;
  void           preAmp12VCasc(unsigned short d);
  
  unsigned short unconnected() const;
  void           unconnected(unsigned short d);
  
  unsigned short dac(unsigned n) const;
  void           dac(unsigned n, unsigned short d);

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


private:
  UtlPack _dac[16];
};


#ifdef CALICE_DAQ_ICC

#include <cstring>

#include "UtlPrintHex.hh"


MpsPcb1ConfigurationData::MpsPcb1ConfigurationData() {
  memset(this,0,sizeof(MpsPcb1ConfigurationData));
  for(unsigned i(0);i<31;i++) {
    dac(i,0x0800);
  }
  //iSenseColRef(3800);  
  //iSenseBias(3500);

  debugVthPos(2048+150);
  vth12Pos(2048+150);
  vth34Pos(2048+150);
  vth12Neg(1024);
  vth34Neg(1024);
}

unsigned short MpsPcb1ConfigurationData::debugVthPos() const {
  return _dac[ 0].halfWord(0);
}

void MpsPcb1ConfigurationData::debugVthPos(unsigned short d) {
  _dac[ 0].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::debugVthNeg() const {
  return _dac[ 0].halfWord(1);
}

void MpsPcb1ConfigurationData::debugVthNeg(unsigned short d) {
  _dac[ 0].halfWord(1,d);
}

int MpsPcb1ConfigurationData::debugVth() const {
  return (int)debugVthPos()-(int)debugVthNeg();
}
/*
void MpsPcb1ConfigurationData::debugVth(int d) {
  assert(d<4096 && d>-4096);
}
*/
unsigned short MpsPcb1ConfigurationData::vth12Pos() const {
  return _dac[ 1].halfWord(0);
}

void MpsPcb1ConfigurationData::vth12Pos(unsigned short d) {
  _dac[ 1].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::vth12Neg() const {
  return _dac[ 1].halfWord(1);
}

void MpsPcb1ConfigurationData::vth12Neg(unsigned short d) {
  _dac[ 1].halfWord(1,d);
}

int MpsPcb1ConfigurationData::vth12() const {
  return (int)vth12Pos()-(int)vth12Neg();
}

unsigned short MpsPcb1ConfigurationData::vth34Pos() const {
  return _dac[ 2].halfWord(0);
}

void MpsPcb1ConfigurationData::vth34Pos(unsigned short d) {
  _dac[ 2].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::vth34Neg() const {
  return _dac[ 2].halfWord(1);
}

void MpsPcb1ConfigurationData::vth34Neg(unsigned short d) {
  _dac[ 2].halfWord(1,d);
}

int MpsPcb1ConfigurationData::vth34() const {
  return (int)vth34Pos()-(int)vth34Neg();
}

unsigned short MpsPcb1ConfigurationData::vRst() const {
  return _dac[ 3].halfWord(0);
}

void MpsPcb1ConfigurationData::vRst(unsigned short d) {
  _dac[ 3].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::iSenseColRef() const {
  return _dac[ 3].halfWord(1);
}

void MpsPcb1ConfigurationData::iSenseColRef(unsigned short d) {
  _dac[ 3].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::preAmp34VCasc() const {
  return _dac[ 4].halfWord(0);
}

void MpsPcb1ConfigurationData::preAmp34VCasc(unsigned short d) {
  _dac[ 4].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::iSenseBias() const {
  return _dac[ 4].halfWord(1);
}

void MpsPcb1ConfigurationData::iSenseBias(unsigned short d) {
  _dac[ 4].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i12Comp1Bias() const {
  return _dac[ 5].halfWord(0);
}

void MpsPcb1ConfigurationData::i12Comp1Bias(unsigned short d) {
  _dac[ 5].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i12Comp2Bias() const {
  return _dac[ 5].halfWord(1);
}

void MpsPcb1ConfigurationData::i12Comp2Bias(unsigned short d) {
  _dac[ 5].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::iSenseIoutBias() const {
  return _dac[ 6].halfWord(0);
}

void MpsPcb1ConfigurationData::iSenseIoutBias(unsigned short d) {
  _dac[ 6].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::iSenseCompBias() const {
  return _dac[ 6].halfWord(1);
}

void MpsPcb1ConfigurationData::iSenseCompBias(unsigned short d) {
  _dac[ 6].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i12IoutBias() const {
  return _dac[ 7].halfWord(0);
}

void MpsPcb1ConfigurationData::i12IoutBias(unsigned short d) {
  _dac[ 7].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i12PreAmpBias() const {
  return _dac[ 7].halfWord(1);
}

void MpsPcb1ConfigurationData::i12PreAmpBias(unsigned short d) {
  _dac[ 7].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i12ShaperBias() const {
  return _dac[ 8].halfWord(0);
}

void MpsPcb1ConfigurationData::i12ShaperBias(unsigned short d) {
  _dac[ 8].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i12CompBiasTrim() const {
  return _dac[ 8].halfWord(1);
}

void MpsPcb1ConfigurationData::i12CompBiasTrim(unsigned short d) {
  _dac[ 8].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i34CompBiasTrim() const {
  return _dac[ 9].halfWord(0);
}

void MpsPcb1ConfigurationData::i34CompBiasTrim(unsigned short d) {
  _dac[ 9].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i34DebugSFBias() const {
  return _dac[ 9].halfWord(1);
}

void MpsPcb1ConfigurationData::i34DebugSFBias(unsigned short d) {
  _dac[ 9].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i34SFBias() const {
  return _dac[10].halfWord(0);
}

void MpsPcb1ConfigurationData::i34SFBias(unsigned short d) {
  _dac[10].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i34CompBias1() const {
  return _dac[10].halfWord(1);
}

void MpsPcb1ConfigurationData::i34CompBias1(unsigned short d) {
  _dac[10].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i34CompBias2() const {
  return _dac[11].halfWord(0);
}

void MpsPcb1ConfigurationData::i34CompBias2(unsigned short d) {
  _dac[11].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i34MSOBias1() const {
  return _dac[11].halfWord(1);
}

void MpsPcb1ConfigurationData::i34MSOBias1(unsigned short d) {
  _dac[11].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i34MSOBias2() const {
  return _dac[12].halfWord(0);
}

void MpsPcb1ConfigurationData::i34MSOBias2(unsigned short d) {
  _dac[12].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i34PreAmpBias() const {
  return _dac[12].halfWord(1);
}

void MpsPcb1ConfigurationData::i34PreAmpBias(unsigned short d) {
  _dac[12].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i34OutBias() const {
  return _dac[13].halfWord(0);
}

void MpsPcb1ConfigurationData::i34OutBias(unsigned short d) {
  _dac[13].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::i34OutSFBias() const {
  return _dac[13].halfWord(1);
}

void MpsPcb1ConfigurationData::i34OutSFBias(unsigned short d) {
  _dac[13].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::shaper12VCasc() const {
  return _dac[14].halfWord(0);
}

void MpsPcb1ConfigurationData::shaper12VCasc(unsigned short d) {
  _dac[14].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::preAmp12VCasc() const {
  return _dac[14].halfWord(1);
}

void MpsPcb1ConfigurationData::preAmp12VCasc(unsigned short d) {
  _dac[14].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::i12MSOBias1() const {
  return _dac[15].halfWord(0);
}

void MpsPcb1ConfigurationData::i12MSOBias1(unsigned short d) {
  _dac[15].halfWord(0,d);
}

unsigned short MpsPcb1ConfigurationData::unconnected() const {
  return _dac[15].halfWord(1);
}

void MpsPcb1ConfigurationData::unconnected(unsigned short d) {
  _dac[15].halfWord(1,d);
}

unsigned short MpsPcb1ConfigurationData::dac(unsigned n) const {
  assert(n<32);
  return _dac[n/2].halfWord(n%2);
}

void MpsPcb1ConfigurationData::dac(unsigned n, unsigned short d) {
  assert(n<32);
  _dac[n/2].halfWord(n%2,d);
}

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

  for(unsigned i(0);i<4;i++) {
    o << s << " DACs " << std::setw(2) << 8*i << "-"
      << std::setw(2) << 8*i+7 << " =";

    for(unsigned j(8*i);j<8*(i+1);j++) {
      o << std::setw(6) << dac(j);
    }
    
    o << std::endl;
  }

  o << s << " Vthreshold debug; pos " << std::setw(4) << debugVthPos()
    << ", neg " << std::setw(4) << debugVthNeg() 
    << ", difference = " << std::setw(5) << debugVth() << std::endl;
  o << s << " Vthreshold reg12; pos " << std::setw(4) << vth12Pos()
    << ", neg " << std::setw(4) << vth12Neg() 
    << ", difference = " << std::setw(5) << vth12() << std::endl;
  o << s << " Vthreshold reg34; pos " << std::setw(4) << vth34Pos()
    << ", neg " << std::setw(4) << vth34Neg() 
    << ", difference = " << std::setw(5) << vth34() << std::endl;
  
  return o;
}

#endif
#endif
