/** @file
 * $Source: /afs/ba.infn.it/user/pamela/src/CVS/chewbacca/PamOffLineSW/techmodel/TmtcReader.cpp,v $
 * $Id: TmtcReader.cpp,v 1.1.1.1 2008/09/23 07:20:28 mocchiut Exp $
 * $Author: mocchiut $
 * 
 * Implementation of the TmtcReader class.
* ToBeDone:
* Control the CRC for the entire data Packet not just for single records
 */

extern "C" {
	#include "CRC.h"
}
#include "ReaderAlgorithms.h"
using namespace pamela::techmodel;


/**
 * Constructor. 
 */
TmtcReader::TmtcReader(void): 
  TechmodelAlgorithm(PacketType::Tmtc, "TechmodelTmtcReader") { 
  Tmtc = new TmtcEvent();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string TmtcReader::GetVersionInfo(void) const {
  return 
    "$Header: /afs/ba.infn.it/user/pamela/src/CVS/chewbacca/PamOffLineSW/techmodel/TmtcReader.cpp,v 1.1.1.1 2008/09/23 07:20:28 mocchiut Exp $\n";
}

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

/**
 * Unpack the Tmtc event
 */
void TmtcReader::PKT_RunEvent(char* mysubData, long int length) throw (WrongCRCException_PKTUsed){
   
    stringstream oss;
	string msg;	
	int  k;
    /* The ' k ' indexs the number of recs. 
     * It is needed to be indipendent from ' i ' because in case of CRC error the single record is skipped and ' i ' increase by one, but correct records to be stored are still ' i '.
    */
    k = 0;

    char subData[TMTC_SUB_LENGTH]={0};
    char CRCbuff[TMTC_SUBCRC_LENGTH]={0};
 //   char eventCRC[TMTC_CRC_LENGTH]={0};

    int numRecords = (length-TMTC_CRC_LENGTH)/(TMTC_SUB_LENGTH + TMTC_SUBCRC_LENGTH); //subtract the last two bytes because are the final CRC
    long int start=0;
    
    TmtcRecord* rec;    
    Tmtc->Records->Clear();
    TClonesArray &recs = *(Tmtc->Records);
    
    UINT16    partialCRC = 0; //partial CRC updated as mcmd packet is read (to compare with the last two bytes of this event)
    UINT16    readCRC = 0;    //partial CRC updated as mcmd packet is read (to compare with the last two bytes of this event)
    
    for(int i=0; i < numRecords; i++) 
    {
    	start=(TMTC_SUB_LENGTH+TMTC_SUBCRC_LENGTH)*i;
		for(int m=0; m<TMTC_SUB_LENGTH; m++){
			subData[m]=mysubData[m + start];
		}
		
		CRCbuff[0]=mysubData[start + TMTC_SUB_LENGTH];

        partialCRC = CM_Compute_CRC16(partialCRC, (UINT8*)&subData, TMTC_SUB_LENGTH);
        partialCRC = CM_Compute_CRC16(partialCRC, (UINT8*)&CRCbuff, TMTC_SUBCRC_LENGTH);
	if((UINT8)(CM_Compute_CRC16(0, (UINT8*)&subData, TMTC_SUB_LENGTH)) == (UINT8)CRCbuff[0])
	  {

        //This == CRCBuff is not really parametric take care if have to change the static lengths
            rec = new(recs[k++]) TmtcRecord(); //add a new TmtcRecord
            rec->TM_RECORD_OBT            = (((UINT32)subData[0]<<24)&0xFF000000) + (((UINT32)subData[1]<<16)&0x00FF0000) +  (((UINT32)subData[2]<<8)&0x0000FF00) + (((UINT32)subData[3])&0x000000FF);
            rec->TM_DIAG_AND_BILEVEL_ACQ  = (((UINT16)subData[4]<<8)&0x0000FF00) + (((UINT16)subData[5])&0x000000FF);
            
            for(int j = 0; j < 16; j++) {
                rec->TM_TH_ANA[j]    = ((((UINT16)subData[6 + 2*j]<<8)&0xFF00) + (((UINT16)subData[7 + 2*j])&0x00FF)); //20 is the size of TM_DEA_ANA(16) + OBT(4)
            }
            
            for(int j = 0; j < 6; j++) {
                rec->TM_DEA_ANA[j]   = subData[38+j];
            }
        } 
        else 
        {
        	oss.str("");
        	oss << "TMTC: Wrong CRC on Subpacket "<< i <<" int TMTC Packet starting at position " << start;         
        	msg=oss.str();
        	PamOffLineSW::mainLogUtil->logAll(msg);	
        }
    }    
//    readCRC = (((UINT16)(eventCRC[0]<<8))&0xFF00) + (((UINT16)eventCRC[1])&0x00FF);
    readCRC = (((UINT16)(mysubData[length - 2]<<8))&0xFF00) + (((UINT16)mysubData[length - 1])&0x00FF);  
    //    readCRC = (((UINT16)(mysubData[length - 1]<<8))&0xFF00) + (((UINT16)mysubData[length])&0x00FF);  
	
    
   // if(partialCRC != readCRC) throw WrongCRCException(" Wrong Global CRC for TMTC Packet ");
    if (partialCRC != readCRC)
    {
    	oss.str("");
    	oss<<"Wrong CRC for TMTC Packet: "<<" CRC COMPUTED= "<< partialCRC<<" CRC READ=  "<< readCRC;
    	msg=oss.str();
    	PamOffLineSW::mainLogUtil->logWarning(msg);	
    	throw WrongCRCException_PKTUsed(" Wrong CRC for TMTC Packet. ");
    }
}




