/** @file * $Source: /home/cvsmanager/yoda/techmodel/McmdReader.cpp,v $ * $Id: McmdReader.cpp,v 1.1.1.1 2004/07/06 12:20:23 kusanagi Exp $ * $Author: kusanagi $ * * Implementation of the McmdReader class. */ #define BYTE unsigned char #include #include extern "C" { #include #include "CRC.h" } #include #include "stdio.h" #include "ReaderAlgorithms.h" #include "event/mcmd/McmdRecord.h" using namespace pamela; using namespace pamela::techmodel; static log4cpp::Category& cat = log4cpp::Category::getInstance("pamela.techmodel.McmdReader"); /** * Constructor. */ McmdReader::McmdReader(void): TechmodelAlgorithm(PacketType::Mcmd, "Mcmd") { cat << log4cpp::Priority::DEBUG << "Constructor " << "\n " << log4cpp::CategoryStream::ENDLINE; Mcmd = new McmdEvent(); } /** * Get a string with the version info of the algorithm. */ std::string McmdReader::GetVersionInfo(void) const { return "$Header: /home/cvsmanager/yoda/techmodel/McmdReader.cpp,v 1.1.1.1 2004/07/06 12:20:23 kusanagi Exp $\n"; } /** * Initialize the algorithm with a special run. This will initialize the * event reader routines for all packet types. */ void McmdReader::Init(PamelaRun *run) { SetInputStream(run); run->WriteSubPacket(this, &Mcmd, Mcmd->Class()); } /** * Unpack the Mcmd event from an input file. * Each subpacket is prafaceded by 4 OBT bytes. * The elementar structure is a kind of * --------CPU - OBT--------------------------------- * OBT - 4 Bytes * --------Start Sub-Packet--------------------------------- * SeqID - 2 Bytes * T - 1 bit | spare - 7 bits | Mcmd-ID - 1 byte * Spare - 4 bits | Mcmd Lenght 12 bits * Time Tag - 4 Bytes * DATA - McmdLength * 2 Bytes * don't care - 1 Byte * END-ID - 1 Byte is the sum of subPacket Bytes module 256 * --------End Sub-Packet--------------------------------- * --------CPU CRC-16 on OBT + subPacket--------------------------------- * subCRC - 2 Bytes * this structure is repeated one or more times. * The last 2 Bytes are CRC16 computed by CPU on all previous (OBT + subpacket data + subCRC) repetitions * @Event Number * @length is the size in bytes of the event (or packet) */ void McmdReader::RunEvent(int EventNumber, long int length) { int i = 0; char OBT[4]; char subHeader[10]; char *subData; char subTrailer[2]; char subPckCRC[2]; char eventCRC[2]; long int start; unsigned short headerCRC; UINT16 subCRC; //CRC of the subpacket (updated as subPckt is read) UINT16 readCRC; //CRC read from the subpacket UINT16 partialCRC; //partial CRC updated as mcmd packet is read (to compare with CRC read in the total Mcmd header) long int lastPosition, dataLength; McmdRecord *rec; //the 2 bytes subtracted belong to the final event CRC bytes lastPosition = (long int)InputFile->tellg() + length - 2; Mcmd->Records->Clear(); TClonesArray &recs = *(Mcmd->Records); partialCRC = 0; while(InputFile->tellg() < lastPosition) { //Just to test crc /* char tempbuff[length]; InputFile->read(tempbuff, sizeof(tempbuff)); subCRC = 0; for (int jj = 0; jj < length ; jj++){ subCRC = CM_Compute_CRC16(subCRC, (BYTE*)(tempbuff+jj), 1); }*/ //Read the OBT preceeding the subpacket then calculate a partial CRC for it //and update the partialCRC start = InputFile->tellg(); InputFile->read(OBT, sizeof(OBT)); subCRC = CM_Compute_CRC16(0, (BYTE*)&OBT, 4); partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)&OBT, 4); //Read the header for the subPacket and read mcmdLength //12 is the total lenght of subHeader + subTrailer InputFile->read(subHeader, sizeof(subHeader)); subCRC = CM_Compute_CRC16(subCRC, (BYTE*)&subHeader, 10); partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)&subHeader, 10); dataLength = (((0x0fff)&((UINT16)subHeader[4]))<<8|((UINT16)subHeader[5])*2) - 12; if (dataLength < 0) break; //it should throw an exception ***TBD*** //read subpacket data according to data length then calculate partial CRC for data //and update the partialCRC // If dataLength > 0 reads the data and compute again a partial CRC // else set subData to 0 //if(dataLength > 0){ subData = new char[dataLength]; InputFile->read(subData, sizeof(unsigned char)*dataLength); for (int jj = 0; jj < dataLength ; jj++){ subCRC = CM_Compute_CRC16(subCRC, (BYTE*)(subData+jj), 1); partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)(subData+jj), 1); } //subCRC = CM_Compute_CRC16(subCRC, (BYTE*)&subData, dataLength); //} else { // subData = "0"; //} //Read the CRC inside of MCMD //To check sum of all sub packet data, module 256 ****TBD**** InputFile->read(subTrailer, sizeof(subTrailer)); subCRC = CM_Compute_CRC16(subCRC, (BYTE*)&subTrailer, 2); partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)&subTrailer, 2); //Read the CRC of subPacket InputFile->read(subPckCRC, sizeof(subPckCRC)); partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)&subPckCRC, 2); readCRC = (((BYTE)subPckCRC[0])<<8) + ((BYTE)subPckCRC[1]); //finally check if the RecordCRC is correct //and finally update the partialCRC //TO DO - if one CRC is wrong also the total one will be corrupted if (subCRC == readCRC){ rec = new(recs[i++]) McmdRecord(); //aggiungo un nuovo McmdRecord all'evento rec->MCMD_RECORD_OBT = (((UINT32)OBT[0]<<24)&0xFF000000) + (((UINT32)OBT[1]<<16)&0x00FF0000) + (((UINT32)OBT[2]<<8)&0x0000FF00) + (((UINT32)OBT[3])&0x000000FF); rec->SeqID = (((BYTE)subHeader[0]<<8)&0xFF00) + (((BYTE)subHeader[1])&0x00FF); rec->Tbit = ((BYTE)((subHeader[2]&0x80))>>7); rec->ID1 = (BYTE)subHeader[3]; rec->McmdLength = (0x0fff)&(((UINT16)(subHeader[4]<<8)) + ((UINT16)subHeader[5])); rec->TimeTag = (((UINT32)OBT[6]<<24)&0xFF000000) + (((UINT32)OBT[7]<<16)&0x00FF0000) + (((UINT32)OBT[8]<<8)&0x0000FF00) + (((UINT32)OBT[9])&0x000000FF); rec->endID = (BYTE)subTrailer[1]; rec->setMcmdData((BYTE*)&subData); //partialCRC = CM_Compute_CRC16(partialCRC, (BYTE*)&readCRC, 1); //free(subData); } else { cat << log4cpp::Priority::ERROR << "Wrong CRC on Subpacket int MCMD Packet starting at position " << start << "\n " << log4cpp::CategoryStream::ENDLINE; } } //in the end compare the calculated partial CRC with the MCMD packet CRC InputFile->read(eventCRC, sizeof(eventCRC)); readCRC = (((UINT16)(eventCRC[0]<<8))&0xFF00) + (((UINT16)eventCRC[1])&0x00FF); if(!(partialCRC == readCRC)) { cat << log4cpp::Priority::ERROR << "Wrong CRC for CalibS4 Packet" << "\n " << log4cpp::CategoryStream::ENDLINE; } }