$treeview $search $mathjax $extrastylesheet
otsdaq_components
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include <iostream> 00002 #include <set> 00003 #include "otsdaq-components/FEInterfaces/FEOtsUDPProducerTemplateInterface.h" 00004 #include "otsdaq-core/Macros/CoutMacros.h" 00005 #include "otsdaq-core/Macros/InterfacePluginMacros.h" 00006 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00007 00008 using namespace ots; 00009 00010 //======================================================================================================================== 00011 FEOtsUDPProducerTemplateInterface::FEOtsUDPProducerTemplateInterface( 00012 const std::string& interfaceUID, 00013 const ConfigurationTree& theXDAQContextConfigTree, 00014 const std::string& interfaceConfigurationPath) 00015 : Socket(theXDAQContextConfigTree.getNode(interfaceConfigurationPath) 00016 .getNode("HostIPAddress") 00017 .getValue<std::string>(), 00018 theXDAQContextConfigTree.getNode(interfaceConfigurationPath) 00019 .getNode("HostPort") 00020 .getValue<unsigned int>()) 00021 //, WorkLoop (interfaceUID + "-workloop") 00022 , FEProducerVInterface( 00023 interfaceUID, theXDAQContextConfigTree, interfaceConfigurationPath) 00024 //, DataProducer ("supervisorID","bufferID","processorID",100/*bufferSize*/) 00025 , OtsUDPHardware(theXDAQContextConfigTree.getNode(interfaceConfigurationPath) 00026 .getNode("InterfaceIPAddress") 00027 .getValue<std::string>(), 00028 theXDAQContextConfigTree.getNode(interfaceConfigurationPath) 00029 .getNode("InterfacePort") 00030 .getValue<unsigned int>()) 00031 , OtsUDPFirmwareDataGen(theXDAQContextConfigTree.getNode(interfaceConfigurationPath) 00032 .getNode("FirmwareVersion") 00033 .getValue<unsigned int>()) 00034 { 00035 // registration of FEMacro 'varTest2' generated, Oct-11-2018 02:28:57, by 'admin' 00036 // using MacroMaker. 00037 FEVInterface::registerFEMacroFunction( 00038 "varTest2", // feMacroName 00039 static_cast<FEVInterface::frontEndMacroFunction_t>( 00040 &FEOtsUDPProducerTemplateInterface::varTest2), // feMacroFunction 00041 std::vector<std::string>{"myOtherArg"}, // namesOfInputArgs 00042 std::vector<std::string>{"myArg", "outArg1"}, // namesOfOutputArgs 00043 1); // requiredUserPermissions 00044 00045 // registration of FEMacro 'varTest' generated, Oct-11-2018 11:36:28, by 'admin' using 00046 // MacroMaker. 00047 FEVInterface::registerFEMacroFunction( 00048 "varTest", // feMacroName 00049 static_cast<FEVInterface::frontEndMacroFunction_t>( 00050 &FEOtsUDPProducerTemplateInterface::varTest), // feMacroFunction 00051 std::vector<std::string>{"myOtherArg"}, // namesOfInputArgs 00052 std::vector<std::string>{"myArg", "outArg1"}, // namesOfOutputArgs 00053 1); // requiredUserPermissions 00054 00055 universalAddressSize_ = 8; 00056 universalDataSize_ = 8; 00057 } 00058 00059 //======================================================================================================================== 00060 FEOtsUDPProducerTemplateInterface::~FEOtsUDPProducerTemplateInterface(void) {} 00061 00062 //======================================================================================================================== 00063 void FEOtsUDPProducerTemplateInterface::configure(void) 00064 { 00065 // unsigned int i = VStateMachine::getIterationIndex(); 00066 // unsigned int j = VStateMachine::getSubIterationIndex(); 00067 // if(i == 0 && j < 5) 00068 // VStateMachine::indicateSubIterationWork(); 00069 // else if(i < 10) 00070 // VStateMachine::indicateIterationWork(); 00071 // 00072 // __FE_COUTV__(VStateMachine::getSubIterationIndex()); 00073 // __FE_COUTV__(VStateMachine::getSubIterationWork()); 00074 // __FE_COUTV__(VStateMachine::getIterationIndex()); 00075 // __FE_COUTV__(VStateMachine::getIterationWork()); 00076 // 00077 // __FE_COUTV__(i); 00078 // __FE_COUTV__(getInterfaceUID()); 00079 // switch(i) 00080 // { 00081 // case 1: 00082 // if(getInterfaceUID() == "ExampleInterface0") 00083 // { 00084 // FEVInterface::sendToFrontEnd("ExampleInterface1","Hello1"); 00085 // FEVInterface::sendToFrontEnd("ExampleInterface1",4.3f); 00086 // FEVInterface::sendToFrontEnd("ExampleInterface1",4); 00087 // FEVInterface::sendToFrontEnd("ExampleInterface2","Hello2"); 00088 // FEVInterface::sendToFrontEnd("ExampleInterface2",4.6f); 00089 // FEVInterface::sendToFrontEnd("ExampleInterface2",6); 00090 // } 00091 // break; 00092 // case 2: 00093 // if(getInterfaceUID() != "ExampleInterface0") 00094 // { 00095 // std::string a = FEVInterface::receiveFromFrontEnd("ExampleInterface0"); 00096 // double b = FEVInterface::receiveFromFrontEnd<double>("ExampleInterface0"); 00097 // unsigned short c = 00098 // FEVInterface::receiveFromFrontEnd<unsigned 00099 // short>("ExampleInterface0"); 00100 // __FE_COUTV__(a); 00101 // __FE_COUTV__(b); 00102 // __FE_COUTV__(c); 00103 // } 00104 // break; 00105 // case 3: 00106 // if(getInterfaceUID() == "ExampleInterface0") 00107 // { 00108 // std::vector<frontEndMacroArg_t> argsIn; 00109 // __SET_ARG_IN__("myOtherArg",(unsigned int)5); 00110 // 00111 // std::vector<frontEndMacroArg_t> argsOut; 00112 // 00113 // __FE_COUTV__(StringMacros::vectorToString(argsIn)); 00114 // 00115 // FEVInterface::runFrontEndMacro("ExampleInterface2","varTest2", 00116 // argsIn,argsOut); 00117 // 00118 // __FE_COUTV__(StringMacros::vectorToString(argsOut)); 00119 // __FE_COUTV__(FEVInterface::getFEMacroArgument( 00120 // argsOut,"outArg1")); 00121 // 00122 // { 00123 // std::string a = FEVInterface::getFEMacroArgument( 00124 // argsOut,"myArg"); 00125 // double b = getFEMacroArgumentValue<double>( 00126 // argsOut,"outArg1"); 00127 // unsigned short c = getFEMacroArgumentValue<unsigned short>( 00128 // argsOut,"outArg1"); 00129 // __FE_COUTV__(a); 00130 // __FE_COUTV__(b); 00131 // __FE_COUTV__(c); 00132 // } 00133 // 00134 // 00135 // 00136 // FEVInterface::runFrontEndMacro("ExampleInterface1","varTest", 00137 // argsIn,argsOut); 00138 // __FE_COUTV__(StringMacros::vectorToString(argsOut)); 00139 // 00140 // { 00141 // std::string a = __GET_ARG_OUT__("myArg",std::string); 00142 // double b = __GET_ARG_OUT__("outArg1",double); 00143 // unsigned short c = __GET_ARG_OUT__("outArg1",unsigned short); 00144 // __FE_COUTV__(a); 00145 // __FE_COUTV__(b); 00146 // __FE_COUTV__(c); 00147 // } 00148 // } 00149 // 00150 // break; 00151 // default:; 00152 // } 00153 // 00154 // 00155 // return; 00156 00157 __FE_COUT__ << "configure" << __E__; 00158 __FE_COUT__ << "Clearing receive socket buffer: " << OtsUDPHardware::clearReadSocket() 00159 << " packets cleared." << __E__; 00160 00161 std::string sendBuffer; 00162 std::string recvBuffer; 00163 uint64_t readQuadWord; 00164 00165 __FE_COUT__ 00166 << "Configuration Path Table: " 00167 << theXDAQContextConfigTree_.getNode(theConfigurationPath_).getTableName() << "-v" 00168 << theXDAQContextConfigTree_.getNode(theConfigurationPath_).getTableVersion() 00169 << __E__; 00170 00171 __FE_COUT__ << "Interface name: " 00172 << theXDAQContextConfigTree_.getNode(theConfigurationPath_) << __E__; 00173 00174 __FE_COUT__ << "Configured Firmware Version: " 00175 << theXDAQContextConfigTree_.getNode(theConfigurationPath_) 00176 .getNode("FirmwareVersion") 00177 .getValue<unsigned int>() 00178 << __E__; 00179 00180 __FE_COUT__ << "Setting Destination IP: " 00181 << theXDAQContextConfigTree_.getNode(theConfigurationPath_) 00182 .getNode("StreamToIPAddress") 00183 .getValue<std::string>() 00184 << __E__; 00185 __FE_COUT__ << "And Destination Port: " 00186 << theXDAQContextConfigTree_.getNode(theConfigurationPath_) 00187 .getNode("StreamToPort") 00188 .getValue<unsigned int>() 00189 << __E__; 00190 00191 OtsUDPFirmwareCore::setDataDestination( 00192 sendBuffer, 00193 theXDAQContextConfigTree_.getNode(theConfigurationPath_) 00194 .getNode("StreamToIPAddress") 00195 .getValue<std::string>(), 00196 theXDAQContextConfigTree_.getNode(theConfigurationPath_) 00197 .getNode("StreamToPort") 00198 .getValue<uint64_t>()); 00199 OtsUDPHardware::write(sendBuffer); 00200 00201 __FE_COUT__ << "Reading back burst dest MAC/IP/Port: " << __E__; 00202 00203 OtsUDPFirmwareCore::readDataDestinationMAC(sendBuffer); 00204 OtsUDPHardware::read(sendBuffer, readQuadWord); 00205 00206 OtsUDPFirmwareCore::readDataDestinationIP(sendBuffer); 00207 OtsUDPHardware::read(sendBuffer, readQuadWord); 00208 00209 OtsUDPFirmwareCore::readDataDestinationPort(sendBuffer); 00210 OtsUDPHardware::read(sendBuffer, readQuadWord); 00211 00212 OtsUDPFirmwareCore::readControlDestinationPort(sendBuffer); 00213 OtsUDPHardware::read(sendBuffer, readQuadWord); 00214 00215 // Run Configure Sequence Commands 00216 FEVInterface::runSequenceOfCommands("LinkToConfigureSequence"); 00217 00218 __FE_COUT__ << "Done with ots Template configuring." << __E__; 00219 } 00220 00221 //======================================================================================================================== 00222 // void FEOtsUDPProducerTemplateInterface::configureDetector(const DACStream& 00223 // theDACStream) 00224 //{ 00225 // __FE_COUT__ << "\tconfigureDetector" << __E__; 00226 //} 00227 00228 //======================================================================================================================== 00229 void FEOtsUDPProducerTemplateInterface::halt(void) 00230 { 00231 __FE_COUT__ << "\tHalt" << __E__; 00232 stop(); 00233 } 00234 00235 //======================================================================================================================== 00236 void FEOtsUDPProducerTemplateInterface::pause(void) 00237 { 00238 __FE_COUT__ << "\tPause" << __E__; 00239 stop(); 00240 } 00241 00242 //======================================================================================================================== 00243 void FEOtsUDPProducerTemplateInterface::resume(void) 00244 { 00245 __FE_COUT__ << "\tResume" << __E__; 00246 start(""); 00247 } 00248 00249 //======================================================================================================================== 00250 void FEOtsUDPProducerTemplateInterface::start(std::string) // runNumber) 00251 { 00252 __FE_COUT__ << "\tStart" << __E__; 00253 00254 // unsigned int i = VStateMachine::getIterationIndex(); 00255 // unsigned int j = VStateMachine::getSubIterationIndex(); 00256 // if(i == 0 && j < 5) 00257 // VStateMachine::indicateSubIterationWork(); 00258 // else if(i < 10) 00259 // VStateMachine::indicateIterationWork(); 00260 // 00261 // 00262 // __FE_COUTV__(VStateMachine::getSubIterationIndex()); 00263 // __FE_COUTV__(VStateMachine::getSubIterationWork()); 00264 // __FE_COUTV__(VStateMachine::getIterationIndex()); 00265 // __FE_COUTV__(VStateMachine::getIterationWork()); 00266 // 00267 // 00268 // return; 00269 00270 // Run Start Sequence Commands 00271 FEVInterface::runSequenceOfCommands("LinkToStartSequence"); 00272 00273 std::string sendBuffer; 00274 OtsUDPFirmwareCore::startBurst(sendBuffer); 00275 OtsUDPHardware::write(sendBuffer); 00276 } 00277 00278 //======================================================================================================================== 00279 void FEOtsUDPProducerTemplateInterface::stop(void) 00280 { 00281 __FE_COUT__ << "\tStop" << __E__; 00282 00283 // Run Stop Sequence Commands 00284 00285 FEVInterface::runSequenceOfCommands("LinkToStopSequence"); 00286 00287 std::string sendBuffer; 00288 OtsUDPFirmwareCore::stopBurst(sendBuffer); 00289 OtsUDPHardware::write(sendBuffer); 00290 } 00291 00292 //======================================================================================================================== 00293 bool FEOtsUDPProducerTemplateInterface::running(void) 00294 { 00295 __FE_COUT__ << "\tRunning" << __E__; 00296 00297 //__SS__ << "?" << __E__; //test exceptions during running 00298 //__SS_THROW__; 00299 00300 int state = -1; 00301 while(WorkLoop::continueWorkLoop_) 00302 { 00303 // while running 00304 // play with the LEDs at address 0x1003 00305 00306 ++state; 00307 if(state < 8) 00308 sleep(1); 00309 else 00310 { 00311 // if(1 || getInterfaceUID() == "ExampleInterface1") 00312 // { 00313 // throw __OTS_SOFT_EXCEPTION__("Soft error here"); 00314 // } 00315 // else 00316 break; 00317 } 00318 00319 { 00320 if(DataProducerBase::attachToEmptySubBuffer(dataP_, headerP_) < 0) 00321 { 00322 __CFG_COUT__ << "There are no available buffers! Retrying...after " 00323 "waiting 10 milliseconds!" 00324 << std::endl; 00325 usleep(10000); 00326 return true; 00327 } 00328 00329 if(1) // test data buffers 00330 { 00331 // sleep(1); 00332 unsigned long long value = 0xB57321; // this is 8-bytes 00333 std::string& buffer = *dataP_; 00334 buffer.resize(8); // NOTE: this is inexpensive according to 00335 // Lorenzo/documentation in C++11 (only increases size 00336 // once and doesn't decrease size) 00337 memcpy( 00338 (void*)&buffer[0] /*dest*/, (void*)&value /*src*/, 8 /*numOfBytes*/); 00339 00340 // size() and length() are equivalent 00341 __CFG_COUT__ << "Writing to buffer " << buffer.size() << " bytes!" 00342 << __E__; 00343 __CFG_COUT__ << "Writing to buffer length " << buffer.length() 00344 << " bytes!" << __E__; 00345 00346 __CFG_COUT__ << "Buffer Data: " 00347 << BinaryStringMacros::binaryTo8ByteHexString(buffer) 00348 << __E__; 00349 00350 __CFG_COUTV__(DataProcessor::theCircularBuffer_); 00351 00352 __CFG_COUT__ << __E__; 00353 00354 __CFG_COUT__ << __E__; 00355 00356 DataProducerBase::setWrittenSubBuffer< 00357 std::string, 00358 std::map<std::string, std::string> >(); 00359 __CFG_COUT__ << __E__; 00360 __CFG_COUTV__(DataProcessor::theCircularBuffer_); 00361 } 00362 } 00363 if(0) 00364 { 00365 unsigned long long value = 0xA54321; // this is 8-bytes 00366 std::string buffer; 00367 buffer.resize(8); // NOTE: this is inexpensive according to 00368 // Lorenzo/documentation in C++11 (only increases size once 00369 // and doesn't decrease size) 00370 memcpy((void*)&buffer[0] /*dest*/, (void*)&value /*src*/, 8 /*numOfBytes*/); 00371 00372 // size() and length() are equivalent 00373 __FE_COUT__ << "Writing to buffer " << buffer.size() << " bytes!" << __E__; 00374 __FE_COUT__ << "Writing to buffer length " << buffer.length() << " bytes!" 00375 << __E__; 00376 00377 __FE_COUT__ << "Buffer Data: " 00378 << BinaryStringMacros::binaryTo8ByteHexString(buffer) << __E__; 00379 00380 FEProducerVInterface::copyToNextBuffer(buffer); 00381 } 00382 } 00383 00384 // //example! 00385 // //play with array of 8 LEDs at address 0x1003 00386 00387 // 00388 // bool flashLEDsWhileRunning = false; 00389 // if(flashLEDsWhileRunning) 00390 // { 00391 // std::string writeBuffer; 00392 // int state = -1; 00393 // while(WorkLoop::continueWorkLoop_) 00394 // { 00395 // //while running 00396 // //play with the LEDs at address 0x1003 00397 // 00398 // ++state; 00399 // if(state < 8) 00400 // { 00401 // writeBuffer.resize(0); 00402 // OtsUDPFirmwareCore::write(writeBuffer, 0x1003,1<<state); 00403 // OtsUDPHardware::write(writeBuffer); 00404 // } 00405 // else if(state%2 == 1 && state < 11) 00406 // { 00407 // writeBuffer.resize(0); 00408 // OtsUDPFirmwareCore::write(writeBuffer, 0x1003, 0xFF); 00409 // OtsUDPHardware::write(writeBuffer); 00410 // } 00411 // else if(state%2 == 0 && state < 11) 00412 // { 00413 // writeBuffer.resize(0); 00414 // OtsUDPFirmwareCore::write(writeBuffer, 0x1003,0); 00415 // OtsUDPHardware::write(writeBuffer); 00416 // } 00417 // else 00418 // state = -1; 00419 // 00420 // sleep(1); 00421 // } 00422 // } 00423 00424 return false; 00425 } 00426 00427 //======================================================================================================================== 00428 // NOTE: buffer for address must be at least size universalAddressSize_ 00429 // NOTE: buffer for returnValue must be max UDP size to handle return possibility 00430 void ots::FEOtsUDPProducerTemplateInterface::universalRead(char* address, 00431 char* returnValue) 00432 { 00433 __FE_COUT__ << "address size " << universalAddressSize_ << __E__; 00434 00435 __FE_COUT__ << "Request: "; 00436 for(unsigned int i = 0; i < universalAddressSize_; ++i) 00437 printf("%2.2X", (unsigned char)address[i]); 00438 std::cout << __E__; 00439 00440 std::string readBuffer, sendBuffer; 00441 OtsUDPFirmwareCore::readAdvanced(sendBuffer, address, 1 /*size*/); 00442 00443 OtsUDPHardware::read(sendBuffer, readBuffer); // data reply 00444 00445 __FE_COUT__ << "Result SIZE: " << readBuffer.size() << __E__; 00446 std::memcpy(returnValue, readBuffer.substr(2).c_str(), universalDataSize_); 00447 } // end universalRead() 00448 00449 //======================================================================================================================== 00450 // NOTE: buffer for address must be at least size universalAddressSize_ 00451 // NOTE: buffer for writeValue must be at least size universalDataSize_ 00452 void ots::FEOtsUDPProducerTemplateInterface::universalWrite(char* address, 00453 char* writeValue) 00454 { 00455 __FE_COUT__ << "address size " << universalAddressSize_ << __E__; 00456 __FE_COUT__ << "data size " << universalDataSize_ << __E__; 00457 __FE_COUT__ << "Sending: "; 00458 for(unsigned int i = 0; i < universalAddressSize_; ++i) 00459 printf("%2.2X", (unsigned char)address[i]); 00460 std::cout << __E__; 00461 00462 std::string sendBuffer; 00463 OtsUDPFirmwareCore::writeAdvanced(sendBuffer, address, writeValue, 1 /*size*/); 00464 OtsUDPHardware::write(sendBuffer); // data request 00465 } // end universalWrite() 00466 00467 //======================================================================================================================== 00468 // varTest 00469 // FEMacro 'varTest' generated, Oct-11-2018 11:36:28, by 'admin' using MacroMaker. 00470 // Macro Notes: This is a great test! 00471 void FEOtsUDPProducerTemplateInterface::varTest(__ARGS__) 00472 { 00473 __FE_COUT__ << "# of input args = " << argsIn.size() << __E__; 00474 __FE_COUT__ << "# of output args = " << argsOut.size() << __E__; 00475 for(auto& argIn : argsIn) 00476 __FE_COUT__ << argIn.first << ": " << argIn.second << __E__; 00477 00478 // macro commands section 00479 { 00480 char* address = new char[universalAddressSize_]{ 00481 0}; //create address buffer of interface size and init to all 0 00482 char* data = new char[universalDataSize_]{ 00483 0}; //create data buffer of interface size and init to all 0 00484 uint64_t macroAddress; // create macro address buffer (size 8 bytes) 00485 uint64_t macroData; // create macro address buffer (size 8 bytes) 00486 std::map<std::string /*arg name*/, uint64_t /*arg val*/> 00487 macroArgs; // create map from arg name to 64-bit number 00488 00489 // command-#0: Read(0x1002 /*address*/,myArg /*data*/); 00490 macroAddress = 0x1002; 00491 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00492 universalRead(address, data); 00493 memcpy(¯oArgs["myArg"], data, 8); // copy buffer to argument map 00494 __SET_ARG_OUT__("myArg", macroArgs["myArg"]); // update output argument result 00495 00496 // command-#1: Read(0x1001 /*address*/,data); 00497 macroAddress = 0x1001; 00498 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00499 universalRead(address, data); 00500 memcpy(¯oArgs["outArg1"], data, 8); // copy buffer to argument map 00501 __SET_ARG_OUT__("outArg1", macroArgs["outArg1"]); // update output argument 00502 // result 00503 00504 // command-#2: Write(0x1002 /*address*/,myOtherArg /*data*/); 00505 macroAddress = 0x1002; 00506 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00507 macroArgs["myOtherArg"] = __GET_ARG_IN__( 00508 "myOtherArg", 00509 uint64_t); // initialize from input arguments //get macro data argument 00510 memcpy(data, ¯oArgs["myOtherArg"], 8); // copy macro data argument to buffer 00511 universalWrite(address, data); 00512 00513 // command-#3: Write(0x1001 /*address*/,myArg /*data*/); 00514 macroAddress = 0x1001; 00515 memcpy(address, 00516 ¯oAddress, 00517 8); // copy macro address to buffer //get macro data argument 00518 memcpy(data, ¯oArgs["myArg"], 8); // copy macro data argument to buffer 00519 universalWrite(address, data); 00520 00521 // command-#4: delay(4); 00522 __FE_COUT__ << "Sleeping for... " << 4 << " milliseconds " << __E__; 00523 usleep(4 * 1000 /* microseconds */); 00524 00525 delete[] address; // free the memory 00526 delete[] data; // free the memory 00527 } 00528 00529 for(auto& argOut : argsOut) 00530 __FE_COUT__ << argOut.first << ": " << argOut.second << __E__; 00531 00532 } // end varTest() 00533 00534 //======================================================================================================================== 00535 // varTest2 00536 // FEMacro 'varTest2' generated, Oct-11-2018 02:28:57, by 'admin' using MacroMaker. 00537 // Macro Notes: [Modified 14:28 10/11/2018] This is a great test! 00538 void FEOtsUDPProducerTemplateInterface::varTest2(__ARGS__) 00539 { 00540 __FE_COUT__ << "# of input args = " << argsIn.size() << __E__; 00541 __FE_COUT__ << "# of output args = " << argsOut.size() << __E__; 00542 for(auto& argIn : argsIn) 00543 __FE_COUT__ << argIn.first << ": " << argIn.second << __E__; 00544 00545 // macro commands section 00546 { 00547 char* address = new char[universalAddressSize_]{ 00548 0}; //create address buffer of interface size and init to all 0 00549 char* data = new char[universalDataSize_]{ 00550 0}; //create data buffer of interface size and init to all 0 00551 uint64_t macroAddress; // create macro address buffer (size 8 bytes) 00552 uint64_t macroData; // create macro address buffer (size 8 bytes) 00553 std::map<std::string /*arg name*/, uint64_t /*arg val*/> 00554 macroArgs; // create map from arg name to 64-bit number 00555 00556 // command-#0: Read(0x1002 /*address*/,myArg /*data*/); 00557 macroAddress = 0x1002; 00558 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00559 universalRead(address, data); 00560 memcpy(¯oArgs["myArg"], data, 8); // copy buffer to argument map 00561 __SET_ARG_OUT__("myArg", macroArgs["myArg"]); // update output argument result 00562 00563 // command-#1: Read(0x1001 /*address*/,data); 00564 macroAddress = 0x1001; 00565 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00566 universalRead(address, data); 00567 memcpy(¯oArgs["outArg1"], data, 8); // copy buffer to argument map 00568 __SET_ARG_OUT__("outArg1", macroArgs["outArg1"]); // update output argument 00569 // result 00570 00571 // command-#2: Write(0x1002 /*address*/,myOtherArg /*data*/); 00572 macroAddress = 0x1002; 00573 memcpy(address, ¯oAddress, 8); // copy macro address to buffer 00574 macroArgs["myOtherArg"] = __GET_ARG_IN__( 00575 "myOtherArg", 00576 uint64_t); // initialize from input arguments //get macro data argument 00577 memcpy(data, ¯oArgs["myOtherArg"], 8); // copy macro data argument to buffer 00578 universalWrite(address, data); 00579 00580 // command-#3: Write(0x1001 /*address*/,myArg /*data*/); 00581 macroAddress = 0x1001; 00582 memcpy(address, 00583 ¯oAddress, 00584 8); // copy macro address to buffer //get macro data argument 00585 memcpy(data, ¯oArgs["myArg"], 8); // copy macro data argument to buffer 00586 universalWrite(address, data); 00587 00588 // command-#4: delay(4); 00589 __FE_COUT__ << "Sleeping for... " << 4 << " milliseconds " << __E__; 00590 usleep(4 * 1000 /* microseconds */); 00591 00592 delete[] address; // free the memory 00593 delete[] data; // free the memory 00594 } 00595 00596 for(auto& argOut : argsOut) 00597 __FE_COUT__ << argOut.first << ": " << argOut.second << __E__; 00598 00599 } // end varTest2() 00600 00601 DEFINE_OTS_INTERFACE(FEOtsUDPProducerTemplateInterface)