From c5e22543cf0b6a38ea603a72af84781d5950e64c Mon Sep 17 00:00:00 2001 From: Maps Date: Thu, 12 Dec 2024 11:51:09 +0100 Subject: [PATCH] added datachecks to analysis --- analysis/datachecks/CRCVerilogJan2.C | 187 +++ analysis/datachecks/dump | 1846 ++++++++++++++++++++++++++ analysis/datachecks/first.C | 63 + analysis/datachecks/mimosis.h | 404 ++++++ analysis/datachecks/mimosis.h.save | 230 ++++ analysis/datachecks/old_second.C | 266 ++++ analysis/datachecks/start.sh | 22 + analysis/datachecks/ucrc_t.cpp | 218 +++ analysis/datachecks/ucrc_t.h | 201 +++ 9 files changed, 3437 insertions(+) create mode 100644 analysis/datachecks/CRCVerilogJan2.C create mode 100644 analysis/datachecks/dump create mode 100644 analysis/datachecks/first.C create mode 100644 analysis/datachecks/mimosis.h create mode 100644 analysis/datachecks/mimosis.h.save create mode 100644 analysis/datachecks/old_second.C create mode 100755 analysis/datachecks/start.sh create mode 100644 analysis/datachecks/ucrc_t.cpp create mode 100644 analysis/datachecks/ucrc_t.h diff --git a/analysis/datachecks/CRCVerilogJan2.C b/analysis/datachecks/CRCVerilogJan2.C new file mode 100644 index 0000000..96475e5 --- /dev/null +++ b/analysis/datachecks/CRCVerilogJan2.C @@ -0,0 +1,187 @@ +#include +#include +#include +#include + + + +std::bitset<16> calc_crc(std::vector>& data_in_array) +{ + std::bitset<16> lfsr_c (0xFFFF),lfsr_c_nomsb, lfsr_q; + std::bitset<128> data_in; + + // reset + lfsr_c.set(); // = 0xFFFF; + + for (size_t i=0; i crc; + + std::vector> messageLong; + + long sizeOfInput=lengthOfArray; + + + cout << sizeOfInput << endl; + + long stepSize=4; + + sizeOfInput=(sizeOfInput/stepSize)*stepSize; //truncate last words due to faulty handling in hardware + + cout << sizeOfInput << endl; + cout << sizeOfInput/4 << endl; + + for (long i=0; i<(sizeOfInput/stepSize); i++){ + + cout << i<< " "; + + uint32_t tempInt = (inputMessage[4*i+stepSize-1]&0xffff)<<16; + tempInt = tempInt|((inputMessage[4*i+stepSize-1]&0xffff0000)>>16); + std::bitset<128> messageTemp(tempInt); + + cout << std::hex << (uint32_t)inputMessage[4*i+stepSize-1] << " "; + + + for(long j=1; j>16); + std::bitset<128> lowerBits (tempInt); + cout << std::hex << (uint32_t)inputMessage[4*i+stepSize-1-j] << " "; + messageTemp=messageTemp|lowerBits; + //cout << std::hex << " messageTemp " << messageTemp << endl; + } + cout << endl; + messageLong.push_back(messageTemp); + } + +// for (long i=0; i<(sizeOfInput/stepSize); i++){ +// +// cout << i<< " "; +// +// std::bitset<128> messageTemp(inputMessage[4*i]); +// cout << std::hex << (uint32_t)inputMessage[4*i] << " "; +// +// +// for(long j=1; j lowerBits ((uint32_t)inputMessage[4*i+j]); +// cout << std::hex << (uint32_t)inputMessage[4*i+j] << " "; +// messageTemp=messageTemp|lowerBits; +// //cout << std::hex << " messageTemp " << messageTemp << endl; +// } +// cout << endl; +// messageLong.push_back(messageTemp); +// } + +// for(size_t i=0; i + +#include "hadaq/TdcProcessor.h" +#include "hadaq/TrbProcessor.h" +#include "hadaq/HldProcessor.h" +#include "base/ProcMgr.h" +#include "mimosis.h" + + +void first() +{ + //base::ProcMgr::instance()->SetRawAnalysis(true); + base::ProcMgr::instance()->SetTriggeredAnalysis(true); + + // all new instances get this value + base::ProcMgr::instance()->SetHistFilling(4); + + // [min..max] range for TDC ids + //hadaq::TrbProcessor::SetTDCRange(0x610, 0x613); + hadaq::TrbProcessor::SetTDCRange(0x0000, 0x5fff); + + // [min..max] range for HUB ids + hadaq::TrbProcessor::SetHUBRange(0x8000, 0x8fff); + + // when first argument true - TRB/TDC will be created on-the-fly + // second parameter is function name, called after elements are created + hadaq::HldProcessor* hld = new hadaq::HldProcessor(false, "after_create"); + + + //-------------------------------------------------------------------------------------- + + // create TRB processor which holds custom data + hadaq::TrbProcessor* trb = new hadaq::TrbProcessor(0xa000, hld); + hadaq::TrbProcessor* trb1 = new hadaq::TrbProcessor(0xa001, hld); + hadaq::TrbProcessor* trb2 = new hadaq::TrbProcessor(0xa100, hld); + // create custom processor + hadaq::MimosisProcessor *mimosis = new hadaq::MimosisProcessor(trb, 0xa000); + hadaq::MimosisProcessor *mimosis1 = new hadaq::MimosisProcessor(trb1, 0xa001); + hadaq::MimosisProcessor *mimosis2 = new hadaq::MimosisProcessor(trb2, 0xa100); + + + +} + +// extern "C" required by DABC to find function from compiled code + +extern "C" void after_create(hadaq::HldProcessor* hld) +{ + printf("Called after all sub-components are created\n"); + + if (hld==0) return; + + for (unsigned k=0;kNumberOfTRB();k++) { + hadaq::TrbProcessor* trb = hld->GetTRB(k); + if (trb==0) continue; + + + printf("Configure %s!\n", trb->GetName()); + trb->SetPrintErrors(10); + } +} diff --git a/analysis/datachecks/mimosis.h b/analysis/datachecks/mimosis.h new file mode 100644 index 0000000..aeb25b5 --- /dev/null +++ b/analysis/datachecks/mimosis.h @@ -0,0 +1,404 @@ +#ifndef MimosisProcessor_h +#define MimosisProcessor_h + +#include "hadaq/SubProcessor.h" +#include +#include +#include +#include + +using namespace std; + + +std::bitset<16> calc_crc(std::vector>& data_in_array) { // FOR CRC TESTS + std::bitset<16> lfsr_c (0xFFFF),lfsr_c_nomsb, lfsr_q; + std::bitset<128> data_in; + + lfsr_c.set(); // = 0xFFFF; + + for (size_t i=0; i(HandleFrameLength); + const base::H1handle HandleNumHeaders = MakeH1("NumHeaders", "", 2000, 0, 2000, "#"); + TH1* NumHeaders = static_cast(HandleNumHeaders); + const base::H1handle HandleNumTrailers = MakeH1("NumTrailers", "Consecutive Frames", 500, 0, 500, "#"); + TH1* NumTrailers = static_cast(HandleNumTrailers); + const base::H1handle HandleRegionHeaders = MakeH1("RegionHeaders", "", 64, 0, 63, "#"); + TH1* RegionHeaders = static_cast(HandleRegionHeaders); + const base::H1handle HandleRegionCounts = MakeH1("RegionCounts", "", 64, 0, 63, "#"); + TH1* RegionCounts = static_cast(HandleRegionCounts); + const base::H1handle HandleColumns = MakeH1("Columns", "Hits per Column", 1024, 0, 1024, "#"); + TH1* Columns = static_cast(HandleColumns); + const base::H1handle HandleErrorFlags = MakeH1("ErrorFlags", "", 9, 0, 9, "Bit"); + TH1* ErrorFlags = static_cast(HandleErrorFlags); + const base::H2handle HandleFrameLengthDist = MakeH2("FrameLengthDist", "", 1024,0,1024,1024,0,1024,"this frame ; last frame"); + TH2* FrameLengthDist = static_cast(HandleFrameLengthDist); + const base::H2handle HandleMatrix = MakeH2("Matrix", "", 1024,0,1024,508,0,508); + TH2* Matrix = static_cast(HandleMatrix); + const base::H2handle HandleMatrixCurrent = MakeH2("MatrixCurrent", "", 1024,0,1024,508,0,508); + TH2* MatrixCurrent = static_cast(HandleMatrixCurrent); + const base::H2handle HandleMatrixLast = MakeH2("MatrixLast", "", 1024,0,1024,508,0,508); + TH2* MatrixLast = static_cast(HandleMatrixLast); + const base::H1handle HandleLast4096 = MakeH1("Last 4096 Content", "", 4095, 0, 4095, "Last 4096 Content"); + TH1* Last4096 = static_cast(HandleLast4096); + const base::H1handle HandleDataErrorHist = MakeH1("Data Error Histogram", "", nDataErrorChecks, 0, nDataErrorChecks, "Data Error Histogram"); // new + TH1* DataErrorHist = static_cast(HandleDataErrorHist); // new + const base::H1handle wrongcrchandle = MakeH1("wrong CRC", "32bit words", 2, 0, 2, "ch"); // FOR CRC TESTS + TH1* wrongcrc = static_cast(wrongcrchandle); // FOR CRC TESTS + + const base::H1handle HandleDiffFrameCountHist = MakeH1("DiffFrameCountHist", "", 10000, 2, 10002, "Data Error Histogram"); // new + TH1* DiffFrameCountHist = static_cast(HandleDiffFrameCountHist); + + unsigned int sensoraddress; + unsigned int sensor; + unsigned int length = 0; + unsigned int region = 0; + uint32_t frameCounter = 0; + uint32_t frameNumber = 0; + uint32_t oldFrameNumber = 0; + uint32_t frameCounter2 = 0; + TrbProcessor * const trb; + + + + ulong + calculate_crc(uint32_t* inputMessage, uint32_t lengthOfArray) { // FOR CRC TESTS + std::bitset<16> crc; + std::vector> messageLong; + long sizeOfInput=lengthOfArray; + long stepSize=4; + + sizeOfInput=(sizeOfInput/stepSize)*stepSize; //truncate last words due to faulty handling in hardware + + for (long i=0; i<(sizeOfInput/stepSize); i++) + { + uint32_t tempInt = (inputMessage[4*i+stepSize-1]&0xffff)<<16; + tempInt = tempInt|((inputMessage[4*i+stepSize-1]&0xffff0000)>>16); + + std::bitset<128> messageTemp(tempInt); + + for(long j=1; j>16); + std::bitset<128> lowerBits (tempInt); + messageTemp=messageTemp|lowerBits; + } + messageLong.push_back(messageTemp); + } + crc = calc_crc(messageLong); + return crc.to_ulong(); + } + + + + virtual bool DecodePixel(const unsigned int& word, unsigned int& column, unsigned int& row) const noexcept + { + unsigned int pixelcode = (word >> 6) & 0x3ff; + unsigned int side = 0, topdown = 0; + if((pixelcode&3) == 0x1 || (pixelcode&3) == 0x2) side = 1; + if((pixelcode&3) == 0x3 || (pixelcode&3) == 0x2) topdown = 1; + row = (pixelcode>>2)*2 + topdown; + column = (((word>>3)&0x7) + region*8)*2 + side; + return true; + } + + + public: + MimosisProcessor(TrbProcessor * const trb, const unsigned subid) noexcept + : hadaq::SubProcessor(trb, "%04X", subid) + , trb(trb) + , sensor(subid-0xa000) + , sensoraddress(subid) + {} + + + + virtual ~MimosisProcessor() noexcept override = default; + + + /** Scan all messages, find reference signals if returned false, buffer has error and must be discarded */ + virtual bool FirstBufferScan(const base::Buffer&) noexcept override; + + + /** Scan buffer for selecting messages inside trigger window */ + virtual bool SecondBufferScan(const base::Buffer&) const noexcept { return true; } + }; +} + + +bool hadaq::MimosisProcessor::FirstBufferScan(const base::Buffer& buf) noexcept +{ + DataErrorHist->GetXaxis()->SetBinLabel(1,"MisTr"); + DataErrorHist->GetXaxis()->SetBinLabel(2,"OverflTr"); + DataErrorHist->GetXaxis()->SetBinLabel(3,"OverflRegTr"); + DataErrorHist->GetXaxis()->SetBinLabel(4,"OverflSRegTr"); + DataErrorHist->GetXaxis()->SetBinLabel(5,"FrSzLimTr"); + DataErrorHist->GetXaxis()->SetBinLabel(6,"ErrChecks"); + DataErrorHist->GetXaxis()->SetBinLabel(7,"ErrFollFN"); + DataErrorHist->GetXaxis()->SetBinLabel(8,"ErrFollRA"); + DataErrorHist->GetXaxis()->SetBinLabel(9,"2HiRA"); + DataErrorHist->GetXaxis()->SetBinLabel(10,"ErrFollPE"); + DataErrorHist->GetXaxis()->SetBinLabel(11,"OverflBitRegHead"); + DataErrorHist->GetXaxis()->SetBinLabel(12,"ErrFollPix"); + DataErrorHist->GetXaxis()->SetBinLabel(13,"MisHead"); + + const uint32_t len = buf.datalen()/4; + uint32_t* arr = static_cast(buf.ptr()); + unsigned int n = 0; + unsigned int column, row, lastcolumn = -1, lastrow = -1; + unsigned int headers = 0, trailers = 0; + unsigned int headersnow = 0; + unsigned int lastlength = -1; + unsigned int hitcount = 0; + uint32_t data; + uint32_t currFrameNumber = 0; // new + uint32_t prevData = 0; + uint32_t startCase = 0; + uint32_t trailDetected = 0; + + unsigned int nMissingTrailer = 0; // new + unsigned int nOverflowInTrailer = 1; // new. + unsigned int nOverflowRegionInTrailer = 2; // new + unsigned int nOverflowSuperRegionInTrailer = 3; // new + unsigned int nFrameSizeLimitInTrailer = 4; // new + unsigned int nIncorrectChecksum = 5; // new + unsigned int nIncorrectFollowingFrameNumber = 6; // new + unsigned int nIncorrectFollowingRegionAddress = 7; // new + unsigned int nTooHighRegionAddress = 8; // new + unsigned int nIncorrectFollowingPE = 9; // new + unsigned int nOverflowBitInRegionHeader = 10; + unsigned int nIncorrectFollowingPix = 11; + unsigned int nMissingHeader = 12; + int lastRegion = -1; + int prevPix = -1; + int prevColumn = -1; + + uint16_t crcsum = 0; + int headerpos = -5; + + for (; n < len; n++) { + data = arr[n]; + length++; + + int assumeFirstFrameHeader = 1; + +// ----------- Begin of frame - store frame header + if ((data & 0xFF000000) == 0xFE000000) { + headers++; + headersnow++; + length = 0; + startCase = 1; + trailDetected = 0; + + headerpos = ( n-headerpos == 1 ) || ( n-headerpos == 2 ) || ( n-headerpos == 3 ) || ( n-headerpos == 4 ) ? headerpos : n; // FOR CRC TESTS + + if (headersnow == 1) { + oldFrameNumber = frameNumber; // new + frameNumber = (data & 0xFF0000) >> 16; + frameNumber += (data & 0xFF) << 8; + if (prevData != 0 && ((prevData & 0xFF000000) != 0xFF000000)) {DataErrorHist->Fill(nMissingTrailer);} // new. + } + + else if (headersnow == 2) { + frameNumber += data & 0xFF0000; + frameNumber += (data & 0xFF) << 24; + DiffFrameCountHist->Fill((frameNumber - oldFrameNumber) % 8000 ); + frameCounter2++; + if ((oldFrameNumber != 0xFFFFFFFF) && oldFrameNumber + 1 != frameNumber && assumeFirstFrameHeader == 0) { + cout << frameCounter2 << " " << oldFrameNumber << " " << frameNumber << endl; + DataErrorHist->Fill(nIncorrectFollowingFrameNumber); + } + else if (assumeFirstFrameHeader == 1) {assumeFirstFrameHeader = 0;} + } + // else {cout << "headearsNowError" << headersnow <<" " << std::hex << data << endl;} + /*if ((headersnow == 2) && (oldFrameNumber != 0xFFFFFFFF) && !((oldFrameNumber + 1 == frameNumber) || (oldFrameNumber + 3 == frameNumber))) { + cout << oldFrameNumber << " " << frameNumber << endl; + DataErrorHist->Fill(nIncorrectFollowingFrameNumber); + }*/ // new + lastRegion = -1; // new, declares new frame to check for region headers + + prevColumn = -1; + + } + +// ---------------- End Frame Header ------------------------ + + + + +//End of frame - process frame results and error flags + else if ((data & 0xFF000000) == 0xFF000000) { + length--; + trailers++; + frameCounter++; + MatrixCurrent->Fill(-1, -1); + if (trailDetected == 1 && startCase == 1) {DataErrorHist->Fill(nMissingHeade);} + trailDetected = 1; + crcsum = data & 0xFFFF; // FOR CRC TESTS + if(crcsum != calculate_crc(arr+headerpos,n-headerpos)) {wrongcrc->Fill(1); DataErrorHist->Fill(nIncorrectChecksum);} // FOR CRC TESTS + else {wrongcrc->Fill(0);} // FOR CRC TESTS + + Last4096->SetBinContent(frameNumber % 4096, hitcount); + hitcount = 0; + + if (frameCounter == 10000) { + MatrixCurrent->Copy(*MatrixLast); + MatrixLast->SetName("MatrixLast10000"); + MatrixCurrent->Reset(); + RegionCounts->Reset(); + frameCounter = 0; + } + + headersnow = 0; + FrameLength->Fill(length); + + if (lastlength != -1) { + FrameLengthDist->Fill(length, lastlength); + } + + lastlength = length; + if (data & 0x00010000) ErrorFlags->Fill(0); + if (data & 0x00020000) ErrorFlags->Fill(1); + if (data & 0x00040000) ErrorFlags->Fill(2); + if (data & 0x00080000) ErrorFlags->Fill(3); + if (data & 0x00100000) ErrorFlags->Fill(4); + if (data & 0x00200000) ErrorFlags->Fill(5); + if (data & 0x00400000) ErrorFlags->Fill(6); + if (data & 0x00800000) ErrorFlags->Fill(7); + if (!(data & 0x00FF0000)) ErrorFlags->Fill(8); + + if (data & 0x00010000) DataErrorHist->Fill(nOverflowInTrailer); + if (data & 0x00020000) DataErrorHist->Fill(nOverflowRegionInTrailer); + if (data & 0x00040000) DataErrorHist->Fill(nOverflowSuperRegionInTrailer); + if (data & 0x00080000) DataErrorHist->Fill(nFrameSizeLimitInTrailer); + + /* + if (data & 0b0000000100000000) DataErrorHist->Fill(nOverflowInTrailer); + if (data & 0b0000001000000000) DataErrorHist->Fill(nOverflowRegionInTrailer); + if (data & 0b0000010000000000) DataErrorHist->Fill(nOverflowSuperRegionInTrailer); + if (data & 0b0000100000000000) DataErrorHist->Fill(nFrameSizeLimitInTrailer); + */ + } + + else { + headersnow = 0; + +//----------- New region starts - save region number ------------------ + if ((data & 0xFF000000) == 0xFD000000) // if region header + { + prevPix = -1; + if ((((data >> 16) & 0x80) >> 7 )) { //detected overflow bit + DataErrorHist->Fill(nOverflowBitInRegionHeader); // Fill error histogram -> Overflow bit in region header + cout << "Overflow in Buffer!" << endl; + } + int tmp = (data >> 16) & 0x7F; // extract new region number, ignore overflow bit + + if (lastRegion != -1 && lastRegion > tmp) { // if new region < region accounting for new frame (lastRegion==-1 if new frame was detected) // new + DataErrorHist->Fill(nIncorrectFollowingRegionAddress); // new + } // new + if (tmp > 63) { + DataErrorHist->Fill(nTooHighRegionAddress); // new + continue; + } + region = tmp; + lastRegion = region; + RegionHeaders->Fill(region); + +//Hit data - decode pixel address and save + } + + else { + DecodePixel(data >> 16, column, row); + hitcount++; + Columns->Fill(column); + Matrix->Fill(column, row); + MatrixCurrent->Fill(column, row); + RegionCounts->Fill(column/16); + if (prevColumn != -1 && prevColumn / 2 > column / 2 ) {DataErrorHist->Fill(nIncorrectFollowingPE); + cout << "Here1!" << endl; + cout << prevColumn << " " << column << endl; + } + if (prevPix != -1 && (data >> 16 != 0xFCAA)) { + if (prevPix >= (data >> 16)) {DataErrorHist->Fill(nIncorrectFollowingPix);} + prevPix = data >> 16; + } + prevColumn = column; + } + +//Second Hit data - decode pixel address and save + if ((data & 0x0000FF00) != 0x0000FC00) { + DecodePixel(data & 0xFFFF, column, row); + hitcount++; + Columns->Fill(column); + Matrix->Fill(column, row); + MatrixCurrent->Fill(column, row); + RegionCounts->Fill(column/16); + if (prevColumn != -1 && prevColumn / 2 > column / 2) {DataErrorHist->Fill(nIncorrectFollowingPE); + cout << "Here2! " << prevColumn << " " << column/2 << endl; + cout << prevColumn << " " << column << endl; + } + if (prevPix != -1 && ((data & 0xFFFF) != 0xFCAA)) { + if (prevPix >= (data & 0xFFFF)) {DataErrorHist->Fill(nIncorrectFollowingPix);} + prevPix = data & 0xFFFF; + } + prevColumn = column; + } + } // new + + prevData = data; + } + +NumHeaders->Fill(headers); +NumTrailers->Fill(trailers); + +return true; +} + +#endif diff --git a/analysis/datachecks/mimosis.h.save b/analysis/datachecks/mimosis.h.save new file mode 100644 index 0000000..d7e4727 --- /dev/null +++ b/analysis/datachecks/mimosis.h.save @@ -0,0 +1,230 @@ +#ifndef MimosisProcessor_h +#define MimosisProcessor_h + + +#include "hadaq/SubProcessor.h" + + + +namespace hadaq +{ + class TrbProcessor; + + /** This is specialized sub-processor for custom data. + * It should be used together with TrbProcessor, + * which the only can provide data + **/ + class MimosisProcessor : public SubProcessor + { + friend class TrbProcessor; + + protected: + const base::H1handle HandleFrameLength = MakeH1("FrameSize", "32bit words", 3000, 0, 3000, "ch"); + TH1* FrameLength = static_cast(HandleFrameLength); + const base::H1handle HandleNumHeaders = MakeH1("NumHeaders", "", 2000, 0, 2000, "#"); + TH1* NumHeaders = static_cast(HandleNumHeaders); + const base::H1handle HandleNumTrailers = MakeH1("NumTrailers", "Consecutive Frames", 500, 0, 500, "#"); + TH1* NumTrailers = static_cast(HandleNumTrailers); + const base::H1handle HandleRegionHeaders = MakeH1("RegionHeaders", "", 64, 0, 63, "#"); + TH1* RegionHeaders = static_cast(HandleRegionHeaders); + const base::H1handle HandleRegionCounts = MakeH1("RegionCounts", "", 64, 0, 63, "#"); + TH1* RegionCounts = static_cast(HandleRegionCounts); + const base::H1handle HandleColumns = MakeH1("Columns", "Hits per Column", 1024, 0, 1024, "#"); + TH1* Columns = static_cast(HandleColumns); + const base::H1handle HandleErrorFlags = MakeH1("ErrorFlags", "", 9, 0, 9, "Bit"); + TH1* ErrorFlags = static_cast(HandleErrorFlags); + const base::H2handle HandleFrameLengthDist = MakeH2("FrameLengthDist", "", 1024,0,1024,1024,0,1024,"this frame ; last frame"); + TH2* FrameLengthDist = static_cast(HandleFrameLengthDist); + const base::H2handle HandleMatrix = MakeH2("Matrix", "", 1024,0,1024,508,0,508); + TH2* Matrix = static_cast(HandleMatrix); + const base::H2handle HandleMatrixCurrent = MakeH2("MatrixCurrent", "", 1024,0,1024,508,0,508); + TH2* MatrixCurrent = static_cast(HandleMatrixCurrent); + const base::H2handle HandleMatrixLast = MakeH2("MatrixLast", "", 1024,0,1024,508,0,508); + TH2* MatrixLast = static_cast(HandleMatrixLast); + const base::H1handle HandleLast4096 = MakeH1("Last 4096 Content", "", 4095, 0, 4095, "Last 4096 Content"); + TH1* Last4096 = static_cast(HandleLast4096); + + const base::H1handle HandleDataErrorHist = MakeH1("Data Error Histogram", "", nDataErrorChecks, 0, nDataErrorChecks, "Data Error Histogram"); // new + TH1* DataErrorHist = static_cast(HandleDataErrorHist); // new + + unsigned int sensoraddress; + unsigned int sensor; + unsigned int length = 0; + unsigned int region = 0; + unsigned int frameCounter = 0; + unsigned int frameNumber = 0; + unsigned int lastRegion = 0; + TrbProcessor * const trb; + + unsigned int nDataErrorChecks = 6; //new. missing trailer, incorrect frame number in trailer, incorrect checksum, incorrect following frame number in following header, incorrectly following region addresses, region address > 63. + unsigned int nMissingTrailer = 1; // new + unsigned int nFrameOverflowInTrailer = 2; + unsigned int nRegionOverflowInTrailer = 3; + unsigned int nSuperRegionOverflowInTrailer = 4; + un + unsigned int nIncorrectChecksum = 3; // new + unsigned int nIncorrectFollowingFrameNumber = 4; // new + unsigned int nIncorrectFollowingRegionAddress = 5; // new + unsigned int nTooHighRegionAddress = 6; // new + + virtual bool DecodePixel(const unsigned int& word, unsigned int& column, unsigned int& row) const noexcept + { + unsigned int pixelcode = (word >> 6) & 0x3ff; + unsigned int side = 0, topdown = 0; + if((pixelcode&3) == 0x1 || (pixelcode&3) == 0x2) side = 1; + if((pixelcode&3) == 0x3 || (pixelcode&3) == 0x2) topdown = 1; + row = (pixelcode>>2)*2 + topdown; + column = (((word>>3)&0x7) + region*8)*2 + side; + return true; + } + + + public: + MimosisProcessor(TrbProcessor * const trb, const unsigned subid) noexcept + : hadaq::SubProcessor(trb, "%04X", subid) + , trb(trb) + , sensor(subid-0xa000) + , sensoraddress(subid) + {} + + + + virtual ~MimosisProcessor() noexcept override = default; + + + /** Scan all messages, find reference signals if returned false, buffer has error and must be discarded */ + virtual bool FirstBufferScan(const base::Buffer&) noexcept override; + + + /** Scan buffer for selecting messages inside trigger window */ + virtual bool SecondBufferScan(const base::Buffer&) const noexcept { return true; } + }; +} + + + +bool hadaq::MimosisProcessor::FirstBufferScan(const base::Buffer& buf) noexcept +{ + const uint32_t len = buf.datalen()/4; + const uint32_t* arr = static_cast(buf.ptr()); + unsigned int n = 0; + unsigned int column, row, lastcolumn = -1, lastrow = -1; + unsigned int headers = 0, trailers = 0; + unsigned int headersnow = 0; + unsigned int lastlength = -1; + unsigned int hitcount = 0; + uint32_t data; + uint32_t currFrameNumber = 0 // new + unit32_t prevData = 0; + + for (; n < len; n++) { + data = arr[n]; + length++; + +//Begin of frame - store frame header + if ((data & 0xFF000000) == 0xFE000000) { + headers++; + headersnow++; + length = 0; + uint32_t oldFrameNumber = currFrameNumber // new + + if (headersnow == 1) { + frameNumber = (data & 0xFF0000) >> 16; + frameNumber += (data & 0xFF) << 8; + } + + else if (headersnow == 2) { + frameNumber += data & 0xFF0000; + frameNumber += (data & 0xFF) << 24; + } + if (currFrameNumber != 0xFEFFFFFF && (oldFrameNumber >= frameNumber)) {DataErrorHist->Fill(nIncorrectFollowingFrameNumber);} // new + if (prevData =! 0 && ((prevData & 0xFF000000) != 0xFF000000)) {DataErrorHist->Fill(nMissingTrailer);} // new + prevData = data; // new + } + +//End of frame - process frame results and error flags + else if ((data & 0xFF000000) == 0xFF000000) { + length--; + trailers++; + frameCounter++; + MatrixCurrent->Fill(-1, -1); + + Last4096->SetBinContent(frameNumber % 4096, hitcount); + hitcount = 0; + + if (frameCounter == 10000) { + MatrixCurrent->Copy(*MatrixLast); + MatrixLast->SetName("MatrixLast10000"); + MatrixCurrent->Reset(); + RegionCounts->Reset(); + frameCounter = 0; + } + + headersnow = 0; + FrameLength->Fill(length); + + if (lastlength != -1) { + FrameLengthDist->Fill(length, lastlength); + } + + lastlength = length; + if (data & 0x00010000) ErrorFlags->Fill(0); + if (data & 0x00020000) ErrorFlags->Fill(1); + if (data & 0x00040000) ErrorFlags->Fill(2); + if (data & 0x00080000) ErrorFlags->Fill(3); + if (data & 0x00100000) ErrorFlags->Fill(4); + if (data & 0x00200000) ErrorFlags->Fill(5); + if (data & 0x00400000) ErrorFlags->Fill(6); + if (data & 0x00800000) ErrorFlags->Fill(7); + if (!(data & 0x00FF0000)) ErrorFlags->Fill(8); + prevData = data; // new + } + + else { + headersnow = 0; + +//New region starts - save region number + if ((data & 0xFF000000) == 0xFD000000) { + lastRegion = region; + int tmp = (data >> 16) & 0xFF; + if (lastRegion >= tmp) { // new + DataErrorHist->Fill(nIncorrectFollowingRegionAddress); // new + } // new + if (tmp > 63) { + DataErrorHist->Fill(nTooHighRegionAddress); // new + continue; + } + region = tmp; + RegionHeaders->Fill(region); + +//Hit data - decode pixel address and save + } else { + DecodePixel(data >> 16, column, row); + hitcount++; + Columns->Fill(column); + Matrix->Fill(column, row); + MatrixCurrent->Fill(column, row); + RegionCounts->Fill(column/16); + } + +//Second Hit data - decode pixel address and save + if ((data & 0x0000FF00) != 0x0000FC00) { + DecodePixel(data & 0xFFFF, column, row); + hitcount++; + Columns->Fill(column); + Matrix->Fill(column, row); + MatrixCurrent->Fill(column, row); + RegionCounts->Fill(column/16); + } + } + + prevData = data; // new + } + +NumHeaders->Fill(headers); +NumTrailers->Fill(trailers); + +return true; +} + +#endif diff --git a/analysis/datachecks/old_second.C b/analysis/datachecks/old_second.C new file mode 100644 index 0000000..a8f7363 --- /dev/null +++ b/analysis/datachecks/old_second.C @@ -0,0 +1,266 @@ +#include "base/EventProc.h" +#include "hadaq/TdcSubEvent.h" +#include "hadaq/HldProcessor.h" +#include "TString.h" + +//#include "base/Event.h" +//#include "base/TimeStamp.h" +// #include "hadaq/HldProcessor.h" + +#define MAXCH 64 + +class SecondProc : public base::EventProc { +protected: + std::string fTdcId; //!< tdc id where channels will be selected + base::H2handle hDiff; + base::H2handle hPrevDiff; + base::H2handle hRiseRef; + + base::H2handle hFineCh; + base::H2handle hFineRiseCh; + base::H2handle hFineFallCh; + base::H2handle hDiffToScint[17]; + base::H1handle hScintCor; + base::H2handle hSciTot[4]; + + +public: + + SecondProc(const char* procname, const char* _tdcid); + virtual void CreateBranch(TTree* t); + virtual bool Process(base::Event* ev); +}; + + + +SecondProc::SecondProc(const char* procname, const char* _tdcid) : + base::EventProc(procname), + fTdcId(_tdcid) +{ + hDiff = MakeH2("Tdiff","Tdiff", MAXCH, 0, MAXCH, 50000, -100, 300, "ns"); + hPrevDiff = MakeH2("TPrevdiff","TPrevdiff", MAXCH, 0, MAXCH, 50000, -300, 300, "ns"); + hRiseRef = MakeH2("TRiseRef","Tdiffch", MAXCH, 0, MAXCH, 40000, -100, 100, "ns"); + hFineCh = MakeH2("Finech","Fine distribution channels", MAXCH, 0, MAXCH, 600, 0, 600, ""); + hFineRiseCh = MakeH2("FineRisech","Fine rising", MAXCH, 0, MAXCH, 600, 0, 600, ""); + hFineFallCh = MakeH2("FineFallch","Fine falling", MAXCH, 0, MAXCH, 600, 0, 600, ""); +// +// hScintCor = MakeH1("ScintCor","Scint Cor",10000,-100,100,"ns"); +// for(unsigned i = 9; i<=16; i++) { +// hDiffToScint[i] = MakeH2(TString::Format("DiffToScint_%d", i),"to sum26/27", 1000, -50, 0, 150, 0, 50, "ns"); +// } +// for(unsigned i = 0; i<=3; i++) { +// hSciTot[i] = MakeH2(TString::Format("hSciTot_%d", i),"", 1000, -5, 5, 800, 0, 400, "ns"); +// } +} + + + +void SecondProc::CreateBranch(TTree* t) +{ + // only called when tree is created in first.C + // one can ignore + // t->Branch(GetName(), fHits, "hits[8]/D"); +} + +bool SecondProc::Process(base::Event* ev) +{ + hadaq::TdcSubEvent* sub = + dynamic_cast (ev->GetSubEvent(fTdcId)); + if (!sub) { + printf("Fail to find %s\n", fTdcId.c_str()); + return false; + } + + hadaq::HldSubEvent *hld = dynamic_cast (ev->GetSubEvent("HLD")); +// if (hld) +// printf("HLD: type %u seq %u run %u\n", hld->fMsg.trig_type, +// hld->fMsg.seq_nr, hld->fMsg.run_nr); + + unsigned trigtype = hld->fMsg.trig_type; + + double last_stamp[2000][64]; + unsigned id = std::stoi(fTdcId.substr(4).c_str()); +// printf("%u",id); + + +// double ch0tm = 0,ch1tm=0; +// double ch17 = 0, ch24 = 0, ch26 = 0,ch25 = 0; +// double tot17 = 0, tot26=0; +// double lead = 0; + for (unsigned ihit=0;ihitSize();ihit++) { + hadaq::TdcMessageExt &ext = sub->msg(ihit); + + unsigned ch = ext.msg().getHitChannel(); + unsigned edge = ext.msg().getHitEdge(); + double stamp = ext.GetGlobalTime(); // here in seconds + + + if(edge == 1) { + last_stamp[id][ch] = stamp; + } + } + +// if(ch==26 && edge == 1) {ch26 = stamp;} +// if(ch==26 && edge == 0) {tot26 = stamp-ch26;} +// if(ch==25 && edge == 1) {ch25 = stamp;} +// +// if(ch==17 && edge == 1) {ch17 = stamp;} +// if(ch==17 && edge == 0) {tot17 = stamp-ch17;} +// if(ch==24 && edge == 1) {ch24 = stamp;} +// +// +// if(ch==26 && edge == 0 && ch25 != 0 && ch24!=0 && ch17 !=0) { +// FillH2(hSciTot[0], ((ch26-ch25))*1E9,(tot26)*1E9); +// FillH2(hSciTot[1], ((ch26+ch25)/2-(ch24+ch17)/2)*1E9,(tot26)*1E9); +// FillH2(hSciTot[2], ((ch26+ch25)/2-(ch24+ch17)/2)*1E9,(tot17)*1E9); +// } +// +// } +// ch0tm = (ch26+ch25)/2; +// ch1tm = (ch17+ch24)/2; +// if (ch26 != 0 && ch25 != 0 && ch24 != 0 && ch17 != 0) { +// FillH1(hScintCor,(ch0tm-ch1tm)*1E9); +// } + +// if(ch1tm != 0) { +// for (unsigned ihit=0;ihitSize();ihit++) { +// hadaq::TdcMessageExt &ext = sub->msg(ihit); +// unsigned ch = ext.msg().getHitChannel(); +// +// if(ch >= 9 && ch <= 16) { +// unsigned edge = ext.msg().getHitEdge(); +// double stamp = ext.GetGlobalTime(); // here in seconds +// if(edge == 1) { +// lead = stamp; +// } +// if(edge == 0) { +// FillH2(hDiffToScint[ch], (lead-ch1tm)*1E9,(stamp-lead)*1E9); +// } +// } +// } +// } + + + + + + for (unsigned ihit=0;ihitSize();ihit++) { + + hadaq::TdcMessageExt &ext = sub->msg(ihit); + + unsigned ch = ext.msg().getHitChannel(); + unsigned edge = ext.msg().getHitEdge(); + unsigned fine = ext.msg().getHitTmFine(); + unsigned coarse = ext.msg().getHitTmCoarse(); + double stamp = ext.GetGlobalTime(); // here in seconds + +// if(ch > 0 && edge == 1 && id==507) { +// FillH2(hDiff, ch, (last_stamp[300][ch]-stamp)*1E9); +// } + if(ch > 1 && edge == 1) { + FillH2(hPrevDiff, ch, (last_stamp[id][ch-1]-stamp)*1E9); + } + +// if (ch==0) { ch0tm = stamp; } // ch0 has absolute time, all other channels relative to ch0 + + if( (stamp < 50e-9 && stamp > -10e-9) || ch == 0 || trigtype != 0xd) { + + if(edge == 1) { + FillH2(hFineRiseCh, ch, fine); +// printf("%i\n",id*64+ch); + FillH2(hDiff, ch, (last_stamp[0][0]-stamp)*1E9); + last_stamp[id][ch] = stamp; + last_stamp[0][0] = stamp; + + FillH2(hRiseRef, ch, stamp*1E9); + } + + + if(edge == 0) + FillH2(hFineFallCh, ch, fine); + + FillH2(hFineCh, ch, fine); + + } + } + + + + + +// // failure, but just keep it here +// // if (ch>=MAXCH) continue; +// +// // printf("ch %u edge %u stamp %f\n", ch, edge, stamp*1e9); + +// if (edge==0) { +// last_rising[ch] = stamp; +// +// } +// } else if (!last_rising[ch]) { +// // printf(" ToT %f\n", stamp - last_rising[ch]); +// FillH1(hToT, stamp - last_rising[ch]); +// FillH2(hToTCh, ch, stamp - last_rising[ch]); +// last_rising[ch] = 0; +// } + + return true; +} + +// void second() +// { +// +// // for (auto &entry : ev->GetEventsMap()) +// // printf("Name %s Instance %p\n", entry.first.c_str(), entry.second); +// +// // new SecondProc("x0050", "TDC_0050"); +// // new SecondProc("x0507", "TDC_0507"); +// // new SecondProc("x0303", "TDC_0303"); +// new SecondProc("x0201", "TDC_0201"); +// new SecondProc("x0203", "TDC_0203"); +// } + + + +class SecondCreator : public base::EventProc { +public: + + bool fCreated{false}; + + SecondCreator(const char *name) : base::EventProc(name) {} + + virtual bool Process(base::Event* ev) + { + if (fCreated) + return true; + + if (ev->NumSubEvents() == 0) + return false; + + for (auto &entry : ev->GetEventsMap()) { + + if (entry.first.compare(0,3,"TDC") == 0) { + std::string procname = std::string("x") + entry.first.substr(4); + new SecondProc(procname.c_str(), entry.first.c_str()); + printf("CREATE SECOND for %s\n", entry.first.c_str()); + fCreated = true; + } + } + + return true; + } + +}; + + +void second() +{ + new SecondCreator("Creator"); + //new SecondProc("x0050", "TDC_0050"); + //new SecondProc("x0507", "TDC_0507"); + //new SecondProc("x0303", "TDC_0303"); +} + + + + diff --git a/analysis/datachecks/start.sh b/analysis/datachecks/start.sh new file mode 100755 index 0000000..3a5e1b6 --- /dev/null +++ b/analysis/datachecks/start.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +sleep 8 + +if [[ ! -v DAQOPSERVER ]]; then + echo "DAQOPSERVER not set." +elif [[ -z "$DAQOPSERVER" ]]; then + echo "DAQOPSERVER empty." +elif [[ "$DAQOPSERVER" == "jspc29:150" ]]; then + echo "start go4 for Lab317." + source /d/jspc37/soft/trb3/trb3login + go4analysis -http 9999 -stream localhost:36789 -disable-asf +elif [[ "$DAQOPSERVER" == "jspc29:31" ]]; then + echo "start go4 for Probestation." + source /d/jspc37/soft/trb3/trb3login + go4analysis -http 8031 -stream localhost:6788 -disable-asf +else + echo "DAQOPSERVER unknown value." +fi + +bash -i + diff --git a/analysis/datachecks/ucrc_t.cpp b/analysis/datachecks/ucrc_t.cpp new file mode 100644 index 0000000..8be8e64 --- /dev/null +++ b/analysis/datachecks/ucrc_t.cpp @@ -0,0 +1,218 @@ +/* + * uCRC_t - is C++ class for calculation CRC any sizes 1-64 bits + * + * + * version 1.4 + * + * + * BSD 3-Clause License + * + * Copyright (c) 2015, Koynov Stas - skojnov@yandex.ru + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "ucrc_t.h" + + + + + +uCRC_t::uCRC_t(std::string Name, + uint8_t Bits, + uint64_t Poly, + uint64_t Init, + bool RefIn, + bool RefOut, + uint64_t XorOut) noexcept: + name (std::move(Name)), + poly (Poly), + init (Init), + xor_out(XorOut), + bits (Bits), + ref_in (RefIn), + ref_out(RefOut) +{ + init_class(); +} + + + +uCRC_t::uCRC_t(uint8_t Bits, + uint64_t Poly, + uint64_t Init, + bool RefIn, + bool RefOut, + uint64_t XorOut) noexcept: + poly (Poly), + init (Init), + xor_out(XorOut), + bits (Bits), + ref_in (RefIn), + ref_out(RefOut) +{ + init_class(); +} + + + +int uCRC_t::get_crc(uint64_t &crc, const char *file_name, void *buf, size_t size_buf) const noexcept +{ + std::ifstream ifs(file_name, std::ios_base::binary); + + if( !ifs || !buf || !size_buf) + { + errno = EINVAL; + return -1; + } + + return get_crc(crc, ifs, buf, size_buf); +} + + + +int uCRC_t::get_crc(uint64_t &crc, std::ifstream &ifs, void *buf, size_t size_buf) const noexcept +{ + crc = crc_init; + + while( ifs ) + { + ifs.read(static_cast(buf), size_buf); + crc = get_raw_crc(buf, ifs.gcount(), crc); + } + + crc = get_end_crc(crc); + + return (ifs.rdstate() & std::ios_base::badbit); //return 0 if all good +} + + + +uint64_t uCRC_t::get_raw_crc(const void* data, size_t len, uint64_t raw_crc) const noexcept +{ + auto buf = static_cast< const uint8_t* >(data); + + + if(bits > 8) + { + if(ref_in) + while (len--) + raw_crc = (raw_crc >> 8) ^ crc_table[ (raw_crc ^ *buf++) & 0xff ]; + else + while (len--) + raw_crc = (raw_crc << 8) ^ crc_table[ ((raw_crc >> shift) ^ *buf++) & 0xff ]; + } + else + { + if (ref_in) + while (len--) + raw_crc = crc_table[ (raw_crc ^ *buf++) & 0xff ]; + else + while (len--) + raw_crc = crc_table[ ((raw_crc << shift) ^ *buf++) & 0xff ]; + } + + + return raw_crc; +} + + + +uint64_t uCRC_t::reflect(uint64_t data, uint8_t num_bits) noexcept +{ + uint64_t reflection = 0; + + while( num_bits-- ) + { + reflection = (reflection << 1) | (data & 1); + data >>= 1; + } + + return reflection; +} + + + +void uCRC_t::init_crc_table() noexcept +{ + //Calculation of the standard CRC table for byte. + for(int i = 0; i < 256; i++) + { + uint64_t crc = 0; + + for(uint8_t mask = 0x80; mask; mask >>= 1) + { + + if ( i & mask ) + crc ^= top_bit; + + + if (crc & top_bit) + { + crc <<= 1; + crc ^= poly; + } + else + crc <<= 1; + } + + crc &= crc_mask; //for CRC not power 2 + + if(ref_in) + crc_table[reflect(i, 8)] = reflect(crc, bits); + else + crc_table[i] = crc; + } +} + + + +void uCRC_t::init_class() noexcept +{ + top_bit = (uint64_t)1 << (bits - 1); + crc_mask = ( (top_bit - 1) << 1) | 1; + + + if(bits > 8) + shift = (bits - 8); + else + shift = (8 - bits); + + + if(ref_in) + crc_init = reflect(init, bits); + else + crc_init = init; + + + init_crc_table(); +} diff --git a/analysis/datachecks/ucrc_t.h b/analysis/datachecks/ucrc_t.h new file mode 100644 index 0000000..124ac48 --- /dev/null +++ b/analysis/datachecks/ucrc_t.h @@ -0,0 +1,201 @@ +/* + * uCRC_t - is C++ class for calculation CRC any sizes 1-64 bits + * + * + * version 1.4 + * + * + * BSD 3-Clause License + * + * Copyright (c) 2015, Koynov Stas - skojnov@yandex.ru + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * more details see https://github.com/KoynovStas/uCRC_t + * + */ + +#ifndef UCRC_T_H +#define UCRC_T_H + +#include +#include +#include // for std::ifstream +#include // for std::ios_base, etc. + + + + + +class uCRC_t +{ + public: + explicit uCRC_t(std::string Name = "CRC-32", + uint8_t Bits = 32, + uint64_t Poly = 0x04c11db7, + uint64_t Init = 0xffffffff, + bool RefIn = true, + bool RefOut = true, + uint64_t XorOut = 0xffffffff) noexcept; + + + explicit uCRC_t(uint8_t Bits, + uint64_t Poly, + uint64_t Init, + bool RefIn, + bool RefOut, + uint64_t XorOut) noexcept; + + + std::string name; + + + // get param CRC + uint8_t get_bits() const noexcept { return bits; } + uint64_t get_poly() const noexcept { return poly; } + uint64_t get_init() const noexcept { return init; } + uint64_t get_xor_out() const noexcept { return xor_out;} + bool get_ref_in() const noexcept { return ref_in; } + bool get_ref_out() const noexcept { return ref_out;} + + uint64_t get_top_bit() const noexcept { return top_bit; } + uint64_t get_crc_mask()const noexcept { return crc_mask;} + uint64_t get_crc_init()const noexcept { return crc_init;} //crc_init = reflect(init, bits) if RefIn, else = init + uint64_t get_check() const noexcept; //crc for ASCII string "123456789" (i.e. 313233... (hexadecimal)). + + + // set param CRC + int set_bits(uint8_t new_value) noexcept; + void set_poly(uint64_t new_value) noexcept { poly = new_value; init_class();} + void set_init(uint64_t new_value) noexcept { init = new_value; init_class();} + void set_xor_out(uint64_t new_value) noexcept { xor_out = new_value;} + void set_ref_in(bool new_value) noexcept { ref_in = new_value; init_class();} + void set_ref_out(bool new_value) noexcept { ref_out = new_value;} + + + // Calculate methods + uint64_t get_crc(const void* data, size_t len) const noexcept; + int get_crc(uint64_t &crc, const char* file_name) const noexcept; + int get_crc(uint64_t &crc, const char* file_name, void* buf, size_t size_buf) const noexcept; + + + // Calculate for chunks of data + uint64_t get_raw_crc(const void* data, size_t len) const noexcept; //get raw_crc for first chunk of data + uint64_t get_raw_crc(const void* data, size_t len, uint64_t raw_crc) const noexcept; //get raw_crc for chunk of data + uint64_t get_end_crc(uint64_t raw_crc) const noexcept; + + + private: + uint64_t poly; + uint64_t init; + uint64_t xor_out; + uint64_t crc_init; //crc_init = reflect(init, bits) if RefIn, else = init + uint64_t top_bit; + uint64_t crc_mask; + uint64_t crc_table[256]; + + uint8_t bits; + uint8_t shift; + bool ref_in; + bool ref_out; + + + static uint64_t reflect(uint64_t data, uint8_t num_bits) noexcept; + void init_crc_table() noexcept; + void init_class() noexcept; + + int get_crc(uint64_t &crc, std::ifstream& ifs, void* buf, size_t size_buf) const noexcept; +}; + + + + + +inline uint64_t uCRC_t::get_check() const noexcept +{ + const uint8_t data[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; + + return get_crc(data, sizeof(data)); +} + + + +inline int uCRC_t::set_bits(uint8_t new_value) noexcept +{ + if( (new_value < 1) || (new_value > 64) ) + return -1; //error + + bits = new_value; + init_class(); + + return 0; //good job +} + + + +inline uint64_t uCRC_t::get_crc(const void* data, size_t len) const noexcept +{ + uint64_t crc = get_raw_crc(data, len, crc_init); + + return get_end_crc(crc); +} + + + +inline int uCRC_t::get_crc(uint64_t& crc, const char* file_name) const noexcept +{ + char buf[4096]; + + return get_crc(crc, file_name, buf, sizeof(buf)); +} + + + +inline uint64_t uCRC_t::get_raw_crc(const void* data, size_t len) const noexcept +{ + return get_raw_crc(data, len, crc_init); +} + + + +inline uint64_t uCRC_t::get_end_crc(uint64_t raw_crc) const noexcept +{ + if(ref_out^ref_in) raw_crc = reflect(raw_crc, bits); + + raw_crc ^= xor_out; + raw_crc &= crc_mask; //for CRC not power 2 + + return raw_crc; +} + + + + + +#endif // UCRC_T_H -- 2.43.0