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