commit a35bd6e5771412ac51b450e191615c191abc6db6 Author: carina@hades Date: Tue Apr 11 11:13:23 2023 -0400 setup the base for Qt6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1fab57e --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +*.o + +FSUDAQ_Qt6 + +*~ +*.autosave +moc_* +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..4fd5c50 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Hades", + "includePath": [ + "${workspaceFolder}/**", + "/usr/include/x86_64-linux-gnu/qt6/**", + "/usr/local/cern/root_v6.26.06/include/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..71dc804 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,87 @@ +{ + "better-comments.tags": [ + { + "tag": "!", + "color": "#FF2D00", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "?", + "color": "#0076FF", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "@", + "color": "#00F8FF", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "/", + "color": "#00A0FF", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "//", + "color": "#474747", + "strikethrough": true, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "^", + "color": "#EAF622", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "*", + "color": "#28FF00", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "&", + "color": "#FF06A0", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "~", + "color": "#BE00FF", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + }, + { + "tag": "todo", + "color": "#FF8C00", + "strikethrough": false, + "backgroundColor": "transparent", + "bold": false, + "italic": false + } + ], + "files.associations": { + "mainWindow.C": "cpp" + } +} \ No newline at end of file diff --git a/ClassData.h b/ClassData.h new file mode 100644 index 0000000..57bf037 --- /dev/null +++ b/ClassData.h @@ -0,0 +1,698 @@ +#ifndef DATA_H +#define DATA_H + +#include +#include +#include +#include +#include ///memset +#include ///cout +#include +#include + +#include "CAENDigitizerType.h" +#include "macro.h" + +#define MaxNData 10000 /// 10k events per channels + +class Data{ + + public: + + int DPPType; /// this is set from the boardID from the Board Agg. header when it is > 0 + unsigned short boardSN; + float ch2ns; + + unsigned int nByte; /// number of byte from read buffer + char *buffer; /// readout buffer + uint32_t AllocatedSize; + + double TriggerRate[MaxNChannels]; /// Hz + unsigned long TotNumEvents[MaxNChannels]; + unsigned short NumEventsDecoded[MaxNChannels]; + + /// stored Raw event + bool IsNotRollOverFakeAgg; + unsigned short NumEvents[MaxNChannels]; + unsigned long long Timestamp[MaxNChannels][MaxNData]; /// 47 bit + unsigned short fineTime[MaxNChannels][MaxNData]; /// 10 bits, in unit of ch2ns / 1000 = ps + unsigned short Energy[MaxNChannels][MaxNData]; /// 15 bit + unsigned short Energy2[MaxNChannels][MaxNData]; /// 15 bit, in PSD, Energy = Qshort, Energy2 = Qlong + + std::vector Waveform1[MaxNChannels][MaxNData]; + std::vector Waveform2[MaxNChannels][MaxNData]; + std::vector DigiWaveform1[MaxNChannels][MaxNData]; + std::vector DigiWaveform2[MaxNChannels][MaxNData]; + + public: + Data(); + ~Data(); + + void Allocate80MBMemory(); + void AllocateMemory(uint32_t size); + + void SetSaveWaveToMemory(bool OnOff) { this->SaveWaveToMemory = OnOff; } + + void ClearData(); + void ClearTriggerRate(); + void ClearBuffer(); + + void CopyBuffer( const char * buffer, const unsigned int size); + + void SaveBuffer(const char * fileName); + unsigned int GetPresentFileSize() {return presentFileSizeByte;} + + void PrintBuffer() const; //Incorrect + void DecodeBuffer(bool fastDecode, int verbose = 0); /// fastDecode will not save waveform + void DecodeBuffer(char * buffer, unsigned int size, bool fastDecode, int verbose = 0); // for outside data + + void PrintStat() const; + + void PrintData() const; + + protected: + + unsigned int nw; + bool SaveWaveToMemory; + + ///for temperary + std::vector tempWaveform1; + std::vector tempWaveform2; + std::vector tempDigiWaveform1; + std::vector tempDigiWaveform2; + + unsigned int ReadBuffer(unsigned int nWord, int verbose = 0); + + int DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose); + int DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose); + + unsigned int presentFileSizeByte; + unsigned short saveFileIndex; + +}; + +//========================================== + +inline Data::Data(){ + ch2ns = 2.0; + boardSN = 0; + DPPType = V1730_DPP_PHA_CODE; + IsNotRollOverFakeAgg = false; + buffer = NULL; + for ( int i = 0; i < MaxNChannels; i++) TotNumEvents[i] = 0; + ClearData(); + ClearTriggerRate(); + SaveWaveToMemory = true; + nw = 0; + saveFileIndex = 0; +} + +inline Data::~Data(){ + if( buffer != NULL ) delete buffer; +} + +inline void Data::AllocateMemory(uint32_t size){ + ClearBuffer(); + AllocatedSize = size; + buffer = (char *) malloc( AllocatedSize); + printf("Allocated %u byte for buffer = %u words\n", AllocatedSize, AllocatedSize / 4); +} + +inline void Data::Allocate80MBMemory(){ + AllocateMemory( 80 * 1024 * 1024 ); /// 80 M Byte +} + +inline void Data::ClearTriggerRate(){ + for( int i = 0 ; i < MaxNChannels; i++) { + TriggerRate[i] = 0.0; + NumEventsDecoded[i] = 0; + } +} + +inline void Data::ClearData(){ + nByte = 0; + AllocatedSize = 0; + IsNotRollOverFakeAgg = false; + for( int i = 0 ; i < MaxNChannels; i++){ + NumEvents[i] = 0; + for( int j = 0; j < MaxNData; j++){ + Timestamp[i][j] = 0; + fineTime[i][j] = 0; + Energy[i][j] = 0; + Energy2[i][j] = 0; + Waveform1[i][j].clear(); + Waveform2[i][j].clear(); + DigiWaveform1[i][j].clear(); + DigiWaveform2[i][j].clear(); + } + } + + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + tempDigiWaveform2.clear(); +} + +inline void Data::ClearBuffer(){ + delete buffer; + AllocatedSize = 0; + nByte = 0; +} + +inline void Data::CopyBuffer(const char * buffer, const unsigned int size){ + std::memcpy(this->buffer, buffer, size); +} + +inline void Data::SaveBuffer(const char * fileName){ + + char saveFileName[100]; + sprintf(saveFileName, "%s_%03d_%03d_%03u.fsu", fileName , boardSN, DPPType, saveFileIndex); + + FILE * haha = fopen(saveFileName, "a+"); + fseek(haha, 0L, SEEK_END); + unsigned int inFileSize = ftell(haha); /// unsigned int = Max ~ 4 GB + ///printf("file Size = %u Byte\n", inFileSize); + + if( inFileSize > (unsigned int)MaxSaveFileSize ) { /// 2 GB + fclose(haha); + saveFileIndex ++; + sprintf(saveFileName, "%s_%03u.fsu", fileName , saveFileIndex); + FILE * haha = fopen(saveFileName, "a+"); + } + + fwrite(buffer, nByte, 1, haha); + + presentFileSizeByte = ftell(haha); + ///printf("=========== file Size : %u Byte = %.2f MB\n", presentFileSizeByte, presentFileSizeByte/1024./1024.); + + fclose(haha); +} + +inline void Data::PrintStat() const{ + + if( !IsNotRollOverFakeAgg ) { + printf(" this is roll-over fake event or no events.\n"); + return; + } + printf("%2s | %6s | %9s | %6s\n", "ch", "# Evt.", "Rate [Hz]", "Tot. Evt."); + printf("---+--------+-----------+----------\n"); + for(int ch = 0; ch < MaxNChannels; ch++){ + printf("%2d | %6d | %9.2f | %6lu\n", ch, NumEventsDecoded[ch], TriggerRate[ch], TotNumEvents[ch]); + } + printf("---+--------+-----------+----------\n"); +} + +inline void Data::PrintBuffer() const{ + unsigned int length = sizeof(buffer); + for( int i = 0; i < length; i++){ + printf("%3d | 0x%08x \n", i, buffer[i]); + } +} + +inline void Data::PrintData() const{ + printf("============================= Print Data\n"); + for( int ch = 0; ch < MaxNChannels ; ch++){ + if( NumEvents[ch] == 0 ) continue; + printf("------------ ch : %d, %d \n", ch, NumEvents[ch]); + for( int ev = 0; ev < NumEvents[ch] ; ev++){ + printf("%4d, %5u, %15llu, %5u \n", ev, Energy[ch][ev], Timestamp[ch][ev], fineTime[ch][ev]); + } + } +} + +//####################################################### Decode +inline unsigned int Data::ReadBuffer(unsigned int nWord, int verbose){ + if( buffer == NULL ) return 0; + + unsigned int word = 0; + for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i); + if( verbose >= 2) printf("%6d | 0x%08X | ", nWord, word); + return word; +} + +inline void Data::DecodeBuffer(char * buffer, unsigned int size, bool fastDecode, int verbose){ + this->buffer = buffer; + this->nByte = size; + DecodeBuffer(fastDecode, verbose); +} + +inline void Data::DecodeBuffer(bool fastDecode, int verbose){ + /// verbose : 0 = off, 1 = only energy + timestamp, 2 = show header, 3 = wave + + if( buffer == NULL ) { + if( verbose >= 1 ) printf(" buffer is empty \n"); + return; + } + + if( nByte == 0 ) { + return; + } + + nw = 0; + + ClearTriggerRate(); + + do{ + if( verbose >= 1 ) printf("Data::DecodeBuffer ######################################### Board Agg.\n"); + unsigned int word = ReadBuffer(nw, verbose); + if( ( (word >> 28) & 0xF ) == 0xA ) { /// start of Board Agg + unsigned int nWord = word & 0x0FFFFFFF ; + if( verbose >= 1 ) printf("Number of words in this Agg : %u = %u Byte\n", nWord, nWord * 4); + + nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned int BoardID = ((word >> 27) & 0x1F); + unsigned short pattern = ((word >> 8 ) & 0x7FFF ); + bool BoardFailFlag = ((word >> 26) & 0x1 ); + unsigned int ChannelMask = ( word & 0xFF ) ; + if( verbose >= 1 ) printf("Board ID(type) : %d, FailFlag = %d, Patten = %u, ChannelMask = 0x%X\n", + BoardID, BoardFailFlag, pattern, ChannelMask); + + if( BoardID > 0 ) { + switch(BoardID){ + case 0x8 : DPPType = V1730_DPP_PSD_CODE; break; + case 0xB : DPPType = V1730_DPP_PHA_CODE; break; + } + } + + nw = nw + 1; + unsigned int bdAggCounter = ReadBuffer(nw, verbose); + if( verbose >= 1 ) printf("Board Agg Counter : %u \n", bdAggCounter & 0x7FFFFF); + + nw = nw + 1; + unsigned int bdAggTimeTag = ReadBuffer(nw, verbose); + if( verbose >= 2 ) printf("Agg Counter : %u \n", bdAggTimeTag); + + for( int chMask = 0; chMask < MaxNChannels/2 ; chMask ++ ){ + if( ((ChannelMask >> chMask) & 0x1 ) == 0 ) continue; + if( verbose >= 2 ) printf("==================== Dual Channel Block, ch Mask : %d, nw : %d\n", chMask *2, nw); + + if( DPPType == V1730_DPP_PHA_CODE ) { + if ( DecodePHADualChannelBlock(chMask, fastDecode, verbose) < 0 ) break; + } + if( DPPType == V1730_DPP_PSD_CODE ) { + if ( DecodePHADualChannelBlock(chMask, fastDecode, verbose) < 0 ) break; + } + } + }else{ + if( verbose >= 1 ) printf("nw : %d, incorrect buffer header. \n", nw); + break; + } + nw++; + ///printf("nw : %d ,x 4 = %d, nByte : %d \n", nw, 4*nw, nByte); + }while(4*nw < nByte); + + ///Calculate trigger rate and first and last Timestamp + for(int ch = 0; ch < MaxNChannels; ch++){ + if( NumEventsDecoded[ch] > 0 ) IsNotRollOverFakeAgg = true; + unsigned long long dTime = Timestamp[ch][NumEvents[ch]-1] - Timestamp[ch][NumEvents[ch] - NumEventsDecoded[ch]]; + double sec = dTime * ch2ns / 1e9; + if( sec != 0 && NumEventsDecoded[ch] > 1 ){ + TriggerRate[ch] = NumEventsDecoded[ch]/sec; + } + } + +} + +inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + + nw = nw + 1; + unsigned int word = ReadBuffer(nw, verbose); + + bool hasFormatInfo = ((word >> 31) & 0x1); + unsigned int aggSize = ( word & 0x7FFFFFFF ) ; + if( verbose >= 2 ) printf("Dual Channel size : %d \n", aggSize); + unsigned int nSample = 0; /// wave form; + unsigned int nEvents = 0; + unsigned int extra2Option = 0; + bool hasExtra2 = false; + bool hasDualTrace = 0 ; + if( hasFormatInfo ){ + nw = nw + 1; word = ReadBuffer(nw, verbose); + + nSample = ( word & 0xFFFF ) * 8; + extra2Option = ( (word >> 24 ) & 0x7 ); + hasExtra2 = ( (word >> 28 ) & 0x1 ); + if( !fastDecode || verbose >= 2){ + unsigned int digitalProbe = ( (word >> 16 ) & 0xF ); + unsigned int analogProbe2 = ( (word >> 20 ) & 0x3 ); + unsigned int analogProbe1 = ( (word >> 22 ) & 0x3 ); + bool hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasEnergy = ( (word >> 30 ) & 0x1 ); + hasDualTrace = ( (word >> 31 ) & 0x1 ); + + if( verbose >= 2 ) { + printf("DualTrace : %d, Energy : %d, Time: %d, Wave : %d, Extra2: %d \n", + hasDualTrace, hasEnergy, hasTimeStamp, hasWaveForm, hasExtra2); + } + if( verbose >= 3){ + if( hasExtra2 ){ + printf("...... extra 2 : "); + switch (extra2Option){ + case 0: printf("[0:15] trapwzoid baseline * 4 [16:31] Extended timestamp (16-bit)\n"); break; + case 1: printf("Reserved\n"); break; + case 2: printf("[0:9] Fine time stamp [10:15] Reserved [16:31] Extended timestamp (16-bit)\n"); break; + case 3: printf("Reserved\n"); break; + case 4: printf("[0:15] Total trigger counter [16:31] Lost trigger counter\n"); break; + case 5: printf("[0:15] Event after Zero crossing [16:31] Event before Zero crossing\n"); break; + case 6: printf("Reserved\n"); break; + case 7: printf("Reserved\n"); break; + } + } + printf("...... Analog Probe 1 : "); + switch (analogProbe1 ){ + case 0 : printf("Input \n"); break; + case 1 : printf("RC-CR (1st derivative) \n"); break; + case 2 : printf("RC-CR2 (2st derivative) \n"); break; + case 3 : printf("trapazoid \n"); break; + } + printf("...... Analog Probe 2 : "); + switch (analogProbe2 ){ + case 0 : printf("Input \n"); break; + case 1 : printf("Theshold \n"); break; + case 2 : printf("trapezoid - baseline \n"); break; + case 3 : printf("baseline \n"); break; + } + printf("...... Digital Probe : "); + switch (digitalProbe ){ + case 0 : printf("Peaking \n"); break; + case 1 : printf("Armed (trigger) \n"); break; + case 2 : printf("Peak Run \n"); break; + case 3 : printf("Pile up \n"); break; + case 4 : printf("Peaking \n"); break; + case 5 : printf("Trigger Validation Window \n"); break; + case 6 : printf("Baseline for energy calculation \n"); break; + case 7 : printf("Trigger holdoff \n"); break; + case 8 : printf("Trigger Validation \n"); break; + case 9 : printf("ACQ Busy \n"); break; + case 10 : printf("Trigger window \n"); break; + case 11 : printf("Ext. Trigger \n"); break; + case 12 : printf("Busy = memory is full \n"); break; + } + } + } + nEvents = (aggSize - 2) / (nSample/2 + 2 + hasExtra2 ); + if( verbose >= 2 ) printf("-------------------nEvents : %d \n", nEvents); + }else{ + if( verbose >= 2 ) printf("does not has format info. unable to read buffer.\n"); + return 0; + } + + ///========== decode an event + for( int ev = 0; ev < nEvents ; ev++){ + if( verbose >= 2 ) printf("------ event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + bool channelTag = ((word >> 31) & 0x1); + unsigned int timeStamp0 = (word & 0x7FFFFFFF); + int channel = ChannelMask*2 + channelTag; + if( verbose >= 2 ) printf("ch : %d, timeStamp0 %u \n", channel, timeStamp0); + + //TODO Skip + ///===== read waveform + if( !fastDecode && SaveWaveToMemory ) { + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + } + + unsigned int triggerAtSample = 0 ; + if( fastDecode ){ + nw += nSample/2; + }else{ + for( int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, verbose-2); + ///The CAEN manual is wrong, the bit [31:16] is anaprobe 1 + bool isTrigger1 = (( word >> 31 ) & 0x1 ); + bool dp1 = (( word >> 30 ) & 0x1 ); + unsigned short wave1 = (( word >> 16) & 0x3FFF); + ///The CAEN manual is wrong, the bit [31:16] is anaprobe 2 + bool isTrigger0 = (( word >> 15 ) & 0x1 ); + bool dp0 = (( word >> 14 ) & 0x1 ); + unsigned short wave0 = ( word & 0x3FFF); + + if( SaveWaveToMemory){ + if( hasDualTrace ){ + tempWaveform1.push_back(wave1); + tempWaveform2.push_back(wave0); + tempDigiWaveform1.push_back(dp0); + }else{ + tempWaveform1.push_back(wave1); + tempWaveform1.push_back(wave0); + tempDigiWaveform1.push_back(dp0); + tempDigiWaveform1.push_back(dp1); + } + } + + if( isTrigger0 == 1 ) triggerAtSample = 2*wi ; + if( isTrigger1 == 1 ) triggerAtSample = 2*wi + 1; + + if( verbose >= 4 && ev == 0 ){ + if( !hasDualTrace ){ + printf("%4d| %5d, %d, %d \n", 2*wi, wave0, dp0, isTrigger0); + printf("%4d| %5d, %d, %d \n", 2*wi+1, wave1, dp1, isTrigger1); + }else{ + printf("%4d| %5d, %5d | %d, %d | %d %d\n", wi, wave0, wave1, dp0, dp1, isTrigger0, isTrigger1); + } + } + } + + if( SaveWaveToMemory ) { + if( hasDualTrace ){ + Waveform1[channel][NumEvents[channel]] = tempWaveform1; + Waveform2[channel][NumEvents[channel]] = tempWaveform2; + }else{ + Waveform1[channel][NumEvents[channel]] = tempWaveform1; + } + DigiWaveform1[channel][NumEvents[channel]] = tempDigiWaveform1; + } + } + unsigned long long extTimeStamp = 0; + unsigned int extra2 = 0; + if( hasExtra2 ){ + nw = nw +1 ; word = ReadBuffer(nw, verbose); + extra2 = word; + if( extra2Option == 0 || extra2Option == 2 ) extTimeStamp = (extra2 >> 16); + } + + unsigned long long timeStamp = (extTimeStamp << 31) ; + timeStamp = timeStamp + timeStamp0; + + if( verbose >= 2 && hasExtra2 ) printf("extra2 : 0x%0X, TimeStamp : %llu\n", extra2, timeStamp); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int extra = (( word >> 16) & 0x3FF); + unsigned int energy = (word & 0x7FFF); + bool rollOver = (extra & 0x002); + bool pileUp = (extra & 0x200); + bool pileUpOrRollOver = ((word >> 15) & 0x1); + + if( verbose >= 3 ) { + printf("PileUp : %d , extra : 0x%03x, energy : %d \n", pileUp, extra, energy); + printf(" lost event : %d \n", ((extra >> 0) & 0x1) ); + printf(" roll-over : %d (fake event)\n", ((extra >> 1) & 0x1) ); + printf(" fake-event : %d \n", ((extra >> 3) & 0x1) ); + printf(" input sat. : %d \n", ((extra >> 4) & 0x1) ); + printf(" lost trg : %d \n", ((extra >> 5) & 0x1) ); + printf(" tot trg : %d \n", ((extra >> 6) & 0x1) ); + printf(" coincident : %d \n", ((extra >> 7) & 0x1) ); + printf(" not coin. : %d \n", ((extra >> 8) & 0x1) ); + printf(" pile-up : %d \n", ((extra >> 9) & 0x1) ); + printf(" trapezoid sat. : %d \n", ((extra >> 10) & 0x1) ); + } + + if( rollOver == 0 ) { + Energy[channel][NumEvents[channel]] = energy; + Timestamp[channel][NumEvents[channel]] = timeStamp; + if(extra2Option == 0 || extra2Option == 2 ) fineTime[channel][NumEvents[channel]] = (extra2 & 0x07FF ); + NumEvents[channel] ++; + NumEventsDecoded[channel] ++; + TotNumEvents[channel] ++; + } + + if( verbose >= 1 ) printf("%4d | ch : %2d, PileUp : %d , energy : %5d, rollOver: %d, timestamp : %10llu, triggerAt : %d, nSample : %d, %f sec\n", + NumEvents[channel], channel, pileUp, energy, rollOver, timeStamp, triggerAtSample, nSample , timeStamp * 4. / 1e9); + + } + + ///=========== Key information + /// ch, energy, timestamp + /// trace + + return nw; +} + +inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDecode, int verbose){ + + nw = nw + 1; + unsigned int word = ReadBuffer(nw, verbose); + + if( (word >> 31) != 1 ) return 0; + + unsigned int aggSize = ( word & 0x3FFFFF ) ; + if( verbose >= 2 ) printf(" size : %d \n", aggSize); + + unsigned int nEvents = 0; + nw = nw + 1; word = ReadBuffer(nw, verbose); + unsigned int nSample = ( word & 0xFFFF ) * 8; + unsigned int digitalProbe1 = ( (word >> 16 ) & 0x7 ); + unsigned int digitalProbe2 = ( (word >> 19 ) & 0x7 ); + unsigned int analogProbe = ( (word >> 22 ) & 0x3 ); + unsigned int extraOption = ( (word >> 24 ) & 0x7 ); + bool hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasExtra = ( (word >> 28 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasCharge = ( (word >> 30 ) & 0x1 ); + bool hasDualTrace = ( (word >> 31 ) & 0x1 ); + + if( verbose >= 2 ) { + printf("dualTrace : %d, Charge : %d, Time: %d, Wave : %d, Extra: %d\n", + hasDualTrace, hasCharge, hasTimeStamp, hasWaveForm, hasExtra); + if( hasExtra ){ + printf(".... extra : "); + switch(extraOption){ + case 0: printf("[0:15] trapwzoid baseline * 4 [16:31] Extended timestamp (16-bit)\n"); break; + case 1: printf("[0:11] reserved [12] lost trigger counted [13] 1024 trigger counted [14] Over-range\n"); + printf("[15] trigger lost [16:31] Extended timestamp (16-bit)\n"); break; + case 2: printf("[0:9] Fine time stamp [10:15] flag [10:15] Reserved [16:31] Extended timestamp (16-bit)\n"); break; + case 3: printf("Reserved\n"); break; + case 4: printf("[0:15] Total trigger counter [16:31] Lost trigger counter\n"); break; + case 5: printf("[0:15] Event after Zero crossing [16:31] Event before Zero crossing\n"); break; + case 6: printf("Reserved\n"); break; + case 7: printf("debug, must be 0x12345678\n"); break; + } + } + printf(".... digital Probe 1 : "); + switch(digitalProbe1){ + case 0 : printf("Long gate \n"); break; + case 1 : printf("Over threshold \n"); break; + case 2 : printf("Shaped TRG \n"); break; + case 3 : printf("TRG Val. Acceptance \n"); break; + case 4 : printf("Pile-Up \n"); break; + case 5 : printf("Coincidence \n"); break; + case 6 : printf("Reserved \n"); break; + case 7 : printf("Trigger \n"); break; + } + printf(".... digital Probe 2 : "); + switch(digitalProbe2){ + case 0 : printf("Short gate \n"); break; + case 1 : printf("Over threshold \n"); break; + case 2 : printf("TRG Validation \n"); break; + case 3 : printf("TRG HoldOff \n"); break; + case 4 : printf("Pile-Up \n"); break; + case 5 : printf("Coincidence \n"); break; + case 6 : printf("Reserved \n"); break; + case 7 : printf("Trigger \n"); break; + } + printf(".... analog Probe (dual trace : %d): ", hasDualTrace); + if( hasDualTrace ) { + switch(analogProbe){ + case 0 : printf("Input and baseline \n"); break; + case 1 : printf("CFD and baseline \n"); break; + case 2 : printf("Input and CFD \n"); break; + } + }else{ + switch(analogProbe){ + case 0 : printf("Input \n"); break; + case 1 : printf("CFD \n"); break; + } + } + } + + nEvents = (aggSize -2) / (nSample/2 + 2 + hasExtra ); + if( verbose >= 2 ) printf("----------------- nEvents : %d \n", nEvents); + + ///========= Decode an event + for( int ev = 0; ev < nEvents ; ev++){ + if( verbose >= 2 ) printf("--------------------------- event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, verbose); + bool channelTag = ((word >> 31) & 0x1); + unsigned int timeStamp0 = (word & 0x7FFFFFFF); + int channel = ChannelMask*2 + channelTag; + if( verbose >= 2 ) printf("ch : %d, timeStamp %u \n", channel, timeStamp0); + + ///===== read waveform + if( !fastDecode && SaveWaveToMemory ) { + tempWaveform1.clear(); + tempWaveform2.clear(); + tempDigiWaveform1.clear(); + tempDigiWaveform2.clear(); + } + + if( fastDecode ){ + nw += nSample/2; + }else{ + for( int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, verbose - 2); + bool dp2b = (( word >> 31 ) & 0x1 ); + bool dp1b = (( word >> 30 ) & 0x1 ); + unsigned short waveb = (( word >> 16) & 0x3FFF); + + bool dp2a = (( word >> 15 ) & 0x1 ); + bool dp1a = (( word >> 14 ) & 0x1 ); + unsigned short wavea = ( word & 0x3FFF); + + if( SaveWaveToMemory){ + if( hasDualTrace ){ + tempWaveform1.push_back(wavea); + tempWaveform2.push_back(waveb); + }else{ + tempWaveform1.push_back(wavea); + tempWaveform1.push_back(waveb); + } + tempDigiWaveform1.push_back(dp1a); + tempDigiWaveform1.push_back(dp1b); + tempDigiWaveform2.push_back(dp2a); + tempDigiWaveform2.push_back(dp2b); + } + + if( verbose >= 3 && ev == 0 ){ + printf("%4d| %5d, %d, %d \n", 2*wi, wavea, dp1a, dp2a); + printf("%4d| %5d, %d, %d \n", 2*wi+1, waveb, dp1b, dp2b); + } + } + if( SaveWaveToMemory ) { + if( hasDualTrace ){ + Waveform1[channel][NumEvents[channel]] = tempWaveform1; + Waveform2[channel][NumEvents[channel]] = tempWaveform2; + }else{ + Waveform1[channel][NumEvents[channel]] = tempWaveform1; + } + DigiWaveform1[channel][NumEvents[channel]] = tempDigiWaveform1; + DigiWaveform2[channel][NumEvents[channel]] = tempDigiWaveform2; + } + } + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int extra = word; + unsigned long long extTimeStamp = 0; + if( extraOption == 0 || extraOption == 2 ) extTimeStamp = (extra >> 16); + + unsigned long long timeStamp = (extTimeStamp << 31) ; + timeStamp = timeStamp + timeStamp0; + + nw = nw +1 ; word = ReadBuffer(nw, verbose); + unsigned int Qlong = (( word >> 16) & 0xFFFF); + unsigned int Qshort = (word & 0x7FFF); + bool isEnergyCorrect = ((word >> 15) & 0x1); + + if( isEnergyCorrect == 1 ) { + NumEvents[channel] ++; + NumEventsDecoded[channel] ++; + TotNumEvents[channel] ++; + } + + if( verbose >= 2 ) printf("extra : 0x%08x, Qshort : %d, Qlong : %d \n", extra, Qshort, Qlong); + + if( verbose >= 1 ) printf("ch : %2d, Qshort : %d, Qlong : %d, timestamp : %llu\n", + channel, Qshort, Qlong, timeStamp); + + Timestamp[channel][NumEvents[channel]] = timeStamp; + + } + + ///=========== Key information + /// ch, Qshort, Qlong , timestamp + /// trace + + return nw; +} + +#endif diff --git a/ClassDigitizer.cpp b/ClassDigitizer.cpp new file mode 100644 index 0000000..040ea97 --- /dev/null +++ b/ClassDigitizer.cpp @@ -0,0 +1,943 @@ +#include "ClassDigitizer.h" + +Digitizer::Digitizer(){ + Initalization(); +} + +Digitizer::Digitizer(int boardID, int portID, bool program, bool verbose){ + Initalization(); + OpenDigitizer(boardID, portID, program, verbose); +} + +Digitizer::~Digitizer(){ + CloseDigitizer(); + delete data; +} + +void Digitizer::Initalization(){ + + data = new Data(); + + portID = -1; + boardID = -1; + handle = -1; + NChannel = 16; + ADCbits = 1; + DPPType = 0; + ADCFullSize = 0; + ch2ns = 0; + BoardInfo = {}; + + channelMask = 0xFFFF; + VMEBaseAddress = 0; + LinkType = CAEN_DGTZ_USB; /// default USB + IOlev = CAEN_DGTZ_IOLevel_NIM; ///default NIM + + isSettingFilledinMemeory = false; + settingFileName = ""; + settingFileExist = false; + settingFile = NULL; + + ret = -1; + isConnected = false; + AcqRun = false; + isDummy = true; +} + +void Digitizer::Reset(){ + ret = CAEN_DGTZ_Reset(handle); + if( ret != 0 ) ErrorMsg(__func__); + + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::SoftwareClear_W, 1); + if( ret != 0 ) ErrorMsg("Reset-SoftwareClear_W"); + +} + +void Digitizer::PrintBoard (){ + printf("Connected to Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link"); + printf("Sampling rate : %.0f MHz = %.1f ns \n", 1000/ch2ns, ch2ns); + printf("Number of Channels : %d = 0x%X\n", NChannel, channelMask); + printf("SerialNumber :\e[1m\e[33m %d\e[0m\n", BoardInfo.SerialNumber); + printf("DPPType : %d (%s)\n", DPPType, GetDPPString().c_str()); + printf("ADC bit is \e[33m%d\e[0m, %d = 0x%X\n", ADCbits, ADCFullSize, ADCFullSize); + printf("ROC FPGA Release is %s\n", BoardInfo.ROC_FirmwareRel); + printf("AMC FPGA Release is %s\n", BoardInfo.AMC_FirmwareRel); +} + +int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose){ + + this->boardID = boardID; + this->portID = portID; + + if( boardID < 0 || portID < 0 ) return 0; /// for using the Digitizer Class without open digitizer + + /***************************************************/ + /** Open the digitizer and read board information */ + /***************************************************/ + + if( verbose) printf("============= Opening Digitizer at Board %d, Port %d \n", boardID, portID); + + ///-------- try USB first + LinkType = CAEN_DGTZ_USB; /// Link Type + ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, boardID, 0, VMEBaseAddress, &handle); + if (ret != 0){ ///---------- try Optical link + LinkType = CAEN_DGTZ_OpticalLink ; + ret = (int) CAEN_DGTZ_OpenDigitizer(LinkType, portID, boardID, VMEBaseAddress, &handle); + } + ErrorMsg("=== Open Digitizer port " +std::to_string(portID) + " board " + std::to_string(boardID)); + + if (ret != 0) { + if( verbose) printf("Can't open digitizer\n"); + return -1; + }else{ + ///----- Getting Board Info + ret = (int) CAEN_DGTZ_GetInfo(handle, &BoardInfo); + if (ret != 0) { + if( verbose) printf("Can't read board info\n"); + }else{ + isConnected = true; + NChannel = BoardInfo.Channels; + channelMask = pow(2, NChannel)-1; + switch(BoardInfo.Model){ + case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s + case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s + default : ch2ns = 4.0; break; + } + data->ch2ns = ch2ns; + data->boardSN = BoardInfo.SerialNumber; + ADCbits = BoardInfo.ADC_NBits; + ADCFullSize = (unsigned int)( pow(2, ADCbits) -1 ); + } + } + + ///====================== Check DPP firmware revision + sscanf(BoardInfo.AMC_FirmwareRel, "%d", &DPPType); + data->DPPType = DPPType; + /// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header. + ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardID, (DPPType & 0xF)); + if ( verbose ){ + PrintBoard(); + if (DPPType < 0x80 ) { + printf("This digitizer does not have DPP-PHA firmware\n"); + }else { + printf("\t==== This digitizer has a DPP firmware!\n"); + printf("\e[32m\t %s \e[0m", GetDPPString().c_str()); + } + } + ErrorMsg("========== Set BoardID"); + + ///======================= Check virtual probe + int probes[MAX_SUPPORTED_PROBES]; + int numProbes; + ret = CAEN_DGTZ_GetDPP_SupportedVirtualProbes(handle, 1, probes, &numProbes); + ErrorMsg("=== Get Supported Virtual Probes"); + if( verbose ){ + printf("\t==== supported virtual probe (number of Probe : %d)\n", numProbes); + for( int i = 0 ; i < numProbes; i++){ + switch (probes[i]){ + case 0: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Input\n"); break; + case 1: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta\n"); break; + case 2: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Delta2\n"); break; + case 3: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Trapezoid\n"); break; + case 4: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_TrapezoidReduced\n"); break; + case 5: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Baseline\n"); break; + case 6: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_Threshold\n"); break; + case 7: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_CFD\n"); break; + case 8: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_SmoothedInput\n"); break; + case 9: printf("\t\t CAEN_DGTZ_DPP_VIRTUALPROBE_None\n"); break; + case 10: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGWin\n"); break; + case 11: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Armed\n"); break; + case 12: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PkRun\n"); break; + case 13: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Peaking\n"); break; + case 14: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_CoincWin\n"); break; + case 15: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLHoldoff\n"); break; + case 16: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGHoldoff\n"); break; + case 17: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGVal\n"); break; + case 18: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ACQVeto\n"); break; + case 19: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BFMVeto\n"); break; + case 20: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_ExtTRG\n"); break; + case 21: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_OverThr\n"); break; + case 22: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_TRGOut\n"); break; + case 23: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Coincidence \n"); break; + case 24: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PileUp \n"); break; + case 25: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Gate \n"); break; + case 26: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_GateShort \n"); break; + case 27: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Trigger \n"); break; + case 28: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_None \n"); break; + case 29: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_BLFreeze \n"); break; + case 30: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_Busy \n"); break; + case 31: printf("\t\t CAEN_DGTZ_DPP_DIGITALPROBE_PrgVeto \n"); break; + } + } + } + + ErrorMsg("end of OpenDigitizer"); + + if( isConnected ) isDummy = false; + + if( isConnected && program) { + ProgramBoard(); + } + + if( isConnected ) ReadAllSettingsFromBoard(); + + return ret; +} + +int Digitizer::CloseDigitizer(){ + + if( !isConnected ) return 0; + isConnected = false; + printf("-------- Closing Digtizer Board : %d Port : %d \n", boardID, portID); + printf(" Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link"); + ret = CAEN_DGTZ_SWStopAcquisition(handle); + ret |= CAEN_DGTZ_CloseDigitizer(handle); + + return ret; +} + + +void Digitizer::SetChannelMask(uint32_t mask){ + if( !isConnected ) return; + channelMask = mask; + ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask); + SaveSettingToFile(Register::DPP::ChannelEnableMask, mask); + SetSettingToMemory(Register::DPP::ChannelEnableMask, mask); + ErrorMsg(__func__); +} + +void Digitizer::SetChannelOnOff(unsigned short ch, bool onOff){ + if( !isConnected ) return; + channelMask = ((channelMask & ~( 1 << ch) ) | ( onOff << ch)) ; + SetChannelMask(channelMask); +} + +int Digitizer::ProgramBoard(){ + + printf("----- program Board\n"); + ret = CAEN_DGTZ_Reset(handle); + if (ret) { + printf("ERROR: can't reset the digitizer.\n"); + return -1; + } + + /// Board Configuration without PHA or PSD fireware + ///bx0000 0000 0000 0000 0000 0000 0001 0000 = + /// | | +- (1) trigger overlap not allowed + /// | +- (3) test pattern disable + /// + (6) Self-trigger polarity, 1 = negative, 0 = Positive + ret = CAEN_DGTZ_WriteRegister(handle, (uint32_t) Register::BoardConfiguration , 0x000E0114); /// Channel Control Reg (indiv trg, seq readout) ?? + + /// Set the I/O level (CAEN_DGTZ_IOLevel_NIM or CAEN_DGTZ_IOLevel_TTL) + ret |= CAEN_DGTZ_SetIOLevel(handle, IOlev); + + /// Set the enabled channels + ret |= CAEN_DGTZ_SetChannelEnableMask(handle, channelMask); + + /// Set the number of samples for each waveform + ret |= CAEN_DGTZ_SetRecordLength(handle, 2000); + + /// Set Extras 2 to enable, this override Accusition mode, focring list mode + ret |= CAEN_DGTZ_WriteRegister(handle, Register::BoardConfiguration , 0x00E8114 ); + + /// Set the digitizer acquisition mode (CAEN_DGTZ_SW_CONTROLLED or CAEN_DGTZ_S_IN_CONTROLLED) + ret |= CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command + + CAEN_DGTZ_DPP_AcqMode_t AcqMode = CAEN_DGTZ_DPP_ACQ_MODE_List; + ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, AcqMode, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime); + + /** Set the digitizer's behaviour when an external trigger arrives: + CAEN_DGTZ_TRGMODE_DISABLED: do nothing + CAEN_DGTZ_TRGMODE_EXTOUT_ONLY: generate the Trigger Output signal + CAEN_DGTZ_TRGMODE_ACQ_ONLY = generate acquisition trigger + CAEN_DGTZ_TRGMODE_ACQ_AND_EXTOUT = generate both Trigger Output and acquisition trigger + see CAENDigitizer user manual, chapter "Trigger configuration" for details */ + //TODO set bit + ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); + + ret |= CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled); + + /// Set how many events to accumulate in the board memory before being available for readout + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::NumberEventsPerAggregate_G + 0x7000, 100); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::AggregateOrganization, 0); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::MaxAggregatePerBlockTransfer, 50); + + ErrorMsg(__func__); + return ret; + +} + +int Digitizer::ProgramPHABoard(){ + + ret = CAEN_DGTZ_Reset(handle); + printf("======== program board PHA\n"); + + ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::RecordLength_G + 0x7000, 62); + ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration, 0x0F8915); /// has Extra2 + ///ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration, 0x0D8115); /// diable Extra2 + + //TODO change to write register + ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command + ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM); + ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); + + ret = CAEN_DGTZ_SetChannelEnableMask(handle, 0xFFFF); + + //ret = CAEN_DGTZ_SetNumEventsPerAggregate(handle, 0); + + ret = CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled); + if( ret != 0 ) { printf("==== set board error.\n"); return 0;} + + printf("======== program Channels PHA\n"); + + uint32_t address; + + address = Register::DPP::PHA::DecayTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 5000 ); + address = Register::DPP::PHA::TrapezoidFlatTop; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x1A ); + address = Register::DPP::PHA::TrapezoidRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); + address = Register::DPP::PHA::PeakingTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); + address = Register::DPP::PHA::RCCR2SmoothingFactor; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 4 ); + address = Register::DPP::PHA::InputRiseTime; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 6 ); + address = Register::DPP::PHA::TriggerThreshold; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 1000 ); + address = Register::DPP::PHA::PeakHoldOff; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x3E ); + address = Register::DPP::PHA::TriggerHoldOffWidth; ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x3E ); + address = Register::DPP::PHA::RiseTimeValidationWindow;ret |= CAEN_DGTZ_WriteRegister(handle, address + 0x7000 , 0x0 ); + + + ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(Register::DPP::ChannelDCOffset) + 0x7000 , 0xEEEE ); + ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(Register::DPP::PreTrigger) + 0x7000 , 32 ); + ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(Register::DPP::InputDynamicRange) + 0x7000 , 0x0 ); + + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(Register::DPP::NumberEventsPerAggregate_G) + 0x7000, 511); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(Register::DPP::AggregateOrganization), 2); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(Register::DPP::MaxAggregatePerBlockTransfer), 4); + ret |= CAEN_DGTZ_WriteRegister(handle, (int32_t)(Register::DPP::DPPAlgorithmControl) + 0x7000, 0xC30200f); + + if( ret != 0 ) { printf("==== set channels error.\n"); return 0;} + + printf("End of program board and channels\n"); + + isSettingFilledinMemeory = false; /// unlock the ReadAllSettingsFromBoard(); + ReadAllSettingsFromBoard(); + + return ret; +} + +//========================================================= ACQ control +void Digitizer::StartACQ(){ + if ( AcqRun ) return; + + unsigned int bufferSize = CalByteForBuffer(); + if( bufferSize > 160 * 1024 * 1024 ){ + printf("============= buffer size bigger than 160 MB"); + return; + } + + data->AllocateMemory(bufferSize); + ret = CAEN_DGTZ_SWStartAcquisition(handle); + + if( ret != 0 ) { + ErrorMsg("Start ACQ"); + return; + } + + printf("\e[1m\e[33m======= Acquisition Started for Board %d\e[0m\n", boardID); + AcqRun = true; + data->ClearTriggerRate(); +} + +void Digitizer::StopACQ(){ + if( !AcqRun ) return; + int ret = CAEN_DGTZ_SWStopAcquisition(handle); + ret |= CAEN_DGTZ_ClearData(handle); + if( ret != 0 ) ErrorMsg("something wrong when try to stop ACQ and clear buffer"); + printf("\n\e[1m\e[33m====== Acquisition STOPPED for Board %d\e[0m\n", boardID); + AcqRun = false; + data->ClearTriggerRate(); +} + +unsigned int Digitizer::CalByteForBuffer(){ + unsigned int numAggBLT; + unsigned int chMask ; + unsigned int boardCfg ; + unsigned int eventAgg[NChannel/2]; + unsigned int recordLength[NChannel/2]; + unsigned int aggOrgan; + + if( isConnected ){ + numAggBLT = ReadRegister(Register::DPP::MaxAggregatePerBlockTransfer, 0, false); + chMask = ReadRegister(Register::DPP::ChannelEnableMask, 0, false); + boardCfg = ReadRegister(Register::DPP::BoardConfiguration, 0, false); + aggOrgan = ReadRegister(Register::DPP::AggregateOrganization, 0, false); + + for( int pCh = 0; pCh < NChannel/2; pCh++){ + eventAgg[pCh] = ReadRegister(Register::DPP::NumberEventsPerAggregate_G, pCh * 2 , false); + recordLength[pCh] = ReadRegister(Register::DPP::RecordLength_G, pCh * 2 , false); + } + }else{ + numAggBLT = GetSettingFromMemory(Register::DPP::MaxAggregatePerBlockTransfer); + chMask = GetSettingFromMemory(Register::DPP::ChannelEnableMask); + boardCfg = GetSettingFromMemory(Register::DPP::BoardConfiguration); + aggOrgan = GetSettingFromMemory(Register::DPP::AggregateOrganization); + for( int pCh = 0; pCh < NChannel/2; pCh++){ + eventAgg[pCh] = GetSettingFromMemory(Register::DPP::NumberEventsPerAggregate_G, pCh * 2 ); + recordLength[pCh] = GetSettingFromMemory(Register::DPP::RecordLength_G, pCh * 2); + } + } + + ///printf(" agg. orgainzation (bit) : 0x%X \n", aggOrgan); + ///printf(" Channel Mask : %04X \n", chMask); + ///printf("Max number of Agg per Readout : %u \n", numAggBLT); + ///printf(" is Extra2 enabed : %u \n", ((boardCfg >> 17) & 0x1) ); + ///printf(" is Record wave : %u \n", ((boardCfg >> 16) & 0x1) ); + ///for( int pCh = 0; pCh < NChannel/2; pCh++){ + /// printf("Paired Ch : %d, RecordLength (bit value): %u, Event per Agg. : %u \n", pCh, recordLength[pCh], eventAgg[pCh]); + ///} + + unsigned int bufferSize = 0; + for( int pCh = 0; pCh < NChannel/2 ; pCh++){ + if( (chMask & ( 3 << (2 * pCh) )) == 0 ) continue; + bufferSize += 2 + ( 2 + ((boardCfg >> 17) & 0x1) + ((boardCfg >> 16) & 0x1)*recordLength[pCh]*4 ) * eventAgg[pCh] ; + } + bufferSize += 4; /// Bd. Agg Header + bufferSize = bufferSize * numAggBLT * 4; /// 1 words = 4 byte + + ///printf("=============== Buffer Size : %8d Byte \n", bufferSize ); + return bufferSize ; +} + +void Digitizer::ReadData(){ + if( !isConnected ) return; + if( !AcqRun) return; + if( data->buffer == NULL ) { + printf("need allocate memory for readout buffer\n"); + return; + } + + ret = CAEN_DGTZ_ReadData(handle, CAEN_DGTZ_SLAVE_TERMINATED_READOUT_MBLT, data->buffer, &(data->nByte)); + //uint32_t EventSize = ReadRegister(Register::DPP::EventSize); // Is it as same as data->nByte? + //printf("Read Buffer size %d byte, Event Size : %d byte \n", data->nByte, EventSize); + + if (ret || data->nByte == 0) { + ErrorMsg(__func__); + return; + } +} + +void Digitizer::PrintACQStatue(){ + if( !isConnected ) return; + unsigned int status = ReadRegister(Register::DPP::AcquisitionStatus_R); + + printf("=================== Print ACQ status \n"); + printf(" 32 28 24 20 16 12 8 4 0\n"); + printf(" | | | | | | | | |\n"); + std::cout <<" 0b" << std::bitset<32>(status) << std::endl; + printf(" Acq state (0x%1X): %s \n", (status >> 2) & 0x1, ((status >> 2) & 0x1) == 0? "stopped" : "running"); + printf(" Event Ready (0x%1X): %s \n", (status >> 3) & 0x1, ((status >> 3) & 0x1) == 0? "no event in buffer" : "event in buffer"); + printf(" Event Full (0x%1X): %s \n", (status >> 4) & 0x1, ((status >> 4) & 0x1) == 0? "not full" : "full"); + printf(" Clock source (0x%1X): %s \n", (status >> 5) & 0x1, ((status >> 5) & 0x1) == 0? "internal" : "external"); + printf(" Board ready (0x%1X): %s \n", (status >> 8) & 0x1, ((status >> 8) & 0x1) == 0? "not ready" : "ready"); + printf(" Ch shutDown (0x%1X): %s \n", (status >> 19) & 0x1, ((status >> 19) & 0x1) == 0? "Channels are on" : "channels are shutdown"); + printf(" TRG-IN 0x%1X \n", (status >> 16) & 0x1); + printf(" Ch temp state 0x%04X \n", (status >> 20) & 0xF); +} + +//=========================================================== +//=========================================================== +//=========================================================== +void Digitizer::WriteRegister (Reg registerAddress, uint32_t value, int ch, bool isSave2MemAndFile){ + + printf("%30s[0x%04X](ch-%02d) [0x%04X]: 0x%08X \n", registerAddress.GetNameChar(), registerAddress.GetAddress(),ch, registerAddress.ActualAddress(ch), value); + + if( !isConnected ) { + SetSettingToMemory(registerAddress, value, ch); + SaveSettingToFile(registerAddress, value, ch); + return; + } + + if( registerAddress.GetType() == RW::ReadONLY ) return; + + ret = CAEN_DGTZ_WriteRegister(handle, registerAddress.ActualAddress(ch), value); + if( ret == 0 && isSave2MemAndFile && registerAddress.GetType() == RW::ReadWrite) { + SetSettingToMemory(registerAddress, value, ch); + SaveSettingToFile(registerAddress, value, ch); + } + + ErrorMsg("WriteRegister:" + std::to_string(registerAddress)); +} + +uint32_t Digitizer::ReadRegister(Reg registerAddress, unsigned short ch, bool isSave2MemAndFile, std::string str ){ + if( !isConnected ) return 0; + if( registerAddress.GetType() == RW::WriteONLY ) return 0; + + uint32_t data[1]; + ret = CAEN_DGTZ_ReadRegister(handle, registerAddress.ActualAddress(ch), data); + + if( ret == 0 && isSave2MemAndFile) { + SetSettingToMemory(registerAddress, data[0], ch); + SaveSettingToFile(registerAddress, data[0], ch); + } + ErrorMsg("ReadRegister:" + std::to_string(registerAddress)); + if( str != "" ) printf("%s : 0x%04X(0x%04X) is 0x%08X \n", str.c_str(), + registerAddress.ActualAddress(ch), registerAddress.GetAddress(), data[0]); + return data[0]; +} + +uint32_t Digitizer::PrintRegister(uint32_t address, std::string msg){ + if( !isConnected ) return 0 ; + printf("\e[33m----------------------------------------------------\n"); + printf("------------ %s = 0x%X \n", msg.c_str(), address); + printf("----------------------------------------------------\e[0m\n"); + + uint32_t * value = new uint32_t[1]; + CAEN_DGTZ_ReadRegister(handle, address, value); + printf(" %*s 32 28 24 20 16 12 8 4 0\n", (int) msg.length(), ""); + printf(" %*s | | | | | | | | |\n", (int) msg.length(), ""); + printf(" %*s", (int) msg.length(), ""); + std::cout << " : 0b" << std::bitset<32>(value[0]) << std::endl; + printf(" %*s : 0x%X\n", (int) msg.length(), msg.c_str(), value[0]); + + return value[0]; +} + +//========================================== setting file IO +Reg Digitizer::FindRegister(uint32_t address){ + + Reg tempReg; + ///========= Find Match Register + for( int p = 0; p < (int) RegisterDPPList[p]; p++){ + if( address == RegisterDPPList[p].GetAddress() ) { + tempReg = RegisterDPPList[p]; + break; + } + } + if( tempReg.GetName() == ""){ + if( DPPType == V1730_DPP_PHA_CODE ){ + for( int p = 0; p < (int) RegisterPHAList[p]; p++){ + if( address == RegisterPHAList[p].GetAddress() ) { + tempReg = RegisterPHAList[p]; + break; + } + } + } + if( DPPType == V1730_DPP_PSD_CODE ){ + for( int p = 0; p < (int) RegisterPSDList[p]; p++){ + if( address == RegisterPSDList[p].GetAddress() ) { + tempReg = RegisterPSDList[p]; + break; + } + } + } + } + + return tempReg; +} + +void Digitizer::ReadAllSettingsFromBoard(bool force){ + if( !isConnected ) return; + if( AcqRun ) return; + if( isSettingFilledinMemeory && !force) return; + + printf("===== %s \n", __func__); + + /// board setting + for( int p = 0; p < (int) RegisterDPPList[p]; p++){ + if( RegisterDPPList[p].GetType() == RW::WriteONLY) continue; + ReadRegister(RegisterDPPList[p]); + } + + channelMask = GetSettingFromMemory(Register::DPP::ChannelEnableMask); + + /// Channels Setting + for( int ch = 0; ch < NChannel; ch ++){ + if( DPPType == V1730_DPP_PHA_CODE ){ + for( int p = 0; p < (int) RegisterPHAList[p]; p++){ + if( RegisterPHAList[p].GetType() == RW::WriteONLY) continue; + ReadRegister(RegisterPHAList[p], ch); + } + } + if( DPPType == V1730_DPP_PSD_CODE ){ + for( int p = 0; p < (int) RegisterPSDList[p]; p++){ + if( RegisterPSDList[p].GetType() == RW::WriteONLY) continue; + ReadRegister(RegisterPSDList[p], ch); + } + } + } + isSettingFilledinMemeory = true; +} + +void Digitizer::ProgramSettingsToBoard(){ + if( !isConnected ) return; + if( isDummy ) return; + + Reg haha; + + /// board setting + for( int p = 0; p < (int) RegisterDPPList[p]; p++){ + if( RegisterDPPList[p].GetType() == RW::ReadONLY) continue; + haha = RegisterDPPList[p]; + WriteRegister(haha, GetSettingFromMemory(haha), -1, false); + usleep(100 * 1000); + } + /// Channels Setting + for( int ch = 0; ch < NChannel; ch ++){ + if( DPPType == V1730_DPP_PHA_CODE ){ + for( int p = 0; p < (int) RegisterPHAList[p]; p++){ + if( RegisterPHAList[p].GetType() == RW::ReadONLY) continue; + haha = RegisterPHAList[p]; + WriteRegister(haha, GetSettingFromMemory(haha, ch), ch, false); + usleep(100 * 1000); + } + } + if( DPPType == V1730_DPP_PSD_CODE ){ + for( int p = 0; p < (int) RegisterPSDList[p]; p++){ + if( RegisterPSDList[p].GetType() == RW::ReadONLY) continue; + haha = RegisterPHAList[p]; + WriteRegister(haha, GetSettingFromMemory(haha, ch), ch, false); + usleep(100 * 1000); + } + } + } +} + +void Digitizer::SetSettingToMemory(Reg registerAddress, unsigned int value, unsigned short ch ){ + unsigned short index = registerAddress.Index(ch); + if( index > SETTINGSIZE ) return; + setting[index] = value; +} + +unsigned int Digitizer::GetSettingFromMemory(Reg registerAddress, unsigned short ch ){ + unsigned short index = registerAddress.Index(ch); + if( index > SETTINGSIZE ) return 0xFFFF; + return setting[index] ; +} + +void Digitizer::PrintSettingFromMemory(){ + for( int i = 0; i < SETTINGSIZE; i++) printf("%4d | 0x%04X |0x%08X = %u \n", i, i*4, setting[i], setting[i]); +} + +void Digitizer::SetSettingBinaryPath(std::string fileName){ + + settingFile = fopen(fileName.c_str(), "r+"); + if( settingFile == NULL ){ + printf("cannot open file %s. Create one.\n", fileName.c_str()); + + ReadAllSettingsFromBoard(); + SaveAllSettingsAsBin(fileName); + + this->settingFileName = fileName; + settingFileExist = true; + + }else{ + this->settingFileName = fileName; + settingFileExist = true; + fclose(settingFile); + printf("setting file already exist. do nothing. Should program the digitizer\n"); + } + +} + +int Digitizer::LoadSettingBinaryToMemory(std::string fileName){ + + settingFile = fopen(fileName.c_str(), "r"); + + if( settingFile == NULL ) { + printf(" %s does not exist or cannot load.\n", fileName.c_str()); + settingFileExist = false; + return -1; + + }else{ + settingFileExist = true; + settingFileName = fileName; + fclose (settingFile); + + uint32_t fileDPP = ((ReadSettingFromFile(Register::DPP::AMCFirmwareRevision_R, 0) >> 8) & 0xFF); + + /// compare seeting DPP version; + if( isConnected && DPPType != fileDPP ){ + printf("DPPType in the file is %s(0x%X), but the dgitizer DPPType is %s(0x%X). \n", GetDPPString(fileDPP).c_str(), fileDPP, GetDPPString().c_str(), DPPType); + return -1; + }else{ + /// load binary to memoery + DPPType = fileDPP; + printf("DPPType in the file is %s(0x%X). \n", GetDPPString(fileDPP).c_str(), fileDPP); + + settingFile = fopen(fileName.c_str(), "r"); + size_t dummy = fread( setting, SETTINGSIZE * sizeof(unsigned int), 1, settingFile); + fclose (settingFile); + + uint32_t boardInfo = GetSettingFromMemory(Register::DPP::BoardInfo_R); + if( (boardInfo & 0xFF) == 0x0E ) ch2ns = 4.0; + if( (boardInfo & 0xFF) == 0x0B ) ch2ns = 2.0; + + ///Should seperate file<->memory, memory<->board + ///ProgramSettingsToBoard(); /// do nothing if not connected. + + return 0; + } + } +} + +unsigned int Digitizer::ReadSettingFromFile(Reg registerAddress, unsigned short ch){ + if ( !settingFileExist ) return -1; + + unsigned short index = registerAddress.Index(ch); + + settingFile = fopen (settingFileName.c_str(),"r"); + ///fseek( settingFile, address, SEEK_SET); + fseek( settingFile, index * 4, SEEK_SET); + ///printf(" at pos %lu Byte = index(%lu)\n", ftell(settingFile), ftell(settingFile)/4); + unsigned int lala[1]; + size_t dummy = fread( lala, sizeof(unsigned int), 1, settingFile); + ///printf(" data at pos %lu(%lu) : %X = %d\n", ftell(settingFile) - sizeof(unsigned int), (ftell(settingFile) - sizeof(unsigned int))/4, lala[0], lala[0]); + fclose (settingFile); + return lala[0]; + +} + +void Digitizer::SaveSettingToFile(Reg registerAddress, unsigned int value, unsigned short ch){ + if ( !settingFileExist ) return ; + + unsigned short index = registerAddress.Index(ch); + setting[index] = value; + + settingFile = fopen (settingFileName.c_str(),"r+"); + ///fseek( settingFile, address, SEEK_SET); + fseek( settingFile, index * 4, SEEK_SET); + unsigned int jaja[1] = {value}; + size_t dummy = fwrite( jaja, sizeof(unsigned int), 1, settingFile); + ///printf("fwrite ret : %d, 0x%0X, 0x%0X, %d, 0x%X = %d\n", (int)dummy, registerAddress, index*4, index, jaja[0], jaja[0]); + fclose (settingFile); +} + +void Digitizer::SaveAllSettingsAsBin(std::string fileName){ + if( !isSettingFilledinMemeory ) return; + + FILE * binFile = fopen(fileName.c_str(), "w+"); + if( binFile == NULL ) { + printf("Cannot open %s.\n", fileName.c_str()); + return; + } + + fwrite(setting, SETTINGSIZE * sizeof(unsigned int), 1, binFile); + fseek(binFile, 0L, SEEK_END); + unsigned int inFileSize = ftell(binFile); + printf("Created file : %s. file size : %d Byte\n", fileName.c_str(), inFileSize); + fclose (binFile); +} + +void Digitizer::SaveAllSettingsAsText(std::string fileName){ + if( !isSettingFilledinMemeory ) return; + + FILE * txtFile = fopen(fileName.c_str(), "w+"); + if( txtFile == NULL ) { + printf("Cannot open %s.\n", fileName.c_str()); + return; + } + + Reg haha; + + for( unsigned int i = 0; i < SETTINGSIZE ; i++){ + haha.SetName(""); + uint32_t actualAddress = haha.CalAddress(i); + + ///printf("%7d--- 0x%04X, 0x%04X\n", i, haha->GetAddress(), haha->ActualAddress()); + for( int p = 0; p < (int) RegisterDPPList.size(); p++){ + if( haha.GetAddress() == (uint32_t) RegisterDPPList[p] ) haha = RegisterDPPList[p]; + } + if( DPPType == V1730_DPP_PHA_CODE) { + for( int p = 0; p < (int) RegisterPHAList.size(); p++){ + if( haha.GetAddress() == (uint32_t) RegisterPHAList[p] ) haha = RegisterPHAList[p]; + } + } + if( DPPType == V1730_DPP_PSD_CODE) { + for( int p = 0; p < (int) RegisterPSDList.size(); p++){ + if( haha.GetAddress() == (uint32_t) RegisterPSDList[p] ) haha = RegisterPSDList[p]; + } + } + if( haha.GetName() != "" ) { + std::string typeStr ; + if( haha.GetType() == RW::ReadWrite ) typeStr = "R/W"; + if( haha.GetType() == RW::ReadONLY ) typeStr = "R "; + if( haha.GetType() == RW::WriteONLY ) typeStr = " W"; + fprintf( txtFile, "0x%04X %30s 0x%08X %s %u\n", actualAddress, + haha.GetNameChar(), + setting[i], + typeStr.c_str(), + setting[i]); + } + } +} + +std::string Digitizer::GetDPPString(int DPPType){ + std::string DPPTypeStr = ""; + if( DPPType == 0 ) DPPType = this->DPPType; + switch (DPPType){ + case V1724_DPP_PHA_CODE: DPPTypeStr = "DPP-PHA x724"; break; /// 0x80 + case V1720_DPP_CI_CODE : DPPTypeStr = "DPP-CI x720"; break; /// 0x82 + case V1720_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x720"; break; /// 0x83 + case V1751_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x751"; break; /// 0x84 + case V1751_DPP_ZLE_CODE: DPPTypeStr = "DPP-ZLE x751"; break; /// 0x85 + case V1743_DPP_CI_CODE: DPPTypeStr = "DPP-PSD x743"; break; /// 0x86 + case V1740_DPP_QDC_CODE: DPPTypeStr = "DPP-QDC x740"; break; /// 0x87 + case V1730_DPP_PSD_CODE: DPPTypeStr = "DPP-PSD x730"; break; /// 0x88 + case V1730_DPP_PHA_CODE: DPPTypeStr = "DPP-PHA x730"; break; /// 0x8B + case V1730_DPP_ZLE_CODE: DPPTypeStr = "DPP-ZLE x730"; break; /// 0x8C + case V1730_DPP_DAW_CODE: DPPTypeStr = "DPP-DAW x730"; break; /// 0x8D + } + return DPPTypeStr; +} + +void Digitizer::ErrorMsg(std::string header){ + switch (ret){ + ///case CAEN_DGTZ_Success : /** 0 */ printf("%s | Operation completed successfully.\n", header.c_str()); break; + case CAEN_DGTZ_CommError : /** -1 */ printf("%s | Communication Error.\n", header.c_str()); break; + case CAEN_DGTZ_GenericError : /** -2 */ printf("%s | Unspecified error.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidParam : /** -3 */ printf("%s | Invalid parameter.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidLinkType : /** -4 */ printf("%s | Invalid Link Type.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidHandle : /** -5 */ printf("%s | Invalid device handler.\n", header.c_str()); break; + case CAEN_DGTZ_MaxDevicesError : /** -6 */ printf("%s | Maximum number of devices exceeded.\n", header.c_str()); break; + case CAEN_DGTZ_BadBoardType : /** -7 */ printf("%s | Operation not allowed on this type of board.\n", header.c_str()); break; + case CAEN_DGTZ_BadInterruptLev : /** -8 */ printf("%s | The interrupt level is not allowed.\n", header.c_str()); break; + case CAEN_DGTZ_BadEventNumber : /** -9 */ printf("%s | The event number is bad.\n", header.c_str()); break; + case CAEN_DGTZ_ReadDeviceRegisterFail : /** -10 */ printf("%s | Unable to read the registry.\n", header.c_str()); break; + case CAEN_DGTZ_WriteDeviceRegisterFail : /** -11 */ printf("%s | Unable to write the registry.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidChannelNumber : /** -13 */ printf("%s | The channel number is invalid.\n", header.c_str()); break; + case CAEN_DGTZ_ChannelBusy : /** -14 */ printf("%s | The channel is busy.\n", header.c_str()); break; + case CAEN_DGTZ_FPIOModeInvalid : /** -15 */ printf("%s | Invalid FPIO mode.\n", header.c_str()); break; + case CAEN_DGTZ_WrongAcqMode : /** -16 */ printf("%s | Wrong Acquistion mode.\n", header.c_str()); break; + case CAEN_DGTZ_FunctionNotAllowed : /** -17 */ printf("%s | This function is not allowed on this module.\n", header.c_str()); break; + case CAEN_DGTZ_Timeout : /** -18 */ printf("%s | Communication Timeout.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidBuffer : /** -19 */ printf("%s | The buffer is invalid.\n", header.c_str()); break; + case CAEN_DGTZ_EventNotFound : /** -20 */ printf("%s | The event is not found.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidEvent : /** -21 */ printf("%s | The event is invalid.\n", header.c_str()); break; + case CAEN_DGTZ_OutOfMemory : /** -22 */ printf("%s | Out of memory.\n", header.c_str()); break; + case CAEN_DGTZ_CalibrationError : /** -23 */ printf("%s | Unable to calibrate the board.\n", header.c_str()); break; + case CAEN_DGTZ_DigitizerNotFound : /** -24 */ printf("%s | Unbale to open the digitizer.\n", header.c_str()); break; + case CAEN_DGTZ_DigitizerAlreadyOpen : /** -25 */ printf("%s | The digitizer is already open.\n", header.c_str()); break; + case CAEN_DGTZ_DigitizerNotReady : /** -26 */ printf("%s | The digitizer is not ready.\n", header.c_str()); break; + case CAEN_DGTZ_InterruptNotConfigured : /** -27 */ printf("%s | The digitizer has no IRQ configured.\n", header.c_str()); break; + case CAEN_DGTZ_DigitizerMemoryCorrupted: /** -28 */ printf("%s | The digitizer flash memory is corrupted.\n", header.c_str()); break; + case CAEN_DGTZ_DPPFirmwareNotSupported : /** -29 */ printf("%s | The digitier DPP firmware is not supported in this lib version.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidLicense : /** -30 */ printf("%s | Invalid firmware licence.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidDigitizerStatus : /** -31 */ printf("%s | The digitizer is found in a corrupted status.\n", header.c_str()); break; + case CAEN_DGTZ_UnsupportedTrace : /** -32 */ printf("%s | The given trace is not supported.\n", header.c_str()); break; + case CAEN_DGTZ_InvalidProbe : /** -33 */ printf("%s | The given probe is not supported.\n", header.c_str()); break; + case CAEN_DGTZ_UnsupportedBaseAddress : /** -34 */ printf("%s | The base address is not supported.\n", header.c_str()); break; + case CAEN_DGTZ_NotYetImplemented : /** -99 */ printf("%s | The function is not yet implemented.\n", header.c_str()); break; + } + +} + +/** +void Digitizer::SetRecordLength(unsigned int ns, int ch){ + WriteRegister( Register::DPP::RecordLength_G, ns / ch2ns / 8 , ch); + if( ch >= 0 ) WriteRegister( Register::DPP::RecordLength_G, ns / ch2ns / 8 , ch + int(pow(-1, ch))); + ErrorMsg(__func__); +} + +void Digitizer::SetAggregateOrganization(unsigned int bit){ + WriteRegister(Register::DPP::AggregateOrganization, bit & 0x7); + ErrorMsg(__func__); +} + + +void Digitizer::SetEventAggregation(unsigned int numEvent, int ch){ + WriteRegister( Register::DPP::NumberEventsPerAggregate_G,numEvent, ch); + if( ch >= 0 ) WriteRegister( Register::DPP::NumberEventsPerAggregate_G,numEvent, ch + int(pow(-1, ch))); + ErrorMsg(__func__); +} + +void Digitizer::SetMaxAggregatePerBlockTransfer(unsigned int numEvent){ + WriteRegister( Register::DPP::MaxAggregatePerBlockTransfer,numEvent); + ErrorMsg(__func__); +} + + +void Digitizer::SetACQControl(uint32_t bit){ + WriteRegister( Register::DPP::AcquisitionControl, bit); + ErrorMsg(__func__); +} + +void Digitizer::SetGlobalTriggerMask(uint32_t bit){ + WriteRegister( Register::DPP::GlobalTriggerMask, bit); + ErrorMsg(__func__); +} + +void Digitizer::SetFrontPanelTRGOUTMask(uint32_t bit){ + WriteRegister( Register::DPP::FrontPanelTRGOUTEnableMask, bit); + ErrorMsg(__func__); +} + +void Digitizer::SetFrontPanelIOControl(uint32_t bit){ + WriteRegister( Register::DPP::FrontPanelIOControl, bit); + ErrorMsg(__func__); +} + +void Digitizer::SetTriggerValidationMask(uint32_t bit){ + WriteRegister( Register::DPP::TriggerValidationMask_G, bit); + ErrorMsg(__func__); +} + +void Digitizer::SetInputDynamicRange(unsigned int TwoVol_0_or_halfVol_1, int ch){ WriteRegister( Register::DPP::InputDynamicRange, TwoVol_0_or_halfVol_1, ch); ErrorMsg(__func__);} +void Digitizer::SetPreTriggerSample(unsigned int nSample, int ch) { WriteRegister( Register::DPP::PreTrigger, nSample / 4, ch); ErrorMsg(__func__);} +void Digitizer::SetPreTriggerDuration(unsigned int ns, int ch) { WriteRegister( Register::DPP::PreTrigger, ns / ch2ns / 4, ch); ErrorMsg(__func__);} +void Digitizer::SetDCOffset(float offsetPrecentage, int ch) { WriteRegister( Register::DPP::ChannelDCOffset, uint( 0xFFFF * (1.0-offsetPrecentage)), ch ); ErrorMsg(__func__);} +void Digitizer::SetVetoWidth(uint32_t bit, int ch) { WriteRegister( Register::DPP::VetoWidth, bit, ch); ErrorMsg(__func__);} + +void Digitizer::SetTriggerPolarity(bool RiseingIsZero, int ch ){ + if( !isConnected ) return; + if ( DPPType >= 128 ) return; /// do thing for DPP firmware + if( ch < 0 ) { + ret = 0; + for (int i = 0; i < NChannel; i++){ + ret |= CAEN_DGTZ_SetTriggerPolarity(handle, i, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero)); + } + }else{ + ret = CAEN_DGTZ_SetTriggerPolarity(handle, ch, CAEN_DGTZ_TriggerPolarity_t(RiseingIsZero)); + } + if( ret != 0 ) ErrorMsg(__func__); +} + +//============================== DPP-Alpgorthm Control +void Digitizer::SetDPPAlgorithmControl(uint32_t bit, int ch){ + WriteRegister( Register::DPP::DPPAlgorithmControl, bit, ch); + if( ret != 0 ) ErrorMsg(__func__); +} + +unsigned int Digitizer::ReadBits(Reg address, unsigned int bitLength, unsigned int bitSmallestPos, int ch ){ + int tempCh = ch; + if (ch < 0 && address < 0x8000 ) tempCh = 0; /// take ch-0 + uint32_t bit = ReadRegister(address, tempCh); + bit = (bit >> bitSmallestPos ) & uint(pow(2, bitLength)-1); + return bit; +} + +void Digitizer::SetBits(Reg address, unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, int ch){ + ///printf("address : 0x%X, value : 0x%X, len : %d, pos : %d, ch : %d \n", address, bitValue, bitLength, bitSmallestPos, ch); + uint32_t bit ; + uint32_t bitmask = (uint(pow(2, bitLength)-1) << bitSmallestPos); + int tempCh = ch; + if (ch < 0 && address < 0x8000 ) tempCh = 0; /// take ch-0 + bit = ReadRegister(address, tempCh); + ///printf("bit : 0x%X, bitmask : 0x%X \n", bit, bitmask); + bit = (bit & ~bitmask) | (bitValue << bitSmallestPos); + ///printf("bit : 0x%X, ch : %d \n", bit, ch); + WriteRegister(address, bit, ch); + if( ret != 0 ) ErrorMsg(__func__); +} + +int Digitizer::GetChTemperature(int ch){ + if( !isConnected ) return -404; + if( BoardInfo.Model != CAEN_DGTZ_V1730 && + BoardInfo.Model != CAEN_DGTZ_V1725 && + BoardInfo.Model != CAEN_DGTZ_V1751 ) return -404; + + uint32_t * temp; + ret |= CAEN_DGTZ_ReadTemperature(handle, ch, temp); + if( ret != 0 ) ErrorMsg(__func__); + return temp[0]; +} + + +*/ diff --git a/ClassDigitizer.h b/ClassDigitizer.h new file mode 100644 index 0000000..151b607 --- /dev/null +++ b/ClassDigitizer.h @@ -0,0 +1,179 @@ +#ifndef DIGITIZER_H +#define DIGITIZER_H + +#include +#include +#include +#include +#include ///memset +#include ///cout +#include + +#include "CAENDigitizer.h" +#include "CAENDigitizerType.h" + +#include "macro.h" +#include "ClassData.h" +#include "RegisterAddress.h" + +//################################################################ +class Digitizer{ + + protected: + + Data * data; + + ///---- fixed parameter + int portID; /// port ID for optical link for using PCIe card, from 0, 1, 2, 3 + int boardID; /// board identity + int handle; /// i don't know why, but better separete the handle from boardID + int NChannel; /// number of channel + int ADCbits; /// ADC bit + int DPPType; /// DPP verion + unsigned int ADCFullSize; /// pow(2, ADCbits) - 1 + float ch2ns; /// channel to ns + CAEN_DGTZ_BoardInfo_t BoardInfo; + + ///----- adjustable parameters + uint32_t channelMask ; /// the channel mask from NChannel + uint32_t VMEBaseAddress; /// For direct USB or Optical-link connection, VMEBaseAddress must be 0 + CAEN_DGTZ_ConnectionType LinkType; /// USB or Optic + CAEN_DGTZ_IOLevel_t IOlev; /// TTL signal (1 = 1.5 to 5V, 0 = 0 to 0.7V ) or NIM signal (1 = -1 to -0.8V, 0 = 0V) + + ///------- other parameters + int ret; /// return value, refer to CAEN_DGTZ_ErrorCode + bool isConnected; /// true for digitizer communication estabished. + bool AcqRun; /// true when digitizer is taking data + bool isDummy; /// true for a dummy digitizer. + + /// ------- setting + std::string settingFileName; /// + FILE * settingFile; /// + bool settingFileExist; /// + bool isSettingFilledinMemeory; /// false for disabled ReadAllSettingFromBoard() + unsigned int setting[SETTINGSIZE]; /// Setting, 4bytes x 2048 = 8192 bytes + + ///---------- protected functions + + void ErrorMsg(std::string header = ""); + + public: + Digitizer(); /// no digitizer open + Digitizer(int boardID, int portID = 0, bool program = false, bool verbose = false); + ~Digitizer(); + + /// portID is for optical link for using PCIe card, from 0, 1, 2, 3 + int OpenDigitizer(int boardID, int portID = 0, bool program = false, bool verbose = false); + void SetDPPType (int type) { this->DPPType = type;} /// for manual override, or, digitizer does not open + void SetChannelMask (uint32_t mask); + void SetChannelOnOff (unsigned short ch, bool onOff); + int CloseDigitizer(); + void Initalization(); + void Reset(); + bool IsDummy() {return isDummy;}; + + void PrintBoard() ; + virtual int ProgramBoard() ; /// program a generic board, no program channel + int ProgramPHABoard() ; /// program a default PHA board + + ///================ ACQ control + void StopACQ(); + void StartACQ(); + void ReadData(); + bool IsRunning() const {return AcqRun;} + Data * GetData() const {return data;} + void PrintACQStatue(); + + unsigned int CalByteForBuffer(); + + ///=================Settings + /// write value to digitizer, memory, and settingFile (if exist) + /// ONLY WriteRegister can have ch = -1, for writting all channels + /// for board setting, ignore ch + void WriteRegister (Reg registerAddress, uint32_t value, int ch = -1, bool isSave2MemAndFile = true); + /// read value from digitizer and memory, and save to memory, and settingFile(if exist), + /// for board setting, ignore ch + uint32_t ReadRegister (Reg registerAddress, unsigned short ch = 0, bool isSave2MemAndFile = true, std::string str = "" ); + uint32_t PrintRegister(uint32_t address, std::string msg); + + ///================ Get Board info + std::string GetModelName() const {return BoardInfo.ModelName;} + int GetSerialNumber() const {return BoardInfo.SerialNumber;} + int GetChannelMask() const {return channelMask;} + bool GetChannelOnOff(unsigned ch) const {return (channelMask & ( 1 << ch) );} + float GetCh2ns() const {return ch2ns;} + int GetNChannel() const {return NChannel;} + int GetHandle() const {return handle;} + bool GetConnectionStatus() const {return isConnected;} + int GetDPPType() const {return DPPType;} + std::string GetDPPString(int DPPType = 0); /// if no input, use digitizer DPPType + int GetADCBits() const {return BoardInfo.ADC_NBits;} + std::string GetROCVersion() const {return BoardInfo.ROC_FirmwareRel;} + std::string GetAMCVersion() const {return BoardInfo.AMC_FirmwareRel;} + CAEN_DGTZ_ConnectionType GetLinkType() const {return LinkType;} + + ///================ Setting + Reg FindRegister(uint32_t address); + /// board <--> memory functions + void ReadAllSettingsFromBoard (bool force = false); + void ProgramSettingsToBoard (); + + /// simply read settings from memory + void SetSettingToMemory (Reg registerAddress, unsigned int value, unsigned short ch = 0); + unsigned int GetSettingFromMemory (Reg registerAddress, unsigned short ch = 0); + void PrintSettingFromMemory (); + unsigned int * GetSettings() {return setting;}; + + /// memory <--> file + void SaveAllSettingsAsText (std::string fileName); + void SaveAllSettingsAsBin (std::string fileName); + std::string GetSettingFileName() {return settingFileName;} + /// tell the digitizer where to look at the setting file. + /// if not exist, call SaveAllSettinsAsBin(); + void SetSettingBinaryPath (std::string fileName); + /// load setting file to memory + /// if problem, return -1; load without problem, return 0; + int LoadSettingBinaryToMemory (std::string fileName); + void SaveSettingToFile (Reg registerAddress, unsigned int value, unsigned short ch = 0); /// also save to memory + unsigned int ReadSettingFromFile (Reg registerAddress, unsigned short ch = 0); /// read from setting binary + + ///=================== Relic methods + ///void SetRecordLength (unsigned int ns, int ch = -1); /// when ch == -1, mean set all channels + ///void SetInputDynamicRange (unsigned int TwoVol_0_or_halfVol_1, int ch = -1); + ///void SetPreTriggerSample (unsigned int nSample, int ch = -1 ); + ///void SetPreTriggerDuration (unsigned int ns, int ch = -1 ); + ///void SetDCOffset (float offsetPrecentage, int ch = -1); + ///void SetVetoWidth (uint32_t bit, int ch = -1); /// See manual + ///void SetTriggerPolarity (bool RiseingIsZero, int ch = -1); ///not used for DPP firmware + /// + ///void SetEventAggregation (unsigned int numEvent, int ch = -1); + ///void SetAggregateOrganization (unsigned int bit); + ///void SetMaxAggregatePerBlockTransfer (unsigned int numEvent); + /// + ///void SetBits(Reg address, unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, int ch = -1); + ///void SetDPPAlgorithmControl(uint32_t bit, int ch = -1); + /// + ///void SetACQControl(uint32_t bit); + ///void SetGlobalTriggerMask(uint32_t bit); + ///void SetFrontPanelTRGOUTMask(uint32_t bit); + ///void SetFrontPanelIOControl(uint32_t bit); + ///void SetTriggerValidationMask(uint32_t bit); + ///void SetBoardID(unsigned int ID) {WriteRegister(Register::DPP::BoardID, ID)); + + ///unsigned int GetRecordLengthSample(int ch) {return ReadRegister(Register::DPP::RecordLength_G, ch) * 8;} + ///unsigned int GetInputDynamicRange(int ch) {return ReadRegister(Register::DPP::InputDynamicRange, ch);} + ///unsigned int GetPreTriggerSample(int ch) {return ReadRegister(Register::DPP::PreTrigger, ch) * 4;} + ///float GetDCOffset(int ch) {return 100.0 - ReadRegister(Register::DPP::ChannelDCOffset, ch) * 100. / 0xFFFFF; } + ///unsigned int GetVetoWidth(int ch) {return ReadRegister(Register::DPP::VetoWidth, ch);} + ///unsigned int GetEventAggregation(int ch = -1) {return ReadRegister(Register::DPP::NumberEventsPerAggregate_G, ch);} + ///unsigned int GetAggregateOrganization() {return ReadRegister(Register::DPP::AggregateOrganization);} + ///unsigned int GetMaxNumberOfAggregatePerBlockTransfer() {return ReadRegister(Register::DPP::MaxAggregatePerBlockTransfer);} + /// + ///unsigned int ReadBits(Reg address, unsigned int bitLength, unsigned int bitSmallestPos, int ch = -1 ); + ///unsigned int GetDPPAlgorithmControl(int ch = -1) {return ReadRegister(Register::DPP::DPPAlgorithmControl, ch);} + /// + ///int GetChTemperature(int ch) ; +}; + + +#endif diff --git a/FSUDAQ_Qt6.pro b/FSUDAQ_Qt6.pro new file mode 100644 index 0000000..26d686a --- /dev/null +++ b/FSUDAQ_Qt6.pro @@ -0,0 +1,22 @@ +###################################################################### +# Automatically generated by qmake (3.1) Tue Apr 11 11:05:33 2023 +###################################################################### + +TEMPLATE = app +TARGET = FSUDAQ_Qt6 +INCLUDEPATH += . + +QT += widgets charts + +LIBS += -lCAENDigitizer + +# You can make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# Please consult the documentation of the deprecated API in order to know +# how to port your code away from it. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +# Input +HEADERS += ClassData.h ClassDigitizer.h macro.h mainWindow.h RegisterAddress.h +SOURCES += ClassDigitizer.cpp main.cpp mainWindow.C diff --git a/RegisterAddress.h b/RegisterAddress.h new file mode 100644 index 0000000..508febd --- /dev/null +++ b/RegisterAddress.h @@ -0,0 +1,608 @@ +#ifndef REGISTERADDRESS_H +#define REGISTERADDRESS_H + +#include + +///======= +/// All 0x1XXX registers are either indiviual or Group +/// Indiviual register are all independence +/// Group register, 2m and 2m+1 channels setting are shared. and the name will have _G as prefix +/// Most 0x8XXX registers are common, which share for all channel + +/// For adding Register, two things needed. +/// 1) add to the namepace +/// 2) add to the RegisterXXXList + +/// The Reg Class has conversion operator +/// Reg haha("haha", 0x1234); +/// uint32_t papa = haha; /// papa = 0x1234 + +enum RW { ReadWrite = 0, ReadONLY = 1, WriteONLY = 2}; + +class Reg{ + public: + Reg(){ + this->name = ""; + this->address = 0; + this->type = 0; + this->group = 0; + } + Reg(std::string name, uint32_t address, char type = 0, bool group = 0){ + this->name = name; + this->address = address; + this->type = type; + this->group = group; + }; + + ~Reg(){}; + + operator uint32_t () const {return this->address;} /// this allows Reg kaka("kaka", 0x1234) uint32_t haha = kaka; + + std::string GetName() const {return this->name;} + const char * GetNameChar() const {return this->name.c_str();} + uint32_t GetAddress() const {return this->address; } + char GetType() const {return this->type;} + bool GetGroup() const {return this->group;} + void Print() const ; + + uint32_t ActualAddress(int ch = -1){ + if( address == 0x8180 ) return (ch < 0 ? address : (address + 4*(ch/2))); + if( address < 0x8000 ) return (ch < 0 ? (address + 0x7000) : (address + (ch << 8)) ); + if( address >= 0x8000 ) return address; + return 0; + } + + unsigned short Index (unsigned short ch); + uint32_t CalAddress(unsigned int index); /// output actual address, also write the registerAddress + + void SetName(std::string str) {this->name = str;} + + private: + uint32_t address; /// This is the table of register, the actual address should call ActualAddress(); + std::string name; + char type; /// read/write = 0; read = 1; write = 2 + bool group; +}; + +inline void Reg::Print() const{ + printf(" Name: %s\n", name.c_str()); + printf("Address: 0x%04X\n", address); + printf(" Type: %s\n", type == RW::ReadWrite ? "Read/Write" : (type == RW::ReadONLY ? "Read-Only" : "Write-Only") ); + printf(" Group: %s\n", group ? "True" : "False"); +} + +inline unsigned short Reg::Index (unsigned short ch){ + unsigned short index; + if( address == 0x8180){ + index = ((address + 4*(ch/2)) & 0x0FFF) / 4; + }else if( address < 0x8000){ + index = (address + (ch << 8)) / 4; + }else{ + if(address < 0xF000) { + index = (address & 0x0FFF) / 4; + }else{ + index = ((address & 0x0FFF) + 0x0200 ) / 4; + } + } + return index; +} + +inline uint32_t Reg::CalAddress(unsigned int index){ + + uint32_t actualAddress = 0xFFFF; + this->address = 0xFFFF; + + if( index < 0x0200 /4 ) {actualAddress = index * 4 + 0x8000; this->address = index * 4 + 0x8000; } + if( 0x0200 / 4 <= index && index < 0x0300 /4 ) {actualAddress = index * 4 + 0xEE00; this->address = index * 4 + 0xEE00; }/// EE00 == F000 - 0200 + if( 0x0F00 / 4 <= index && index < 0x1000 /4 ) {actualAddress = index * 4 + 0xE000; this->address = index * 4 + 0xE000; } + if( 0x1000 / 4 <= index ) {actualAddress = index * 4; this->address = (index * 4) & 0xF0FF; } + + ///for TriggerValidationMask + if( index == ((0x8180 + 4) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 4; address = 0x8180;} /// 1 + if( index == ((0x8180 + 8) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 8; address = 0x8180;} /// 2 + if( index == ((0x8180 + 12) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 12; address = 0x8180;} /// 3 + if( index == ((0x8180 + 16) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 16; address = 0x8180;} /// 4 + if( index == ((0x8180 + 20) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 20; address = 0x8180;} /// 5 + if( index == ((0x8180 + 24) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 24; address = 0x8180;} /// 6 + if( index == ((0x8180 + 28) & 0x0FFF) / 4 ) {actualAddress = 0x8180 + 28; address = 0x8180;} /// 7 + + return actualAddress; +} + +namespace Register { + + const Reg EventReadOutBuffer("EventReadOutBuffer", 0x0000, 1); /// R + + ///========== Channel or Group + const Reg ChannelDummy32 ("ChannelDummy32" , 0x1024); /// R/W + const Reg InputDynamicRange ("InputDynamicRange" , 0x1028); /// R/W + const Reg ChannelPulseWidth ("ChannelPulseWidth" , 0x1070); /// R/W + const Reg ChannelTriggerThreshold ("ChannelTriggerThreshold" , 0x1080); /// R/W + const Reg CoupleSelfTriggerLogic_G ("CoupleSelfTriggerLogic_G" , 0x1084, 0 , 1); /// R/W + const Reg ChannelStatus_R ("ChannelStatus_R" , 0x1088, 1); /// R + const Reg AMCFirmwareRevision_R ("AMCFirmwareRevision_R" , 0x108C, 1); /// R + const Reg ChannelDCOffset ("ChannelDCOffset" , 0x1098); /// R/W + const Reg ChannelADCTemperature_R ("ChannelADCTemperature_R" , 0x10A8, 1); /// R + const Reg ChannelSelfTriggerRateMeter_R ("ChannelSelfTriggerRateMeter_R", 0x10EC, 1); /// R + + ///========== Board + const Reg BoardConfiguration ("BoardConfiguration" , 0x8000, 0); /// R/W + const Reg BufferOrganization ("BufferOrganization" , 0x800C, 0); /// R/W + const Reg CustomSize ("CustomSize" , 0x8020, 0); /// R/W + const Reg ADCCalibration_W ("ADCCalibration_W" , 0x809C, 2); /// W + const Reg AcquisitionControl ("AcquisitionControl" , 0x8100, 0); /// R/W + const Reg AcquisitionStatus_R ("AcquisitionStatus_R" , 0x8104, 1); /// R + const Reg SoftwareTrigger_W ("SoftwareTrigger_W" , 0x8108, 2); /// W + const Reg GlobalTriggerMask ("GlobalTriggerMask" , 0x810C, 0); /// R/W + const Reg FrontPanelTRGOUTEnableMask ("FrontPanelTRGOUTEnableMask" , 0x8110, 0); /// R/W + const Reg PostTrigger ("PostTrigger" , 0x8114, 0); /// R/W + const Reg LVDSIOData ("LVDSIOData" , 0x8118, 0); /// R/W + const Reg FrontPanelIOControl ("FrontPanelIOControl" , 0x811C, 0); /// R/W + const Reg ChannelEnableMask ("ChannelEnableMask" , 0x8120, 0); /// R/W + const Reg ROCFPGAFirmwareRevision_R ("ROCFPGAFirmwareRevision_R" , 0x8124, 1); /// R + const Reg EventStored_R ("EventStored_R" , 0x812C, 1); /// R + const Reg VoltageLevelModeConfig ("VoltageLevelModeConfig" , 0x8138, 0); /// R/W + const Reg SoftwareClockSync_W ("SoftwareClockSync_W" , 0x813C, 2); /// W + const Reg BoardInfo_R ("BoardInfo_R" , 0x8140, 1); /// R + const Reg AnalogMonitorMode ("AnalogMonitorMode" , 0x8144, 0); /// R/W + const Reg EventSize_R ("EventSize_R" , 0x814C, 1); /// R + const Reg FanSpeedControl ("FanSpeedControl" , 0x8168, 0); /// R/W + const Reg MemoryBufferAlmostFullLevel ("MemoryBufferAlmostFullLevel" , 0x816C, 0); /// R/W + const Reg RunStartStopDelay ("RunStartStopDelay" , 0x8170, 0); /// R/W + const Reg BoardFailureStatus_R ("BoardFailureStatus_R" , 0x8178, 1); /// R + const Reg FrontPanelLVDSIONewFeatures ("FrontPanelLVDSIONewFeatures" , 0x81A0, 0); /// R/W + const Reg BufferOccupancyGain ("BufferOccupancyGain" , 0x81B4, 0); /// R/W + const Reg ChannelsShutdown_W ("ChannelsShutdown_W" , 0x81C0, 2); /// W + const Reg ExtendedVetoDelay ("ExtendedVetoDelay" , 0x81C4, 0); /// R/W + const Reg ReadoutControl ("ReadoutControl" , 0xEF00, 0); /// R/W + const Reg ReadoutStatus_R ("ReadoutStatus_R" , 0xEF04, 1); /// R + const Reg BoardID ("BoardID" , 0xEF08, 0); /// R/W + const Reg MCSTBaseAddressAndControl ("MCSTBaseAddressAndControl" , 0xEF0C, 0); /// R/W + const Reg RelocationAddress ("RelocationAddress" , 0xEF10, 0); /// R/W + const Reg InterruptStatusID ("InterruptStatusID" , 0xEF14, 0); /// R/W + const Reg InterruptEventNumber ("InterruptEventNumber" , 0xEF18, 0); /// R/W + const Reg MaxAggregatePerBlockTransfer ("MaxAggregatePerBlockTransfer" , 0xEF1C, 0); /// R/W + const Reg Scratch ("Scratch" , 0xEF20, 0); /// R/W + const Reg SoftwareReset_W ("SoftwareReset_W" , 0xEF24, 2); /// W + const Reg SoftwareClear_W ("SoftwareClear_W" , 0xEF28, 2); /// W + + + ///====== Common for PHA and PSD + namespace DPP { + + const Reg RecordLength_G ("RecordLength_G" , 0x1020, 0, 1); /// R/W + const Reg InputDynamicRange ("InputDynamicRange" , 0x1028, 0); /// R/W + const Reg NumberEventsPerAggregate_G ("NumberEventsPerAggregate_G" , 0x1034, 0, 1); /// R/W + const Reg PreTrigger ("PreTrigger" , 0x1038, 0); /// R/W + const Reg TriggerThreshold ("TriggerThreshold" , 0x106C, 0); /// R/W + const Reg TriggerHoldOffWidth ("TriggerHoldOffWidth" , 0x1074, 0); /// R/W + const Reg DPPAlgorithmControl ("DPPAlgorithmControl" , 0x1080, 0); /// R/W + const Reg ChannelStatus_R ("ChannelStatus_R" , 0x1088, 1); /// R + const Reg AMCFirmwareRevision_R ("AMCFirmwareRevision_R" , 0x108C, 1); /// R + const Reg ChannelDCOffset ("ChannelDCOffset" , 0x1098, 0); /// R/W + const Reg ChannelADCTemperature_R ("ChannelADCTemperature_R" , 0x10A8, 1); /// R + const Reg IndividualSoftwareTrigger_W ("IndividualSoftwareTrigger_W" , 0x10C0, 2); /// W + const Reg VetoWidth ("VetoWidth" , 0x10D4, 0); /// R/W + + /// I know there are many duplication, it is the design. + const Reg BoardConfiguration ("BoardConfiguration" , 0x8000, 0 ); /// R/W + const Reg AggregateOrganization ("AggregateOrganization" , 0x800C, 0 ); /// R/W + const Reg ADCCalibration_W ("ADCCalibration_W" , 0x809C, 2 ); /// W + const Reg ChannelShutdown_W ("ChannelShutdown_W" , 0x80BC, 2 ); /// W + const Reg AcquisitionControl ("AcquisitionControl" , 0x8100, 0 ); /// R/W + const Reg AcquisitionStatus_R ("AcquisitionStatus_R" , 0x8104, 1 ); /// R + const Reg SoftwareTrigger_W ("SoftwareTrigger_W" , 0x8108, 2 ); /// W + const Reg GlobalTriggerMask ("GlobalTriggerMask" , 0x810C, 0 ); /// R/W + const Reg FrontPanelTRGOUTEnableMask ("FrontPanelTRGOUTEnableMask" , 0x8110, 0 ); /// R/W + const Reg LVDSIOData ("LVDSIOData" , 0x8118, 0 ); /// R/W + const Reg FrontPanelIOControl ("FrontPanelIOControl" , 0x811C, 0 ); /// R/W + const Reg ChannelEnableMask ("ChannelEnableMask" , 0x8120, 0 ); /// R/W + const Reg ROCFPGAFirmwareRevision_R ("ROCFPGAFirmwareRevision_R" , 0x8124, 1 ); /// R + const Reg EventStored_R ("EventStored_R" , 0x812C, 1 ); /// R + const Reg VoltageLevelModeConfig ("VoltageLevelModeConfig" , 0x8138, 0 ); /// R/W + const Reg SoftwareClockSync_W ("SoftwareClockSync_W" , 0x813C, 2 ); /// W + const Reg BoardInfo_R ("BoardInfo_R" , 0x8140, 1 ); /// R + const Reg AnalogMonitorMode ("AnalogMonitorMode" , 0x8144, 0 ); /// R/W + const Reg EventSize_R ("EventSize_R" , 0x814C, 1 ); /// R + const Reg TimeBombDowncounter_R ("TimeBombDowncounter_R" , 0x8158, 1 ); /// R + const Reg FanSpeedControl ("FanSpeedControl" , 0x8168, 0 ); /// R/W + const Reg RunStartStopDelay ("RunStartStopDelay" , 0x8170, 0 ); /// R/W + const Reg BoardFailureStatus_R ("BoardFailureStatus_R" , 0x8178, 1 ); /// R + const Reg DisableExternalTrigger ("DisableExternalTrigger" , 0x817C, 0 ); /// R/W + const Reg TriggerValidationMask_G ("TriggerValidationMask_G" , 0x8180, 0 , 1); /// R/W, + const Reg FrontPanelLVDSIONewFeatures ("FrontPanelLVDSIONewFeatures" , 0x81A0, 0 ); /// R/W + const Reg BufferOccupancyGain ("BufferOccupancyGain" , 0x81B4, 0 ); /// R/W + const Reg ExtendedVetoDelay ("ExtendedVetoDelay" , 0x81C4, 0 ); /// R/W + const Reg ReadoutControl ("ReadoutControl" , 0xEF00, 0 ); /// R/W + const Reg ReadoutStatus_R ("ReadoutStatus_R" , 0xEF04, 1 ); /// R + const Reg BoardID ("BoardID" , 0xEF08, 0 ); /// R/W + const Reg MCSTBaseAddressAndControl ("MCSTBaseAddressAndControl" , 0xEF0C, 0 ); /// R/W + const Reg RelocationAddress ("RelocationAddress" , 0xEF10, 0 ); /// R/W + const Reg InterruptStatusID ("InterruptStatusID" , 0xEF14, 0 ); /// R/W + const Reg InterruptEventNumber ("InterruptEventNumber" , 0xEF18, 0 ); /// R/W + const Reg MaxAggregatePerBlockTransfer("MaxAggregatePerBlockTransfer", 0xEF1C, 0 ); /// R/W + const Reg Scratch ("Scratch" , 0xEF20, 0 ); /// R/W + const Reg SoftwareReset_W ("SoftwareReset_W" , 0xEF24, 2 ); /// W + const Reg SoftwareClear_W ("SoftwareClear_W" , 0xEF28, 2 ); /// W + const Reg ConfigurationReload_W ("ConfigurationReload_W" , 0xEF34, 2 ); /// W + const Reg ROMChecksum_R ("ROMChecksum_R" , 0xF000, 1 ); /// R + const Reg ROMChecksumByte2_R ("ROMChecksumByte2_R" , 0xF004, 1 ); /// R + const Reg ROMChecksumByte1_R ("ROMChecksumByte1_R" , 0xF008, 1 ); /// R + const Reg ROMChecksumByte0_R ("ROMChecksumByte0_R" , 0xF00C, 1 ); /// R + const Reg ROMConstantByte2_R ("ROMConstantByte2_R" , 0xF010, 1 ); /// R + const Reg ROMConstantByte1_R ("ROMConstantByte1_R" , 0xF014, 1 ); /// R + const Reg ROMConstantByte0_R ("ROMConstantByte0_R" , 0xF018, 1 ); /// R + const Reg ROM_C_Code_R ("ROM_C_Code_R" , 0xF01C, 1 ); /// R + const Reg ROM_R_Code_R ("ROM_R_Code_R" , 0xF020, 1 ); /// R + const Reg ROM_IEEE_OUI_Byte2_R ("ROM_IEEE_OUI_Byte2_R" , 0xF024, 1 ); /// R + const Reg ROM_IEEE_OUI_Byte1_R ("ROM_IEEE_OUI_Byte1_R" , 0xF028, 1 ); /// R + const Reg ROM_IEEE_OUI_Byte0_R ("ROM_IEEE_OUI_Byte0_R" , 0xF02C, 1 ); /// R + const Reg ROM_BoardVersion_R ("ROM_BoardVersion_R" , 0xF030, 1 ); /// R + const Reg ROM_BoardFromFactor_R ("ROM_BoardFromFactor_R" , 0xF034, 1 ); /// R + const Reg ROM_BoardIDByte1_R ("ROM_BoardIDByte1_R" , 0xF038, 1 ); /// R + const Reg ROM_BoardIDByte0_R ("ROM_BoardIDByte0_R" , 0xF03C, 1 ); /// R + const Reg ROM_PCB_rev_Byte3_R ("ROM_PCB_rev_Byte3_R" , 0xF040, 1 ); /// R + const Reg ROM_PCB_rev_Byte2_R ("ROM_PCB_rev_Byte2_R" , 0xF044, 1 ); /// R + const Reg ROM_PCB_rev_Byte1_R ("ROM_PCB_rev_Byte1_R" , 0xF048, 1 ); /// R + const Reg ROM_PCB_rev_Byte0_R ("ROM_PCB_rev_Byte0_R" , 0xF04C, 1 ); /// R + const Reg ROM_FlashType_R ("ROM_FlashType_R" , 0xF050, 1 ); /// R + const Reg ROM_BoardSerialNumByte1_R ("ROM_BoardSerialNumByte1_R" , 0xF080, 1 ); /// R + const Reg ROM_BoardSerialNumByte0_R ("ROM_BoardSerialNumByte0_R" , 0xF084, 1 ); /// R + const Reg ROM_VCXO_Type_R ("ROM_VCXO_Type_R" , 0xF088, 1 ); /// R + + namespace PHA { + const Reg DataFlush_W ("DataFlush_W" , 0x103C, 2); /// W not sure + const Reg ChannelStopAcquisition ("ChannelStopAcquisition" , 0x1040); /// R/W not sure + const Reg RCCR2SmoothingFactor ("RCCR2SmoothingFactor" , 0x1054); /// R/W Trigger Filter smoothing, triggerSmoothingFactor + const Reg InputRiseTime ("InputRiseTime" , 0x1058); /// R/W OK + const Reg TrapezoidRiseTime ("TrapezoidRiseTime" , 0x105C); /// R/W OK + const Reg TrapezoidFlatTop ("TrapezoidFlatTop" , 0x1060); /// R/W OK + const Reg PeakingTime ("PeakingTime" , 0x1064); /// R/W OK + const Reg DecayTime ("DecayTime" , 0x1068); /// R/W OK + const Reg TriggerThreshold ("TriggerThreshold" , 0x106C); /// R/W OK + const Reg RiseTimeValidationWindow ("RiseTimeValidationWindow" , 0x1070); /// R/W OK + const Reg TriggerHoldOffWidth ("TriggerHoldOffWidth" , 0x1074); /// R/W OK + const Reg PeakHoldOff ("PeakHoldOff" , 0x1078); /// R/W OK + const Reg ShapedTriggerWidth ("ShapedTriggerWidth" , 0x1084); /// R/W not sure + const Reg DPPAlgorithmControl2_G ("DPPAlgorithmControl2_G" , 0x10A0, 0, 1); /// R/W OK + const Reg FineGain ("FineGain" , 0x10C4); /// R/W OK + } + + namespace PSD { + const Reg CFDSetting ("CFDSetting" , 0x103C); /// R/W + const Reg ForcedDataFlush_W ("ForcedDataFlush_W" , 0x1040, 2); /// W + const Reg ChargeZeroSuppressionThreshold ("ChargeZeroSuppressionThreshold" , 0x1044); /// R/W + const Reg ShortGateWidth ("ShortGateWidth" , 0x1054); /// R/W + const Reg LongGateWidth ("LongGateWidth" , 0x1058); /// R/W + const Reg GateOffset ("GateOffset" , 0x105C); /// R/W + const Reg TriggerThreshold ("TriggerThreshold" , 0x1060); /// R/W + const Reg FixedBaseline ("FixedBaseline" , 0x1064); /// R/W + const Reg TriggerLatency ("TriggerLatency" , 0x106C); /// R/W + const Reg ShapedTriggerWidth ("ShapedTriggerWidth" , 0x1070); /// R/W + const Reg TriggerHoldOffWidth ("TriggerHoldOffWidth" , 0x1074); /// R/W + const Reg ThresholdForPSDCut ("ThresholdForPSDCut" , 0x1078); /// R/W + const Reg PurGapThreshold ("PurGapThreshold" , 0x107C); /// R/W + const Reg DPPAlgorithmControl2_G ("DPPAlgorithmControl2_G" , 0x1084, 0, 1); /// R/W + const Reg EarlyBaselineFreeze ("EarlyBaselineFreeze" , 0x10D8); /// R/W + } + } +}; + +const std::vector RegisterPHAList = { + Register::DPP::PHA::DataFlush_W , + Register::DPP::PHA::ChannelStopAcquisition , + Register::DPP::PHA::RCCR2SmoothingFactor , + Register::DPP::PHA::InputRiseTime , + Register::DPP::PHA::TrapezoidRiseTime , + Register::DPP::PHA::TrapezoidFlatTop , + Register::DPP::PHA::PeakingTime , + Register::DPP::PHA::DecayTime , + Register::DPP::PHA::TriggerThreshold , + Register::DPP::PHA::RiseTimeValidationWindow , + Register::DPP::PHA::TriggerHoldOffWidth , + Register::DPP::PHA::PeakHoldOff , + Register::DPP::PHA::ShapedTriggerWidth , + Register::DPP::PHA::DPPAlgorithmControl2_G , + Register::DPP::PHA::FineGain , + + Register::DPP::RecordLength_G , + Register::DPP::InputDynamicRange , + Register::DPP::NumberEventsPerAggregate_G , + Register::DPP::PreTrigger , + Register::DPP::TriggerThreshold , + Register::DPP::TriggerHoldOffWidth , + Register::DPP::DPPAlgorithmControl , + Register::DPP::ChannelStatus_R , + Register::DPP::AMCFirmwareRevision_R , + Register::DPP::ChannelDCOffset , + Register::DPP::ChannelADCTemperature_R , + Register::DPP::IndividualSoftwareTrigger_W, + Register::DPP::VetoWidth , + + Register::DPP::TriggerValidationMask_G +}; + +const std::vector RegisterPSDList = { + Register::DPP::PSD::CFDSetting , + Register::DPP::PSD::ForcedDataFlush_W , + Register::DPP::PSD::ChargeZeroSuppressionThreshold , + Register::DPP::PSD::ShortGateWidth , + Register::DPP::PSD::LongGateWidth , + Register::DPP::PSD::GateOffset , + Register::DPP::PSD::TriggerThreshold , + Register::DPP::PSD::FixedBaseline , + Register::DPP::PSD::TriggerLatency , + Register::DPP::PSD::ShapedTriggerWidth , + Register::DPP::PSD::TriggerHoldOffWidth , + Register::DPP::PSD::ThresholdForPSDCut , + Register::DPP::PSD::PurGapThreshold , + Register::DPP::PSD::DPPAlgorithmControl2_G , + Register::DPP::PSD::EarlyBaselineFreeze , + + Register::DPP::RecordLength_G , + Register::DPP::InputDynamicRange , + Register::DPP::NumberEventsPerAggregate_G , + Register::DPP::PreTrigger , + Register::DPP::TriggerThreshold , + Register::DPP::TriggerHoldOffWidth , + Register::DPP::DPPAlgorithmControl , + Register::DPP::ChannelStatus_R , + Register::DPP::AMCFirmwareRevision_R , + Register::DPP::ChannelDCOffset , + Register::DPP::ChannelADCTemperature_R , + Register::DPP::IndividualSoftwareTrigger_W, + Register::DPP::VetoWidth , + + Register::DPP::TriggerValidationMask_G +}; + +/// Only Board Setting +const std::vector RegisterDPPList = { + + Register::DPP::BoardConfiguration , + Register::DPP::AggregateOrganization , + Register::DPP::ADCCalibration_W , + Register::DPP::ChannelShutdown_W , + Register::DPP::AcquisitionControl , + Register::DPP::AcquisitionStatus_R , + Register::DPP::SoftwareTrigger_W , + Register::DPP::GlobalTriggerMask , + Register::DPP::FrontPanelTRGOUTEnableMask , + Register::DPP::LVDSIOData , + Register::DPP::FrontPanelIOControl , + Register::DPP::ChannelEnableMask , + Register::DPP::ROCFPGAFirmwareRevision_R , + Register::DPP::EventStored_R , + Register::DPP::VoltageLevelModeConfig , + Register::DPP::SoftwareClockSync_W , + Register::DPP::BoardInfo_R , + Register::DPP::AnalogMonitorMode , + Register::DPP::EventSize_R , + Register::DPP::TimeBombDowncounter_R , + Register::DPP::FanSpeedControl , + Register::DPP::RunStartStopDelay , + Register::DPP::BoardFailureStatus_R , + Register::DPP::DisableExternalTrigger , + Register::DPP::FrontPanelLVDSIONewFeatures , + Register::DPP::BufferOccupancyGain , + Register::DPP::ExtendedVetoDelay , + Register::DPP::ReadoutControl , + Register::DPP::ReadoutStatus_R , + Register::DPP::BoardID , + Register::DPP::MCSTBaseAddressAndControl , + Register::DPP::RelocationAddress , + Register::DPP::InterruptStatusID , + Register::DPP::InterruptEventNumber , + Register::DPP::MaxAggregatePerBlockTransfer, + Register::DPP::Scratch , + Register::DPP::SoftwareReset_W , + Register::DPP::SoftwareClear_W , + Register::DPP::ConfigurationReload_W , + Register::DPP::ROMChecksum_R , + Register::DPP::ROMChecksumByte2_R , + Register::DPP::ROMChecksumByte1_R , + Register::DPP::ROMChecksumByte0_R , + Register::DPP::ROMConstantByte2_R , + Register::DPP::ROMConstantByte1_R , + Register::DPP::ROMConstantByte0_R , + Register::DPP::ROM_C_Code_R , + Register::DPP::ROM_R_Code_R , + Register::DPP::ROM_IEEE_OUI_Byte2_R , + Register::DPP::ROM_IEEE_OUI_Byte1_R , + Register::DPP::ROM_IEEE_OUI_Byte0_R , + Register::DPP::ROM_BoardVersion_R , + Register::DPP::ROM_BoardFromFactor_R , + Register::DPP::ROM_BoardIDByte1_R , + Register::DPP::ROM_BoardIDByte0_R , + Register::DPP::ROM_PCB_rev_Byte3_R , + Register::DPP::ROM_PCB_rev_Byte2_R , + Register::DPP::ROM_PCB_rev_Byte1_R , + Register::DPP::ROM_PCB_rev_Byte0_R , + Register::DPP::ROM_FlashType_R , + Register::DPP::ROM_BoardSerialNumByte1_R , + Register::DPP::ROM_BoardSerialNumByte0_R , + Register::DPP::ROM_VCXO_Type_R + +}; + + +/*************************** +namespace Register { + const uint32_t EventReadOutBuffer = 0x0000; /// R + + ///========== Channel or Group + const uint32_t ChannelDummy32 = 0x1024; /// R/W + const uint32_t InputDynamicRange = 0x1028; /// R/W + const uint32_t ChannelPulseWidth = 0x1070; /// R/W + const uint32_t ChannelTriggerThreshold = 0x1080; /// R/W + const uint32_t CoupleSelfTriggerLogic_G = 0x1084; /// R/W + const uint32_t ChannelStatus_R = 0x1088; /// R + const uint32_t AMCFirmwareRevision_ = 0x108C; /// R + const uint32_t ChannelDCOffset = 0x1098; /// R/W + const uint32_t ChannelADCTemperature_R = 0x10A8; /// R + const uint32_t ChannelSelfTriggerRateMeter_R = 0x10EC; /// R + + ///========== Board + const uint32_t BoardConfiguration = 0x8000; /// R/W + const uint32_t BufferOrganization = 0x800C; /// R/W + const uint32_t CustomSize = 0x8020; /// R/W + const uint32_t ADCCalibration_W = 0x809C; /// W + const uint32_t AcquisitionControl = 0x8100; /// R/W + const uint32_t AcquisitionStatus_R = 0x8104; /// R + const uint32_t SoftwareTrigger_W = 0x8108; /// W + const uint32_t GlobalTriggerMask = 0x810C; /// R/W + const uint32_t FrontPanelTRGOUTEnableMask = 0x8110; /// R/W + const uint32_t PostTrigger = 0x8114; /// R/W + const uint32_t LVDSIOData = 0x8118; /// R/W + const uint32_t FrontPanelIOControl = 0x811C; /// R/W + const uint32_t ChannelEnableMask = 0x8120; /// R/W + const uint32_t ROCFPGAFirmwareRevision_R = 0x8124; /// R + const uint32_t EventStored_R = 0x812C; /// R + const uint32_t VoltageLevelModeConfig = 0x8138; /// R/W + const uint32_t SoftwareClockSync_W = 0x813C; /// W + const uint32_t BoardInfo_R = 0x8140; /// R + const uint32_t AnalogMonitorMode = 0x8144; /// R/W + const uint32_t EventSize_R = 0x814C; /// R + const uint32_t FanSpeedControl = 0x8168; /// R/W + const uint32_t MemoryBufferAlmostFullLevel = 0x816C; /// R/W + const uint32_t RunStartStopDelay = 0x8170; /// R/W + const uint32_t BoardFailureStatus_R = 0x8178; /// R + const uint32_t FrontPanelLVDSIONewFeatures = 0x81A0; /// R/W + const uint32_t BufferOccupancyGain = 0x81B4; /// R/W + const uint32_t ChannelsShutdown_W = 0x81C0; /// W + const uint32_t ExtendedVetoDelay = 0x81C4; /// R/W + const uint32_t ReadoutControl = 0xEF00; /// R/W + const uint32_t ReadoutStatus_R = 0xEF04; /// R + const uint32_t BoardID = 0xEF08; /// R/W + const uint32_t MCSTBaseAddressAndControl = 0xEF0C; /// R/W + const uint32_t RelocationAddress = 0xEF10; /// R/W + const uint32_t InterruptStatusID = 0xEF14; /// R/W + const uint32_t InterruptEventNumber = 0xEF18; /// R/W + const uint32_t MaxAggregatePerBlockTransfer = 0xEF1C; /// R/W + const uint32_t Scratch = 0xEF20; /// R/W + const uint32_t SoftwareReset_W = 0xEF24; /// W + const uint32_t SoftwareClear_W = 0xEF28; /// W + + ///====== Common for PHA and PSD + namespace DPP { + const uint32_t RecordLength_G = 0x1020; /// R/W + const uint32_t InputDynamicRange = 0x1028; /// R/W + const uint32_t NumberEventsPerAggregate_G = 0x1034; /// R/W + const uint32_t PreTrigger = 0x1038; /// R/W + const uint32_t TriggerThreshold = 0x106C; /// R/W + const uint32_t TriggerHoldOffWidth = 0x1074; /// R/W + const uint32_t DPPAlgorithmControl = 0x1080; /// R/W + const uint32_t ChannelStatus_R = 0x1088; /// R + const uint32_t AMCFirmwareRevision_R = 0x108C; /// R + const uint32_t ChannelDCOffset = 0x1098; /// R/W + const uint32_t ChannelADCTemperature_R = 0x10A8; /// R + const uint32_t IndividualSoftwareTrigger_W = 0x10C0; /// W + const uint32_t VetoWidth = 0x10D4; /// R/W + + /// I know there are many duplication, it is the design. + const uint32_t BoardConfiguration = 0x8000; /// R/W + const uint32_t AggregateOrganization = 0x800C; /// R/W + const uint32_t ADCCalibration_W = 0x809C; /// W + const uint32_t ChannelShutdown_W = 0x80BC; /// W + const uint32_t AcquisitionControl = 0x8100; /// R/W + const uint32_t AcquisitionStatus_R = 0x8104; /// R + const uint32_t SoftwareTrigger_W = 0x8108; /// W + const uint32_t GlobalTriggerMask = 0x810C; /// R/W + const uint32_t FrontPanelTRGOUTEnableMask = 0x8110; /// R/W + const uint32_t LVDSIOData = 0x8118; /// R/W + const uint32_t FrontPanelIOControl = 0x811C; /// R/W + const uint32_t ChannelEnableMask = 0x8120; /// R/W + const uint32_t ROCFPGAFirmwareRevision_R = 0x8124; /// R + const uint32_t EventStored_R = 0x812C; /// R + const uint32_t VoltageLevelModeConfig = 0x8138; /// R/W + const uint32_t SoftwareClockSync_W = 0x813C; /// W + const uint32_t BoardInfo_R = 0x8140; /// R /// [0:7] 0x0E = 725, 0x0B = 730, [8:15] 0x01 = 640 kSample, 0x08 = 5.12 MSample, [16:23] channel number + const uint32_t AnalogMonitorMode = 0x8144; /// R/W + const uint32_t EventSize_R = 0x814C; /// R + const uint32_t TimeBombDowncounter_R = 0x8158; /// R + const uint32_t FanSpeedControl = 0x8168; /// R/W + const uint32_t RunStartStopDelay = 0x8170; /// R/W + const uint32_t BoardFailureStatus_R = 0x8178; /// R + const uint32_t DisableExternalTrigger = 0x817C; /// R/W + const uint32_t TriggerValidationMask_G = 0x8180; /// R/W, 0x8180 + 4n + const uint32_t FrontPanelLVDSIONewFeatures = 0x81A0; /// R/W + const uint32_t BufferOccupancyGain = 0x81B4; /// R/W + const uint32_t ExtendedVetoDelay = 0x81C4; /// R/W + const uint32_t ReadoutControl = 0xEF00; /// R/W + const uint32_t ReadoutStatus_R = 0xEF04; /// R + const uint32_t BoardID = 0xEF08; /// R/W /// Geo address on VME crate + const uint32_t MCSTBaseAddressAndControl = 0xEF0C; /// R/W + const uint32_t RelocationAddress = 0xEF10; /// R/W + const uint32_t InterruptStatusID = 0xEF14; /// R/W + const uint32_t InterruptEventNumber = 0xEF18; /// R/W + const uint32_t MaxAggregatePerBlockTransfer= 0xEF1C; /// R/W + const uint32_t Scratch = 0xEF20; /// R/W + const uint32_t SoftwareReset_W = 0xEF24; /// W + const uint32_t SoftwareClear_W = 0xEF28; /// W + const uint32_t ConfigurationReload_W = 0xEF34; /// W + const uint32_t ROMChecksum_R = 0xF000; /// R + const uint32_t ROMChecksumByte2_R = 0xF004; /// R + const uint32_t ROMChecksumByte1_R = 0xF008; /// R + const uint32_t ROMChecksumByte0_R = 0xF00C; /// R + const uint32_t ROMConstantByte2_R = 0xF010; /// R + const uint32_t ROMConstantByte1_R = 0xF014; /// R + const uint32_t ROMConstantByte0_R = 0xF018; /// R + const uint32_t ROM_C_Code_R = 0xF01C; /// R + const uint32_t ROM_R_Code_R = 0xF020; /// R + const uint32_t ROM_IEEE_OUI_Byte2_R = 0xF024; /// R + const uint32_t ROM_IEEE_OUI_Byte1_R = 0xF028; /// R + const uint32_t ROM_IEEE_OUI_Byte0_R = 0xF02C; /// R + const uint32_t ROM_BoardVersion_R = 0xF030; /// R + const uint32_t ROM_BoardFromFactor_R = 0xF034; /// R + const uint32_t ROM_BoardIDByte1_R = 0xF038; /// R + const uint32_t ROM_BoardIDByte0_R = 0xF03C; /// R + const uint32_t ROM_PCB_rev_Byte3_R = 0xF040; /// R + const uint32_t ROM_PCB_rev_Byte2_R = 0xF044; /// R + const uint32_t ROM_PCB_rev_Byte1_R = 0xF048; /// R + const uint32_t ROM_PCB_rev_Byte0_R = 0xF04C; /// R + const uint32_t ROM_FlashType_R = 0xF050; /// R + const uint32_t ROM_BoardSerialNumByte1_R = 0xF080; /// R + const uint32_t ROM_BoardSerialNumByte0_R = 0xF084; /// R + const uint32_t ROM_VCXO_Type_R = 0xF088; /// R + + namespace PHA { + const uint32_t DataFlush_W = 0x103C; /// W not sure + const uint32_t ChannelStopAcquisition = 0x1040; /// R/W not sure + const uint32_t RCCR2SmoothingFactor = 0x1054; /// R/W Trigger Filter smoothing, triggerSmoothingFactor + const uint32_t InputRiseTime = 0x1058; /// R/W OK + const uint32_t TrapezoidRiseTime = 0x105C; /// R/W OK + const uint32_t TrapezoidFlatTop = 0x1060; /// R/W OK + const uint32_t PeakingTime = 0x1064; /// R/W OK + const uint32_t DecayTime = 0x1068; /// R/W OK + const uint32_t TriggerThreshold = 0x106C; /// R/W OK + const uint32_t RiseTimeValidationWindow = 0x1070; /// R/W OK + const uint32_t TriggerHoldOffWidth = 0x1074; /// R/W OK + const uint32_t PeakHoldOff = 0x1078; /// R/W OK + const uint32_t ShapedTriggerWidth = 0x1084; /// R/W not sure + const uint32_t DPPAlgorithmControl2_G = 0x10A0; /// R/W OK + const uint32_t FineGain = 0x10C4; /// R/W OK + } + + namespace PSD { + const uint32_t CFDSetting = 0x103C; /// R/W + const uint32_t ForcedDataFlush_W = 0x1040; /// W + const uint32_t ChargeZeroSuppressionThreshold = 0x1044; /// R/W + const uint32_t ShortGateWidth = 0x1054; /// R/W + const uint32_t LongGateWidth = 0x1058; /// R/W + const uint32_t GateOffset = 0x105C; /// R/W + const uint32_t TriggerThreshold = 0x1060; /// R/W + const uint32_t FixedBaseline = 0x1064; /// R/W + const uint32_t TriggerLatency = 0x106C; /// R/W + const uint32_t ShapedTriggerWidth = 0x1070; /// R/W + const uint32_t TriggerHoldOffWidth = 0x1074; /// R/W + const uint32_t ThresholdForPSDCut = 0x1078; /// R/W + const uint32_t PurGapThreshold = 0x107C; /// R/W + const uint32_t DPPAlgorithmControl2_G = 0x1084; /// R/W + const uint32_t EarlyBaselineFreeze = 0x10D8; /// R/W + } + } + +} +*********************************/ + +#endif diff --git a/macro.h b/macro.h new file mode 100644 index 0000000..19ad7b6 --- /dev/null +++ b/macro.h @@ -0,0 +1,23 @@ +#ifndef MACRO_H +#define MACRO_H + +#define MaxNPorts 4 +#define MaxNBoards 22 +#define MaxNChannels 16 +#define MaxRecordLength 0x3fff * 8 +#define MaxSaveFileSize 1024 * 1024 * 1024 * 2 + +#define SETTINGSIZE 2048 + +#include /** struct timeval, select() */ + +inline unsigned int get_time(){ + unsigned int time_us; + struct timeval t1; + struct timezone tz; + gettimeofday(&t1, &tz); + time_us = (t1.tv_sec) * 1000 * 1000 + t1.tv_usec; + return time_us; +} + +#endif diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6655d31 --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "mainWindow.h" + +#include + +int main(int argc, char *argv[]){ + QApplication a(argc, argv); + + MainWindow w; + w.show(); + return a.exec(); +} \ No newline at end of file diff --git a/mainWindow.C b/mainWindow.C new file mode 100644 index 0000000..b339e37 --- /dev/null +++ b/mainWindow.C @@ -0,0 +1,17 @@ +#include "mainWindow.h" + +#include + +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ + + setWindowTitle("FSU DAQ"); + setGeometry(500, 100, 1000, 500); + + + +} + +MainWindow::~MainWindow(){ + + +} diff --git a/mainWindow.h b/mainWindow.h new file mode 100644 index 0000000..6c55081 --- /dev/null +++ b/mainWindow.h @@ -0,0 +1,16 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +//^#===================================================== MainWindow +class MainWindow : public QMainWindow{ + Q_OBJECT +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +}; + + +#endif // MAINWINDOW_H \ No newline at end of file diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..9d4be02 --- /dev/null +++ b/test.cpp @@ -0,0 +1,284 @@ +#include "macro.h" +#include "ClassData.h" +#include "ClassDigitizer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include /** struct timeval, select() */ +#include /** tcgetattr(), tcsetattr() */ +#include + +static struct termios g_old_kbd_mode; + +static void cooked(void){ + tcsetattr(0, TCSANOW, &g_old_kbd_mode); +} + +static void uncooked(void){ + struct termios new_kbd_mode; + /** put keyboard (stdin, actually) in raw, unbuffered mode */ + tcgetattr(0, &g_old_kbd_mode); + memcpy(&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios)); + new_kbd_mode.c_lflag &= ~(ICANON | ECHO); + new_kbd_mode.c_cc[VTIME] = 0; + new_kbd_mode.c_cc[VMIN] = 1; + tcsetattr(0, TCSANOW, &new_kbd_mode); +} + +static void raw(void){ + + static char init; + if(init) return; + /** put keyboard (stdin, actually) in raw, unbuffered mode */ + uncooked(); + /** when we exit, go back to normal, "cooked" mode */ + atexit(cooked); + + init = 1; +} + +int keyboardhit(){ + + struct timeval timeout; + fd_set read_handles; + int status; + + raw(); + /** check stdin (fd 0) for activity */ + FD_ZERO(&read_handles); + FD_SET(0, &read_handles); + timeout.tv_sec = timeout.tv_usec = 0; + status = select(0 + 1, &read_handles, NULL, NULL, &timeout); + if(status < 0){ + printf("select() failed in keyboardhit()\n"); + exit(1); + } + return (status); +} + +int getch(void){ + unsigned char temp; + raw(); + /** stdin = fd 0 */ + if(read(0, &temp, 1) != 1) return 0; + return temp; +} + +//^====================================== + +int main(int argc, char* argv[]){ + + /**////##################### Demo for loading and change setting without open a digitizer + + /** + Digitizer * dig = new Digitizer(); + dig->OpenDigitizer(0, 1, false, true); + dig->LoadSettingBinaryToMemory("expDir/settings/setting_323.bin"); + + + //dig->ProgramPHABoard(); + //dig->OpenSettingBinary("setting_323.bin"); + //dig->ReadAllSettingsFromBoard(); + + //dig->PrintSettingFromMemory(); + //dig->StopACQ(); + + //dig->WriteRegister(Register::DPP::SoftwareClear_W, 1); + + printf("========== %d \n", dig->ReadSettingFromFile(Register::DPP::MaxAggregatePerBlockTransfer)); + + + ///dig->SaveSettingAsText("haha.txt"); + ///std::remove("Test_323_139_000.fsu"); + //printf("========== %d \n", dig->ReadRegister(Register::DPP::MaxAggregatePerBlockTransfer)); + + delete dig; + + /** + {///============ Checking the buffer size calculation + unsigned short B = 10; /// BLT + unsigned short Eg = 511; /// Event / dual channel + bool DT = 1; /// dual trace + bool E2 = 1; /// extra 2; + bool Wr = 1; /// wave record; + unsigned short AP2 = 0; /// 00 = input, 01 = Threshold, 10 = Trapezoid - Baseline, 11 = baseline + unsigned short AP1 = 1; /// 00 = input, 01 = RC-CR, 10 = RC-CR2, 11 = Trapezoid + unsigned short DP1 = 0x0000; /// peaking, + unsigned short RL = 100; /// record Length + unsigned short AO = 0x0; + + for( int i = 0; i < dig->GetNChannel(); i++){ + dig->WriteRegister(Register::DPP::NumberEventsPerAggregate_G, Eg, i); + dig->WriteRegister(Register::DPP::RecordLength_G, RL, i); + } + dig->WriteRegister(Register::DPP::MaxAggregatePerBlockTransfer, B); + dig->WriteRegister(Register::DPP::AggregateOrganization, AO); + + uint32_t bit = 0x0C0115; + bit += (DT << 11); + bit += (AP1 << 12); + bit += (AP2 << 14); + bit += (Wr << 16); + bit += (E2 << 17); + bit += (DP1 << 20); + + printf("---- Bd Config : 0x%08X \n", bit); + + dig->WriteRegister(Register::DPP::BoardConfiguration, bit); + + unsigned int bSize = dig->CalByteForBuffer(); + + int bbbb = (((2 + E2 + Wr*RL*4) * Eg + 2)*8 + 2)*B *4 *2 + 4 * 4; + printf("=========== exp Buffer size : %8u byte \n", bbbb); + + usleep(1e6); + + ///using CAEN method + char * buffer = NULL; + uint32_t size; + CAEN_DGTZ_MallocReadoutBuffer(dig->GetHandle(), (char **)& buffer, &size); + + printf("CAEN calculated Buffer Size : %8u byte = %.2f MB \n", size, size/1024./1024.); + printf(" diff : %8u byte \n", size > 2*bSize ? size - 2*bSize : 2*bSize - size); + + delete buffer; + }/**/ + + //dig->GetData()->SetSaveWaveToMemory(true); + + //dig->StartACQ(); + // + //for( int i = 0; i < 60; i++){ + // usleep(500*1000); + // dig->ReadData(); + // printf("------------------- %d\n", i); + // unsigned long time1 = get_time(); + // dig->GetData()->DecodeBuffer(false,0); + // unsigned long time2 = get_time(); + // printf("********************* decode time : %lu usec\n", time2-time1); + // dig->GetData()->PrintStat(); + // //dig->GetData()->SaveBuffer("Test"); + //} + // + //dig->StopACQ(); + + + /**///##################### test with 2 digitizers + + /** + const int nBoard = 2; + Digitizer **dig = new Digitizer *[nBoard]; + + for( int i = 0 ; i < nBoard; i++){ + int board = i % 3; + int port = i/3; + dig[i] = new Digitizer(board, port, false, true); + dig[i]->OpenSettingBinary("setting_" + to_string(dig[i]->GetSerialNumber()) + ".bin"); + dig[i]->LoadSettingBinaryToMemory("setting_" + to_string(dig[0]->GetSerialNumber()) + ".bin"); + } + + dig[0]->SaveSettingAsText("haha.txt"); + + + + delete dig[0]; + delete dig[1]; + + TApplication * app = new TApplication("app", &argc, argv); + TCanvas * canvas = new TCanvas("c", "haha", 1200, 400); + canvas->Divide(3, 1); + + TH1F * h1 = new TH1F("h1", "count", dig[0]->GetNChannel(), 0, dig[0]->GetNChannel()); + TH1F * h2 = new TH1F("h2", "energy ch-0", 400, 0, 40000); + + TGraph * g1 = new TGraph(); + + canvas->cd(1); h1->Draw("hist"); + canvas->cd(2); h2->Draw(); + canvas->cd(3); g1->Draw("AP"); + + Data * data = dig[0]->GetData(); + data->AllocateMemory(); + + remove("test.bin"); + + dig[0]->StartACQ(); + + std::vector haha ; + + uint32_t PreviousTime = get_time(); + uint32_t CurrentTime = 0; + uint32_t ElapsedTime = 0; + + while(true){ + + if(keyboardhit()) { + break; + } + + usleep(50000); + dig[0]->ReadData(); + + if( data->nByte > 0 ){ + data->SaveBuffer("test"); + data->DecodeBuffer(0); + + unsigned short nData = data->NumEvents[0]; //channel-0 + haha = data->Waveform1[0][nData-1]; + for( int i = 0; i < waveFormLength; i++) g1->SetPoint(i, i*ch2ns, haha[i]); + + canvas->cd(3); g1->Draw("AP"); + + canvas->Modified(); + canvas->Update(); + gSystem->ProcessEvents(); + + } + + CurrentTime = get_time(); + ElapsedTime = CurrentTime - PreviousTime; /// milliseconds + + if( ElapsedTime > 1000 ){ + int temp = system("clear"); + data->PrintStat(); + + for(int i = 0; i < dig[0]->GetNChannel(); i++){ + h1->Fill(i, data->NumEvents[i]); + } + + for( int i = 0; i < data->NumEvents[0]; i++){ + h2->Fill( data->Energy[0][i]); + } + data->ClearData(); + + canvas->cd(1); h1->Draw("hist"); + canvas->cd(2); h2->Draw(); + canvas->Modified(); + canvas->Update(); + gSystem->ProcessEvents(); + + PreviousTime = CurrentTime; + + printf("Press any key to Stop\n"); + } + + + } + + dig[0]->StopACQ(); + + app->Run(); + + delete [] dig; + + /*********************/ + + return 0; +} diff --git a/test_indep.cpp b/test_indep.cpp new file mode 100644 index 0000000..cd5af37 --- /dev/null +++ b/test_indep.cpp @@ -0,0 +1,477 @@ +#include +#include +#include +#include +#include ///memset +#include ///cout +#include + +#include "CAENDigitizer.h" +#include "CAENDigitizerType.h" +#include "macro.h" +#include "RegisterAddress.h" + +using namespace std; + +void PrintChannelSettingFromDigitizer(int handle, int ch, float ch2ns){ + + printf("\e[33m================================================\n"); + printf("================ Setting for channel %d \n", ch); + printf("================================================\e[0m\n"); + ///DPP algorithm Control + uint32_t * value = new uint32_t[16]; + CAEN_DGTZ_ReadRegister(handle, Register::DPP::DPPAlgorithmControl + (ch << 8), value); + printf(" 32 28 24 20 16 12 8 4 0\n"); + printf(" | | | | | | | | |\n"); + cout <<" DPP algorithm Control : 0b" << bitset<32>(value[0]); + printf(" = 0x%x\n", value[0]); + + int trapRescaling = int(value[0]) & 0x1f ; + int polarity = int(value[0] >> 16) & 0x1; /// in bit[16] + int baseline = int(value[0] >> 20) & 0x7; /// in bit[22:20] + int NsPeak = int(value[0] >> 12) & 0x3; /// in bit[13:12] + int rollOver = int(value[0] >> 26) & 0x1; + int pileUp = int(value[0] >> 27) & 0x1; + + ///DPP algorithm Control 2 + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::DPPAlgorithmControl2_G + (ch << 8), value); + cout <<" DPP algorithm Control 2: 0b" << bitset<32>(value[0]) ; + printf(" = 0x%x\n", value[0]); + + int extras2WordOption = int(value[0] >> 8) & 0x3; + string extra2WordOptStr = ""; + switch (extras2WordOption){ + case 0 : extra2WordOptStr = "[0:15] Baseline *4 [16:31] Extended Time Stamp"; break; + case 2 : extra2WordOptStr = "[0:9] Fine Time Stamp [10:15] Reserved [16:31] Extended Time Stamp"; break; + case 4 : extra2WordOptStr = "[0:15] Total Trigger Counter [16:31] Lost Trigger Counter"; break; + case 5 : extra2WordOptStr = "[0:15] Event After the Zero Crossing [16:31] Event Before the Zero Crossing"; break; + default: extra2WordOptStr = "Reserved"; break; + } + + printf(" ch2ns : %.0f ns\n", ch2ns); + + printf("==========----- input \n"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::RecordLength_G + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Record Length", ((value[0] * 8) & MaxRecordLength), ((value[0] * 8) & MaxRecordLength) * ch2ns); ///Record length + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PreTrigger + (ch << 8), value); printf("%24s %5d samples = %5.0f ns \n", "Pre-tigger", value[0] * 4, value[0] * 4 * ch2ns); ///Pre-trigger + printf("%24s %5.0f samples, DPP-[20:22]\n", "baseline mean", pow(4, 1 + baseline)); ///Ns baseline + CAEN_DGTZ_ReadRegister(handle, Register::DPP::ChannelDCOffset + (ch << 8), value); printf("%24s %.2f %% \n", "DC offset", 100.0 - value[0] * 100./ 0xFFFF); ///DC offset + CAEN_DGTZ_ReadRegister(handle, Register::DPP::InputDynamicRange + (ch << 8), value); printf("%24s %.1f Vpp \n", "input Dynamic", value[0] == 0 ? 2 : 0.5); ///InputDynamic + printf("%24s %s, DPP-[16]\n", "polarity", polarity == 0 ? "Positive" : "negative"); ///Polarity + + printf("==========----- discriminator \n"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::TriggerThreshold + (ch << 8), value); printf("%24s %4d LSB\n", "Threshold", value[0]); ///Threshold + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::TriggerHoldOffWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "trigger hold off", value[0], value[0] * 4 * ch2ns); ///Trigger Hold off + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::RCCR2SmoothingFactor + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. smoothing", (value[0] & 0x1f) * 2, (value[0] & 0x1f) * 2 * ch2ns ); ///Fast Discriminator smoothing + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::ShapedTriggerWidth + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Fast Dis. output width", value[0], value[0] * 4 * ch2ns); ///Fast Dis. output width + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::InputRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Input rise time ", value[0], value[0] * 4 * ch2ns); ///Input rise time + + printf("==========----- Trapezoid \n"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::TrapezoidRiseTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. rise time", value[0], value[0] * 4 * ch2ns); ///Trap. rise time, 2 for 1 ch to 2ns + int riseTime = value[0] * 4 * ch2ns; + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::TrapezoidFlatTop + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Trap. flat time", value[0], value[0] * 4 * ch2ns); ///Trap. flat time + int flatTopTime = value[0] * 4 * ch2ns; + double shift = log(riseTime * flatTopTime ) / log(2) - 2; + printf("%24s %4d bit =? %.1f = Ceil( Log(rise [ns] x decay [ns])/Log(2) ), DPP-[0:5]\n", "Trap. Rescaling", trapRescaling, shift ); ///Trap. Rescaling Factor + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::DecayTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Decay time", value[0], value[0] * 4 * ch2ns); ///Trap. pole zero + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::PeakingTime + (ch << 8), value); printf("%24s %4d samples, %5.0f ns = %.2f %% of FlatTop\n", "Peaking time", value[0], value[0] * 4 * ch2ns, value[0] * 400. * ch2ns / flatTopTime ); ///Peaking time + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::PeakHoldOff + (ch << 8), value); printf("%24s %4d samples, %5.0f ns \n", "Peak hole off", value[0], value[0] * 4 *ch2ns ); ///Peak hold off + printf("%24s %4.0f samples, DPP-[12:13]\n", "Peak mean", pow(4, NsPeak)); ///Ns peak + + printf("==========----- Other \n"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::FineGain + (ch << 8), value); printf("%24s %d = 0x%x\n", "Energy fine gain", value[0], value[0]); ///Energy fine gain + CAEN_DGTZ_ReadRegister(handle, Register::DPP::ChannelADCTemperature_R + (ch << 8), value); printf("%24s %d C\n", "Temperature", value[0]); ///Temperature + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::RiseTimeValidationWindow + (ch << 8), value); printf("%24s %.0f ns \n", "RiseTime Vaild Win.", value[0] * ch2ns); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::PHA::ChannelStopAcquisition + (ch << 8), value); printf("%24s %d = %s \n", "Stop Acq bit", value[0] & 1 , (value[0] & 1 ) == 0 ? "Run" : "Stop"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::ChannelStatus_R + (ch << 8), value); printf("%24s 0x%x \n", "Status bit", (value[0] & 0xff) ); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::AMCFirmwareRevision_R + (ch << 8), value); printf("%24s 0x%x \n", "AMC firmware rev.", value[0] ); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::VetoWidth + (ch << 8), value); printf("%24s 0x%x \n", "VetoWidth bit", value[0] ); + printf("%24s %d = %s\n", "RollOverFlag, DPP-[26]", rollOver, rollOver ? "enable" : "disable" ); + printf("%24s %d = %s\n", "Pile-upFlag, DPP-[27]", pileUp, pileUp ? "enable" : "disable" ); + printf("%24s %d, %s \n", "Extra2 opt, DPP2-[8:10]", extras2WordOption, extra2WordOptStr.c_str()); + printf("========= events storage and transfer\n"); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::NumberEventsPerAggregate_G + (ch << 8), value); printf("%24s %d \n", "Event Aggregate", value[0] & 0x3FF); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::AggregateOrganization, value); printf("%24s %d \n", "Buffer Division", ((value[0] & 0x007) < 2 ? 0 : (int)pow(2, value[0] & 7))); + CAEN_DGTZ_ReadRegister(handle, Register::DPP::MaxAggregatePerBlockTransfer , value); printf("%24s %d \n", "Num of Agg. / ReadData", value[0] & 0x1FF); + + printf("========================================= end of ch-%d\n", ch); + +} + + +void PrintBoardConfiguration(int handle){ + printf("\e[33m================================================\n"); + printf("================ Setting for Board \n"); + printf("================================================\e[0m\n"); + uint32_t * value = new uint32_t[1]; + CAEN_DGTZ_ReadRegister(handle, (uint32_t) Register::BoardConfiguration, value); + printf(" 32 28 24 20 16 12 8 4 0\n"); + printf(" | | | | | | | | |\n"); + cout <<" Board Configuration : 0b" << bitset<32>(value[0]) << endl; + printf(" : 0x%x\n", value[0]); + + printf(" Bit[ 0] = %d = Auto Data Flush \n", value[0] & 0x1); + printf(" Bit[ 1] = %d = Decimated waveform \n", (value[0] >> 1) & 0x1 ); + printf(" Bit[ 2] = %d = Trigger propagation \n", (value[0] >> 2) & 0x1 ); + printf(" Bit[ 3:10] = %d = must be 001 0001 0 = 22 \n", (value[0] >> 3) & 0xFF ); + printf(" Bit[ 11] = %d = Dual Trace \n", (value[0] >> 11) & 0x1 ); + printf(" Bit[12:13] = %d = Analog probe 1 : ",((value[0] >> 12) & 0x3 )); + switch ( ((value[0] >> 12) & 0x3 ) ){ + case 0 : printf("input\n"); break; + case 1 : printf("RC-CR (1st derivative)\n");break; + case 2 : printf("RC-CR2 (2nd derivative)\n"); break; + case 3 : printf("Trapezoid \n"); break; + } + printf(" Bit[14:15] = %d = Analog probe 2 : ", ((value[0] >> 14) & 0x3 )); + switch ( ((value[0] >> 14) & 0x3 ) ){ + case 0 : printf("input\n"); break; + case 1 : printf("Threshold\n"); break; + case 2 : printf("Trapezoid - Baseline\n"); break; + case 3 : printf("baseline.\n"); break; + } + printf(" Bit[ 16] = %d = WaveForm Recording \n",((value[0] >> 16) & 0x1 ) ); + printf(" Bit[ 17] = %d = Extras 2 word enable \n", ((value[0] >> 17) & 0x1 )); + printf(" Bit[ 18] = %d = Record Time Stamp \n", ((value[0] >> 18) & 0x1 )); + printf(" Bit[ 19] = %d = Record Energy \n", ((value[0] >> 19) & 0x1 )); + printf(" Bit[20:23] = %d = Digital Virtual probe 1 : ", ((value[0] >> 20) & 0x7 )); + switch (((value[0] >> 20) & 0xF )) { + case 0: printf("Peaking, shows where the energy is calculated; \n"); break; + case 1: printf("”Armed”, digital input showing where the RC‐CR2 crosses the Threshold\n"); + case 2: printf("”Peak Run”, starts with the trigger and last for the whole event\n"); + case 3: printf("”Pile‐up”, shows where a pile‐up event occurred\n"); + case 4: printf("”Peaking”, shows where the energy is calculated\n"); + case 5: printf("”TRG Validation Win”, digital input showing the trigger validation acceptance window TVAW\n"); + case 6: printf("”Baseline freeze”, shows where the algorithm stops calculating the baseline and its value is frozen\n"); + case 7: printf("”TRG Holdoff”, shows the trigger hold‐off parameter\n"); + case 8: printf("”TRG Validation”, shows the trigger validation signal TRG_VAL \n"); + case 9: printf("”Acq Busy”, this is 1 when the board is busy (saturated input signal or full memory board) or there is a veto\n"); + case 10: printf("”Zero Cross. Win.”, shows the RT Discrimination Width\n"); + case 11: printf("”Ext TRG”, shows the external trigger, when available\n"); + case 12: printf("”Busy”, shows when the memory board is full.\n"); + } + printf(" Bit[26:28] = %d = Digital Virtual probe 2 : ", ((value[0] >> 26) & 0x7 )); + if( ((value[0] >> 26) & 0x7 ) == 0 ) { + printf("Trigger\n"); + }else{ + printf("Reserved\n"); + } + printf("====================================== \n"); +} + +unsigned int ReadBuffer(unsigned int nWord, char * buffer, bool verbose = true){ + if( buffer == NULL ) return 0; + + unsigned int word = 0; + for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i); + if( verbose) printf("%d | 0x%08x\n", nWord, word); + return word; +} + + + +int main(int argc, char* argv[]){ + + + ///============== open digitizer + int handle; + + printf("======== open board\n"); + int ret = CAEN_DGTZ_OpenDigitizer(CAEN_DGTZ_OpticalLink, 1, 0, 0, &handle); + + CAEN_DGTZ_BoardInfo_t BoardInfo; + ret = (int) CAEN_DGTZ_GetInfo(handle, &BoardInfo); + int NChannel = BoardInfo.Channels; + uint32_t channelMask = 0xFFFF; + float ch2ns = 4.0; + switch(BoardInfo.Model){ + case CAEN_DGTZ_V1730: ch2ns = 2.0; break; ///ns -> 500 MSamples/s + case CAEN_DGTZ_V1725: ch2ns = 4.0; break; ///ns -> 250 MSamples/s + } + unsigned int ADCbits = BoardInfo.ADC_NBits; + + if( ret != 0 ) { printf("==== open digitizer\n"); return 0;} + + ///======= reset + ret = CAEN_DGTZ_Reset(handle); + + printf("======== program board\n"); + + ///ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, CAEN_DGTZ_DPP_ACQ_MODE_List, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime); + ///ret |= CAEN_DGTZ_SetDPPAcquisitionMode(handle, CAEN_DGTZ_DPP_ACQ_MODE_Mixed, CAEN_DGTZ_DPP_SAVE_PARAM_EnergyAndTime); /// Board Configure can do that + + /// Set the number of samples for each waveform + ret = CAEN_DGTZ_WriteRegister(handle, Register::DPP::RecordLength_G + 0x7000, 625); + if( ret != 0 ) { printf("==== set Record Length.\n"); return 0;} + + + //ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration, 0x4F8115); // with wave + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration, 0x4E8115); // with-out wave + + + /// Set the digitizer acquisition mode (CAEN_DGTZ_SW_CONTROLLED or CAEN_DGTZ_S_IN_CONTROLLED) + ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command + + /// Set the I/O level (CAEN_DGTZ_IOLevel_NIM or CAEN_DGTZ_IOLevel_TTL) + ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM); + + /** Set the digitizer's behaviour when an external trigger arrives: + CAEN_DGTZ_TRGMODE_DISABLED: do nothing + CAEN_DGTZ_TRGMODE_EXTOUT_ONLY: generate the Trigger Output signal + CAEN_DGTZ_TRGMODE_ACQ_ONLY = generate acquisition trigger + CAEN_DGTZ_TRGMODE_ACQ_AND_EXTOUT = generate both Trigger Output and acquisition trigger + see CAENDigitizer user manual, chapter "Trigger configuration" for details */ + ret |= CAEN_DGTZ_SetExtTriggerInputMode(handle, CAEN_DGTZ_TRGMODE_ACQ_ONLY); + if( ret != 0 ) { printf("==== CAEN_DGTZ_SetExtTriggerInputMode.\n"); return 0;} + + ret = CAEN_DGTZ_SetChannelEnableMask(handle, 0xFFFF); + if( ret != 0 ) { printf("==== CAEN_DGTZ_SetChannelEnableMask.\n"); return 0;} + + ret = CAEN_DGTZ_SetNumEventsPerAggregate(handle, 0); + if( ret != 0 ) { printf("==== CAEN_DGTZ_SetNumEventsPerAggregate. %d\n", ret); return 0;} + + //ret = CAEN_DGTZ_SetDPPEventAggregation(handle, 0, 0); + //if( ret != 0 ) { printf("==== CAEN_DGTZ_SetDPPEventAggregation. %d\n", ret); return 0;} + + + /** Set the mode used to syncronize the acquisition between different boards. + In this example the sync is disabled */ + ret = CAEN_DGTZ_SetRunSynchronizationMode(handle, CAEN_DGTZ_RUN_SYNC_Disabled); + if( ret != 0 ) { printf("==== set board error.\n"); return 0;} + + printf("======== program Channels\n"); + ///CAEN_DGTZ_DPP_PHA_Params_t DPPParams; + ///memset(&DPPParams, 0, sizeof(CAEN_DGTZ_DPP_PHA_Params_t)); + ///for(int i = 0; i < NChannel; i++){ + /// DPPParams.M[i] = 5000; /// decay time [ns] + /// DPPParams.m[i] = 992; /// flat-top [ns] + /// DPPParams.k[i] = 96; /// rise-time [ns] + /// DPPParams.ftd[i] = 192; /// flat-top delay, peaking time [ns] + /// DPPParams.a[i] = 4; /// Trigger Filter smoothing factor, 1, 2, 3, 4, 16, 32 + /// DPPParams.b[i] = 96; /// input rise time [ns] + /// DPPParams.thr[i] = 100; /// Threshold [LSB] + /// DPPParams.nsbl[i] = 3; /// Baseline samples, 0 = 0, when > 0, pow(4, n+1) /// in DPP Control + /// DPPParams.nspk[i] = 2; /// peak samples, 4^n /// in DPP Control + /// DPPParams.pkho[i] = 992 ; /// peak hold off [ns] + /// DPPParams.trgho[i] = 480 ; /// trigger hold off [ns] + /// DPPParams.twwdt[i] = 0 ; /// rise time validation window, 0x1070 + /// DPPParams.trgwin[i] = 0 ; /// trigger coincident window + /// DPPParams.dgain[i] = 0; /// digial gain for digial probe, 2^n + /// DPPParams.enf[i] = 1 ; /// energy normalization factor (fine gain?) + /// DPPParams.decimation[i] = 0 ; /// waveform decimation, 2^n, when n = 0, disable + /// DPPParams.blho[i] = 0; /// not use + ///} + ///ret = CAEN_DGTZ_SetDPPParameters(handle, channelMask, &DPPParams); + + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::DecayTime + 0x7000 , 5000 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TrapezoidFlatTop + 0x7000 , 62 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TrapezoidRiseTime + 0x7000 , 6 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::PeakingTime + 0x7000 , 6 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::RCCR2SmoothingFactor + 0x7000 , 4 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::InputRiseTime + 0x7000 , 6 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TriggerThreshold + 0x7000 , 64 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::PeakHoldOff + 0x7000 , 0x3E ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::TriggerHoldOffWidth + 0x7000 , 0x3E ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PHA::RiseTimeValidationWindow + 0x7000 , 0x0 ); + + + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::ChannelDCOffset + 0x7000 , 0xEEEE ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::PreTrigger + 0x7000 , 124 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::InputDynamicRange + 0x7000 , 0x0 ); + + + //ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::BoardConfiguration , 0x10E0114 ); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::NumberEventsPerAggregate_G + 0x7000, 5); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::AggregateOrganization, 0); + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::MaxAggregatePerBlockTransfer, 40); + + ret |= CAEN_DGTZ_WriteRegister(handle, Register::DPP::DPPAlgorithmControl + 0x7000, 0xe30200f); + + + if( ret != 0 ) { printf("==== set channels error.\n"); return 0;} + + printf("================ allowcate memory \n"); + + int Nb; /// number of byte + char *buffer = NULL; /// readout buffer + uint32_t NumEvents[MaxNChannels]; + uint32_t AllocatedSize, BufferSize; + CAEN_DGTZ_DPP_PHA_Event_t *Events[MaxNChannels]; /// events buffer + CAEN_DGTZ_DPP_PHA_Waveforms_t *Waveform[MaxNChannels]; /// waveforms buffer + + ret = CAEN_DGTZ_MallocReadoutBuffer(handle, &buffer, &AllocatedSize); + printf("allowcated %d byte ( %d words) for buffer\n", AllocatedSize, AllocatedSize/4); + ret |= CAEN_DGTZ_MallocDPPEvents(handle, reinterpret_cast(&Events), &AllocatedSize) ; + printf("allowcated %d byte for Events\n", AllocatedSize); + for( int i = 0 ; i < NChannel; i++){ + ret |= CAEN_DGTZ_MallocDPPWaveforms(handle, reinterpret_cast(&Waveform[i]), &AllocatedSize); + printf("allowcated %d byte for waveform-%d\n", AllocatedSize, i); + } + + if( ret != 0 ) { printf("==== memory allocation error.\n"); return 0;} + + PrintBoardConfiguration(handle); + PrintChannelSettingFromDigitizer(handle, 4, ch2ns); + + printf("============ Start ACQ \n"); + CAEN_DGTZ_SWStartAcquisition(handle); + + sleep(1); + + printf("============ Read Data \n"); + + ret = CAEN_DGTZ_ReadData(handle, CAEN_DGTZ_SLAVE_TERMINATED_READOUT_MBLT, buffer, &BufferSize); + if (ret) { + printf("Error when reading data %d\n", ret); + return 0; + } + Nb = BufferSize; + if (Nb == 0 || ret) { + return 0; + } + ret |= (CAEN_DGTZ_ErrorCode) CAEN_DGTZ_GetDPPEvents(handle, buffer, BufferSize, reinterpret_cast(&Events), NumEvents); + if (ret) { + printf("Error when getting events from data %d\n", ret); + return 0; + } + + for (int ch = 0; ch < NChannel; ch++) { + if( NumEvents[ch] > 0 ) printf("------------------------ %d, %d\n", ch, NumEvents[ch]); + for (int ev = 0; ev < NumEvents[ch]; ev++) { + ///TrgCnt[ch]++; + + if( ev == 0 ){ + printf("%3s, %6s, %13s | %5s | %13s | %13s \n", "ev", "energy", "timetag", "ex2", "rollover", "timeStamp"); + } + + if (Events[ch][ev].Energy > 0 && Events[ch][ev].TimeTag > 0 ) { + ///ECnt[ch]++; + unsigned long long timetag = (unsigned long long) Events[ch][ev].TimeTag; + unsigned long long rollOver = Events[ch][ev].Extras2 >> 16; + rollOver = rollOver << 31; + timetag += rollOver ; + + printf("%3d, %6d, %13lu | %5u | %13llu | %13llu \n", + ev, Events[ch][ev].Energy, + Events[ch][ev].TimeTag, + Events[ch][ev].Extras2 , + rollOver >> 32, timetag); + + } else { /// PileUp + ///PurCnt[ch]++; + } + + } /// loop on events + } /// loop on channels + + printf("============ Stop ACQ \n"); + ret |= CAEN_DGTZ_ClearData(handle); + + + printf("============= Read Buffer \n"); + + unsigned int nw = 0; + + do{ + printf("######################################### Board Agg.\n"); + unsigned int word = ReadBuffer(nw, buffer); + if( ( (word >> 28) & 0xF ) == 0xA ) { /// start of Board Agg + unsigned int nWord = word & 0x0FFFFFFF ; + printf(" number of words in this Agg : %d \n", nWord); + + nw = nw + 1; word = ReadBuffer(nw, buffer); + unsigned int BoardID = ((word >> 27) & 0x1F); + bool BoardFailFlag = ((word >> 26) & 0x1 ); + unsigned int ChannelMask = ( word & 0xFF ) ; + printf("Board ID : %d, FailFlag = %d, ChannelMask = 0x%x\n", BoardID, BoardFailFlag, ChannelMask); + + nw = nw + 2; + unsigned int AggCounter = ReadBuffer(nw, buffer); + printf("Agg Counter : %d \n", AggCounter); + + + + for( int chMask = 0; chMask < 8 ; chMask ++ ){ + if( ((ChannelMask >> chMask) & 0x1 ) == 0 ) continue; + printf("---------------------- Dual Channel Block : %d\n", chMask *2 ); + nw = nw + 1; word = ReadBuffer(nw, buffer); + bool hasFormatInfo = ((word >> 31) & 0x1); + unsigned int aggSize = ( word & 0x3FFFFFF ) ; + printf(" size : %d \n", aggSize); + unsigned int nSample = 0; /// wave form; + unsigned int nEvents = 0; + if( hasFormatInfo ){ + nw = nw + 1; word = ReadBuffer(nw, buffer); + nSample = ( word & 0xFFFF ) * 8; + unsigned int digitalProbe = ( (word >> 16 ) & 0xF ); + unsigned int analogProbe2 = ( (word >> 20 ) & 0x3 ); + unsigned int analogProbe1 = ( (word >> 22 ) & 0x3 ); + unsigned int extra2Option = ( (word >> 24 ) & 0x7 ); + bool hasWaveForm = ( (word >> 27 ) & 0x1 ); + bool hasExtra2 = ( (word >> 28 ) & 0x1 ); + bool hasTimeStamp = ( (word >> 29 ) & 0x1 ); + bool hasEnergy = ( (word >> 30 ) & 0x1 ); + bool hasDualTrace = ( (word >> 31 ) & 0x1 ); + + printf("dualTrace : %d, Energy : %d, Time: %d, Wave : %d, Extra2: %d, Extra2Option: %d \n", + hasDualTrace, hasEnergy, hasTimeStamp, hasWaveForm, hasExtra2, extra2Option); + printf("Ana Probe 1 & 2: %d %d , Digi Probe: %d, nSample : %d \n", + analogProbe1, analogProbe2, digitalProbe, nSample); + + nEvents = aggSize / (nSample/2 + 2 + hasExtra2 ); + printf("=========== nEvents : %d \n", nEvents); + }else{ + printf("does not has format info. unable to read buffer.\n"); + break; + } + + for( int ev = 0; ev < nEvents ; ev++){ + printf("=================================== event : %d\n", ev); + nw = nw +1 ; word = ReadBuffer(nw, buffer); + bool channelTag = ((word >> 31) & 0x1); + unsigned int timeStamp = (word & 0x7FFFFFFF); + int channel = chMask*2 + channelTag; + printf("ch : %d, timeStamp %u \n", channel, timeStamp); + + ///===== read waveform + for( int wi = 0; wi < nSample/2; wi++){ + nw = nw +1 ; word = ReadBuffer(nw, buffer, false); + bool isTrigger1 = (( word >> 31 ) & 0x1 ); + unsigned int wave1 = (( word >> 16) & 0x3FFF); + + bool isTrigger0 = (( word >> 15 ) & 0x1 ); + unsigned int wave0 = ( word & 0x3FFF); + + if( ev == 0 ){ + printf("%4d| %5d, %d \n", 2*wi, wave0, isTrigger0); + printf("%4d| %5d, %d \n", 2*wi+1, wave1, isTrigger1); + } + } + + nw = nw +1 ; word = ReadBuffer(nw, buffer); + unsigned int extra2 = word; + + nw = nw +1 ; word = ReadBuffer(nw, buffer); + unsigned int extra = (( word >> 16) & 0x3FF); + unsigned int energy = (word & 0x7FFF); + bool pileUp = ((word >> 15) & 0x1); + + printf("PileUp : %d , extra : 0x%04x, energy : %d \n", pileUp, extra, energy); + + } + } + }else{ + printf("incorrect buffer header. \n"); + break; + } + nw++; + }while(true); + + + printf("=========== close Digitizer \n"); + CAEN_DGTZ_SWStopAcquisition(handle); + CAEN_DGTZ_CloseDigitizer(handle); + CAEN_DGTZ_FreeReadoutBuffer(&buffer); + CAEN_DGTZ_FreeDPPEvents(handle, reinterpret_cast(&Events)); + CAEN_DGTZ_FreeDPPWaveforms(handle, Waveform); + + return 0; +}