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 while(slowControlsWorkLoop_.getContinueWorkLoop())
221 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
228 for(
auto& slowControlsChannelPair : mapOfSlowControlsChannels_)
230 channel = &slowControlsChannelPair.second;
233 if(!channel->readAccess_)
237 if(timeCounter % channel->delayBetweenSamples_)
240 __FE_COUT__ <<
"Channel:" << getInterfaceUID() <<
"/"
241 << slowControlsChannelPair.first << __E__;
242 __FE_COUT__ <<
"Monitoring..." << __E__;
244 universalRead(channel->getUniversalAddress(), &readVal[0]);
256 channel->handleSample(readVal, txBuffer, fp, aggregateFileIsBinaryFormat);
258 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
265 if(metricMan && universalAddressSize_ <= 8)
268 for(
size_t ii = 0; ii < universalAddressSize_; ++ii)
269 val += (uint8_t)readVal[ii] << (ii * 4);
271 __FE_COUT__ <<
"Sending sample to Metric Manager..." << __E__;
272 metricMan->sendMetric(
273 getInterfaceUID() +
"/" + slowControlsChannelPair.first,
277 artdaq::MetricMode::LastPoint);
281 if(txBuffer.size() > txBufferSz)
283 __FE_SS__ <<
"This should never happen hopefully!" << __E__;
288 if(slowContrlolsTxSocket && txBuffer.size() > txBufferFullThreshold)
290 __FE_COUT__ <<
"Sending now! txBufferFullThreshold="
291 << txBufferFullThreshold << __E__;
292 slowContrlolsTxSocket->send(txBuffer);
298 __FE_COUT__ <<
"txBuffer sz=" << txBuffer.size() << __E__;
301 if(slowContrlolsTxSocket && txBuffer.size())
303 __FE_COUT__ <<
"Sending now!" << __E__;
304 slowContrlolsTxSocket->send(txBuffer);
316 catch(
const std::runtime_error& e)
318 __FE_COUT__ <<
"Error caught during slow controls running thread: " << e.what()
324 __FE_COUT__ <<
"Unknown error caught during slow controls running thread." << __E__;
333 void FEVInterface::sendAsyncErrorToGateway(
FEVInterface* fe,
334 const std::string& errorMessage,
335 bool isSoftError)
try
338 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
339 <<
":" << fe->theConfigurationRecordName_ <<
":"
340 <<
"Sending FE Async SOFT Running Error... \n"
341 << errorMessage << __E__;
343 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
344 <<
":" << fe->theConfigurationRecordName_ <<
":"
345 <<
"Sending FE Async Running Error... \n"
346 << errorMessage << __E__;
348 XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor =
349 fe->VStateMachine::parentSupervisor_->allSupervisorInfo_.getGatewayInfo()
353 parameters.addParameter(
"ErrorMessage", errorMessage);
355 xoap::MessageReference replyMessage =
356 fe->VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
357 gatewaySupervisor, isSoftError ?
"AsyncSoftError" :
"AsyncError", parameters);
359 std::stringstream replyMessageSStream;
360 replyMessageSStream << SOAPUtilities::translate(replyMessage);
361 __COUT__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID() <<
":"
362 << fe->theConfigurationRecordName_ <<
":"
363 <<
"Received... " << replyMessageSStream.str() << std::endl;
365 if(replyMessageSStream.str().find(
"Fault") != std::string::npos)
367 __COUT_ERR__ <<
":FE:" << fe->getInterfaceType() <<
":" << fe->getInterfaceUID()
368 <<
":" << fe->theConfigurationRecordName_ <<
":"
369 <<
"Failure to indicate fault to Gateway..." << __E__;
373 catch(
const xdaq::exception::Exception& e)
376 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running SOFT "
377 "error back to Gateway: "
378 << e.what() << __E__;
380 __COUT__ <<
"SOAP message failure indicating front-end asynchronous running "
381 "error back to Gateway: "
382 << e.what() << __E__;
387 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
388 "SOFT error back to Gateway."
391 __COUT__ <<
"Unknown error encounter indicating front-end asynchronous running "
392 "error back to Gateway."
399 bool FEVInterface::workLoopThread(toolbox::task::WorkLoop* workLoop)
411 bool isSoftError =
false;
419 ss <<
"SOFT Error was caught while configuring: " << e.what() << std::endl;
422 catch(
const std::runtime_error& e)
424 ss <<
"Caught an error during running at FE Interface '"
425 << Configurable::theConfigurationRecordName_ <<
"': " << e.what() << __E__;
429 ss <<
"Caught an unknown error during running." << __E__;
436 __FE_COUT_ERR__ << ss.str();
439 [](
FEVInterface* fe,
const std::string errorMessage,
bool isSoftError) {
440 FEVInterface::sendAsyncErrorToGateway(fe, errorMessage, isSoftError);
451 return continueWorkLoop_;
462 void FEVInterface::registerFEMacroFunction(
463 const std::string& feMacroName,
464 frontEndMacroFunction_t feMacroFunction,
465 const std::vector<std::string>& namesOfInputArgs,
466 const std::vector<std::string>& namesOfOutputArgs,
467 uint8_t requiredUserPermissions,
468 const std::string& allowedCallingFEs)
470 if(mapOfFEMacroFunctions_.find(feMacroName) != mapOfFEMacroFunctions_.end())
472 __FE_SS__ <<
"feMacroName '" << feMacroName <<
"' already exists! Not allowed."
474 __FE_COUT_ERR__ <<
"\n" << ss.str();
478 mapOfFEMacroFunctions_.insert(std::pair<std::string, frontEndMacroStruct_t>(
480 frontEndMacroStruct_t(feMacroName,
484 requiredUserPermissions,
485 allowedCallingFEs)));
493 const std::string& FEVInterface::getFEMacroConstArgument(frontEndMacroConstArgs_t& args,
494 const std::string& argName)
496 for(
const frontEndMacroArg_t& pair : args)
498 if(pair.first == argName)
500 __COUT__ <<
"argName : " << pair.second << __E__;
504 __SS__ <<
"Requested input argument not found with name '" << argName <<
"'" << __E__;
512 std::string ots::getFEMacroConstArgumentValue<std::string>(
513 FEVInterface::frontEndMacroConstArgs_t& args,
const std::string& argName)
515 return FEVInterface::getFEMacroConstArgument(args, argName);
522 std::string ots::getFEMacroArgumentValue<std::string>(FEVInterface::frontEndMacroArgs_t& args,
523 const std::string& argName)
525 return FEVInterface::getFEMacroArgument(args, argName);
533 std::string& FEVInterface::getFEMacroArgument(frontEndMacroArgs_t& args,
534 const std::string& argName)
536 for(std::pair<
const std::string ,
537 std::string >& pair : args)
539 if(pair.first == argName)
542 __SS__ <<
"Requested argument not found with name '" << argName <<
"'" << __E__;
551 void FEVInterface::runSequenceOfCommands(
const std::string& treeLinkName)
553 std::map<uint64_t, uint64_t> writeHistory;
554 uint64_t writeAddress, writeValue, bitMask;
557 std::string writeBuffer;
558 std::string readBuffer;
560 bool ignoreError =
true;
566 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
567 .getNode(treeLinkName);
572 if(configSeqLink.isDisconnected())
573 __FE_COUT__ <<
"Disconnected configure sequence" << __E__;
576 __FE_COUT__ <<
"Handling configure sequence." << __E__;
577 auto childrenMap = configSeqLink.getChildrenMap();
578 for(
const auto& child : childrenMap)
583 child.second.getNode(
"WriteAddress").getValue<uint64_t>();
584 writeValue = child.second.getNode(
"WriteValue").getValue<uint64_t>();
586 child.second.getNode(
"StartingBitPosition").getValue<uint8_t>();
588 (1 << child.second.getNode(
"BitFieldSize").getValue<uint8_t>()) -
591 writeValue &= bitMask;
592 writeValue <<= bitPosition;
593 bitMask = ~(bitMask << bitPosition);
596 if(writeHistory.find(writeAddress) == writeHistory.end())
597 writeHistory[writeAddress] = 0;
599 writeHistory[writeAddress] &= bitMask;
600 writeHistory[writeAddress] |= writeValue;
603 "\t Writing %s: \t %ld(0x%lX) \t %ld(0x%lX)",
607 writeHistory[writeAddress],
608 writeHistory[writeAddress]);
610 __FE_COUT__ << msg << __E__;
612 universalWrite((
char*)&writeAddress,
613 (
char*)&(writeHistory[writeAddress]));
629 <<
"Unable to access sequence of commands through configuration tree. "
630 <<
"Assuming no sequence. " << __E__;
642 void FEVInterface::runSelfFrontEndMacro(
643 const std::string& feMacroName,
646 const std::vector<FEVInterface::frontEndMacroArg_t>& argsIn,
647 std::vector<FEVInterface::frontEndMacroArg_t>& argsOut)
650 auto FEMacroIt = this->getMapOfFEMacroFunctions().find(feMacroName);
651 if(FEMacroIt == this->getMapOfFEMacroFunctions().end())
653 __CFG_SS__ <<
"FE Macro '" << feMacroName <<
"' of interfaceID '"
654 << getInterfaceUID() <<
"' was not found!" << __E__;
655 __CFG_COUT_ERR__ <<
"\n" << ss.str();
661 for(
unsigned int i = 0; i < argsIn.size(); ++i)
662 if(argsIn[i].first != feMacro.namesOfInputArguments_[i])
664 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
665 << getInterfaceUID() <<
"' was attempted with a mismatch in"
666 <<
" a name of an input argument. " << argsIn[i].first
667 <<
" was given. " << feMacro.namesOfInputArguments_[i]
668 <<
" expected." << __E__;
669 __CFG_COUT_ERR__ <<
"\n" << ss.str();
674 if(feMacro.namesOfInputArguments_.size() != argsIn.size())
676 __CFG_SS__ <<
"FE Macro '" << feMacro.feMacroName_ <<
"' of interfaceID '"
677 << getInterfaceUID() <<
"' was attempted with a mismatch in"
678 <<
" number of input arguments. " << argsIn.size() <<
" were given. "
679 << feMacro.namesOfInputArguments_.size() <<
" expected." << __E__;
680 __CFG_COUT_ERR__ <<
"\n" << ss.str();
684 __CFG_COUT__ <<
"# of input args = " << argsIn.size() << __E__;
685 for(
auto& argIn : argsIn)
686 __CFG_COUT__ << argIn.first <<
": " << argIn.second << __E__;
688 __CFG_COUT__ <<
"Launching FE Macro '" << feMacro.feMacroName_ <<
"' ..." << __E__;
691 for(
unsigned int i = 0; i < feMacro.namesOfOutputArguments_.size(); ++i)
692 argsOut.push_back(FEVInterface::frontEndMacroArg_t(
693 feMacro.namesOfOutputArguments_[i],
"DEFAULT"));
696 (this->*(feMacro.macroFunction_))(feMacro, argsIn, argsOut);
698 __CFG_COUT__ <<
"FE Macro complete!" << __E__;
700 __CFG_COUT__ <<
"# of output args = " << argsOut.size() << __E__;
701 for(
const auto& arg : argsOut)
702 __CFG_COUT__ << arg.first <<
": " << arg.second << __E__;
710 void FEVInterface::runFrontEndMacro(
711 const std::string& targetInterfaceID,
712 const std::string& feMacroName,
713 const std::vector<FEVInterface::frontEndMacroArg_t>& inputArgs,
714 std::vector<FEVInterface::frontEndMacroArg_t>& outputArgs)
const
716 __FE_COUTV__(targetInterfaceID);
717 __FE_COUTV__(VStateMachine::parentSupervisor_);
719 std::string inputArgsStr = StringMacros::vectorToString(
720 inputArgs,
";" ,
"," );
722 __FE_COUTV__(inputArgsStr);
724 xoap::MessageReference message =
725 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
728 parameters.addParameter(
"type",
"feMacro");
729 parameters.addParameter(
"requester", FEVInterface::interfaceUID_);
730 parameters.addParameter(
"targetInterfaceID", targetInterfaceID);
731 parameters.addParameter(
"feMacroName", feMacroName);
732 parameters.addParameter(
"inputArgs", inputArgsStr);
733 SOAPUtilities::addParameters(message, parameters);
735 __FE_COUT__ <<
"Sending FE communication: " << SOAPUtilities::translate(message)
738 xoap::MessageReference replyMessage =
739 VStateMachine::parentSupervisor_->SOAPMessenger::sendWithSOAPReply(
740 VStateMachine::parentSupervisor_->allSupervisorInfo_
741 .getAllMacroMakerTypeSupervisorInfo()
743 ->second.getDescriptor(),
746 __FE_COUT__ <<
"Response received: " << SOAPUtilities::translate(replyMessage)
750 rxParameters.addParameter(
"Error");
751 SOAPUtilities::receive(replyMessage, rxParameters);
753 std::string error = rxParameters.getValue(
"Error");
758 __FE_SS__ <<
"Error transmitting request to target interface '"
759 << targetInterfaceID <<
"' from '" << FEVInterface::interfaceUID_
760 <<
".' " << error << __E__;
766 argsOutParameter.addParameter(
"outputArgs");
767 SOAPUtilities::receive(replyMessage, argsOutParameter);
769 std::string outputArgsStr = argsOutParameter.getValue(
"outputArgs");
770 std::set<char> pairDelimiter({
';'}), nameValueDelimiter({
','});
772 std::map<std::string, std::string> mapToReturn;
773 StringMacros::getMapFromString(
774 outputArgsStr, mapToReturn, pairDelimiter, nameValueDelimiter);
777 for(
auto& mapPair : mapToReturn)
778 outputArgs.push_back(mapPair);
787 void FEVInterface::receiveFromFrontEnd(
const std::string& requester,
788 std::string& retValue,
789 unsigned int timeoutInSeconds)
const
791 __FE_COUTV__(requester);
792 __FE_COUTV__(parentSupervisor_);
794 std::string data =
"0";
800 std::lock_guard<std::mutex> lock(
801 parentInterfaceManager_->frontEndCommunicationReceiveMutex_);
803 auto receiveBuffersForTargetIt =
804 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.find(
805 FEVInterface::interfaceUID_);
806 if(receiveBuffersForTargetIt !=
807 parentInterfaceManager_->frontEndCommunicationReceiveBuffer_.end())
809 __FE_COUT__ <<
"Number of source buffers found for front-end '"
810 << FEVInterface::interfaceUID_
811 <<
"': " << receiveBuffersForTargetIt->second.size() << __E__;
813 for(
auto& buffPair : receiveBuffersForTargetIt->second)
814 __FE_COUTV__(buffPair.first);
817 std::string sourceBufferId =
"";
818 std::queue<std::string >& sourceBuffer =
819 StringMacros::getWildCardMatchFromMap(
820 requester, receiveBuffersForTargetIt->second, &sourceBufferId);
822 __FE_COUT__ <<
"Found source buffer '" << sourceBufferId <<
"' with size "
823 << sourceBuffer.size() << __E__;
825 if(sourceBuffer.size())
827 __FE_COUT__ <<
"Found a value in queue of size "
828 << sourceBuffer.size() << __E__;
831 retValue = sourceBuffer.front();
836 __FE_COUT__ <<
"Source buffer empty for '" << requester <<
"'"
843 if(!timeoutInSeconds)
845 __FE_SS__ <<
"Timeout (" << timeoutInSeconds
846 <<
" s) waiting for front-end communication from " << requester
855 __FE_COUT__ <<
"Waiting for front-end communication from " << requester <<
" for "
856 << timeoutInSeconds <<
" more seconds..." << __E__;
870 std::string FEVInterface::receiveFromFrontEnd(
const std::string& requester,
871 unsigned int timeoutInSeconds)
const
873 std::string retValue;
874 FEVInterface::receiveFromFrontEnd(requester, retValue, timeoutInSeconds);
880 FEVInterface::macroStruct_t::macroStruct_t(
const std::string& macroString)
882 __COUTV__(macroString);
888 std::vector<std::string> extractVec;
889 StringMacros::getVectorFromString(macroString, extractVec, {
'"'});
891 __COUTV__(StringMacros::vectorToString(extractVec,
" ||| "));
895 MACRONAME_NAME_INDEX = 1,
896 MACRONAME_VALUE_INDEX = 3,
897 SEQUENCE_NAME_INDEX = 5,
898 SEQUENCE_VALUE_INDEX = 7,
899 LSBF_NAME_INDEX = 17,
900 LSFBF_VALUE_INDEX = 19,
904 if(MACRONAME_NAME_INDEX >= extractVec.size() ||
905 extractVec[MACRONAME_NAME_INDEX] !=
"name")
907 __SS__ <<
"Invalid sequence, 'name' expected in position " << MACRONAME_NAME_INDEX
911 if(SEQUENCE_NAME_INDEX >= extractVec.size() ||
912 extractVec[SEQUENCE_NAME_INDEX] !=
"sequence")
914 __SS__ <<
"Invalid sequence, 'sequence' expected in position "
915 << SEQUENCE_NAME_INDEX << __E__;
918 if(LSBF_NAME_INDEX >= extractVec.size() || extractVec[LSBF_NAME_INDEX] !=
"LSBF")
920 __SS__ <<
"Invalid sequence, 'LSBF' expected in position " << LSBF_NAME_INDEX
924 macroName_ = extractVec[MACRONAME_VALUE_INDEX];
925 __COUTV__(macroName_);
926 lsbf_ = extractVec[LSFBF_VALUE_INDEX] ==
"false" ?
false :
true;
928 std::string& sequence = extractVec[SEQUENCE_VALUE_INDEX];
931 std::vector<std::string> sequenceCommands;
932 StringMacros::getVectorFromString(sequence, sequenceCommands, {
','});
934 __COUTV__(StringMacros::vectorToString(sequenceCommands,
" ### "));
936 for(
auto& command : sequenceCommands)
943 std::vector<std::string> commandPieces;
944 StringMacros::getVectorFromString(command, commandPieces, {
':'});
946 __COUTV__(StringMacros::vectorToString(commandPieces,
" ### "));
948 __COUTV__(commandPieces.size());
959 if(commandPieces.size() < 3 || commandPieces.size() > 4 ||
960 commandPieces[1].size() != 1)
962 __SS__ <<
"Invalid command type specified in command string: " << command
969 std::function<bool(
const std::string&
971 localIsVariable = [](
const std::string& fieldValue) {
973 std::string mfSubject_ =
"isVar";
974 __GEN_COUTV__(fieldValue);
977 for(
const auto& c : fieldValue)
978 if(!((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f') ||
979 (c >=
'A' && c <=
'F')))
985 if(commandPieces[1][0] ==
'r' && commandPieces.size() == 4)
987 __COUT__ <<
"Read type found." << __E__;
991 operations_.push_back(
992 std::make_pair(macroStruct_t::OP_TYPE_READ, readOps_.size()));
994 readOps_.push_back(macroStruct_t::readOp_t());
995 readOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
996 readOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
998 if(!readOps_.back().addressIsVar_)
1002 std::string lsbfData =
"";
1005 commandPieces[2] =
"0" + commandPieces[2];
1006 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1008 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1011 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1013 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1014 __COUTV__(lsbfData);
1016 __COUTV__(lsbfData);
1017 StringMacros::getNumber(
"0x" + lsbfData, readOps_.back().address_);
1020 StringMacros::getNumber(
"0x" + commandPieces[2],
1021 readOps_.back().address_);
1025 readOps_.back().addressVarName_ = commandPieces[2];
1026 __COUTV__(readOps_.back().addressVarName_);
1028 namesOfInputArguments_.emplace(readOps_.back().addressVarName_);
1031 if(readOps_.back().dataIsVar_)
1033 readOps_.back().dataVarName_ = commandPieces[3];
1034 __COUTV__(readOps_.back().dataVarName_);
1036 namesOfOutputArguments_.emplace(readOps_.back().dataVarName_);
1039 else if(commandPieces[1][0] ==
'w' && commandPieces.size() == 4)
1041 __COUT__ <<
"Write type found." << __E__;
1045 operations_.push_back(
1046 std::make_pair(macroStruct_t::OP_TYPE_WRITE, writeOps_.size()));
1048 writeOps_.push_back(macroStruct_t::writeOp_t());
1049 writeOps_.back().addressIsVar_ = localIsVariable(commandPieces[2]);
1050 writeOps_.back().dataIsVar_ = localIsVariable(commandPieces[3]);
1052 if(!writeOps_.back().addressIsVar_)
1056 std::string lsbfData =
"";
1059 commandPieces[2] =
"0" + commandPieces[2];
1060 for(
unsigned int i = 0; i < commandPieces[2].size() / 2; ++i)
1062 __COUTV__(commandPieces[2].size() - 2 * (i + 1));
1065 commandPieces[2][commandPieces[2].size() - 2 * (i + 1)];
1067 commandPieces[2][commandPieces[2].size() - 2 * (i + 1) + 1];
1068 __COUTV__(lsbfData);
1070 __COUTV__(lsbfData);
1071 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().address_);
1074 StringMacros::getNumber(
"0x" + commandPieces[2],
1075 writeOps_.back().address_);
1079 writeOps_.back().addressVarName_ = commandPieces[2];
1080 __COUTV__(writeOps_.back().addressVarName_);
1082 namesOfInputArguments_.emplace(writeOps_.back().addressVarName_);
1085 if(!writeOps_.back().dataIsVar_)
1089 std::string lsbfData =
"";
1092 commandPieces[2] =
"0" + commandPieces[3];
1093 for(
unsigned int i = 0; i < commandPieces[3].size() / 2; ++i)
1095 __COUTV__(commandPieces[3].size() - 2 * (i + 1));
1098 commandPieces[3][commandPieces[3].size() - 2 * (i + 1)];
1100 commandPieces[3][commandPieces[3].size() - 2 * (i + 1) + 1];
1101 __COUTV__(lsbfData);
1103 __COUTV__(lsbfData);
1104 StringMacros::getNumber(
"0x" + lsbfData, writeOps_.back().data_);
1107 StringMacros::getNumber(
"0x" + commandPieces[3],
1108 writeOps_.back().data_);
1112 writeOps_.back().dataVarName_ = commandPieces[3];
1113 __COUTV__(writeOps_.back().dataVarName_);
1115 namesOfInputArguments_.emplace(writeOps_.back().dataVarName_);
1118 else if(commandPieces[1][0] ==
'd' && commandPieces.size() == 3)
1120 __COUT__ <<
"Delay type found." << __E__;
1123 operations_.push_back(
1124 std::make_pair(macroStruct_t::OP_TYPE_DELAY, delayOps_.size()));
1126 delayOps_.push_back(macroStruct_t::delayOp_t());
1127 delayOps_.back().delayIsVar_ = localIsVariable(commandPieces[2]);
1129 if(!delayOps_.back().delayIsVar_)
1130 StringMacros::getNumber(
"0x" + commandPieces[2], delayOps_.back().delay_);
1133 delayOps_.back().delayVarName_ = commandPieces[2];
1134 __COUTV__(delayOps_.back().delayVarName_);
1136 namesOfInputArguments_.emplace(delayOps_.back().delayVarName_);
1141 __SS__ <<
"Invalid command type '" << commandPieces[1][0]
1142 <<
"' specified with " << commandPieces.size() <<
" components."
1149 __COUT__ << operations_.size() <<
" operations extracted: \n\t" << readOps_.size()
1150 <<
" reads \n\t" << writeOps_.size() <<
" writes \n\t" << delayOps_.size()
1151 <<
" delays" << __E__;
1153 __COUT__ <<
"Input arguments: " << __E__;
1154 for(
const auto& inputArg : namesOfInputArguments_)
1155 __COUT__ <<
"\t" << inputArg << __E__;
1157 __COUT__ <<
"Output arguments: " << __E__;
1158 for(
const auto& outputArg : namesOfOutputArguments_)
1159 __COUT__ <<
"\t" << outputArg << __E__;
1165 void FEVInterface::runMacro(
1167 std::map<std::string /*name*/, uint64_t /*value*/>& variableMap)
1171 __FE_COUT__ <<
"Running Macro '" << macro.macroName_ <<
"' of "
1172 << macro.operations_.size() <<
" operations." << __E__;
1174 for(
auto& op : macro.operations_)
1176 if(op.first == macroStruct_t::OP_TYPE_READ)
1178 __FE_COUT__ <<
"Doing read op..." << __E__;
1179 macroStruct_t::readOp_t& readOp = macro.readOps_[op.second];
1180 if(readOp.addressIsVar_)
1182 __FE_COUTV__(readOp.addressVarName_);
1183 readOp.address_ = variableMap.at(readOp.addressVarName_);
1186 uint64_t dataValue = 0;
1188 __FE_COUT__ << std::hex <<
"Read address: \t 0x" << readOp.address_ << __E__
1191 universalRead((
char*)&readOp.address_, (
char*)&dataValue);
1193 __FE_COUT__ << std::hex <<
"Read data: \t 0x" << dataValue << __E__
1196 if(readOp.dataIsVar_)
1198 __FE_COUTV__(readOp.dataVarName_);
1199 variableMap.at(readOp.dataVarName_) = dataValue;
1203 else if(op.first == macroStruct_t::OP_TYPE_WRITE)
1205 __FE_COUT__ <<
"Doing write op..." << __E__;
1206 macroStruct_t::writeOp_t& writeOp = macro.writeOps_[op.second];
1207 if(writeOp.addressIsVar_)
1209 __FE_COUTV__(writeOp.addressVarName_);
1210 writeOp.address_ = variableMap.at(writeOp.addressVarName_);
1212 if(writeOp.dataIsVar_)
1214 __FE_COUTV__(writeOp.dataVarName_);
1215 writeOp.data_ = variableMap.at(writeOp.dataVarName_);
1218 __FE_COUT__ << std::hex <<
"Write address: \t 0x" << writeOp.address_ << __E__
1220 __FE_COUT__ << std::hex <<
"Write data: \t 0x" << writeOp.data_ << __E__
1223 universalWrite((
char*)&writeOp.address_, (
char*)&writeOp.data_);
1226 else if(op.first == macroStruct_t::OP_TYPE_DELAY)
1228 __FE_COUT__ <<
"Doing delay op..." << __E__;
1230 macroStruct_t::delayOp_t& delayOp = macro.delayOps_[op.second];
1231 if(delayOp.delayIsVar_)
1233 __FE_COUTV__(delayOp.delayVarName_);
1234 delayOp.delay_ = variableMap.at(delayOp.delayVarName_);
1237 __FE_COUT__ << std::dec <<
"Delay ms: \t " << delayOp.delay_ << __E__;
1239 usleep(delayOp.delay_ * 1000);
1244 __FE_SS__ <<
"Invalid command type '" << op.first <<
"!'" << __E__;