otsdaq_components  v2_05_02_indev
OtsUDPFirmwareCore.cc
1 #include "otsdaq-components/DAQHardware/OtsUDPFirmwareCore.h"
2 
3 #include "otsdaq/Macros/CoutMacros.h"
4 #include "otsdaq/MessageFacility/MessageFacility.h"
5 
6 //#include "otsdaq/BitManipulator/BitManipulator.h"
7 //#include "otsdaq-components/DAQHardware/FirmwareBaseDefinitions.h"
8 
9 #include <arpa/inet.h>
10 #include <netinet/in.h>
11 #include <sys/socket.h>
12 #include <algorithm>
13 #include <cstdlib>
14 #include <iomanip>
15 #include <iostream>
16 //#include
17 //"otsdaq-components/UserConfigurationDataFormats/FEOtsUDPFSSRInterfaceTable.h"
18 
19 using namespace ots;
20 
22 // ADDRESS SPACE
23 // http://otsdaq.fnal.gov/docs/oei_address_space.html
24 // field size (bits)
25 #define UDP_CORE_BLOCK_ADDRESS ((uint64_t)(0x1) << 32)
26 #define ADDR_SELF_UPPER_IP (uint64_t)(0x0) // 24
27 #define ADDR_SELF_LOWER_IP (uint64_t)(0x1) // 8
28 #define ADDR_SELF_MAC (uint64_t)(0x2) // 40
29 
30 #define ADDR_CTRL_DEST_IP (uint64_t)(0x3) // 32
31 #define ADDR_CTRL_DEST_MAC (uint64_t)(0x4) // 48
32 #define ADDR_CTRL_DEST_PORT (uint64_t)(0x5) // 16
33 
34 #define ADDR_DATA_DEST_IP (uint64_t)(0x6) // 32
35 #define ADDR_DATA_DEST_MAC (uint64_t)(0x7) // 48
36 #define ADDR_DATA_DEST_PORT (uint64_t)(0x8) // 16
37 
38 #define ADDR_BURST_MODE (uint64_t)(0x9) // 1
39 #define ADDR_CTRL_RESOLVE_MAC (uint64_t)(0xA) // 1
40 #define ADDR_DATA_RESOLVE_MAC (uint64_t)(0xB) // 1
41 #define ADDR_SELF_VERSION (uint64_t)(0x64) // 16 (read only)
42 #define ADDR_SELF_RESET (uint64_t)(0xFFFFFFFF) // 1 (write only)
43 
44 // end ADDRESS SPACE
46 
47 const uint8_t OtsUDPFirmwareCore::FIFO_ADDRESS_CMD_TYPE = (1 << 3);
48 
49 //==============================================================================
50 OtsUDPFirmwareCore::OtsUDPFirmwareCore(unsigned int version)
51  : FrontEndFirmwareBase(version)
52 {
53 }
54 
55 //==============================================================================
56 OtsUDPFirmwareCore::~OtsUDPFirmwareCore(void) {}
57 
58 //==============================================================================
59 void OtsUDPFirmwareCore::init(void) {}
60 
61 //==============================================================================
62 std::string OtsUDPFirmwareCore::write(char* address, char* data)
63 {
64  std::string buffer;
65  writeAdvanced(buffer, address, data);
66  return buffer;
67 }
68 
69 //==============================================================================
70 void OtsUDPFirmwareCore::write(std::string& buffer,
71  char* address,
72  char* data,
73  bool clearBuffer)
74 {
75  writeAdvanced(buffer, address, data, 1 /*size*/, 0 /*options*/, clearBuffer);
76 }
77 
78 //==============================================================================
79 void OtsUDPFirmwareCore::write(std::string& buffer,
80  uint32_t address,
81  uint32_t data,
82  bool clearBuffer)
83 {
84  writeAdvanced(buffer, address, data, 0 /*options*/, clearBuffer);
85 }
86 
87 //==============================================================================
88 void OtsUDPFirmwareCore::write(std::string& buffer,
89  uint64_t address,
90  uint64_t data,
91  bool clearBuffer)
92 {
93  writeAdvanced(buffer, address, data, 0 /*options*/, clearBuffer);
94 }
95 
96 //==============================================================================
97 // OtsUDPFirmwareCore::writeAdvanced
98 // size is in units of quad-words (8-Bytes)
99 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
100  const char* address,
101  const char* data,
102  uint8_t size,
103  uint8_t commandTypeOptions,
104  bool clearBuffer)
105 {
106  if(size > 182)
107  {
108  __SS__ << "Invalid OtsUDPFirmwareCore::writeAdvanced size: " << size << std::endl;
109  __COUT_ERR__ << "\n" << ss.str();
110  __SS_THROW__;
111  }
112 
113  if(buffer.size() + 2 + 8 + 8 * size > 2 + 8 + 8 * 182)
114  {
115  __SS__ << "Aborting. Buffer overflow attempt: " << buffer.size() << " + "
116  << 2 + 8 + 8 * size << " > " << 2 + 8 + 8 * 182 << std::endl;
117  __COUT_ERR__ << "\n" << ss.str();
118  __SS_THROW__;
119  }
120 
121  if(clearBuffer)
122  buffer.resize(0);
123 
124  unsigned int begin = buffer.length();
125  buffer.resize(buffer.length() + 2 + 8 + 8 * size, '\0');
126 
127  buffer[begin + 0] = 1 | commandTypeOptions; // OtsUDPFirmwareCore::writeAdvanced
128  buffer[begin + 1] = size; //# of 64 bits words
129 
130  std::copy_n(address, sizeof(uint64_t), &buffer[begin + 2]);
131  for(uint8_t i = 0; i < size; ++i)
132  std::copy_n(
133  (char*)&data[8 * i], sizeof(uint64_t), &buffer[begin + 2 + 8 + 8 * i]);
134 
136  /*
137  __SS__ << "\tAdded OtsUDPFirmwareCore::writeAdvanced to Buffer:-";
138  for(uint32_t i=begin; i<buffer.size(); i++)
139  {
140  if(i==begin+2) ss << ":::";
141  else if(i==begin+10) ss << ":::";
142  ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) buffer[i])
143  &0xFF) << "-" << std::dec;
144  }
145  ss << " added " << (buffer.size() - begin) << " to " << buffer.size();
146  ss << std::endl;
147  __COUT__ << "\n" << ss.str();
148  */
149 }
150 
151 //==============================================================================
152 // OtsUDPFirmwareCore::writeAdvanced
153 // Note: size is required, to remove ambiguity when calling
154 // OtsUDPFirmwareCore::writeAdvanced with data=0
155 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
156  const uint64_t& address,
157  const char* data,
158  uint8_t size,
159  uint8_t commandTypeOptions,
160  bool clearBuffer)
161 {
162  OtsUDPFirmwareCore::writeAdvanced(
163  buffer, (char*)&address, data, size, commandTypeOptions, clearBuffer);
164 }
165 
166 //==============================================================================
167 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
168  const uint64_t& address,
169  const uint64_t& data,
170  uint8_t commandTypeOptions,
171  bool clearBuffer)
172 {
173  OtsUDPFirmwareCore::writeAdvanced(buffer,
174  (char*)&address,
175  (char*)&data,
176  1 /*size*/,
177  commandTypeOptions,
178  clearBuffer);
179 }
180 
181 //==============================================================================
182 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(
183  std::string& buffer,
184  const uint64_t& address,
185  const std::vector<uint64_t>& data,
186  uint8_t commandTypeOptions,
187  bool clearBuffer)
188 {
189  OtsUDPFirmwareCore::writeAdvanced(buffer,
190  (char*)&address,
191  (char*)&data[0],
192  data.size() /*size*/,
193  commandTypeOptions,
194  clearBuffer);
195 }
196 
197 //==============================================================================
198 std::string OtsUDPFirmwareCore::read(char* address)
199 {
200  __COUT__ << "OTS pointer based read!! " << std::endl;
201  std::string buffer;
202  readAdvanced(buffer, address);
203  return buffer;
204 }
205 
206 //==============================================================================
207 void OtsUDPFirmwareCore::read(std::string& buffer, char* address, bool clearBuffer)
208 {
209  readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer);
210 }
211 
212 //==============================================================================
213 void OtsUDPFirmwareCore::read(std::string& buffer, uint64_t address, bool clearBuffer)
214 {
215  readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer);
216 }
217 
218 //==============================================================================
219 void OtsUDPFirmwareCore::read(std::string& buffer, uint32_t address, bool clearBuffer)
220 {
221  readAdvanced(buffer, address, 1 /*size*/, 0 /*options*/, clearBuffer);
222 }
223 
224 //==============================================================================
225 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer,
226  char* address,
227  uint8_t size,
228  uint8_t commandTypeOptions,
229  bool clearBuffer)
230 {
231  if(size > 182)
232  {
233  __SS__ << "Invalid OtsUDPFirmwareCore::readAdvanced size: " << size << std::endl;
234  __COUT_ERR__ << "\n" << ss.str();
235  __SS_THROW__;
236  }
237 
238  if(buffer.size() + 2 + 8 > 2 + 8 + 8 * 182)
239  {
240  __SS__ << "Aborting. Buffer overflow attempt: " << buffer.size() << " + " << 2 + 8
241  << " > " << 2 + 8 + 8 * 182 << std::endl;
242  __COUT_ERR__ << "\n" << ss.str();
243  __SS_THROW__;
244  }
245 
246  if(clearBuffer)
247  buffer.resize(0);
248 
249  unsigned int begin = buffer.length();
250  buffer.resize(buffer.length() + 2 + 8, '\0');
251 
252  buffer[begin + 0] =
253  (uint8_t)0 | commandTypeOptions; // OtsUDPFirmwareCore::readAdvanced
254  buffer[begin + 1] = size; //# of 64 bits words
255 
256  // NOTE -- be wary of copy_n RAR -- it failed for me with uint32_t size
257  std::copy_n(address, sizeof(uint64_t), &buffer[begin + 2]);
258 
260  //__SS__ << "\tAdded OtsUDPFirmwareCore::readAdvanced to Buffer:-";
261  // for(uint32_t i=begin; i<buffer.size(); i++)
262  //{
263  // if(i==begin+2) ss << ":::";
264  // else if(i==begin+10) ss << ":::";
265  // ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) buffer[i])
266  //&0xFF) << "-" << std::dec;
267  //}
268  // ss << std::endl;
269  //__COUT__ << "\n" << ss.str();
270 }
271 
272 //==============================================================================
273 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer,
274  const uint64_t& address,
275  uint8_t size,
276  uint8_t commandTypeOptions,
277  bool clearBuffer)
278 {
279  OtsUDPFirmwareCore::readAdvanced(
280  buffer, (char*)&address, size, commandTypeOptions, clearBuffer);
281 }
282 
283 //==============================================================================
284 void OtsUDPFirmwareCore::setDataDestination(std::string& buffer,
285  const std::string& ipAddress,
286  const uint16_t port,
287  bool clearBuffer)
288 {
289  // put firmware in dynamic mac resolution mode for burst mode
290  //__COUT__ << "Dynamic mac address: " << std::hex <<
291  // uint64_t(UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC) << std::endl;
292  OtsUDPFirmwareCore::write(buffer,
293  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC /* addr */,
294  1 /* data */,
295  clearBuffer);
296 
297  // extract ip address from string
298  //__COUT__ << "IP Address = " << ipAddress << std::endl;
299  uint64_t ip = 0;
300  int ipArr[4];
301  sscanf(ipAddress.c_str(), "%d.%d.%d.%d", &ipArr[3], &ipArr[2], &ipArr[1], &ipArr[0]);
302  for(int i = 0; i < 4; ++i)
303  (((char*)&ip)[i]) += ipArr[i] & 0x0FF;
304 
305  writeDataDestinationIP(buffer, ip, false /*clearBuffer*/);
306  writeDataDestinationPort(buffer, port, false /*clearBuffer*/);
307 }
308 
309 //==============================================================================
310 void OtsUDPFirmwareCore::setControlDestination(std::string& buffer,
311  const std::string& ipAddress,
312  const uint16_t port)
313 {
314  // put firmware in dynamic mac resolution mode for burst mode
315  OtsUDPFirmwareCore::writeAdvanced(
316  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_RESOLVE_MAC /* addr */, 1 /* data */);
317 
318  // extract ip address from string
319  __COUT__ << "ipAddress = " << ipAddress << std::endl;
320  uint64_t ip = 0;
321  int ipArr[4];
322  sscanf(ipAddress.c_str(), "%d.%d.%d.%d", &ipArr[3], &ipArr[2], &ipArr[1], &ipArr[0]);
323  for(int i = 0; i < 4; ++i)
324  (((char*)&ip)[i]) += ipArr[i] & 0x0FF;
325 
326  writeControlDestinationIP(buffer, ip);
327  writeControlDestinationPort(buffer, port);
328 }
329 
330 //==============================================================================
331 // return data lower 32 bits
332 uint32_t OtsUDPFirmwareCore::createRegisterFromValue(std::string& /*readBuffer*/,
333  std::string& receivedValue)
334 {
335  uint32_t retVal = *((uint32_t*)(&receivedValue[2]));
336 
337  // for(unsigned int i=0;i<receivedValue.size();++i)
338  // __COUT__ << std::hex << (int)receivedValue[i] << std::dec << std::endl;
339  //__COUT__ << "Register value: 0x" << std::hex << retVal << std::dec << std::endl;
340  return retVal;
341 }
342 
343 //==============================================================================
344 void OtsUDPFirmwareCore::writeDataDestinationIP(std::string& buffer,
345  const uint64_t value,
346  bool clearBuffer)
347 {
348  OtsUDPFirmwareCore::writeAdvanced(
349  buffer,
350  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */,
351  value /* data */,
352  0 /*options*/,
353  clearBuffer);
354 }
355 
356 //==============================================================================
357 void OtsUDPFirmwareCore::writeDataDestinationMAC(std::string& buffer,
358  const uint64_t value,
359  bool clearBuffer)
360 {
361  OtsUDPFirmwareCore::writeAdvanced(
362  buffer,
363  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */,
364  value /* data */,
365  0 /*options*/,
366  clearBuffer);
367 }
368 
369 //==============================================================================
370 void OtsUDPFirmwareCore::writeDataDestinationPort(std::string& buffer,
371  const uint64_t value,
372  bool clearBuffer)
373 {
374  OtsUDPFirmwareCore::writeAdvanced(
375  buffer,
376  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */,
377  value /* data */,
378  0 /*options*/,
379  clearBuffer);
380 }
381 
382 //==============================================================================
383 void OtsUDPFirmwareCore::readDataDestinationIP(std::string& buffer)
384 {
385  OtsUDPFirmwareCore::readAdvanced(
386  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */);
387 }
388 
389 //==============================================================================
390 void OtsUDPFirmwareCore::readDataDestinationMAC(std::string& buffer)
391 {
392  OtsUDPFirmwareCore::readAdvanced(
393  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */);
394 }
395 
396 //==============================================================================
397 void OtsUDPFirmwareCore::readDataDestinationPort(std::string& buffer)
398 {
399  OtsUDPFirmwareCore::readAdvanced(
400  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */);
401 }
402 
403 //==============================================================================
404 void OtsUDPFirmwareCore::writeControlDestinationIP(std::string& buffer,
405  const uint64_t value)
406 {
407  OtsUDPFirmwareCore::writeAdvanced(
408  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */, value /* data */);
409 }
410 
411 //==============================================================================
412 void OtsUDPFirmwareCore::writeControlDestinationMAC(std::string& buffer,
413  const uint64_t value)
414 {
415  OtsUDPFirmwareCore::writeAdvanced(
416  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */, value /* data */);
417 }
418 
419 //==============================================================================
420 void OtsUDPFirmwareCore::writeControlDestinationPort(std::string& buffer,
421  const uint64_t value)
422 {
423  OtsUDPFirmwareCore::writeAdvanced(
424  buffer,
425  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */,
426  value /* data */);
427 }
428 
429 //==============================================================================
430 void OtsUDPFirmwareCore::readControlDestinationIP(std::string& buffer)
431 {
432  OtsUDPFirmwareCore::readAdvanced(
433  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */);
434 }
435 
436 //==============================================================================
437 void OtsUDPFirmwareCore::readControlDestinationMAC(std::string& buffer)
438 {
439  OtsUDPFirmwareCore::readAdvanced(
440  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */);
441 }
442 
443 //==============================================================================
444 void OtsUDPFirmwareCore::readControlDestinationPort(std::string& buffer)
445 {
446  OtsUDPFirmwareCore::readAdvanced(
447  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */);
448 }
449 
450 //==============================================================================
451 void OtsUDPFirmwareCore::readUDPFirmwareVersion(std::string& buffer)
452 {
453  OtsUDPFirmwareCore::readAdvanced(
454  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_VERSION /* addr */);
455 }
456 
457 //==============================================================================
458 void OtsUDPFirmwareCore::softEthernetReset(std::string& buffer)
459 {
460  OtsUDPFirmwareCore::writeAdvanced(
461  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0x3 /* data */);
462 }
463 
464 //==============================================================================
465 void OtsUDPFirmwareCore::hardEthernetReset(std::string& buffer)
466 {
467  OtsUDPFirmwareCore::writeAdvanced(
468  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0x1 /* data */);
469 }
470 
471 //==============================================================================
472 void OtsUDPFirmwareCore::clearEthernetReset(std::string& buffer)
473 {
474  OtsUDPFirmwareCore::writeAdvanced(
475  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */, 0 /* data */);
476 }
477 
478 //==============================================================================
479 void OtsUDPFirmwareCore::startBurst(std::string& buffer)
480 {
481  __COUT__ << std::endl;
482  OtsUDPFirmwareCore::writeAdvanced(
483  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */, 1 /* data */);
484 }
485 
486 //==============================================================================
487 void OtsUDPFirmwareCore::stopBurst(std::string& buffer)
488 {
489  __COUT__ << std::endl;
490  OtsUDPFirmwareCore::writeAdvanced(
491  buffer, UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */, 0 /* data */);
492 }