
// Implementation of the CalibCalPulse1Reader class.
 

extern "C" {
#include "CRC.h"  
    //Struct per il passaggio di dati da e verso la chiamata fortran
extern struct {
        int   iev;
        int   pstwerr[4];
        float pperror[4];
        float calpuls[4][11][96];
    } calpul_; 
    
    //external declaration of the Fortran function 
    void calpulse_(char*, long int*, int*);
}

#include "ReaderAlgorithms.h"

using namespace pamela::techmodel;


/**
 * Constructor. 
 */
CalibCalPulse1Reader::CalibCalPulse1Reader(void): 
  TechmodelAlgorithm(PacketType::CalibCalPulse1, "TechmodelCalibCalPulse1Reader") { 
  calibCalPulse1 = new CalibCalPulse1Event();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string CalibCalPulse1Reader::GetVersionInfo(void) const {
  return 
    "$Header: /afs/ba.infn.it/user/pamela/src/CVS/chewbacca/PamOffLineSW/techmodel/CalibCalPulse1Reader.cpp,v 1.3 2009-07-24 13:53:43 mocchiut Exp $\n";
}

/**
 * Initialize the algorithm with a special run. This will initialize the
 * event reader routines for all packet types.
 */
void CalibCalPulse1Reader::Init(PamelaRun *run) {
  run->WriteSubPacket(this, &calibCalPulse1, calibCalPulse1->Class());
}

/**
 * Unpack the CalibCalPulse1 event
 */
void CalibCalPulse1Reader::PKT_RunEvent(char* packetData, long int dataLength) throw (Exception){
  
  string msg;    
  std::stringstream oss;       
  int         ERROR;

  //
  // FAFEDE0808 is used to store two different data set: when length = 6 we store the calorimeter answer to commands CAL_RESET, WRITE_FPGA_REG_CH, WRITE_FPGA_REG_VCAL
  // else when length > 6 we store calpulse1 data
  //  
  if ( dataLength == 6 ){
    if ( calpul_.iev != calpul_.iev || calpul_.iev < 0 || calpul_.iev > 9000000 ) calpul_.iev = 0;
    calpul_.iev++;
    calibCalPulse1->iev = calpul_.iev;    
    //
    calibCalPulse1->pstwerr[0] = 0;
    calibCalPulse1->pstwerr[1] = 0;
    calibCalPulse1->pstwerr[2] = 0;
    calibCalPulse1->pstwerr[3] = 0;
    //
    calibCalPulse1->pperror[0] = 129.;
    calibCalPulse1->pperror[1] = 129.;
    calibCalPulse1->pperror[2] = 129.;
    calibCalPulse1->pperror[3] = 129.;
    //
    float tempCalpuls[96][11][4];
    memset(calpul_.calpuls,0,sizeof(tempCalpuls));
    memcpy(tempCalpuls, calpul_.calpuls, sizeof(tempCalpuls));
    for (int i = 0; i < 4; i++){
      for (int j = 0; j <11; j++){
	for (int z = 0; z < 96; z++){
	  calibCalPulse1->calpuls[i][j][z]  = tempCalpuls[z][j][i];
	}
      }
    }
    //
    calibCalPulse1->CAL_RESET = (((UINT16)(packetData[0]<<8))&0xFF00) + (((UINT16)(packetData[1]))&0x00FF);
    calibCalPulse1->WRITE_FPGA_REG_CH = (((UINT16)(packetData[2]<<8))&0xFF00) + (((UINT16)(packetData[3]))&0x00FF);
    calibCalPulse1->WRITE_FPGA_REG_VCAL = (((UINT16)(packetData[4]<<8))&0xFF00) + (((UINT16)(packetData[5]))&0x00FF);
    calibCalPulse1->unpackError = 1;
    //
  } else {
    //
    calpulse_(packetData, &dataLength, &ERROR);
    
    calibCalPulse1->unpackError = ERROR;
    oss.str("");    
    if (ERROR != 0) {
      const char *errmsg="";
      switch (ERROR){
      case 1: errmsg = "CALORIMETER NOT FOUND";
      }
      oss << "CalibCalPulse1: Fortran77 function calpulse error code = " << ERROR
	  <<  " " << errmsg;
      msg=oss.str();
      if ( dataLength > 6 ) PamOffLineSW::mainLogUtil->logWarning(msg);	
    } //else {
    //Store the unpacked data
    calibCalPulse1->iev = calpul_.iev;
    memcpy(calibCalPulse1->pstwerr, calpul_.pstwerr, sizeof(calibCalPulse1->pstwerr));
    memcpy(calibCalPulse1->pperror, calpul_.pperror, sizeof(calibCalPulse1->pperror));
    //--------have to invert array because of FORTRAN <-> C different management of the indexes
    float tempCalpuls[96][11][4];
    memcpy(tempCalpuls, calpul_.calpuls, sizeof(tempCalpuls));
    for (int i = 0; i < 4; i++){
      for (int j = 0; j <11; j++){
	for (int z = 0; z < 96; z++){
	  calibCalPulse1->calpuls[i][j][z]  = tempCalpuls[z][j][i];
	}
      }
    }
    //
    calibCalPulse1->CAL_RESET = 0;
    calibCalPulse1->WRITE_FPGA_REG_CH = 0;
    calibCalPulse1->WRITE_FPGA_REG_VCAL = 0;
    //
  };
  //-----------------------------------------------------------------------------------------
  //}
}
