/* * PndMvdReadInTBData.cxx * * Created on: 23.10.2014 * Author: Stockmanns */ #include #include "mrfdata_8b.h" #include "mrftools.h" #include "boost/archive/binary_oarchive.hpp" #include "boost/archive/binary_iarchive.hpp" #include "boost/serialization/binary_object.hpp" #include PndMvdReadInTBData::PndMvdReadInTBData() : fDigiArray(0), fClockFrequency(0), fSuperFrameCount(0), fOldFrameCount(0), fFirstHeader(kTRUE), fFE(-1), fNonSequentialFC(0), fWrongHammingCodeCount(0),fHeaderPresent(kFALSE), fTrailerPresent(kFALSE), fDoubleHeader(0), fDoubleTrailer(0), fDataLostCount(0), fVerbose(0),order(16), polynom(0x8005), direct(1), crcinit(0x0000), crcxor(0x0000), refin(0), refout(0) { // TODO Auto-generated constructor stub crcmask = ((((unsigned long)1<<(order-1))-1)<<1)|1; crchighbit = (unsigned long)1<<(order-1); GenerateCRCTable(); } PndMvdReadInTBData::~PndMvdReadInTBData() { // for (int i = 0; i < fFileHandle.size(); i++){ fFileHandle->close(); delete(fFileHandle); // } } void PndMvdReadInTBData::GenerateCRCTable() { // make CRC lookup table used by table algorithms ULong64_t bit, crc; for (int i=0; i<256; i++) { crc=(ULong64_t)i; if (refin) { crc=ReflectBitsStream(crc, 8); } crc<<= order-8; for (int j=0; j<8; j++) { bit = crc & crchighbit; crc<<= 1; if (bit) { crc^= polynom; } } if (refin) { crc = ReflectBitsStream(crc, order); } crc&= crcmask; crctab[i]= crc; } } UShort_t PndMvdReadInTBData::CheckHammingCode(ULong64_t dataword, int dataword_length) { // This function expects a standard hamming encoded dataword (including hamming bits at 2^i positions) and returns the hamming bits // If the dataword is correct, the hamming bits are 0 // If an error occured, the hamming bits are !=0 // If a 1-bit error occured, the hamming bits give the possions of the wrong bit ULong64_t shift=1; ULong64_t hamming_code=0; if(dataword_length > 63) { std::cout << "Error: maximum length of datastream is 63" << std::endl; return 0xffff; } // loop over all hamming bits for (int i = 0; pow(2,i) < dataword_length; ++i) { int start=pow(2,i); int stepwidth=2*start; int parity_bit=0; for (int j = start; j < dataword_length+1; j+=stepwidth) { for (int k = j; k < j+stepwidth/2 && k < dataword_length+1; ++k) { parity_bit ^= ((dataword & (shift <<(k-1)))>> (k-1)); } } hamming_code += (parity_bit << i); } return hamming_code; } ULong64_t PndMvdReadInTBData::ConvertToPix4HammingToStandardHamming(ULong64_t topixhamming) { // The ToPix header and trailer data word consists of 34 data bits and 6 hamming bits. // bit no: 39 38 37 36 35 9 8 7 6 5 4 3 2 1 0 // In a ToPix4 dataword the hamming bits are at the end of the word: (d34)(d33)(d32)(d31)(d30) ... (d04)(d03)(d02)(d01)(H 6)(H 5)(H 4)(H 3)(H 2)(H 1) // At the standard hamming encoding the hamming bits are at the 2^i positions (d34)(d33)(d32)(d31)(d30) ... (d07)(d06)(d05)(d04)(H 3)(d03)(d02)(d01)(H 2)(H 1) // This function expects a ToPix4 encoded dataword and moves the hamming bits at the end to the defined positions. ULong64_t standard_hamming = 0; standard_hamming = ( topixhamming & 0xff00000000); standard_hamming += ((topixhamming & 0x00fffe0000) >> 1 ); standard_hamming += ((topixhamming & 0x000001fc00) >> 2 ); standard_hamming += ((topixhamming & 0x0000000380) >> 3 ); standard_hamming += ((topixhamming & 0x0000000040) >> 4 ); standard_hamming += ((topixhamming & 0x0000000020) << 26 ); standard_hamming += ((topixhamming & 0x0000000010) << 11 ); standard_hamming += ((topixhamming & 0x0000000008) << 4 ); standard_hamming += ((topixhamming & 0x0000000004) << 1 ); standard_hamming += ( topixhamming & 0x0000000002); standard_hamming += ( topixhamming & 0x0000000001); return standard_hamming; } void PndMvdReadInTBData::Init(){ //std::cout << "PndMvdReadInTBData::Init called" << std::endl; // for (int i = 0; i < fFileName.size(); i++){ std::ifstream* ifs = new std::ifstream(fFileName.Data(), std::ios::binary); std::cout << "File: " << fFileName << " is good: " << ifs->good() << std::endl; fFileHandle=ifs; // } fChipIdMap[0] = 0; fChipIdMap[1] = 1; fChipIdMap[2] = 2; fChipIdMap[3] = 3; } Bool_t PndMvdReadInTBData::ReadInData(TClonesArray* sdsDigiContainer){ TMrfData_8b* tempdata; tempdata = new TMrfData_8b; ULong_t dataword=0; Bool_t endOfFile = kFALSE; fOutputArray = sdsDigiContainer; // for (int k = 0; k < fFileHandle.size(); k++){ std::vector rawArray; endOfFile |= ReadInRawData(fFileHandle, rawArray); // SetFE(k); AnalyzeData(rawArray, fClockFrequency); // } return endOfFile; } Bool_t PndMvdReadInTBData::ReadInRawData(std::ifstream* fileHandle, std::vector& rawData){ TMrfData_8b* tempdata; tempdata = new TMrfData_8b; ULong_t dataword=0; Bool_t endOfFile = kFALSE; if (fileHandle->good()){ if (fVerbose > 2) { std::cout << std::endl; std::cout << "PndMvdReadInTBData::ReadInRawData reading file " << std::endl; } try{ boost::archive::binary_iarchive iar(*fileHandle); //this line causes an "Invalid Signature Error" at the end of the file but the file is still good iar >> tempdata; } catch (boost::archive::archive_exception& exception){ if (fVerbose > 1) std::cout << "PndMvdReadInTBData::ReadInRawData: Error found in reading file " << " : " << fileHandle->good() << " " << fileHandle->eof() << " Exception: " << exception.code << std::endl; if (fVerbose > 1) std::cout << exception.what() << std::endl; if (exception.code == 3){ endOfFile = kTRUE; return endOfFile; } else { return endOfFile; } } if (fVerbose > 2) std::cout << fFE << " PndMvdReadInTBData::ReadInRawData: NWords: " << tempdata->getNumWords() << std::endl; for (UInt_t i=0;i < tempdata->getNumWords();i+=5) { dataword=0; for(uint j=0; j< 5 ; j++) { dataword = dataword << 8; dataword += tempdata->getWord(i+j); } rawData.push_back(dataword); ULong_t frameCount = dataword & 0x3FC0000; frameCount = frameCount >> 18; if (fVerbose > 2) std::cout << std::dec << "dataword No "<< i/5<< "/"<< tempdata->getNumWords()/5 << ": "< p, ULong64_t len) { // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. // only usable with polynom orders of 8, 16, 24 or 32. ULong64_t crc = crcinit_direct; std::vector::iterator it=p.begin(); if (refin) { crc = ReflectBitsStream(crc, order); } if (!refin) { while (len--) { crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ (*it & 0xff)]; it++; } } else { while (len--) { crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ (*it & 0xff)]; it++; } } if (refout^refin) { crc = ReflectBitsStream(crc, order); } crc^= crcxor; crc&= crcmask; return(crc); } ULong64_t PndMvdReadInTBData::ReflectBitsStream(ULong64_t crc, int bitnum) { // reflects the lower 'bitnum' bits of 'crc' ULong64_t i, j=1, crcout=0; for (i=(ULong64_t)1<<(bitnum-1); i; i>>=1) { if (crc & i) { crcout|=j; } j<<= 1; } return (crcout); } void PndMvdReadInTBData::AnalyzeToPixFrame(Double_t clockFrequency) { if (fVerbose > 2) { std::cout << fFE << " PndMvdReadInTBData::AnalyzeToPixFrame: fToPixFrame size: " << std::dec << fToPixFrame.size() << " header " << std::hex << fToPixFrame[0] << std::endl; } PndSdsDigiTopix4 recentPixel; std::vector topix_data; // vector necessary to do crc check for(int i=1; i< fToPixFrame.size()-1;i++) { for(int j=0; j<8 ;j++) { if(j==0 or j==1 or j==2) { topix_data.push_back(0x00); } else { topix_data.push_back((fToPixFrame[i] >> (7-j)*2*4) & 0xff); } } } ULong64_t crc_calculated = CalculateCRCTableFast(topix_data,topix_data.size()); if(crc_calculated != ((fToPixFrame.back()>>6) & 0xffff)) { if(fVerbose == -1) { std::cout << fFE << " CRC WRONG! Frame will be deleted. Calculated CRC: " <>6) & 0xffff) << std::endl; for(int y=0; y< fToPixFrame.size(); y++) { if(y==0) { std::cout <> 38; //header = header >> 38; switch (header) { case 1 : fRecentFrameHeader = BitAnalyzeHeader(fToPixFrame[i]); if (fVerbose > 2) std::cout << fFE << " FrameHeader: rawData: " << std::hex << fToPixFrame[i] << " chip " << std::dec << fRecentFrameHeader.fChipAddress << " framecount " << fRecentFrameHeader.fFrameCount << std::endl; if (fOldFrameCount + 1 != fRecentFrameHeader.fFrameCount){ if (!(fOldFrameCount == 255 & fRecentFrameHeader.fFrameCount == 0)){ if (fVerbose > 1) std::cout << fFE << "-E- non sequential FC: " << fOldFrameCount << " " << fRecentFrameHeader.fFrameCount << std::endl; fNonSequentialFC++; } } if (fOldFrameCount > fRecentFrameHeader.fFrameCount){ fSuperFrameCount++; if (fVerbose > 1) std::cout << fFE << " SuperFrameCount increased: " << std::dec<< fSuperFrameCount << " oldFC " << fOldFrameCount << " recent FC " << fRecentFrameHeader.fFrameCount << std::endl; } fOldFrameCount = fRecentFrameHeader.fFrameCount; //new ((*fOutputArrayHeader)[fOutputArrayHeader->GetEntriesFast()]) frameHeader(fRecentFrameHeader); break; case 2 : fRecentFrameTrailer = BitAnalyzeTrailer(fToPixFrame[i]); if (fRecentFrameTrailer.fFrameCRC !=0 && (fToPixFrame.size() < 20)) { // std::cout << fFE << " Frame counter " << fRecentFrameHeader.fFrameCount << std::endl; if(fVerbose ==0) { for(int y=0; y< fToPixFrame.size(); y++) { if(y==0) { std::cout < 2) std::cout << fFE <<" FrameTrailer: nEvents " << fRecentFrameTrailer.fNEvents << " frame CRC: " << fRecentFrameTrailer.fFrameCRC << std::endl; break; case 3 : recentPixel = ProcessData(fToPixFrame[i], fRecentFrameHeader, clockFrequency); if (fVerbose > 2) std::cout << fFE << " Pixel: " << recentPixel << std::endl; new ((*fOutputArray)[fOutputArray->GetEntriesFast()]) PndSdsDigiTopix4(recentPixel); break; } } } void PndMvdReadInTBData::AnalyzeData(std::vector& rawData, Double_t clockFrequency) { if (fVerbose > 2) std::cout << "PndMvdReadInTBData::AnalyzeData rawData.size(): " << rawData.size() << std::endl; for (int i = 0; i < rawData.size(); i++){ ULong_t header = rawData[i] & 0xC000000000; header = header >> 38; if (fFirstHeader) { if (header == 1){ fFirstHeader = kFALSE; } else { continue; } } if(header==1 or header==2) { ULong_t hammingcheck = CheckHammingCode(ConvertToPix4HammingToStandardHamming(rawData[i]),40); if(hammingcheck!=0) { if (fVerbose > 1) { std::cout << "Wrong Hamming Code found!: " << std::hex<< rawData[i] << " Parity bits "<< hammingcheck << std::endl; } fWrongHammingCodeCount++; continue; } } if (header == 1) // header word found { if(fHeaderPresent==kTRUE) { // double header found, cant check previous data without trailer, clear vector fDoubleHeader++; if (fVerbose > 1) { std::cout << "Double Header Found! count: " << fDoubleHeader << "| FE: " << fFE << std::hex << " last ToPixFrame element: "<< fToPixFrame.back()<< " new frame header " << rawData[i] << std::endl; } fToPixFrame.clear(); fToPixFrame.push_back(rawData[i]); } else { // header found, start recording topix frame fTrailerPresent=kFALSE; fHeaderPresent=kTRUE; fToPixFrame.push_back(rawData[i]); } } else if(header == 2) // trailer word found { if(fTrailerPresent==kTRUE) { // double trailer found, cant give the hits a valid timestamp without the header, clear vector fToPixFrame.clear(); fDoubleTrailer++; if (fVerbose > 1) { std::cout << "Double Trailer Found! Double header counter: " << fDoubleTrailer << std::endl; } } else { if(fHeaderPresent==kTRUE) { // one topix frame found! Go and analyze the vector... fHeaderPresent=kFALSE; fTrailerPresent=kTRUE; fToPixFrame.push_back(rawData[i]); // if (fVerbose > 1) // { // std::cout << "ToPix Frame found! Go and analyze this amont of data: " << fToPixFrame.size() << std::endl; //} AnalyzeToPixFrame(clockFrequency); fToPixFrame.clear(); } else { if (fVerbose > 1) { std::cout << "Trailer without header found! Double header counter: " << fDoubleHeader << std::endl; } // trailer without header, can happen at the beginning of the file or the header was not detected correctly // this case is in principle impossible to enter fDoubleTrailer++; fToPixFrame.clear(); continue; } } } else if(header==3) // data word found { if(fHeaderPresent==kTRUE) { // found data while a active header is present, go and save the data fToPixFrame.push_back(rawData[i]); } else { // found data without a valid header, may happen at the beginning of the file or the header was detected fDataLostCount++; } } else { // not interessting } } } frameHeader PndMvdReadInTBData::BitAnalyzeHeader(ULong64_t& header) { frameHeader tempHeader; ULong_t temp = header; tempHeader.fECC = temp & 0x3F; temp = temp >> 18; tempHeader.fFrameCount = temp & 0xFF; temp = temp >> 8; tempHeader.fChipAddress = temp & 0xFFF; return tempHeader; } frameTrailer PndMvdReadInTBData::BitAnalyzeTrailer(ULong64_t& trailer) { frameTrailer tempTrailer; ULong_t temp = trailer; tempTrailer.fECC = temp & 0x3F; temp = temp >> 6; tempTrailer.fFrameCRC = temp & 0xFFFF; temp = temp >> 16; tempTrailer.fNEvents = temp & 0xFFFF; return tempTrailer; } pixel PndMvdReadInTBData::BitAnalyzePixelData(ULong64_t& data) { //le_dataword = ((dataword & 0x0000000000fff000)>>12);¬ //te_dataword = (dataword & 0x0000000000000fff);¬ //pixeladdress = ((dataword & 0x0000003fff000000)>>24);¬ pixel tempPixel; ULong_t temp = data; tempPixel.fTrailingEdge = mrftools::grayToBin(temp & 0X0000000000000FFF); temp = temp >> 12; tempPixel.fLeadingEdge = mrftools::grayToBin(temp & 0X0000000000000FFF); temp = temp >> 12; tempPixel.fPixelAddress = temp & 0X00000000000003FFF; // if (fVerbose > 1) std::cout << "BitAnalyzePixelData: " << std::hex << data << " pixel " << std::dec << tempPixel.fPixelAddress << " " << tempPixel.fLeadingEdge << " " << tempPixel.fTrailingEdge << std::endl; return tempPixel; } PndSdsDigiTopix4 PndMvdReadInTBData::ProcessData(ULong64_t& data, frameHeader& header, Double_t& clockFrequency) { if (fVerbose > 1) std::cout << "PndMvdReadInTBData::ProcessData raw Data: " << data << std::endl; pixel pixelData = BitAnalyzePixelData(data); std::pair pixelAddress = PixeladdressToMatrixAddress(pixelData.fPixelAddress); Double_t timestamp = ((Double_t)fSuperFrameCount * 256. * 4096. + (Double_t)header.fFrameCount * 4096. + (Double_t)pixelData.fLeadingEdge)/clockFrequency * 1000.; // if (fVerbose > 1) std::cout << "PndMvdReadInTBData::ProcessData timestamp: FE " << fFE << " SFC " << fSuperFrameCount << " FC " << header.fFrameCount << " LE " << pixelData.fLeadingEdge << " TE " << pixelData.fTrailingEdge << " TS " << timestamp < 1) std::cout << "RawAddress: " << pixelData.fPixelAddress << " " << pixelAddress.first << "/" << pixelAddress.second << " LE " << pixelData.fLeadingEdge << " TE " << pixelData.fTrailingEdge << std::endl; std::vector indices; // just for compatibility with PndSdsDigiPixel return PndSdsDigiTopix4(indices, 0, 0, fFE, pixelAddress.first, pixelAddress.second, pixelData.fLeadingEdge, pixelData.fTrailingEdge, header.fFrameCount, timestamp); } std::pair PndMvdReadInTBData::PixeladdressToMatrixAddress(UInt_t pixelglobaladdress) { // Matrix: 32 columns x 20 rows UInt_t double_column_address =0; UInt_t double_column_side=0; UInt_t pixel_address=0; UInt_t matrix_column, matrix_row; UInt_t temp = pixelglobaladdress; pixel_address= temp & 0x7f; //todo check if this conversion is correct! temp = temp >> 7; double_column_side= temp & 0x1; temp = temp >> 1; double_column_address= temp & 0x3f; temp = temp >> 6; // if (pixel_address > 127) { // std::cout << "-E- PndMvdReadInTBData::PixeladdressToMatrixAddress PixelAddress > 128 " << pixel_address << std::endl; // } // temp = temp >> 6; // if (fVerbose > 1) std::cout << "PixeladdressToMatrix rawData " << pixelglobaladdress << " dc " << double_column_address << " dcs " << double_column_side << " pixel " << pixel_address << std::endl; UInt_t sel = (double_column_address<<1) | (double_column_side); if(sel == 0) { matrix_row = pixel_address; matrix_column = 1; } else if(sel ==1) { matrix_row = pixel_address; matrix_column = 0; } else if(sel == 6) { matrix_row = pixel_address; matrix_column = 19; } else if(sel == 7) { matrix_row = pixel_address; matrix_column = 18; } else if (sel==2) { if (pixel_address <32) { matrix_row = pixel_address; matrix_column = 3; } else if (pixel_address < 64) { matrix_row = 31 - (pixel_address-32); matrix_column = 4; } else if (pixel_address < 96) { matrix_row = (pixel_address-64); matrix_column = 7; } else if (pixel_address < 128) { matrix_row = 31 - (pixel_address-96); matrix_column = 8; } } else if (sel==3) { if (pixel_address <32) { matrix_row = pixel_address; matrix_column = 2; } else if (pixel_address < 64) { matrix_row = 31 - (pixel_address-32); matrix_column = 5; } else if (pixel_address < 96) { matrix_row = (pixel_address-64); matrix_column = 6; } else if (pixel_address < 128) { matrix_row = 31 - (pixel_address-96); matrix_column = 9; } } else if (sel==4) { if (pixel_address < 32) { matrix_row = pixel_address; matrix_column = 10; } else if (pixel_address < 64) { matrix_row = 31 - (pixel_address-32); matrix_column = 13; } else if (pixel_address < 96) { matrix_row = (pixel_address-64); matrix_column = 14; } else if (pixel_address < 128) { matrix_row = 31 - (pixel_address-96); matrix_column = 17; } } else if (sel==5) { if (pixel_address < 32) { matrix_row = pixel_address; matrix_column = 11; } else if (pixel_address < 64) { matrix_row = 31 - (pixel_address-32); matrix_column = 12; } else if (pixel_address < 96) { matrix_row = (pixel_address-64); matrix_column = 15; } else if (pixel_address < 128) { matrix_row = 31 - (pixel_address-96); matrix_column = 16; } } return std::pair(matrix_column, matrix_row); }