/************************************************************************
 * AhcConfigReader.hh                                                   *
 *                                                                      *
 * class to load HAB settings from a config file                        *
 *                                                                      *
 * Author:  Benjamin Lutz                                               *
 * Version: 1.3                                                         * 
 * date:    12.04.05                                                    *
 *                                                                      *
 * 06.04.05  added support for different DAC values for each channel    *
 * 12.04.05  added LED_Sel to switch between VCalib destination         *
 * 26.04.05  added getHolsStart() function                              *
 *                                                                      *
 * to-do: predifined modes are not supportet until now                  *
 *                                                                      *
 ************************************************************************/

#ifndef AhcConfigReader_h
#define AhcConfigReader_h

#include <iostream>
#include <cstdio>
#include "AhcVfeConfigurationData.hh"
#include "AhcFeConfigurationData.hh"

class AhcConfigReader
{

public: 
  AhcConfigReader(char* filename, unsigned printlevel);         // constructor needs name of config file and printlevel
  ~AhcConfigReader();

  void insertSettings(AhcVfeConfigurationData* AHCVfe, unsigned slot, unsigned fe, unsigned chip); // these routines copies the values of the config file into 
  void insertSettings(AhcFeConfigurationData* CRCFe);           // the given data types

  unsigned getHoldStart();

private:

  ifstream _configFile;
  string _strBuffer;
  char _charBuffer[128];
  bool _readUser;
  bool _injectionResistor;
  bool _gainCap[4];
  bool _shapingCap[4];
  bool _DACenable;
  bool _DACuseFile;
  unsigned _DACvalue;
  char _DACfile[128];
  bool _Tcalib;
  unsigned _Vcalib;
  unsigned _calibWidth;
  bool _LEDSel;
  bool _holdEnable;
  unsigned _holdStart;
  unsigned _holdWidth;
  unsigned _printlevel;

  unsigned _DACvalueArray[22][8][12][18];
  
};
 

AhcConfigReader::AhcConfigReader(char* filename, unsigned printlevel)
{
  _readUser=false;
  _injectionResistor=true;
  _gainCap[0]=true;
  _gainCap[1]=true;
  _gainCap[2]=true;
  _gainCap[3]=true;
  _shapingCap[0]=true;
  _shapingCap[1]=true;
  _shapingCap[2]=true;
  _shapingCap[3]=true;
  _DACenable=false;
  _DACuseFile=false;
  _DACvalue=0;
  _DACfile[0]=0;
  _Tcalib=true;
  _Vcalib=0;
  _calibWidth=128;
  _LEDSel=false;
  _holdEnable=true;
  _holdStart=55;
  _holdWidth=64000;
  _printlevel=printlevel;


  cout << "**************************************" << endl << "loading settings from " << filename  << endl << endl;
   
  _configFile.open(filename);
  while (_configFile.good())
    {
      _configFile >> _strBuffer;
      
      if (_strBuffer=="#")
	{
	  _configFile.getline(_charBuffer,sizeof(_charBuffer));
	  if (printlevel >2) cout << "comment: "<< _charBuffer  << endl;
	}

      if (_strBuffer=="mode")
	{
	  _configFile >> _strBuffer;
	  if (_strBuffer=="physics") {}                //notimplemented yet
	  if (_strBuffer=="calibration") {}            //notimplemented yet
	    if (_strBuffer=="user") _readUser = true;
	  if (printlevel >4)	    cout << "found mode setting: "<< _strBuffer  << endl;
	}
      
      if (_readUser && _strBuffer=="injectionResistor")
	{
	  if (printlevel >4)	  cout << "injection resistor setting found" <<endl;
	  _configFile >> _strBuffer;
	  if (_strBuffer == "used")  
	    {
	      cout << "set injection resistor to 10kOhm" << endl;         
	      _injectionResistor = true;
	    }
	  else if (_strBuffer == "unused") 
	    {
		cout << "set injection resistor to shorted" << endl;         
	      _injectionResistor = false;
	    }
	  else 
	    {
	      cout << "syntax error: injectionResistor value must be used or unused only" << endl;
	      exit(1);
	    }
	  
	}
      if (_readUser && _strBuffer=="gainCapacitor0.1pF")
	{
	  if (printlevel >4)	  cout << "gain capacitor 0.1pF setting found" <<endl;
	  _configFile >> _strBuffer;
	  if (_strBuffer == "used")  
	    {
	      cout << "set gain capacitor 0.1pF on" << endl;         
	      _gainCap[3] = true;
	    }
	  else if (_strBuffer == "unused") 
	    {
	      cout << "set gain capacitor 0.1pF off" << endl;         
	      _gainCap[3] = false;
	    }
	  else 
	    {
	      cout << "syntax error: gainCapacitor0.1pF value must be used or unused only" << endl;
	      exit(1);
	    }
	}
      
 	if (_readUser && _strBuffer=="gainCapacitor0.2pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.2pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.2pF on" << endl;         
		_gainCap[2]=true; 
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.2pF off" << endl;         
		_gainCap[2]=false;
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.2pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
	if (_readUser && _strBuffer=="gainCapacitor0.4pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.4pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.4pF on" << endl;         
		_gainCap[1]=true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.4pF off" << endl;         
		_gainCap[1]=false;	
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.4pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
 	if (_readUser && _strBuffer=="gainCapacitor0.8pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.8pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.8pF on" << endl;         
		_gainCap[0]=true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.8pF off" << endl;         
		_gainCap[0]=false;
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.8pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

 	if (_readUser && _strBuffer=="shapingCapacitor0.3pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 0.3pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 0.3pF on" << endl;         
		_shapingCap[3] = true;
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 0.3pF off" << endl;         
		_shapingCap[3] = false; 
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor0.3pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
 	if (_readUser && _strBuffer=="shapingCapacitor0.6pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 0.6pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 0.6pF on" << endl;         
		_shapingCap[2] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 0.6pF off" << endl;         
		_shapingCap[2] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor0.6pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

 	if (_readUser && _strBuffer=="shapingCapacitor1.2pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 1.2pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 1.2pF on" << endl;         
		_shapingCap[1] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 1.2pF off" << endl;         
		_shapingCap[1] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor1.2pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="shapingCapacitor2.4pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 2.4pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 2.4pF on" << endl;         
		_shapingCap[0] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 2.4pF off" << endl;         
		_shapingCap[0] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor2.4pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
  	if (_readUser && _strBuffer=="DACenable")
	  {
	  if (printlevel >4)	    cout << "DAC enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set DAC on" << endl;         
		_DACenable = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set DAC off" << endl;         
		_DACenable = false;
	      }
	    else 
	      {
		cout << "syntax error: DACenable value must be on or off only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="DACmode")
	  {
	  if (printlevel >4)	    cout << "DAC mode setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "single")  
	      {
 		cout << "one single DAC value will be used" << endl;         
		_DACuseFile = false;
	      }
	    else if (_strBuffer == "multi") 
	      {
		cout << "DAC values will be read from file" << endl;         
		_DACuseFile = true;
	      }
	    else 
	      {
		cout << "syntax error: DACmode value must be single or multi only" << endl;
		exit(1);
	      }
	  }


  	if (_readUser && _strBuffer=="DACvalue")
	  {
	  if (printlevel >4)	    cout << "DAC value setting found" <<endl;
	    _configFile >> _DACvalue;
	    cout << "set DAC value to " << _DACvalue << endl;         
	  }

  	if (_readUser && _strBuffer=="DACfile")
	  {
	    if (printlevel >4)	    cout << "DAC file name found" <<endl;
	    _configFile >> _DACfile;
	    if (_DACuseFile)  cout << "found file "<< _DACfile << " with DAC values" << endl;         
	    else   cout << "found file "<< _DACfile << " with DAC values, but will not be used because DAC-mode is single" << endl; 
	  }


  	if (_readUser && _strBuffer=="TCalib")
	  {
	  if (printlevel >4)	    cout << "TCalib enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set TCalib on" << endl;         
		_Tcalib = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set TCalib off" << endl;         
		_Tcalib = false;
	      }
	    else 
	      {
		cout << "syntax error: TCalib value must be on or off only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="VCalib")
	  {
	    if (printlevel >4)	    cout << "Vcalib value setting found" <<endl;
	    _configFile >> _Vcalib;
	    cout << "set Vcalib to " << _Vcalib<< endl;         
	  }

  	if (_readUser && _strBuffer=="calibWidth")
	  {
	  if (printlevel >4)	    cout << "calibWidth value setting found" <<endl;
	    _configFile >> _calibWidth;
	    cout << "set calib width to " << _calibWidth << endl;         
	  }

	
	if (_readUser && _strBuffer=="LEDSel")
	  {
	  if (printlevel >4)	    cout << "LEDSel enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set LEDSel on" << endl;         
		_LEDSel = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set LEDSel off" << endl;         
		_LEDSel = false;
	      }
	    else 
	      {
		cout << "syntax error: LEDSel value must be on or off only" << endl;
		exit(1);
	      }
	  }



  	if (_readUser && _strBuffer=="holdEnable")
	  {
	  if (printlevel >4)	    cout << "hold enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set hold on" << endl;         
		_holdEnable = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set hold off" << endl;         
		_holdEnable = false;
	      }
	    else 
	      {
		cout << "syntax error: holdEnable value must be on or off only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="holdStart")
	  {

	  if (printlevel >4)	    cout << "holdStart value setting found" <<endl;
	    _configFile >> _holdStart;
	    cout << "set hold start to " << _holdStart << endl;         
	  }


  	if (_readUser && _strBuffer=="holdWidth")
	  {
	  if (printlevel >4)	    cout << "holdWidth value setting found" <<endl;
	    _configFile >> _holdWidth;
	    cout << "set hold width to " << _holdWidth << endl;         
	  }
	_strBuffer  = "";
      }

  _configFile.close();

  for (unsigned slot(5);slot<22;slot++)
    for (unsigned fe(0);fe<8;fe++)
      for (unsigned chip(0);chip<12;chip++)
	for (unsigned chan(0);chan<18;chan++)  _DACvalueArray[slot][fe][chip][chan] = _DACvalue;

  if (_DACuseFile) 
    {
      if (printlevel >4)  cout << "trying to load DAC values from " << _DACfile <<endl;
      if (_DACfile == "") 
	{ 
	  cout << "syntax error: emtpy DAC file string. In DACmode multi you must supply a valid DACfile value" << endl;
	  exit(1);
	}

      _configFile.open(_DACfile);

      if (!_configFile.good() || !_configFile.is_open()) 
	{
	  cout << "file error: error while opening "<< _DACfile << " please check if file exist and is readable" << endl;	  
	  exit(1);
	}

      unsigned DACentries(0);
      unsigned badEntries(0);
      unsigned slot, fe, chip, chan, value;
      bool dataStart(false);
      while (_configFile.good())
	{
	  if (!dataStart)
	    {
	      _configFile >> _strBuffer;
	      
	      if (_strBuffer=="#")
		{
		  _configFile.getline(_charBuffer,sizeof(_charBuffer));
		  if (printlevel >2) cout << "comment: "<< _charBuffer  << endl;
		}
	      if (_strBuffer=="--data--") dataStart = true;
	      
	    }
	  else
	    {
	      _configFile >> slot >> fe >> chip >> chan >> value;
	      if (value < 256)  _DACvalueArray[slot][fe][chip][chan] = value;
	      else 
		{
		  cout << "-- range error -- slot: " << slot << "  frontend: " << fe << "  chip: " << chip << "  channel: " << chan << "  DAC value: "<< value <<endl;
		  badEntries++;
		}
	      DACentries++;
	      if (printlevel > 4) cout << "slot: " << slot << "  frontend: " << fe << "  chip: " << chip << "  channel: " << chan << "  DAC value: "<< value <<endl;
	    }
	}
      _configFile.close();
      cout << "found " << DACentries << " DAC setting entries in file" << endl;
      cout << badEntries << " entries were out of range and not used" << endl;
    }


  cout << endl << "finished loading settings" << endl <<"**************************************" << endl << endl ;
}

AhcConfigReader::~AhcConfigReader() 
{
}

void AhcConfigReader::insertSettings(AhcVfeConfigurationData* AHCVfe,unsigned slot, unsigned fe, unsigned chip)
{
  AhcVfeShiftRegister sr;
  sr.injectionResistor(_injectionResistor);

  for (int i(0);i<4;i++)
    {
      sr.gainCapacitor(i,_gainCap[i]);
      sr.shapingCapacitor(i,_shapingCap[i]);
    }

  for (int i(0);i<12;i++)
    {
      AHCVfe->shiftRegister(i,sr);
    }

  //  if (_printlevel > 0) 
  cout << "loaded settings to AhcVfeConfigurationData structure" << endl;
  //AHCVfe->print(cout);
}

void AhcConfigReader::insertSettings(AhcFeConfigurationData* CRCFe)
{
  CRCFe->calibEnable(_Tcalib);
  CRCFe->calibWidth(_calibWidth);

  CRCFe->dacData(CrcFeConfigurationData::top,_Vcalib);
  CRCFe->dacData(CrcFeConfigurationData::bot,_Vcalib);

  CRCFe->holdStart(_holdStart);
  CRCFe->holdWidth(_holdWidth);

  AhcVfeControl c;
  c.ledSel(CrcFeConfigurationData::top,!_LEDSel);
  c.ledSel(CrcFeConfigurationData::bot,!_LEDSel);
  c.swHoldIn(CrcFeConfigurationData::top,!_holdEnable);
  c.swHoldIn(CrcFeConfigurationData::bot,!_holdEnable);
  CRCFe->vfeControl(c);

  //  if (_printlevel > 0) 
  cout << "loaded settings to AhcFeConfigurationData structure" << endl;
  //CRCFe->print(cout);
}

unsigned AhcConfigReader::getHoldStart()
{
  return _holdStart;
}



#endif
