00001 #include "otsdaq-components/FEInterfaces/FEOtsUDPProducerTemplateInterface.h"
00002 #include "otsdaq-core/MessageFacility/MessageFacility.h"
00003 #include "otsdaq-core/Macros/CoutMacros.h"
00004 #include "otsdaq-core/Macros/InterfacePluginMacros.h"
00005 #include <iostream>
00006 #include <set>
00007
00008 using namespace ots;
00009
00010
00011 FEOtsUDPProducerTemplateInterface::FEOtsUDPProducerTemplateInterface(const std::string& interfaceUID,
00012 const ConfigurationTree& theXDAQContextConfigTree, const std::string& interfaceConfigurationPath)
00013 : Socket (
00014 theXDAQContextConfigTree.getNode(interfaceConfigurationPath).getNode("HostIPAddress").getValue<std::string>()
00015 , theXDAQContextConfigTree.getNode(interfaceConfigurationPath).getNode("HostPort").getValue<unsigned int>())
00016
00017 , FEProducerVInterface (interfaceUID, theXDAQContextConfigTree, interfaceConfigurationPath)
00018
00019 , OtsUDPHardware (theXDAQContextConfigTree.getNode(interfaceConfigurationPath).getNode("InterfaceIPAddress").getValue<std::string>()
00020 , theXDAQContextConfigTree.getNode(interfaceConfigurationPath).getNode("InterfacePort").getValue<unsigned int>())
00021 , OtsUDPFirmwareDataGen(theXDAQContextConfigTree.getNode(interfaceConfigurationPath).getNode("FirmwareVersion").getValue<unsigned int>())
00022 {
00023
00024 FEVInterface::registerFEMacroFunction("varTest2",
00025 static_cast<FEVInterface::frontEndMacroFunction_t>(&FEOtsUDPProducerTemplateInterface::varTest2),
00026 std::vector<std::string>{"myOtherArg"},
00027 std::vector<std::string>{"myArg","outArg1"},
00028 1);
00029
00030
00031
00032 FEVInterface::registerFEMacroFunction("varTest",
00033 static_cast<FEVInterface::frontEndMacroFunction_t>(&FEOtsUDPProducerTemplateInterface::varTest),
00034 std::vector<std::string>{"myOtherArg"},
00035 std::vector<std::string>{"myArg","outArg1"},
00036 1);
00037
00038 universalAddressSize_ = 8;
00039 universalDataSize_ = 8;
00040 }
00041
00042
00043 FEOtsUDPProducerTemplateInterface::~FEOtsUDPProducerTemplateInterface(void)
00044 {}
00045
00046
00047 void FEOtsUDPProducerTemplateInterface::configure(void)
00048 {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 __FE_COUT__ << "configure" << __E__;
00141 __FE_COUT__ << "Clearing receive socket buffer: " << OtsUDPHardware::clearReadSocket() << " packets cleared." << __E__;
00142
00143 std::string sendBuffer;
00144 std::string recvBuffer;
00145 uint64_t readQuadWord;
00146
00147 __FE_COUT__ << "Configuration Path Table: " <<
00148 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getConfigurationName() <<
00149 "-v" <<
00150 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getConfigurationVersion() <<
00151 __E__;
00152
00153 __FE_COUT__ << "Interface name: " <<
00154 theXDAQContextConfigTree_.getNode(theConfigurationPath_) << __E__;
00155
00156 __FE_COUT__ << "Configured Firmware Version: " <<
00157 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("FirmwareVersion").getValue<unsigned int>()
00158 << __E__;
00159
00160 __FE_COUT__ << "Setting Destination IP: " <<
00161 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("StreamToIPAddress").getValue<std::string>()
00162 << __E__;
00163 __FE_COUT__ << "And Destination Port: " <<
00164 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("StreamToPort").getValue<unsigned int>()
00165 << __E__;
00166
00167 OtsUDPFirmwareCore::setDataDestination(sendBuffer,
00168 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("StreamToIPAddress").getValue<std::string>(),
00169 theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("StreamToPort").getValue<uint64_t>()
00170 );
00171 OtsUDPHardware::write(sendBuffer);
00172
00173 __FE_COUT__ << "Reading back burst dest MAC/IP/Port: " << __E__;
00174
00175 OtsUDPFirmwareCore::readDataDestinationMAC(sendBuffer);
00176 OtsUDPHardware::read(sendBuffer,readQuadWord);
00177
00178 OtsUDPFirmwareCore::readDataDestinationIP(sendBuffer);
00179 OtsUDPHardware::read(sendBuffer,readQuadWord);
00180
00181 OtsUDPFirmwareCore::readDataDestinationPort(sendBuffer);
00182 OtsUDPHardware::read(sendBuffer,readQuadWord);
00183
00184
00185
00186 OtsUDPFirmwareCore::readControlDestinationPort(sendBuffer);
00187 OtsUDPHardware::read(sendBuffer,readQuadWord);
00188
00189
00190 FEVInterface::runSequenceOfCommands("LinkToConfigureSequence");
00191
00192 __FE_COUT__ << "Done with ots Template configuring." << __E__;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202 void FEOtsUDPProducerTemplateInterface::halt(void)
00203 {
00204 __FE_COUT__ << "\tHalt" << __E__;
00205 stop();
00206 }
00207
00208
00209 void FEOtsUDPProducerTemplateInterface::pause(void)
00210 {
00211 __FE_COUT__ << "\tPause" << __E__;
00212 stop();
00213 }
00214
00215
00216 void FEOtsUDPProducerTemplateInterface::resume(void)
00217 {
00218 __FE_COUT__ << "\tResume" << __E__;
00219 start("");
00220 }
00221
00222
00223 void FEOtsUDPProducerTemplateInterface::start(std::string )
00224 {
00225 __FE_COUT__ << "\tStart" << __E__;
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 FEVInterface::runSequenceOfCommands("LinkToStartSequence");
00248
00249 std::string sendBuffer;
00250 OtsUDPFirmwareCore::startBurst(sendBuffer);
00251 OtsUDPHardware::write(sendBuffer);
00252 }
00253
00254
00255 void FEOtsUDPProducerTemplateInterface::stop(void)
00256 {
00257 __FE_COUT__ << "\tStop" << __E__;
00258
00259
00260
00261 FEVInterface::runSequenceOfCommands("LinkToStopSequence");
00262
00263 std::string sendBuffer;
00264 OtsUDPFirmwareCore::stopBurst(sendBuffer);
00265 OtsUDPHardware::write(sendBuffer);
00266 }
00267
00268
00269 bool FEOtsUDPProducerTemplateInterface::running(void)
00270 {
00271 __FE_COUT__ << "\tRunning" << __E__;
00272
00273
00274
00275
00276
00277 int state = -1;
00278 while(WorkLoop::continueWorkLoop_)
00279 {
00280
00281
00282
00283 ++state;
00284 if(state < 8)
00285 sleep(1);
00286 else
00287 {
00288
00289
00290
00291
00292
00293 break;
00294 }
00295
00296
00297
00298 {
00299 if(DataProducerBase::attachToEmptySubBuffer(
00300 dataP_, headerP_) < 0)
00301 {
00302 __CFG_COUT__ << "There are no available buffers! Retrying...after waiting 10 milliseconds!" << std::endl;
00303 usleep(10000);
00304 return true;
00305 }
00306
00307 if(1)
00308 {
00309
00310 unsigned long long value = 0xB57321;
00311 std::string& buffer = *dataP_;
00312 buffer.resize(8);
00313 memcpy((void *)&buffer[0] ,(void *)&value , 8 );
00314
00315
00316 __CFG_COUT__ << "Writing to buffer " << buffer.size() << " bytes!" << __E__;
00317 __CFG_COUT__ << "Writing to buffer length " << buffer.length() << " bytes!" << __E__;
00318
00319 __CFG_COUT__ << "Buffer Data: " << BinaryStringMacros::binaryTo8ByteHexString(buffer) << __E__;
00320
00321 __CFG_COUTV__(DataProcessor::theCircularBuffer_);
00322
00323 __CFG_COUT__ << __E__;
00324
00325
00326
00327
00328
00329 __CFG_COUT__ << __E__;
00330
00331
00332 DataProducerBase::setWrittenSubBuffer<std::string,std::map<std::string,std::string> >();
00333 __CFG_COUT__ << __E__;
00334 __CFG_COUTV__(DataProcessor::theCircularBuffer_);
00335
00336 }
00337 }
00338 if(0)
00339 {
00340
00341 unsigned long long value = 0xA54321;
00342 std::string buffer;
00343 buffer.resize(8);
00344 memcpy((void *)&buffer[0] ,(void *)&value , 8 );
00345
00346
00347 __FE_COUT__ << "Writing to buffer " << buffer.size() << " bytes!" << __E__;
00348 __FE_COUT__ << "Writing to buffer length " << buffer.length() << " bytes!" << __E__;
00349
00350 __FE_COUT__ << "Buffer Data: " << BinaryStringMacros::binaryTo8ByteHexString(buffer) << __E__;
00351
00352
00353 FEProducerVInterface::copyToNextBuffer(buffer);
00354 }
00355
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 return false;
00399 }
00400
00401
00402
00403
00404 void ots::FEOtsUDPProducerTemplateInterface::universalRead(char *address, char *returnValue)
00405 {
00406 __FE_COUT__ << "address size " << universalAddressSize_ << __E__;
00407
00408 __FE_COUT__ << "Request: ";
00409 for(unsigned int i=0;i<universalAddressSize_;++i)
00410 printf("%2.2X",(unsigned char)address[i]);
00411 std::cout << __E__;
00412
00413 std::string readBuffer, sendBuffer;
00414 OtsUDPFirmwareCore::readAdvanced(sendBuffer,address,1 );
00415
00416 OtsUDPHardware::read(sendBuffer, readBuffer);
00417
00418 __FE_COUT__ << "Result SIZE: " << readBuffer.size() << __E__;
00419 std::memcpy(returnValue,readBuffer.substr(2).c_str(),universalDataSize_);
00420 }
00421
00422
00423
00424
00425 void ots::FEOtsUDPProducerTemplateInterface::universalWrite(char* address, char* writeValue)
00426 {
00427 __FE_COUT__ << "address size " << universalAddressSize_ << __E__;
00428 __FE_COUT__ << "data size " << universalDataSize_ << __E__;
00429 __FE_COUT__ << "Sending: ";
00430 for(unsigned int i=0;i<universalAddressSize_;++i)
00431 printf("%2.2X",(unsigned char)address[i]);
00432 std::cout << __E__;
00433
00434 std::string sendBuffer;
00435 OtsUDPFirmwareCore::writeAdvanced(sendBuffer,address,writeValue,1 );
00436 OtsUDPHardware::write(sendBuffer);
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446 void FEOtsUDPProducerTemplateInterface::varTest(__ARGS__)
00447 {
00448 __FE_COUT__ << "# of input args = " << argsIn.size() << __E__;
00449 __FE_COUT__ << "# of output args = " << argsOut.size() << __E__;
00450 for(auto &argIn:argsIn)
00451 __FE_COUT__ << argIn.first << ": " << argIn.second << __E__;
00452
00453
00454 {
00455 char *address = new char[universalAddressSize_]{0};
00456 char *data = new char[universalDataSize_]{0};
00457 uint64_t macroAddress;
00458 uint64_t macroData;
00459 std::map<std::string ,uint64_t > macroArgs;
00460
00461
00462 macroAddress = 0x1002; memcpy(address,¯oAddress,8);
00463 universalRead(address,data); memcpy(¯oArgs["myArg"],data,8);
00464 __SET_ARG_OUT__("myArg",macroArgs["myArg"]);
00465
00466
00467 macroAddress = 0x1001; memcpy(address,¯oAddress,8);
00468 universalRead(address,data); memcpy(¯oArgs["outArg1"],data,8);
00469 __SET_ARG_OUT__("outArg1",macroArgs["outArg1"]);
00470
00471
00472 macroAddress = 0x1002; memcpy(address,¯oAddress,8);
00473 macroArgs["myOtherArg"] = __GET_ARG_IN__("myOtherArg", uint64_t);
00474 memcpy(data,¯oArgs["myOtherArg"],8);
00475 universalWrite(address,data);
00476
00477
00478 macroAddress = 0x1001; memcpy(address,¯oAddress,8);
00479 memcpy(data,¯oArgs["myArg"],8);
00480 universalWrite(address,data);
00481
00482
00483 __FE_COUT__ << "Sleeping for... " << 4 << " milliseconds " << __E__;
00484 usleep(4*1000 );
00485
00486
00487 delete[] address;
00488 delete[] data;
00489 }
00490
00491 for(auto &argOut:argsOut)
00492 __FE_COUT__ << argOut.first << ": " << argOut.second << __E__;
00493
00494 }
00495
00496
00497
00498
00499
00500
00501 void FEOtsUDPProducerTemplateInterface::varTest2(__ARGS__)
00502 {
00503 __FE_COUT__ << "# of input args = " << argsIn.size() << __E__;
00504 __FE_COUT__ << "# of output args = " << argsOut.size() << __E__;
00505 for(auto &argIn:argsIn)
00506 __FE_COUT__ << argIn.first << ": " << argIn.second << __E__;
00507
00508
00509 {
00510 char *address = new char[universalAddressSize_]{0};
00511 char *data = new char[universalDataSize_]{0};
00512 uint64_t macroAddress;
00513 uint64_t macroData;
00514 std::map<std::string ,uint64_t > macroArgs;
00515
00516
00517 macroAddress = 0x1002; memcpy(address,¯oAddress,8);
00518 universalRead(address,data); memcpy(¯oArgs["myArg"],data,8);
00519 __SET_ARG_OUT__("myArg",macroArgs["myArg"]);
00520
00521
00522 macroAddress = 0x1001; memcpy(address,¯oAddress,8);
00523 universalRead(address,data); memcpy(¯oArgs["outArg1"],data,8);
00524 __SET_ARG_OUT__("outArg1",macroArgs["outArg1"]);
00525
00526
00527 macroAddress = 0x1002; memcpy(address,¯oAddress,8);
00528 macroArgs["myOtherArg"] = __GET_ARG_IN__("myOtherArg", uint64_t);
00529 memcpy(data,¯oArgs["myOtherArg"],8);
00530 universalWrite(address,data);
00531
00532
00533 macroAddress = 0x1001; memcpy(address,¯oAddress,8);
00534 memcpy(data,¯oArgs["myArg"],8);
00535 universalWrite(address,data);
00536
00537
00538 __FE_COUT__ << "Sleeping for... " << 4 << " milliseconds " << __E__;
00539 usleep(4*1000 );
00540
00541
00542 delete[] address;
00543 delete[] data;
00544 }
00545
00546 for(auto &argOut:argsOut)
00547 __FE_COUT__ << argOut.first << ": " << argOut.second << __E__;
00548
00549 }
00550
00551 DEFINE_OTS_INTERFACE(FEOtsUDPProducerTemplateInterface)