otsdaq-mu2e-stm  5.02.01
stm_data.cc
1 // STM data header
2 #include "Mu2e-STMDAQ/config/stm_data.hh"
3 
4 // Constructor
5 STMdata::STMdata(Config& cfg_, const std::shared_ptr<AsyncLogger>& logger_)
6  : cfg(cfg_)
7  , logger(logger_)
8  , master_config(cfg, logger)
9  , // STMDAQ master config
10  fw_config(cfg, logger)
11  , // firmware config
12  mu2e_config(cfg, logger, fw_config)
13  , // mu2e config
14  udp_config(cfg, logger, master_config)
15  , // udp config
16  zs_config(cfg, logger, master_config, fw_config, mu2e_config)
17  , // zero suppression config
18  prescale_config(cfg, logger)
19  , // prescale config
20  write_config(cfg, logger)
21  , // file writing config
22  buffer_config(cfg, logger, fw_config, mu2e_config, zs_config, MAX_PACKET_SIZE)
23  , // buffer config
24  baseline_config(
25  cfg, logger, fw_config, buffer_config, MAX_PACKET_LEN - pHdr_Len - fw_eHdr_len)
26  , // adc baseline config
27  mwd_config(cfg, logger, fw_config, baseline_config)
28  , // mwd config
29  pulseheight_config(cfg, logger, fw_config, baseline_config)
30  , // pulse height config
31  tcp_config(cfg, logger, master_config)
32  , // tcp config
33  dqm_config(cfg, logger, fw_config) // dqm config
34 {
35 }
36 
37 // Form uint32_t out of 2 x int16_t
38 uint32_t STMdata::make_uint32_t(int16_t p0, int16_t p1)
39 {
40  uint32_t value = static_cast<uint32_t>(static_cast<uint16_t>(p1)) << 16;
41  value |= static_cast<uint16_t>(p0);
42  return value;
43 }
44 
45 // Form uint64_t out of 4 x int16_t
46 uint64_t STMdata::make_uint64_t(int16_t p0, int16_t p1, int16_t p2, int16_t p3)
47 {
48  uint64_t value = (static_cast<uint64_t>(static_cast<uint16_t>(p3)) << 48) |
49  (static_cast<uint64_t>(static_cast<uint16_t>(p2)) << 32) |
50  (static_cast<uint64_t>(static_cast<uint16_t>(p1)) << 16) |
51  static_cast<uint64_t>(static_cast<uint16_t>(p0));
52  return value;
53 }
54 
55 // Split uint32_t into 2 x int16_t
56 std::vector<int16_t> STMdata::split_uint32_t(uint32_t value)
57 {
58  std::vector<int16_t> split_value(2);
59  split_value[0] = static_cast<int16_t>((value >> 0) & 0xFFFF);
60  split_value[1] = static_cast<int16_t>((value >> 16) & 0xFFFF);
61  return split_value;
62 }
63 
64 // Split uint64_t into 4 x int16_t
65 std::vector<int16_t> STMdata::split_uint64_t(uint64_t value)
66 {
67  std::vector<int16_t> split_value(4);
68  split_value[0] = static_cast<int16_t>((value >> 0) & 0xFFFF);
69  split_value[1] = static_cast<int16_t>((value >> 16) & 0xFFFF);
70  split_value[2] = static_cast<int16_t>((value >> 32) & 0xFFFF);
71  split_value[3] = static_cast<int16_t>((value >> 48) & 0xFFFF);
72  return split_value;
73 }
74 
75 // Get just the ADC clock time from the event header
76 uint64_t STMdata::get_ADCclock(int16_t* data, uint64_t hdr_index)
77 {
78  uint64_t ADCclock = make_uint64_t(data[hdr_index + fw_eHdr.ADCclk_0],
79  data[hdr_index + fw_eHdr.ADCclk_1],
80  data[hdr_index + fw_eHdr.ADCclk_2],
81  data[hdr_index + fw_eHdr.ADCclk_3]);
82  return ADCclock;
83 }
84 
85 // Get just the internal event number from the event header
86 uint64_t STMdata::get_event_number(int16_t* data, uint64_t hdr_index)
87 {
88  uint64_t event_number = make_uint64_t(data[hdr_index + fw_eHdr.EvNum_0],
89  data[hdr_index + fw_eHdr.EvNum_1],
90  data[hdr_index + fw_eHdr.EvNum_2],
91  0);
92  return event_number;
93 }
94 
95 // Get just the EWT from the event header
96 uint64_t STMdata::get_EWT(int16_t* data, uint64_t hdr_index)
97 {
98  uint64_t EWT = make_uint64_t(data[hdr_index + fw_eHdr.EWT_0],
99  data[hdr_index + fw_eHdr.EWT_1],
100  data[hdr_index + fw_eHdr.EWT_2],
101  0);
102  return EWT;
103 }
104 
105 // // Check the end of a packet for repeated 0xDEADBEEF
106 uint16_t STMdata::check_dead_beef(int16_t* data,
107  uint64_t packet_start,
108  uint16_t leftInPacket)
109 {
110  // Get the packet number
111  uint32_t pnum = (uint16_t)data[packet_start + 1] << 16 | (uint16_t)data[packet_start];
112 
113  // Check remainder of packet is filled with 0xDEADBEEF
114  while(leftInPacket != 0)
115  {
116  // Find location to check
117  int loc = packet_start + MAX_PACKET_LEN - leftInPacket;
118  // If end of packet isn't filled with 0xDEADBEE, throw critical error
119  if((uint16_t)(data[loc] & 0xFFFF) != BEEF and
120  (uint16_t)(data[loc + 1] & 0xFFFF) != DEAD)
121  {
122  if(logger)
123  {
124  logger->log("ERROR! End of packet " + std::to_string(pnum) +
125  " not filled with 0xDEADBEEF!!",
126  0);
127  return leftInPacket;
128  }
129  else
130  {
131  std::cout << "ERROR! End of packet " << pnum
132  << " not filled with 0xDEADBEEF!!" << std::endl;
133  exit(0);
134  }
135  }
136  // Subtract from leftInPacket
137  leftInPacket -= 2;
138  }
139 
140  return leftInPacket;
141 }
142 
143 // Get the event mode
144 uint64_t STMdata::get_event_mode(int16_t* data, uint64_t hdr_index)
145 {
146  // Get event mode data
147  uint16_t EM0 = static_cast<uint16_t>(data[hdr_index + fw_eHdr.EM_0]);
148  uint16_t EM1 = static_cast<uint16_t>(data[hdr_index + fw_eHdr.EM_1]);
149  uint16_t EM2 = static_cast<uint16_t>(data[hdr_index + fw_eHdr.EM_2_DRTDC]);
150 
151  // Extract each byte
152  uint8_t byte0 = EM0 & 0xFF;
153  uint8_t byte1 = (EM0 >> 8) & 0xFF;
154  uint8_t byte2 = EM1 & 0xFF;
155  uint8_t byte3 = (EM1 >> 8) & 0xFF;
156  uint8_t byte4 = EM2 & 0xFF;
157 
158  // Combine into a 40-bit value (stored in 64-bit int)
159  uint64_t EM = 0;
160  EM |= static_cast<uint64_t>(byte3) << 32;
161  EM |= static_cast<uint64_t>(byte2) << 24;
162  EM |= static_cast<uint64_t>(byte1) << 16;
163  EM |= static_cast<uint64_t>(byte0) << 8;
164  EM |= static_cast<uint64_t>(byte4);
165 
166  return EM;
167 }
168 
169 // Get just the DTC clock time from the event header
170 uint64_t STMdata::get_Ch_DTCclk(int16_t* data, uint64_t hdr_index)
171 {
172  uint64_t Ch_DTCclk = make_uint64_t(data[hdr_index + fw_eHdr.Ch_DTCclk_0],
173  data[hdr_index + fw_eHdr.DTCclk_1],
174  data[hdr_index + fw_eHdr.DTCclk_2],
175  data[hdr_index + fw_eHdr.DTCclk_3]);
176  return Ch_DTCclk;
177 }
178 
179 // Get just the channel number from the event header
180 uint16_t STMdata::get_channel(int16_t* data, uint64_t hdr_index)
181 {
182  return static_cast<uint16_t>(data[hdr_index + fw_eHdr.Ch_DTCclk_0]) & 0x00FF;
183 }
184 
185 // Get just the DTC clock time from the event header
186 uint64_t STMdata::get_DTCclock(int16_t* data, uint64_t hdr_index)
187 {
188  uint64_t Ch_DTCclk = get_Ch_DTCclk(data, hdr_index);
189  uint64_t DTCclock = Ch_DTCclk >> 8; // bits [63:8] → now in [55:0]
190  return DTCclock;
191 }
192 
193 // Create software event header form buffer
194 sw_event_header STMdata::create_sw_eHdr(int16_t* data, uint64_t hdr_index)
195 {
196  // Create empty header
197  sw_event_header hdr{};
198 
199  // Starting anchor = 0xCAFE
200  hdr[sw_eHdr.anchor_start] = sw_eHdr.anchor;
201 
202  // EWT
203  hdr[sw_eHdr.EWT_0] = data[hdr_index + fw_eHdr.EWT_0];
204  hdr[sw_eHdr.EWT_1] = data[hdr_index + fw_eHdr.EWT_1];
205  hdr[sw_eHdr.EWT_2] = data[hdr_index + fw_eHdr.EWT_2];
206 
207  // ADC clock
208  hdr[sw_eHdr.ADCclk_0] = data[hdr_index + fw_eHdr.ADCclk_0];
209  hdr[sw_eHdr.ADCclk_1] = data[hdr_index + fw_eHdr.ADCclk_1];
210  hdr[sw_eHdr.ADCclk_2] = data[hdr_index + fw_eHdr.ADCclk_2];
211  hdr[sw_eHdr.ADCclk_3] = data[hdr_index + fw_eHdr.ADCclk_3];
212 
213  // Channel number and DTC clock
214  hdr[sw_eHdr.Ch_DTCclk_0] = data[hdr_index + fw_eHdr.Ch_DTCclk_0];
215  hdr[sw_eHdr.DTCclk_1] = data[hdr_index + fw_eHdr.DTCclk_1];
216  hdr[sw_eHdr.DTCclk_2] = data[hdr_index + fw_eHdr.DTCclk_2];
217  hdr[sw_eHdr.DTCclk_3] = data[hdr_index + fw_eHdr.DTCclk_3];
218 
219  // Event mode
220  hdr[sw_eHdr.EM_0] = data[hdr_index + fw_eHdr.EM_0];
221  hdr[sw_eHdr.EM_1] = data[hdr_index + fw_eHdr.EM_1];
222  hdr[sw_eHdr.EM_2_DRTDC] = data[hdr_index + fw_eHdr.EM_2_DRTDC];
223 
224  // Ending anchor = 0xCAFE
225  hdr[sw_eHdr.anchor_end] = sw_eHdr.anchor;
226 
227  return hdr;
228 }
229 
230 // Create software event header from individual inputs
231 sw_event_header STMdata::create_sw_eHdr(uint64_t EWT,
232  uint64_t ADCclk,
233  uint64_t Ch_DTCclk,
234  uint64_t EM)
235 {
236  // Create empty header
237  sw_event_header hdr{};
238 
239  hdr[sw_eHdr.anchor_start] = sw_eHdr.anchor;
240 
241  auto ewt_words = split_uint64_t(EWT);
242  auto adc_words = split_uint64_t(ADCclk);
243  auto chdtc_words = split_uint64_t(Ch_DTCclk);
244  auto em_words = split_uint64_t(EM);
245 
246  hdr[sw_eHdr.EWT_0] = ewt_words[0];
247  hdr[sw_eHdr.EWT_1] = ewt_words[1];
248  hdr[sw_eHdr.EWT_2] = ewt_words[2];
249 
250  hdr[sw_eHdr.ADCclk_0] = adc_words[0];
251  hdr[sw_eHdr.ADCclk_1] = adc_words[1];
252  hdr[sw_eHdr.ADCclk_2] = adc_words[2];
253  hdr[sw_eHdr.ADCclk_3] = adc_words[3];
254 
255  hdr[sw_eHdr.Ch_DTCclk_0] = chdtc_words[0];
256  hdr[sw_eHdr.DTCclk_1] = chdtc_words[1];
257  hdr[sw_eHdr.DTCclk_2] = chdtc_words[2];
258  hdr[sw_eHdr.DTCclk_3] = chdtc_words[3];
259 
260  hdr[sw_eHdr.EM_0] = em_words[0];
261  hdr[sw_eHdr.EM_1] = em_words[1];
262  hdr[sw_eHdr.EM_2_DRTDC] = em_words[2];
263 
264  hdr[sw_eHdr.anchor_end] = sw_eHdr.anchor;
265 
266  return hdr;
267 }
Definition: config.hh:19
Definition: data.hh:4