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