Belle II Software  release-05-01-25
PXDReadRawBonnDAQ.cc
1 //+
2 // File : PXDReadRawBonnDAQ.cc
3 // Description : Module to Load Raw PXD Data from DHH network-dump file and store it as RawPXD in Data Store
4 // This is meant for lab use (standalone testing, debugging) without an event builder.
5 //
6 // Author : Bjoern Spruck
7 // Date : 02.05.2018
8 //-
9 
10 #include <pxd/modules/pxdUnpacking/PXDReadRawBonnDAQ.h>
11 #include <boost/spirit/home/support/detail/endian.hpp>
12 #include <boost/crc.hpp>
13 
14 using namespace std;
15 using namespace Belle2;
16 using namespace PXD;
17 
18 using namespace boost::spirit::endian;
19 
20 using boost::crc_optimal;
21 typedef crc_optimal<32, 0x04C11DB7, 0, 0, false, false> dhe_crc_32_type;
22 
23 //-----------------------------------------------------------------
24 // Register the Module
25 //-----------------------------------------------------------------
26 REG_MODULE(PXDReadRawBonnDAQ)
27 
28 //-----------------------------------------------------------------
29 // Implementation
30 //-----------------------------------------------------------------
31 
33 {
34  fh = 0;
35  //Set module properties
36  setDescription("Read a BonnDAQ file and stores it as RawPXD in Data Store");
37  //setPropertyFlags(c_Input | c_ParallelProcessingCertified); // not parallel processing!
38 
39  addParam("FileName", m_filename, "file name");
40  addParam("SubRunNr", m_subRunNr, "sub-run number", 0u);
41  addParam("RunNr", m_runNr, "run number", 0u);
42  addParam("ExpNr", m_expNr, "exp number", 0u);
43  m_buffer = new int[MAXEVTSIZE];
44 
45  B2DEBUG(29, "PXDReadRawBonnDAQModule: Constructor done.");
46 }
47 
48 
49 PXDReadRawBonnDAQModule::~PXDReadRawBonnDAQModule()
50 {
51  delete[] m_buffer;
52 }
53 
54 void PXDReadRawBonnDAQModule::initialize()
55 {
56  // Open file
57  fh = fopen(m_filename.c_str(), "rb");
58  if (fh) {
59  B2INFO("Read BonnDAQ Data from " << m_filename);
60  } else {
61  B2ERROR("Could not open BonnDAQ Data: " << m_filename);
62  }
63 
64  // Register EvtMetaData
65  m_eventMetaDataPtr.registerInDataStore(DataStore::EStoreFlags::c_ErrorIfAlreadyRegistered);
66  // Register RawPXD
67  m_rawPXD.registerInDataStore(DataStore::EStoreFlags::c_ErrorIfAlreadyRegistered);
68 
69  B2DEBUG(29, "PXDReadRawBonnDAQModule: initialized.");
70 }
71 
72 int PXDReadRawBonnDAQModule::read_data(char* data, size_t len)
73 {
74  size_t l = 0;
75  if (fh) l = fread(data, 1, len, fh);
76  if (l != len) return 0;
77  return l;
78 }
79 
80 int PXDReadRawBonnDAQModule::readOneEvent()
81 {
82  unsigned int triggernr = 0xFFFFFFFF;
83 
84  struct EvtHeader {
85  ulittle16_t size;
86  ulittle16_t header;
87  unsigned int get_size(void) { return (unsigned int) size + (((unsigned int)(header & 0x000F)) << 16);};
88  unsigned int get_size_group(void) { return (unsigned int) size + (((unsigned int)((header & 0x003F) ^ 0x0020)) << 16);};
89  unsigned int get_header12(void) { return (header & 0xFFF0);};
90  unsigned int get_header10(void) { return (header & 0xFFC0);};
91  unsigned int get_header8(void) { return (header & 0xFF00);};
92  };
93 
94  char* data = (char*)m_buffer;
95  struct EvtHeader* evt = (struct EvtHeader*)data;
96 
97  while (1) {
98  ulittle32_t* data32 = (ulittle32_t*)data;
99  ulittle16_t* data16 = (ulittle16_t*)data;
100  // Read 8 bytes header (group)
101  int br = read_data(data, 4);
102  if (br <= 0) return br;
103  unsigned int chunk_size = 0;
104  if (evt->get_header8() == 0) {
105  B2DEBUG(29, "Group Header $" << std::hex << evt->get_header10() << " Chunk size " << std::dec << evt->get_size());
106  chunk_size = evt->get_size_group();
107  } else {
108  B2DEBUG(29, "Header $" << std::hex << evt->get_header12() << " Chunk size " << std::dec << evt->get_size());
109  chunk_size = evt->get_size();
110  }
111  if (chunk_size <= 1) return 0;
112  br = read_data(data + 4, chunk_size * 4 - 4);
113  if (br <= 0) return br;
114  if (evt->get_header12() == 0xe230) {
115  B2DEBUG(29, "File info " << std::hex << evt->get_header12() << " Events " << std::dec << data32[1]);
116  continue;
117  } else if (evt->get_header12() == 0xe100) {
118  B2DEBUG(29, "Info Event " << std::hex << evt->get_header12() << " RunNr $" << std::hex << data32[1]);
119  if (m_runNr == 0) m_runNr = data32[1]; // we assume it will not change within one file
120  continue;
121  } else if (evt->get_header10() == 0x0000) { // war 0x0020
122  B2DEBUG(29, "Run Event Group " << std::hex << evt->get_header10() << " Magic $" << std::hex << data32[1]);
123  continue;
124  } else if (evt->get_header12() == 0xbb00) {
125  B2DEBUG(29, "Run Event " << std::hex << evt->get_header12() << " Magic $" << std::hex << data32[1]);
126  continue;
127  } else if (evt->get_header10() == 0x0080) { // war 0x00A0
128  int togo = chunk_size;
129  B2DEBUG(29, "Data Event Group " << std::hex << evt->get_header10() << " TriggerNr $" << std::hex << data32[1]);
130  triggernr = data32[1];
131  togo -= 2;
132  data32 += 2;
133  data16 += 4;
134  while (togo > 2) {
135  B2DEBUG(29, "TOGO: " << togo);
136  B2DEBUG(29, " ............... " << std::hex << data32[0] << " TriggerNr $" << std::hex << data32[1]);
137  if (triggernr != data32[1]) B2ERROR("Trigger Nr does not match!");
138  B2DEBUG(29, " ............... " << std::hex << data32[2]);
139  togo -= 2;
140  data32 += 2;
141  data16 += 4;
142  if ((data32[0] & 0xFFFF0000) == 0xCAFE0000) {
143  int frames = (data32[0] & 0x3FF);
144  B2DEBUG(29, "Frames: " << frames);
145  int size = 0;
146  bool nocrc = (data32[0] & 0x8000) != 0;
147 
148  if ((data32[0] & 0x4000) == 0) B2FATAL("large data fields not supported");
149 
150  togo--;
151  data32++;
152  data16 += 2;
154  std::vector <unsigned int> m_onsen_header;
155 
157  std::vector <std::vector <unsigned char>> m_onsen_payload;
158  int offset = ((frames + 1) & ~1);
159 
160  ulittle16_t* table16 = data16;
161  if (!nocrc) {
162  togo--; // jump over TOC CRC
163  data32++;
164  data16 += 2;
165  }
166 
167  for (int i = 0; i < frames; i++) {
168  B2INFO(".... " << i << ": " << table16[i]);
169  size += table16[i];
170 
172  std::vector <unsigned char> m_current_frame;
173 
174  for (int j = 0; j < (int)table16[i] * 2; j++) {
175  unsigned short w = data16[offset++];
176  m_current_frame.push_back((unsigned char)(w >> 8));
177  m_current_frame.push_back((unsigned char)(w));
178  }
179 
180  if (nocrc) { // recalculate
181  dhe_crc_32_type current_crc;
182  current_crc.process_bytes(m_current_frame.data(), m_current_frame.size());
183  unsigned int w = current_crc.checksum();
184  m_current_frame.push_back((unsigned char)(w >> 24));
185  m_current_frame.push_back((unsigned char)(w >> 16));
186  m_current_frame.push_back((unsigned char)(w >> 8));
187  m_current_frame.push_back((unsigned char)(w));
188  }
189 
190  m_onsen_header.push_back(m_current_frame.size());
191  m_onsen_payload.push_back(m_current_frame);
192  }
193  togo -= ((frames + 1) & ~1) / 2 + size;
194  data32 += ((frames + 1) & ~1) / 2 + size;
195  data16 += ((frames + 1) & ~1) + size * 2;
196 
197  if (nocrc) {
198  togo--;
199  data32++;
200  data16 += 2;
201  }
202 
203  m_rawPXD.appendNew(m_onsen_header, m_onsen_payload);
204  }
205  }// while ...
206 
207  // Update EventMetaData
208  B2INFO("Set Meta: Exp " << m_expNr << " Run " << m_runNr << " TrgNr " << triggernr);
209  m_eventMetaDataPtr.create();
210  m_eventMetaDataPtr->setExperiment(m_expNr);
211  m_eventMetaDataPtr->setRun(m_runNr);
212  m_eventMetaDataPtr->setEvent(triggernr);
213  // we cannot recover time tag here. this would need further decoding from DHH header
214  // m_eventMetaDataPtr->setTime((unsigned long long int)((time_tag_hi<<1) +(time_tag_mid &0x8000?1:0))*1000000000+(int)std::round(tt / 0.127216));
215 
216  return 1;
217  } else {
218  B2ERROR("Undefine Header $" << std::hex << evt->get_header12());
219  continue;
220  }
221  continue;
222 
223  }
224  return 0;
225 }
226 
227 void PXDReadRawBonnDAQModule::event()
228 {
229  if (fh == 0) {
230  B2ERROR("Unexpected close of dump file.");
231  terminate();
232  return;
233  }
234 
235  // Get a record from file
236  int stat;
237  do {
238  stat = readOneEvent();
239  if (stat <= 0) {
241  terminate();
242  return;
243  };
244  } while (stat == 0);
245 
246  return;
247 }
248 
249 void PXDReadRawBonnDAQModule::terminate()
250 {
251  if (fh) fclose(fh);
252  fh = 0;
253 }
254 
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::EvtHeader
Header structure of streamed object list.
Definition: EvtMessage.h:29
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::PXD::PXDReadRawBonnDAQModule
Module to Load Raw PXD Data from DHH network-dump file and store it as RawPXD in Data Store This is m...
Definition: PXDReadRawBonnDAQ.h:32