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