otsdaq_components  v2_01_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  throw std::runtime_error(ss.str());
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  throw std::runtime_error(ss.str());
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  __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]) &0xFF) << "-" << std::dec;
143  }
144  ss << " added " << (buffer.size() - begin) << " to " << buffer.size();
145  ss << std::endl;
146  __COUT__ << "\n" << ss.str();
147 }
148 
149 //========================================================================================================================
150 //OtsUDPFirmwareCore::writeAdvanced
151 // Note: size is required, to remove ambiguity when calling OtsUDPFirmwareCore::writeAdvanced with data=0
152 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
153  const uint64_t& address,
154  const char* data,
155  uint8_t size,
156  uint8_t commandTypeOptions,
157  bool clearBuffer)
158 {
159  OtsUDPFirmwareCore::writeAdvanced(buffer,(char *)&address,data,size,commandTypeOptions,clearBuffer);
160 }
161 
162 //========================================================================================================================
163 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
164  const uint64_t& address,
165  const uint64_t& data,
166  uint8_t commandTypeOptions,
167  bool clearBuffer)
168 {
169  OtsUDPFirmwareCore::writeAdvanced(buffer,(char *)&address,(char *)&data,1 /*size*/,commandTypeOptions,clearBuffer);
170 }
171 
172 //========================================================================================================================
173 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::writeAdvanced(std::string& buffer,
174  const uint64_t& address,
175  const std::vector<uint64_t>& data,
176  uint8_t commandTypeOptions,
177  bool clearBuffer)
178 {
179  OtsUDPFirmwareCore::writeAdvanced(buffer,(char *)&address,(char *)&data[0],data.size() /*size*/,commandTypeOptions,clearBuffer);
180 }
181 
182 //========================================================================================================================
183 std::string OtsUDPFirmwareCore::read
184  (char* address)
185 {
186  __COUT__ << "OTS pointer based read!! " << std::endl;
187  std::string buffer;
188  readAdvanced(buffer,address);
189  return buffer;
190 }
191 
192 //========================================================================================================================
193 void OtsUDPFirmwareCore::read
194  (std::string& buffer, char* address, bool clearBuffer)
195 {
196  readAdvanced(buffer,address,1/*size*/,0/*options*/,clearBuffer);
197 }
198 
199 //========================================================================================================================
200 void OtsUDPFirmwareCore::read
201  (std::string& buffer, uint64_t address, bool clearBuffer)
202 {
203  readAdvanced(buffer,address,1/*size*/,0/*options*/,clearBuffer);
204 }
205 
206 //========================================================================================================================
207 void OtsUDPFirmwareCore::read
208  (std::string& buffer, uint32_t address, bool clearBuffer)
209 {
210  readAdvanced(buffer,address,1/*size*/,0/*options*/,clearBuffer);
211 }
212 
213 
214 //========================================================================================================================
215 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer,
216  char* address,
217  uint8_t size,
218  uint8_t commandTypeOptions, bool clearBuffer)
219 {
220  if(size > 182)
221  {
222  __SS__ << "Invalid OtsUDPFirmwareCore::readAdvanced size: " << size << std::endl;
223  __COUT_ERR__ << "\n" << ss.str();
224  throw std::runtime_error(ss.str());
225  }
226 
227  if(buffer.size() + 2 + 8 > 2 + 8 + 8*182)
228  {
229  __SS__ << "Aborting. Buffer overflow attempt: " << buffer.size() << " + " <<
230  2 + 8 << " > " << 2 + 8 + 8*182 << std::endl;
231  __COUT_ERR__ << "\n" << ss.str();
232  throw std::runtime_error(ss.str());
233  }
234 
235  if(clearBuffer)
236  buffer.resize(0);
237 
238  unsigned int begin = buffer.length();
239  buffer.resize(buffer.length() + 2 + 8, '\0');
240 
241  buffer[begin + 0] = (uint8_t)0 | commandTypeOptions;//OtsUDPFirmwareCore::readAdvanced
242  buffer[begin + 1] = size;//# of 64 bits words
243 
244  //NOTE -- be wary of copy_n RAR -- it failed for me with uint32_t size
245  std::copy_n(address,sizeof(uint64_t),&buffer[begin + 2]);
246 
248  __SS__ << "\tAdded OtsUDPFirmwareCore::readAdvanced to Buffer:-";
249  for(uint32_t i=begin; i<buffer.size(); i++)
250  {
251  if(i==begin+2) ss << ":::";
252  else if(i==begin+10) ss << ":::";
253  ss << std::setfill('0') << std::setw(2) << std::hex << (((int16_t) buffer[i]) &0xFF) << "-" << std::dec;
254  }
255  ss << std::endl;
256  __COUT__ << "\n" << ss.str();
257 }
258 
259 
260 //========================================================================================================================
261 void OtsUDPFirmwareCore::OtsUDPFirmwareCore::readAdvanced(std::string& buffer,
262  const uint64_t& address,
263  uint8_t size,
264  uint8_t commandTypeOptions, bool clearBuffer)
265 {
266  OtsUDPFirmwareCore::readAdvanced(buffer,(char *)&address,size,commandTypeOptions,clearBuffer);
267 }
268 
269 
270 //========================================================================================================================
271 void OtsUDPFirmwareCore::setDataDestination(std::string& buffer,
272  const std::string& ipAddress, const uint16_t port, bool clearBuffer)
273 {
274  //put firmware in dynamic mac resolution mode for burst mode
275  __COUT__ << "dynamic mac address: " << std::hex <<
276  uint64_t(UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC) << std::endl;
277  OtsUDPFirmwareCore::write(buffer,
278  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_RESOLVE_MAC /* addr */,
279  1 /* data */, clearBuffer);
280 
281  //extract ip address from string
282  __COUT__ << "ipAddress = " << ipAddress << std::endl;
283  uint64_t ip = 0;
284  int ipArr[4];
285  sscanf(ipAddress.c_str(),"%d.%d.%d.%d",
286  &ipArr[3],
287  &ipArr[2],
288  &ipArr[1],
289  &ipArr[0]
290  );
291  for(int i=0;i<4;++i)
292  (((char *)&ip)[i]) += ipArr[i]&0x0FF;
293 
294  writeDataDestinationIP(buffer,ip,false /*clearBuffer*/);
295  writeDataDestinationPort(buffer,port,false/*clearBuffer*/);
296 
297 
298 
299 }
300 
301 //========================================================================================================================
302 void OtsUDPFirmwareCore::setControlDestination(std::string& buffer,
303  const std::string& ipAddress, const uint16_t port)
304 {
305  //put firmware in dynamic mac resolution mode for burst mode
306  OtsUDPFirmwareCore::writeAdvanced(buffer,
307  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_RESOLVE_MAC /* addr */,
308  1 /* data */);
309 
310  //extract ip address from string
311  __COUT__ << "ipAddress = " << ipAddress << std::endl;
312  uint64_t ip = 0;
313  int ipArr[4];
314  sscanf(ipAddress.c_str(),"%d.%d.%d.%d",
315  &ipArr[3],
316  &ipArr[2],
317  &ipArr[1],
318  &ipArr[0]
319  );
320  for(int i=0;i<4;++i)
321  (((char *)&ip)[i]) += ipArr[i]&0x0FF;
322 
323  writeControlDestinationIP(buffer,ip);
324  writeControlDestinationPort(buffer,port);
325 }
326 
327 //========================================================================================================================
328 //return data lower 32 bits
329 uint32_t OtsUDPFirmwareCore::createRegisterFromValue
330  (std::string& readBuffer, std::string& receivedValue)
331 {
332  uint32_t retVal = *((uint32_t *)(&receivedValue[2]));
333 
334  //for(unsigned int i=0;i<receivedValue.size();++i)
335  // __COUT__ << std::hex << (int)receivedValue[i] << std::dec << std::endl;
336  __COUT__ << "Register value: 0x" << std::hex << retVal << std::dec << std::endl;
337  return retVal;
338 }
339 
340 
341 //========================================================================================================================
342 void OtsUDPFirmwareCore::writeDataDestinationIP(std::string& buffer, const uint64_t value,
343  bool clearBuffer)
344 {
345  OtsUDPFirmwareCore::writeAdvanced(buffer,
346  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */,
347  value /* data */,
348  0/*options*/,clearBuffer);
349 }
350 
351 //========================================================================================================================
352 void OtsUDPFirmwareCore::writeDataDestinationMAC(std::string& buffer, const uint64_t value,
353  bool clearBuffer)
354 {
355  OtsUDPFirmwareCore::writeAdvanced(buffer,
356  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */,
357  value /* data */,
358  0/*options*/,clearBuffer);
359 }
360 
361 //========================================================================================================================
362 void OtsUDPFirmwareCore::writeDataDestinationPort(std::string& buffer, const uint64_t value,
363  bool clearBuffer)
364 {
365  OtsUDPFirmwareCore::writeAdvanced(buffer,
366  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */,
367  value /* data */,
368  0/*options*/,clearBuffer);
369 }
370 
371 //========================================================================================================================
372 void OtsUDPFirmwareCore::readDataDestinationIP(std::string& buffer)
373 {
374  OtsUDPFirmwareCore::readAdvanced(buffer,
375  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_IP /* addr */);
376 }
377 
378 //========================================================================================================================
379 void OtsUDPFirmwareCore::readDataDestinationMAC(std::string& buffer)
380 {
381  OtsUDPFirmwareCore::readAdvanced(buffer,
382  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_MAC /* addr */);
383 }
384 
385 //========================================================================================================================
386 void OtsUDPFirmwareCore::readDataDestinationPort(std::string& buffer)
387 {
388  OtsUDPFirmwareCore::readAdvanced(buffer,
389  UDP_CORE_BLOCK_ADDRESS | ADDR_DATA_DEST_PORT /* addr */);
390 }
391 
392 //========================================================================================================================
393 void OtsUDPFirmwareCore::writeControlDestinationIP(std::string& buffer, const uint64_t value)
394 {
395  OtsUDPFirmwareCore::writeAdvanced(buffer,
396  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */,
397  value /* data */);
398 }
399 
400 //========================================================================================================================
401 void OtsUDPFirmwareCore::writeControlDestinationMAC(std::string& buffer, const uint64_t value)
402 {
403  OtsUDPFirmwareCore::writeAdvanced(buffer,
404  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */,
405  value /* data */);
406 }
407 
408 //========================================================================================================================
409 void OtsUDPFirmwareCore::writeControlDestinationPort(std::string& buffer, const uint64_t value)
410 {
411  OtsUDPFirmwareCore::writeAdvanced(buffer,
412  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */,
413  value /* data */);
414 }
415 
416 //========================================================================================================================
417 void OtsUDPFirmwareCore::readControlDestinationIP(std::string& buffer)
418 {
419  OtsUDPFirmwareCore::readAdvanced(buffer,
420  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_IP /* addr */);
421 }
422 
423 //========================================================================================================================
424 void OtsUDPFirmwareCore::readControlDestinationMAC(std::string& buffer)
425 {
426  OtsUDPFirmwareCore::readAdvanced(buffer,
427  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_MAC /* addr */);
428 }
429 
430 //========================================================================================================================
431 void OtsUDPFirmwareCore::readControlDestinationPort(std::string& buffer)
432 {
433  OtsUDPFirmwareCore::readAdvanced(buffer,
434  UDP_CORE_BLOCK_ADDRESS | ADDR_CTRL_DEST_PORT /* addr */);
435 }
436 
437 //========================================================================================================================
438 void OtsUDPFirmwareCore::readUDPFirmwareVersion(std::string& buffer)
439 {
440  OtsUDPFirmwareCore::readAdvanced(buffer,
441  UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_VERSION /* addr */);
442 }
443 
444 //========================================================================================================================
445 void OtsUDPFirmwareCore::ethernetReset(std::string& buffer)
446 {
447  OtsUDPFirmwareCore::writeAdvanced(buffer,
448  UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */,
449  1 | (1<<1 /*for soft reset*/) /* data */);
450 }
451 //========================================================================================================================
452 void OtsUDPFirmwareCore::ethernetUnreset(std::string& buffer)
453 {
454  OtsUDPFirmwareCore::writeAdvanced(buffer,
455  UDP_CORE_BLOCK_ADDRESS | ADDR_SELF_RESET /* addr */,
456  0 /* data */);
457 }
458 
459 //========================================================================================================================
460 void OtsUDPFirmwareCore::startBurst(std::string& buffer)
461 {
462  __COUT__ << std::endl;
463  OtsUDPFirmwareCore::writeAdvanced(buffer,
464  UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */,
465  1 /* data */);
466 }
467 
468 //========================================================================================================================
469 void OtsUDPFirmwareCore::stopBurst(std::string& buffer)
470 {
471  __COUT__ << std::endl;
472  OtsUDPFirmwareCore::writeAdvanced(buffer,
473  UDP_CORE_BLOCK_ADDRESS | ADDR_BURST_MODE /* addr */,
474  0 /* data */);
475 }
476