otsdaq_components  v2_05_02_indev
FEOtsUDPTemplateInterface_interface.cc
1 #include <iostream>
2 #include <set>
3 #include "otsdaq-components/FEInterfaces/FEOtsUDPTemplateInterface.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/Macros/InterfacePluginMacros.h"
6 #include "otsdaq/MessageFacility/MessageFacility.h"
7 
8 using namespace ots;
9 
10 //==============================================================================
11 FEOtsUDPTemplateInterface::FEOtsUDPTemplateInterface(
12  const std::string& interfaceUID,
13  const ConfigurationTree& theXDAQContextConfigTree,
14  const std::string& interfaceConfigurationPath)
15  : Socket(theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
16  .getNode("HostIPAddress")
17  .getValue<std::string>(),
18  theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
19  .getNode("HostPort")
20  .getValue<unsigned int>())
21  , FEVInterface(interfaceUID, theXDAQContextConfigTree, interfaceConfigurationPath)
22  , OtsUDPHardware(theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
23  .getNode("InterfaceIPAddress")
24  .getValue<std::string>(),
25  theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
26  .getNode("InterfacePort")
27  .getValue<unsigned int>())
28  , OtsUDPFirmwareDataGen(theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
29  .getNode("FirmwareVersion")
30  .getValue<unsigned int>())
31 {
32  // registration of FEMacro 'test' generated, Jan-20-2020 09:41:49, by 'admin' using
33  // MacroMaker.
34  FEVInterface::registerFEMacroFunction(
35  "test", // feMacroName
36  static_cast<FEVInterface::frontEndMacroFunction_t>(
37  &FEOtsUDPTemplateInterface::test), // feMacroFunction
38  std::vector<std::string>{}, // namesOfInputArgs
39  std::vector<std::string>{"outArg1"}, // namesOfOutputArgs
40  1); // requiredUserPermissions
41 
42  universalAddressSize_ = 8;
43  universalDataSize_ = 8;
44 
45  // example self-call of FE-macros
46  if (1)
47  {
48  // registration of FEMacro 'varTest2' generated, Oct-11-2018 02:28:57, by 'admin'
49  // using MacroMaker.
50  FEVInterface::registerFEMacroFunction(
51  "varTest2", // feMacroName
52  static_cast<FEVInterface::frontEndMacroFunction_t>(
53  &FEOtsUDPTemplateInterface::varTest2), // feMacroFunction
54  std::vector<std::string>{"myOtherArg"}, // namesOfInputArgs
55  std::vector<std::string>{"myArg", "outArg1"}, // namesOfOutputArgs
56  1); // requiredUserPermissions
57 
58  // registration of FEMacro 'varTest' generated, Oct-11-2018 11:36:28, by 'admin'
59  // using MacroMaker.
60  FEVInterface::registerFEMacroFunction(
61  "varTest", // feMacroName
62  static_cast<FEVInterface::frontEndMacroFunction_t>(
63  &FEOtsUDPTemplateInterface::varTest), // feMacroFunction
64  std::vector<std::string>{"myOtherArg"}, // namesOfInputArgs
65  std::vector<std::string>{"myArg", "outArg1"}, // namesOfOutputArgs
66  1); // requiredUserPermissions
67 
68  std::vector<frontEndMacroArg_t> argsIn;
69  __SET_ARG_IN__("myOtherArg", (unsigned int)5);
70 
71  std::vector<frontEndMacroArg_t> argsOut;
72 
73  __FE_COUTV__(StringMacros::vectorToString(argsIn));
74 
75  runSelfFrontEndMacro("varTest2", argsIn, argsOut);
76 
77  __FE_COUTV__(StringMacros::vectorToString(argsOut));
78  __FE_COUTV__(FEVInterface::getFEMacroArgument(argsOut, "outArg1"));
79 
80  {
81  std::string a = FEVInterface::getFEMacroArgument(argsOut, "myArg");
82  double b = getFEMacroArgumentValue<double>(argsOut, "outArg1");
83  unsigned short c =
84  getFEMacroArgumentValue<unsigned short>(argsOut, "outArg1");
85  __FE_COUTV__(a);
86  __FE_COUTV__(b);
87  __FE_COUTV__(c);
88  }
89  } // end example of calling own FE-macros
90 
91 } // end constructor
92 
93 //==============================================================================
94 FEOtsUDPTemplateInterface::~FEOtsUDPTemplateInterface(void) {}
95 
96 //==============================================================================
97 void FEOtsUDPTemplateInterface::configure(void)
98 {
99  //unsigned int i = VStateMachine::getIterationIndex();
100  //unsigned int j = VStateMachine::getSubIterationIndex();
101  // if(i == 0 && j < 5)
102  // {
103  // VStateMachine::indicateSubIterationWork();
104  // sleep(3);
105  // }
106  // else if(i < 10)
107  // {
108  // VStateMachine::indicateIterationWork();
109  // sleep(1);
110  // }
111  //
112  // __FE_COUTV__(VStateMachine::getSubIterationIndex());
113  // __FE_COUTV__(VStateMachine::getSubIterationWork());
114  // __FE_COUTV__(VStateMachine::getIterationIndex());
115  // __FE_COUTV__(VStateMachine::getIterationWork());
116  //
117  // __FE_COUTV__(i);
118  // __FE_COUTV__(getInterfaceUID());
119  // switch(i)
120  // {
121  // case 1:
122  // if(getInterfaceUID() == "ExampleInterface0")
123  // {
124  // FEVInterface::sendToFrontEnd("ExampleInterface1","Hello1");
125  // FEVInterface::sendToFrontEnd("ExampleInterface1",4.3f);
126  // FEVInterface::sendToFrontEnd("ExampleInterface1",4);
127  // FEVInterface::sendToFrontEnd("ExampleInterface2","Hello2");
128  // FEVInterface::sendToFrontEnd("ExampleInterface2",4.6f);
129  // FEVInterface::sendToFrontEnd("ExampleInterface2",6);
130  // }
131  // break;
132  // case 2:
133  // if(getInterfaceUID() != "ExampleInterface0")
134  // {
135  // std::string a = FEVInterface::receiveFromFrontEnd("ExampleInterface0");
136  // double b = FEVInterface::receiveFromFrontEnd<double>("ExampleInterface0");
137  // unsigned short c =
138  // FEVInterface::receiveFromFrontEnd<unsigned
139  // short>("ExampleInterface0");
140  // __FE_COUTV__(a);
141  // __FE_COUTV__(b);
142  // __FE_COUTV__(c);
143  // }
144  // break;
145  // case 3:
146  // if(getInterfaceUID() == "ExampleInterface0")
147  // {
148  // std::vector<frontEndMacroArg_t> argsIn;
149  // __SET_ARG_IN__("myOtherArg",(unsigned int)5);
150  //
151  // std::vector<frontEndMacroArg_t> argsOut;
152  //
153  // __FE_COUTV__(StringMacros::vectorToString(argsIn));
154  //
155  // FEVInterface::runFrontEndMacro("ExampleInterface2","varTest2",
156  // argsIn,argsOut);
157  //
158  // __FE_COUTV__(StringMacros::vectorToString(argsOut));
159  // __FE_COUTV__(FEVInterface::getFEMacroArgument(
160  // argsOut,"outArg1"));
161  //
162  // {
163  // std::string a = FEVInterface::getFEMacroArgument(
164  // argsOut,"myArg");
165  // double b = getFEMacroArgumentValue<double>(
166  // argsOut,"outArg1");
167  // unsigned short c = getFEMacroArgumentValue<unsigned short>(
168  // argsOut,"outArg1");
169  // __FE_COUTV__(a);
170  // __FE_COUTV__(b);
171  // __FE_COUTV__(c);
172  // }
173  //
174  //
175  //
176  // FEVInterface::runFrontEndMacro("ExampleInterface1","varTest",
177  // argsIn,argsOut);
178  // __FE_COUTV__(StringMacros::vectorToString(argsOut));
179  //
180  // {
181  // std::string a = __GET_ARG_OUT__("myArg",std::string);
182  // double b = __GET_ARG_OUT__("outArg1",double);
183  // unsigned short c = __GET_ARG_OUT__("outArg1",unsigned short);
184  // __FE_COUTV__(a);
185  // __FE_COUTV__(b);
186  // __FE_COUTV__(c);
187  // }
188  // }
189  //
190  // break;
191  // default:;
192  // }
193  //
194  //
195  // return;
196 
197  __FE_COUT__ << "configure" << __E__;
198  __FE_COUT__ << "Clearing receive socket buffer: " << OtsUDPHardware::clearReadSocket()
199  << " packets cleared." << __E__;
200 
201  std::string sendBuffer;
202  std::string recvBuffer;
203  uint64_t readQuadWord;
204 
205  __FE_COUT__
206  << "Configuration Path Table: "
207  << theXDAQContextConfigTree_.getNode(theConfigurationPath_).getTableName() << "-v"
208  << theXDAQContextConfigTree_.getNode(theConfigurationPath_).getTableVersion()
209  << __E__;
210 
211  __FE_COUT__ << "Interface name: "
212  << theXDAQContextConfigTree_.getNode(theConfigurationPath_) << __E__;
213 
214  __FE_COUT__ << "Configured Firmware Version: "
215  << theXDAQContextConfigTree_.getNode(theConfigurationPath_)
216  .getNode("FirmwareVersion")
217  .getValue<unsigned int>()
218  << __E__;
219 
220  __FE_COUT__ << "Setting Destination IP: "
221  << theXDAQContextConfigTree_.getNode(theConfigurationPath_)
222  .getNode("StreamToIPAddress")
223  .getValue<std::string>()
224  << __E__;
225  __FE_COUT__ << "And Destination Port: "
226  << theXDAQContextConfigTree_.getNode(theConfigurationPath_)
227  .getNode("StreamToPort")
228  .getValue<unsigned int>()
229  << __E__;
230 
231  OtsUDPFirmwareCore::setDataDestination(
232  sendBuffer,
233  theXDAQContextConfigTree_.getNode(theConfigurationPath_)
234  .getNode("StreamToIPAddress")
235  .getValue<std::string>(),
236  theXDAQContextConfigTree_.getNode(theConfigurationPath_)
237  .getNode("StreamToPort")
238  .getValue<uint64_t>());
239  OtsUDPHardware::write(sendBuffer);
240 
241  __FE_COUT__ << "Reading back burst dest MAC/IP/Port: " << __E__;
242 
243  OtsUDPFirmwareCore::readDataDestinationMAC(sendBuffer);
244  OtsUDPHardware::read(sendBuffer, readQuadWord);
245 
246  OtsUDPFirmwareCore::readDataDestinationIP(sendBuffer);
247  OtsUDPHardware::read(sendBuffer, readQuadWord);
248 
249  OtsUDPFirmwareCore::readDataDestinationPort(sendBuffer);
250  OtsUDPHardware::read(sendBuffer, readQuadWord);
251 
252  OtsUDPFirmwareCore::readControlDestinationPort(sendBuffer);
253  OtsUDPHardware::read(sendBuffer, readQuadWord);
254 
255  // Run Configure Sequence Commands
256  FEVInterface::runSequenceOfCommands("LinkToConfigureSequence");
257 
258  __FE_COUT__ << "Done with ots Template configuring." << __E__;
259 } // end configure()
260 
261 //==============================================================================
262 // void FEOtsUDPTemplateInterface::configureDetector(const DACStream& theDACStream)
263 //{
264 // __FE_COUT__ << "\tconfigureDetector" << __E__;
265 //}
266 
267 //==============================================================================
268 void FEOtsUDPTemplateInterface::halt(void)
269 {
270  __FE_COUT__ << "\tHalt" << __E__;
271  stop();
272 }
273 
274 //==============================================================================
275 void FEOtsUDPTemplateInterface::pause(void)
276 {
277  __FE_COUT__ << "\tPause" << __E__;
278  stop();
279 }
280 
281 //==============================================================================
282 void FEOtsUDPTemplateInterface::resume(void)
283 {
284  __FE_COUT__ << "\tResume" << __E__;
285  start("");
286 }
287 
288 //==============================================================================
289 void FEOtsUDPTemplateInterface::start(std::string) // runNumber)
290 {
291  __FE_COUT__ << "\tStart" << __E__;
292 
293  // unsigned int i = VStateMachine::getIterationIndex();
294  // unsigned int j = VStateMachine::getSubIterationIndex();
295  // if(i == 0 && j < 5)
296  // VStateMachine::indicateSubIterationWork();
297  // else if(i < 10)
298  // VStateMachine::indicateIterationWork();
299  //
300  //
301  // __FE_COUTV__(VStateMachine::getSubIterationIndex());
302  // __FE_COUTV__(VStateMachine::getSubIterationWork());
303  // __FE_COUTV__(VStateMachine::getIterationIndex());
304  // __FE_COUTV__(VStateMachine::getIterationWork());
305  //
306  //
307  // return;
308 
309  // Run Start Sequence Commands
310  FEVInterface::runSequenceOfCommands("LinkToStartSequence");
311 
312  std::string sendBuffer;
313  OtsUDPFirmwareCore::startBurst(sendBuffer);
314  OtsUDPHardware::write(sendBuffer);
315 }
316 
317 //==============================================================================
318 void FEOtsUDPTemplateInterface::stop(void)
319 {
320  __FE_COUT__ << "\tStop" << __E__;
321 
322  // Run Stop Sequence Commands
323 
324  FEVInterface::runSequenceOfCommands("LinkToStopSequence");
325 
326  std::string sendBuffer;
327  OtsUDPFirmwareCore::stopBurst(sendBuffer);
328  OtsUDPHardware::write(sendBuffer);
329 }
330 
331 //==============================================================================
332 bool FEOtsUDPTemplateInterface::running(void)
333 {
334  __FE_COUT__ << "\tRunning" << __E__;
335 
336  //__SS__ << "?" << __E__; //test exceptions during running
337  //__SS_THROW__;
338 
339  int state = -1;
340  while (WorkLoop::continueWorkLoop_)
341  {
342  // while running
343  // play with the LEDs at address 0x1003
344 
345  ++state;
346  if (state < 8)
347  sleep(1);
348  else
349  {
350  // if(1 || getInterfaceUID() == "ExampleInterface1")
351  // {
352  // __FE_SS__ << "Soft Error Here" << __E__;
353  // throw __OTS_SOFT_EXCEPTION__(ss.str());
354  // }
355  // else
356  break;
357  }
358  }
359 
360  // //example!
361  // //play with array of 8 LEDs at address 0x1003
362 
363  //
364  // bool flashLEDsWhileRunning = false;
365  // if(flashLEDsWhileRunning)
366  // {
367  // std::string writeBuffer;
368  // int state = -1;
369  // while(WorkLoop::continueWorkLoop_)
370  // {
371  // //while running
372  // //play with the LEDs at address 0x1003
373  //
374  // ++state;
375  // if(state < 8)
376  // {
377  // writeBuffer.resize(0);
378  // OtsUDPFirmwareCore::write(writeBuffer, 0x1003,1<<state);
379  // OtsUDPHardware::write(writeBuffer);
380  // }
381  // else if(state%2 == 1 && state < 11)
382  // {
383  // writeBuffer.resize(0);
384  // OtsUDPFirmwareCore::write(writeBuffer, 0x1003, 0xFF);
385  // OtsUDPHardware::write(writeBuffer);
386  // }
387  // else if(state%2 == 0 && state < 11)
388  // {
389  // writeBuffer.resize(0);
390  // OtsUDPFirmwareCore::write(writeBuffer, 0x1003,0);
391  // OtsUDPHardware::write(writeBuffer);
392  // }
393  // else
394  // state = -1;
395  //
396  // sleep(1);
397  // }
398  // }
399 
400  return false;
401 }
402 
403 //==============================================================================
404 // NOTE: buffer for address must be at least size universalAddressSize_
405 // NOTE: buffer for returnValue must be max UDP size to handle return possibility
406 void ots::FEOtsUDPTemplateInterface::universalRead(char* address, char* returnValue)
407 {
408  __FE_COUT__ << "address size " << universalAddressSize_ << __E__;
409 
410  __FE_COUT__ << "Universal Read Address: 0x";
411  for (unsigned int i = 0; i < universalAddressSize_; ++i)
412  printf("%2.2X", (unsigned char)address[universalAddressSize_ - 1 - i]);
413  std::cout << __E__;
414 
415  std::string readBuffer, sendBuffer;
416  OtsUDPFirmwareCore::readAdvanced(sendBuffer, address, 1 /*size*/);
417 
418  OtsUDPHardware::read(sendBuffer, readBuffer); // data reply
419 
420  __FE_COUT__ << "Result SIZE: " << readBuffer.size() << __E__;
421  std::memcpy(returnValue, readBuffer.substr(2).c_str(), universalDataSize_);
422 
423  __FE_COUT__ << "Universal Read Data: 0x";
424  for (unsigned int i = 0; i < universalDataSize_; ++i)
425  printf("%2.2X", (unsigned char)returnValue[universalDataSize_ - 1 - i]);
426  std::cout << __E__;
427 
428 } // end universalRead()
429 
430 //==============================================================================
431 // NOTE: buffer for address must be at least size universalAddressSize_
432 // NOTE: buffer for writeValue must be at least size universalDataSize_
433 void ots::FEOtsUDPTemplateInterface::universalWrite(char* address, char* writeValue)
434 {
435  __FE_COUT__ << "address size " << universalAddressSize_ << __E__;
436  __FE_COUT__ << "data size " << universalDataSize_ << __E__;
437  __FE_COUT__ << "Universal Write Address: 0x";
438  for (unsigned int i = 0; i < universalAddressSize_; ++i)
439  printf("%2.2X", (unsigned char)address[universalAddressSize_ - 1 - i]);
440  std::cout << __E__;
441  __FE_COUT__ << "Universal Write Data: 0x";
442  for (unsigned int i = 0; i < universalDataSize_; ++i)
443  printf("%2.2X", (unsigned char)writeValue[universalDataSize_ - 1 - i]);
444  std::cout << __E__;
445 
446  std::string sendBuffer;
447  OtsUDPFirmwareCore::writeAdvanced(sendBuffer, address, writeValue, 1 /*size*/);
448  OtsUDPHardware::write(sendBuffer); // data request
449 } // end universalWrite()
450 
451 //==============================================================================
452 // varTest
453 // FEMacro 'varTest' generated, Oct-11-2018 11:36:28, by 'admin' using MacroMaker.
454 // Macro Notes: This is a great test!
455 void FEOtsUDPTemplateInterface::varTest(__ARGS__)
456 {
457  __FE_COUT__ << "# of input args = " << argsIn.size() << __E__;
458  __FE_COUT__ << "# of output args = " << argsOut.size() << __E__;
459  for (auto& argIn : argsIn)
460  __FE_COUT__ << argIn.first << ": " << argIn.second << __E__;
461 
462  // macro commands section
463  {
464  char* address = new char[universalAddressSize_] {
465  0}; //create address buffer of interface size and init to all 0
466  char* data = new char[universalDataSize_] {
467  0}; //create data buffer of interface size and init to all 0
468  uint64_t macroAddress; // create macro address buffer (size 8 bytes)
469  //uint64_t macroData; // create macro address buffer (size 8 bytes)
470  std::map<std::string /*arg name*/, uint64_t /*arg val*/>
471  macroArgs; // create map from arg name to 64-bit number
472 
473  // command-#0: Read(0x1002 /*address*/,myArg /*data*/);
474  macroAddress = 0x1002;
475  memcpy(address, &macroAddress, 8); // copy macro address to buffer
476  universalRead(address, data);
477  memcpy(&macroArgs["myArg"], data, 8); // copy buffer to argument map
478  __SET_ARG_OUT__("myArg", macroArgs["myArg"]); // update output argument result
479 
480  // command-#1: Read(0x1001 /*address*/,data);
481  macroAddress = 0x1001;
482  memcpy(address, &macroAddress, 8); // copy macro address to buffer
483  universalRead(address, data);
484  memcpy(&macroArgs["outArg1"], data, 8); // copy buffer to argument map
485  __SET_ARG_OUT__("outArg1", macroArgs["outArg1"]); // update output argument
486  // result
487 
488  // command-#2: Write(0x1002 /*address*/,myOtherArg /*data*/);
489  macroAddress = 0x1002;
490  memcpy(address, &macroAddress, 8); // copy macro address to buffer
491  macroArgs["myOtherArg"] = __GET_ARG_IN__(
492  "myOtherArg",
493  uint64_t); // initialize from input arguments //get macro data argument
494  memcpy(data, &macroArgs["myOtherArg"], 8); // copy macro data argument to buffer
495  universalWrite(address, data);
496 
497  // command-#3: Write(0x1001 /*address*/,myArg /*data*/);
498  macroAddress = 0x1001;
499  memcpy(address,
500  &macroAddress,
501  8); // copy macro address to buffer //get macro data argument
502  memcpy(data, &macroArgs["myArg"], 8); // copy macro data argument to buffer
503  universalWrite(address, data);
504 
505  // command-#4: delay(4);
506  __FE_COUT__ << "Sleeping for... " << 4 << " milliseconds " << __E__;
507  usleep(4 * 1000 /* microseconds */);
508 
509  delete[] address; // free the memory
510  delete[] data; // free the memory
511  }
512 
513  for (auto& argOut : argsOut)
514  __FE_COUT__ << argOut.first << ": " << argOut.second << __E__;
515 
516 } // end varTest()
517 
518 //==============================================================================
519 // varTest2
520 // FEMacro 'varTest2' generated, Oct-11-2018 02:28:57, by 'admin' using MacroMaker.
521 // Macro Notes: [Modified 14:28 10/11/2018] This is a great test!
522 void FEOtsUDPTemplateInterface::varTest2(__ARGS__)
523 {
524  __FE_COUT__ << "# of input args = " << argsIn.size() << __E__;
525  __FE_COUT__ << "# of output args = " << argsOut.size() << __E__;
526  for (auto& argIn : argsIn)
527  __FE_COUT__ << argIn.first << ": " << argIn.second << __E__;
528 
529  __SET_ARG_OUT__("myArg", "hello2"); // update output argument result
530  uint64_t macroData = __GET_ARG_IN__("myOtherArg", uint64_t);
531  macroData *= 3;
532  __SET_ARG_OUT__("outArg1", macroData); // update output argument result
533 
534  for (auto& argOut : argsOut)
535  __FE_COUT__ << argOut.first << ": " << argOut.second << __E__;
536 
537 } // end varTest2()
538 
539 //========================================================================================================================
540 // test
541 // FEMacro 'test' generated, Jan-20-2020 09:41:49, by 'admin' using MacroMaker.
542 // Macro Notes: Testing notes
543 void FEOtsUDPTemplateInterface::test(__ARGS__)
544 {
545  __CFG_COUT__ << "# of input args = " << argsIn.size() << __E__;
546  __CFG_COUT__ << "# of output args = " << argsOut.size() << __E__;
547  for (auto& argIn : argsIn)
548  __CFG_COUT__ << argIn.first << ": " << argIn.second << __E__;
549 
550  // macro commands section
551  {
552  char* address = new char[universalAddressSize_] {
553  0}; //create address buffer of interface size and init to all 0
554  char* data = new char[universalDataSize_] {
555  0}; //create data buffer of interface size and init to all 0
556  uint64_t macroAddress; // create macro address buffer (size 8 bytes)
557  uint64_t macroData; // create macro address buffer (size 8 bytes)
558  std::map<std::string /*arg name*/, uint64_t /*arg val*/>
559  macroArgs; // create map from arg name to 64-bit number
560 
561  // command-#0: Write(0x4 /*address*/,0x2 /*data*/);
562  macroAddress = 0x4;
563  memcpy(address, &macroAddress, 8); // copy macro address to buffer
564  macroData = 0x2;
565  memcpy(data, &macroData, 8); // copy macro data to buffer
566  universalWrite(address, data);
567 
568  // command-#1: Read(0x4 /*address*/,data);
569  macroAddress = 0x4;
570  memcpy(address, &macroAddress, 8); // copy macro address to buffer
571  universalRead(address, data);
572  memcpy(&macroArgs["outArg1"], data, 8); // copy buffer to argument map
573  __SET_ARG_OUT__("outArg1", macroArgs["outArg1"]); // update output argument
574  // result
575 
576  delete[] address; // free the memory
577  delete[] data; // free the memory
578  }
579 
580  for (auto& argOut : argsOut)
581  __CFG_COUT__ << argOut.first << ": " << argOut.second << __E__;
582 
583 } // end test()
584 
585 DEFINE_OTS_INTERFACE(FEOtsUDPTemplateInterface)