/** @file
 * $Source: /repository/PamOffLineSW/techmodel/CalibTrk2Reader.cpp,v $
 * $Id: CalibTrk2Reader.cpp,v 1.8 2008-03-21 16:18:46 messineo Exp $
 * $Author: messineo $
 * 
 * Implementation of the LogReader class.
* ToBeDone:
* Control the CRC for the entire data Packet not just for single records
 */

#include "ReaderAlgorithms.h"

extern "C" {
    #include "CRC.h"
    extern void trkcalibpkt_(int*, unsigned char[], long int*, int*); //(*)

    //Struct per il passaggio di dati da e verso la chiamata fortran
    extern struct {
    int   good0;
    int   DAQmode[6];
    int   DSPnumber[6];
    int   calibnumber[6];
    int   ncalib_event[6];
    int   ped_l1[6];
    int   ped_l2[6];
    int   ped_l3[6];
    int   sig_l1[6];
    int   sig_l2[6];
    int   sig_l3[6];
    int   nbad_l1[6];
    int   nbad_l2[6];
    int   nbad_l3[6];
    int   cal_flag[6];
    float DSPped_par[3072][6];
    float DSPsig_par[3072][6];
    int   DSPbad_par[3072][6];
    int   crc_cal[3][6];
    int   crc_hcal[6];
    } trkcalib_;
#include <dirent.h>
}

using namespace pamela::techmodel;


/**
 * Constructor. 
 */
CalibTrk2Reader::CalibTrk2Reader(void): 
  TechmodelAlgorithm(PacketType::CalibTrk2, "TechmodelCalibTrk2Reader") { 
  calibTrk2 = new CalibTrk2Event();
}



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

/**
 * Unpack the CalibTrk event
 */
void CalibTrk2Reader::PKT_RunEvent(char* data, long int dataLength) throw (CalibException){
    std::stringstream oss;    
	string msg;    
    int       ERROR;
    int curpos=1;                                               

    //Call to the FORTRAN routin that unpack tracker events
    trkcalibpkt_( &ERROR,(unsigned char*)data, &dataLength, &curpos); 

    calibTrk2->unpackError = ERROR;
    if (ERROR != 0) {
        oss.str("");
        oss <<  "CalibTrk2: Fortran77 function trkcalibpkt error code = " << ERROR;
        msg=oss.str();
        PamOffLineSW::mainLogUtil->logWarning(msg);	
    }

    //Store the unpacked data
    calibTrk2->good0 = trkcalib_.good0;
    memcpy(calibTrk2->DAQmode,      trkcalib_.DAQmode,      sizeof(calibTrk2->DAQmode));
    memcpy(calibTrk2->DSPnumber,    trkcalib_.DSPnumber,    sizeof(calibTrk2->DSPnumber));
    memcpy(calibTrk2->calibnumber,  trkcalib_.calibnumber,  sizeof(calibTrk2->calibnumber));
    memcpy(calibTrk2->ncalib_event, trkcalib_.ncalib_event, sizeof(calibTrk2->ncalib_event));
    memcpy(calibTrk2->ped_l1,       trkcalib_.ped_l1,       sizeof(calibTrk2->ped_l1));
    memcpy(calibTrk2->ped_l2,       trkcalib_.ped_l2,       sizeof(calibTrk2->ped_l2));
    memcpy(calibTrk2->ped_l3,       trkcalib_.ped_l3,       sizeof(calibTrk2->ped_l3));
    memcpy(calibTrk2->sig_l1,       trkcalib_.sig_l1,       sizeof(calibTrk2->sig_l1));
    memcpy(calibTrk2->sig_l2,       trkcalib_.sig_l2,       sizeof(calibTrk2->sig_l2));
    memcpy(calibTrk2->sig_l3,       trkcalib_.sig_l3,       sizeof(calibTrk2->sig_l3));
    memcpy(calibTrk2->nbad_l1,      trkcalib_.nbad_l1,      sizeof(calibTrk2->nbad_l1));
    memcpy(calibTrk2->nbad_l2,      trkcalib_.nbad_l2,      sizeof(calibTrk2->nbad_l2));
    memcpy(calibTrk2->nbad_l3,      trkcalib_.nbad_l3,      sizeof(calibTrk2->nbad_l3));
    memcpy(calibTrk2->cal_flag,     trkcalib_.cal_flag,     sizeof(calibTrk2->cal_flag));      

    int     tempBad_par[3072][6];
    float   tempPed_par[3072][6];
    float   tempSig_par[3072][6];
    int     tempCrc_cal[3][6];
    memcpy(tempBad_par,trkcalib_.DSPbad_par, sizeof(tempBad_par));      
    memcpy(tempPed_par,trkcalib_.DSPped_par, sizeof(tempPed_par));      
    memcpy(tempSig_par,trkcalib_.DSPsig_par, sizeof(tempSig_par));      
    memcpy(tempCrc_cal,trkcalib_.crc_cal,    sizeof(tempCrc_cal));      

    for (int i = 0; i < 6; i++){
        for (int j = 0; j < 3072; j++){
            calibTrk2->DSPbad_par[i][j] = tempBad_par[j][i];
            calibTrk2->DSPped_par[i][j] = tempPed_par[j][i];
            calibTrk2->DSPsig_par[i][j] = tempSig_par[j][i];
        }
        for (int k = 0; k < 3; k++){
            calibTrk2->crc_cal[i][k] = tempCrc_cal[k][i];
        }
    }
    
    PamOffLineSW::mainLogUtil->logError("CANNOT CHECK IF CalibTrk2 IS GOOD OR NOT ...");	

     //TODO: put the correct check here ....
     if(1>2){
     	oss.str("");
     	//oss <<  "CalibTrk1 Problem: ??[0] = " <<cperror[0]<<" cperror[1] = " <<cperror[1]<<" cperror[2] = " <<cperror[2]<<" cperror[3] = " <<cperror[3];
     	msg=oss.str();
		PamOffLineSW::mainLogUtil->logError(msg);
	  	throw CalibException("Wrong Global CRC for CalibTrk2 Packet ");
     }
//-----------------------------------------------------------------------------------------
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string CalibTrk2Reader::GetVersionInfo(void) const {
  return 
    "$Header: /repository/PamOffLineSW/techmodel/CalibTrk2Reader.cpp,v 1.8 2008-03-21 16:18:46 messineo Exp $\n";
}
