diff --git a/daq/ARCPacket.cxx b/daq/ARCPacket.cxx new file mode 100644 index 0000000..38b8e51 --- /dev/null +++ b/daq/ARCPacket.cxx @@ -0,0 +1,405 @@ + +#include + +#include +#include + +void ARCPacket::DataPacket_Print (uint16_t *fr, const uint16_t &size){ + + int sz_rd=0,si=0; + uint16_t r0, r1, r2, r3; + + do { + if ((*fr & PFX_14_BIT_CONTENT_MASK) == PFX_CARD_CHIP_CHAN_HIT_IX){ + r0 = GET_CARD_IX(*fr); + r1 = GET_CHIP_IX(*fr); + r2 = GET_CHAN_IX(*fr); + printf("Card %02d Chip %01d Channel %02d\n", r0, r1, r2); + fr++; + sz_rd++; + si=0; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_CHIP_CHAN_HIT_CNT) { + r0 = GET_CHIP_IX(*fr); + r1 = GET_CHAN_IX(*fr); + printf( "Chip %01d Channel_Hit_Count %02d\n", r0, r1 ); + fr++; + sz_rd++; + } else if ((*fr & PFX_0_BIT_CONTENT_MASK) == PFX_EXTD_CARD_CHIP_CHAN_HIT_IX){ + fr++; + sz_rd++; + r0 = GET_CARD_IX(*fr); + r1 = GET_CHIP_IX(*fr); + r2 = GET_CHAN_IX(*fr); + printf("Card %02d Chip %01d Channel %02d\n", r0, r1, r2); + fr++; + sz_rd++; + si=0; + } else if ((*fr & PFX_0_BIT_CONTENT_MASK) == PFX_EXTD_CARD_CHIP_CHAN_HISTO){ + fr++; + sz_rd++; + r0 = GET_CARD_IX(*fr); + r1 = GET_CHIP_IX(*fr); + r2 = GET_CHAN_IX(*fr); + printf("Card %02d Chip %01d Channel %02d\n", r0, r1, r2); + fr++; + sz_rd++; + } else if ((*fr & PFX_14_BIT_CONTENT_MASK) == PFX_CARD_CHIP_CHAN_HISTO){ + r0 = GET_CARD_IX(*fr); + r1 = GET_CHIP_IX(*fr); + r2 = GET_CHAN_IX(*fr); + printf( "Card %02d Chip %01d Channel_Histo_Index %02d\n", r0, r1, r2); + fr++; + sz_rd++; + } else if ((*fr & PFX_12_BIT_CONTENT_MASK) == PFX_ADC_SAMPLE) { + r0 = GET_ADC_DATA(*fr); + printf("%03d 0x%04x (%4d)\n", si, r0, r0); + fr++; + sz_rd++; + si++; + } else if ((*fr & PFX_12_BIT_CONTENT_MASK) == PFX_LAT_HISTO_BIN) { + r0 = GET_LAT_HISTO_BIN(*fr); + fr++; + sz_rd++; + uint32_t tmp = GetUInt32FromBufferInv(fr, sz_rd);fr+=2; + printf("%03d %03d\n", r0, tmp); + } else if ((*fr & PFX_11_BIT_CONTENT_MASK) == PFX_CHIP_LAST_CELL_READ){ + r0 = GET_CHIP_IX_LCR(*fr); + r1 = GET_LAST_CELL_READ(*fr); + printf("#Last Cell Read chip %d bin %d\n", r0, r1); + fr++; + sz_rd++; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_TIME_BIN_IX) { + r0 = GET_TIME_BIN(*fr); + printf("Time_Bin: %d\n", r0); + fr++; + sz_rd++; + si = 0; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_HISTO_BIN_IX){ + r0 = GET_HISTO_BIN(*fr); + fr++; + sz_rd++; + printf("Bin %3d Val %5d\n", r0, *fr); + fr++; + sz_rd++; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_PEDTHR_LIST){ + r0 = GET_PEDTHR_LIST_FEM(*fr); + r1 = GET_PEDTHR_LIST_ASIC(*fr); + r2 = GET_PEDTHR_LIST_MODE(*fr); + r3 = GET_PEDTHR_LIST_TYPE(*fr); + fr++; + sz_rd++; + + if (r3 == 0){ // pedestal entry + printf("# Pedestal List for FEM %02d ASIC %01d\n", r0, r1); + } else { + printf("# Threshold List for FEM %02d ASIC %01d\n", r0, r1); + } + printf("fem %02d\n", r0); + if(r2==0){ //AGET + r2 = 71; + } else { + r2 = 78; + } + + for (int j=0;j<=r2; j++){ + if(r3==0)printf("ped "); + else printf("thr "); + printf("%1d %2d 0x%04x (%4d)\n", r1, j, *fr, *fr); + fr++; + sz_rd++; + } + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_START_OF_DFRAME){ + r0 = GET_VERSION_FRAMING(*fr); + r1 = GET_SOURCE_TYPE(*fr); + r2 = GET_SOURCE_ID(*fr); + fr++; + sz_rd++; + printf("--- Start of Data Frame (V.%01d) Source type %02d id %02d --\n", r0, r1, r2); + printf("Filled with %d bytes\n", *fr); + fr++; + sz_rd++; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_START_OF_MFRAME) { + r0 = GET_VERSION_FRAMING(*fr); + r1 = GET_SOURCE_TYPE(*fr); + r2 = GET_SOURCE_ID(*fr); + printf("--- Start of Moni Frame (V.%01d) Source type %02d id %02d --\n", r0, r1, r2); + fr++; + sz_rd++; + printf("Filled with %d bytes\n", *fr); + fr++; + sz_rd++; + } else if ((*fr & PFX_9_BIT_CONTENT_MASK) == PFX_START_OF_CFRAME) { + r0 = GET_VERSION_FRAMING(*fr); + r1 = GET_SOURCE_TYPE(*fr); + r2 = GET_SOURCE_ID(*fr); + fr++; + sz_rd++; + printf("--- Start of Config Frame (V.%01d) Source type %02d id %02d --\n", r0, r1, r2); + printf("Error code: %d\n", *((short *) fr)); + fr++; + sz_rd++; + } else if ((*fr & PFX_8_BIT_CONTENT_MASK) == PFX_ASCII_MSG_LEN){ + r0 = GET_ASCII_LEN(*fr); + fr++; + sz_rd++; + printf("ASCII Msg length: %d\n",r0); + for (int j=0;j> 8) ); + fr++; + sz_rd++; + } + if ((*fr) & 0x1){// Skip the null string parity + fr++; + sz_rd++; + } + } else if ((*fr & PFX_8_BIT_CONTENT_MASK) == PFX_START_OF_EVENT) { + r0 = GET_SOE_EV_TYPE(*fr); + printf("-- Start of Event (Type %01d) --\n", r0); + fr++; + sz_rd++; + uint64_t ts = *fr; + fr++; + sz_rd++; + ts |= ( (*fr) << 16); + fr++; + sz_rd++; + ts |= ( (*fr) << 24); + fr++; + sz_rd++; + printf("Time %" PRId64 "\n", ts); + + uint32_t evC = GetUInt32FromBufferInv(fr, sz_rd);fr+=2; + printf("Event_Count %d\n", evC); + + } else if ((*fr & PFX_6_BIT_CONTENT_MASK) == PFX_END_OF_EVENT){ + r1 = GET_EOE_SOURCE_TYPE(*fr); + r2 = GET_EOE_SOURCE_ID(*fr); + //Skip one word (reserved) + fr++; + sz_rd++; + fr++; + sz_rd++; + uint32_t size_ev = ( (*fr) << 16); + fr++; + sz_rd++; + size_ev |= *fr; + fr++; + sz_rd++; + printf("----- End of Event ----- (size %d bytes)\n", size); + } else if ((*fr & PFX_2_BIT_CONTENT_MASK) == PFX_CH_HIT_CNT_HISTO) { + r0 = GET_CH_HIT_CNT_HISTO_CHIP_IX(*fr); + printf("Channel Hit Count Histogram (ASIC %d)\n", r0); + fr++; + sz_rd++; + //null word + fr++; + sz_rd++; + + fr +=HistoStat_Print (fr, sz_rd, r0); + + } else if ((*fr & PFX_0_BIT_CONTENT_MASK) == PFX_END_OF_FRAME) { + printf("----- End of Frame -----\n"); + fr++; + sz_rd++; + } else if ( *fr == PFX_NULL_CONTENT ) { + printf("null word (2 bytes)\n"); + fr++; + sz_rd++; + } else if ((*fr == PFX_DEADTIME_HSTAT_BINS) || (*fr == PFX_EVPERIOD_HSTAT_BINS)) { + if (*fr == PFX_DEADTIME_HSTAT_BINS)printf("Dead-time Histogram\n"); + else printf("Inter Event Time Histogram\n"); + fr++; + sz_rd++; + //null word + fr++; + sz_rd++; + + fr +=HistoStat_Print (fr, sz_rd, 0); + + } else if (*fr == PFX_PEDESTAL_HSTAT) { + printf("\nPedestal Histogram Statistics\n"); + fr++; + sz_rd++; + + fr+=HistoStat_Print (fr, sz_rd, 0); + + } else if (*fr == PFX_PEDESTAL_H_MD) { + fr++; + sz_rd++; + + uint32_t mean = GetUInt32FromBufferInv(fr, sz_rd);fr+=2; + uint32_t std_dev = GetUInt32FromBufferInv(fr, sz_rd);fr+=2; + printf("Mean/Std_dev : %.2f %.2f\n", (float)mean/100., (float)std_dev/100.); + + fr++; + sz_rd++; + + } else if (*fr == PFX_SHISTO_BINS) { + printf("Threshold Turn-on curve\n"); + fr++; + sz_rd++; + for(int j=0;j<16;j++){ + printf("%d ", *fr); + fr++; + sz_rd++; + } + printf("\n\n"); + } else if (*fr == PFX_CMD_STATISTICS) { + fr++; + sz_rd++; + + uint32_t tmp_i[9]; + for(int j=0;j<9;j++){tmp_i[j] = GetUInt32FromBuffer(fr, sz_rd);fr+=2;} + + printf("Server RX stat: cmd_count=%d daq_req=%d daq_timeout=%d daq_delayed=%d daq_missing=%d cmd_errors=%d\n", tmp_i[0], tmp_i[1], tmp_i[2], tmp_i[3], tmp_i[4], tmp_i[5]); + printf("Server TX stat: cmd_replies=%d daq_replies=%d daq_replies_resent=%d\n", tmp_i[6], tmp_i[7], tmp_i[8]); + } else { // No interpretable data + printf("word(%04d) : 0x%x (%d) unknown data\n", sz_rd, *fr, *fr); + fr++; + sz_rd++; + } + + } while (sz_rd < size); + + if(sz_rd > size)printf("Format error: read %d words but packet size is %d\n", sz_rd, size); + +} + +int ARCPacket::HistoStat_Print (uint16_t *fr, int &sz_rd, const uint16_t &hitCount) { + + int length=sz_rd; + + printf("Min Bin : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Max Bin : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Bin Width : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Bin Count : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Min Value : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Max Value : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + printf("Mean : %.2f\n", ((float) GetUInt32FromBuffer(fr, sz_rd)) / 100.0);fr+=2; + printf("Std Dev : %.2f\n", ((float) GetUInt32FromBuffer(fr, sz_rd)) / 100.0);fr+=2; + printf("Entries : %d\n", GetUInt32FromBuffer(fr, sz_rd));fr+=2; + // Get all bins + for (int j=0; j &buffer, TRestRawSignalEvent* sEvent, uint64_t &tS, uint32_t &ev_count){ + + bool endOfEvent = false; + //std::cout<<__PRETTY_FUNCTION__<<" "< sData(512,0); + while( (buffer.front() & PFX_12_BIT_CONTENT_MASK) == PFX_ADC_SAMPLE || + (buffer.front() & PFX_9_BIT_CONTENT_MASK ) == PFX_TIME_BIN_IX ){ + + if ((buffer.front() & PFX_9_BIT_CONTENT_MASK) == PFX_TIME_BIN_IX) { + timeBin = GET_TIME_BIN(buffer.front()); + } else if ((buffer.front() & PFX_12_BIT_CONTENT_MASK) == PFX_ADC_SAMPLE) { + if(timeBin<512)sData[timeBin] = GET_ADC_DATA(buffer.front()); + //std::cout<<"TimeBin "<AddSignal(rawSignal); + + } else if ( (buffer.front() & PFX_6_BIT_CONTENT_MASK) == PFX_END_OF_EVENT ){ + endOfEvent=true; + buffer.pop_front(); + buffer.pop_front(); + uint32_t event_size = buffer.front() & 0xFFFF; + buffer.pop_front(); + event_size |= ( buffer.front() << 16) & 0xFFFF0000; + buffer.pop_front(); + //std::cout<<"END OF EVENT with "< +#include +#include + +#include + +#define PFX_14_BIT_CONTENT_MASK 0xC000 // Mask to select 2 MSB's of prefix +#define PFX_CARD_CHIP_CHAN_HIT_IX 0xC000 // Index of Card, Chip and Channel Hit +#define PFX_CARD_CHIP_CHAN_HISTO 0x4000 // Pedestal Histogram for given Card and Chip + +#define PUT_CARD_CHIP_CHAN_HISTO(ca, as, ch) (PFX_CARD_CHIP_CHAN_HISTO | (((ca) & 0x1F) <<9) | (((as) & 0x3) <<7) | (((ch) & 0x7F) <<0)) + +// Prefix Codes for 12-bit data content +#define PFX_12_BIT_CONTENT_MASK 0xF000 // Mask to select 4 MSB's of prefix +#define PFX_ADC_SAMPLE 0x3000 // ADC sample +#define PFX_LAT_HISTO_BIN 0x2000 // latency or inter event time histogram bin + +// Prefix Codes for 11-bit data content +#define PFX_11_BIT_CONTENT_MASK 0xF800 // Mask to select 5 MSB's of prefix +#define PFX_CHIP_LAST_CELL_READ 0x1800 // Chip index (2 bit) + last cell read (9 bits) + +// Prefix Codes for 9-bit data content +#define PFX_9_BIT_CONTENT_MASK 0xFE00 // Mask to select 7 MSB's of prefix +#define PFX_TIME_BIN_IX 0x0E00 // Time-bin Index +#define PFX_HISTO_BIN_IX 0x0C00 // Histogram bin Index +#define PFX_PEDTHR_LIST 0x0A00 // List of pedestal or thresholds +#define PFX_START_OF_DFRAME 0x0800 // Start of Data Frame + 3 bit Version + 1 bit source type + 5 bit source +#define PFX_START_OF_MFRAME 0x0600 // Start of Monitoring Frame + 3 bit Version + 1 bit source type + 5 bit source +#define PFX_START_OF_CFRAME 0x0400 // Start of Configuration Frame + 3 bit Version + 1 bit source type + 5 bit source +#define PFX_CHIP_CHAN_HIT_CNT 0x1200 // Chip (2 bit) Channel hit count (7 bit) +#define PFX_FRAME_SEQ_NB 0x1000 // Sequence number for UDP frame + +#define PUT_HISTO_BIN_IX(bi) (PFX_HISTO_BIN_IX | ((bi) & 0x1FF)) +#define PUT_PEDTHR_LIST(f, a, m, t) (PFX_PEDTHR_LIST | (((f) & 0x1F)<<4) | (((a) & 0x3)<<2) | (((m) & 0x1)<<1) | (((t) & 0x1)<<0)) +#define PUT_FRAME_SEQ_NB(nb) (PFX_FRAME_SEQ_NB | ((nb) & 0x1FF)) +#define GET_FRAME_SEQ_NB(fr) ((fr) & 0x1FF) + +// Prefix Codes for 8-bit data content +#define PFX_8_BIT_CONTENT_MASK 0xFF00 // Mask to select 8 MSB's of prefix +#define PFX_ASCII_MSG_LEN 0x0100 // ASCII message length +#define PFX_START_OF_EVENT 0x0300 // Start Of Event + 2 bit event type + 1 bit source type + 5 bit source ID + +// Prefix Codes for 6-bit data content +#define PFX_6_BIT_CONTENT_MASK 0xFFC0 // Mask to select 10 MSB's of prefix +#define PFX_END_OF_EVENT 0x02C0 // End Of Event + 1 bit source type + 5 bit source ID +#define PFX_BERT_STAT 0x0280 // RX BERT Statistics + 1 bit source + 5 bit ID + +// Prefix Codes for 4-bit data content +#define PFX_4_BIT_CONTENT_MASK 0xFFF0 // Mask to select 12 MSB's of prefix +#define PFX_START_OF_EVENT_MINOS 0x00F0 // Start of Event + 1 bit free + Event Trigger Type +#define PFX_END_OF_EVENT_MINOS 0x00E0 // End of Event + 4 MSB of size +#define PFX_EXTD_CARD_CHIP_LAST_CELL_READ 0x00D0 // Last Cell Read + 4 bit Card/Chip index followed by 16-bit last cell value + +// Prefix Codes for 2-bit data content +#define PFX_2_BIT_CONTENT_MASK 0xFFFC // Mask to select 14 MSB's of prefix +#define PFX_CH_HIT_CNT_HISTO 0x007C // Channel Hit Count Histogram + +// Prefix Codes for 1-bit data content +#define PFX_1_BIT_CONTENT_MASK 0xFFFE // Mask to select 15 MSB's of prefix + +// Prefix Codes for 0-bit data content +#define PFX_0_BIT_CONTENT_MASK 0xFFFF // Mask to select 16 MSB's of prefix +#define PFX_EXTD_CARD_CHIP_CHAN_H_MD 0x0012 // Header for pedestal histogram of one channel - mean and std deviation +#define PFX_EXTD_CARD_CHIP_CHAN_HIT_IX 0x0011 // Header for data of one channel +#define PFX_EXTD_CARD_CHIP_CHAN_HISTO 0x0010 // Header for pedestal histogram of one channel +#define PFX_END_OF_FRAME 0x000F // End of Frame (any type) +#define PFX_DEADTIME_HSTAT_BINS 0x000E // Deadtime statistics and histogram +#define PFX_PEDESTAL_HSTAT 0x000D // Pedestal histogram statistics +#define PFX_PEDESTAL_H_MD 0x000C // Pedestal histogram Mean and Deviation +#define PFX_SHISTO_BINS 0x000B // Hit S-curve histogram +#define PFX_CMD_STATISTICS 0x000A // Command server statistics +#define PFX_START_OF_BUILT_EVENT 0x0009 // Start of built event +#define PFX_END_OF_BUILT_EVENT 0x0008 // End of built event +#define PFX_EVPERIOD_HSTAT_BINS 0x0007 // Inter Event Time statistics and histogram +#define PFX_SOBE_SIZE 0x0006 // Start of built event + Size +#define PFX_LONG_ASCII_MSG 0x0005 // Long ASCII message + Size (16-bit) +#define PFX_EXTD_PEDTHR_LIST 0x0004 // Extended Pedestal Threshold List + +#define PFX_NULL_CONTENT 0x0000 // Null content + +#define PUT_EXTD_PEDTHR_LIST(f, a, m, t) ((((f) & 0x1F)<<6) | (((a) & 0xF)<<2) | (((m) & 0x1)<<1) | (((t) & 0x1)<<0)) +#define GET_EXTD_PEDTHR_LIST_FEM(w) (((w) & 0x07C0) >> 6) +#define GET_EXTD_PEDTHR_LIST_ASIC(w) (((w) & 0x003C) >> 2) +#define GET_EXTD_PEDTHR_LIST_MODE(w) (((w) & 0x0002) >> 1) +#define GET_EXTD_PEDTHR_LIST_TYPE(w) (((w) & 0x0001) >> 0) + +// Macros to extract 14-bit data content +#define GET_CARD_IX(w) (((w) & 0x3E00) >> 9) +#define GET_CHIP_IX(w) (((w) & 0x0180) >> 7) +#define GET_CHAN_IX(w) (((w) & 0x007F) >> 0) + +// Macros to extract 12-bit data content +#define GET_ADC_DATA(w) (((w) & 0x0FFF) >> 0) +#define GET_LAT_HISTO_BIN(w) (((w) & 0x0FFF) >> 0) +#define PUT_LAT_HISTO_BIN(w) (PFX_LAT_HISTO_BIN | (((w) & 0x0FFF) >> 0)) + +// Macros to extract 11-bit data content +#define GET_LAST_CELL_READ(w) (((w) & 0x01FF) >> 0) +#define GET_CHIP_IX_LCR(w) (((w) & 0x0600) >> 9) + +// Macros to extract 9-bit data content +#define GET_TIME_BIN(w) (((w) & 0x01FF) >> 0) +#define GET_HISTO_BIN(w) (((w) & 0x01FF) >> 0) +#define GET_PEDTHR_LIST_FEM(w) (((w) & 0x01F0) >> 4) +#define GET_PEDTHR_LIST_ASIC(w) (((w) & 0x000C) >> 2) +#define GET_PEDTHR_LIST_MODE(w) (((w) & 0x0002) >> 1) +#define GET_PEDTHR_LIST_TYPE(w) (((w) & 0x0001) >> 0) +#define PUT_VERSION_ST_SID(w, v, t, i) (((w) & 0xFE00) | (((v) & 0x0007) << 6) | (((t) & 0x0001) << 5) | (((i) & 0x001F) << 0)) +#define GET_VERSION_FRAMING(w) (((w) & 0x01C0) >> 6) +#define GET_SOURCE_TYPE(w) (((w) & 0x0020) >> 5) +#define GET_SOURCE_ID(w) (((w) & 0x001F) >> 0) +#define GET_CHAN_HIT_CNT(w) (((w) & 0x007F) >> 0) +#define GET_CHIP_IX_CHC(w) (((w) & 0x0180) >> 7) + +// Macros to act on 8-bit data content +#define GET_ASCII_LEN(w) (((w) & 0x00FF) >> 0) +#define PUT_ASCII_LEN(w) (PFX_ASCII_MSG_LEN | ((w) & 0x00FF)) +#define GET_SOE_EV_TYPE(w) (((w) & 0x00C0) >> 6) +#define GET_SOE_SOURCE_TYPE(w) (((w) & 0x0020) >> 5) +#define GET_SOE_SOURCE_ID(w) (((w) & 0x001F) >> 0) + +// Macros to act on 6-bit data content +#define GET_EOE_SOURCE_TYPE(w) (((w) & 0x0020) >> 5) +#define GET_EOE_SOURCE_ID(w) (((w) & 0x001F) >> 0) +#define GET_BERT_STAT_SOURCE_TYPE(w) (((w) & 0x0020) >> 5) +#define GET_BERT_STAT_SOURCE_ID(w) (((w) & 0x001F) >> 0) + +// Macros to act on 4-bit data content +#define GET_EVENT_TYPE(w) (((w) & 0x0007) >> 0) +#define GET_EOE_SIZE(w) (((w) & 0x000F) >> 0) +#define GET_EXTD_CARD_CHIP_LAST_CELL_READ(w) (((w) & 0x000F) >> 0) + +// Macros to extract 2-bit data content +#define GET_CH_HIT_CNT_HISTO_CHIP_IX(w) (((w) & 0x0003) >> 0) +#define PUT_CH_HIT_CNT_HISTO_CHIP_IX(w) (PFX_CH_HIT_CNT_HISTO | ((w) & 0x0003)) + +// Macros to work with extended card/chip/channel format +#define PUT_EXTD_CARD_CHIP_CHAN(ca, as, ch) ((((ca) & 0x1F) <<11) | (((as) & 0xF) <<7) | (((ch) & 0x7F) <<0)) +#define GET_EXTD_CARD_IX(w) (((w) & 0xF800) >> 11) +#define GET_EXTD_CHIP_IX(w) (((w) & 0x0780) >> 7) +#define GET_EXTD_CHAN_IX(w) (((w) & 0x007F) >> 0) + +#define CURRENT_FRAMING_VERSION 0 + +// Definition of types of source +#define SRC_TYPE_FRONT_END 0 +#define SRC_TYPE_BACK_END 1 + +// Definition of verboseness flags used by MFrame_Print +#define FRAME_PRINT_ALL 0x00000001 +#define FRAME_PRINT_SIZE 0x00000002 +#define FRAME_PRINT_HIT_CH 0x00000004 +#define FRAME_PRINT_HIT_CNT 0x00000008 +#define FRAME_PRINT_CHAN_DATA 0x00000010 +#define FRAME_PRINT_HISTO_BINS 0x00000020 +#define FRAME_PRINT_ASCII 0x00000040 +#define FRAME_PRINT_FRBND 0x00000080 +#define FRAME_PRINT_EVBND 0x00000100 +#define FRAME_PRINT_NULLW 0x00000200 +#define FRAME_PRINT_HISTO_STAT 0x00000400 +#define FRAME_PRINT_LISTS 0x00000800 +#define FRAME_PRINT_LAST_CELL_READ 0x00001000 +#define FRAME_PRINT_EBBND 0x00002000 +#define FRAME_PRINT_LISTS_FOR_ARC 0x00004000 + +#include "TRestRawSignalEvent.h" + +#include + +namespace ARCPacket { + + //enum class packetReply { ERROR = -1, RETRY = 0, OK = 1 }; + //enum class packetType { ASCII = 0, BINARY = 1 }; + + void DataPacket_Print(uint16_t *fr, const uint16_t &size); + int HistoStat_Print (uint16_t *fr, int &sz_rd, const uint16_t &hitCount); + uint32_t GetUInt32FromBuffer(uint16_t *fr, int & sz_rd); + uint32_t GetUInt32FromBufferInv(uint16_t *fr, int & sz_rd); + bool GetNextEvent(std::deque &buffer, TRestRawSignalEvent* sEvent, uint64_t &tS, uint32_t &ev_count); + bool isDataFrame(uint16_t *fr); + +} + +#endif diff --git a/daq/FEMProxy.h b/daq/FEMProxy.h new file mode 100644 index 0000000..3401633 --- /dev/null +++ b/daq/FEMProxy.h @@ -0,0 +1,35 @@ +/********************************************************************************* +FEMProxy.h + +Author: JuanAn Garcia 18/08/2021 + +Based on mclient program from Denis Calvet + +*********************************************************************************/ + +#ifndef __FEM_PROXY__ +#define __FEM_PROXY__ + +#include + +#include "TRestRawDAQMetadata.h" +#include "TRESTDAQSocket.h" + +class FEMProxy : public TRESTDAQSocket { + + public: + FEMProxy(){ } + bool pendingEvent=false; + TRestRawDAQMetadata::FECMetadata fecMetadata; + //std::atomic_int + int cmd_sent=0; + //std::atomic_int + int cmd_rcv=0; + + std::deque buffer; + + inline static std::mutex mutex_socket; + inline static std::mutex mutex_mem; +}; + +#endif diff --git a/daq/TRESTDAQARC.cxx b/daq/TRESTDAQARC.cxx new file mode 100644 index 0000000..7607c07 --- /dev/null +++ b/daq/TRESTDAQARC.cxx @@ -0,0 +1,496 @@ +/********************************************************************************* +TRESTDAQARC.cxx + +Implement data acquisition for ARC based readout + +Author: JuanAn Garcia 15/04/2024 + +*********************************************************************************/ + +#include "TRESTDAQARC.h" +#include "ARCPacket.h" + + +std::atomic TRESTDAQARC::stopReceiver(false); + +TRESTDAQARC::TRESTDAQARC(TRestRun* rR, TRestRawDAQMetadata* dM) : TRESTDAQ(rR, dM) { initialize(); } + +void TRESTDAQARC::initialize() { + + for(auto fec : daqMetadata->GetFECs()){ + FEMProxy FEM; + FEM.Open(fec.ip, REMOTE_DST_PORT); + FEM.fecMetadata = fec; + FEMArray.emplace_back(std::move(FEM)); + } + + for (auto &FEM : FEMArray){ + auto cT = daq_metadata_types::chipTypes_map.find(FEM.fecMetadata.chipType.Data()); + if(cT == daq_metadata_types::chipTypes_map.end() ){ + std::cerr << "Unknown chip type for FEC id "<< FEM.fecMetadata.id <<" " << FEM.fecMetadata.chipType.Data() << std::endl; + std::cerr << "Valid chip types "<< std::endl; + for(const auto &[type, chip] : daq_metadata_types::chipTypes_map){ + std::cerr << type <<" ["<< (int)chip <<"], \t"; + } + std::cerr << std::endl; + throw (TRESTDAQException("Unknown chip type, please check RML")); + } else if (cT->second != daq_metadata_types::chipTypes::AGET){ + std::cerr << "Unsupported chip type for FEC id "<< FEM.fecMetadata.id <<" " << FEM.fecMetadata.chipType.Data() << std::endl; + throw (TRESTDAQException("Unsupported chip type, please check RML")); + } + } + + //Start receive and event builder threads + receiveThread = std::thread( TRESTDAQARC::ReceiveThread, &FEMArray); + eventBuilderThread = std::thread( TRESTDAQARC::EventBuilderThread, &FEMArray, restRun, &fSignalEvent); +} + +void TRESTDAQARC::startUp(){ + std::cout << "Starting up readout" << std::endl; + //FEC Power-down + //BroadcastCommand("power_inv 0",FEMArray); + BroadcastCommand("fec_enable 0",FEMArray); + //Ring Buffer and DAQ cleanup + BroadcastCommand("DAQ 0",FEMArray,false); + BroadcastCommand("daq 0xFFFFFF B",FEMArray); + BroadcastCommand("sca enable 0",FEMArray); + std::this_thread::sleep_for(std::chrono::seconds(1)); + BroadcastCommand("serve_target 0",FEMArray); + std::this_thread::sleep_for(std::chrono::seconds(4)); + BroadcastCommand("rbf getpnd",FEMArray); + std::this_thread::sleep_for(std::chrono::seconds(1)); + //Ring Buffer startup + BroadcastCommand("rbf timed 1",FEMArray); + BroadcastCommand("rbf timeval 2",FEMArray); + BroadcastCommand("rbf resume",FEMArray); + //Selection of operating mode + for (auto &FEM : FEMArray){ + char cmd[200]; + sprintf(cmd, "mode %s", FEM.fecMetadata.chipType.Data()); + SendCommand(cmd,FEM); + uint8_t asicMask =0; + for(int a=0;aGetAcquisitionType())); + if (rT == daq_metadata_types::acqTypes_map.end()) { + std::cout << "Unknown acquisition type " << daqMetadata->GetAcquisitionType() << " skipping" << std::endl; + std::cout << "Valid acq types:" << std::endl; + for (auto& [name, t] : daq_metadata_types::acqTypes_map) std::cout << (int)t << " " << name << std::endl; + return; + } + + if (rT->second == daq_metadata_types::acqTypes::PEDESTAL) { + pedestal(); + } else { + dataTaking(); + } +} + +void TRESTDAQARC::pedestal() { + std::cout << "Starting pedestal run" << std::endl; + //Readout settings + BroadcastCommand("modify_hit_reg 0",FEMArray); + BroadcastCommand("emit_hit_cnt 1",FEMArray); + BroadcastCommand("emit_empty_ch 1",FEMArray); + BroadcastCommand("keep_rst 1",FEMArray); + BroadcastCommand("skip_rst 0",FEMArray); + //Pedestal Thresholds and Zero-suppression + BroadcastCommand("ped * * 0x0",FEMArray); + BroadcastCommand("subtract_ped 0",FEMArray); + BroadcastCommand("zero_suppress 0",FEMArray); + BroadcastCommand("zs_pre_post 0 0",FEMArray); + BroadcastCommand("thr * * 0x0",FEMArray); + //Event generator + BroadcastCommand("event_limit 0x3",FEMArray);//# Event limit: 0x0:infinite; 0x1:1; 0x2:10; 0x3:100; 0x4: 1000; 0x5:10000; 0x6:100000; 0x7:1000000 + BroadcastCommand("trig_rate 1 10",FEMArray);//# Range: 0:0.1Hz-10Hz 1:10Hz-1kHz 2:100Hz-10kHz 3:1kHz-100kHz + BroadcastCommand("trig_enable 0x1",FEMArray); + //Pedestal Histograms + BroadcastCommand("hped offset * * 0",FEMArray); + BroadcastCommand("hped clr * *",FEMArray); + //Data server target: 0:drop data; 1:send to DAQ; 2:feed to pedestal histos; 3:feed to hit channel histos + BroadcastCommand("serve_target 2",FEMArray); + BroadcastCommand("sca enable 1",FEMArray); + std::this_thread::sleep_for(std::chrono::seconds(15));// Wait pedestal accumulation completion + BroadcastCommand("sca enable 0",FEMArray); + char cmd[200]; + for (auto &FEM : FEMArray){ + for(int a=0;a<4;a++){ + if(!FEM.fecMetadata.asic_isActive[a])continue; + sprintf(cmd, "hped getsummary %d *", a ); + SendCommand(cmd,FEM); + //Set pedestal equalization + sprintf(cmd, "hped centermean %d * %d", a , FEM.fecMetadata.asic_pedCenter[a] ); + SendCommand(cmd,FEM); + } + } + + BroadcastCommand("subtract_ped 1",FEMArray); + BroadcastCommand("hped clr * *",FEMArray); + BroadcastCommand("sca enable 1",FEMArray); + std::this_thread::sleep_for(std::chrono::seconds(15));// Wait pedestal accumulation completion + BroadcastCommand("sca enable 0",FEMArray); + for (auto &FEM : FEMArray){ + for(int a=0;aGetNEvents() == 0 || event_cnt < daqMetadata->GetNEvents())) { + //Do something here? E.g. send packet request + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + BroadcastCommand("sca enable 0",FEMArray); + BroadcastCommand("daq 0xFFFFFF F",FEMArray,false);//Stop DAQ request + std::this_thread::sleep_for(std::chrono::milliseconds(500));//Wait some time till DAQ command is propagated +} + +void TRESTDAQARC::stopDAQ() { + stopReceiver = true; + receiveThread.join(); + eventBuilderThread.join(); + + for (auto &FEM : FEMArray) + FEM.Close(); +} + +void TRESTDAQARC::BroadcastCommand(const char* cmd, std::vector &FEMA, bool wait){ + + for (auto &FEM : FEMA){ + SendCommand(cmd,FEM,wait); + } + + //if (verboseLevel >= REST_Debug)std::cout<<"Command sent "< lock(FEM.mutex_socket); + if (sendto (FEM.client, cmd, strlen(cmd), 0, (struct sockaddr*)&(FEM.target), sizeof(struct sockaddr)) == -1) { + std::string error ="sendto failed: " + std::string(strerror(errno)); + throw (TRESTDAQException(error)); + } + + lock.unlock(); + if (verboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Debug)std::cout<<"FEM "< lock(FEM.mutex_socket); + condition = (FEM.cmd_sent > FEM.cmd_rcv); + lock.unlock(); + timeout++; + } while ( condition && timeout <10); + + if (verboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Debug)std::cout<<"Cmd sent "<=10)std::cout<<"Cmd timeout "< *FEMA ) { + + fd_set readfds, writefds, exceptfds, readfds_work; + struct timeval t_timeout; + t_timeout.tv_sec = 5; + t_timeout.tv_usec = 0; + + // Build the socket descriptor set from which we want to read + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + + int smax = 0; + for (auto &FEM : *FEMA){ + FD_SET(FEM.client, &readfds); + if (FEM.client > smax) + smax = FEM.client; + } + smax++; + + while (!stopReceiver){ + + // Copy the read fds from what we computed outside of the loop + readfds_work = readfds; + + int err =0; + // Wait for any of these sockets to be ready + if ((err = select(smax, &readfds_work, &writefds, &exceptfds, &t_timeout)) < 0){ + std::string error ="select failed: " + std::string(strerror(errno)); + throw (TRESTDAQException(error)); + } + + if(err == 0 )continue;//Nothing received + + for (auto &FEM : *FEMA){ + + if (FD_ISSET(FEM.client, &readfds_work)){ + std::unique_lock lock(FEM.mutex_socket); + uint16_t buf_rcv[8192/(sizeof(uint16_t))]; + int length = recvfrom(FEM.client, buf_rcv, 8192, 0, (struct sockaddr*)&FEM.remote, &FEM.remote_size); + lock.unlock(); + if (length < 0) { + std::string error ="recvfrom failed: " + std::string(strerror(errno)); + throw (TRESTDAQException(error)); + } + + if (verboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Debug)std::cout<<"Packet received with length "<6){//empty frame? + const size_t size = length/sizeof(uint16_t);//Note that length is in bytes while size is uint16_t + + if (verboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Debug)ARCPacket::DataPacket_Print(&buf_rcv[1], size-1); + + if(!ARCPacket::isDataFrame(&buf_rcv[1])){ + //lock.lock(); + FEM.cmd_rcv++; + //lock.unlock(); + } else { + std::unique_lock lock_mem(FEM.mutex_mem); + //const std::deque frame (&buf_rcv[1], &buf_rcv[size -1]); + FEM.buffer.insert(FEM.buffer.end(), &buf_rcv[1], &buf_rcv[size -1]); + const size_t bufferSize = FEM.buffer.size(); + lock_mem.unlock(); + if (verboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Debug) + std::cout<<"Packet buffered with size "<<(int)size-1<<" queue size: "< 1024*1024*1024){ + std::string error ="Buffer FULL with size "+std::to_string(bufferSize/sizeof(uint16_t))+" bytes"; + throw (TRESTDAQException(error)); + } + + } + } + } + + } + } +} + +void TRESTDAQARC::EventBuilderThread(std::vector *FEMA, TRestRun *rR, TRestRawSignalEvent* sEvent){ + + sEvent->Initialize(); + + uint32_t ev_count; + uint64_t ts; + + bool newEvent = false; + bool pendingEvent = false; + + while (!stopReceiver ){ + + for (auto &FEM : *FEMA){ + std::unique_lock lock(FEM.mutex_mem); + if(!FEM.buffer.empty()){//Do nothing + if(FEM.pendingEvent){//Wait till we reach end of event for all the ARC + FEM.pendingEvent = !ARCPacket::GetNextEvent( FEM.buffer, sEvent, ts, ev_count); + } else if( !FEM.pendingEvent && !pendingEvent) { + FEM.pendingEvent = !ARCPacket::GetNextEvent( FEM.buffer, sEvent, ts, ev_count); + newEvent=true; + } + } + lock.unlock(); + } + + pendingEvent=false; + + for (const auto &FEM : *FEMA){ + //std::unique_lock lock(FEM.mutex_mem); + if(FEM.pendingEvent)pendingEvent=true;//Check if the event is pending + //lock.unlock(); + } + + if(newEvent && !pendingEvent){//Save Event if closed + if(rR){ + sEvent->SetID(ev_count); + sEvent->SetTime( rR->GetStartTimestamp() + (double) ts * 2E-8 ); + FillTree(rR, sEvent); + sEvent->Initialize(); + newEvent = false; + if(event_cnt%100 == 0)std::cout<<"Events "< +#include +#include + +class TRESTDAQARC : public TRESTDAQ { + public: + TRESTDAQARC(TRestRun* rR, TRestRawDAQMetadata* dM); + + void configure() override; + void startDAQ() override; + void stopDAQ() override; + void initialize() override; + void startUp() override; + + static void ReceiveThread(std::vector *FEMA); + static void ReceiveBuffer(FEMProxy &FEM); + static void EventBuilderThread(std::vector *FEMA, TRestRun *rR, TRestRawSignalEvent* sEvent); + static void waitForCmd(FEMProxy &FEM); + static std::atomic stopReceiver; + + inline static std::mutex mutex; + + private: + void pedestal(); + void dataTaking(); + void BroadcastCommand(const char* cmd, std::vector &FEMA, bool wait=true); + void SendCommand(const char* cmd, FEMProxy &FEM, bool wait=true); + + std::vector FEMArray;//Vector of ARC + + std::thread receiveThread, eventBuilderThread; + +}; + +#endif