1 #include "otsdaq-core/FECore/FEVInterface.h"
2 #include "otsdaq-core/CoreSupervisors/CoreSupervisorBase.h"
3 #include "otsdaq-core/FECore/FEVInterfacesManager.h"
4 #include "otsdaq-core/NetworkUtilities/UDPDataStreamerBase.h"
13 FEVInterface::FEVInterface(
const std::string& interfaceUID,
15 const std::string& configurationPath)
17 ,
Configurable(theXDAQContextConfigTree, configurationPath)
18 , interfaceUID_(interfaceUID)
23 , slowControlsWorkLoop_(interfaceUID +
"-SlowControls", this)
28 __COUT__ <<
"'" << interfaceUID <<
"' Constructed." << __E__;
32 FEVInterface::~FEVInterface(
void)
36 __COUT__ << FEVInterface::interfaceUID_ <<
" Destructed." << __E__;
40 void FEVInterface::configureSlowControls(
void)
43 if(metricMan && !metricMan->Running() && metricMan->Initialized())
44 metricMan->do_start();
47 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
48 .getNode(
"LinkToSlowControlsChannelTable");
50 if(slowControlsGroupLink.isDisconnected())
53 <<
"slowControlsGroupLink is disconnected, so done configuring slow controls."
57 __FE_COUT__ <<
"slowControlsGroupLink is valid! Configuring slow controls..."
60 mapOfSlowControlsChannels_.clear();
61 std::vector<std::pair<std::string, ConfigurationTree> > groupLinkChildren =
62 slowControlsGroupLink.getChildren();
63 for(
auto& groupLinkChild : groupLinkChildren)
66 if(!(groupLinkChild.second.getNode(TableViewColumnInfo::COL_NAME_STATUS)
70 __FE_COUT__ <<
"Channel:" << getInterfaceUID() <<
"/" << groupLinkChild.first
71 <<
"\t Type:" << groupLinkChild.second.getNode(
"ChannelDataType")
74 mapOfSlowControlsChannels_.insert(std::pair<std::string, FESlowControlsChannel>(
79 groupLinkChild.second.getNode(
"ChannelDataType").getValue<std::string>(),
81 universalAddressSize_,
82 groupLinkChild.second.getNode(
"UniversalInterfaceAddress")
83 .getValue<std::string>(),
84 groupLinkChild.second.getNode(
"UniversalDataBitOffset")
85 .getValue<
unsigned int>(),
86 groupLinkChild.second.getNode(
"ReadAccess").getValue<
bool>(),
87 groupLinkChild.second.getNode(
"WriteAccess").getValue<
bool>(),
88 groupLinkChild.second.getNode(
"MonitoringEnabled").getValue<
bool>(),
89 groupLinkChild.second.getNode(
"RecordChangesOnly").getValue<
bool>(),
90 groupLinkChild.second.getNode(
"DelayBetweenSamplesInSeconds")
92 groupLinkChild.second.getNode(
"LocalSavingEnabled").getValue<
bool>(),
93 groupLinkChild.second.getNode(
"LocalFilePath").getValue<std::string>(),
94 groupLinkChild.second.getNode(
"RadixFileName").getValue<std::string>(),
95 groupLinkChild.second.getNode(
"SaveBinaryFile").getValue<
bool>(),
96 groupLinkChild.second.getNode(
"AlarmsEnabled").getValue<
bool>(),
97 groupLinkChild.second.getNode(
"LatchAlarms").getValue<
bool>(),
98 groupLinkChild.second.getNode(
"LowLowThreshold").getValue<std::string>(),
99 groupLinkChild.second.getNode(
"LowThreshold").getValue<std::string>(),
100 groupLinkChild.second.getNode(
"HighThreshold").getValue<std::string>(),
101 groupLinkChild.second.getNode(
"HighHighThreshold")
102 .getValue<std::string>())));
107 bool FEVInterface::slowControlsRunning(
void)
try
109 __FE_COUT__ <<
"slowControlsRunning" << __E__;
111 if(mapOfSlowControlsChannels_.size() == 0)
114 <<
"No slow controls channels to monitor, exiting slow controls workloop."
119 readVal.resize(universalDataSize_);
123 const unsigned int txBufferSz = 1500;
124 const unsigned int txBufferFullThreshold = 750;
125 std::string txBuffer;
126 txBuffer.reserve(txBufferSz);
129 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_);
132 std::unique_ptr<UDPDataStreamerBase> slowContrlolsTxSocket;
133 std::string slowControlsSupervisorIPAddress =
"", slowControlsSelfIPAddress =
"";
134 int slowControlsSupervisorPort = 0, slowControlsSelfPort = 0;
138 FEInterfaceNode.getNode(
"LinkToSlowControlsSupervisorTable");
140 if(slowControlsInterfaceLink.isDisconnected())
142 __FE_SS__ <<
"slowControlsInterfaceLink is disconnected, so no socket made."
147 slowControlsSelfIPAddress =
148 FEInterfaceNode.getNode(
"SlowControlsTxSocketIPAddress")
149 .getValue<std::string>();
150 slowControlsSelfPort =
151 FEInterfaceNode.getNode(
"SlowControlsTxSocketPort").getValue<
int>();
152 slowControlsSupervisorIPAddress =
153 slowControlsInterfaceLink.getNode(
"IPAddress").getValue<std::string>();
154 slowControlsSupervisorPort =
155 slowControlsInterfaceLink.getNode(
"Port").getValue<
int>();
159 __FE_COUT__ <<
"Link to slow controls supervisor is missing, so no socket made."
163 if(slowControlsSupervisorPort && slowControlsSelfPort &&
164 slowControlsSupervisorIPAddress !=
"" && slowControlsSelfIPAddress !=
"")
166 __FE_COUT__ <<
"slowControlsInterfaceLink is valid! Create tx socket..." << __E__;
167 slowContrlolsTxSocket.reset(
169 slowControlsSelfPort,
170 slowControlsSupervisorIPAddress,
171 slowControlsSupervisorPort));
175 __FE_COUT__ <<
"Invalid Slow Controls socket parameters, so no socket made."
182 bool aggregateFileIsBinaryFormat =
false;
183 if(FEInterfaceNode.getNode(
"SlowControlsLocalAggregateSavingEnabled")
186 aggregateFileIsBinaryFormat =
187 FEInterfaceNode.getNode(
"SlowControlsSaveBinaryFile").getValue<
bool>();
189 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned On BinaryFormat="
190 << aggregateFileIsBinaryFormat << __E__;
192 std::string saveFullFileName =
193 FEInterfaceNode.getNode(
"SlowControlsLocalFilePath").getValue<std::string>() +
195 FEInterfaceNode.getNode(
"SlowControlsRadixFileName").getValue<std::string>() +
196 "-" + FESlowControlsChannel::underscoreString(getInterfaceUID()) +
"-" +
197 std::to_string(time(0)) + (aggregateFileIsBinaryFormat ?
".dat" :
".txt");
199 fp = fopen(saveFullFileName.c_str(), aggregateFileIsBinaryFormat ?
"ab" :
"a");
202 __FE_COUT_ERR__ <<
"Failed to open slow controls channel file: "
203 << saveFullFileName << __E__;
207 __FE_COUT_INFO__ <<
"Slow controls aggregate file opened: "
208 << saveFullFileName << __E__;
211 __FE_COUT_INFO__ <<
"Slow Controls Aggregate Saving turned off." << __E__;
213 time_t timeCounter = 0;
215 __FE_COUTV__(slowControlsWorkLoop_.getContinueWorkLoop());
218 unsigned int numOfReadChannels = 0;
219 for(
const auto& channelPair : mapOfSlowControlsChannels_)
221 __FE_COUT__ <<
"SC Channel '" << channelPair.first
222 <<
"' readAccess:" << channelPair.second.readAccess_ << __E__;
225 if(numOfReadChannels == 0)
226 __MCOUT_WARN__(
"There are no slow controls channels with read access!");
229 while(slowControlsWorkLoop_.getContinueWorkLoop())
231 __FE_COUT__ <<
"..." << __E__;
237 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
244 for(
auto& slowControlsChannelPair : mapOfSlowControlsChannels_)
246 channel = &slowControlsChannelPair.second;
249 if(!channel->readAccess_)
253 if(timeCounter % channel->delayBetweenSamples_)
256 __FE_COUT__ <<
"Channel:" << getInterfaceUID() <<
"/"
257 << slowControlsChannelPair.first << __E__;
258 __FE_COUT__ <<
"Monitoring..." << __E__;
260 universalRead(channel->getUniversalAddress(), &readVal[0]);
272 channel->handleSample(readVal, txBuffer, fp, aggregateFileIsBinaryFormat);
274 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
281 if(metricMan && universalAddressSize_ <= 8)
284 for(
size_t ii = 0; ii < universalAddressSize_; ++ii)
285 val += (uint8_t)readVal[ii] << (ii * 4);
287 __FE_COUT__ <<
"Sending sample to Metric Manager..." << __E__;
288 metricMan->sendMetric(
289 getInterfaceUID() +
"/" + slowControlsChannelPair.first,
293 artdaq::MetricMode::LastPoint);
297 if(txBuffer.size() > txBufferSz)
299 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
304 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
306 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
307 << txBufferFullThreshold << __E__;
308 slowContrlolsTxSocket->send(txBuffer);
314 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
317 if(slowContrlolsTxSocket && txBuffer.size())
319 __FE_COUT__ <<
"Sending now!" << __E__;
320 slowContrlolsTxSocket->send(txBuffer);
330 __FE_COUT__ <<
"Slow controls workloop done." << __E__;
334 catch(
const std::runtime_error& e)
336 __FE_COUT__ <<
"Error caught during slow controls running thread: " << e.what()
342 __FE_COUT__ <<
"Unknown error caught during slow controls running thread." << __E__;
351 void FEVInterface::sendAsyncErrorToGateway(
FEVInterface* fe,
352 const std::string& errorMessage,
353 bool isSoftError)
try
356 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
357 <<
":" << fe->theConfigurationRecordName_ <<
":"
358 <<
"Sending FE Async SOFT Running Error... \n"
359 << errorMessage << __E__;
361 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
362 <<
":" << fe->theConfigurationRecordName_ <<
":"
363 <<
"Sending FE Async Running Error... \n"
364 << errorMessage << __E__;
366 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
367 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
371 parameters.addParameter(
"ErrorMessage", errorMessage);
373 xoap::MessageReference replyMessage =
374 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
375 gatewaySupervisor, isSoftError ?
"AsyncSoftError" :
"AsyncError", parameters);
377 std::stringstream replyMessageSStream;
378 replyMessageSStream << SOAPUtilities::translate(replyMessage);
379 __COUT__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
380 << fe->theConfigurationRecordName_ <<
":"
381 <<
"Received... " << replyMessageSStream.str() << std::endl;
383 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
385 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
386 <<
":" << fe->theConfigurationRecordName_ <<
":"
387 <<
"Failure to indicate fault to Gateway..." << __E__;
391 catch(
const xdaq::exception::Exception& e)
394 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
395 "error back to Gateway: "
396 << e.what() << __E__;
398 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
399 "error back to Gateway: "
400 << e.what() << __E__;
405 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
406 "SOFT error back to Gateway."
409 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
410 "error back to Gateway."
417 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* workLoop)
429 bool isSoftError =
false;
437 ss <<
"SOFT Error was caught while configuring: " << e.what() << std::endl;
440 catch(
const std::runtime_error& e)
442 ss <<
"Caught an error during running at FE Interface '"
443 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
447 ss <<
"Caught an unknown error during running." << __E__;
454 __FE_COUT_ERR__ << ss.str();
457 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) {
458 FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError);
469 return continueWorkLoop_;
480 void FEVInterface::registerFEMacroFunction(
481 const std::string& feMacroName,
482 frontEndMacroFunction_t feMacroFunction,
483 const std::vector<std::string>& namesOfInputArgs,
484 const std::vector<std::string>& namesOfOutputArgs,
485 uint8_t requiredUserPermissions,
486 const std::string& allowedCallingFEs)
488 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
490 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
492 __FE_COUT_ERR__ <<
"\n" << ss.str();
496 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
498 frontEndMacroStruct_t(feMacroName,
502 requiredUserPermissions,
503 allowedCallingFEs)));
511 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
512 const std::string& argName)
514 for(
const frontEndMacroArg_t& pair : args)
516 if(pair.first == argName)
518 __COUT__ <<
"argName : " << pair.second << __E__;
522 __SS__ <<
"Requested input argument not found with name '" << argName <<
"'" << __E__;
530 std::string ots::getFEMacroConstArgumentValue<std::string>(
531 FEVInterface::frontEndMacroConstArgs_t& args,
const std::string& argName)
533 return FEVInterface::getFEMacroConstArgument(args, argName);
540 std::string ots::getFEMacroArgumentValue<std::string>(
541 FEVInterface::frontEndMacroArgs_t& args,
const std::string& argName)
543 return FEVInterface::getFEMacroArgument(args, argName);
551 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
552 const std::string& argName)
554 for(std::pair<
const std::string ,
555 std::string >& pair : args)
557 if(pair.first == argName)
560 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
569 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
571 std::map<uint64_t, uint64_t> writeHistory;
572 uint64_t writeAddress, writeValue, bitMask;
575 std::string writeBuffer;
576 std::string readBuffer;
578 bool ignoreError =
true;
584 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
585 .getNode(treeLinkName);
590 if(configSeqLink.isDisconnected())
591 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
594 __FE_COUT__ <<
"Handling configure sequence." << __E__;
595 auto childrenMap = configSeqLink.getChildrenMap();
596 for(
const auto& child : childrenMap)
601 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
602 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
604 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
606 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
609 writeValue &= bitMask;
610 writeValue <<= bitPosition;
611 bitMask = ~(bitMask << bitPosition);
614 if(writeHistory.find(writeAddress) == writeHistory.end())
615 writeHistory[writeAddress] = 0;
617 writeHistory[writeAddress] &= bitMask;
618 writeHistory[writeAddress] |= writeValue;
621 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
625 writeHistory[writeAddress],
626 writeHistory[writeAddress]);
628 __FE_COUT__ << msg << __E__;
630 universalWrite((
char*)&writeAddress,
631 (
char*)&(writeHistory[writeAddress]));
647 <<
"Unable to access sequence of commands through configuration tree. "
648 <<
"Assuming no sequence. " << __E__;
660 void FEVInterface::runSelfFrontEndMacro(
661 const std::string& feMacroName,
664 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
665 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
668 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
669 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
671 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
672 << getInterfaceUID() <<
"' was not found!" << __E__;
673 __CFG_COUT_ERR__ <<
"\n" << ss.str();
679 for(
unsigned int i = 0; i < argsIn.size(); ++i)
680 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
682 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
683 << getInterfaceUID() <<
"' was attempted with a mismatch in"
684 <<
" a name of an input argument. " << argsIn[i].first
685 <<
" was given. " << feMacro.namesOfInputArguments_[i]
686 <<
" expected." << __E__;
687 __CFG_COUT_ERR__ <<
"\n" << ss.str();
692 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
694 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
695 << getInterfaceUID() <<
"' was attempted with a mismatch in"
696 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
697 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
698 __CFG_COUT_ERR__ <<
"\n" << ss.str();
702 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
703 for(
auto& argIn : argsIn)
704 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
706 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
709 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
710 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
711 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
714 (this->*(feMacro.macroFunction_))(feMacro, argsIn, argsOut);
716 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
718 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
719 for(
const auto& arg : argsOut)
720 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
728 void FEVInterface::runFrontEndMacro(
729 const std::string& targetInterfaceID,
730 const std::string& feMacroName,
731 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
732 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
734 __FE_COUTV__(targetInterfaceID);
735 __FE_COUTV__(VStateMachine::parentSupervisor_);
737 std::string inputArgsStr = StringMacros::vectorToString(
738 inputArgs,
";" ,
"," );
740 __FE_COUTV__(inputArgsStr);
742 xoap::MessageReference message =
743 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
746 parameters.addParameter(
"type",
"feMacro");
747 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
748 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
749 parameters.addParameter(
"feMacroName", feMacroName);
750 parameters.addParameter(
"inputArgs", inputArgsStr);
751 SOAPUtilities::addParameters(message, parameters);
753 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
756 xoap::MessageReference replyMessage =
757 VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
758 VStateMachine::parentSupervisor_->allSupervisorInfo_
759 .getAllMacroMakerTypeSupervisorInfo()
761 ->second.getDescriptor(),
764 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
768 rxParameters.addParameter(
"Error");
769 SOAPUtilities::receive(replyMessage, rxParameters);
771 std::string error = rxParameters.getValue(
"Error");
776 __FE_SS__ <<
"Error transmitting request to target interface '"
777 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
778 <<
".' " << error << __E__;
784 argsOutParameter.addParameter(
"outputArgs");
785 SOAPUtilities::receive(replyMessage, argsOutParameter);
787 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
788 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
790 std::map<std::string, std::string> mapToReturn;
791 StringMacros::getMapFromString(
792 outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
795 for(
auto& mapPair : mapToReturn)
796 outputArgs.push_back(mapPair);
805 void FEVInterface::receiveFromFrontEnd(
const std::string& requester,
806 std::string& retValue,
807 unsigned int timeoutInSeconds)
const
809 __FE_COUTV__(requester);
810 __FE_COUTV__(parentSupervisor_);
812 std::string data =
"0";
818 std::lock_guard<std::mutex> lock(
819 parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
821 auto receiveBuffersForTargetIt =
822 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
823 FEVInterface::interfaceUID_);
824 if(receiveBuffersForTargetIt !=
825 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
827 __FE_COUT__ <<
"Number of source buffers found for front-end '"
828 << FEVInterface::interfaceUID_
829 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
831 for(
auto& buffPair : receiveBuffersForTargetIt->second)
832 __FE_COUTV__(buffPair.first);
835 std::string sourceBufferId =
"";
836 std::queue<std::string >& sourceBuffer =
837 StringMacros::getWildCardMatchFromMap(
838 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
840 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
841 << sourceBuffer.size() << __E__;
843 if(sourceBuffer.size())
845 __FE_COUT__ <<
"Found a value in queue of size "
846 << sourceBuffer.size() << __E__;
849 retValue = sourceBuffer.front();
854 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
861 if(!timeoutInSeconds)
863 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
864 <<
" s) waiting for front-end communication from " << requester
873 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
874 << timeoutInSeconds <<
" more seconds..." << __E__;
888 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
889 unsigned int timeoutInSeconds)
const
891 std::string retValue;
892 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
898 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
900 __COUTV__(macroString);
906 std::vector<std::string> extractVec;
907 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
909 __COUTV__(StringMacros::vectorToString(extractVec,
" ||| "));
913 MACRONAME_NAME_INDEX = 1,
914 MACRONAME_VALUE_INDEX = 3,
915 SEQUENCE_NAME_INDEX = 5,
916 SEQUENCE_VALUE_INDEX = 7,
917 LSBF_NAME_INDEX = 17,
918 LSFBF_VALUE_INDEX = 19,
922 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
923 extractVec[MACRONAME_NAME_INDEX] !=
"name")
925 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
929 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
930 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
932 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
933 << SEQUENCE_NAME_INDEX << __E__;
936 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
938 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
942 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
943 __COUTV__(macroName_);
944 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ?
false :
true;
946 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
949 std::vector<std::string> sequenceCommands;
950 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
952 __COUTV__(StringMacros::vectorToString(sequenceCommands,
" ### "));
954 for(
auto& command : sequenceCommands)
961 std::vector<std::string> commandPieces;
962 StringMacros::getVectorFromString(command, commandPieces, {
':'});
964 __COUTV__(StringMacros::vectorToString(commandPieces,
" ### "));
966 __COUTV__(commandPieces.size());
977 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
978 commandPieces[1].size() != 1)
980 __SS__ <<
"Invalid command type specified in command string: " << command
987 std::function<bool(
const std::string&
989 localIsVariable = [](
const std::string& fieldValue) {
991 std::string mfSubject_ =
"isVar";
992 __GEN_COUTV__(fieldValue);
995 for(
const auto& c : fieldValue)
996 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
997 (c >=
'A' && c <=
'F')))
1003 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
1005 __COUT__ <<
"Read type found." << __E__;
1009 operations_.push_back(
1010 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
1012 readOps_.push_back(macroStruct_t::readOp_t());
1013 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1014 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1016 if(!readOps_.back().addressIsVar_)
1020 std::string lsbfData =
"";
1023 commandPieces[2] =
"0" + commandPieces[2];
1024 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1026 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1029 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1031 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1032 __COUTV__(lsbfData);
1034 __COUTV__(lsbfData);
1035 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1038 StringMacros::getNumber(
"0x" + commandPieces[2],
1039 readOps_.back().address_);
1043 readOps_.back().addressVarName_ = commandPieces[2];
1044 __COUTV__(readOps_.back().addressVarName_);
1046 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1049 if(readOps_.back().dataIsVar_)
1051 readOps_.back().dataVarName_ = commandPieces[3];
1052 __COUTV__(readOps_.back().dataVarName_);
1054 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1057 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1059 __COUT__ <<
"Write type found." << __E__;
1063 operations_.push_back(
1064 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1066 writeOps_.push_back(macroStruct_t::writeOp_t());
1067 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1068 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1070 if(!writeOps_.back().addressIsVar_)
1074 std::string lsbfData =
"";
1077 commandPieces[2] =
"0" + commandPieces[2];
1078 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1080 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1083 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1085 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1086 __COUTV__(lsbfData);
1088 __COUTV__(lsbfData);
1089 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1092 StringMacros::getNumber(
"0x" + commandPieces[2],
1093 writeOps_.back().address_);
1097 writeOps_.back().addressVarName_ = commandPieces[2];
1098 __COUTV__(writeOps_.back().addressVarName_);
1100 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1103 if(!writeOps_.back().dataIsVar_)
1107 std::string lsbfData =
"";
1110 commandPieces[2] =
"0" + commandPieces[3];
1111 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1113 __COUTV__(commandPieces[3].size() - 2 * (i + 1));
1116 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1118 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1119 __COUTV__(lsbfData);
1121 __COUTV__(lsbfData);
1122 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1125 StringMacros::getNumber(
"0x" + commandPieces[3],
1126 writeOps_.back().data_);
1130 writeOps_.back().dataVarName_ = commandPieces[3];
1131 __COUTV__(writeOps_.back().dataVarName_);
1133 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1136 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1138 __COUT__ <<
"Delay type found." << __E__;
1141 operations_.push_back(
1142 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1144 delayOps_.push_back(macroStruct_t::delayOp_t());
1145 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1147 if(!delayOps_.back().delayIsVar_)
1148 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1151 delayOps_.back().delayVarName_ = commandPieces[2];
1152 __COUTV__(delayOps_.back().delayVarName_);
1154 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1159 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1160 <<
"' specified with " << commandPieces.size() <<
" components."
1167 __COUT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1168 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1169 <<
" delays" << __E__;
1171 __COUT__ <<
"Input arguments: " << __E__;
1172 for(
const auto& inputArg : namesOfInputArguments_)
1173 __COUT__ <<
"\t" << inputArg << __E__;
1175 __COUT__ <<
"Output arguments: " << __E__;
1176 for(
const auto& outputArg : namesOfOutputArguments_)
1177 __COUT__ <<
"\t" << outputArg << __E__;
1183 void FEVInterface::runMacro(
1185 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1189 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1190 << macro.operations_.size() <<
" operations." << __E__;
1192 for(
auto& op : macro.operations_)
1194 if(op.first == macroStruct_t::OP_TYPE_READ)
1196 __FE_COUT__ <<
"Doing read op..." << __E__;
1197 macroStruct_t::readOp_t& readOp = macro.readOps_[op.second];
1198 if(readOp.addressIsVar_)
1200 __FE_COUTV__(readOp.addressVarName_);
1201 readOp.address_ = variableMap.at(readOp.addressVarName_);
1204 uint64_t dataValue = 0;
1206 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1209 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1211 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1214 if(readOp.dataIsVar_)
1216 __FE_COUTV__(readOp.dataVarName_);
1217 variableMap.at(readOp.dataVarName_) = dataValue;
1221 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1223 __FE_COUT__ <<
"Doing write op..." << __E__;
1224 macroStruct_t::writeOp_t& writeOp = macro.writeOps_[op.second];
1225 if(writeOp.addressIsVar_)
1227 __FE_COUTV__(writeOp.addressVarName_);
1228 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1230 if(writeOp.dataIsVar_)
1232 __FE_COUTV__(writeOp.dataVarName_);
1233 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1236 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1238 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1241 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1244 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1246 __FE_COUT__ <<
"Doing delay op..." << __E__;
1248 macroStruct_t::delayOp_t& delayOp = macro.delayOps_[op.second];
1249 if(delayOp.delayIsVar_)
1251 __FE_COUTV__(delayOp.delayVarName_);
1252 delayOp.delay_ = variableMap.at(delayOp.delayVarName_);
1255 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.delay_ << __E__;
1257 usleep(delayOp.delay_ * 1000);
1262 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;