4 #include "otsdaq-core/Macros/CoutMacros.h"
5 #include "otsdaq-core/Macros/InterfacePluginMacros.h"
6 #include "otsdaq-core/MessageFacility/MessageFacility.h"
7 #include "otsdaq-prepmodernization/FEInterfaces/FENIMPlusInterface.h"
12 #define __MF_SUBJECT__ "FE-FENIMPlusInterface"
14 FENIMPlusInterface::FENIMPlusInterface(
const std::string& interfaceUID,
15 const ConfigurationTree& theXDAQContextConfigTree,
16 const std::string& interfaceConfigurationPath)
17 : Socket(theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
18 .getNode(
"HostIPAddress")
19 .getValue<std::string>(),
20 theXDAQContextConfigTree.getNode(interfaceConfigurationPath)
22 .getValue<unsigned int>())
23 , FEOtsUDPTemplateInterface(
24 interfaceUID, theXDAQContextConfigTree, interfaceConfigurationPath)
27 registerFEMacroFunction(
29 static_cast<FEVInterface::frontEndMacroFunction_t>(
30 &FENIMPlusInterface::FEMacroGenerateTriggers),
31 std::vector<std::string>{
"numberOfTriggers",
34 std::vector<std::string>{
"triggersWereLaunched"},
39 FENIMPlusInterface::~FENIMPlusInterface(
void) {}
42 void FENIMPlusInterface::configure(
void)
44 __CFG_COUT__ <<
"configure" << std::endl;
46 std::string writeBuffer;
47 std::string readBuffer;
48 uint64_t readQuadWord;
50 ConfigurationTree optionalLink =
51 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
52 .getNode(
"LinkToOptionalParameters");
53 bool usingOptionalParams = !optionalLink.isDisconnected();
61 if((usingOptionalParams &&
62 optionalLink.getNode(
"EnableClockResetDuringConfigure").getValue<
bool>()))
64 __CFG_COUT__ <<
"\"Soft\" Resetting NIM PLUS Ethernet!" << std::endl;
66 OtsUDPFirmwareCore::softEthernetReset(writeBuffer);
67 OtsUDPHardware::write(writeBuffer);
68 OtsUDPFirmwareCore::clearEthernetReset(writeBuffer);
69 OtsUDPHardware::write(writeBuffer);
75 __CFG_COUT__ <<
"Could not find reset clock flag, so not resetting... "
80 FEOtsUDPTemplateInterface::configure();
83 __CFG_COUT__ <<
"Choosing external or internal clock..." << std::endl;
84 OtsUDPFirmwareCore::writeAdvanced(
88 ? (optionalLink.getNode(
"UseExternalClock").getValue<
bool>() ? 1 : 0)
90 (((usingOptionalParams
91 ? (optionalLink.getNode(
"ExternalClockSource").getValue<unsigned int>()
92 ? (optionalLink.getNode(
"ExternalClockSource")
93 .getValue<unsigned int>() -
105 ? (optionalLink.getNode(
"UseExternalClock").getValue<
bool>() ? 1 : 0)
107 (((usingOptionalParams
108 ? (optionalLink.getNode(
"ExternalClockSource").getValue<unsigned int>()
109 ? (optionalLink.getNode(
"ExternalClockSource")
110 .getValue<unsigned int>() -
117 __CFG_COUT__ <<
"CHOOSING EXTERNAL CLOCK: " << usingOptionalParams <<
" : "
118 << optionalLink.getNode(
"UseExternalClock").getValue<
bool>() <<
" : "
119 << optionalLink.getNode(
"ExternalClockSource").getValue<
unsigned int>()
120 << std::hex <<
" : " << val << std::dec << std::endl;
122 OtsUDPHardware::write(writeBuffer);
127 OtsUDPFirmwareCore::readAdvanced(writeBuffer,
129 OtsUDPHardware::read(writeBuffer,
133 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x10);
134 OtsUDPHardware::read(writeBuffer, readQuadWord);
135 __CFG_COUT__ <<
"Clocks lock loss " << ((readQuadWord >> 24) & 0xF) << __E__;
139 if(!((readQuadWord >> 24) & 0xF))
141 __CFG_COUT__ <<
"Re-locking clocks..." << std::endl;
143 OtsUDPFirmwareCore::writeAdvanced(
147 OtsUDPHardware::write(writeBuffer);
149 OtsUDPFirmwareCore::writeAdvanced(
150 writeBuffer, 0x999, 0);
151 OtsUDPHardware::write(writeBuffer);
153 OtsUDPFirmwareCore::writeAdvanced(
157 OtsUDPHardware::write(writeBuffer);
159 OtsUDPFirmwareCore::writeAdvanced(
160 writeBuffer, 0x999, 0);
161 OtsUDPHardware::write(writeBuffer);
165 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x10);
166 OtsUDPHardware::read(writeBuffer, readQuadWord);
167 __CFG_COUT__ <<
"Clocks lock loss " << ((readQuadWord >> 24) & 0xF) << __E__;
171 OtsUDPFirmwareCore::readAdvanced(writeBuffer,
173 OtsUDPHardware::read(writeBuffer,
187 OtsUDPFirmwareCore::writeAdvanced(
188 writeBuffer, 0x4, 0x3);
189 OtsUDPHardware::write(writeBuffer);
191 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x18016, 0x3);
192 OtsUDPHardware::write(writeBuffer);
194 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x18017, 0x3);
195 OtsUDPHardware::write(writeBuffer);
197 OtsUDPFirmwareCore::writeAdvanced(
198 writeBuffer, 0x5, 0x0);
199 OtsUDPHardware::write(writeBuffer);
201 OtsUDPFirmwareCore::writeAdvanced(
202 writeBuffer, 0x18013, 0x0);
203 OtsUDPHardware::write(writeBuffer);
205 OtsUDPFirmwareCore::writeAdvanced(
206 writeBuffer, 0x18014, 0x0);
207 OtsUDPHardware::write(writeBuffer);
209 OtsUDPFirmwareCore::writeAdvanced(
210 writeBuffer, 0x18015, 0x0);
211 OtsUDPHardware::write(writeBuffer);
213 OtsUDPFirmwareCore::writeAdvanced(
214 writeBuffer, 0x1800C, 0xF);
215 OtsUDPHardware::write(writeBuffer);
217 sel_ctl_register_ = 0x0;
218 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x6, sel_ctl_register_);
219 OtsUDPHardware::write(writeBuffer);
222 __CFG_COUT__ <<
"Initializing counter/sig-gen/acc-sync resets and enables." << __E__;
229 OtsUDPFirmwareCore::writeAdvanced(
232 nimResets_.to_ulong());
233 OtsUDPHardware::write(writeBuffer);
234 OtsUDPFirmwareCore::writeAdvanced(
235 writeBuffer, 0x18001, nimEnables_.to_ulong());
236 OtsUDPHardware::write(writeBuffer);
240 OtsUDPFirmwareCore::writeAdvanced(
241 writeBuffer, 0x18000, nimResets_.to_ulong());
242 OtsUDPHardware::write(writeBuffer);
244 std::array<std::string, 4> channelNames(
245 {
"ChannelA",
"ChannelB",
"ChannelC",
"ChannelD"});
247 bool doWriteDACs =
false;
251 usingOptionalParams &&
252 optionalLink.getNode(
"EnableDACSetupDuringConfigure").getValue<
bool>();
256 __CFG_COUT__ <<
"Skipping DAC writing because enable field was not found in tree."
262 __CFG_COUT__ <<
"Setting up DACs" << std::endl;
263 const std::string dacValueField =
"DACValue";
264 for(
const auto& channelName : channelNames)
266 changeDACLevel(channelName,
267 optionalLink.getNode(dacValueField + channelName)
268 .getValue<
unsigned short>());
276 unsigned char channelCount = 0;
280 unsigned int logicInput;
281 uint64_t inputModMask;
282 unsigned int inputDelay;
283 unsigned int inputWidth;
285 unsigned char inputPolarityMask = 0;
287 __CFG_COUT__ <<
"Setting up input channels..." << std::endl;
288 for(
const auto& channelName : channelNames)
297 logicInput = theXDAQContextConfigTree_.getNode(theConfigurationPath_)
298 .getNode(
"LogicInput" + channelName)
299 .getValue<
unsigned int>();
302 sel_ctl_register_ |= (logicInput & 0x3) << (channelCount * 2 + 8);
303 __CFG_COUT__ <<
"Logic input " << channelName <<
" : " << logicInput
304 <<
" => sel_ctl_register_= " << std::hex << sel_ctl_register_
305 << std::dec << std::endl;
306 if(usingOptionalParams)
308 inputDelay = optionalLink.getNode(
"DelayInput" + channelName)
309 .getValue<
unsigned int>();
310 inputWidth = optionalLink.getNode(
"WidthInput" + channelName)
311 .getValue<
unsigned int>();
312 inputModMask = (0xFFFFFFFFFFFFFFFF >> (64 - inputWidth)) << inputDelay;
326 invertPolarity = usingOptionalParams &&
327 optionalLink.getNode(
"InvertPolarityInput" + channelName)
330 inputPolarityMask |= ((invertPolarity ? 1 : 0) << channelCount);
332 __CFG_COUT__ <<
"Output word for " << channelName <<
" is "
333 << std::bitset<64>(inputModMask) << std::endl
334 <<
" with a delay of " << inputDelay <<
" and a width of "
335 << inputWidth << std::endl;
337 OtsUDPFirmwareCore::writeAdvanced(writeBuffer,
338 ((channelCount + 1) << 8),
340 OtsUDPHardware::write(writeBuffer);
342 OtsUDPFirmwareCore::writeAdvanced(
344 ((channelCount + 1) << 8) | 0x2,
346 OtsUDPHardware::write(writeBuffer);
354 __CFG_COUT__ <<
"Input polarity mask is " << std::bitset<8>(inputPolarityMask)
356 OtsUDPFirmwareCore::writeAdvanced(
360 OtsUDPHardware::write(writeBuffer);
363 __CFG_COUT__ <<
" sel_ctl_register_: " << std::bitset<16>(sel_ctl_register_)
365 OtsUDPFirmwareCore::writeAdvanced(
371 OtsUDPHardware::write(writeBuffer);
373 __CFG_COUT__ <<
"Writing 40 MHz clock delay." << __E__;
374 OtsUDPFirmwareCore::writeAdvanced(
378 ? optionalLink.getNode(
"40MHzClockDelay").getValue<
unsigned int>()
381 OtsUDPHardware::write(writeBuffer);
383 __CFG_COUT__ <<
"Writing clock mask setup." << __E__;
384 OtsUDPFirmwareCore::writeAdvanced(
389 ? optionalLink.getNode(
"ClockMaskSetup").getValue<
unsigned int>()
391 OtsUDPHardware::write(writeBuffer);
395 OtsUDPFirmwareCore::writeAdvanced(
398 nimResets_.to_ulong());
399 OtsUDPHardware::write(writeBuffer);
402 OtsUDPFirmwareCore::writeAdvanced(
405 nimResets_.to_ulong());
406 OtsUDPHardware::write(writeBuffer);
408 __CFG_COUT__ <<
"Clock mask setup: " << std::hex
409 << optionalLink.getNode(
"ClockMaskSetup").getValue<
unsigned int>()
410 << std::dec << std::endl;
412 catch(
const std::runtime_error& e)
414 __CFG_COUT__ <<
"Failed input stage setup!\n" << e.what() << std::endl;
421 unsigned char channelCount = 0;
423 unsigned int outputDelay;
424 unsigned int outputWidthMask;
425 uint64_t outputWidth;
426 uint64_t outputModMask;
428 unsigned int outputMuxSelect;
429 unsigned int outputChannelSourceSelect;
430 unsigned int outputTimeVetoDuration, outputPrescaleCount;
431 bool outputBackpressureSelect;
432 unsigned char backpressureMask = 0;
433 unsigned int gateChannelVetoSel[3] = {0, 0, 0};
435 __CFG_COUT__ <<
"Setting up output channels..." << std::endl;
437 std::array<std::string, 3> outChannelNames = {
"Channel0",
"Channel1",
"Channel2"};
438 for(
const auto& channelName : outChannelNames)
440 outputChannelSourceSelect =
441 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
442 .getNode(
"TriggerInput" + channelName)
443 .getValue<
unsigned int>();
444 __CFG_COUT__ <<
"TriggerInput for " << channelName <<
" is "
445 << outputChannelSourceSelect << std::endl;
446 if(outputChannelSourceSelect)
448 --outputChannelSourceSelect;
450 if(usingOptionalParams)
452 outputDelay = optionalLink.getNode(
"DelayTriggerOutput" + channelName)
453 .getValue<
unsigned int>();
454 outputWidth = optionalLink.getNode(
"WidthTriggerOutput" + channelName)
455 .getValue<uint64_t>();
460 outputWidthMask = 64;
463 outputWidthMask = outputWidth;
466 outputModMask = (0xFFFFFFFFFFFFFFFF >> (64 - outputWidthMask))
472 outputTimeVetoDuration =
473 optionalLink.getNode(
"TimeVetoTriggerOutput" + channelName)
474 .getValue<
unsigned int>();
476 outputPrescaleCount =
477 optionalLink.getNode(
"PrescaleTriggerOutput" + channelName)
478 .getValue<
unsigned int>();
479 outputBackpressureSelect =
480 optionalLink.getNode(
"BackpressureTriggerOutput" + channelName)
482 gateChannelVetoSel[channelCount] =
483 optionalLink.getNode(
"VetoSourceTriggerOutput" + channelName)
485 __CFG_COUT__ <<
"Raw gateChannelVetoSelect for " << channelName <<
" is "
486 << gateChannelVetoSel[channelCount] << std::endl;
491 outputModMask = 0xFFF;
493 outputTimeVetoDuration = 0;
494 outputPrescaleCount = 0;
495 outputBackpressureSelect =
false;
498 if(gateChannelVetoSel[channelCount] <= 1)
499 gateChannelVetoSel[channelCount] = 4;
501 gateChannelVetoSel[channelCount] -= 2;
503 backpressureMask |= (outputBackpressureSelect ? 1 : 0) << channelCount;
505 OtsUDPFirmwareCore::writeAdvanced(
507 channelCount == 0 ? 0x4 : (0x18016 + channelCount - 1),
509 OtsUDPHardware::write(writeBuffer);
511 OtsUDPFirmwareCore::writeAdvanced(
513 channelCount == 0 ? 0x2 : (0x18002 + channelCount - 1),
515 OtsUDPHardware::write(writeBuffer);
517 OtsUDPFirmwareCore::writeAdvanced(
519 0x106 + channelCount * 0x100,
520 outputWidth | (uint64_t(outputWidth ? 1 : 0 )
522 OtsUDPHardware::write(writeBuffer);
524 __CFG_COUT__ <<
"Output word for " << channelName <<
" is "
525 << std::bitset<64>(outputModMask) << std::endl;
526 __CFG_COUT__ <<
"Output delay of " << outputDelay
527 <<
" and an extended width of " << outputWidth << std::endl;
531 writeBuffer.resize(0);
532 OtsUDPFirmwareCore::writeAdvanced(
534 (0x18018 + channelCount - 1),
535 outputChannelSourceSelect);
537 OtsUDPHardware::write(writeBuffer);
538 __CFG_COUT__ <<
"Output src select is " << outputChannelSourceSelect
539 <<
" for " << channelName << std::endl;
543 writeBuffer.resize(0);
544 OtsUDPFirmwareCore::writeAdvanced(
546 channelCount == 0 ? 0x1801B : (0x18011 + channelCount - 1),
547 outputTimeVetoDuration);
548 OtsUDPHardware::write(writeBuffer);
550 __CFG_COUT__ <<
"Veto count for " << channelName <<
" is "
551 << outputTimeVetoDuration <<
" writing to ch "
552 << (channelCount == 0 ? 0x1801B : (0x18011 + channelCount - 1))
556 writeBuffer.resize(0);
557 OtsUDPFirmwareCore::writeAdvanced(
558 writeBuffer, 0x1801C + channelCount, 0);
559 OtsUDPHardware::write(writeBuffer);
560 writeBuffer.resize(0);
561 OtsUDPFirmwareCore::writeAdvanced(
562 writeBuffer, 0x1801C + channelCount, outputPrescaleCount);
563 OtsUDPHardware::write(writeBuffer);
565 __CFG_COUT__ <<
"Prescaler count for " << channelName <<
" is "
566 << outputPrescaleCount <<
" writing to ch "
567 << 0x1801C + channelCount << std::endl;
577 __CFG_COUT__ <<
"Backpressure Selecting..." << std::endl;
578 outputBackpressureSelect =
579 usingOptionalParams &&
580 optionalLink.getNode(
"EnableBackPressureNwFmcPta1").getValue<
bool>();
581 backpressureMask |= outputBackpressureSelect << 3;
582 outputBackpressureSelect =
583 usingOptionalParams &&
584 optionalLink.getNode(
"EnableBackPressureNwFmcPta2").getValue<
bool>();
585 backpressureMask |= outputBackpressureSelect << 4;
586 writeBuffer.resize(0);
587 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1801A, backpressureMask);
588 OtsUDPHardware::write(writeBuffer);
591 OtsUDPFirmwareCore::writeAdvanced(
592 writeBuffer, 0x200, (uint64_t)-1);
593 OtsUDPHardware::write(writeBuffer);
596 __CFG_COUT__ <<
"Setting output muxes..." << std::endl;
597 unsigned int outputPolarityMask = 0;
598 bool outputInvertPolarity;
600 for(
const auto& channelName : channelNames)
602 outputMuxSelect = theXDAQContextConfigTree_.getNode(theConfigurationPath_)
603 .getNode(
"OutputMuxSelect" + channelName)
604 .getValue<
unsigned int>();
609 if(outputMuxSelect > 31)
612 throw std::runtime_error(ss.str() +
"Invalid output mux select!");
615 if(usingOptionalParams)
617 outputInvertPolarity =
618 usingOptionalParams &&
619 optionalLink.getNode(
"InvertPolarityOutput" + channelName)
621 outputPolarityMask |= ((outputInvertPolarity ? 1 : 0) << channelCount);
625 outputPolarityMask = 0xF;
628 writeBuffer.resize(0);
629 OtsUDPFirmwareCore::writeAdvanced(
631 channelCount == 0 ? 0x5 : (0x18013 + channelCount - 1),
633 OtsUDPHardware::write(writeBuffer);
634 __CFG_COUT__ <<
"Mux value for output channel " << channelName <<
" is "
635 << outputMuxSelect <<
", written to 0x" << std::hex
636 << (channelCount == 0 ? 0x5 : (0x18013 + channelCount - 1))
637 << std::dec << std::endl;
642 writeBuffer.resize(0);
643 OtsUDPFirmwareCore::writeAdvanced(
647 OtsUDPHardware::write(writeBuffer);
648 __CFG_COUT__ <<
"Output polarity mask is " << std::bitset<8>(outputPolarityMask)
652 if(usingOptionalParams)
669 uint64_t trigClkOutBankRegister = 0;
670 unsigned int bank = 0;
672 std::array<std::string, 2> trigClkOutBankNames = {
673 "TriggerMuxSelectionsBankA",
"TriggerMuxSelectionsBankB"};
674 for(
auto& trigClkOutBankName : trigClkOutBankNames)
676 __COUTV__(trigClkOutBankName);
678 ConfigurationTree::BitMap bankSelectionMap =
679 optionalLink.getNode(trigClkOutBankName).getValueAsBitMap();
684 unsigned int col = 0;
685 for(; col < 6; ++col)
686 trigClkOutBankRegister |=
687 (bankSelectionMap.get(0, col) & 0x3)
688 << ((bank * 6 + col) *
691 for(; col < 9; ++col)
692 trigClkOutBankRegister |=
693 (bankSelectionMap.get(0, col) & 0x3)
694 << ((12 + bank * 3 + col) *
700 OtsUDPFirmwareCore::writeAdvanced(
703 trigClkOutBankRegister);
704 OtsUDPHardware::write(writeBuffer);
709 __CFG_COUT__ <<
"Setting up Burst Data Blocks" << std::endl;
711 unsigned int logicSampleDelay = 0;
712 unsigned int gateChannel = 0;
713 unsigned int gateChannelReg =
714 (gateChannelVetoSel[2] << 8) | (gateChannelVetoSel[1] << 4) |
715 (gateChannelVetoSel[0] << 0);
717 __CFG_COUT__ <<
"Gate Ch Veto Selections - 2: " << gateChannelVetoSel[2]
719 __CFG_COUT__ <<
"Gate Ch Veto Selections - 1: " << gateChannelVetoSel[1]
721 __CFG_COUT__ <<
"Gate Ch Veto Selections - 0: " << gateChannelVetoSel[0]
726 if(usingOptionalParams)
729 optionalLink.getNode(
"BurstDataMuxSelect").getValue<
unsigned int>();
730 logicSampleDelay = optionalLink.getNode(
"BurstDataLogicSampleDelay")
731 .getValue<
unsigned int>();
732 gateChannel = optionalLink.getNode(
"BurstDataGateInputChannel")
733 .getValue<
unsigned int>();
746 gateChannelReg |= gateChannel << 12;
750 gateChannelReg |= 4 << 12;
752 __CFG_COUT__ <<
"Gate Ch Veto Selections - Burst: " << gateChannel
754 std::bitset<16> gateChannelRegBitset(gateChannelReg);
755 __CFG_COUT__ <<
"Gate Ch Veto Register: " << gateChannelReg << std::endl;
756 __CFG_COUT__ <<
"Gate Ch Veto Register: " << gateChannelRegBitset.to_string()
759 OtsUDPFirmwareCore::writeAdvanced(
760 writeBuffer, 0x1800E, outputMuxSelect);
761 OtsUDPHardware::write(writeBuffer);
763 OtsUDPFirmwareCore::writeAdvanced(
767 OtsUDPHardware::write(writeBuffer);
769 OtsUDPFirmwareCore::writeAdvanced(
773 OtsUDPHardware::write(writeBuffer);
775 if(outputMuxSelect == 1)
777 OtsUDPFirmwareCore::writeAdvanced(
778 writeBuffer, 0x1800F, 0x2);
779 OtsUDPHardware::write(writeBuffer);
783 OtsUDPFirmwareCore::writeAdvanced(
784 writeBuffer, 0x1800F, 0);
785 OtsUDPHardware::write(writeBuffer);
790 unsigned int coincidenceLogicWord =
791 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
792 .getNode(
"CoincidenceLogicWord")
793 .getValue<
unsigned int>();
795 sel_ctl_register_ |= 1;
796 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x6, sel_ctl_register_);
797 OtsUDPHardware::write(writeBuffer);
798 __CFG_COUT__ <<
" sel_ctl_register_ 1: " << std::bitset<16>(sel_ctl_register_)
803 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x6, sel_ctl_register_);
804 OtsUDPHardware::write(writeBuffer);
805 __CFG_COUT__ <<
" sel_ctl_register_ 2: " << std::bitset<16>(sel_ctl_register_)
808 OtsUDPFirmwareCore::writeAdvanced(
809 writeBuffer, 0x7, coincidenceLogicWord);
810 OtsUDPHardware::write(writeBuffer);
811 __CFG_COUT__ <<
"Selection Logic word is bit: "
812 << std::bitset<16>(coincidenceLogicWord) << std::endl;
818 sel_ctl_register_ |= 1 << 1;
819 OtsUDPFirmwareCore::writeAdvanced(
820 writeBuffer, 0x6, sel_ctl_register_);
821 OtsUDPHardware::write(writeBuffer);
822 __CFG_COUT__ <<
" sel_ctl_register_: 3" << std::bitset<16>(sel_ctl_register_)
825 unsigned int sigGenCount =
826 optionalLink.getNode(
"SignalGeneratorPulseCount").getValue<
unsigned int>();
827 unsigned int sigGenHighPer =
828 optionalLink.getNode(
"SignalGeneratorHighPeriod").getValue<
unsigned int>();
829 unsigned int sigGenLowPer =
830 optionalLink.getNode(
"SignalGeneratorLowPeriod").getValue<
unsigned int>();
831 bool sigGenPolarity =
832 optionalLink.getNode(
"SignalGeneratorInvertPolarity").getValue<
bool>();
833 unsigned int sigGenPolarityMask = (sigGenPolarity ? 1 : 0);
835 if(optionalLink.getNode(
"SignalGeneratorEnable").getValue<
bool>())
838 OtsUDPFirmwareCore::writeAdvanced(
839 writeBuffer, 0x18000, nimResets_.to_ulong());
840 OtsUDPHardware::write(writeBuffer);
842 __CFG_COUT__ <<
"Resets all for sig gen!" << std::endl;
845 writeBuffer.resize(0);
846 OtsUDPFirmwareCore::writeAdvanced(
847 writeBuffer, 0x18005, sigGenCount);
848 OtsUDPHardware::write(writeBuffer);
849 writeBuffer.resize(0);
850 OtsUDPFirmwareCore::writeAdvanced(
851 writeBuffer, 0x18006, sigGenHighPer);
852 OtsUDPHardware::write(writeBuffer);
853 writeBuffer.resize(0);
854 OtsUDPFirmwareCore::writeAdvanced(
855 writeBuffer, 0x18007, sigGenLowPer);
856 OtsUDPHardware::write(writeBuffer);
857 writeBuffer.resize(0);
858 OtsUDPFirmwareCore::writeAdvanced(
859 writeBuffer, 0x1800D, sigGenPolarityMask);
860 OtsUDPHardware::write(writeBuffer);
862 __CFG_COUT__ <<
"Configured signal generator with a count of " << sigGenCount
863 <<
" (0 is continuous output), a high period of "
864 << sigGenHighPer <<
", a low period of " << sigGenLowPer
865 <<
", and output inversion set to " << sigGenPolarity
875 nimEnables_.reset(5);
876 __CFG_COUT__ <<
"Signal Generator disabled" << std::endl;
879 OtsUDPFirmwareCore::writeAdvanced(
882 nimResets_.to_ulong());
883 OtsUDPHardware::write(writeBuffer);
884 __CFG_COUT__ <<
"Nim Resets (after sig gen setup) set to " << nimResets_
887 OtsUDPFirmwareCore::writeAdvanced(
888 writeBuffer, 0x18001, nimEnables_.to_ulong());
889 OtsUDPHardware::write(writeBuffer);
890 __CFG_COUT__ <<
"Nim Enables (after sig gen setup) set to " << nimEnables_
893 catch(
const std::runtime_error& e)
895 __CFG_COUT__ <<
"Failed output stage setup!\n" << e.what() << std::endl;
899 __CFG_COUT__ <<
"Checking sel_ctl_register_... Expect sel_ctl_register_ = 0x"
900 << std::hex << sel_ctl_register_ << std::dec << std::endl;
903 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 10 );
914 __CFG_COUT__ <<
"sel_ctl_register_ = 0x" << std::hex << sel_ctl_register_ << std::dec
920 __CFG_COUT__ <<
" sel_ctl_register_: " << std::bitset<16>(sel_ctl_register_)
923 __CFG_COUT__ <<
"Done with configuring." << std::endl;
927 void FENIMPlusInterface::halt(
void)
929 __CFG_COUT__ <<
"\tHalt" << std::endl;
934 void FENIMPlusInterface::pause(
void)
936 __CFG_COUT__ <<
"\tPause" << std::endl;
941 void FENIMPlusInterface::resume(
void)
943 __CFG_COUT__ <<
"\tResume" << std::endl;
948 void FENIMPlusInterface::start(std::string runNumber)
950 runNumber_ = runNumber;
951 __CFG_COUT__ <<
"\tStart " << runNumber_ << std::endl;
952 std::string writeBuffer;
957 __CFG_COUT__ <<
"Disabling sig_log" << std::endl;
958 OtsUDPFirmwareCore::writeAdvanced(
961 (sel_ctl_register_) & (~(1 << 1)));
962 OtsUDPHardware::write(writeBuffer);
964 __CFG_COUT__ <<
"Resetting all counters (including sig log)" << std::endl;
969 OtsUDPFirmwareCore::writeAdvanced(
970 writeBuffer, 0x18000, nimResets_.to_ulong());
973 OtsUDPHardware::write(writeBuffer);
976 OtsUDPFirmwareCore::writeAdvanced(
979 nimResets_.to_ulong());
980 OtsUDPHardware::write(writeBuffer);
982 ConfigurationTree optionalLink =
983 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
984 .getNode(
"LinkToOptionalParameters");
985 bool usingOptionalParams = !optionalLink.isDisconnected();
987 if(usingOptionalParams && optionalLink.getNode(
"EnableBurstData").getValue<
bool>())
989 __CFG_COUT__ <<
"Enabling burst mode!" << __E__;
990 OtsUDPFirmwareCore::startBurst(writeBuffer);
991 OtsUDPHardware::write(writeBuffer);
995 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1801F, 0x6);
996 OtsUDPHardware::write(writeBuffer);
997 __CFG_COUT__ <<
"\tStart Done" << std::endl;
1001 void FENIMPlusInterface::stop(
void)
1003 std::string writeBuffer;
1005 OtsUDPFirmwareCore::writeAdvanced(
1008 (sel_ctl_register_) & (~(1 << 1)));
1009 OtsUDPHardware::write(writeBuffer);
1011 __CFG_COUT__ <<
"\tStop" << std::endl;
1014 runSequenceOfCommands(
"LinkToStopSequence");
1017 OtsUDPFirmwareCore::stopBurst(writeBuffer);
1018 OtsUDPHardware::write(writeBuffer);
1020 uint64_t readQuadWord;
1022 ConfigurationTree optionalLink =
1023 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
1024 .getNode(
"LinkToOptionalParameters");
1025 if(!optionalLink.isDisconnected())
1029 optionalLink.getNode(
"TriggerCountAtRunStopFilename").getValue<std::string>();
1031 if(filename !=
"DEFAULT" && filename !=
"")
1033 std::string filename = optionalLink.getNode(
"TriggerCountAtRunStopFilename")
1034 .getValue<std::string>();
1036 if(filename !=
"DEFAULT" && filename !=
"")
1038 filename +=
"_" + runNumber_ +
".cnt";
1040 __CFG_COUT__ <<
"Attempting to save counts to " << filename << __E__;
1048 __CFG_COUT__ <<
"Saving counts to " << filename << __E__;
1054 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x102);
1055 OtsUDPHardware::read(writeBuffer, readQuadWord);
1057 count = (readQuadWord >> 32);
1059 count = (count & 0x0FFFFFFF);
1060 __CFG_COUT__ <<
"sig_log count = " << count << __E__;
1061 fprintf(fp,
"sig_log \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1063 count = (readQuadWord & 0x0FFFFFFFF);
1065 count = (count & 0x0FFFFFFF);
1066 __CFG_COUT__ <<
"sig_norm(out0) count = " << count << __E__;
1068 fp,
"sig_norm(out0) \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1070 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x100);
1071 OtsUDPHardware::read(writeBuffer, readQuadWord);
1073 count = (readQuadWord & 0x0FFFFFFFF);
1075 count = (count & 0x0FFFFFFF);
1076 __CFG_COUT__ <<
"sig_cms1(out1) count = " << count << __E__;
1078 fp,
"sig_cms1(out1) \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1080 count = (readQuadWord >> 32);
1082 count = (count & 0x0FFFFFFF);
1083 __CFG_COUT__ <<
"sig_cms2(out2) count = " << count << __E__;
1085 fp,
"sig_cms2(out2) \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1087 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x105);
1088 OtsUDPHardware::read(writeBuffer, readQuadWord);
1090 count = (readQuadWord & 0x0FFFFFFFF);
1092 count = (count & 0x0FFFFFFF);
1093 __CFG_COUT__ <<
"muxout-A count = " << count << __E__;
1094 fprintf(fp,
"muxout-A \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1096 count = (readQuadWord >> 32);
1098 count = (count & 0x0FFFFFFF);
1099 __CFG_COUT__ <<
"muxout-B count = " << count << __E__;
1100 fprintf(fp,
"muxout-B \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1102 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x106);
1103 OtsUDPHardware::read(writeBuffer, readQuadWord);
1105 count = (readQuadWord & 0x0FFFFFFFF);
1107 count = (count & 0x0FFFFFFF);
1108 __CFG_COUT__ <<
"muxout-C count = " << count << __E__;
1109 fprintf(fp,
"muxout-C \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1111 count = (readQuadWord >> 32);
1113 count = (count & 0x0FFFFFFF);
1114 __CFG_COUT__ <<
"muxout-D count = " << count << __E__;
1115 fprintf(fp,
"muxout-D \t [tag=%d] %d 0x%4.4X\n", tag, count, count);
1118 OtsUDPFirmwareCore::readAdvanced(writeBuffer, 0x10);
1119 OtsUDPHardware::read(writeBuffer, readQuadWord);
1121 __CFG_COUT__ <<
"Clocks lock loss " << count << __E__;
1123 count = (((readQuadWord >> 24) & 0xF) >> 0) & 1;
1125 fp,
"DAC Clock-Lock-Loss \t %d 0x%4.4X\n", count, count);
1126 count = (((readQuadWord >> 24) & 0xF) >> 1) & 1;
1128 fp,
"Main Clock-Lock-Loss \t %d 0x%4.4X\n", count, count);
1129 count = (((readQuadWord >> 24) & 0xF) >> 2) & 1;
1131 fp,
"External Clock-Lock-Loss \t %d 0x%4.4X\n", count, count);
1132 count = (((readQuadWord >> 24) & 0xF) >> 3) & 1;
1134 fp,
"OutPhase Clock-Lock-Loss \t %d 0x%4.4X\n", count, count);
1144 writeBuffer.resize(0);
1145 OtsUDPFirmwareCore::writeAdvanced(
1146 writeBuffer, 0x4, 0x33);
1149 OtsUDPHardware::write(writeBuffer);
1153 bool FENIMPlusInterface::running(
void)
1155 std::string writeBuffer;
1163 __CFG_COUT__ <<
"Running" << std::endl;
1164 __CFG_COUT__ <<
" sel_ctl_register_: " << std::bitset<16>(sel_ctl_register_)
1170 ConfigurationTree optionalLink =
1171 theXDAQContextConfigTree_.getNode(theConfigurationPath_)
1172 .getNode(
"LinkToOptionalParameters");
1173 bool usingOptionalParams = !optionalLink.isDisconnected();
1178 unsigned int sleepSeconds = 0;
1179 if(usingOptionalParams)
1183 sleepSeconds = optionalLink.getNode(
"SecondsDelayBeforeStartingTriggers")
1184 .getValue<
unsigned int>();
1189 <<
"Ingore missing SecondsDelayBeforeStartingTriggers field..."
1195 __CFG_COUT__ <<
"Sleeping for " << sleepSeconds <<
" seconds..." << __E__;
1196 sleep(sleepSeconds);
1198 unsigned char channelCount = 0;
1199 bool enable40MHzMask;
1200 unsigned int gateChannelVetoSel;
1203 std::array<std::string, 3> outChannelNames = {
"Channel0",
"Channel1",
"Channel2"};
1205 __CFG_COUT__ <<
"Enabling output trigger channels!" << std::endl;
1208 for(channelCount = 2; channelCount <= 2; --channelCount)
1211 usingOptionalParams && optionalLink
1212 .getNode(
"EnableClockMaskTriggerOutput" +
1213 outChannelNames[channelCount])
1215 gateChannelVetoSel = usingOptionalParams
1217 .getNode(
"VetoSourceTriggerOutput" +
1218 outChannelNames[channelCount])
1222 OtsUDPFirmwareCore::writeAdvanced(
1224 channelCount == 0 ? 0x4 : (0x18016 + channelCount - 1),
1225 (enable40MHzMask ? 0x0 : 0x8) |
1226 (gateChannelVetoSel <= 1
1229 OtsUDPHardware::write(writeBuffer);
1232 __CFG_COUT__ <<
"Enabling siglog block!" << __E__;
1233 __CFG_COUT__ <<
" sel_ctl_register_: " << std::bitset<16>(sel_ctl_register_)
1235 OtsUDPFirmwareCore::writeAdvanced(
1241 OtsUDPHardware::write(writeBuffer);
1243 catch(
const std::runtime_error& e)
1245 __SS__ <<
"Failed start setup!\n" << e.what() << std::endl;
1246 __CFG_COUT_ERR__ << ss.str();
1247 throw std::runtime_error(ss.str());
1286 void FENIMPlusInterface::FEMacroGenerateTriggers(__ARGS__)
1288 __CFG_COUT__ <<
"FEMacroGenerateTriggers" << __E__;
1290 unsigned int numberOfTriggers = __GET_ARG_IN__(
"numberOfTriggers",
unsigned int);
1291 unsigned int signalHiDuration = __GET_ARG_IN__(
"signalHiDuration",
unsigned int);
1292 unsigned int signalLoDuration = __GET_ARG_IN__(
"signalLoDuration",
unsigned int);
1293 std::string& triggersWereLaunched =
1294 getFEMacroArgument(argsOut,
"triggersWereLaunched");
1295 std::string numberOfTriggersStr = __GET_ARG_IN__(
"numberOfTriggers", std::string);
1297 __CFG_COUTV__(numberOfTriggers);
1298 __CFG_COUTV__(signalHiDuration);
1299 __CFG_COUTV__(signalLoDuration);
1300 __CFG_COUTV__(numberOfTriggersStr);
1304 std::string writeBuffer;
1307 nimEnables_.reset(5);
1308 OtsUDPFirmwareCore::writeAdvanced(
1309 writeBuffer, 0x18001, nimEnables_.to_ulong());
1310 OtsUDPHardware::write(writeBuffer);
1311 __CFG_COUT__ <<
"Nim Enables set to 0x" << std::hex << nimEnables_ << std::dec
1319 OtsUDPFirmwareCore::writeAdvanced(
1320 writeBuffer, 0x18005, nimEnables_.to_ulong());
1321 OtsUDPHardware::write(writeBuffer);
1322 __CFG_COUT__ <<
"Nim Enables set to 0x" << std::hex << nimEnables_ << std::dec
1331 OtsUDPFirmwareCore::writeAdvanced(
1332 writeBuffer, 0x18001, numberOfTriggers);
1333 OtsUDPHardware::write(writeBuffer);
1334 __CFG_COUT__ <<
"Nim Enables set to 0x" << std::hex << nimEnables_ << std::dec
1338 __CFG_COUT__ <<
"triggersWereLaunched " << triggersWereLaunched << __E__;
1339 triggersWereLaunched =
"Done!";
1340 __CFG_COUT__ <<
"triggersWereLaunched " << triggersWereLaunched << __E__;
1341 __SET_ARG_OUT__(
"triggersWereLaunched", 42.2f);
1342 __CFG_COUT__ <<
"triggersWereLaunched " << triggersWereLaunched << __E__;
1343 __SET_ARG_OUT__(
"triggersWereLaunched", 42.2f);
1344 __CFG_COUT__ <<
"triggersWereLaunched " << triggersWereLaunched << __E__;
1348 void FENIMPlusInterface::changeDACLevel(
const std::string& channelName,
1349 unsigned int dacValue)
1351 std::string writeBuffer;
1355 std::map<std::string, unsigned int> channelNameToAddressMap;
1361 channelNameToAddressMap[
"ChannelA"] = 0x2;
1362 channelNameToAddressMap[
"ChannelB"] = 0x6;
1363 channelNameToAddressMap[
"ChannelC"] = 0x9;
1364 channelNameToAddressMap[
"ChannelD"] = 0xe;
1365 const std::string dacValueField =
"DACValue";
1366 writeBuffer.resize(0);
1367 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1, 0x0);
1368 OtsUDPHardware::write(writeBuffer);
1378 writeBuffer.resize(0);
1379 OtsUDPFirmwareCore::writeAdvanced(
1382 (channelNameToAddressMap[channelName] << 12) | (dacValue & 0xFFF));
1383 OtsUDPHardware::write(writeBuffer);
1385 writeBuffer.resize(0);
1386 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1, 0x2);
1387 OtsUDPHardware::write(writeBuffer);
1388 writeBuffer.resize(0);
1389 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1, 0x0);
1390 OtsUDPHardware::write(writeBuffer);
1391 writeBuffer.resize(0);
1392 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1, 0x4);
1393 OtsUDPHardware::write(writeBuffer);
1394 writeBuffer.resize(0);
1395 OtsUDPFirmwareCore::writeAdvanced(writeBuffer, 0x1, 0x0);
1396 OtsUDPHardware::write(writeBuffer);