Line data Source code
1 : #include "DTC_Registers.h"
2 :
3 : #include <assert.h>
4 : #include <unistd.h>
5 : #include <chrono>
6 : #include <cmath>
7 : #include <iomanip> // std::setw, std::setfill
8 : #include <sstream> // Convert uint to hex string
9 :
10 : #include "TRACE/tracemf.h"
11 :
12 : #define TLVL_ResetDTC TLVL_DEBUG + 5
13 : #define TLVL_AutogenDRP TLVL_DEBUG + 6
14 : #define TLVL_SERDESReset TLVL_DEBUG + 7
15 : #define TLVL_CalculateFreq TLVL_DEBUG + 8
16 : #define TLVL_Detail TLVL_DEBUG + 11
17 : #define TLVL_ReadRegister TLVL_DEBUG + 20
18 :
19 : #include "dtcInterfaceLib/otsStyleCoutMacros.h"
20 :
21 : #undef __COUT_HDR__
22 : #define __COUT_HDR__ "DTC " << this->getDeviceUID() << ": "
23 :
24 : /// <summary>
25 : /// Construct an instance of the DTC register map
26 : /// </summary>
27 : /// <param name="mode">Default: DTC_SimMode_Disabled; The simulation mode of the DTC</param>
28 : /// <param name="dtc">DTC card index to use</param>
29 : /// <param name="simFileName">Name to use for simulated DTC memory file, if needed</param>
30 : /// <param name="rocMask">Nibble-mask for enabled ROCs. Ex. 0x1011 enables ROC0, 1, and 3</param>
31 : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will
32 : /// throw an exception if the DTC firmware does not match (Default: "")</param>
33 : /// <param name="skipInit">Whether to skip initialization phase for reading DTC out in current state</param>
34 0 : DTCLib::DTC_Registers::DTC_Registers(DTC_SimMode mode, int dtc, std::string simFileName, unsigned rocMask, std::string expectedDesignVersion,
35 0 : bool skipInit, const std::string& uid)
36 0 : : simMode_(mode), usingDetectorEmulator_(false), dmaSize_(64)
37 : {
38 0 : TLOG(TLVL_TRACE) << "CONSTRUCTOR";
39 :
40 0 : auto sim = getenv("DTCLIB_SIM_ENABLE");
41 0 : if (sim != nullptr)
42 : {
43 0 : auto simstr = std::string(sim);
44 0 : simMode_ = DTC_SimModeConverter::ConvertToSimMode(simstr);
45 0 : }
46 :
47 0 : if (dtc == -1)
48 : {
49 0 : auto dtcE = getenv("DTCLIB_DTC");
50 0 : if (dtcE != nullptr)
51 : {
52 0 : dtc = atoi(dtcE);
53 : }
54 : else
55 0 : dtc = 0;
56 : }
57 :
58 0 : SetSimMode(expectedDesignVersion, simMode_, dtc, simFileName, rocMask, skipInit, (uid == "" ? ("DTC" + std::to_string(dtc)) : uid));
59 0 : } // end constructor()
60 :
61 : /// <summary>
62 : /// DTC_Registers destructor
63 : /// </summary>
64 0 : DTCLib::DTC_Registers::~DTC_Registers()
65 : {
66 0 : TLOG(TLVL_INFO) << "DESTRUCTOR";
67 0 : DisableDetectorEmulator();
68 : // DisableDetectorEmulatorMode();
69 : // DisableCFOEmulation();
70 : // SoftReset();
71 0 : TLOG(TLVL_INFO) << "DESTRUCTOR end";
72 0 : } // end destructor()
73 :
74 : /// <summary>
75 : /// Initialize the DTC in the given SimMode.
76 : /// </summary>
77 : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will throw an exception if the DTC firmware does not match</param>
78 : /// <param name="mode">Mode to set</param>
79 : /// <param name="dtc">DTC card index to use</param>
80 : /// <param name="simMemoryFile">Name to use for simulated DTC memory file, if needed</param>
81 : /// <param name="rocMask">Default 0x1; The initially-enabled links. Each digit corresponds to a link, so all links = 0x111111</param>
82 : /// <param name="skipInit">Whether to skip initializing the DTC using the SimMode. Used to read state.</param>
83 : /// <returns></returns>
84 0 : DTCLib::DTC_SimMode DTCLib::DTC_Registers::SetSimMode(std::string expectedDesignVersion, DTC_SimMode mode, int dtc, std::string simMemoryFile,
85 : unsigned rocMask, bool skipInit, const std::string& uid)
86 : {
87 0 : simMode_ = mode;
88 0 : TLOG(TLVL_INFO) << "Initializing DTC device, sim mode is " << DTC_SimModeConverter(simMode_).toString() << " for uid = " << uid << ", deviceIndex = " << dtc << ", expectedDesignVersion = " << expectedDesignVersion;
89 :
90 0 : device_.init(simMode_, dtc, simMemoryFile, uid);
91 0 : if (expectedDesignVersion != "")
92 : {
93 0 : uint32_t parsedExpectedVersion = 0;
94 0 : std::string parsedDesignDate = "";
95 : try
96 : {
97 0 : parsedExpectedVersion = static_cast<uint32_t>(std::stoul(expectedDesignVersion, nullptr, 16));
98 0 : parsedDesignDate = ReadDesignDate(parsedExpectedVersion);
99 : }
100 0 : catch (...) // illegal/non-hex expectedDesignVersion
101 : {
102 0 : __SS__;
103 0 : ss << "Version mismatch (is Expected Firmware Version string legal?)! Expected DTC (device index #" << dtc << ") version is '" << expectedDesignVersion << "' while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
104 0 : __SS_THROW__;
105 0 : }
106 :
107 0 : if (parsedExpectedVersion != ReadRegister_(CFOandDTC_Register_DesignDate))
108 : {
109 0 : __SS__;
110 0 : ss << "Version mismatch! Expected DTC (device index #" << dtc << ") version is '" << parsedDesignDate << "' (0x" << std::hex << parsedExpectedVersion << " != 0x" << ReadRegister_(CFOandDTC_Register_DesignDate) << ") while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
111 0 : __SS_THROW__;
112 : // throw new DTC_WrongVersionException(expectedDesignVersion, ReadDesignVersion());
113 0 : }
114 0 : }
115 :
116 : // if (skipInit || true)
117 0 : if (skipInit)
118 : {
119 0 : __COUT_INFO__ << "SKIPPING Initializing device";
120 0 : return simMode_;
121 : }
122 :
123 0 : __COUT__ << "Initialize requested, setting device registers acccording to sim mode " << DTC_SimModeConverter(simMode_).toString();
124 :
125 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up DTC links...";
126 0 : for (auto link : DTC_ROC_Links)
127 : {
128 0 : bool linkEnabled = ((rocMask >> (link * 4)) & 0x1) != 0;
129 0 : if (!linkEnabled)
130 : {
131 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Disabling Link " << (int)link;
132 0 : DisableLink(link);
133 :
134 0 : DisableROCEmulator(link);
135 0 : SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
136 : }
137 : else
138 : {
139 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Enabling Link " << (int)link;
140 0 : EnableLink(link, DTC_LinkEnableMode(true, true));
141 : }
142 : }
143 :
144 0 : if (simMode_ != DTC_SimMode_Disabled)
145 : {
146 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation modes in Hardware...";
147 : // Set up hardware simulation mode: Link 0 Tx/Rx Enabled, Loopback Enabled, ROC Emulator Enabled. All other links
148 : // disabled. for (auto link : DTC_ROC_Links)
149 : // {
150 : // DisableLink(link);
151 : // }
152 : // EnableLink(DTC_Link_0, DTC_LinkEnableMode(true, true, false), DTC_ROC_0);
153 0 : for (auto link : DTC_ROC_Links)
154 : {
155 0 : if (simMode_ == DTC_SimMode_Loopback)
156 : {
157 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of Loopback in Hardware... Link " << (int)link;
158 0 : SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_NearPCS);
159 : // SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
160 : }
161 0 : else if (simMode_ == DTC_SimMode_ROCEmulator)
162 : {
163 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of ROC in Hardware... Link " << (int)link;
164 0 : EnableROCEmulator(link);
165 : // SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
166 : }
167 : else
168 : {
169 0 : TLOG(TLVL_Detail) << __COUT_HDR__ << "Turning off simulation in Hardware... Link " << (int)link;
170 0 : SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
171 0 : DisableROCEmulator(link);
172 : }
173 : }
174 0 : SetCFOEmulationMode();
175 : }
176 : else
177 : {
178 0 : ClearCFOEmulationMode();
179 : }
180 0 : ReadMinDMATransferLength();
181 :
182 0 : __COUT__ << "Done setting device registers";
183 0 : return simMode_;
184 : }
185 :
186 : /// <summary>
187 : /// Read the DDR interface reset bit
188 : /// </summary>
189 : /// <returns>The current value of the DDR interface reset bit</returns>
190 0 : bool DTCLib::DTC_Registers::ReadDDRInterfaceReset(std::optional<uint32_t> val)
191 : {
192 0 : return !std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[1];
193 : }
194 :
195 : /// <summary>
196 : /// Set the Reset bit in the Design Status register
197 : /// </summary>
198 : /// <param name="reset"></param>
199 0 : void DTCLib::DTC_Registers::SetDDRInterfaceReset(bool reset)
200 : {
201 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_DesignStatus);
202 0 : data[1] = !reset;
203 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_DesignStatus);
204 0 : }
205 :
206 : /// <summary>
207 : /// Resets the DDR interface in the firmware
208 : /// </summary>
209 0 : void DTCLib::DTC_Registers::ResetDDRInterface()
210 : {
211 0 : SetDDRInterfaceReset(true);
212 0 : usleep(1000);
213 0 : SetDDRInterfaceReset(false);
214 0 : while (ReadDDRInterfaceReset() && !ReadDDRAutoCalibrationDone())
215 : {
216 0 : usleep(1000);
217 : }
218 0 : }
219 :
220 : /// <summary>
221 : /// Read the DDR Auto Calibration Done bit of the Design status register
222 : /// </summary>
223 : /// <returns>Whether the DDR Auto Calibration is done</returns>
224 0 : bool DTCLib::DTC_Registers::ReadDDRAutoCalibrationDone(std::optional<uint32_t> val)
225 : {
226 0 : return std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[0];
227 : }
228 :
229 : /// <summary>
230 : /// Formats the register's current value for register dumps
231 : /// </summary>
232 : /// <returns>RegisterFormatter object containing register information</returns>
233 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDesignStatus()
234 : {
235 0 : auto form = CreateFormatter(CFOandDTC_Register_DesignStatus);
236 0 : form.description = "Control and Status";
237 0 : form.vals.push_back(std::string("Reset DDR Interface: [") + (ReadDDRInterfaceReset(form.value) ? "x" : " ") + "]");
238 0 : form.vals.push_back(std::string("DDR Auto-Calibration Done: [") + (ReadDDRAutoCalibrationDone(form.value) ? "x" : " ") + "]");
239 0 : return form;
240 0 : }
241 :
242 : /// <summary>
243 : /// Enable the DTC CFO Emulator
244 : /// Parameters for the CFO Emulator, such as count and starting timestamp, must be set before enabling.
245 : /// </summary>
246 0 : void DTCLib::DTC_Registers::EnableCFOEmulation()
247 : {
248 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
249 0 : data[30] = 1;
250 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
251 0 : }
252 :
253 : /// <summary>
254 : /// Disable the DTC CFO Emulator
255 : /// </summary>
256 0 : void DTCLib::DTC_Registers::DisableCFOEmulation()
257 : {
258 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
259 0 : data[30] = 0;
260 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
261 0 : }
262 :
263 : /// <summary>
264 : /// Reads the current state of the DTC CFO Emulator
265 : /// </summary>
266 : /// <returns>True if the emulator is enabled, false otherwise</returns>
267 0 : bool DTCLib::DTC_Registers::ReadCFOEmulationEnabled(std::optional<uint32_t> val)
268 : {
269 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
270 0 : return dataSet[30];
271 : }
272 :
273 : /// <summary>
274 : /// Enable CFO Loopback. CFO packets will be returned to the CFO, for delay calculation.
275 : /// </summary>
276 0 : void DTCLib::DTC_Registers::EnableCFOLoopback()
277 : {
278 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
279 0 : data[28] = 0; // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
280 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
281 0 : }
282 :
283 : /// <summary>
284 : /// Disable CFO Loopback. CFO packets will be transmitted instead to the next DTC (Normal operation)
285 : /// </summary>
286 0 : void DTCLib::DTC_Registers::DisableCFOLoopback()
287 : {
288 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
289 0 : data[28] = 1; // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
290 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
291 0 : }
292 :
293 : /// <summary>
294 : /// Read the value of the CFO Link Loopback bit
295 : /// </summary>
296 : /// <returns>Value of the bit</returns>
297 0 : bool DTCLib::DTC_Registers::ReadCFOLoopback(std::optional<uint32_t> val)
298 : {
299 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
300 0 : return dataSet[28];
301 : }
302 :
303 : /// <summary>
304 : /// Resets the DDR Write pointer to 0
305 : /// </summary>
306 0 : void DTCLib::DTC_Registers::ResetDDRWriteAddress()
307 : {
308 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
309 0 : data[27] = 1;
310 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
311 0 : usleep(1000);
312 0 : data = ReadRegister_(CFOandDTC_Register_Control);
313 0 : data[27] = 0;
314 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
315 0 : }
316 :
317 : /// <summary>
318 : /// Determine whether a DDR Write Pointer reset is in progress
319 : /// </summary>
320 : /// <returns>True if the DDR Write pointer is resetting, false otherwise</returns>
321 0 : bool DTCLib::DTC_Registers::ReadResetDDRWriteAddress(std::optional<uint32_t> val)
322 : {
323 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
324 0 : return data[27];
325 : }
326 :
327 : /// <summary>
328 : /// Reset the DDR Read pointer to 0
329 : /// </summary>
330 0 : void DTCLib::DTC_Registers::ResetDDRReadAddress()
331 : {
332 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
333 0 : data[26] = 1;
334 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
335 0 : usleep(1000);
336 0 : data = ReadRegister_(CFOandDTC_Register_Control);
337 0 : data[26] = 0;
338 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
339 0 : }
340 :
341 : /// <summary>
342 : /// Determine whether the DDR Read pointer is currently being reset.
343 : /// </summary>
344 : /// <returns>True if the read pointer is currently being reset, false otherwise</returns>
345 0 : bool DTCLib::DTC_Registers::ReadResetDDRReadAddress(std::optional<uint32_t> val)
346 : {
347 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
348 0 : return data[26];
349 : }
350 :
351 : /// <summary>
352 : /// Reset the DDR memory interface
353 : /// </summary>
354 0 : void DTCLib::DTC_Registers::ResetDDR()
355 : {
356 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
357 0 : data[25] = 1;
358 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
359 0 : usleep(1000);
360 0 : data = ReadRegister_(CFOandDTC_Register_Control);
361 0 : data[25] = 0;
362 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
363 0 : }
364 :
365 : /// <summary>
366 : /// Determine whether the DDR memory interface is currently being reset
367 : /// </summary>
368 : /// <returns>True if the DDR memory interface is currently being reset, false otherwise</returns>
369 0 : bool DTCLib::DTC_Registers::ReadResetDDR(std::optional<uint32_t> val)
370 : {
371 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
372 0 : return data[25];
373 : }
374 :
375 : /// <summary>
376 : /// Enable sending Data Request packets from the DTC CFO Emulator with every
377 : /// Readout Request
378 : /// </summary>
379 0 : void DTCLib::DTC_Registers::EnableCFOEmulatorDRP()
380 : {
381 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
382 0 : data[24] = 1;
383 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
384 0 : }
385 :
386 : /// <summary>
387 : /// Disable sending Data Request packets from the DTC CFO Emulator with every
388 : /// Readout Request
389 : /// </summary>
390 0 : void DTCLib::DTC_Registers::DisableCFOEmulatorDRP()
391 : {
392 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
393 0 : data[24] = 0;
394 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
395 0 : }
396 :
397 : /// <summary>
398 : /// Read whether the DTC CFO Emulator is sending Data Request packets with every readout request
399 : /// </summary>
400 : /// <returns>True if the DTC CFO Emulator is sending Data Request packets with every readout request, false
401 : /// otherwise</returns>
402 0 : bool DTCLib::DTC_Registers::ReadCFOEmulatorDRP(std::optional<uint32_t> val)
403 : {
404 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
405 0 : return data[24];
406 : }
407 :
408 : /// <summary>
409 : /// Enable automatically generating Data Request packets when heartbeats are received
410 : /// </summary>
411 0 : void DTCLib::DTC_Registers::EnableAutogenDRP()
412 : {
413 0 : TLOG(TLVL_AutogenDRP) << __COUT_HDR__ << "EnableAutogenDRP start";
414 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
415 0 : data[23] = 1;
416 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
417 0 : }
418 :
419 : /// <summary>
420 : /// Disable automatically generating Data Request packets when heartbeats are received
421 : /// </summary>
422 0 : void DTCLib::DTC_Registers::DisableAutogenDRP()
423 : {
424 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
425 0 : data[23] = 0;
426 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
427 0 : }
428 :
429 : /// <summary>
430 : /// Read whether Data Request packets are generated by the DTC when heartbeats are received
431 : /// </summary>
432 : /// <returns>True if Data Request packets are generated by the DTC when heartbeats are received, false otherwise</returns>
433 0 : bool DTCLib::DTC_Registers::ReadAutogenDRP(std::optional<uint32_t> val)
434 : {
435 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
436 0 : return data[23];
437 : }
438 :
439 : /// <summary>
440 : /// Enable receiving Data Request Packets from the DTCLib on DMA Channel 0
441 : /// Possibly obsolete, ask Rick before using
442 : /// </summary>
443 0 : void DTCLib::DTC_Registers::EnableSoftwareDRP()
444 : {
445 0 : DisableAutogenDRP();
446 0 : }
447 :
448 : /// <summary>
449 : /// Disable receiving Data Request Packets from the DTCLib on DMA Channel 0
450 : /// Possibly obsolete, ask Rick before using
451 : /// </summary>
452 0 : void DTCLib::DTC_Registers::DisableSoftwareDRP()
453 : {
454 0 : EnableAutogenDRP();
455 0 : }
456 : // std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
457 : // data[22] = 0;
458 : // WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
459 : // }
460 :
461 : /// <summary>
462 : /// Read whether receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled
463 : /// </summary>
464 : /// <returns>True if receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled, false
465 : /// otherwise</returns>
466 0 : bool DTCLib::DTC_Registers::ReadSoftwareDRP(std::optional<uint32_t> val)
467 : {
468 0 : return !ReadAutogenDRP(val);
469 : }
470 :
471 : /// <summary>
472 : /// Enable kill of ROCs on 10x timeouts
473 : /// </summary>
474 0 : void DTCLib::DTC_Registers::EnableKillTimeoutROCs()
475 : {
476 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
477 0 : data[22] = 1;
478 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
479 0 : }
480 :
481 : /// <summary>
482 : /// Disable kill of ROCs on 10x timeouts
483 : /// </summary>
484 0 : void DTCLib::DTC_Registers::DisableKillTimeoutROCs()
485 : {
486 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
487 0 : data[22] = 0;
488 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
489 0 : }
490 :
491 : /// <summary>
492 : /// Read whether kill of ROCs on 10x timeouts is enabled
493 : /// </summary>
494 : /// <returns>True if kill of ROCs on 10x timeouts is enabled, false otherwise</returns>
495 0 : bool DTCLib::DTC_Registers::ReadKillTimeoutROCs(std::optional<uint32_t> val)
496 : {
497 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
498 0 : return data[22];
499 : }
500 :
501 : /// <summary>
502 : /// Reset the PCIe interface
503 : /// </summary>
504 0 : void DTCLib::DTC_Registers::ResetPCIe()
505 : {
506 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
507 0 : data[21] = 1;
508 0 : data[20] = 1;
509 0 : data[11] = 1;
510 0 : data[7] = 1;
511 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
512 0 : usleep(1000);
513 0 : data = ReadRegister_(CFOandDTC_Register_Control);
514 0 : data[21] = 0;
515 0 : data[20] = 0;
516 0 : data[11] = 0;
517 0 : data[7] = 0;
518 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
519 :
520 : // Note the DTC instance likely needs to be reinitialized on a firmware-DMA reset to realign pointers:
521 : // e.g. device_.initDMAEngine();
522 0 : }
523 :
524 : /// <summary>
525 : /// Determine whether the PCIe interface is currently being reset
526 : /// </summary>
527 : /// <returns>True if the PCIe interface is currently being reset, false otherwise</returns>
528 0 : bool DTCLib::DTC_Registers::ReadResetPCIe(std::optional<uint32_t> val)
529 : {
530 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
531 0 : return data[21];
532 : }
533 :
534 : /// <summary>
535 : /// Enable the All LED bits in Control register
536 : /// </summary>
537 0 : void DTCLib::DTC_Registers::EnableLEDs()
538 : {
539 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
540 0 : data[16] = 1;
541 0 : data[17] = 1;
542 0 : data[18] = 1;
543 0 : data[19] = 1;
544 0 : data[20] = 1;
545 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
546 0 : }
547 :
548 : /// <summary>
549 : /// Disable the All LED bits in Control register
550 : /// </summary>
551 0 : void DTCLib::DTC_Registers::DisableLEDs()
552 : {
553 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
554 0 : data[16] = 0;
555 0 : data[17] = 0;
556 0 : data[18] = 0;
557 0 : data[19] = 0;
558 0 : data[20] = 0;
559 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
560 0 : }
561 :
562 : /// <summary>
563 : /// Enable the All LED bits in Control register
564 : /// </summary>
565 0 : void DTCLib::DTC_Registers::FlashLEDs()
566 : {
567 0 : DisableLEDs();
568 0 : sleep(1);
569 0 : EnableLEDs();
570 0 : sleep(1);
571 0 : DisableLEDs();
572 0 : }
573 :
574 : /// <summary>
575 : /// Enable the Down LED0 Control register bit
576 : /// </summary>
577 0 : void DTCLib::DTC_Registers::EnableDownLED0()
578 : {
579 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
580 0 : data[19] = 1;
581 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
582 0 : }
583 :
584 : /// <summary>
585 : /// Disable the Down LED0 Control register bit
586 : /// </summary>
587 0 : void DTCLib::DTC_Registers::DisableDownLED0()
588 : {
589 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
590 0 : data[19] = 0;
591 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
592 0 : }
593 :
594 : /// <summary>
595 : /// Read the state of the Down LED0 Control register bit
596 : /// </summary>
597 : /// <returns>Whether the Down LED0 bit is set</returns>
598 0 : bool DTCLib::DTC_Registers::ReadDownLED0State(std::optional<uint32_t> val)
599 : {
600 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
601 0 : return data[19];
602 : }
603 : /// <summary>
604 : /// Enable the Up LED1 Control register bit
605 : /// </summary>
606 0 : void DTCLib::DTC_Registers::EnableUpLED1()
607 : {
608 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
609 0 : data[18] = 1;
610 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
611 0 : }
612 :
613 : /// <summary>
614 : /// Disable the Up LED1 Control register bit
615 : /// </summary>
616 0 : void DTCLib::DTC_Registers::DisableUpLED1()
617 : {
618 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
619 0 : data[18] = 0;
620 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
621 0 : }
622 :
623 : /// <summary>
624 : /// Read the state of the Up LED1 Control register bit
625 : /// </summary>
626 : /// <returns>Whether the Up LED1 bit is set</returns>
627 0 : bool DTCLib::DTC_Registers::ReadUpLED1State(std::optional<uint32_t> val)
628 : {
629 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
630 0 : return data[18];
631 : }
632 : /// <summary>
633 : /// Enable the Up LED0 Control register bit
634 : /// </summary>
635 0 : void DTCLib::DTC_Registers::EnableUpLED0()
636 : {
637 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
638 0 : data[17] = 1;
639 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
640 0 : }
641 :
642 : /// <summary>
643 : /// Disable the Up LED0 Control register bit
644 : /// </summary>
645 0 : void DTCLib::DTC_Registers::DisableUpLED0()
646 : {
647 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
648 0 : data[17] = 0;
649 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
650 0 : }
651 :
652 : /// <summary>
653 : /// Read the state of the Up LED0 Control register bit
654 : /// </summary>
655 : /// <returns>Whether the Up LED0 bit is set</returns>
656 0 : bool DTCLib::DTC_Registers::ReadUpLED0State(std::optional<uint32_t> val)
657 : {
658 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
659 0 : return data[17];
660 : }
661 :
662 : /// <summary>
663 : /// Enable the LED6 Control register bit
664 : /// </summary>
665 0 : void DTCLib::DTC_Registers::EnableLED6()
666 : {
667 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
668 0 : data[16] = 1;
669 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
670 0 : }
671 :
672 : /// <summary>
673 : /// Disable the LED6 Control register bit
674 : /// </summary>
675 0 : void DTCLib::DTC_Registers::DisableLED6()
676 : {
677 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
678 0 : data[16] = 0;
679 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
680 0 : }
681 :
682 : /// <summary>
683 : /// Read the state of the LED6 Control register bit
684 : /// </summary>
685 : /// <returns>Whether the LED6 bit is set</returns>
686 0 : bool DTCLib::DTC_Registers::ReadLED6State(std::optional<uint32_t> val)
687 : {
688 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
689 0 : return data[16];
690 : }
691 :
692 : /// <summary>
693 : /// Enable CFO Emulation mode.
694 : /// </summary>
695 0 : void DTCLib::DTC_Registers::SetCFOEmulationMode()
696 : {
697 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
698 0 : data[15] = 1;
699 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
700 0 : }
701 :
702 : /// <summary>
703 : /// Disable CFO Emulation mode.
704 : /// </summary>
705 0 : void DTCLib::DTC_Registers::ClearCFOEmulationMode()
706 : {
707 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
708 0 : data[15] = 0;
709 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
710 0 : }
711 :
712 : /// <summary>
713 : /// Read the state of the CFO Emulation Mode bit
714 : /// </summary>
715 : /// <returns>Whether CFO Emulation Mode is enabled</returns>
716 0 : bool DTCLib::DTC_Registers::ReadCFOEmulationMode(std::optional<uint32_t> val)
717 : {
718 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
719 0 : return data[15];
720 : }
721 :
722 0 : void DTCLib::DTC_Registers::SetDataFilterEnable()
723 : {
724 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
725 0 : data[13] = 1;
726 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
727 0 : }
728 :
729 0 : void DTCLib::DTC_Registers::ClearDataFilterEnable()
730 : {
731 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
732 0 : data[13] = 0;
733 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
734 0 : }
735 :
736 0 : bool DTCLib::DTC_Registers::ReadDataFilterEnable(std::optional<uint32_t> val)
737 : {
738 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
739 0 : return data[13];
740 : }
741 :
742 0 : void DTCLib::DTC_Registers::SetDRPPrefetchEnable()
743 : {
744 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
745 0 : data[12] = 1;
746 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
747 0 : }
748 :
749 0 : void DTCLib::DTC_Registers::ClearDRPPrefetchEnable()
750 : {
751 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
752 0 : data[12] = 0;
753 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
754 0 : }
755 :
756 0 : bool DTCLib::DTC_Registers::ReadDRPPrefetchEnable(std::optional<uint32_t> val)
757 : {
758 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
759 0 : return data[12];
760 : }
761 :
762 0 : void DTCLib::DTC_Registers::ROCInterfaceSoftReset()
763 : {
764 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
765 0 : data[12] = 1;
766 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
767 0 : usleep(100000);
768 0 : data[12] = 0;
769 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
770 0 : }
771 :
772 0 : bool DTCLib::DTC_Registers::ReadROCInterfaceSoftReset(std::optional<uint32_t> val)
773 : {
774 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
775 0 : return data[11];
776 : }
777 :
778 0 : void DTCLib::DTC_Registers::EnableDropDataToEmulateEventBuilding()
779 : {
780 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
781 0 : data[10] = 1;
782 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
783 0 : }
784 :
785 0 : void DTCLib::DTC_Registers::DisableDropDataToEmulateEventBuilding()
786 : {
787 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
788 0 : data[10] = 0;
789 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
790 0 : }
791 :
792 0 : bool DTCLib::DTC_Registers::ReadDropDataToEmulateEventBuilding(std::optional<uint32_t> val)
793 : {
794 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
795 0 : return data[10];
796 : }
797 :
798 : /// This offset should be set 'permanently' for the DTC in response to
799 : /// the sample measurement at bits [18:16] of DTC_Register_CFOLinkErrorFlags
800 0 : void DTCLib::DTC_Registers::SetCFOSamplePermanentOffset(int permanentOffset)
801 : {
802 : // do not write more bits because high bits, in older versions were the error clear latch... ReadRegister_(DTC_Register_CFOLinkErrorFlags);
803 : // set only 3-bits [2:0]
804 0 : WriteRegister_(permanentOffset & 7, DTC_Register_CFOLinkErrorFlags);
805 0 : } // end SetCFOSamplePermanentOffset()
806 :
807 0 : int DTCLib::DTC_Registers::ReadCFOSamplePermanentOffset(std::optional<uint32_t> val)
808 : {
809 0 : uint32_t setting = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
810 0 : setting &= 7;
811 0 : if (setting > 3)
812 0 : setting = -8 + setting;
813 0 : return setting; // return 3-bit value handling of [-2,2]
814 : } // end ReadCFOSamplePermanentOffset()
815 :
816 : /// @brief Set edge selection of RTF clock and external CFO rx -> tx data
817 : /// @param forceCFOedge is a 2-bit value
818 0 : void DTCLib::DTC_Registers::SetExternalCFOSampleEdgeMode(int forceCFOedge)
819 : {
820 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
821 :
822 0 : data[6] = ((forceCFOedge >> 1) & 1) ? 0 : 1; // invert bit[1], DTC control bit [6] := 1 for forced, 0 for auto
823 0 : data[5] = (forceCFOedge & 1); // DTC control bit [5] := 1 for falling-edge, 0 for rising-edge
824 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
825 0 : } // end SetExternalCFOSampleEdgeMode()
826 :
827 0 : int DTCLib::DTC_Registers::ReadExternalCFOSampleEdgeMode(std::optional<uint32_t> val)
828 : {
829 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
830 0 : return (data[6] << 1) | data[5];
831 : } // end ReadExternalCFOSampleEdgeMode()
832 :
833 0 : void DTCLib::DTC_Registers::SetExternalFanoutClockInput()
834 : {
835 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
836 0 : data[4] = 1;
837 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
838 0 : }
839 :
840 0 : void DTCLib::DTC_Registers::SetInternalFanoutClockInput()
841 : {
842 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
843 0 : data[4] = 0;
844 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
845 0 : }
846 :
847 0 : bool DTCLib::DTC_Registers::ReadFanoutClockInput(std::optional<uint32_t> val)
848 : {
849 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
850 0 : return data[4];
851 : }
852 :
853 : /// <summary>
854 : /// Enable receiving DCS packets.
855 : /// </summary>
856 0 : void DTCLib::DTC_Registers::EnableDCSReception()
857 : {
858 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
859 0 : data[2] = 1;
860 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
861 0 : }
862 : /// <summary>
863 : /// Disable receiving DCS packets. Any DCS packets received will be ignored
864 : /// </summary>
865 0 : void DTCLib::DTC_Registers::DisableDCSReception()
866 : {
867 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
868 0 : data[2] = 0;
869 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
870 0 : }
871 : /// <summary>
872 : /// Read the status of the DCS Enable bit
873 : /// </summary>
874 : /// <returns>Whether DCS packet reception is enabled</returns>
875 0 : bool DTCLib::DTC_Registers::ReadDCSReception(std::optional<uint32_t> val)
876 : {
877 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
878 0 : return data[2];
879 : }
880 :
881 : /// <summary>
882 : /// Formats the register's current value for register dumps
883 : /// </summary>
884 : /// <returns>RegisterFormatter object containing register information</returns>
885 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDTCControl()
886 : {
887 0 : auto form = CreateFormatter(CFOandDTC_Register_Control);
888 0 : form.description = "DTC Control";
889 0 : form.vals.push_back("([ x = 1 (hi) ])");
890 :
891 : // ~~~ DTC Control Register (0x9100) ~~~
892 : // Bit Position Mode Default Value Description
893 : // 31 WO 0b0 DTC Soft Reset (Self-clearing)
894 : // 30 RW 0b0 CFO Emulation Enable
895 : // 29 RW 0b0 Reserved (Formerly CFO Emulation Enable Continuous)
896 : // 28 RW 0b0 CFO Link Output Control
897 : // 27 RW 0b0 Reset DDR Write Address
898 : // 26 RW 0b0 Reserved (Formerly Reset DDR Read Address)
899 : // 25 RW 0b0 Reserved (DDR Interface Reset)
900 : // 24 RW 0b0 CFO Emulator DRP Enable
901 : // 23 RW 0b0 DTC Autogenerate DRP Enable
902 : // 22 RW 0b0 Reserved (Formerly Software DRP Enable)
903 : // 21 RW 0b0 Reserved (Formerly local EVB Source Buffer Reset)
904 : // 20 RW 0b0 Reserved (Formerly EVB DMA Buffer Reset)
905 : // 19 RW 0b0 Down LED 0
906 : // 18 RW 0b0 Up LED 1
907 : // 17 RW 0b0 Up LED 0
908 : // 16 RW 0b0 LED 7
909 : // 15 RW 0b0 CFO Emulation Mode
910 : // 14 RW 0b0 Reserved (Formerly EVB Debug Count Enable)
911 : // 13 RW 0b0 Reserved (Formerly Trigger Filter Enable)
912 : // 12 RW 0b0 DRP Prefetch Enable
913 : // 11 RW 0b0 Reserved (Formerly EVM Buffer Reset)
914 : // 10 RW 0b0 Drop Subevent Data to Emulate Hardware Event Building Reserved (Formerly Sequence Number Disable)
915 : // 9 RW 0b0 Punch Enable on RJ-45 Output
916 : // 8 RW 0b0 SERDES Global Reset
917 : // 7 RW 0b0 Reserved (Formerly Global Buffer Reset)
918 : // 6 RW 0b0 Do Force External CFO Sample Edge (Formerly RX Packet Error Feedback Enable)
919 : // 5 RW 0b0 Force External CFO Sample Edge Select (Formerly Comma Tolerance Enable)
920 : // 4 RW 0b0 Fanout Clock Input Select
921 : // 3 RW 0b0 CFO Emulator Loopback Test Launch Control
922 : // 2 RW 0b0 DCS Enable
923 : // 1 RW 0b0 Reserved (Formerly SERDES Comma Align)
924 : // 0 WO 0b0 DTC Hard Reset (Self-clearing)
925 :
926 0 : form.vals.push_back(std::string("Bit-31 DTC Soft Reset (Self-clearing): [") + (ReadSoftReset(form.value) ? "x" : " ") + "]");
927 0 : form.vals.push_back(std::string("Bit-30 CFO Emulation Enable: [") + (ReadCFOEmulationEnabled(form.value) ? "x" : " ") + "]");
928 0 : form.vals.push_back(std::string("Bit-28 CFO Link Timing Card not-in-Loopback: [") + (ReadCFOLoopback(form.value) ? "x" : " ") + "]");
929 : // form.vals.push_back(std::string("Bit-27 Reset DDR Write Address: [") + (ReadResetDDRWriteAddress(form.value) ? "x" : " ") + "]");
930 : // form.vals.push_back(std::string("Bit-26 Reset DDR Read Address: [") + (ReadResetDDRReadAddress(form.value) ? "x" : " ") + "]");
931 : // form.vals.push_back(std::string("Bit-25 Reset DDR Interface: [") + (ReadResetDDR(form.value) ? "x" : " ") + "]");
932 : // form.vals.push_back(std::string("Bit-24 CFO Emulator DRP Enable: [") + (ReadCFOEmulatorDRP(form.value) ? "x" : " ") + "]");
933 0 : form.vals.push_back(std::string("Bit-23 DTC Autogenerate DRP: [") + (ReadAutogenDRP(form.value) ? "x" : " ") + "]");
934 : // Bit-22 is currently defined as "Kill ROCs on 10x Timeouts" (legacy Software DRP meaning no longer applies).
935 0 : form.vals.push_back(std::string("Bit-22 Kill ROCs on 10x Timeouts: [") + (ReadKillTimeoutROCs(form.value) ? "x" : " ") + "]");
936 0 : form.vals.push_back(std::string("Bit-19 Down LED 0: [") + (ReadDownLED0State(form.value) ? "x" : " ") + "]");
937 0 : form.vals.push_back(std::string("Bit-18 Up LED 1: [") + (ReadUpLED1State(form.value) ? "x" : " ") + "]");
938 0 : form.vals.push_back(std::string("Bit-17 Up LED 0: [") + (ReadUpLED0State(form.value) ? "x" : " ") + "]");
939 0 : form.vals.push_back(std::string("Bit-16 LED 6: [") + (ReadLED6State(form.value) ? "x" : " ") + "]");
940 0 : form.vals.push_back(std::string("Bit-15 CFO Emulation Mode: [") + (ReadCFOEmulationMode(form.value) ? "x" : " ") + "]");
941 : // form.vals.push_back(std::string("Bit-31 Data Filter Enable: [") + (ReadDataFilterEnable(form.value) ? "x" : " ") + "]");
942 0 : form.vals.push_back(std::string("Bit-12 DRP Prefetch Enable: [") + (ReadDRPPrefetchEnable(form.value) ? "x" : " ") + "]");
943 0 : form.vals.push_back(std::string("Bit-10 Skip-by-32 Subevent Readout Enable: [") + (ReadDropDataToEmulateEventBuilding(form.value) ? "x" : " ") + "]");
944 : // form.vals.push_back(std::string("Bit-31 ROC Interface Soft Reset: [") + (ReadROCInterfaceSoftReset(form.value) ? "x" : " ") + "]");
945 : // form.vals.push_back(std::string("Bit-31 Sequence Number Disable: [") + (ReadSequenceNumberDisable(form.value) ? "x" : " ") + "]");
946 : // form.vals.push_back(std::string("Bit-31 Punch Enable: [") + (ReadPunchEnable(form.value) ? "x" : " ") + "]");
947 :
948 0 : form.vals.push_back(std::string("Bit-09 Punched Clock Enable: [") + (CFOandDTC_Registers::ReadPunchEnable(form.value) ? "x" : " ") + "]");
949 0 : form.vals.push_back(std::string("Bit-08 SERDES Global Reset: [") + (CFOandDTC_Registers::ReadResetSERDES(form.value) ? "x" : " ") + "]");
950 :
951 0 : form.vals.push_back(std::string("Bit-06 Enable CFO-RTF Offset Control: [") + (((ReadExternalCFOSampleEdgeMode(form.value) >> 1) & 1) ? "x" : " ") + "]");
952 0 : form.vals.push_back(std::string("Bit-05 CFO-RTF Edge Select: [") + ((ReadExternalCFOSampleEdgeMode(form.value) & 1) ? "x" : " ") + "]");
953 :
954 : // form.vals.push_back(std::string("Bit-31 RX Packet Error Feedback Enable: [") + (ReadRxPacketErrorFeedbackEnable(form.value) ? "x" : " ") + "]");
955 : // form.vals.push_back(std::string("Bit-31 Comma Tolerance Enable: [") + (ReadCommaToleranceEnable(form.value) ? "x" : " ") + "]");
956 0 : form.vals.push_back(std::string("Bit-04 Fanout Clock Input Select: [") + (ReadFanoutClockInput(form.value) ? "FMC SFP Rx" : "FPGA") + "]");
957 0 : form.vals.push_back(std::string("Bit-02 DCS Enable: [") + (ReadDCSReception(form.value) ? "x" : " ") + "]");
958 0 : form.vals.push_back(std::string("Bit-00 DTC Hard Reset (Self-clearing): [") + (ReadHardReset(form.value) ? "x" : " ") + "]");
959 0 : return form;
960 0 : }
961 :
962 : // DMA Transfer Length Register
963 : /// <summary>
964 : /// Set the DMA buffer size which will automatically trigger a DMA
965 : /// </summary>
966 : /// <param name="length">Size, in bytes of buffer that will trigger a DMA</param>
967 0 : void DTCLib::DTC_Registers::SetTriggerDMATransferLength(uint16_t length)
968 : {
969 0 : auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
970 0 : data = (data & 0x0000FFFF) + (length << 16);
971 0 : WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
972 0 : }
973 :
974 : /// <summary>
975 : /// Read the DMA buffer size which will automatically trigger a DMA
976 : /// </summary>
977 : /// <returns>The DMA buffer size which will automatically trigger a DMA, in bytes</returns>
978 0 : uint16_t DTCLib::DTC_Registers::ReadTriggerDMATransferLength(std::optional<uint32_t> val)
979 : {
980 0 : auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
981 0 : data >>= 16;
982 0 : return static_cast<uint16_t>(data);
983 : }
984 :
985 : /// <summary>
986 : /// Set the minimum DMA transfer size. Absolute minimum is 64 bytes.
987 : /// Buffers smaller than this size will be padded to the minimum.
988 : /// </summary>
989 : /// <param name="length">Size, in bytes, of the minimum DMA transfer buffer</param>
990 0 : void DTCLib::DTC_Registers::SetMinDMATransferLength(uint16_t length)
991 : {
992 0 : auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
993 0 : data = (data & 0xFFFF0000) + length;
994 0 : WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
995 0 : }
996 :
997 : /// <summary>
998 : /// Read the minimum DMA transfer size.
999 : /// </summary>
1000 : /// <returns>The minimum DMA size, in bytes</returns>
1001 0 : uint16_t DTCLib::DTC_Registers::ReadMinDMATransferLength(std::optional<uint32_t> val)
1002 : {
1003 0 : auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
1004 0 : data = data & 0x0000FFFF;
1005 0 : dmaSize_ = static_cast<uint16_t>(data);
1006 0 : return dmaSize_;
1007 : }
1008 :
1009 : /// <summary>
1010 : /// Formats the register's current value for register dumps
1011 : /// </summary>
1012 : /// <returns>RegisterFormatter object containing register information</returns>
1013 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATransferLength()
1014 : {
1015 0 : auto form = CreateFormatter(CFOandDTC_Register_DMATransferLength);
1016 0 : form.description = "DMA Transfer Length";
1017 0 : std::stringstream o;
1018 0 : o << "Trigger Length: 0x" << std::hex << ReadTriggerDMATransferLength(form.value);
1019 0 : form.vals.push_back(o.str());
1020 0 : std::stringstream p;
1021 0 : p << "Minimum Length: 0x" << std::hex << ReadMinDMATransferLength(form.value);
1022 0 : form.vals.push_back(p.str());
1023 0 : return form;
1024 0 : }
1025 :
1026 : // SERDES Loopback Enable Register
1027 : /// <summary>
1028 : /// Set the SERDES Loopback mode for the given link
1029 : /// </summary>
1030 : /// <param name="link">Link to set for</param>
1031 : /// <param name="mode">DTC_SERDESLoopbackMode to set</param>
1032 0 : void DTCLib::DTC_Registers::SetSERDESLoopbackMode(DTC_Link_ID const& link, const DTC_SERDESLoopbackMode& mode)
1033 : {
1034 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable);
1035 0 : std::bitset<3> modeSet = mode;
1036 0 : data[3 * link] = modeSet[0];
1037 0 : data[3 * link + 1] = modeSet[1];
1038 0 : data[3 * link + 2] = modeSet[2];
1039 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_LoopbackEnable);
1040 0 : }
1041 :
1042 : /// <summary>
1043 : /// Read the SERDES Loopback mode for the given link
1044 : /// </summary>
1045 : /// <param name="link">Link to read</param>
1046 : /// <returns>DTC_SERDESLoopbackMode of the link</returns>
1047 0 : DTCLib::DTC_SERDESLoopbackMode DTCLib::DTC_Registers::ReadSERDESLoopback(DTC_Link_ID const& link, std::optional<uint32_t> val)
1048 : {
1049 0 : std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable)) >> 3 * link;
1050 0 : return static_cast<DTC_SERDESLoopbackMode>(dataSet.to_ulong());
1051 : }
1052 :
1053 : /// <summary>
1054 : /// Formats the register's current value for register dumps
1055 : /// </summary>
1056 : /// <returns>RegisterFormatter object containing register information</returns>
1057 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESLoopbackEnable()
1058 : {
1059 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
1060 0 : form.description = "SERDES Loopback Enable";
1061 0 : form.vals.push_back(""); // translation
1062 0 : for (auto r : DTC_ROC_Links)
1063 : {
1064 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " +
1065 0 : DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(r, form.value)).toString());
1066 : }
1067 0 : form.vals.push_back(std::string("CFO: ") +
1068 0 : DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_CFO, form.value)).toString());
1069 0 : form.vals.push_back(std::string("EVB: ") +
1070 0 : DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_EVB, form.value)).toString());
1071 0 : return form;
1072 0 : }
1073 :
1074 : // Clock Status Register
1075 : /// <summary>
1076 : /// Read the SERDES Oscillator IIC Error Bit
1077 : /// </summary>
1078 : /// <returns>True if the SERDES Oscillator IIC Error is set</returns>
1079 0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICError(std::optional<uint32_t> val)
1080 : {
1081 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
1082 0 : return dataSet[2];
1083 : }
1084 :
1085 : /// <summary>
1086 : /// Read the DDR Oscillator IIC Error Bit
1087 : /// </summary>
1088 : /// <returns>True if the DDR Oscillator IIC Error is set</returns>
1089 0 : bool DTCLib::DTC_Registers::ReadDDROscillatorIICError(std::optional<uint32_t> val)
1090 : {
1091 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
1092 0 : return dataSet[18];
1093 : }
1094 :
1095 : /// <summary>
1096 : /// Formats the register's current value for register dumps
1097 : /// </summary>
1098 : /// <returns>RegisterFormatter object containing register information</returns>
1099 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatClockOscillatorStatus()
1100 : {
1101 0 : auto form = CreateFormatter(CFOandDTC_Register_ClockOscillatorStatus);
1102 0 : form.description = "Clock Oscillator Status";
1103 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
1104 0 : form.vals.push_back(std::string("SERDES IIC Error: [") + (ReadSERDESOscillatorIICError(form.value) ? "x" : " ") + "]");
1105 0 : form.vals.push_back(std::string("DDR IIC Error: [") + (ReadDDROscillatorIICError(form.value) ? "x" : " ") + "]");
1106 0 : return form;
1107 0 : }
1108 :
1109 : // ROC Emulation Enable Register
1110 : /// <summary>
1111 : /// Enable the ROC emulator on the given link
1112 : /// </summary>
1113 : /// <param name="link">Link to enable</param>
1114 0 : void DTCLib::DTC_Registers::EnableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
1115 : {
1116 0 : std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
1117 0 : if (link == DTC_Link_ALL)
1118 0 : for (const auto& l : DTC_ROC_Links)
1119 0 : dataSet[l + type * 6] = 1;
1120 : else
1121 0 : dataSet[link + type * 6] = 1;
1122 :
1123 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
1124 0 : }
1125 :
1126 : /// <summary>
1127 : /// Disable the ROC emulator on the given link
1128 : /// </summary>
1129 : /// <param name="link">Link to disable</param>
1130 0 : void DTCLib::DTC_Registers::DisableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
1131 : {
1132 0 : std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
1133 0 : if (link == DTC_Link_ALL)
1134 0 : for (const auto& l : DTC_ROC_Links)
1135 0 : dataSet[l + type * 6] = 0;
1136 : else
1137 0 : dataSet[link + type * 6] = 0;
1138 :
1139 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
1140 0 : }
1141 :
1142 : /// <summary>
1143 : /// Read the state of the ROC emulator on the given link
1144 : /// </summary>
1145 : /// <param name="link">Link to read</param>
1146 : /// <returns>True if the ROC Emulator is enabled on the link</returns>
1147 0 : bool DTCLib::DTC_Registers::ReadROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type, std::optional<uint32_t> val)
1148 : {
1149 0 : if (std::find(DTC_ROC_Links.begin(), DTC_ROC_Links.end(), link) == DTC_ROC_Links.end())
1150 : {
1151 0 : __SS__ << "Illegal link specified for ROC Emulator target: " << link << __E__;
1152 0 : __SS_THROW__;
1153 0 : }
1154 :
1155 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
1156 0 : return dataSet[link + type * 6];
1157 : }
1158 0 : void DTCLib::DTC_Registers::SetROCEmulatorMask(uint32_t rocEnableMask)
1159 : {
1160 0 : WriteRegister_(rocEnableMask, DTC_Register_ROCEmulationEnable);
1161 0 : }
1162 0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorMask(std::optional<uint32_t> val)
1163 : {
1164 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
1165 : }
1166 :
1167 : /// <summary>
1168 : /// Formats the register's current value for register dumps
1169 : /// </summary>
1170 : /// <returns>RegisterFormatter object containing register information</returns>
1171 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationEnable()
1172 : {
1173 0 : auto form = CreateFormatter(DTC_Register_ROCEmulationEnable);
1174 0 : form.description = "ROC Emulator Enable";
1175 0 : form.vals.push_back(" ([ Internal, Fiber-Loopback, External ])"); // translation
1176 0 : for (auto r : DTC_ROC_Links)
1177 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) +
1178 0 : ": [" + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_Internal_Emulation, form.value) ? "x" : ".") + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_FiberLoopback_Emulation, form.value) ? "x" : ".") + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_External_Emulation, form.value) ? "x" : ".") + "]");
1179 :
1180 0 : return form;
1181 0 : }
1182 :
1183 : // Link Enable Register
1184 : /// <summary>
1185 : /// Enable Receive CFO Link
1186 : /// </summary>
1187 0 : void DTCLib::DTC_Registers::EnableReceiveCFOLink()
1188 : {
1189 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1190 0 : data[14] = 1;
1191 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1192 0 : }
1193 : /// <summary>
1194 : /// Disable Receive CFO Link
1195 : /// </summary>
1196 0 : void DTCLib::DTC_Registers::DisableReceiveCFOLink()
1197 : {
1198 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1199 0 : data[14] = 0;
1200 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1201 0 : }
1202 : /// <summary>
1203 : /// Enable Receive CFO Link
1204 : /// </summary>
1205 0 : void DTCLib::DTC_Registers::EnableTransmitCFOLink()
1206 : {
1207 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1208 0 : data[6] = 1;
1209 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1210 0 : }
1211 : /// <summary>
1212 : /// Disable Receive CFO Link
1213 : /// </summary>
1214 0 : void DTCLib::DTC_Registers::DisableTransmitCFOLink()
1215 : {
1216 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1217 0 : data[6] = 0;
1218 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1219 0 : }
1220 : /// <summary>
1221 : /// Enable a SERDES Link based on the mode tx/rx enable bits (default is enabled)
1222 : /// </summary>
1223 : /// <param name="link">Link to enable</param>
1224 : /// <param name="mode">Link enable bits to set (Default: All)</param>
1225 0 : void DTCLib::DTC_Registers::EnableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
1226 : {
1227 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1228 0 : data[link] = mode.TransmitEnable;
1229 0 : data[link + 8] = mode.ReceiveEnable;
1230 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1231 0 : }
1232 :
1233 : /// <summary>
1234 : /// Disable a SERDES Link
1235 : /// The given mode bits will be UNSET
1236 : /// </summary>
1237 : /// <param name="link">Link to disable</param>
1238 : /// <param name="mode">Link enable bits to unset (Default: All)</param>
1239 0 : void DTCLib::DTC_Registers::DisableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
1240 : {
1241 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1242 0 : data[link] = data[link] && !mode.TransmitEnable;
1243 0 : data[link + 8] = data[link + 8] && !mode.ReceiveEnable;
1244 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1245 0 : }
1246 :
1247 : /// <summary>
1248 : /// Read the Link Enable bits for a given SERDES link
1249 : /// </summary>
1250 : /// <param name="link">Link to read</param>
1251 : /// <returns>DTC_LinkEnableMode containing TX, RX, and CFO bits</returns>
1252 0 : DTCLib::DTC_LinkEnableMode DTCLib::DTC_Registers::ReadLinkEnabled(DTC_Link_ID const& link, std::optional<uint32_t> val)
1253 : {
1254 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
1255 0 : return DTC_LinkEnableMode(dataSet[link], dataSet[link + 8]);
1256 : }
1257 0 : uint32_t DTCLib::DTC_Registers::ReadLinkEnabledData()
1258 : {
1259 0 : return ReadRegister_(CFOandDTC_Register_LinkEnable);
1260 : }
1261 :
1262 0 : bool DTCLib::DTC_Registers::ReadBlockNullHeartbeatsToROC(std::optional<uint32_t> val)
1263 : {
1264 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
1265 0 : return dataSet[24];
1266 : }
1267 0 : void DTCLib::DTC_Registers::SetBlockNullHeartbeatsToROC(bool enable)
1268 : {
1269 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1270 0 : data[24] = enable;
1271 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1272 0 : }
1273 :
1274 0 : bool DTCLib::DTC_Registers::ReadResequenceNonNullEvents(std::optional<uint32_t> val)
1275 : {
1276 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
1277 0 : return dataSet[25];
1278 : }
1279 0 : void DTCLib::DTC_Registers::SetResequenceNonNullEvents(bool enable)
1280 : {
1281 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1282 0 : data[25] = enable;
1283 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1284 0 : }
1285 :
1286 0 : bool DTCLib::DTC_Registers::ReadAutoGenDRPPerLink(DTC_Link_ID const& link, std::optional<uint32_t> val)
1287 : {
1288 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
1289 0 : return dataSet[link + 16];
1290 : }
1291 0 : void DTCLib::DTC_Registers::SetAutoGenDRPPerLink(DTC_Link_ID const& link, bool enable)
1292 : {
1293 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
1294 0 : data[link + 16] = enable;
1295 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
1296 0 : }
1297 :
1298 : /// <summary>
1299 : /// Formats the register's current value for register dumps
1300 : /// </summary>
1301 : /// <returns>RegisterFormatter object containing register information</returns>
1302 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkEnable()
1303 : {
1304 0 : auto form = CreateFormatter(CFOandDTC_Register_LinkEnable);
1305 0 : form.description = "Link Enable";
1306 0 : form.vals.push_back(" ([TX, RX])");
1307 0 : for (auto r : DTC_ROC_Links)
1308 : {
1309 0 : auto re = ReadLinkEnabled(r, form.value);
1310 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.TransmitEnable ? "x" : ".") + "" +
1311 0 : (re.ReceiveEnable ? "x" : ".") + "]");
1312 : }
1313 : {
1314 0 : auto ce = ReadLinkEnabled(DTC_Link_CFO, form.value);
1315 0 : form.vals.push_back(std::string("CFO: [") + (ce.TransmitEnable ? "x" : ".") + "" +
1316 0 : (ce.ReceiveEnable ? "x" : ".") + "]");
1317 : }
1318 : {
1319 0 : auto ee = ReadLinkEnabled(DTC_Link_EVB, form.value);
1320 0 : form.vals.push_back(std::string("EVB: [") + (ee.TransmitEnable ? "x" : ".") + "" +
1321 0 : (ee.ReceiveEnable ? "x" : ".") + "]");
1322 : }
1323 0 : form.vals.push_back(std::string("Block Null Heartbeats to ALL ROCs: [") +
1324 0 : (ReadBlockNullHeartbeatsToROC(form.value) ? "x" : ".") + "]");
1325 0 : form.vals.push_back(std::string("Resequence Non-null Events for ALL ROCs: [") +
1326 0 : (ReadResequenceNonNullEvents(form.value) ? "x" : ".") + "]");
1327 0 : for (auto r : DTC_ROC_Links)
1328 : {
1329 0 : form.vals.push_back(std::string("Auto-Gen DRP Link ") + std::to_string(r) + ": [" +
1330 0 : (ReadAutoGenDRPPerLink(r, form.value) ? "x" : ".") + "]");
1331 : }
1332 0 : return form;
1333 0 : }
1334 :
1335 : // SERDES Reset Register
1336 : /// <summary>
1337 : /// Reset the SERDES TX side
1338 : /// Will poll the Reset SERDES TX Done flag until the SERDES reset is complete
1339 : /// </summary>
1340 : /// <param name="link">Link to reset</param>
1341 : /// <param name="interval">Polling interval, in microseconds</param>
1342 0 : void DTCLib::DTC_Registers::ResetSERDESTX(DTC_Link_ID const& link, int interval)
1343 : {
1344 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES TX Reset Loop for Link " << link;
1345 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1346 0 : if (link == DTC_Link_ALL)
1347 : {
1348 0 : for (uint8_t i = 0; i < 8; ++i)
1349 0 : data[i + 24] = 1;
1350 : }
1351 : else
1352 0 : data[link + 24] = 1;
1353 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1354 :
1355 0 : usleep(interval);
1356 :
1357 0 : data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1358 0 : if (link == DTC_Link_ALL)
1359 : {
1360 0 : for (uint8_t i = 0; i < 8; ++i)
1361 0 : data[i + 24] = 0;
1362 : }
1363 : else
1364 0 : data[link + 24] = 0;
1365 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1366 :
1367 0 : auto resetDone = false;
1368 0 : uint32_t loops = 0;
1369 0 : while (!resetDone && ++loops < 10)
1370 : {
1371 0 : usleep(interval);
1372 :
1373 : // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
1374 0 : resetDone = true;
1375 : // if(link == DTC_Link_ALL)
1376 : // {
1377 : // //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
1378 : // resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
1379 : // }
1380 : // else
1381 : // resetDone = ReadResetTXSERDESDone(link);
1382 :
1383 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES TX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
1384 : }
1385 :
1386 0 : if (loops >= 10)
1387 : {
1388 0 : __SS__ << "Timeout waiting for SERDES TX Reset loop.";
1389 0 : __SS_THROW__;
1390 : // throw DTC_IOErrorException("Timeout waiting for SERDES TX Reset loop.");
1391 0 : }
1392 0 : }
1393 :
1394 : /// <summary>
1395 : /// Read if a SERDES TX reset is currently in progress
1396 : /// </summary>
1397 : /// <param name="link">Link to read</param>
1398 : /// <returns>True if a SERDES TX reset is in progress</returns>
1399 0 : bool DTCLib::DTC_Registers::ReadResetSERDESTX(DTC_Link_ID const& link, std::optional<uint32_t> val)
1400 : {
1401 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1402 0 : return dataSet[link + 24];
1403 : }
1404 :
1405 : /// <summary>
1406 : /// Reset the SERDES RX side
1407 : /// Will poll the Reset SERDES RX Done flag until the SERDES reset is complete
1408 : /// </summary>
1409 : /// <param name="link">Link to reset</param>
1410 : /// <param name="interval">Polling interval, in microseconds</param>
1411 0 : void DTCLib::DTC_Registers::ResetSERDESRX(DTC_Link_ID const& link, int interval)
1412 : {
1413 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES RX Reset Loop for Link " << link;
1414 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1415 0 : if (link == DTC_Link_ALL)
1416 : {
1417 0 : for (uint8_t i = 0; i < 8; ++i)
1418 0 : data[i + 16] = 1;
1419 : }
1420 : else
1421 0 : data[link + 16] = 1;
1422 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1423 :
1424 0 : usleep(interval);
1425 :
1426 0 : data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1427 0 : if (link == DTC_Link_ALL)
1428 : {
1429 0 : for (uint8_t i = 0; i < 8; ++i)
1430 0 : data[i + 16] = 0;
1431 : }
1432 : else
1433 0 : data[link + 16] = 0;
1434 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1435 :
1436 0 : auto resetDone = false;
1437 0 : uint32_t loops = 0;
1438 0 : while (!resetDone && ++loops < 10)
1439 : {
1440 0 : usleep(interval);
1441 :
1442 : // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
1443 0 : resetDone = true;
1444 : // if(link == DTC_Link_ALL)
1445 : // {
1446 : // //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
1447 : // resetDone = ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF;
1448 : // }
1449 : // else
1450 : // resetDone = ReadResetRXSERDESDone(link);
1451 :
1452 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES RX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
1453 : }
1454 :
1455 0 : if (loops >= 10)
1456 : {
1457 0 : __SS__ << "Timeout waiting for SERDES RX Reset loop.";
1458 0 : __SS_THROW__;
1459 : // throw DTC_IOErrorException("Timeout waiting for SERDES RX Reset loop.");
1460 0 : }
1461 0 : }
1462 :
1463 : /// <summary>
1464 : /// Read if a SERDES RX reset is currently in progress
1465 : /// </summary>
1466 : /// <param name="link">Link to read</param>
1467 : /// <returns>True if a SERDES reset is in progress</returns>
1468 0 : bool DTCLib::DTC_Registers::ReadResetSERDESRX(DTC_Link_ID const& link, std::optional<uint32_t> val)
1469 : {
1470 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1471 0 : return dataSet[link + 16];
1472 : }
1473 :
1474 : /// <summary>
1475 : /// Reset the SERDES PLL
1476 : /// Will poll the Reset SERDES PLL Done flag until the SERDES reset is complete
1477 : /// </summary>
1478 : /// <param name="pll">PLL to reset</param>
1479 : /// <param name="interval">Polling interval, in microseconds</param>
1480 0 : void DTCLib::DTC_Registers::ResetSERDESPLL(const DTC_PLL_ID& pll, int interval)
1481 : {
1482 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1483 0 : data[pll + 8] = 1;
1484 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1485 :
1486 0 : usleep(interval);
1487 :
1488 0 : data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1489 0 : data[pll + 8] = 0;
1490 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1491 0 : }
1492 :
1493 : /// <summary>
1494 : /// Read if a SERDES PLL reset is currently in progress
1495 : /// </summary>
1496 : /// <param name="pll">PLL to read</param>
1497 : /// <returns>True if a SERDES reset is in progress</returns>
1498 0 : bool DTCLib::DTC_Registers::ReadResetSERDESPLL(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
1499 : {
1500 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1501 0 : return dataSet[pll + 8];
1502 : }
1503 :
1504 : /// <summary>
1505 : /// Reset the SERDES
1506 : /// Will poll the Reset SERDES Done flag until the SERDES reset is complete
1507 : /// </summary>
1508 : /// <param name="link">Link to reset</param>
1509 : /// <param name="interval">Polling interval, in microseconds</param>
1510 0 : void DTCLib::DTC_Registers::ResetSERDES(DTC_Link_ID const& link, int interval)
1511 : {
1512 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES Reset Loop for Link " << link;
1513 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1514 0 : if (link == DTC_Link_ALL)
1515 : {
1516 0 : for (uint8_t i = 0; i < 8; ++i)
1517 0 : data[i] = 1;
1518 : }
1519 : else
1520 0 : data[link] = 1;
1521 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1522 :
1523 : // usleep(interval);
1524 :
1525 0 : data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1526 0 : if (link == DTC_Link_ALL)
1527 : {
1528 0 : for (uint8_t i = 0; i < 8; ++i)
1529 0 : data[i] = 0;
1530 : }
1531 : else
1532 0 : data[link] = 0;
1533 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
1534 :
1535 0 : auto resetDone = false;
1536 0 : uint32_t loops = 0;
1537 0 : while (!resetDone && ++loops < 100)
1538 : {
1539 0 : usleep(interval);
1540 :
1541 0 : if (link == DTC_Link_ALL)
1542 : {
1543 : // Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
1544 : // For new DTC versions since December 2023, EVB is not instantiated, so also ignore
1545 : // resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
1546 : // resetDone = resetDone &&
1547 : // ( ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF);
1548 0 : resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0x3F) == 0x3F;
1549 0 : resetDone = resetDone &&
1550 0 : (((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0x3F) == 0x3F);
1551 : }
1552 : else
1553 : {
1554 0 : resetDone = ReadResetRXSERDESDone(link);
1555 0 : resetDone = resetDone && ReadResetTXSERDESDone(link);
1556 : }
1557 0 : TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
1558 : }
1559 :
1560 0 : if (loops >= 100)
1561 : {
1562 0 : __SS__ << "Timeout waiting for SERDES Reset loop=" << loops;
1563 0 : __SS_THROW__;
1564 : // throw DTC_IOErrorException("Timeout waiting for SERDES Reset loop.");
1565 0 : }
1566 0 : }
1567 :
1568 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDiagFifo(DTC_Link_ID const& link)
1569 : {
1570 0 : __COUT__ << "FormatRXDiagFifo.";
1571 : DTC_Register reg;
1572 0 : switch (link)
1573 : {
1574 0 : case DTC_Link_0:
1575 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link0;
1576 0 : break;
1577 0 : case DTC_Link_1:
1578 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link1;
1579 0 : break;
1580 0 : case DTC_Link_2:
1581 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link2;
1582 0 : break;
1583 0 : case DTC_Link_3:
1584 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link3;
1585 0 : break;
1586 0 : case DTC_Link_4:
1587 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link4;
1588 0 : break;
1589 0 : case DTC_Link_5:
1590 0 : reg = DTC_Register_RXDataDiagnosticFIFO_Link5;
1591 0 : break;
1592 0 : case DTC_Link_CFO:
1593 0 : reg = DTC_Register_RXDataDiagnosticFIFO_LinkCFO;
1594 0 : break;
1595 0 : default: {
1596 0 : __SS__ << "Invalid DTC Link";
1597 0 : __SS_THROW__;
1598 : // throw std::runtime_error("Invalid DTC Link");
1599 0 : }
1600 : }
1601 :
1602 0 : auto form = CreateFormatter(reg);
1603 0 : form.description = "Rx Diag FIFO";
1604 0 : form.vals.push_back(""); // translation
1605 0 : for (uint8_t i = 0; i < 100; ++i)
1606 : {
1607 0 : __COUT__ << "FormatRXDiagFifo loop." << i;
1608 0 : std::ostringstream o;
1609 0 : o << std::hex << std::setfill('0');
1610 0 : o << " 0x" << std::setw(4) << static_cast<int>(form.address) << " | 0x" << std::setw(8)
1611 0 : << static_cast<int>(ReadRegister_(reg)) << " | ";
1612 0 : form.vals.push_back(o.str());
1613 0 : }
1614 :
1615 0 : __COUT__ << "FormatRXDiagFifo loop done.";
1616 0 : return form;
1617 0 : }
1618 :
1619 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDiagFifo(DTC_Link_ID const& link)
1620 : {
1621 : DTC_Register reg;
1622 0 : switch (link)
1623 : {
1624 0 : case DTC_Link_0:
1625 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link0;
1626 0 : break;
1627 0 : case DTC_Link_1:
1628 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link1;
1629 0 : break;
1630 0 : case DTC_Link_2:
1631 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link2;
1632 0 : break;
1633 0 : case DTC_Link_3:
1634 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link3;
1635 0 : break;
1636 0 : case DTC_Link_4:
1637 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link4;
1638 0 : break;
1639 0 : case DTC_Link_5:
1640 0 : reg = DTC_Register_TXDataDiagnosticFIFO_Link5;
1641 0 : break;
1642 0 : case DTC_Link_CFO:
1643 0 : reg = DTC_Register_TXDataDiagnosticFIFO_LinkCFO;
1644 0 : break;
1645 0 : default: {
1646 0 : __SS__ << "Invalid DTC Link";
1647 0 : __SS_THROW__;
1648 : // throw std::runtime_error("Invalid DTC Link");
1649 0 : }
1650 : }
1651 0 : auto form = CreateFormatter(reg);
1652 0 : form.description = "Tx Diag FIFO";
1653 0 : form.vals.push_back(""); // translation
1654 0 : for (uint8_t i = 0; i < 100; ++i)
1655 : {
1656 0 : std::ostringstream o;
1657 0 : o << std::hex << std::setfill('0');
1658 0 : o << " 0x" << std::setw(4) << static_cast<int>(form.address) << " | 0x" << std::setw(8)
1659 0 : << static_cast<int>(ReadRegister_(reg)) << " | ";
1660 0 : form.vals.push_back(o.str());
1661 0 : }
1662 :
1663 0 : return form;
1664 0 : }
1665 :
1666 : /// <summary>
1667 : /// Read if a SERDES reset is currently in progress
1668 : /// </summary>
1669 : /// <param name="link">Link to read</param>
1670 : /// <returns>True if a SERDES reset is in progress</returns>
1671 0 : bool DTCLib::DTC_Registers::ReadResetSERDES(DTC_Link_ID const& link, std::optional<uint32_t> val)
1672 : {
1673 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
1674 0 : return dataSet[link];
1675 : }
1676 :
1677 : /// <summary>
1678 : /// Formats the register's current value for register dumps
1679 : /// </summary>
1680 : /// <returns>RegisterFormatter object containing register information</returns>
1681 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESReset()
1682 : {
1683 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_Reset);
1684 0 : form.description = "SERDES Reset";
1685 0 : form.vals.push_back(" ([TX,RX,Link])");
1686 0 : for (auto r : DTC_ROC_Links)
1687 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
1688 0 : (ReadResetSERDESTX(r, form.value) ? "x" : ".") +
1689 0 : (ReadResetSERDESRX(r, form.value) ? "x" : ".") +
1690 0 : (ReadResetSERDES(r, form.value) ? "x" : ".") + "]");
1691 0 : form.vals.push_back(std::string("CFO: [") +
1692 0 : (ReadResetSERDESTX(DTC_Link_CFO, form.value) ? "x" : ".") +
1693 0 : (ReadResetSERDESRX(DTC_Link_CFO, form.value) ? "x" : ".") +
1694 0 : (ReadResetSERDES(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
1695 0 : form.vals.push_back(std::string("EVB: [") +
1696 0 : (ReadResetSERDESTX(DTC_Link_EVB, form.value) ? "x" : ".") +
1697 0 : (ReadResetSERDESRX(DTC_Link_EVB, form.value) ? "x" : ".") +
1698 0 : (ReadResetSERDES(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
1699 :
1700 0 : form.vals.push_back(" ([ x = 1 (hi) ])");
1701 0 : for (auto r : DTC_PLLs)
1702 0 : form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ": [" +
1703 0 : (ReadResetSERDESPLL(r, form.value) ? "x" : ".") + "]");
1704 0 : form.vals.push_back(std::string("PLL CFO RX: [") +
1705 0 : (ReadResetSERDESPLL(DTC_PLL_CFO_RX, form.value) ? "x" : ".") + "]");
1706 0 : form.vals.push_back(std::string("PLL CFO TX: [") +
1707 0 : (ReadResetSERDESPLL(DTC_PLL_CFO_TX, form.value) ? "x" : ".") + "]");
1708 :
1709 0 : return form;
1710 0 : }
1711 :
1712 : // SERDES RX Disparity Error Register
1713 : /// <summary>
1714 : /// Read the SERDES RX Dispatity Error bits
1715 : /// </summary>
1716 : /// <param name="link">Link to read</param>
1717 : /// <returns>DTC_SERDESRXDisparityError object with error bits</returns>
1718 0 : DTCLib::DTC_SERDESRXDisparityError DTCLib::DTC_Registers::ReadSERDESRXDisparityError(DTC_Link_ID const& link, std::optional<uint32_t> val)
1719 : {
1720 0 : return DTC_SERDESRXDisparityError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXDisparityError), link);
1721 : }
1722 :
1723 : /// <summary>
1724 : /// Formats the register's current value for register dumps
1725 : /// </summary>
1726 : /// <returns>RegisterFormatter object containing register information</returns>
1727 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityError()
1728 : {
1729 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXDisparityError);
1730 0 : form.description = "SERDES RX Disparity Error";
1731 0 : form.vals.push_back(" ([H,L])");
1732 0 : for (auto r : DTC_ROC_Links)
1733 : {
1734 0 : auto re = ReadSERDESRXDisparityError(r, form.value);
1735 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
1736 0 : to_string(re.GetData()[0]) + "]");
1737 : }
1738 0 : auto ce = ReadSERDESRXDisparityError(DTC_Link_CFO, form.value);
1739 0 : form.vals.push_back(std::string("CFO: [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
1740 0 : return form;
1741 0 : }
1742 :
1743 : // SERDES RX Character Not In Table Error Register
1744 : /// <summary>
1745 : /// Read the SERDES Character Not In Table Error bits
1746 : /// </summary>
1747 : /// <param name="link">Link to read</param>
1748 : /// <returns>DTC_CharacterNotInTableError object with error bits</returns>
1749 0 : DTCLib::DTC_CharacterNotInTableError DTCLib::DTC_Registers::ReadSERDESRXCharacterNotInTableError(DTC_Link_ID const& link, std::optional<uint32_t> val)
1750 : {
1751 0 : return DTC_CharacterNotInTableError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXCharacterNotInTableError), link);
1752 : }
1753 :
1754 : /// <summary>
1755 : /// Formats the register's current value for register dumps
1756 : /// </summary>
1757 : /// <returns>RegisterFormatter object containing register information</returns>
1758 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCharacterNotInTableError()
1759 : {
1760 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXCharacterNotInTableError);
1761 0 : form.description = "SERDES RX CNIT Error";
1762 0 : form.vals.push_back(" ([H,L])");
1763 0 : for (auto r : DTC_ROC_Links)
1764 : {
1765 0 : auto re = ReadSERDESRXCharacterNotInTableError(r, form.value);
1766 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
1767 0 : to_string(re.GetData()[0]) + "]");
1768 : }
1769 0 : auto ce = ReadSERDESRXCharacterNotInTableError(DTC_Link_CFO, form.value);
1770 0 : form.vals.push_back(std::string("CFO: [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
1771 0 : return form;
1772 0 : }
1773 :
1774 : // SERDES Unlock Error Register
1775 : /// <summary>
1776 : /// Read whether the SERDES CDR Unlock Error bit is set
1777 : /// </summary>
1778 : /// <param name="link">Link to check</param>
1779 : /// <returns>True if the SERDES CDR Unlock Error bit is set on the given link</returns>
1780 0 : bool DTCLib::DTC_Registers::ReadSERDESCDRUnlockError(DTC_Link_ID const& link, std::optional<uint32_t> val)
1781 : {
1782 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
1783 0 : return dataSet[16 + link];
1784 : }
1785 :
1786 : /// <summary>
1787 : /// Read whether the SERDES PLL Unlock Error bit is set
1788 : /// </summary>
1789 : /// <param name="pll">PLL to check</param>
1790 : /// <returns>True if the SERDES PLL Unlock Error bit is set for the given PLL</returns>
1791 0 : bool DTCLib::DTC_Registers::ReadSERDESPLLUnlockError(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
1792 : {
1793 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
1794 0 : return dataSet[pll];
1795 : }
1796 :
1797 : /// <summary>
1798 : /// Formats the register's current value for register dumps
1799 : /// </summary>
1800 : /// <returns>RegisterFormatter object containing register information</returns>
1801 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESUnlockError()
1802 : {
1803 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_UnlockError);
1804 0 : form.description = "SERDES Unlock Error";
1805 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
1806 0 : for (auto r : DTC_ROC_Links)
1807 0 : form.vals.push_back(std::string("CDR Link ") + std::to_string(r) + ": [" +
1808 0 : (ReadSERDESCDRUnlockError(r, form.value) ? "x" : " ") + "]");
1809 0 : form.vals.push_back(std::string("CDR CFO: [") + (ReadSERDESCDRUnlockError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
1810 0 : form.vals.push_back(std::string("CDR EVB: [") + (ReadSERDESCDRUnlockError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
1811 0 : for (auto r : DTC_PLLs)
1812 0 : form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ": [" +
1813 0 : (ReadSERDESPLLUnlockError(r, form.value) ? "x" : " ") + "]");
1814 0 : form.vals.push_back(std::string("PLL CFO RX: [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_RX, form.value) ? "x" : " ") + "]");
1815 0 : form.vals.push_back(std::string("PLL CFO TX: [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_TX, form.value) ? "x" : " ") + "]");
1816 0 : form.vals.push_back(std::string("PLL EVB: [") + (ReadSERDESPLLUnlockError(DTC_PLL_EVB_TXRX, form.value) ? "x" : " ") + "]");
1817 0 : form.vals.push_back(std::string("PLL PunchClock:[") + (ReadSERDESPLLUnlockError(DTC_PLL_PunchedClock, form.value) ? "x" : " ") + "]");
1818 0 : return form;
1819 0 : }
1820 :
1821 : // SERDES PLL Locked Register
1822 : /// <summary>
1823 : /// Read if the SERDES PLL is locked for the given SERDES link
1824 : /// </summary>
1825 : /// <param name="link">Link to read</param>
1826 : /// <returns>True if the PLL is locked, false otherwise</returns>
1827 0 : bool DTCLib::DTC_Registers::ReadSERDESPLLLocked(DTC_Link_ID const& link, std::optional<uint32_t> val)
1828 : {
1829 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLLocked);
1830 0 : return dataSet[link];
1831 : }
1832 :
1833 : /// <summary>
1834 : /// Formats the register's current value for register dumps
1835 : /// </summary>
1836 : /// <returns>RegisterFormatter object containing register information</returns>
1837 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLLocked()
1838 : {
1839 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLLocked);
1840 0 : form.description = "SERDES PLL Locked";
1841 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
1842 0 : for (auto r : DTC_ROC_Links)
1843 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (ReadSERDESPLLLocked(r, form.value) ? "x" : " ") + "]");
1844 0 : form.vals.push_back(std::string("CFO: [") + (ReadSERDESPLLLocked(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
1845 0 : form.vals.push_back(std::string("EVB: [") + (ReadSERDESPLLLocked(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
1846 0 : form.vals.push_back(std::string("Clock to JA: [") + ((((form.value) >> 8) & 1) ? "x" : " ") + "]");
1847 0 : form.vals.push_back(std::string("Clock from JA: [") + ((((form.value) >> 9) & 1) ? "x" : " ") + "]");
1848 0 : return form;
1849 0 : }
1850 :
1851 : /// <summary>
1852 : /// Disable the SERDES PLL Power Down bit for the given link, enabling that link
1853 : /// </summary>
1854 : /// <param name="link">Link to set</param>
1855 0 : void DTCLib::DTC_Registers::EnableSERDESPLL(DTC_Link_ID const& link)
1856 : {
1857 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
1858 0 : data[link] = 0;
1859 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
1860 0 : }
1861 :
1862 : /// <summary>
1863 : /// Enable the SERDES PLL Power Down bit for the given link, disabling that link
1864 : /// </summary>
1865 : /// <param name="link">Link to set</param>
1866 0 : void DTCLib::DTC_Registers::DisableSERDESPLL(DTC_Link_ID const& link)
1867 : {
1868 0 : std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
1869 0 : data[link] = 1;
1870 0 : WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
1871 0 : }
1872 :
1873 : /// <summary>
1874 : /// Read the SERDES PLL Power Down bit for the given link
1875 : /// </summary>
1876 : /// <param name="link">link to read</param>
1877 : /// <returns>Value of the bit</returns>
1878 0 : bool DTCLib::DTC_Registers::ReadSERDESPLLPowerDown(DTC_Link_ID const& link, std::optional<uint32_t> val)
1879 : {
1880 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
1881 0 : return data[link];
1882 : }
1883 :
1884 : /// <summary>
1885 : /// Formats the register's current value for register dumps
1886 : /// </summary>
1887 : /// <returns>RegisterFormatter object containing register information</returns>
1888 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLPowerDown()
1889 : {
1890 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLPowerDown);
1891 0 : form.description = "SERDES PLL Power Down";
1892 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
1893 0 : for (auto r : DTC_ROC_Links)
1894 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (ReadSERDESPLLPowerDown(r, form.value) ? "x" : " ") + "]");
1895 0 : form.vals.push_back(std::string("CFO: [") + (ReadSERDESPLLPowerDown(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
1896 0 : form.vals.push_back(std::string("EVB: [") + (ReadSERDESPLLPowerDown(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
1897 0 : return form;
1898 0 : }
1899 :
1900 : // SERDES RX Status Register
1901 : /// <summary>
1902 : /// Read the SERDES RX Status for the given SERDES Link
1903 : /// </summary>
1904 : /// <param name="link">Link to read</param>
1905 : /// <returns>DTC_RXStatus object</returns>
1906 0 : DTCLib::DTC_RXStatus DTCLib::DTC_Registers::ReadSERDESRXStatus(DTC_Link_ID const& link, std::optional<uint32_t> val)
1907 : {
1908 0 : std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXStatus)) >> 3 * link;
1909 0 : return static_cast<DTC_RXStatus>(dataSet.to_ulong());
1910 : }
1911 :
1912 : /// <summary>
1913 : /// Formats the register's current value for register dumps
1914 : /// </summary>
1915 : /// <returns>RegisterFormatter object containing register information</returns>
1916 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXStatus()
1917 : {
1918 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXStatus);
1919 0 : form.description = "SERDES RX Status";
1920 0 : form.vals.push_back(""); // translation
1921 0 : for (auto r : DTC_ROC_Links)
1922 : {
1923 0 : auto re = ReadSERDESRXStatus(r, form.value);
1924 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " + DTC_RXStatusConverter(re).toString());
1925 : }
1926 0 : auto ce = ReadSERDESRXStatus(DTC_Link_CFO, form.value);
1927 0 : form.vals.push_back(std::string("CFO: ") + DTC_RXStatusConverter(ce).toString());
1928 :
1929 0 : return form;
1930 0 : }
1931 :
1932 : // SERDES Reset Done Register
1933 : /// <summary>
1934 : /// Read the SERDES Reset RX FSM Done bit
1935 : /// </summary>
1936 : /// <param name="link">link to read</param>
1937 : /// <returns>Value of the bit</returns>
1938 0 : bool DTCLib::DTC_Registers::ReadResetRXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
1939 : {
1940 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
1941 0 : return dataSet[link + 24];
1942 : }
1943 : /// <summary>
1944 : /// Read the SERDES Reset RX Done bit
1945 : /// </summary>
1946 : /// <param name="link">link to read</param>
1947 : /// <returns>Value of the bit</returns>
1948 0 : bool DTCLib::DTC_Registers::ReadResetRXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
1949 : {
1950 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
1951 0 : return dataSet[link + 16];
1952 : }
1953 : /// <summary>
1954 : /// Read the SERDES Reset TX FSM Done bit
1955 : /// </summary>
1956 : /// <param name="link">link to read</param>
1957 : /// <returns>Value of the bit</returns>
1958 0 : bool DTCLib::DTC_Registers::ReadResetTXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
1959 : {
1960 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
1961 0 : return dataSet[link + 8];
1962 : }
1963 : /// <summary>
1964 : /// Read the SERDES Reset TX Done bit
1965 : /// </summary>
1966 : /// <param name="link">link to read</param>
1967 : /// <returns>Value of the bit</returns>
1968 0 : bool DTCLib::DTC_Registers::ReadResetTXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
1969 : {
1970 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
1971 0 : return dataSet[link];
1972 : }
1973 :
1974 : /// <summary>
1975 : /// Formats the register's current value for register dumps
1976 : /// </summary>
1977 : /// <returns>RegisterFormatter object containing register information</returns>
1978 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESResetDone()
1979 : {
1980 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_ResetDone);
1981 0 : form.description = "SERDES Reset Done";
1982 0 : form.vals.push_back(" ([RX FSM, RX, TX FSM, TX])");
1983 0 : for (auto r : DTC_ROC_Links)
1984 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
1985 0 : (ReadResetRXFSMSERDESDone(r, form.value) ? "x" : ".") +
1986 0 : (ReadResetRXSERDESDone(r, form.value) ? "x" : ".") +
1987 0 : (ReadResetTXFSMSERDESDone(r, form.value) ? "x" : ".") +
1988 0 : (ReadResetTXSERDESDone(r, form.value) ? "x" : ".") + "]");
1989 0 : form.vals.push_back(std::string("CFO: [") +
1990 0 : (ReadResetRXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
1991 0 : (ReadResetRXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
1992 0 : (ReadResetTXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
1993 0 : (ReadResetTXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
1994 0 : form.vals.push_back(std::string("EVB: [") +
1995 0 : (ReadResetRXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
1996 0 : (ReadResetRXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
1997 0 : (ReadResetTXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
1998 0 : (ReadResetTXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
1999 0 : return form;
2000 0 : }
2001 :
2002 : // SFP / SERDES Status Register
2003 :
2004 : /// <summary>
2005 : /// Read the SERDES CDR Lock bit for the given SERDES Link
2006 : /// </summary>
2007 : /// <param name="link">Link to read</param>
2008 : /// <returns>True if the SERDES CDR Lock bit is set</returns>
2009 0 : bool DTCLib::DTC_Registers::ReadSERDESRXCDRLock(DTC_Link_ID const& link, std::optional<uint32_t> val)
2010 : {
2011 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
2012 :
2013 : // read the lock value 20x because it might not be stable, consider unlocked if ever low
2014 0 : if (!val.has_value() && dataSet[link])
2015 : {
2016 0 : for (int i = 0; i < 20; ++i)
2017 : {
2018 0 : std::bitset<32> tmpDataSet = ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
2019 0 : if (!tmpDataSet[link]) // override with any exception
2020 0 : return false;
2021 0 : usleep(10);
2022 : }
2023 : }
2024 0 : return dataSet[link];
2025 : }
2026 :
2027 : /// <summary>
2028 : /// Formats the register's current value for register dumps
2029 : /// </summary>
2030 : /// <returns>RegisterFormatter object containing register information</returns>
2031 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRLockStatus()
2032 : {
2033 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCDRLockStatus);
2034 0 : form.description = "RX CDR Lock Status";
2035 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
2036 0 : for (auto r : DTC_ROC_Links)
2037 : {
2038 0 : form.vals.push_back(std::string("ROC Link ") + std::to_string(r) +
2039 0 : " CDR Lock: [" + (ReadSERDESRXCDRLock(r) ? "x" : " ") + "]"); // do not use form.value to force multi reread in case of instability
2040 : }
2041 0 : if (ReadCFOEmulationMode())
2042 0 : form.vals.push_back(std::string("CFO Emulated CDR Lock: [") + (ReadSERDESRXCDRLock(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
2043 : else
2044 0 : form.vals.push_back(std::string("CFO CDR Lock: [") + (ReadSERDESRXCDRLock(DTC_Link_CFO) ? "x" : " ") + "]"); // do not use form.value to force multi reread in case of instability
2045 :
2046 0 : form.vals.push_back(std::string("EVB CDR Lock: [") + (ReadSERDESRXCDRLock(DTC_Link_EVB) ? "x" : " ") + "]"); // do not use form.value to force multi reread in case of instability
2047 0 : return form;
2048 0 : }
2049 :
2050 : // DMA Timeout Preset Register
2051 : /// <summary>
2052 : /// Set the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
2053 : /// The default value is 0x800
2054 : /// </summary>
2055 : /// <param name="preset">Maximum active time for DMA buffers</param>
2056 0 : void DTCLib::DTC_Registers::SetDMATimeoutPreset(uint32_t preset)
2057 : {
2058 0 : WriteRegister_(preset, DTC_Register_DMATimeoutPreset);
2059 0 : }
2060 :
2061 : /// <summary>
2062 : /// Read the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
2063 : /// The default value is 0x800
2064 : /// </summary>
2065 : /// <returns>Maximum active time for DMA buffers</returns>
2066 0 : uint32_t DTCLib::DTC_Registers::ReadDMATimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_DMATimeoutPreset); }
2067 :
2068 : /// <summary>
2069 : /// Formats the register's current value for register dumps
2070 : /// </summary>
2071 : /// <returns>RegisterFormatter object containing register information</returns>
2072 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATimeoutPreset()
2073 : {
2074 0 : auto form = CreateFormatter(DTC_Register_DMATimeoutPreset);
2075 0 : form.description = "DMA Timeout";
2076 0 : std::stringstream o;
2077 0 : o << "0x" << std::hex << ReadDMATimeoutPreset(form.value);
2078 0 : form.vals.push_back(o.str());
2079 0 : return form;
2080 0 : }
2081 :
2082 : // ROC Timeout Preset Register
2083 : /// <summary>
2084 : /// Read the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
2085 : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
2086 : /// </summary>
2087 : /// <returns>Timeout value</returns>
2088 0 : uint32_t DTCLib::DTC_Registers::ReadROCTimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeout); }
2089 :
2090 : /// <summary>
2091 : /// Set the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
2092 : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
2093 : /// </summary>
2094 : /// <param name="preset">Timeout value. Default: 0x200000</param>
2095 0 : void DTCLib::DTC_Registers::SetROCTimeoutPreset(uint32_t preset)
2096 : {
2097 0 : WriteRegister_(preset, DTC_Register_ROCReplyTimeout);
2098 0 : }
2099 :
2100 : /// <summary>
2101 : /// Formats the register's current value for register dumps
2102 : /// </summary>
2103 : /// <returns>RegisterFormatter object containing register information</returns>
2104 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeout()
2105 : {
2106 0 : auto form = CreateFormatter(DTC_Register_ROCReplyTimeout);
2107 0 : form.description = "ROC Reply Timeout";
2108 0 : std::stringstream o;
2109 0 : o << "0x" << std::hex << ReadROCTimeoutPreset(form.value);
2110 0 : form.vals.push_back(o.str());
2111 0 : return form;
2112 0 : }
2113 :
2114 : // ROC Timeout Error Register
2115 : /// <summary>
2116 : /// Clear the ROC Data Packet timeout error flag for the given SERDES link
2117 : /// </summary>
2118 : /// <param name="link">Link to clear</param>
2119 0 : bool DTCLib::DTC_Registers::ReadROCTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
2120 : {
2121 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeoutError);
2122 0 : return data[static_cast<int>(link)];
2123 : }
2124 :
2125 : /// <summary>
2126 : /// Read the ROC Data Packet Timeout Error Flag for the given SERDES link
2127 : /// </summary>
2128 : /// <param name="link">Link to read</param>
2129 : /// <returns>True if the error flag is set, false otherwise</returns>
2130 0 : void DTCLib::DTC_Registers::ClearROCTimeoutError(DTC_Link_ID const& link)
2131 : {
2132 0 : std::bitset<32> data = 0x0;
2133 0 : data[link] = 1;
2134 0 : WriteRegister_(data.to_ulong(), DTC_Register_ROCReplyTimeoutError);
2135 0 : }
2136 :
2137 : /// <summary>
2138 : /// Formats the register's current value for register dumps
2139 : /// </summary>
2140 : /// <returns>RegisterFormatter object containing register information</returns>
2141 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeoutError()
2142 : {
2143 0 : auto form = CreateFormatter(DTC_Register_ROCReplyTimeoutError);
2144 0 : form.description = "ROC Reply Timeout Error";
2145 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
2146 0 : for (auto r : DTC_ROC_Links)
2147 : {
2148 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
2149 0 : (ReadROCTimeoutError(r, form.value) ? "x" : " ") + "]");
2150 : }
2151 0 : return form;
2152 0 : }
2153 :
2154 : /// <summary>
2155 : /// Set the DTC ID and EVB Info register
2156 : /// </summary>
2157 : /// <returns></returns>
2158 0 : void DTCLib::DTC_Registers::SetEVBInfo(uint8_t dtcid, uint8_t mode,
2159 : uint8_t partitionId, uint8_t macByte)
2160 : {
2161 0 : uint32_t regVal = dtcid << 24;
2162 0 : regVal |= mode << 16;
2163 0 : regVal |= partitionId << 8;
2164 0 : regVal |= macByte;
2165 0 : WriteRegister_(regVal, DTC_Register_EVBPartitionID);
2166 0 : }
2167 :
2168 : /// <summary>
2169 : /// Set only the DTC ID within the EVB Info register
2170 : /// </summary>
2171 : /// <returns></returns>
2172 0 : void DTCLib::DTC_Registers::SetDTCID(uint8_t dtcid)
2173 : {
2174 0 : auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0x00FFFFFF;
2175 0 : regVal += dtcid << 24;
2176 0 : WriteRegister_(regVal, DTC_Register_EVBPartitionID);
2177 0 : }
2178 :
2179 : // EVB Network Partition ID / EVB Network Local MAC Index Register
2180 0 : uint8_t DTCLib::DTC_Registers::ReadDTCID(std::optional<uint32_t> val)
2181 : {
2182 0 : auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF000000;
2183 0 : return static_cast<uint8_t>(regVal >> 24);
2184 : }
2185 :
2186 : /// <summary>
2187 : /// Set the EVB Mode byte
2188 : /// </summary>
2189 : /// <param name="mode">New Mode byte</param>
2190 0 : void DTCLib::DTC_Registers::SetEVBMode(uint8_t mode)
2191 : {
2192 0 : auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFF00FFFF;
2193 0 : regVal += mode << 16;
2194 0 : WriteRegister_(regVal, DTC_Register_EVBPartitionID);
2195 0 : }
2196 :
2197 : /// <summary>
2198 : /// Read the EVB Mode byte
2199 : /// </summary>
2200 : /// <returns>EVB Mode byte</returns>
2201 0 : uint8_t DTCLib::DTC_Registers::ReadEVBMode(std::optional<uint32_t> val)
2202 : {
2203 0 : auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF0000;
2204 0 : return static_cast<uint8_t>(regVal >> 16);
2205 : }
2206 :
2207 : /// <summary>
2208 : /// Set the local partition ID
2209 : /// </summary>
2210 : /// <param name="id">Local partition ID</param>
2211 0 : void DTCLib::DTC_Registers::SetEVBLocalParitionID(uint8_t partitionId)
2212 : {
2213 0 : auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFFFCFF;
2214 0 : regVal += (partitionId & 0x3) << 8;
2215 0 : WriteRegister_(regVal, DTC_Register_EVBPartitionID);
2216 0 : }
2217 :
2218 : /// <summary>
2219 : /// Read the local partition ID
2220 : /// </summary>
2221 : /// <returns>Partition ID</returns>
2222 0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalParitionID(std::optional<uint32_t> val)
2223 : {
2224 0 : auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF0000;
2225 0 : return static_cast<uint8_t>((regVal >> 8) & 0x3);
2226 : }
2227 :
2228 : /// <summary>
2229 : /// Set the MAC address for the EVB network (lowest byte)
2230 : /// </summary>
2231 : /// <param name="macByte">MAC Address</param>
2232 0 : void DTCLib::DTC_Registers::SetEVBLocalMACAddress(uint8_t macByte)
2233 : {
2234 0 : auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFFFFC0;
2235 0 : regVal += (macByte & 0x3F);
2236 0 : WriteRegister_(regVal, DTC_Register_EVBPartitionID);
2237 0 : }
2238 :
2239 : /// <summary>
2240 : /// Read the MAC address for the EVB network (lowest byte)
2241 : /// </summary>
2242 : /// <returns>MAC Address</returns>
2243 0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalMACAddress(std::optional<uint32_t> val) { return (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0x3F; }
2244 :
2245 : /// <summary>
2246 : /// Formats the register's current value for register dumps
2247 : /// </summary>
2248 : /// <returns>RegisterFormatter object containing register information</returns>
2249 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBLocalParitionIDMACIndex()
2250 : {
2251 0 : auto form = CreateFormatter(DTC_Register_EVBPartitionID);
2252 0 : form.description = "EVB Local Partition ID / MAC Index";
2253 0 : form.vals.push_back(""); // translation
2254 0 : std::ostringstream o;
2255 0 : o << "DTC ID: 0x" << std::hex << static_cast<int>(ReadDTCID(form.value));
2256 0 : form.vals.push_back(o.str());
2257 0 : o.str("");
2258 0 : o.clear();
2259 0 : o << "EVB Mode: 0x" << std::hex << static_cast<int>(ReadEVBMode(form.value));
2260 0 : form.vals.push_back(o.str());
2261 0 : o.str("");
2262 0 : o.clear();
2263 0 : o << "EVB Parition ID: 0x" << std::hex << static_cast<int>(ReadEVBLocalParitionID(form.value));
2264 0 : form.vals.push_back(o.str());
2265 0 : o.str("");
2266 0 : o.clear();
2267 0 : o << "EVB Self MAC Address Last Byte: 0x" << std::hex << static_cast<int>(ReadEVBLocalMACAddress(form.value));
2268 0 : form.vals.push_back(o.str());
2269 0 : return form;
2270 0 : }
2271 :
2272 : /// EVB Number of Destination Nodes Register
2273 0 : void DTCLib::DTC_Registers::SetEVBClusterInfo(uint16_t deadTime,
2274 : uint8_t baseDTCAddress, uint8_t numOfDTCs)
2275 : {
2276 0 : uint32_t regVal = (deadTime & 0xFFFF) << 16;
2277 0 : regVal |= baseDTCAddress << 8;
2278 0 : regVal |= numOfDTCs;
2279 0 : WriteRegister_(regVal, DTC_Register_EVBConfiguration);
2280 0 : }
2281 :
2282 : /// <summary>
2283 : /// Set the dead time (clocks at start of destination switch to block tx to avoid collissions with previous round-robin tx) of the EVB cluster
2284 : /// </summary>
2285 0 : void DTCLib::DTC_Registers::SetEVBDeadTime(uint16_t deadTime)
2286 : {
2287 0 : auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0x0FFFF;
2288 0 : regVal += (deadTime & 0xFFFF) << 16;
2289 0 : WriteRegister_(regVal, DTC_Register_EVBConfiguration);
2290 0 : }
2291 :
2292 : /// <summary>
2293 : /// Read the dead time (clocks at start of destination switch to block tx to avoid collissions with previous round-robin tx) of the EVB cluster
2294 : /// </summary>
2295 0 : uint16_t DTCLib::DTC_Registers::ReadEVBDeadTime(std::optional<uint32_t> val)
2296 : {
2297 0 : return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFFFF0000)) >> 16);
2298 : }
2299 :
2300 : /// <summary>
2301 : /// Set the start node in the EVB cluster
2302 : /// </summary>
2303 0 : void DTCLib::DTC_Registers::SetEVBStartNode(uint8_t startNode)
2304 : {
2305 0 : auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFFC0FF;
2306 0 : regVal += (startNode & 0x3F) << 8;
2307 0 : WriteRegister_(regVal, DTC_Register_EVBConfiguration);
2308 0 : }
2309 :
2310 : /// <summary>
2311 : /// Read the start node in the EVB cluster
2312 : /// </summary>
2313 0 : uint8_t DTCLib::DTC_Registers::ReadEVBStartNode(std::optional<uint32_t> val)
2314 : {
2315 0 : return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0x3F00)) >> 8);
2316 : }
2317 :
2318 : /// <summary>
2319 : /// Set the number of destination nodes in the EVB cluster
2320 : /// </summary>
2321 : /// <param name="numOfNodes">Number of nodes</param>
2322 0 : void DTCLib::DTC_Registers::SetEVBNumberOfDestinationNodes(uint8_t numOfNodes)
2323 : {
2324 0 : auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFFFFC0;
2325 0 : regVal += (numOfNodes & 0x3F);
2326 0 : WriteRegister_(regVal, DTC_Register_EVBConfiguration);
2327 0 : }
2328 :
2329 : /// <summary>
2330 : /// Read the number of destination nodes in the EVB cluster
2331 : /// </summary>
2332 : /// <returns>Number of nodes</returns>
2333 0 : uint8_t DTCLib::DTC_Registers::ReadEVBNumberOfDestinationNodes(std::optional<uint32_t> val)
2334 : {
2335 0 : return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0x3F);
2336 : }
2337 :
2338 : /// <summary>
2339 : /// Formats the register's current value for register dumps
2340 : /// </summary>
2341 : /// <returns>RegisterFormatter object containing register information</returns>
2342 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBClusterInfo()
2343 : {
2344 0 : auto form = CreateFormatter(DTC_Register_EVBConfiguration);
2345 0 : form.description = "EVB DTC Cluster Configuration";
2346 0 : form.vals.push_back(""); // translation
2347 0 : std::stringstream o;
2348 0 : o << "EVB Dead Time: " << std::dec << static_cast<int>(ReadEVBDeadTime(form.value));
2349 0 : form.vals.push_back(o.str());
2350 0 : o.str("");
2351 0 : o.clear();
2352 0 : o << "EVB Start Node: " << std::dec << static_cast<int>(ReadEVBStartNode(form.value));
2353 0 : form.vals.push_back(o.str());
2354 0 : o.str("");
2355 0 : o.clear();
2356 0 : o << "EVB Number of Destination Nodes: " << std::dec << static_cast<int>(ReadEVBNumberOfDestinationNodes(form.value));
2357 0 : form.vals.push_back(o.str());
2358 0 : return form;
2359 0 : }
2360 :
2361 : /// Hardware Event Building Packet Control Info Register
2362 0 : void DTCLib::DTC_Registers::SetEVBPacketControlInfo(uint16_t idlePacketWordCount,
2363 : uint8_t interpacketGap, uint8_t loopbackCalibratedOffset)
2364 : {
2365 0 : uint32_t regVal = idlePacketWordCount << 16;
2366 0 : regVal |= interpacketGap << 8;
2367 0 : regVal |= loopbackCalibratedOffset;
2368 0 : WriteRegister_(regVal, DTC_Register_EVBPacketControl);
2369 0 : }
2370 :
2371 : /// Read the number of words in EVB idle packets
2372 0 : uint16_t DTCLib::DTC_Registers::ReadEVBIdlePacketWordCount(std::optional<uint32_t> val)
2373 : {
2374 0 : return static_cast<uint16_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
2375 : }
2376 : /// Read the EVB interpacket gap in units of GbE transmit clocks
2377 0 : uint8_t DTCLib::DTC_Registers::ReadEVBInterpacketGap(std::optional<uint32_t> val)
2378 : {
2379 0 : return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 8);
2380 : }
2381 : /// Read the DTC's EVB delay offset in units of 200MHz CFO clocks, which should be calibrated by CFO-DTC loopback
2382 0 : uint8_t DTCLib::DTC_Registers::ReadEVBLoopbackCalibratedOffset(std::optional<uint32_t> val)
2383 : {
2384 0 : return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 0);
2385 : }
2386 :
2387 : /// Formats the Hardware Event Building Packet Control Info Register's current value for register dumps
2388 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBPacketControlInfo()
2389 : {
2390 0 : auto form = CreateFormatter(DTC_Register_EVBPacketControl);
2391 0 : form.description = "EVB Packet Control Info";
2392 0 : form.vals.push_back(""); // translation
2393 0 : std::stringstream o;
2394 0 : o << "Idle Packet Word Count: " << std::dec << static_cast<int>(ReadEVBIdlePacketWordCount(form.value));
2395 0 : form.vals.push_back(o.str());
2396 0 : o.str("");
2397 0 : o.clear();
2398 0 : o << "Interpacket Gap [GbE tx clocks]: " << std::dec << static_cast<int>(ReadEVBInterpacketGap(form.value));
2399 0 : form.vals.push_back(o.str());
2400 0 : o.str("");
2401 0 : o.clear();
2402 0 : o << "DTC's Loopback Calibrated Offset [200MHz clocks]: " << std::dec << static_cast<int>(ReadEVBLoopbackCalibratedOffset(form.value));
2403 0 : form.vals.push_back(o.str());
2404 0 : return form;
2405 0 : }
2406 :
2407 : /// Read theHardware Event Building Stats data based on type and DTC mac address
2408 0 : uint32_t DTCLib::DTC_Registers::ReadEVBStats(DTC_EVBStatsType type, uint8_t dtc_mac, std::optional<uint32_t> val)
2409 : {
2410 0 : if (val.has_value()) // assum address is already setup when value is passed, and just read updated stat value
2411 0 : return ReadRegister_(DTC_Register_EVBStats); //*val;
2412 :
2413 0 : uint32_t t = static_cast<uint8_t>(type) << DTC_EVBStatsType_BRAM_TYPE_SIZE;
2414 0 : if (dtc_mac >= (1 << DTC_EVBStatsType_BRAM_TYPE_SIZE))
2415 : {
2416 0 : __SS__ << "Illegal DTC MAC adress value: " << (int)dtc_mac << " must be < 2^" << DTC_EVBStatsType_BRAM_TYPE_SIZE << __E__;
2417 0 : ss << otsStyleStackTrace() << __E__;
2418 0 : __SS_THROW__;
2419 0 : }
2420 0 : t |= dtc_mac; // address fully built now
2421 0 : __COUTT__ << "Read EVB Stat address: 0x" << std::hex << t << __E__;
2422 :
2423 0 : WriteRegister_(t, DTC_Register_EVBStats);
2424 :
2425 0 : return ReadRegister_(DTC_Register_EVBStats);
2426 : } // end ReadEVBStats()
2427 :
2428 : // Get the last packet count and its timestamp for a DTC
2429 0 : std::pair<uint32_t, std::chrono::steady_clock::time_point> DTCLib::DTC_Registers::getPacketCountInfo(uint8_t dtc) const
2430 : {
2431 0 : auto i = lastPacketCount.find(dtc);
2432 0 : if (i != lastPacketCount.end())
2433 0 : return i->second;
2434 0 : return {0, std::chrono::steady_clock::time_point::min()};
2435 : }
2436 :
2437 : // Update the packet count and timestamp and calculate packet rate for a DTC
2438 0 : void DTCLib::DTC_Registers::updatePacketCount(uint8_t dtc, uint32_t currentCount)
2439 : {
2440 0 : auto now = std::chrono::steady_clock::now();
2441 :
2442 0 : auto [lastCount, lastTime] = getPacketCountInfo(dtc);
2443 0 : if (lastTime == std::chrono::steady_clock::time_point::min())
2444 : {
2445 0 : lastPacketCount[dtc] = {currentCount, now};
2446 0 : return;
2447 : }
2448 :
2449 0 : auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
2450 0 : if (ns > 1e6)
2451 : {
2452 0 : double rate = (currentCount - lastCount) / (ns / 1e9);
2453 0 : lastPacketRate[dtc] = rate;
2454 0 : lastPacketCount[dtc] = {currentCount, now};
2455 : }
2456 : }
2457 :
2458 : // Get the most recent packet rate for a DTC
2459 0 : double DTCLib::DTC_Registers::getLastPacketRate(uint8_t dtc) const
2460 : {
2461 0 : auto i = lastPacketRate.find(dtc);
2462 0 : return i != lastPacketRate.end() ? i->second : 0.0;
2463 : }
2464 :
2465 : /// Formats the Hardware Event Building Stats data for all DTC mac addresses, as specified by the EVB Info 'Number Of Destination Nodes'
2466 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBStats(DTCLib::DTC_EVBStatsType type /* = DTC_EVBStatsType::DTC_EVBStatsType_All */)
2467 : {
2468 0 : uint8_t t = static_cast<uint8_t>(type);
2469 0 : if (type == DTC_EVBStatsType::DTC_EVBStatsType_All)
2470 0 : t = 0;
2471 0 : __COUTV__(t);
2472 :
2473 0 : auto form = CreateFormatter(DTC_Register_EVBStats, false /* getValue */);
2474 0 : form.description = "EVB Stats";
2475 0 : form.vals.push_back(""); // translation
2476 0 : std::stringstream o;
2477 :
2478 0 : uint8_t baseDTCAddress = ReadEVBStartNode();
2479 0 : uint8_t numOfDTCs = ReadEVBNumberOfDestinationNodes();
2480 :
2481 0 : __COUTV__(numOfDTCs);
2482 :
2483 0 : uint32_t idlePacketWordCount = (static_cast<uint32_t>(ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
2484 :
2485 0 : for (; t < DTC_EVBStatsType_BRAM_TYPE_COUNT; ++t)
2486 : {
2487 0 : for (uint8_t d = 0; d < numOfDTCs; ++d)
2488 : {
2489 0 : uint32_t v = ReadEVBStats(DTC_EVBStatsType(t), d);
2490 :
2491 0 : o << "BRAM Stat - ";
2492 0 : switch (DTC_EVBStatsType(t))
2493 : {
2494 0 : case DTC_EVBStatsType_RxCount:
2495 0 : if (v > 0 && // start time for rates as soon as there is non-zero data
2496 0 : EVB_startDataTime ==
2497 0 : std::chrono::steady_clock::time_point::min())
2498 0 : EVB_startDataTime = std::chrono::steady_clock::now();
2499 :
2500 0 : EVB_endDataTime = std::chrono::steady_clock::now();
2501 :
2502 0 : o << "Received Packet Rate: ";
2503 0 : o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
2504 :
2505 : {
2506 0 : auto now = std::chrono::steady_clock::now();
2507 0 : auto [lastCount, lastTime] = getPacketCountInfo(d);
2508 :
2509 0 : if (lastTime == std::chrono::steady_clock::time_point::min())
2510 : {
2511 0 : updatePacketCount(d, v);
2512 0 : o << "Initializing";
2513 : }
2514 : else
2515 : {
2516 0 : auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
2517 :
2518 0 : if (ns > 1e6) // prevent divide by 0
2519 : {
2520 0 : double rate = (v - lastCount) / (ns / 1e9);
2521 0 : o << rate << " Packets/s";
2522 :
2523 0 : updatePacketCount(d, v);
2524 : }
2525 : else
2526 0 : o << "T too short.";
2527 : }
2528 : }
2529 0 : form.vals.push_back(o.str());
2530 0 : o.str("");
2531 0 : o.clear();
2532 :
2533 0 : o << "Bram Stat - Received Packet Count: ";
2534 0 : break;
2535 0 : case DTC_EVBStatsType_RxLastSequenceTag:
2536 0 : o << "Last Received Sequence Tag: ";
2537 0 : break;
2538 0 : case DTC_EVBStatsType_RxMissingPacketCount:
2539 0 : o << "Rx Missing Packet Count: ";
2540 0 : break;
2541 0 : case DTC_EVBStatsType_RxByteCount:
2542 0 : o << "Received Byte Rate: ";
2543 0 : o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
2544 :
2545 0 : o << getLastPacketRate(d) * idlePacketWordCount * 8 << " Byte/s";
2546 0 : form.vals.push_back(o.str());
2547 0 : o.str("");
2548 0 : o.clear();
2549 :
2550 0 : o << "Bram Stat - Received Byte Count: ";
2551 0 : break;
2552 0 : case DTC_EVBStatsType_RxLastPacketArrival:
2553 0 : o << "Rx Last Packet Arrival [10gbe clocks]: ";
2554 0 : break;
2555 0 : case DTC_EVBStatsType_TxLastSequenceTag:
2556 0 : o << "Last Transmitted Sequence Tag: ";
2557 0 : break;
2558 0 : default:
2559 0 : __SS__ << "Invalid DTC EVB Stat type: " << t << __E__;
2560 0 : __SS_THROW__;
2561 : }
2562 0 : o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = " << std::hex << "0x" << std::setw(8) << v << "\t" << std::dec << v;
2563 0 : form.vals.push_back(o.str());
2564 0 : o.str("");
2565 0 : o.clear();
2566 : } // end DTC mac address loop
2567 0 : if (type != DTC_EVBStatsType::DTC_EVBStatsType_All) break;
2568 : } // end type loop
2569 :
2570 0 : return form;
2571 0 : } // end FormatEVBStats()
2572 :
2573 : /// <summary>
2574 : /// Read the Reset bit of the SERDES IIC Bus
2575 : /// </summary>
2576 : /// <returns>Reset bit value</returns>
2577 0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICInterfaceReset(std::optional<uint32_t> val)
2578 : {
2579 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESClock_IICBusControl));
2580 0 : return dataSet[31];
2581 : }
2582 :
2583 : /// <summary>
2584 : /// Reset the SERDES IIC Bus
2585 : /// </summary>
2586 0 : void DTCLib::DTC_Registers::ResetSERDESOscillatorIICInterface()
2587 : {
2588 0 : auto bs = std::bitset<32>();
2589 0 : bs[31] = 1;
2590 0 : WriteRegister_(bs.to_ulong(), DTC_Register_SERDESClock_IICBusControl);
2591 0 : while (ReadSERDESOscillatorIICInterfaceReset())
2592 : {
2593 0 : usleep(1000);
2594 : }
2595 0 : }
2596 :
2597 : /// <summary>
2598 : /// Read the current SERDES Oscillator clock speed
2599 : /// </summary>
2600 : /// <returns>Current SERDES clock speed</returns>
2601 0 : DTCLib::DTC_SerdesClockSpeed DTCLib::DTC_Registers::ReadSERDESOscillatorClock(std::optional<uint32_t> val)
2602 : {
2603 : // DTC register definition was removed, all DTC versions only were returning constant value
2604 0 : auto freq = 0x09502f90; // 156.25mhz // ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, val);
2605 :
2606 : // Clocks should be accurate to 30 ppm
2607 0 : if (freq > 156250000 - 4687.5 && freq < 156250000 + 4687.5) return DTC_SerdesClockSpeed_3125Gbps;
2608 0 : if (freq > 125000000 - 3750 && freq < 125000000 + 3750) return DTC_SerdesClockSpeed_25Gbps;
2609 0 : return DTC_SerdesClockSpeed_Unknown;
2610 : }
2611 : /// <summary>
2612 : /// Set the SERDES Oscillator clock speed for the given SERDES transfer rate
2613 : /// </summary>
2614 : /// <param name="speed">Clock speed to set</param>
2615 0 : void DTCLib::DTC_Registers::SetSERDESOscillatorClock(DTC_SerdesClockSpeed speed)
2616 : {
2617 : double targetFreq;
2618 0 : switch (speed)
2619 : {
2620 0 : case DTC_SerdesClockSpeed_25Gbps:
2621 0 : targetFreq = 125000000.0;
2622 0 : break;
2623 0 : case DTC_SerdesClockSpeed_3125Gbps:
2624 0 : targetFreq = 156250000.0;
2625 0 : break;
2626 0 : default:
2627 0 : targetFreq = 0.0;
2628 0 : break;
2629 : }
2630 0 : if (SetNewOscillatorFrequency(DTC_OscillatorType_SERDES, targetFreq))
2631 : {
2632 0 : for (auto& link : DTC_ROC_Links)
2633 : {
2634 0 : ResetSERDES(link, 1000);
2635 : }
2636 0 : ResetSERDES(DTC_Link_CFO, 1000);
2637 : // ResetSERDES(DTC_Link_EVB, 1000);
2638 : }
2639 0 : }
2640 :
2641 : /// <summary>
2642 : /// Set the Timing Oscillator clock to a given frequency
2643 : /// </summary>
2644 : /// <param name="freq">Frequency to set the Timing card Oscillator clock</param>
2645 0 : void DTCLib::DTC_Registers::SetTimingOscillatorClock(uint32_t freq)
2646 : {
2647 0 : double targetFreq = freq;
2648 0 : if (SetNewOscillatorFrequency(DTC_OscillatorType_Timing, targetFreq))
2649 : {
2650 0 : ResetSERDES(DTC_Link_CFO, 1000);
2651 : // ResetSERDES(DTC_Link_EVB, 1000);
2652 : }
2653 0 : }
2654 :
2655 : // /// <summary>
2656 : // /// Formats the register's current value for register dumps
2657 : // /// </summary>
2658 : // /// <returns>RegisterFormatter object containing register information</returns>
2659 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTimingSERDESOscillatorFrequency()
2660 : // {
2661 : // auto form = CreateFormatter(DTC_Register_SERDESTimingCardOscillatorFrequency);
2662 : // form.description = "SERDES Timing Card Oscillator Reference Frequency";
2663 : // std::stringstream o;
2664 : // o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_CFO, form.value);
2665 : // form.vals.push_back(o.str());
2666 : // return form;
2667 : // }
2668 :
2669 : // /// <summary>
2670 : // /// Formats the register's current value for register dumps
2671 : // /// </summary>
2672 : // /// <returns>RegisterFormatter object containing register information</returns>
2673 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMainBoardSERDESOscillatorFrequency()
2674 : // {
2675 : // auto form = CreateFormatter(DTC_Register_SERDESReferenceClockFrequency);
2676 : // form.description = "SERDES Main Board Oscillator Reference Frequency";
2677 : // std::stringstream o;
2678 : // o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, form.value);
2679 : // form.vals.push_back(o.str());
2680 : // return form;
2681 : // }
2682 : /// <summary>
2683 : /// Formats the register's current value for register dumps
2684 : /// </summary>
2685 : /// <returns>RegisterFormatter object containing register information</returns>
2686 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESOscillatorControl()
2687 : {
2688 0 : auto form = CreateFormatter(DTC_Register_SERDESClock_IICBusControl);
2689 0 : form.description = "SERDES Oscillator IIC Bus Control";
2690 0 : form.vals.push_back(std::string("Reset: [") + (ReadSERDESOscillatorIICInterfaceReset(form.value) ? "x" : " ") + "]");
2691 0 : return form;
2692 0 : }
2693 :
2694 : // FIFO Full Error Flags Registers
2695 : /// <summary>
2696 : /// Clear all FIFO Full Error Flags for the given link
2697 : /// </summary>
2698 : /// <param name="link">Link to clear</param>
2699 0 : void DTCLib::DTC_Registers::ClearFIFOFullErrorFlags(DTC_Link_ID const& link)
2700 : {
2701 0 : auto flags = ReadFIFOFullErrorFlags(link);
2702 0 : std::bitset<32> data0 = 0;
2703 0 : std::bitset<32> data1 = 0;
2704 0 : std::bitset<32> data2 = 0;
2705 :
2706 0 : data0[link] = flags.OutputData;
2707 0 : data0[link + 8] = flags.CFOLinkInput;
2708 0 : data0[link + 16] = flags.ReadoutRequestOutput;
2709 0 : data0[link + 24] = flags.DataRequestOutput;
2710 0 : data1[link] = flags.OtherOutput;
2711 0 : data1[link + 8] = flags.OutputDCS;
2712 0 : data1[link + 16] = flags.OutputDCSStage2;
2713 0 : data1[link + 24] = flags.DataInput;
2714 0 : data2[link] = flags.DCSStatusInput;
2715 :
2716 0 : WriteRegister_(data0.to_ulong(), DTC_Register_FIFOFullErrorFlag0);
2717 0 : WriteRegister_(data1.to_ulong(), DTC_Register_FIFOFullErrorFlag1);
2718 0 : WriteRegister_(data2.to_ulong(), DTC_Register_FIFOFullErrorFlag2);
2719 0 : }
2720 :
2721 : /// <summary>
2722 : /// Read the FIFO Full Error/Status Flags for the given link
2723 : /// </summary>
2724 : /// <param name="link">Link to read</param>
2725 : /// <returns>DTC_FIFOFullErrorFlags object</returns>
2726 0 : DTCLib::DTC_FIFOFullErrorFlags DTCLib::DTC_Registers::ReadFIFOFullErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val0,
2727 : std::optional<uint32_t> val1, std::optional<uint32_t> val2)
2728 : {
2729 0 : std::bitset<32> data0 = val0.has_value() ? *val0 : ReadRegister_(DTC_Register_FIFOFullErrorFlag0);
2730 0 : std::bitset<32> data1 = val1.has_value() ? *val1 : ReadRegister_(DTC_Register_FIFOFullErrorFlag1);
2731 0 : std::bitset<32> data2 = val2.has_value() ? *val2 : ReadRegister_(DTC_Register_FIFOFullErrorFlag2);
2732 0 : DTC_FIFOFullErrorFlags flags;
2733 :
2734 0 : flags.OutputData = data0[link];
2735 0 : flags.CFOLinkInput = data0[link + 8];
2736 0 : flags.ReadoutRequestOutput = data0[link + 16];
2737 0 : flags.DataRequestOutput = data0[link + 24];
2738 0 : flags.OtherOutput = data1[link];
2739 0 : flags.OutputDCS = data1[link + 8];
2740 0 : flags.OutputDCSStage2 = data1[link + 16];
2741 0 : flags.DataInput = data1[link + 24];
2742 0 : flags.DCSStatusInput = data2[link];
2743 :
2744 0 : return flags;
2745 : }
2746 :
2747 : /// <summary>
2748 : /// Formats the register's current value for register dumps
2749 : /// </summary>
2750 : /// <returns>RegisterFormatter object containing register information</returns>
2751 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag0()
2752 : {
2753 0 : auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag0);
2754 0 : form.description = "FIFO Full Error Flags 0";
2755 0 : form.vals.push_back(" ([DataRequest, ReadoutRequest, CFOLink, OutputData])");
2756 0 : for (auto r : DTC_ROC_Links)
2757 : {
2758 0 : auto re = ReadFIFOFullErrorFlags(r, form.value);
2759 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataRequestOutput ? "x" : " ") + "," +
2760 0 : (re.ReadoutRequestOutput ? "x" : " ") + "," + (re.CFOLinkInput ? "x" : " ") + "," +
2761 0 : (re.OutputData ? "x" : " ") + "]");
2762 : }
2763 0 : return form;
2764 0 : }
2765 :
2766 : /// <summary>
2767 : /// Formats the register's current value for register dumps
2768 : /// </summary>
2769 : /// <returns>RegisterFormatter object containing register information</returns>
2770 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag1()
2771 : {
2772 0 : auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag1);
2773 0 : form.description = "FIFO Full Error Flags 1";
2774 0 : form.vals.push_back(" ([DataInput, OutputDCSStage2, OutputDCS, OtherOutput])");
2775 0 : for (auto r : DTC_ROC_Links)
2776 : {
2777 0 : auto re = ReadFIFOFullErrorFlags(r, form.value);
2778 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataInput ? "x" : " ") + "," +
2779 0 : (re.OutputDCSStage2 ? "x" : " ") + "," + (re.OutputDCS ? "x" : " ") + "," +
2780 0 : (re.OtherOutput ? "x" : " ") + "]");
2781 : }
2782 : {
2783 0 : auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
2784 0 : form.vals.push_back(std::string("CFO: [") + +(ce.DataInput ? "x" : " ") + "," +
2785 0 : (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
2786 0 : (ce.OtherOutput ? "x" : " ") + "]");
2787 : }
2788 : {
2789 0 : auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
2790 0 : form.vals.push_back(std::string("EVB: [") + +(ce.DataInput ? "x" : " ") + "," +
2791 0 : (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
2792 0 : (ce.OtherOutput ? "x" : " ") + "]");
2793 : }
2794 0 : return form;
2795 0 : }
2796 :
2797 : /// <summary>
2798 : /// Formats the register's current value for register dumps
2799 : /// </summary>
2800 : /// <returns>RegisterFormatter object containing register information</returns>
2801 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag2()
2802 : {
2803 0 : auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag2);
2804 0 : form.description = "FIFO Full Error Flags 2";
2805 0 : form.vals.push_back(" ([DCSStatusInput])");
2806 0 : for (auto r : DTC_ROC_Links)
2807 : {
2808 0 : auto re = ReadFIFOFullErrorFlags(r, form.value);
2809 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DCSStatusInput ? "x" : " ") + "]");
2810 : }
2811 : {
2812 0 : auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
2813 0 : form.vals.push_back(std::string("CFO: [") + (ce.DCSStatusInput ? "x" : " ") + "]");
2814 : }
2815 : {
2816 0 : auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
2817 0 : form.vals.push_back(std::string("EVB: [") + (ce.DCSStatusInput ? "x" : " ") + "]");
2818 : }
2819 0 : return form;
2820 0 : }
2821 :
2822 : // Receive Packet Error Register
2823 : /// <summary>
2824 : /// Clear the Packet Error Flag for the given link
2825 : /// </summary>
2826 : /// <param name="link">Link to clear</param>
2827 0 : void DTCLib::DTC_Registers::ClearPacketError(DTC_Link_ID const& link)
2828 : {
2829 0 : std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
2830 0 : data[static_cast<int>(link) + 8] = 0;
2831 0 : WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
2832 0 : }
2833 :
2834 : /// <summary>
2835 : /// Read the Packet Error Flag for the given link
2836 : /// </summary>
2837 : /// <param name="link">Link to read</param>
2838 : /// <returns>True if the Packet Error Flag is set</returns>
2839 0 : bool DTCLib::DTC_Registers::ReadPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
2840 : {
2841 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
2842 0 : return data[static_cast<int>(link) + 8];
2843 : }
2844 :
2845 : /// <summary>
2846 : /// Clear the Packet CRC Error Flag for the given link
2847 : /// </summary>
2848 : /// <param name="link">Link to clear</param>
2849 0 : void DTCLib::DTC_Registers::ClearPacketCRCError(DTC_Link_ID const& link)
2850 : {
2851 0 : std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
2852 0 : data[static_cast<int>(link)] = 0;
2853 0 : WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
2854 0 : }
2855 :
2856 : /// <summary>
2857 : /// Read the Packet CRC Error Flag for the given link
2858 : /// </summary>
2859 : /// <param name="link">Link to read</param>
2860 : /// <returns>True if the Packet CRC Error Flag is set</returns>
2861 0 : bool DTCLib::DTC_Registers::ReadPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
2862 : {
2863 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
2864 0 : return data[static_cast<int>(link)];
2865 : }
2866 :
2867 : /// <summary>
2868 : /// Formats the register's current value for register dumps
2869 : /// </summary>
2870 : /// <returns>RegisterFormatter object containing register information</returns>
2871 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatReceivePacketError()
2872 : {
2873 0 : auto form = CreateFormatter(DTC_Register_ReceivePacketError);
2874 0 : form.description = "Receive Packet Error";
2875 0 : form.vals.push_back(" ([CRC, PacketError])");
2876 0 : for (auto r : DTC_ROC_Links)
2877 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
2878 0 : (ReadPacketCRCError(r, form.value) ? "x" : " ") + "," +
2879 0 : (ReadPacketError(r, form.value) ? "x" : " ") + "]");
2880 0 : form.vals.push_back(std::string("CFO: [") +
2881 0 : (ReadPacketCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
2882 0 : (ReadPacketError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
2883 0 : form.vals.push_back(std::string("EVB: [") +
2884 0 : (ReadPacketCRCError(DTC_Link_EVB, form.value) ? "x" : " ") + "," +
2885 0 : (ReadPacketError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
2886 0 : return form;
2887 0 : }
2888 :
2889 : // CFO Emulation Timestamp Registers
2890 : /// <summary>
2891 : /// Set the starting DTC_EventWindowTag for the CFO Emulator
2892 : /// </summary>
2893 : /// <param name="ts">Starting Timestamp for CFO Emulation</param>
2894 0 : void DTCLib::DTC_Registers::SetCFOEmulationTimestamp(const DTC_EventWindowTag& ts)
2895 : {
2896 0 : auto timestamp = ts.GetEventWindowTag();
2897 0 : auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
2898 0 : timestamp >>= 32;
2899 0 : auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
2900 :
2901 0 : WriteRegister_(timestampLow, DTC_Register_CFOEmulation_TimestampLow);
2902 0 : WriteRegister_(timestampHigh, DTC_Register_CFOEmulation_TimestampHigh);
2903 0 : }
2904 :
2905 : /// <summary>
2906 : /// Read the starting DTC_EventWindowTag for the CFO Emulator
2907 : /// </summary>
2908 : /// <returns>DTC_EventWindowTag object</returns>
2909 0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadCFOEmulationTimestamp(std::optional<uint32_t> val)
2910 : {
2911 0 : auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
2912 0 : DTC_EventWindowTag output;
2913 0 : output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh)));
2914 0 : return output;
2915 0 : }
2916 :
2917 : /// <summary>
2918 : /// Formats the register's current value for register dumps
2919 : /// </summary>
2920 : /// <returns>RegisterFormatter object containing register information</returns>
2921 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampLow()
2922 : {
2923 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampLow);
2924 0 : form.description = "CFO Emulation Timestamp Low";
2925 0 : std::stringstream o;
2926 0 : o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
2927 0 : form.vals.push_back(o.str());
2928 0 : return form;
2929 0 : }
2930 :
2931 : /// <summary>
2932 : /// Formats the register's current value for register dumps
2933 : /// </summary>
2934 : /// <returns>RegisterFormatter object containing register information</returns>
2935 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampHigh()
2936 : {
2937 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampHigh);
2938 0 : form.description = "CFO Emulation Timestamp High";
2939 0 : std::stringstream o;
2940 0 : o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh);
2941 0 : form.vals.push_back(o.str());
2942 0 : return form;
2943 0 : }
2944 :
2945 : // CFO Emulation Delay Measure
2946 : /// <summary>
2947 : /// Read the Delay Measure acquired with the CFO Emulator Loopback Test
2948 : /// </summary>
2949 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationLoopbackDelayMeasure(std::optional<uint32_t> val)
2950 : {
2951 0 : uint32_t readVal = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
2952 0 : uint32_t i = 0;
2953 0 : while (!(readVal >> 31))
2954 : {
2955 0 : if (i > 1000)
2956 : {
2957 0 : __SS__ << "Timeout looking for the CFO Emulator Loopback Test to complete... readval: 0x" << std::hex << readVal << __E__;
2958 0 : __SS_THROW__;
2959 0 : }
2960 :
2961 0 : usleep(10000);
2962 0 : readVal = ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
2963 0 : ++i;
2964 : }
2965 0 : return readVal & (~(1 << 31)); // clear the Ready bit from return value
2966 : }
2967 :
2968 : /// <summary>
2969 : /// Formats the register's current value for register dumps
2970 : /// </summary>
2971 : /// <returns>RegisterFormatter object containing register information</returns>
2972 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationLoopbackDelayMeasure()
2973 : {
2974 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
2975 0 : form.description = "CFO Emu. Loopback Delay Measure";
2976 0 : std::stringstream o;
2977 0 : o << "0x" << std::hex << ReadCFOEmulationLoopbackDelayMeasure(form.value) << std::dec << "(" << double(1.0) * ReadCFOEmulationLoopbackDelayMeasure(form.value) * 5 /*ns for 200MHz period*/ / 8.0 /* for 8 samples */ << " ns)";
2978 0 : form.vals.push_back(o.str());
2979 0 : return form;
2980 0 : }
2981 :
2982 : // CFO Emulation Request Interval Register
2983 : /// <summary>
2984 : /// Set the clock interval between CFO Emulator Event Windows.
2985 : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
2986 : /// </summary>
2987 : /// <param name="interval">Clock cycles between Event Window Markers</param>
2988 0 : void DTCLib::DTC_Registers::SetCFOEmulationEventWindowInterval(uint32_t interval)
2989 : {
2990 0 : WriteRegister_(interval, DTC_Register_CFOEmulation_HeartbeatInterval);
2991 0 : }
2992 :
2993 : /// <summary>
2994 : /// Read the clock interval between CFO Emulator Event Windows.
2995 : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
2996 : /// </summary>
2997 : /// <returns>Clock cycles between Event Window Markers</returns>
2998 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationEventWindowInterval(std::optional<uint32_t> val)
2999 : {
3000 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_HeartbeatInterval);
3001 : }
3002 :
3003 : /// <summary>
3004 : /// Formats the register's current value for register dumps
3005 : /// </summary>
3006 : /// <returns>RegisterFormatter object containing register information</returns>
3007 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationEventWindowInterval()
3008 : {
3009 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_HeartbeatInterval);
3010 0 : form.description = "CFO Emu. EWM Interval";
3011 0 : std::stringstream o;
3012 0 : o << "0x" << std::hex << ReadCFOEmulationEventWindowInterval(form.value);
3013 0 : form.vals.push_back(o.str());
3014 0 : return form;
3015 0 : }
3016 :
3017 : // CFO Emulation Number of Requests Register
3018 : /// <summary>
3019 : /// Set the number of Readout Requests the CFO Emulator is configured to send.
3020 : /// A value of 0 means that the CFO Emulator will send requests continuously.
3021 : /// </summary>
3022 : /// <param name="NumHeartbeats">Number of Readout Requests the CFO Emulator will send</param>
3023 0 : void DTCLib::DTC_Registers::SetCFOEmulationNumHeartbeats(uint32_t NumHeartbeats)
3024 : {
3025 0 : WriteRegister_(NumHeartbeats, DTC_Register_CFOEmulation_NumHeartbeats);
3026 0 : }
3027 :
3028 : /// <summary>
3029 : /// Reads the number of Readout Requests the CFO Emulator is configured to send.
3030 : /// A value of 0 means that the CFO Emulator will send requests continuously.
3031 : /// </summary>
3032 : /// <returns>Number of Readout Requests the CFO Emulator will send</returns>
3033 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumHeartbeats(std::optional<uint32_t> val)
3034 : {
3035 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumHeartbeats);
3036 : }
3037 :
3038 : /// <summary>
3039 : /// Formats the register's current value for register dumps
3040 : /// </summary>
3041 : /// <returns>RegisterFormatter object containing register information</returns>
3042 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumHeartbeats()
3043 : {
3044 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_NumHeartbeats);
3045 0 : form.description = "CFO Emulator Number Requests";
3046 0 : std::stringstream o;
3047 0 : o << "0x" << std::hex << ReadCFOEmulationNumHeartbeats(form.value);
3048 0 : form.vals.push_back(o.str());
3049 0 : return form;
3050 0 : }
3051 :
3052 : // CFO Emulation Number of Packets Registers
3053 : /// <summary>
3054 : /// Set the number of packets the CFO Emulator will request from the link
3055 : /// </summary>
3056 : /// <param name="link">Link to set</param>
3057 : /// <param name="numPackets">Number of packets to request</param>
3058 0 : void DTCLib::DTC_Registers::SetROCEmulationNumPackets(DTC_Link_ID const& link_in, uint16_t numPackets)
3059 : {
3060 0 : uint16_t data = numPackets & 0x7FF;
3061 : DTC_Register reg;
3062 :
3063 0 : for (const auto& link : DTC_ROC_Links)
3064 : {
3065 0 : if (!(link_in == DTC_Link_ALL || link_in == link))
3066 0 : continue; // skip ROC links that should not be set
3067 :
3068 0 : switch (link)
3069 : {
3070 0 : case DTC_Link_0:
3071 : case DTC_Link_1:
3072 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
3073 0 : break;
3074 0 : case DTC_Link_2:
3075 : case DTC_Link_3:
3076 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
3077 0 : break;
3078 0 : case DTC_Link_4:
3079 : case DTC_Link_5:
3080 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
3081 0 : break;
3082 0 : default: {
3083 0 : __SS__ << "Illegal link " << link << " specified." << __E__;
3084 0 : __SS_THROW__;
3085 0 : }
3086 : }
3087 :
3088 0 : auto regval = ReadRegister_(reg);
3089 0 : auto upper = (regval & 0xFFFF0000) >> 16;
3090 0 : auto lower = regval & 0x0000FFFF;
3091 0 : if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
3092 : {
3093 0 : lower = data;
3094 : }
3095 : else
3096 : {
3097 0 : upper = data;
3098 : }
3099 0 : WriteRegister_((upper << 16) + lower, reg);
3100 : } // end link write loop
3101 0 : }
3102 :
3103 : /// <summary>
3104 : /// Read the requested number of packets the ROC Emulator will generate from the given link
3105 : /// </summary>
3106 : /// <param name="link">Link to read</param>
3107 : /// <returns>Number of packets generated by the ROC Emulator</returns>
3108 0 : uint16_t DTCLib::DTC_Registers::ReadROCEmulationNumPackets(DTC_Link_ID const& link, std::optional<uint32_t> val)
3109 : {
3110 : DTC_Register reg;
3111 0 : switch (link)
3112 : {
3113 0 : case DTC_Link_0:
3114 : case DTC_Link_1:
3115 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
3116 0 : break;
3117 0 : case DTC_Link_2:
3118 : case DTC_Link_3:
3119 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
3120 0 : break;
3121 0 : case DTC_Link_4:
3122 : case DTC_Link_5:
3123 0 : reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
3124 0 : break;
3125 0 : default: {
3126 0 : __SS__ << "Illegal link " << link << " specified." << __E__;
3127 0 : __SS_THROW__;
3128 0 : }
3129 : }
3130 :
3131 0 : auto regval = val.has_value() ? *val : ReadRegister_(reg);
3132 0 : auto upper = (regval & 0xFFFF0000) >> 16;
3133 0 : auto lower = regval & 0x0000FFFF;
3134 0 : if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
3135 : {
3136 0 : return static_cast<uint16_t>(lower);
3137 : }
3138 0 : return static_cast<uint16_t>(upper);
3139 : }
3140 :
3141 : /// <summary>
3142 : /// Formats the register's current value for register dumps
3143 : /// </summary>
3144 : /// <returns>RegisterFormatter object containing register information</returns>
3145 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink01()
3146 : {
3147 0 : auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks10);
3148 0 : form.description = "ROC Emulator Num Packets R0,1";
3149 0 : form.vals.push_back(""); // translation
3150 0 : std::stringstream o;
3151 0 : o << "Link 0: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_0, form.value);
3152 0 : form.vals.push_back(o.str());
3153 0 : o.str("");
3154 0 : o.clear();
3155 0 : o << "Link 1: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_1, form.value);
3156 0 : form.vals.push_back(o.str());
3157 0 : return form;
3158 0 : }
3159 :
3160 : /// <summary>
3161 : /// Formats the register's current value for register dumps
3162 : /// </summary>
3163 : /// <returns>RegisterFormatter object containing register information</returns>
3164 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink23()
3165 : {
3166 0 : auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks32);
3167 0 : form.description = "ROC Emulator Num Packets R2,3";
3168 0 : form.vals.push_back(""); // translation
3169 0 : std::stringstream o;
3170 0 : o << "Link 2: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_2, form.value);
3171 0 : form.vals.push_back(o.str());
3172 0 : o.str("");
3173 0 : o.clear();
3174 0 : o << "Link 3: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_3, form.value);
3175 0 : form.vals.push_back(o.str());
3176 0 : return form;
3177 0 : }
3178 :
3179 : /// <summary>
3180 : /// Formats the register's current value for register dumps
3181 : /// </summary>
3182 : /// <returns>RegisterFormatter object containing register information</returns>
3183 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink45()
3184 : {
3185 0 : auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks54);
3186 0 : form.description = "ROC Emulator Num Packets R4,5";
3187 0 : form.vals.push_back(""); // translation
3188 0 : std::stringstream o;
3189 0 : o << "Link 4: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_4, form.value);
3190 0 : form.vals.push_back(o.str());
3191 0 : o.str("");
3192 0 : o.clear();
3193 0 : o << "Link 5: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_5, form.value);
3194 0 : form.vals.push_back(o.str());
3195 0 : return form;
3196 0 : }
3197 :
3198 : // CFO Emulation Number of Null Heartbeats Register
3199 : /// <summary>
3200 : /// Set the number of null heartbeats the CFO Emulator will generate following the requested ones
3201 : /// </summary>
3202 : /// <param name="count">Number of null heartbeats to generate</param>
3203 0 : void DTCLib::DTC_Registers::SetCFOEmulationNumNullHeartbeats(const uint32_t& count)
3204 : {
3205 0 : WriteRegister_(count, DTC_Register_CFOEmulation_NumNullHeartbeats);
3206 0 : }
3207 :
3208 : /// <summary>
3209 : /// Read the requested number of null heartbeats that will follow the configured heartbeats from the CFO Emulator
3210 : /// </summary>
3211 : /// <returns>Number of null heartbeats to follow "live" heartbeats</returns>
3212 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumNullHeartbeats(std::optional<uint32_t> val)
3213 : {
3214 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumNullHeartbeats);
3215 : }
3216 :
3217 : /// <summary>
3218 : /// Formats the register's current value for register dumps
3219 : /// </summary>
3220 : /// <returns>RegisterFormatter object containing register information</returns>
3221 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumNullHeartbeats()
3222 : {
3223 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_NumNullHeartbeats);
3224 0 : form.description = "CFO Emulator Num Null Heartbeats";
3225 0 : form.vals.push_back(std::to_string(ReadCFOEmulationNumNullHeartbeats(form.value)));
3226 0 : return form;
3227 0 : }
3228 :
3229 0 : void DTCLib::DTC_Registers::SetCFOEventModeRequiredMask(const uint32_t& mask)
3230 : {
3231 0 : WriteRegister_(mask, DTC_Register_CFOEventModeRequiredMask);
3232 0 : }
3233 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEventModeRequiredMask(std::optional<uint32_t> val)
3234 : {
3235 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEventModeRequiredMask);
3236 : }
3237 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEventModeRequiredMask()
3238 : {
3239 0 : auto form = CreateFormatter(DTC_Register_CFOEventModeRequiredMask);
3240 0 : form.description = "CFO Emulation Event Mode Required Mask";
3241 0 : std::stringstream o;
3242 0 : o << "0x" << std::hex << ReadCFOEventModeRequiredMask(form.value);
3243 0 : form.vals.push_back(o.str());
3244 0 : return form;
3245 0 : }
3246 :
3247 : // CFO Emulation Event Mode Bytes Registers
3248 : /// <summary>
3249 : /// Set the CFO Emulation Event Mode 48 bits
3250 : /// </summary>
3251 0 : void DTCLib::DTC_Registers::SetCFOEmulationEventMode(const uint64_t& eventMode)
3252 : {
3253 0 : WriteRegister_(eventMode, DTC_Register_CFOEmulation_EventMode1);
3254 0 : WriteRegister_(eventMode >> 32, DTC_Register_CFOEmulation_EventMode2);
3255 0 : }
3256 0 : uint64_t DTCLib::DTC_Registers::ReadCFOEmulationEventMode()
3257 : {
3258 0 : uint64_t eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode2);
3259 0 : eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode1) |
3260 0 : (eventMode << 32);
3261 0 : return eventMode;
3262 : }
3263 :
3264 : /// <summary>
3265 : /// Set the given CFO Emulation Mode byte to the given value
3266 : /// </summary>
3267 : /// <param name="byteNum">Byte to set. Valid range is 0-5</param>
3268 : /// <param name="data">Data for byte</param>
3269 0 : void DTCLib::DTC_Registers::SetCFOEmulationModeByte(const uint8_t& byteNum, uint8_t data)
3270 : {
3271 : DTC_Register reg;
3272 0 : if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
3273 : {
3274 0 : reg = DTC_Register_CFOEmulation_EventMode1;
3275 : }
3276 0 : else if (byteNum == 4 || byteNum == 5)
3277 : {
3278 0 : reg = DTC_Register_CFOEmulation_EventMode2;
3279 : }
3280 : else
3281 : {
3282 0 : __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
3283 0 : __SS_THROW__;
3284 0 : }
3285 0 : auto regVal = ReadRegister_(reg);
3286 :
3287 0 : switch (byteNum)
3288 : {
3289 0 : case 0:
3290 0 : regVal = (regVal & 0xFFFFFF00) + data;
3291 0 : break;
3292 0 : case 1:
3293 0 : regVal = (regVal & 0xFFFF00FF) + (data << 8);
3294 0 : break;
3295 0 : case 2:
3296 0 : regVal = (regVal & 0xFF00FFFF) + (data << 16);
3297 0 : break;
3298 0 : case 3:
3299 0 : regVal = (regVal & 0x00FFFFFF) + (data << 24);
3300 0 : break;
3301 0 : case 4:
3302 0 : regVal = (regVal & 0xFF00) + data;
3303 0 : break;
3304 0 : case 5:
3305 0 : regVal = (regVal & 0x00FF) + (data << 8);
3306 0 : break;
3307 0 : default:
3308 : // impossible
3309 : {
3310 0 : __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
3311 0 : __SS_THROW__;
3312 0 : }
3313 : }
3314 :
3315 0 : WriteRegister_(regVal, reg);
3316 0 : }
3317 :
3318 : /// <summary>
3319 : /// Read the given CFO Emulation Mode byte
3320 : /// </summary>
3321 : /// <param name="byteNum">Byte to read. Valid range is 0-5</param>
3322 : /// <returns>Current value of the mode byte</returns>
3323 0 : uint8_t DTCLib::DTC_Registers::ReadCFOEmulationModeByte(const uint8_t& byteNum, std::optional<uint32_t> val)
3324 : {
3325 : DTC_Register reg;
3326 0 : if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
3327 : {
3328 0 : reg = DTC_Register_CFOEmulation_EventMode1;
3329 : }
3330 0 : else if (byteNum == 4 || byteNum == 5)
3331 : {
3332 0 : reg = DTC_Register_CFOEmulation_EventMode2;
3333 : }
3334 : else
3335 : {
3336 0 : __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
3337 0 : __SS_THROW__;
3338 0 : }
3339 0 : auto regVal = val.has_value() ? *val : ReadRegister_(reg);
3340 :
3341 0 : switch (byteNum)
3342 : {
3343 0 : case 0:
3344 0 : return static_cast<uint8_t>(regVal & 0xFF);
3345 0 : case 1:
3346 0 : return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
3347 0 : case 2:
3348 0 : return static_cast<uint8_t>((regVal & 0xFF0000) >> 16);
3349 0 : case 3:
3350 0 : return static_cast<uint8_t>((regVal & 0xFF000000) >> 24);
3351 0 : case 4:
3352 0 : return static_cast<uint8_t>(regVal & 0xFF);
3353 0 : case 5:
3354 0 : return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
3355 0 : default:
3356 : // impossible
3357 : {
3358 0 : __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
3359 0 : __SS_THROW__;
3360 0 : }
3361 : }
3362 : }
3363 :
3364 : /// <summary>
3365 : /// Formats the register's current value for register dumps
3366 : /// </summary>
3367 : /// <returns>RegisterFormatter object containing register information</returns>
3368 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes03()
3369 : {
3370 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode1);
3371 0 : form.description = "CFO Emulation Event Mode Bytes 0-3";
3372 0 : form.vals.push_back(""); // translation
3373 0 : std::ostringstream o;
3374 0 : o << "Byte 0: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(0, form.value));
3375 0 : form.vals.push_back(o.str());
3376 0 : o.str("");
3377 0 : o.clear();
3378 0 : o << "Byte 1: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(1, form.value));
3379 0 : form.vals.push_back(o.str());
3380 0 : o.str("");
3381 0 : o.clear();
3382 0 : o << "Byte 2: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(2, form.value));
3383 0 : form.vals.push_back(o.str());
3384 0 : o.str("");
3385 0 : o.clear();
3386 0 : o << "Byte 3: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(3, form.value));
3387 0 : form.vals.push_back(o.str());
3388 0 : return form;
3389 0 : }
3390 :
3391 : /// <summary>
3392 : /// Formats the register's current value for register dumps
3393 : /// </summary>
3394 : /// <returns>RegisterFormatter object containing register information</returns>
3395 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes45()
3396 : {
3397 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode2);
3398 0 : form.description = "CFO Emulation Event Mode Bytes 4-5";
3399 0 : form.vals.push_back(""); // translation
3400 0 : std::ostringstream o;
3401 0 : o << "Byte 4: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(4, form.value));
3402 0 : form.vals.push_back(o.str());
3403 0 : o.str("");
3404 0 : o.clear();
3405 0 : o << "Byte 5: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(5, form.value));
3406 0 : form.vals.push_back(o.str());
3407 0 : o.str("");
3408 0 : o.clear();
3409 0 : return form;
3410 0 : }
3411 :
3412 : /// <summary>
3413 : /// Set the DebugType used by the CFO Emulator
3414 : /// </summary>
3415 : /// <param name="type">The DTC_DebugType the CFO Emulator will fill into Readout Requests</param>
3416 : // void DTCLib::DTC_Registers::SetCFOEmulationDebugType(DTC_DebugType type)
3417 : //{
3418 : // std::bitset<32> data = type & 0xF;
3419 : // data[16] = ReadDebugPacketMode();
3420 : // WriteRegister_(data.to_ulong(), DTC_Register_DebugPacketType);
3421 : // }
3422 :
3423 : /// <summary>
3424 : /// Read the DebugType field filled into Readout Requests generated by the CFO Emulator
3425 : /// </summary>
3426 : /// <returns>The DTC_DebugType used by the CFO Emulator</returns>
3427 : // DTCLib::DTC_DebugType DTCLib::DTC_Registers::ReadCFOEmulationDebugType(std::optional<uint32_t> val)
3428 : //{
3429 : // return static_cast<DTC_DebugType>((0xFFFF & val.has_value()) ? *val : ReadRegister_(DTC_Register_DebugPacketType));
3430 : // }
3431 :
3432 : /// <summary>
3433 : /// Formats the register's current value for register dumps
3434 : /// </summary>
3435 : /// <returns>RegisterFormatter object containing register information</returns>
3436 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationDebugPacketType()
3437 : //{
3438 : // auto form = CreateFormatter(DTC_Register_DebugPacketType);
3439 : // form.description = "CFO Emulation Debug Packet Type";
3440 : // form.vals.push_back("([ x = 1 (hi) ])"); // translation
3441 : // form.vals.push_back(std::string("Debug Mode: [") + (ReadDebugPacketMode(form.value) ? "x" : " ") + "]");
3442 : // std::stringstream o;
3443 : // o << "Debug Packet Type: 0x" << std::hex << ReadCFOEmulationDebugType(form.value);
3444 : // form.vals.push_back(o.str());
3445 : // return form;
3446 : // }
3447 :
3448 : // RX Packet Count Error Flags Register
3449 : /// <summary>
3450 : /// Read the RX Packet Count Error flag for the given link
3451 : /// </summary>
3452 : /// <param name="link">Link to read</param>
3453 : /// <returns>Whether the RX Packet Count Error flag is set on the link</returns>
3454 0 : bool DTCLib::DTC_Registers::ReadRXPacketCountErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val)
3455 : {
3456 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
3457 0 : return dataSet[link];
3458 : }
3459 :
3460 : /// <summary>
3461 : /// Clear the RX Packet Count Error flag for the given link
3462 : /// </summary>
3463 : /// <param name="link">Link to clear</param>
3464 0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags(DTC_Link_ID const& link)
3465 : {
3466 0 : std::bitset<32> dataSet;
3467 0 : dataSet[link] = true;
3468 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
3469 0 : }
3470 :
3471 : /// <summary>
3472 : /// Clear all RX Packet Count Error Flags
3473 : /// </summary>
3474 0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags()
3475 : {
3476 0 : std::bitset<32> dataSet = ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
3477 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
3478 0 : }
3479 :
3480 : /// <summary>
3481 : /// Formats the register's current value for register dumps
3482 : /// </summary>
3483 : /// <returns>RegisterFormatter object containing register information</returns>
3484 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXPacketCountErrorFlags()
3485 : {
3486 0 : auto form = CreateFormatter(DTC_Register_RXPacketCountErrorFlags);
3487 0 : form.description = "RX Packet Count Error Flags";
3488 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
3489 0 : for (auto r : DTC_ROC_Links)
3490 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
3491 0 : (ReadRXPacketCountErrorFlags(r, form.value) ? "x" : " ") + "]");
3492 0 : form.vals.push_back(std::string("CFO: [") + (ReadRXPacketCountErrorFlags(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
3493 0 : form.vals.push_back(std::string("EVB: [") + (ReadRXPacketCountErrorFlags(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
3494 0 : return form;
3495 0 : }
3496 :
3497 : // Detector Emulator DMA Count Register
3498 : /// <summary>
3499 : /// Set the number of DMAs that the Detector Emulator will generate when enabled
3500 : /// </summary>
3501 : /// <param name="count">The number of DMAs that the Detector Emulator will generate when enabled</param>
3502 0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMACount(uint32_t count)
3503 : {
3504 0 : WriteRegister_(count, DTC_Register_DetEmulation_DMACount);
3505 0 : }
3506 :
3507 : /// <summary>
3508 : /// Read the number of DMAs that the Detector Emulator will generate
3509 : /// </summary>
3510 : /// <returns>The number of DMAs that the Detector Emulator will generate</returns>
3511 0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMACount(std::optional<uint32_t> val)
3512 : {
3513 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DMACount);
3514 : }
3515 :
3516 : /// <summary>
3517 : /// Formats the register's current value for register dumps
3518 : /// </summary>
3519 : /// <returns>RegisterFormatter object containing register information</returns>
3520 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMACount()
3521 : {
3522 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_DMACount);
3523 0 : form.description = "DetEmu DMA Count";
3524 0 : std::stringstream o;
3525 0 : o << "0x" << std::hex << ReadDetectorEmulationDMACount(form.value);
3526 0 : form.vals.push_back(o.str());
3527 0 : return form;
3528 0 : }
3529 :
3530 : // Detector Emulator DMA Delay Counter Register
3531 : /// <summary>
3532 : /// Set the delay between DMAs in Detector Emulator mode
3533 : /// </summary>
3534 : /// <param name="count">Delay between DMAs in Detector Emulation mode, in 4ns ticks</param>
3535 0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMADelayCount(uint32_t count)
3536 : {
3537 0 : WriteRegister_(count, DTC_Register_DetEmulation_DelayCount);
3538 0 : }
3539 :
3540 : /// <summary>
3541 : /// Read the amount of the delay between DMAs in Detector Emulator mode
3542 : /// </summary>
3543 : /// <returns>The amount of the delay between DMAs in Detector Emulator mode, in 4ns ticks</returns>
3544 0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMADelayCount(std::optional<uint32_t> val)
3545 : {
3546 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DelayCount);
3547 : }
3548 :
3549 : /// <summary>
3550 : /// Formats the register's current value for register dumps
3551 : /// </summary>
3552 : /// <returns>RegisterFormatter object containing register information</returns>
3553 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMADelayCount()
3554 : {
3555 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_DelayCount);
3556 0 : form.description = "DetEmu DMA Delay Count";
3557 0 : std::stringstream o;
3558 0 : o << "0x" << std::hex << ReadDetectorEmulationDMADelayCount(form.value);
3559 0 : form.vals.push_back(o.str());
3560 0 : return form;
3561 0 : }
3562 :
3563 : /// <summary>
3564 : /// Enable Detector Emulator Mode. This sends all DMA writes to DMA channel 0 (DAQ) to DDR memory
3565 : /// </summary>
3566 0 : void DTCLib::DTC_Registers::EnableDetectorEmulatorMode()
3567 : {
3568 0 : std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
3569 0 : data[0] = 1;
3570 0 : WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
3571 0 : }
3572 :
3573 : /// <summary>
3574 : /// Disable sending DMA data to DDR memory
3575 : /// </summary>
3576 0 : void DTCLib::DTC_Registers::DisableDetectorEmulatorMode()
3577 : {
3578 0 : std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
3579 0 : data[0] = 0;
3580 0 : WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
3581 0 : }
3582 :
3583 : /// <summary>
3584 : /// Read whether writes to DMA Channel 0 will be loaded into DDR memory
3585 : /// </summary>
3586 : /// <returns>Whether the Detector Emulator Mode bit is set</returns>
3587 0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorMode(std::optional<uint32_t> val)
3588 : {
3589 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
3590 0 : return data[0];
3591 : }
3592 :
3593 : /// <summary>
3594 : /// Enable the Detector Emulator (Playback Mode)
3595 : /// This assumes that data has been loaded into DDR memory using DMA Channel 0 before enabling.
3596 : /// </summary>
3597 0 : void DTCLib::DTC_Registers::EnableDetectorEmulator()
3598 : {
3599 0 : std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
3600 0 : data[1] = 1;
3601 0 : WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
3602 0 : }
3603 :
3604 : /// <summary>
3605 : /// Turn off the Detector Emulator (Playback Mode)
3606 : /// </summary>
3607 0 : void DTCLib::DTC_Registers::DisableDetectorEmulator()
3608 : {
3609 0 : std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control1);
3610 0 : data[1] = 1;
3611 0 : WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control1);
3612 0 : }
3613 :
3614 : /// <summary>
3615 : /// Read whether the Detector Emulator is enabled
3616 : /// </summary>
3617 : /// <returns>Whether the Detector Emulator is enabled</returns>
3618 0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnable(std::optional<uint32_t> val)
3619 : {
3620 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
3621 0 : return data[1];
3622 : }
3623 :
3624 : /// <summary>
3625 : /// Read whether a Detector Emulator Disable operation is in progress
3626 : /// </summary>
3627 : /// <returns>Whether the Detector Emulator Enable Clear bit is set</returns>
3628 0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnableClear(std::optional<uint32_t> val)
3629 : {
3630 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control1);
3631 0 : return data[1];
3632 : }
3633 :
3634 : /// <summary>
3635 : /// Clear the "Detector Emulator In Use" virtual register
3636 : /// </summary>
3637 0 : void DTCLib::DTC_Registers::ClearDetectorEmulatorInUse()
3638 : {
3639 0 : DisableDetectorEmulator();
3640 0 : DisableDetectorEmulatorMode();
3641 0 : ResetDDRWriteAddress();
3642 0 : ResetDDRReadAddress();
3643 0 : SetDDRDataLocalStartAddress(0);
3644 0 : SetDDRDataLocalEndAddress(0x7000000);
3645 0 : usingDetectorEmulator_ = false;
3646 0 : }
3647 :
3648 : /// <summary>
3649 : /// Formats the register's current value for register dumps
3650 : /// </summary>
3651 : /// <returns>RegisterFormatter object containing register information</returns>
3652 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl0()
3653 : {
3654 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_Control0);
3655 0 : form.description = "Detector Emulation Control 0";
3656 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
3657 0 : form.vals.push_back(std::string("Detector Emulation Enable: [") + (ReadDetectorEmulatorEnable(form.value) ? "x" : " ") + "]");
3658 0 : form.vals.push_back(std::string("Detector Emulation Mode: [") + (ReadDetectorEmulatorMode(form.value) ? "x" : " ") + "]");
3659 0 : return form;
3660 0 : }
3661 :
3662 : /// <summary>
3663 : /// Formats the register's current value for register dumps
3664 : /// </summary>
3665 : /// <returns>RegisterFormatter object containing register information</returns>
3666 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl1()
3667 : {
3668 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_Control1);
3669 0 : form.description = "Detector Emulation Control 1";
3670 0 : form.vals.push_back(std::string("Detector Emulation Enable Clear: [") +
3671 0 : (ReadDetectorEmulatorEnableClear(form.value) ? "x" : " ") + "]");
3672 0 : return form;
3673 0 : }
3674 :
3675 : // DDR Event Data Local Start Address Register
3676 : /// <summary>
3677 : /// Set the DDR Data Start Address
3678 : /// DDR Addresses are in bytes and must be 64-bit aligned
3679 : /// </summary>
3680 : /// <param name="address">Start address for the DDR data section</param>
3681 0 : void DTCLib::DTC_Registers::SetDDRDataLocalStartAddress(uint32_t address)
3682 : {
3683 0 : WriteRegister_(address, DTC_Register_DetEmulation_DataStartAddress);
3684 0 : }
3685 :
3686 : /// <summary>
3687 : /// Read the DDR Data Start Address
3688 : /// </summary>
3689 : /// <returns>The current DDR data start address</returns>
3690 0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalStartAddress(std::optional<uint32_t> val)
3691 : {
3692 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataStartAddress);
3693 : }
3694 :
3695 : /// <summary>
3696 : /// Formats the register's current value for register dumps
3697 : /// </summary>
3698 : /// <returns>RegisterFormatter object containing register information</returns>
3699 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalStartAddress()
3700 : {
3701 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_DataStartAddress);
3702 0 : form.description = "DDR Event Data Local Start Address";
3703 0 : std::stringstream o;
3704 0 : o << "0x" << std::hex << ReadDDRDataLocalStartAddress(form.value);
3705 0 : form.vals.push_back(o.str());
3706 0 : return form;
3707 0 : }
3708 :
3709 : // DDR Event Data Local End Address Register
3710 : /// <summary>
3711 : /// Set the end address for the DDR data section
3712 : /// DDR Addresses are in bytes and must be 64-bit aligned
3713 : /// </summary>
3714 : /// <param name="address"></param>
3715 0 : void DTCLib::DTC_Registers::SetDDRDataLocalEndAddress(uint32_t address)
3716 : {
3717 0 : WriteRegister_(address, DTC_Register_DetEmulation_DataEndAddress);
3718 0 : }
3719 :
3720 : /// <summary>
3721 : /// Read the current end address for the DDR Data section
3722 : /// </summary>
3723 : /// <returns>End address for the DDR data section</returns>
3724 0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalEndAddress(std::optional<uint32_t> val)
3725 : {
3726 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataEndAddress);
3727 : }
3728 :
3729 : /// <summary>
3730 : /// Formats the register's current value for register dumps
3731 : /// </summary>
3732 : /// <returns>RegisterFormatter object containing register information</returns>
3733 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalEndAddress()
3734 : {
3735 0 : auto form = CreateFormatter(DTC_Register_DetEmulation_DataEndAddress);
3736 0 : form.description = "DDR Event Data Local End Address";
3737 0 : std::stringstream o;
3738 0 : o << "0x" << std::hex << ReadDDRDataLocalEndAddress(form.value);
3739 0 : form.vals.push_back(o.str());
3740 0 : return form;
3741 0 : }
3742 :
3743 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulatorInterpacketDelay(std::optional<uint32_t> val)
3744 : {
3745 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_DataRequestDelay);
3746 : }
3747 :
3748 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulatorInterpacketDelay()
3749 : {
3750 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_DataRequestDelay);
3751 0 : form.description = "CFO Emulator Data Request Interpacket Delay";
3752 0 : std::stringstream o;
3753 0 : o << std::dec << ReadCFOEmulatorInterpacketDelay(form.value) << " * 5 ns";
3754 0 : form.vals.push_back(o.str());
3755 0 : return form;
3756 0 : }
3757 :
3758 : /// <summary>
3759 : /// Read the current maximum Ethernet payload size
3760 : /// </summary>
3761 : /// <returns>The current maximum Ethernet payload size</returns>
3762 0 : uint32_t DTCLib::DTC_Registers::ReadEthernetPayloadSize(std::optional<uint32_t> val)
3763 : {
3764 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_EthernetFramePayloadSize);
3765 : }
3766 :
3767 : /// <summary>
3768 : /// Set the maximum Ethernet payload size, in bytes. Maximum is 1492 bytes.
3769 : /// </summary>
3770 : /// <param name="size">Maximum Ethernet payload size, in bytes</param>
3771 0 : void DTCLib::DTC_Registers::SetEthernetPayloadSize(uint32_t size)
3772 : {
3773 0 : if (size > 1492)
3774 : {
3775 0 : size = 1492;
3776 : }
3777 0 : WriteRegister_(size, DTC_Register_EthernetFramePayloadSize);
3778 0 : }
3779 :
3780 : /// <summary>
3781 : /// Formats the register's current value for register dumps
3782 : /// </summary>
3783 : /// <returns>RegisterFormatter object containing register information</returns>
3784 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEthernetPayloadSize()
3785 : {
3786 0 : auto form = CreateFormatter(DTC_Register_EthernetFramePayloadSize);
3787 0 : form.description = "Ethernet Frame Payload Max Size";
3788 0 : std::stringstream o;
3789 0 : o << std::dec << ReadEthernetPayloadSize(form.value) << " bytes";
3790 0 : form.vals.push_back(o.str());
3791 0 : return form;
3792 0 : }
3793 :
3794 0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulation40MHzMarkerInterval(std::optional<uint32_t> val)
3795 : {
3796 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
3797 : }
3798 :
3799 0 : void DTCLib::DTC_Registers::SetCFOEmulation40MHzMarkerInterval(uint32_t interval)
3800 : {
3801 0 : WriteRegister_(interval, DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
3802 0 : }
3803 :
3804 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulation40MHzMarkerInterval()
3805 : {
3806 0 : auto form = CreateFormatter(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
3807 0 : form.description = "CFO Emulation 40MHz Marker Interval";
3808 0 : std::stringstream o;
3809 0 : o << "0x" << std::hex << ReadCFOEmulation40MHzMarkerInterval(form.value);
3810 0 : form.vals.push_back(o.str());
3811 0 : return form;
3812 0 : }
3813 :
3814 : // bool DTCLib::DTC_Registers::ReadCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
3815 : // {
3816 : // std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(DTC_Register_CFOMarkerEnables);
3817 : // return dataSet[link + 8];
3818 : // }
3819 :
3820 : // void DTCLib::DTC_Registers::SetCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, bool enable)
3821 : // {
3822 : // std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
3823 : // data[link + 8] = enable;
3824 : // WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
3825 : // }
3826 :
3827 0 : bool DTCLib::DTC_Registers::ReadCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
3828 : {
3829 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOMarkerEnables);
3830 0 : return dataSet[link];
3831 : }
3832 :
3833 0 : void DTCLib::DTC_Registers::SetCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, bool enable)
3834 : {
3835 0 : std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
3836 0 : if (link == DTC_Link_ALL)
3837 : {
3838 0 : for (uint8_t i = 0; i < 6; ++i) // just ROC links
3839 0 : data[i] = enable;
3840 : }
3841 : else
3842 0 : data[link] = enable;
3843 0 : WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
3844 0 : }
3845 :
3846 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFO40MHzClockMarkerEnables()
3847 : {
3848 0 : auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
3849 0 : form.description = "CFO Emulation Marker Enables";
3850 : // form.vals.push_back(" [Event Start, 40 MHz]");
3851 0 : form.vals.push_back(" [40 MHz Clock Marker]");
3852 0 : for (auto r : DTC_ROC_Links)
3853 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
3854 : // (ReadCFOEventStartMarkerEnable(r, form.value) ? "x" : " ") + "," +
3855 0 : (ReadCFO40MHzClockMarkerEnable(r, form.value) ? "x" : " ") + "]");
3856 0 : return form;
3857 0 : }
3858 :
3859 0 : uint8_t DTCLib::DTC_Registers::ReadROCCommaLimit(std::optional<uint32_t> val)
3860 : {
3861 0 : return static_cast<uint8_t>(val.has_value() ? *val : ReadRegister_(DTC_Register_ROCFinishThreshold));
3862 : }
3863 :
3864 0 : void DTCLib::DTC_Registers::SetROCCommaLimit(uint8_t limit)
3865 : {
3866 0 : uint32_t data = ReadRegister_(DTC_Register_ROCFinishThreshold) & 0xFFFFFF00;
3867 0 : data += limit;
3868 0 : WriteRegister_(data, DTC_Register_ROCFinishThreshold);
3869 0 : }
3870 :
3871 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCFinishThreshold()
3872 : {
3873 0 : auto form = CreateFormatter(DTC_Register_ROCFinishThreshold);
3874 0 : form.description = "ROC Finish Threshold";
3875 0 : std::stringstream o;
3876 0 : o << "ROC Comma Limit: 0x" << std::hex << static_cast<int>(ReadROCCommaLimit(form.value));
3877 0 : form.vals.push_back(o.str());
3878 0 : return form;
3879 0 : }
3880 :
3881 0 : bool DTCLib::DTC_Registers::ReadTXPRBSForceError(DTC_Link_ID const& link, std::optional<uint32_t> val)
3882 : {
3883 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl));
3884 0 : return dataSet[link + 24];
3885 : }
3886 :
3887 0 : void DTCLib::DTC_Registers::SetTXPRBSForceError(DTC_Link_ID const& link)
3888 : {
3889 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
3890 0 : dataSet[link + 24] = 1;
3891 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
3892 0 : }
3893 :
3894 0 : void DTCLib::DTC_Registers::ClearTXPRBSForceError(DTC_Link_ID const& link)
3895 : {
3896 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
3897 0 : dataSet[link + 24] = 0;
3898 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
3899 0 : }
3900 :
3901 0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadTXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
3902 : {
3903 0 : auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl);
3904 0 : auto masked = (data >> link) & 0x7;
3905 0 : return static_cast<DTC_PRBSMode>(masked);
3906 : }
3907 :
3908 0 : void DTCLib::DTC_Registers::SetTXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
3909 : {
3910 0 : auto data = ReadRegister_(DTC_Register_TXPRBSControl);
3911 0 : auto masked = data & ~(0x7 << link);
3912 0 : auto newMode = static_cast<uint32_t>(mode);
3913 0 : WriteRegister_(masked + (newMode << link), DTC_Register_TXPRBSControl);
3914 0 : }
3915 :
3916 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESTXPRBSControl()
3917 : {
3918 0 : auto form = CreateFormatter(DTC_Register_TXPRBSControl);
3919 0 : form.description = "SERDES TX PRBS Control";
3920 0 : form.vals.push_back(" ([Force Error, Mode])");
3921 0 : for (auto r : DTC_ROC_Links)
3922 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
3923 0 : (ReadTXPRBSForceError(r, form.value) ? "x" : " ") + "," +
3924 0 : (DTC_PRBSModeConverter(ReadTXPRBSMode(r, form.value)).toString()) + "]");
3925 0 : form.vals.push_back(std::string("CFO: [") + (ReadTXPRBSForceError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
3926 0 : (DTC_PRBSModeConverter(ReadTXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
3927 0 : return form;
3928 0 : }
3929 :
3930 0 : bool DTCLib::DTC_Registers::ReadRXPRBSError(DTC_Link_ID const& link, std::optional<uint32_t> val)
3931 : {
3932 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl));
3933 0 : return dataSet[link + 24];
3934 : }
3935 :
3936 0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadRXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
3937 : {
3938 0 : auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl);
3939 0 : auto masked = (data >> link) & 0x7;
3940 0 : return static_cast<DTC_PRBSMode>(masked);
3941 : }
3942 :
3943 0 : void DTCLib::DTC_Registers::SetRXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
3944 : {
3945 0 : auto data = ReadRegister_(DTC_Register_RXPRBSControl);
3946 0 : auto masked = data & ~(0x7 << link);
3947 0 : auto newMode = static_cast<uint32_t>(mode);
3948 0 : WriteRegister_(masked + (newMode << link), DTC_Register_RXPRBSControl);
3949 0 : }
3950 :
3951 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSControl()
3952 : {
3953 0 : auto form = CreateFormatter(DTC_Register_RXPRBSControl);
3954 0 : form.description = "SERDES RX PRBS Control";
3955 0 : form.vals.push_back(" ([Error, Mode])");
3956 0 : for (auto r : DTC_ROC_Links)
3957 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
3958 0 : (ReadRXPRBSError(r, form.value) ? "x" : " ") + "," +
3959 0 : (DTC_PRBSModeConverter(ReadRXPRBSMode(r, form.value)).toString()) + "]");
3960 0 : form.vals.push_back(std::string("CFO: [") +
3961 0 : (ReadRXPRBSError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
3962 0 : (DTC_PRBSModeConverter(ReadRXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
3963 0 : return form;
3964 0 : }
3965 :
3966 0 : bool DTCLib::DTC_Registers::ReadEventModeTableEnable(std::optional<uint32_t> val)
3967 : {
3968 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl));
3969 0 : return dataSet[16];
3970 : }
3971 :
3972 0 : void DTCLib::DTC_Registers::SetEventModeTableEnable()
3973 : {
3974 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
3975 0 : dataSet[16] = 1;
3976 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
3977 0 : }
3978 :
3979 0 : void DTCLib::DTC_Registers::ClearEventModeTableEnable()
3980 : {
3981 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
3982 0 : dataSet[16] = 0;
3983 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
3984 0 : }
3985 :
3986 0 : uint8_t DTCLib::DTC_Registers::ReadEventModeLookupByteSelect(std::optional<uint32_t> val)
3987 : {
3988 0 : auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl);
3989 0 : auto masked = (data) & 0x7;
3990 0 : return static_cast<uint8_t>(masked);
3991 : }
3992 :
3993 0 : void DTCLib::DTC_Registers::SetEventModeLookupByteSelect(uint8_t byte)
3994 : {
3995 0 : auto data = ReadRegister_(DTC_Register_EventModeLookupTableControl);
3996 0 : auto masked = data & 0xFFF8;
3997 0 : WriteRegister_(masked + (byte & 0x7), DTC_Register_EventModeLookupTableControl);
3998 0 : }
3999 :
4000 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventModeLookupTableControl()
4001 : {
4002 0 : auto form = CreateFormatter(DTC_Register_EventModeLookupTableControl);
4003 0 : form.description = "Event Mode Lookup Table Control";
4004 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4005 0 : form.vals.push_back(std::string("Enabled: [") +
4006 0 : (ReadEventModeTableEnable(form.value) ? "x" : " ") + "]");
4007 0 : form.vals.push_back(std::string("Byte: [") +
4008 0 : std::to_string(ReadEventModeLookupByteSelect(form.value)) + "]");
4009 0 : return form;
4010 0 : }
4011 :
4012 0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestComplete(std::optional<uint32_t> val)
4013 : {
4014 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
4015 0 : return dataSet[8];
4016 : }
4017 :
4018 0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestError(std::optional<uint32_t> val)
4019 : {
4020 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
4021 0 : return dataSet[0];
4022 : }
4023 :
4024 0 : void DTCLib::DTC_Registers::ClearDDRMemoryTestError()
4025 : {
4026 0 : WriteRegister_(1, DTC_Register_DD3TestRegister);
4027 0 : }
4028 :
4029 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRMemoryTestRegister()
4030 : {
4031 0 : auto form = CreateFormatter(DTC_Register_DD3TestRegister);
4032 0 : form.description = "DDR3 Memory Test";
4033 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4034 0 : form.vals.push_back(std::string("Test Complete: [") +
4035 0 : (ReadDDRMemoryTestComplete(form.value) ? "x" : " ") + "]");
4036 0 : form.vals.push_back(std::string("Error: [") +
4037 0 : (ReadDDRMemoryTestError(form.value) ? "x" : " ") + "]");
4038 0 : return form;
4039 0 : }
4040 :
4041 : // SERDES Serial Inversion Enable Register
4042 : /// <summary>
4043 : /// Read the Invert SERDES RX Input bit
4044 : /// </summary>
4045 : /// <param name="link">Link to read</param>
4046 : /// <returns>Whether the Invert SERDES RX Input bit is set</returns>
4047 0 : bool DTCLib::DTC_Registers::ReadInvertSERDESRXInput(DTC_Link_ID const& link, std::optional<uint32_t> val)
4048 : {
4049 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
4050 0 : return data[link + 8];
4051 : }
4052 : /// <summary>
4053 : /// Set the Invert SERDES RX Input bit
4054 : /// </summary>
4055 : /// <param name="link">Link to set</param>
4056 : /// <param name="invert">Whether to invert</param>
4057 0 : void DTCLib::DTC_Registers::SetInvertSERDESRXInput(DTC_Link_ID const& link, bool invert)
4058 : {
4059 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
4060 0 : data[link + 8] = invert;
4061 0 : WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
4062 0 : }
4063 : /// <summary>
4064 : /// Read the Invert SERDES TX Output bit
4065 : /// </summary>
4066 : /// <param name="link">Link to read</param>
4067 : /// <returns>Whether the Invert SERDES TX Output bit is set</returns>
4068 0 : bool DTCLib::DTC_Registers::ReadInvertSERDESTXOutput(DTC_Link_ID const& link, std::optional<uint32_t> val)
4069 : {
4070 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
4071 0 : return data[link];
4072 : }
4073 : /// <summary>
4074 : /// Set the Invert SERDES TX Output bit
4075 : /// </summary>
4076 : /// <param name="link">Link to set</param>
4077 : /// <param name="invert">Whether to invert</param>
4078 0 : void DTCLib::DTC_Registers::SetInvertSERDESTXOutput(DTC_Link_ID const& link, bool invert)
4079 : {
4080 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
4081 0 : data[link] = invert;
4082 0 : WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
4083 0 : }
4084 : /// <summary>
4085 : /// Formats the register's current value for register dumps
4086 : /// </summary>
4087 : /// <returns>RegisterFormatter object containing register information</returns>
4088 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESSerialInversionEnable()
4089 : {
4090 0 : auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
4091 0 : form.description = "SERDES Serial Inversion Enable";
4092 0 : form.vals.push_back(" ([Input, Output])");
4093 0 : for (auto r : DTC_ROC_Links)
4094 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
4095 0 : (ReadInvertSERDESRXInput(r, form.value) ? "x" : " ") + "," +
4096 0 : (ReadInvertSERDESTXOutput(r, form.value) ? "x" : " ") + "]");
4097 0 : form.vals.push_back(std::string("CFO: [") +
4098 0 : (ReadInvertSERDESRXInput(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
4099 0 : (ReadInvertSERDESTXOutput(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
4100 :
4101 0 : return form;
4102 0 : }
4103 :
4104 : // Jitter Attenuator CSR Register
4105 : /// <summary>
4106 : /// Read the value of the Jitter Attenuator Select
4107 : /// </summary>
4108 : /// <returns>Jitter Attenuator Select value</returns>
4109 0 : std::bitset<2> DTCLib::DTC_Registers::ReadJitterAttenuatorSelect(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR); }
4110 :
4111 : /// <summary>
4112 : /// Set the Jitter Attenuator Select bits. JA reset only needed after a power cycle
4113 : /// </summary>
4114 : /// <param name="data">Value to set</param>
4115 0 : void DTCLib::DTC_Registers::SetJitterAttenuatorSelect(std::bitset<2> data, bool alsoResetJA /* = false */) { CFOandDTC_Registers::SetJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR, data, alsoResetJA); }
4116 :
4117 : /// <summary>
4118 : /// Read the Jitter Attenuator Reset bit
4119 : /// </summary>
4120 : /// <returns>Value of the Jitter Attenuator Reset bit</returns>
4121 0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorReset(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorReset(DTC_Register_JitterAttenuatorCSR, val); }
4122 0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorLocked(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorLocked(DTC_Register_JitterAttenuatorCSR, val); }
4123 :
4124 : /// <summary>
4125 : /// Reset the Jitter Attenuator
4126 : /// </summary>
4127 0 : void DTCLib::DTC_Registers::ResetJitterAttenuator() { CFOandDTC_Registers::ResetJitterAttenuator(DTC_Register_JitterAttenuatorCSR); }
4128 :
4129 : /// <summary>
4130 : /// Formats the register's current value for register dumps
4131 : /// </summary>
4132 : /// <returns>RegisterFormatter object containing register information</returns>
4133 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorCSR() { return CFOandDTC_Registers::FormatJitterAttenuatorCSR(DTC_Register_JitterAttenuatorCSR); }
4134 :
4135 : // SFP IIC Registers
4136 :
4137 : /// <summary>
4138 : /// Read the Reset bit of the SFP IIC Bus
4139 : /// </summary>
4140 : /// <returns>Reset bit value</returns>
4141 0 : bool DTCLib::DTC_Registers::ReadSFPIICInterfaceReset(std::optional<uint32_t> val)
4142 : {
4143 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SFP_IICBusControl));
4144 0 : return dataSet[31];
4145 : }
4146 : /// <summary>
4147 : /// Reset the SFP IIC Bus
4148 : /// </summary>
4149 0 : void DTCLib::DTC_Registers::ResetSFPIICInterface()
4150 : {
4151 0 : auto bs = std::bitset<32>();
4152 0 : bs[31] = 1;
4153 0 : WriteRegister_(bs.to_ulong(), DTC_Register_SFP_IICBusControl);
4154 0 : while (ReadSFPIICInterfaceReset())
4155 : {
4156 0 : usleep(1000);
4157 : }
4158 0 : }
4159 : /// <summary>
4160 : /// Write a value to the SFP IIC Bus
4161 : /// </summary>
4162 : /// <param name="device">Device address</param>
4163 : /// <param name="address">Register address</param>
4164 : /// <param name="data">Data to write</param>
4165 0 : void DTCLib::DTC_Registers::WriteSFPIICInterface(uint8_t device, uint8_t address, uint8_t data)
4166 : {
4167 0 : uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16) + (data << 8);
4168 0 : WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
4169 0 : WriteRegister_(0x1, DTC_Register_SFP_IICBusHigh);
4170 0 : while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x1)
4171 : {
4172 0 : usleep(1000);
4173 : }
4174 0 : }
4175 : /// <summary>
4176 : /// Read a value from the SFP IIC Bus
4177 : /// </summary>
4178 : /// <param name="device">Device address</param>
4179 : /// <param name="address">Register address</param>
4180 : /// <returns>Value of register</returns>
4181 0 : uint8_t DTCLib::DTC_Registers::ReadSFPIICInterface(uint8_t device, uint8_t address)
4182 : {
4183 0 : uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16);
4184 0 : WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
4185 0 : WriteRegister_(0x2, DTC_Register_SFP_IICBusHigh);
4186 0 : while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x2)
4187 : {
4188 0 : usleep(1000);
4189 : }
4190 0 : auto data = ReadRegister_(DTC_Register_SFP_IICBusLow);
4191 0 : return static_cast<uint8_t>(data);
4192 : }
4193 :
4194 : /// <summary>
4195 : /// Formats the register's current value for register dumps
4196 : /// </summary>
4197 : /// <returns>RegisterFormatter object containing register information</returns>
4198 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICControl()
4199 : {
4200 0 : auto form = CreateFormatter(DTC_Register_SFP_IICBusControl);
4201 0 : form.description = "SFP Oscillator IIC Bus Control";
4202 0 : form.vals.push_back(std::string("Reset: [") + (ReadSFPIICInterfaceReset(form.value) ? "x" : " ") + "]");
4203 0 : return form;
4204 0 : }
4205 : /// <summary>
4206 : /// Formats the register's current value for register dumps
4207 : /// </summary>
4208 : /// <returns>RegisterFormatter object containing register information</returns>
4209 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterLow()
4210 : {
4211 0 : auto form = CreateFormatter(DTC_Register_SFP_IICBusLow);
4212 0 : form.description = "SFP Oscillator IIC Bus Low";
4213 0 : form.vals.push_back(""); // translation
4214 0 : auto data = form.value;
4215 0 : std::ostringstream s1, s2, s3, s4;
4216 0 : s1 << "Device: " << std::showbase << std::hex << ((data & 0xFF000000) >> 24);
4217 0 : form.vals.push_back(s1.str());
4218 0 : s2 << "ASFPess: " << std::showbase << std::hex << ((data & 0xFF0000) >> 16);
4219 0 : form.vals.push_back(s2.str());
4220 0 : s3 << "Write Data: " << std::showbase << std::hex << ((data & 0xFF00) >> 8);
4221 0 : form.vals.push_back(s3.str());
4222 0 : s4 << "Read Data: " << std::showbase << std::hex << (data & 0xFF);
4223 0 : form.vals.push_back(s4.str());
4224 0 : return form;
4225 0 : }
4226 : /// <summary>
4227 : /// Formats the register's current value for register dumps
4228 : /// </summary>
4229 : /// <returns>RegisterFormatter object containing register information</returns>
4230 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterHigh()
4231 : {
4232 0 : auto form = CreateFormatter(DTC_Register_SFP_IICBusHigh);
4233 0 : auto data = form.value;
4234 0 : form.description = "SFP Oscillator IIC Bus High";
4235 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4236 0 : form.vals.push_back(std::string("Write: [") + (data & 0x1 ? "x" : " ") + "]");
4237 0 : form.vals.push_back(std::string("Read: [") + (data & 0x2 ? "x" : " ") + "]");
4238 0 : return form;
4239 0 : }
4240 :
4241 0 : uint32_t DTCLib::DTC_Registers::ReadRetransmitRequestCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
4242 : {
4243 0 : switch (link)
4244 : {
4245 0 : case DTC_Link_0:
4246 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link0);
4247 0 : case DTC_Link_1:
4248 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link1);
4249 0 : case DTC_Link_2:
4250 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link2);
4251 0 : case DTC_Link_3:
4252 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link3);
4253 0 : case DTC_Link_4:
4254 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link4);
4255 0 : case DTC_Link_5:
4256 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link5);
4257 0 : default: {
4258 0 : __SS__ << "Illegal link index provided: " << link << __E__;
4259 0 : __SS_THROW__;
4260 0 : }
4261 : }
4262 : }
4263 0 : void DTCLib::DTC_Registers::ClearRetransmitRequestCount(DTC_Link_ID const& link)
4264 : {
4265 0 : switch (link)
4266 : {
4267 0 : case DTC_Link_0:
4268 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link0);
4269 0 : break;
4270 0 : case DTC_Link_1:
4271 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link1);
4272 0 : break;
4273 0 : case DTC_Link_2:
4274 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link2);
4275 0 : break;
4276 0 : case DTC_Link_3:
4277 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link3);
4278 0 : break;
4279 0 : case DTC_Link_4:
4280 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link4);
4281 0 : break;
4282 0 : case DTC_Link_5:
4283 0 : WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link5);
4284 0 : break;
4285 0 : default: {
4286 0 : __SS__ << "Illegal link index provided: " << link << __E__;
4287 0 : __SS_THROW__;
4288 0 : }
4289 : }
4290 0 : }
4291 :
4292 : /// <summary>
4293 : /// Formats the register's current value for register dumps
4294 : /// </summary>
4295 : /// <returns>RegisterFormatter object containing register information</returns>
4296 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink0()
4297 : {
4298 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link0);
4299 0 : form.description = "ROC Retransmit Request Count Link 0";
4300 0 : std::stringstream o;
4301 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_0, form.value);
4302 0 : form.vals.push_back(o.str());
4303 0 : return form;
4304 0 : }
4305 :
4306 : /// <summary>
4307 : /// Formats the register's current value for register dumps
4308 : /// </summary>
4309 : /// <returns>RegisterFormatter object containing register information</returns>
4310 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink1()
4311 : {
4312 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link1);
4313 0 : form.description = "ROC Retransmit Request Count Link 1";
4314 0 : std::stringstream o;
4315 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_1, form.value);
4316 0 : form.vals.push_back(o.str());
4317 0 : return form;
4318 0 : }
4319 :
4320 : /// <summary>
4321 : /// Formats the register's current value for register dumps
4322 : /// </summary>
4323 : /// <returns>RegisterFormatter object containing register information</returns>
4324 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink2()
4325 : {
4326 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link2);
4327 0 : form.description = "ROC Retransmit Request Count Link 2";
4328 0 : std::stringstream o;
4329 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_2, form.value);
4330 0 : form.vals.push_back(o.str());
4331 0 : return form;
4332 0 : }
4333 :
4334 : /// <summary>
4335 : /// Formats the register's current value for register dumps
4336 : /// </summary>
4337 : /// <returns>RegisterFormatter object containing register information</returns>
4338 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink3()
4339 : {
4340 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link3);
4341 0 : form.description = "ROC Retransmit Request Count Link 3";
4342 0 : std::stringstream o;
4343 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_3, form.value);
4344 0 : form.vals.push_back(o.str());
4345 0 : return form;
4346 0 : }
4347 :
4348 : /// <summary>
4349 : /// Formats the register's current value for register dumps
4350 : /// </summary>
4351 : /// <returns>RegisterFormatter object containing register information</returns>
4352 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink4()
4353 : {
4354 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link4);
4355 0 : form.description = "ROC Retransmit Request Count Link 4";
4356 0 : std::stringstream o;
4357 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_4, form.value);
4358 0 : form.vals.push_back(o.str());
4359 0 : return form;
4360 0 : }
4361 :
4362 : /// <summary>
4363 : /// Formats the register's current value for register dumps
4364 : /// </summary>
4365 : /// <returns>RegisterFormatter object containing register information</returns>
4366 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink5()
4367 : {
4368 0 : auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link5);
4369 0 : form.description = "ROC Retransmit Request Count Link 5";
4370 0 : std::stringstream o;
4371 0 : o << std::dec << ReadRetransmitRequestCount(DTC_Link_5, form.value);
4372 0 : form.vals.push_back(o.str());
4373 0 : return form;
4374 0 : }
4375 :
4376 : // Missed CFO Packet Count Registers
4377 : /**
4378 : * @brief Read the missed CFO Packet Count for the given link
4379 : * @param link Link to read
4380 : * @returns Number of missed CFO packets for the given link, or 0 if an invalid link is given
4381 : */
4382 0 : uint32_t DTCLib::DTC_Registers::ReadMissedCFOPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
4383 : {
4384 0 : switch (link)
4385 : {
4386 0 : case DTC_Link_0:
4387 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link0);
4388 0 : case DTC_Link_1:
4389 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link1);
4390 0 : case DTC_Link_2:
4391 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link2);
4392 0 : case DTC_Link_3:
4393 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link3);
4394 0 : case DTC_Link_4:
4395 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link4);
4396 0 : case DTC_Link_5:
4397 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link5);
4398 0 : default: {
4399 0 : __SS__ << "Illegal link index provided: " << link << __E__;
4400 0 : __SS_THROW__;
4401 0 : }
4402 : }
4403 : }
4404 :
4405 : /// <summary>
4406 : /// Clears the Missed CFO Packet Count for the given link
4407 : /// </summary>
4408 : /// <param name="link">Link to clear</param>
4409 0 : void DTCLib::DTC_Registers::ClearMissedCFOPacketCount(DTC_Link_ID const& link)
4410 : {
4411 0 : switch (link)
4412 : {
4413 0 : case DTC_Link_0:
4414 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link0);
4415 0 : break;
4416 0 : case DTC_Link_1:
4417 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link1);
4418 0 : break;
4419 0 : case DTC_Link_2:
4420 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link2);
4421 0 : break;
4422 0 : case DTC_Link_3:
4423 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link3);
4424 0 : break;
4425 0 : case DTC_Link_4:
4426 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link4);
4427 0 : break;
4428 0 : case DTC_Link_5:
4429 0 : WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link5);
4430 0 : break;
4431 0 : default: {
4432 0 : __SS__ << "Illegal link index provided: " << link << __E__;
4433 0 : __SS_THROW__;
4434 0 : }
4435 : }
4436 0 : }
4437 :
4438 : /// <summary>
4439 : /// Formats the register's current value for register dumps
4440 : /// </summary>
4441 : /// <returns>RegisterFormatter object containing register information</returns>
4442 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink0()
4443 : {
4444 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link0);
4445 0 : form.description = "Missed CFO Packet Count Link 0";
4446 0 : std::stringstream o;
4447 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_0, form.value);
4448 0 : form.vals.push_back(o.str());
4449 0 : return form;
4450 0 : }
4451 :
4452 : /// <summary>
4453 : /// Formats the register's current value for register dumps
4454 : /// </summary>
4455 : /// <returns>RegisterFormatter object containing register information</returns>
4456 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink1()
4457 : {
4458 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link1);
4459 0 : form.description = "Missed CFO Packet Count Link 1";
4460 0 : std::stringstream o;
4461 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_1, form.value);
4462 0 : form.vals.push_back(o.str());
4463 0 : return form;
4464 0 : }
4465 :
4466 : /// <summary>
4467 : /// Formats the register's current value for register dumps
4468 : /// </summary>
4469 : /// <returns>RegisterFormatter object containing register information</returns>
4470 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink2()
4471 : {
4472 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link2);
4473 0 : form.description = "Missed CFO Packet Count Link 2";
4474 0 : std::stringstream o;
4475 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_2, form.value);
4476 0 : form.vals.push_back(o.str());
4477 0 : return form;
4478 0 : }
4479 :
4480 : /// <summary>
4481 : /// Formats the register's current value for register dumps
4482 : /// </summary>
4483 : /// <returns>RegisterFormatter object containing register information</returns>
4484 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink3()
4485 : {
4486 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link3);
4487 0 : form.description = "Missed CFO Packet Count Link 3";
4488 0 : std::stringstream o;
4489 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_3, form.value);
4490 0 : form.vals.push_back(o.str());
4491 0 : return form;
4492 0 : }
4493 :
4494 : /// <summary>
4495 : /// Formats the register's current value for register dumps
4496 : /// </summary>
4497 : /// <returns>RegisterFormatter object containing register information</returns>
4498 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink4()
4499 : {
4500 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link4);
4501 0 : form.description = "Missed CFO Packet Count Link 4";
4502 0 : std::stringstream o;
4503 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_4, form.value);
4504 0 : form.vals.push_back(o.str());
4505 0 : return form;
4506 0 : }
4507 :
4508 : /// <summary>
4509 : /// Formats the register's current value for register dumps
4510 : /// </summary>
4511 : /// <returns>RegisterFormatter object containing register information</returns>
4512 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink5()
4513 : {
4514 0 : auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link5);
4515 0 : form.description = "Missed CFO Packet Count Link 5";
4516 0 : std::stringstream o;
4517 0 : o << std::dec << ReadMissedCFOPacketCount(DTC_Link_5, form.value);
4518 0 : form.vals.push_back(o.str());
4519 0 : return form;
4520 0 : }
4521 :
4522 : // Local Fragment Drop Count Register
4523 : /// <summary>
4524 : /// Reads the current value of the Local Fragment Drop Counter
4525 : /// </summary>
4526 : /// <returns>The number of fragments dropped by the DTC</returns>
4527 0 : uint32_t DTCLib::DTC_Registers::ReadLocalFragmentDropCount(std::optional<uint32_t> val)
4528 : {
4529 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_LocalFragmentDropCount);
4530 : }
4531 :
4532 : /// <summary>
4533 : /// Clears the Local Fragment Drop Counter
4534 : /// </summary>
4535 0 : void DTCLib::DTC_Registers::ClearLocalFragmentDropCount() { WriteRegister_(1, DTC_Register_LocalFragmentDropCount); }
4536 :
4537 : /// <summary>
4538 : /// Formats the register's current value for register dumps
4539 : /// </summary>
4540 : /// <returns>RegisterFormatter object containing register information</returns>
4541 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLocalFragmentDropCount()
4542 : {
4543 0 : auto form = CreateFormatter(DTC_Register_LocalFragmentDropCount);
4544 0 : form.description = "Local Data Fragment Drop Count";
4545 0 : std::stringstream o;
4546 0 : o << std::dec << ReadLocalFragmentDropCount(form.value);
4547 0 : form.vals.push_back(o.str());
4548 0 : return form;
4549 0 : }
4550 :
4551 0 : uint32_t DTCLib::DTC_Registers::ReadEVBSubEventReceiveTimer(std::optional<uint32_t> val)
4552 : {
4553 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSubEventReceiveTimerPreset);
4554 : }
4555 :
4556 0 : void DTCLib::DTC_Registers::SetEVBSubEventReceiveTimer(uint32_t timer)
4557 : {
4558 0 : WriteRegister_(timer, DTC_Register_EVBSubEventReceiveTimerPreset);
4559 0 : }
4560 :
4561 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSubEventReceiveTimer()
4562 : {
4563 0 : auto form = CreateFormatter(DTC_Register_EVBSubEventReceiveTimerPreset);
4564 0 : form.description = "EVB SubEvent Receive Timer (*4ns)";
4565 0 : std::stringstream o;
4566 0 : o << std::dec << ReadEVBSubEventReceiveTimer(form.value);
4567 0 : form.vals.push_back(o.str());
4568 0 : return form;
4569 0 : }
4570 :
4571 : // EVB SERDES PRBS Register
4572 : /// <summary>
4573 : /// Determine if an error was detected in the EVB SERDES PRBS module
4574 : /// </summary>
4575 : /// <returns>True if error condition was detected, false otherwise</returns>
4576 0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSErrorFlag(std::optional<uint32_t> val)
4577 : {
4578 0 : std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4579 0 : return regVal[31];
4580 : }
4581 :
4582 : /// <summary>
4583 : /// Read the EVB SERDES TX PRBS Select
4584 : /// </summary>
4585 : /// <returns>Value of the EVB SERDES TX PRBS Select</returns>
4586 0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESTXPRBSSEL(std::optional<uint32_t> val)
4587 : {
4588 0 : uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x7000) >> 12);
4589 0 : return regVal;
4590 : }
4591 :
4592 : /// <summary>
4593 : /// Set the EVB SERDES TX PRBS Select
4594 : /// </summary>
4595 : /// <param name="byte">Value of the EVB SERDES TX PRBS Select</param>
4596 0 : void DTCLib::DTC_Registers::SetEVBSERDESTXPRBSSEL(uint8_t byte)
4597 : {
4598 0 : uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFF8FFF);
4599 0 : regVal += ((byte & 0x7) << 12);
4600 0 : WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
4601 0 : }
4602 :
4603 : /// <summary>
4604 : /// Read the EVB SERDES RX PRBS Select
4605 : /// </summary>
4606 : /// <returns>Value of the EVB SERDES RX PRBS Select</returns>
4607 0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESRXPRBSSEL(std::optional<uint32_t> val)
4608 : {
4609 0 : uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x700) >> 8);
4610 0 : return regVal;
4611 : }
4612 :
4613 : /// <summary>
4614 : /// Set the EVB SERDES RX PRBS Select
4615 : /// </summary>
4616 : /// <param name="byte">Value of the EVB SERDES RX PRBS Select</param>
4617 0 : void DTCLib::DTC_Registers::SetEVBSERDESRXPRBSSEL(uint8_t byte)
4618 : {
4619 0 : uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFFF8FF);
4620 0 : regVal += ((byte & 0x7) << 8);
4621 0 : WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
4622 0 : }
4623 :
4624 : /// <summary>
4625 : /// Read the state of the EVB SERDES PRBS Force Error bit
4626 : /// </summary>
4627 : /// <returns>True if the EVB SERDES PRBS Force Error bit is high</returns>
4628 0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSForceError(std::optional<uint32_t> val)
4629 : {
4630 0 : std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4631 0 : return regVal[1];
4632 : }
4633 :
4634 : /// <summary>
4635 : /// Set the EVB SERDES PRBS Force Error bit
4636 : /// </summary>
4637 : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
4638 0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSForceError(bool flag)
4639 : {
4640 0 : std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4641 0 : regVal[1] = flag;
4642 0 : WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
4643 0 : }
4644 :
4645 : /// <summary>
4646 : /// Toggle the EVB SERDES PRBS Force Error bit (make it true if false, false if true)
4647 : /// </summary>
4648 0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSForceError()
4649 : {
4650 0 : std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4651 0 : regVal.flip(0);
4652 0 : WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
4653 0 : }
4654 :
4655 : /// <summary>
4656 : /// Read the state of the EVB SERDES PRBS Reset bit
4657 : /// </summary>
4658 : /// <returns>True if the EVB SERDES PRBS Reset bit is high</returns>
4659 0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSReset(std::optional<uint32_t> val)
4660 : {
4661 0 : std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4662 0 : return regVal[0];
4663 : }
4664 :
4665 : /// <summary>
4666 : /// Set the EVB SERDES PRBS Reset bit
4667 : /// </summary>
4668 : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
4669 0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSReset(bool flag)
4670 : {
4671 0 : std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4672 0 : regVal[0] = flag;
4673 0 : WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
4674 0 : }
4675 :
4676 : /// <summary>
4677 : /// Toggle the EVB SERDES PRBS Reset bit (make it true if false, false if true)
4678 : /// </summary>
4679 0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSReset()
4680 : {
4681 0 : std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
4682 0 : regVal.flip(0);
4683 0 : WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
4684 0 : }
4685 :
4686 : /// <summary>
4687 : /// Formats the register's current value for register dumps
4688 : /// </summary>
4689 : /// <returns>RegisterFormatter object containing register information</returns>
4690 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESPRBSControl()
4691 : {
4692 0 : auto form = CreateFormatter(DTC_Register_EVBSERDESPRBSControlStatus);
4693 0 : form.description = "EVB SERDES PRBS Control / Status";
4694 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4695 0 : form.vals.push_back(std::string("PRBS Error: [") + (ReadEVBSERDESPRBSErrorFlag(form.value) ? "x" : " ") + "]");
4696 0 : std::stringstream o;
4697 0 : o << "EVB SERDES TX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESTXPRBSSEL(form.value));
4698 0 : form.vals.push_back(o.str());
4699 0 : o.str("");
4700 0 : o.clear();
4701 0 : o << "EVB SERDES RX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESRXPRBSSEL(form.value));
4702 0 : form.vals.push_back(std::string("PRBS Force Error: [") + (ReadEVBSERDESPRBSForceError(form.value) ? "x" : " ") + "]");
4703 0 : form.vals.push_back(std::string("PRBS Reset: [") + (ReadEVBSERDESPRBSReset(form.value) ? "x" : " ") + "]");
4704 :
4705 0 : return form;
4706 0 : }
4707 :
4708 : // Event Builder Error Register
4709 : /// <summary>
4710 : /// Read the Event Builder SubEvent Receiver Flags Buffer Error bit
4711 : /// </summary>
4712 : /// <returns>Value of the bit</returns>
4713 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_SubEventReceiverFlagsBufferError(std::optional<uint32_t> val)
4714 : {
4715 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4716 0 : return data[24];
4717 : }
4718 : /// <summary>
4719 : /// Read the Event Builder Ethernet Input FIFO Full bit
4720 : /// </summary>
4721 : /// <returns>Value of the bit</returns>
4722 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_EthernetInputFIFOFull(std::optional<uint32_t> val)
4723 : {
4724 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4725 0 : return data[16];
4726 : }
4727 : /// <summary>
4728 : /// Read the Event Builder Link Error bit
4729 : /// </summary>
4730 : /// <returns>Value of the bit</returns>
4731 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LinkError(std::optional<uint32_t> val)
4732 : {
4733 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4734 0 : return data[9];
4735 : }
4736 : /// <summary>
4737 : /// Read the Event Builder TX Packet Error bit
4738 : /// </summary>
4739 : /// <returns>Value of the bit</returns>
4740 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TXPacketError(std::optional<uint32_t> val)
4741 : {
4742 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4743 0 : return data[8];
4744 : }
4745 : /// <summary>
4746 : /// Read the Event Builder Local Data Pointer FIFO Queue Error bit
4747 : /// </summary>
4748 : /// <returns>Value of the bit</returns>
4749 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LocalDataPointerFIFOQueueError(std::optional<uint32_t> val)
4750 : {
4751 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4752 0 : return data[1];
4753 : }
4754 : /// <summary>
4755 : /// Read the Event Builder Transmit DMA Byte Count FIFO Full bit
4756 : /// </summary>
4757 : /// <returns>Value of the bit</returns>
4758 0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TransmitDMAByteCountFIFOFull(std::optional<uint32_t> val)
4759 : {
4760 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
4761 0 : return data[0];
4762 : }
4763 : /// <summary>
4764 : /// Formats the register's current value for register dumps
4765 : /// </summary>
4766 : /// <returns>RegisterFormatter object containing register information</returns>
4767 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventBuilderErrorRegister()
4768 : {
4769 0 : auto form = CreateFormatter(DTC_Register_EventBuilderErrorFlags);
4770 0 : form.description = "Event Builder Error Flags";
4771 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4772 0 : form.vals.push_back(std::string("Sub-Event Received Flags Buffer Error: [") +
4773 0 : (ReadEventBuilder_SubEventReceiverFlagsBufferError(form.value) ? "x" : " ") + "]");
4774 0 : form.vals.push_back(std::string("Input FIFO Full: [") +
4775 0 : (ReadEventBuilder_EthernetInputFIFOFull(form.value) ? "x" : " ") + "]");
4776 0 : form.vals.push_back(std::string("Link Error: [") +
4777 0 : (ReadEventBuilder_LinkError(form.value) ? "x" : " ") + "]");
4778 0 : form.vals.push_back(std::string("TX Packet Error: [") +
4779 0 : (ReadEventBuilder_TXPacketError(form.value) ? "x" : " ") + "]");
4780 0 : form.vals.push_back(std::string("Local Data Pointer FIFO Queue Error: [") +
4781 0 : (ReadEventBuilder_LocalDataPointerFIFOQueueError(form.value) ? "x" : " ") + "]");
4782 0 : form.vals.push_back(std::string("Transmit DMA Byte Count FIFO Full: [") +
4783 0 : (ReadEventBuilder_TransmitDMAByteCountFIFOFull(form.value) ? "x" : " ") + "]");
4784 0 : return form;
4785 0 : }
4786 :
4787 : // SERDES VFIFO Error Register
4788 : /// <summary>
4789 : /// Read the SERDES VFIFO Egress FIFO Full bit
4790 : /// </summary>
4791 : /// <returns>Value of the bit</returns>
4792 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
4793 : {
4794 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4795 0 : return data[10];
4796 : }
4797 : /// <summary>
4798 : /// Read the SERDES VFIFO Ingress FIFO Full bit
4799 : /// </summary>
4800 : /// <returns>Value of the bit</returns>
4801 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
4802 : {
4803 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4804 0 : return data[9];
4805 : }
4806 : /// <summary>
4807 : /// Read the SERDES VFIFO Event Byte Count Total Error bit
4808 : /// </summary>
4809 : /// <returns>Value of the bit</returns>
4810 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
4811 : {
4812 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4813 0 : return data[8];
4814 : }
4815 : /// <summary>
4816 : /// Read the SERDES VFIFO Last Word Written Timeout Error bit
4817 : /// </summary>
4818 : /// <returns>Value of the bit</returns>
4819 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_LastWordWrittenTimeoutError(std::optional<uint32_t> val)
4820 : {
4821 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4822 0 : return data[2];
4823 : }
4824 : /// <summary>
4825 : /// Read the SERDES VFIFO Fragment Count Error bit
4826 : /// </summary>
4827 : /// <returns>Value of the bit</returns>
4828 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_FragmentCountError(std::optional<uint32_t> val)
4829 : {
4830 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4831 0 : return data[1];
4832 : }
4833 : /// <summary>
4834 : /// Read the SERDES VFIFO DDR Full Error bit
4835 : /// </summary>
4836 : /// <returns>Value of the bit</returns>
4837 0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_DDRFullError(std::optional<uint32_t> val)
4838 : {
4839 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
4840 0 : return data[0];
4841 : }
4842 : /// <summary>
4843 : /// Formats the register's current value for register dumps
4844 : /// </summary>
4845 : /// <returns>RegisterFormatter object containing register information</returns>
4846 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESVFIFOError()
4847 : {
4848 0 : auto form = CreateFormatter(DTC_Register_InputBufferErrorFlags);
4849 0 : form.description = "SERDES VFIFO Error Flags";
4850 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4851 0 : form.vals.push_back(std::string("Egress FIFO Full: [") + (ReadSERDESVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
4852 : "]");
4853 0 : form.vals.push_back(std::string("Ingress FIFO Full: [") + (ReadSERDESVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
4854 : "]");
4855 0 : form.vals.push_back(std::string("Event Byte Count Total Error: [") +
4856 0 : (ReadSERDESVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
4857 0 : form.vals.push_back(std::string("Last Word Written Timeout: [") +
4858 0 : (ReadSERDESVFIFO_LastWordWrittenTimeoutError(form.value) ? "x" : " ") + "]");
4859 0 : form.vals.push_back(std::string("Fragment count Error: [") +
4860 0 : (ReadSERDESVFIFO_FragmentCountError(form.value) ? "x" : " ") + "]");
4861 0 : form.vals.push_back(std::string("DDR Full Error: [") + (ReadSERDESVFIFO_DDRFullError(form.value) ? "x" : " ") +
4862 : "]");
4863 0 : return form;
4864 0 : }
4865 :
4866 : // PCI VFIFO Error Register
4867 : /// <summary>
4868 : /// Read the PCI VIFO DDR Full bit
4869 : /// </summary>
4870 : /// <returns>Value of the bit</returns>
4871 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_DDRFull(std::optional<uint32_t> val)
4872 : {
4873 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4874 0 : return data[12];
4875 : }
4876 : /// <summary>
4877 : /// Read the PCI VIFO Memmory Mapped Write Complete FIFO Full bit
4878 : /// </summary>
4879 : /// <returns>Value of the bit</returns>
4880 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(std::optional<uint32_t> val)
4881 : {
4882 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4883 0 : return data[11];
4884 : }
4885 : /// <summary>
4886 : /// Read the PCI VIFO PCI Write Event FIFO Full bit
4887 : /// </summary>
4888 : /// <returns>Value of the bit</returns>
4889 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_PCIWriteEventFIFOFull(std::optional<uint32_t> val)
4890 : {
4891 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4892 0 : return data[10];
4893 : }
4894 : /// <summary>
4895 : /// Read the PCI VIFO Local Data Pointer FIFO Full bit
4896 : /// </summary>
4897 : /// <returns>Value of the bit</returns>
4898 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_LocalDataPointerFIFOFull(std::optional<uint32_t> val)
4899 : {
4900 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4901 0 : return data[9];
4902 : }
4903 : /// <summary>
4904 : /// Read the PCI VIFO Egress FIFO Full bit
4905 : /// </summary>
4906 : /// <returns>Value of the bit</returns>
4907 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
4908 : {
4909 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4910 0 : return data[8];
4911 : }
4912 : /// <summary>
4913 : /// Read the PCI VIFO RX Buffer Select FIFO Full bit
4914 : /// </summary>
4915 : /// <returns>Value of the bit</returns>
4916 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_RXBufferSelectFIFOFull(std::optional<uint32_t> val)
4917 : {
4918 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4919 0 : return data[2];
4920 : }
4921 : /// <summary>
4922 : /// Read the PCI VIFO Ingress FIFO Full bit
4923 : /// </summary>
4924 : /// <returns>Value of the bit</returns>
4925 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
4926 : {
4927 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4928 0 : return data[1];
4929 : }
4930 : /// <summary>
4931 : /// Read the PCI VIFO Event Byte Count Total Error bit
4932 : /// </summary>
4933 : /// <returns>Value of the bit</returns>
4934 0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
4935 : {
4936 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
4937 0 : return data[0];
4938 : }
4939 : /// <summary>
4940 : /// Formats the register's current value for register dumps
4941 : /// </summary>
4942 : /// <returns>RegisterFormatter object containing register information</returns>
4943 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatPCIVFIFOError()
4944 : {
4945 0 : auto form = CreateFormatter(DTC_Register_OutputBufferErrorFlags);
4946 0 : form.description = "PCI VFIFO Error Flags";
4947 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
4948 0 : form.vals.push_back(std::string("DDR Full Error: [") + (ReadPCIVFIFO_DDRFull(form.value) ? "x" : " ") + "]");
4949 0 : form.vals.push_back(std::string("Memmap Write Cmplt FIFO Full: [") +
4950 0 : (ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(form.value) ? "x" : " ") + "]");
4951 0 : form.vals.push_back(std::string("PCI Write Event FIFO Full: [") +
4952 0 : (ReadPCIVFIFO_PCIWriteEventFIFOFull(form.value) ? "x" : " ") + "]");
4953 0 : form.vals.push_back(std::string("Local Data Pointer FIFO Full: [") +
4954 0 : (ReadPCIVFIFO_LocalDataPointerFIFOFull(form.value) ? "x" : " ") + "]");
4955 0 : form.vals.push_back(std::string("Egress FIFO Full: [") + (ReadPCIVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
4956 : "]");
4957 0 : form.vals.push_back(std::string("RX Buffer Select FIFO Full: [") +
4958 0 : (ReadPCIVFIFO_RXBufferSelectFIFOFull(form.value) ? "x" : " ") + "]");
4959 0 : form.vals.push_back(std::string("Ingress FIFO Ful: [") + (ReadPCIVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
4960 : "]");
4961 0 : form.vals.push_back(std::string("Event Byte Count Total Error: [") +
4962 0 : (ReadPCIVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
4963 0 : return form;
4964 0 : }
4965 :
4966 : // ROC Link Error Registers
4967 : /// <summary>
4968 : /// Read the Receive Data Request Sync Error bit for the given link
4969 : /// </summary>
4970 : /// <param name="link">Link to read</param>
4971 : /// <returns>Value of the bit</returns>
4972 0 : bool DTCLib::DTC_Registers::ReadROCLink_ROCDataRequestSyncError(DTC_Link_ID const& link, std::optional<uint32_t> val)
4973 : {
4974 0 : std::bitset<32> data;
4975 0 : switch (link)
4976 : {
4977 0 : case DTC_Link_0:
4978 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
4979 0 : break;
4980 0 : case DTC_Link_1:
4981 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
4982 0 : break;
4983 0 : case DTC_Link_2:
4984 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
4985 0 : break;
4986 0 : case DTC_Link_3:
4987 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
4988 0 : break;
4989 0 : case DTC_Link_4:
4990 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
4991 0 : break;
4992 0 : case DTC_Link_5:
4993 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
4994 0 : break;
4995 0 : default: {
4996 0 : __SS__ << "Illegal link index provided: " << link << __E__;
4997 0 : __SS_THROW__;
4998 0 : }
4999 : }
5000 0 : return data[5];
5001 : }
5002 : /// <summary>
5003 : /// Read the Receive RX Packet Count Error bit for the given link
5004 : /// </summary>
5005 : /// <param name="link">Link to read</param>
5006 : /// <returns>Value of the bit</returns>
5007 0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
5008 : {
5009 0 : std::bitset<32> data;
5010 0 : switch (link)
5011 : {
5012 0 : case DTC_Link_0:
5013 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
5014 0 : break;
5015 0 : case DTC_Link_1:
5016 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
5017 0 : break;
5018 0 : case DTC_Link_2:
5019 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
5020 0 : break;
5021 0 : case DTC_Link_3:
5022 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
5023 0 : break;
5024 0 : case DTC_Link_4:
5025 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
5026 0 : break;
5027 0 : case DTC_Link_5:
5028 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
5029 0 : break;
5030 0 : default: {
5031 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5032 0 : __SS_THROW__;
5033 0 : }
5034 : }
5035 0 : return data[4];
5036 : }
5037 : /// <summary>
5038 : /// Read the Receive RX Packet Error bit for the given link
5039 : /// </summary>
5040 : /// <param name="link">Link to read</param>
5041 : /// <returns>Value of the bit</returns>
5042 0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
5043 : {
5044 0 : std::bitset<32> data;
5045 0 : switch (link)
5046 : {
5047 0 : case DTC_Link_0:
5048 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
5049 0 : break;
5050 0 : case DTC_Link_1:
5051 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
5052 0 : break;
5053 0 : case DTC_Link_2:
5054 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
5055 0 : break;
5056 0 : case DTC_Link_3:
5057 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
5058 0 : break;
5059 0 : case DTC_Link_4:
5060 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
5061 0 : break;
5062 0 : case DTC_Link_5:
5063 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
5064 0 : break;
5065 0 : default: {
5066 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5067 0 : __SS_THROW__;
5068 0 : }
5069 : }
5070 0 : return data[3];
5071 : }
5072 : /// <summary>
5073 : /// Read the Receive RX Packet CRC Error bit for the given link
5074 : /// </summary>
5075 : /// <param name="link">Link to read</param>
5076 : /// <returns>Value of the bit</returns>
5077 0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
5078 : {
5079 0 : std::bitset<32> data;
5080 0 : switch (link)
5081 : {
5082 0 : case DTC_Link_0:
5083 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
5084 0 : break;
5085 0 : case DTC_Link_1:
5086 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
5087 0 : break;
5088 0 : case DTC_Link_2:
5089 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
5090 0 : break;
5091 0 : case DTC_Link_3:
5092 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
5093 0 : break;
5094 0 : case DTC_Link_4:
5095 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
5096 0 : break;
5097 0 : case DTC_Link_5:
5098 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
5099 0 : break;
5100 0 : default: {
5101 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5102 0 : __SS_THROW__;
5103 0 : }
5104 : }
5105 0 : return data[2];
5106 : }
5107 : /// <summary>
5108 : /// Read the Receive Data Pending Timeout Error bit for the given link
5109 : /// </summary>
5110 : /// <param name="link">Link to read</param>
5111 : /// <returns>Value of the bit</returns>
5112 0 : bool DTCLib::DTC_Registers::ReadROCLink_DataPendingTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
5113 : {
5114 0 : std::bitset<32> data;
5115 0 : switch (link)
5116 : {
5117 0 : case DTC_Link_0:
5118 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
5119 0 : break;
5120 0 : case DTC_Link_1:
5121 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
5122 0 : break;
5123 0 : case DTC_Link_2:
5124 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
5125 0 : break;
5126 0 : case DTC_Link_3:
5127 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
5128 0 : break;
5129 0 : case DTC_Link_4:
5130 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
5131 0 : break;
5132 0 : case DTC_Link_5:
5133 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
5134 0 : break;
5135 0 : default: {
5136 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5137 0 : __SS_THROW__;
5138 0 : }
5139 : }
5140 0 : return data[1];
5141 : }
5142 : /// <summary>
5143 : /// Read the Receive Data Packet Count Error bit for the given link
5144 : /// </summary>
5145 : /// <param name="link">Link to read</param>
5146 : /// <returns>Value of the bit</returns>
5147 0 : bool DTCLib::DTC_Registers::ReadROCLink_ReceiveDataPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
5148 : {
5149 0 : std::bitset<32> data;
5150 0 : switch (link)
5151 : {
5152 0 : case DTC_Link_0:
5153 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
5154 0 : break;
5155 0 : case DTC_Link_1:
5156 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
5157 0 : break;
5158 0 : case DTC_Link_2:
5159 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
5160 0 : break;
5161 0 : case DTC_Link_3:
5162 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
5163 0 : break;
5164 0 : case DTC_Link_4:
5165 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
5166 0 : break;
5167 0 : case DTC_Link_5:
5168 0 : data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
5169 0 : break;
5170 0 : default: {
5171 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5172 0 : __SS_THROW__;
5173 0 : }
5174 : }
5175 0 : return data[0];
5176 : }
5177 : /// <summary>
5178 : /// Formats the register's current value for register dumps
5179 : /// </summary>
5180 : /// <returns>RegisterFormatter object containing register information</returns>
5181 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink0Error()
5182 : {
5183 0 : auto form = CreateFormatter(DTC_Register_Link0ErrorFlags);
5184 0 : form.description = "ROC Link 0 Error";
5185 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5186 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5187 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5188 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5189 0 : (ReadROCLink_RXPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5190 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5191 0 : (ReadROCLink_RXPacketError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5192 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5193 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5194 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5195 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5196 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5197 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
5198 0 : return form;
5199 0 : }
5200 : /// <summary>
5201 : /// Formats the register's current value for register dumps
5202 : /// </summary>
5203 : /// <returns>RegisterFormatter object containing register information</returns>
5204 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink1Error()
5205 : {
5206 0 : auto form = CreateFormatter(DTC_Register_Link1ErrorFlags);
5207 0 : form.description = "ROC Link 1 Error";
5208 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5209 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5210 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5211 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5212 0 : (ReadROCLink_RXPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5213 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5214 0 : (ReadROCLink_RXPacketError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5215 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5216 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5217 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5218 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5219 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5220 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
5221 0 : return form;
5222 0 : }
5223 : /// <summary>
5224 : /// Formats the register's current value for register dumps
5225 : /// </summary>
5226 : /// <returns>RegisterFormatter object containing register information</returns>
5227 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink2Error()
5228 : {
5229 0 : auto form = CreateFormatter(DTC_Register_Link2ErrorFlags);
5230 0 : form.description = "ROC Link 2 Error";
5231 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5232 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5233 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5234 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5235 0 : (ReadROCLink_RXPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5236 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5237 0 : (ReadROCLink_RXPacketError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5238 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5239 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5240 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5241 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5242 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5243 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
5244 0 : return form;
5245 0 : }
5246 : /// <summary>
5247 : /// Formats the register's current value for register dumps
5248 : /// </summary>
5249 : /// <returns>RegisterFormatter object containing register information</returns>
5250 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink3Error()
5251 : {
5252 0 : auto form = CreateFormatter(DTC_Register_Link3ErrorFlags);
5253 0 : form.description = "ROC Link 3 Error";
5254 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5255 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5256 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5257 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5258 0 : (ReadROCLink_RXPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5259 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5260 0 : (ReadROCLink_RXPacketError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5261 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5262 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5263 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5264 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5265 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5266 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
5267 0 : return form;
5268 0 : }
5269 : /// <summary>
5270 : /// Formats the register's current value for register dumps
5271 : /// </summary>
5272 : /// <returns>RegisterFormatter object containing register information</returns>
5273 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink4Error()
5274 : {
5275 0 : auto form = CreateFormatter(DTC_Register_Link4ErrorFlags);
5276 0 : form.description = "ROC Link 4 Error";
5277 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5278 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5279 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5280 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5281 0 : (ReadROCLink_RXPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5282 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5283 0 : (ReadROCLink_RXPacketError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5284 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5285 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5286 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5287 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5288 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5289 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
5290 0 : return form;
5291 0 : }
5292 : /// <summary>
5293 : /// Formats the register's current value for register dumps
5294 : /// </summary>
5295 : /// <returns>RegisterFormatter object containing register information</returns>
5296 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink5Error()
5297 : {
5298 0 : auto form = CreateFormatter(DTC_Register_Link5ErrorFlags);
5299 0 : form.description = "ROC Link 5 Error";
5300 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5301 0 : form.vals.push_back(std::string("ROC Data Request Sync Error: [") +
5302 0 : (ReadROCLink_ROCDataRequestSyncError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5303 0 : form.vals.push_back(std::string("RX Packet Count Error: [") +
5304 0 : (ReadROCLink_RXPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5305 0 : form.vals.push_back(std::string("RX Packet Error: [") +
5306 0 : (ReadROCLink_RXPacketError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5307 0 : form.vals.push_back(std::string("RX Packet CRC Error: [") +
5308 0 : (ReadROCLink_RXPacketCRCError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5309 0 : form.vals.push_back(std::string("Data Pending Timeout Error: [") +
5310 0 : (ReadROCLink_DataPendingTimeoutError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5311 0 : form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
5312 0 : (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
5313 0 : return form;
5314 0 : }
5315 :
5316 : // CFO Link Error Register
5317 : /// <summary>
5318 : /// Formats the register's current value for register dumps
5319 : /// </summary>
5320 : /// <returns>RegisterFormatter object containing register information</returns>
5321 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOLinkError()
5322 : {
5323 0 : auto form = CreateFormatter(DTC_Register_CFOLinkErrorFlags);
5324 0 : form.description = "CFO Link Settings & Error Flags";
5325 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5326 :
5327 : // bit 9 - Event Start marker tx error at CFO Interface
5328 : // bit 10 - Clock marker tx error at CFO Interface
5329 : // bit 11 - RTF 40MHz clock phase has shifted
5330 : // bit 12 - Illegal marker timing in RTF 40MHz clock count
5331 : // bit 13 - Moving data from CFO rx to tx clock domain has marker corruption at "external" CFO Interface
5332 0 : form.vals.push_back(std::string("CFO Event Start Marker tx Error: [") +
5333 0 : (((form.value >> 9) & 1) ? "x" : " ") + "]");
5334 0 : form.vals.push_back(std::string("CFO Clock Marker tx Error: [") +
5335 0 : (((form.value >> 10) & 1) ? "x" : " ") + "]");
5336 0 : form.vals.push_back(std::string("CFO RTF 40MHz Phase Shift Error: [") +
5337 0 : (((form.value >> 11) & 1) ? "x" : " ") + "]");
5338 0 : form.vals.push_back(std::string("CFO Illegal Marker Over Link Timing: [") +
5339 0 : (((form.value >> 12) & 1) ? "x" : " ") + "]");
5340 0 : form.vals.push_back(std::string("CFO Rx-to-Tx Data Corruption Error: [") +
5341 0 : (((form.value >> 13) & 1) ? "x" : " ") + "]");
5342 0 : int measuredPos = (form.value >> 16) & 7;
5343 0 : int impliedPos = 2 - measuredPos; // legal values are -2 -1 0 1 2 (if measured value is 4 3 2 1 0, respsectively)
5344 0 : form.vals.push_back(std::string("CFO Measured Marker position {0,4}: [") +
5345 0 : std::to_string(measuredPos) + "] ==> " + std::to_string(impliedPos));
5346 0 : form.vals.push_back(std::string("CFO Permanent Offset setting {-2,2}: [") +
5347 0 : std::to_string(ReadCFOSamplePermanentOffset(form.value)) + "]");
5348 :
5349 0 : form.vals.push_back(""); // spacer
5350 :
5351 : // also show link enables for CFO and EVB
5352 0 : uint32_t val = ReadRegister_(CFOandDTC_Register_LinkEnable);
5353 0 : form.vals.push_back(std::string("CFO Link Rx Enabled: [") +
5354 0 : (ReadLinkEnabled(DTC_Link_CFO, val).ReceiveEnable ? "x" : " ") + "]");
5355 0 : form.vals.push_back(std::string("CFO Link Tx Enabled: [") +
5356 0 : (ReadLinkEnabled(DTC_Link_CFO, val).TransmitEnable ? "x" : " ") + "]");
5357 0 : form.vals.push_back(std::string("EVB Link Rx Enabled: [") +
5358 0 : (ReadLinkEnabled(DTC_Link_EVB, val).ReceiveEnable ? "x" : " ") + "]");
5359 0 : form.vals.push_back(std::string("EVB Link Tx Enabled: [") +
5360 0 : (ReadLinkEnabled(DTC_Link_EVB, val).TransmitEnable ? "x" : " ") + "]");
5361 :
5362 0 : return form;
5363 0 : }
5364 :
5365 : // Link Mux Error Register
5366 : /// <summary>
5367 : /// Read the DCS Mux Decode Error bit
5368 : /// </summary>
5369 : /// <returns>Value of the bit</returns>
5370 0 : bool DTCLib::DTC_Registers::ReadDCSMuxDecodeError(std::optional<uint32_t> val)
5371 : {
5372 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
5373 0 : return data[1];
5374 : }
5375 : /// <summary>
5376 : /// Read the Data Mux Decode Error bit
5377 : /// </summary>
5378 : /// <returns>Value of the bit</returns>
5379 0 : bool DTCLib::DTC_Registers::ReadDataMuxDecodeError(std::optional<uint32_t> val)
5380 : {
5381 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
5382 0 : return data[0];
5383 : }
5384 : /// <summary>
5385 : /// Formats the register's current value for register dumps
5386 : /// </summary>
5387 : /// <returns>RegisterFormatter object containing register information</returns>
5388 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkMuxError()
5389 : {
5390 0 : auto form = CreateFormatter(DTC_Register_LinkMuxErrorFlags);
5391 0 : form.description = "Link Mux Error Flags";
5392 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5393 0 : form.vals.push_back(std::string("DCS Mux Decode Error: [") + (ReadDCSMuxDecodeError(form.value) ? "x" : " ") + "]");
5394 0 : form.vals.push_back(std::string("Data Mux Decode Error: [") + (ReadDataMuxDecodeError(form.value) ? "x" : " ") + "]");
5395 0 : return form;
5396 0 : }
5397 :
5398 : // SFP Control/Status Register
5399 : /// <summary>
5400 : /// Read the SFP Present bit
5401 : /// </summary>
5402 : /// <returns>Value of the bit</returns>
5403 0 : bool DTCLib::DTC_Registers::ReadSFPPresent(std::optional<uint32_t> val)
5404 : {
5405 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
5406 0 : return data[31];
5407 : }
5408 :
5409 : /// <summary>
5410 : /// Read the SFP LOS bit
5411 : /// </summary>
5412 : /// <returns>Value of the bit</returns>
5413 0 : bool DTCLib::DTC_Registers::ReadSFPLOS(std::optional<uint32_t> val)
5414 : {
5415 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
5416 0 : return data[17];
5417 : }
5418 :
5419 : /// <summary>
5420 : /// Read the SFP TX Fault bit
5421 : /// </summary>
5422 : /// <returns>Value of the bit</returns>
5423 0 : bool DTCLib::DTC_Registers::ReadSFPTXFault(std::optional<uint32_t> val)
5424 : {
5425 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
5426 0 : return data[16];
5427 : }
5428 :
5429 : /// <summary>
5430 : /// Set the SFP Rate Select bit high
5431 : /// </summary>
5432 0 : void DTCLib::DTC_Registers::EnableSFPRateSelect()
5433 : {
5434 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
5435 0 : data[1] = 1;
5436 0 : WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
5437 0 : }
5438 :
5439 : /// <summary>
5440 : /// Set the SFP Rate Select bit low
5441 : /// </summary>
5442 0 : void DTCLib::DTC_Registers::DisableSFPRateSelect()
5443 : {
5444 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
5445 0 : data[1] = 0;
5446 0 : WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
5447 0 : }
5448 :
5449 : /// <summary>
5450 : /// Read the value of the SFP Rate Select bit
5451 : /// </summary>
5452 : /// <returns>The value of the SFP Rate Select bit</returns>
5453 0 : bool DTCLib::DTC_Registers::ReadSFPRateSelect(std::optional<uint32_t> val)
5454 : {
5455 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
5456 0 : return data[1];
5457 : }
5458 :
5459 : /// <summary>
5460 : /// Disable SFP TX
5461 : /// </summary>
5462 0 : void DTCLib::DTC_Registers::DisableSFPTX()
5463 : {
5464 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
5465 0 : data[0] = 1;
5466 0 : WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
5467 0 : }
5468 :
5469 : /// <summary>
5470 : /// Enable SFP TX
5471 : /// </summary>
5472 0 : void DTCLib::DTC_Registers::EnableSFPTX()
5473 : {
5474 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
5475 0 : data[0] = 0;
5476 0 : WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
5477 0 : }
5478 :
5479 : /// <summary>
5480 : /// Read the SFP TX Disable bit
5481 : /// </summary>
5482 : /// <returns>Value of the SFP TX Disable bit</returns>
5483 0 : bool DTCLib::DTC_Registers::ReadSFPTXDisable(std::optional<uint32_t> val)
5484 : {
5485 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
5486 0 : return data[0];
5487 : }
5488 :
5489 : /// <summary>
5490 : /// Formats the register's current value for register dumps
5491 : /// </summary>
5492 : /// <returns>RegisterFormatter object containing register information</returns>
5493 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPControlStatus()
5494 : {
5495 0 : auto form = CreateFormatter(DTC_Register_SFPControlStatus);
5496 0 : form.description = "SFP Control Status";
5497 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5498 0 : form.vals.push_back(std::string("SFP Present: [") + (ReadSFPPresent(form.value) ? "x" : " ") + "]");
5499 0 : form.vals.push_back(std::string("SFP LOS: [") + (ReadSFPLOS(form.value) ? "x" : " ") + "]");
5500 0 : form.vals.push_back(std::string("SFP TX Fault: [") + (ReadSFPTXFault(form.value) ? "x" : " ") + "]");
5501 0 : form.vals.push_back(std::string("SFP Rate Select: [") + (ReadSFPRateSelect(form.value) ? "x" : " ") + "]");
5502 0 : form.vals.push_back(std::string("SFP TX Disable: [") + (ReadSFPTXDisable(form.value) ? "x" : " ") + "]");
5503 0 : return form;
5504 0 : }
5505 :
5506 0 : uint32_t DTCLib::DTC_Registers::ReadRXCDRUnlockCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
5507 : {
5508 0 : switch (link)
5509 : {
5510 0 : case DTC_Link_0:
5511 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link0);
5512 0 : case DTC_Link_1:
5513 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link1);
5514 0 : case DTC_Link_2:
5515 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link2);
5516 0 : case DTC_Link_3:
5517 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link3);
5518 0 : case DTC_Link_4:
5519 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link4);
5520 0 : case DTC_Link_5:
5521 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link5);
5522 0 : case DTC_Link_CFO:
5523 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_CFOLink);
5524 0 : default: {
5525 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5526 0 : __SS_THROW__;
5527 0 : }
5528 : }
5529 : }
5530 :
5531 0 : void DTCLib::DTC_Registers::ClearRXCDRUnlockCount(DTC_Link_ID const& link)
5532 : {
5533 0 : switch (link)
5534 : {
5535 0 : case DTC_Link_0:
5536 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link0);
5537 0 : break;
5538 0 : case DTC_Link_1:
5539 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link1);
5540 0 : break;
5541 0 : case DTC_Link_2:
5542 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link2);
5543 0 : break;
5544 0 : case DTC_Link_3:
5545 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link3);
5546 0 : break;
5547 0 : case DTC_Link_4:
5548 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link4);
5549 0 : break;
5550 0 : case DTC_Link_5:
5551 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link5);
5552 0 : break;
5553 0 : case DTC_Link_CFO:
5554 0 : WriteRegister_(0, DTC_Register_RXCDRUnlockCount_CFOLink);
5555 0 : break;
5556 0 : default: {
5557 0 : __SS__ << "Illegal link index provided: " << link << __E__;
5558 0 : __SS_THROW__;
5559 0 : }
5560 : }
5561 0 : }
5562 :
5563 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink0()
5564 : {
5565 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link0);
5566 0 : form.description = "RX CDR Unlock Count Link 0";
5567 0 : std::stringstream o;
5568 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_0, form.value);
5569 0 : form.vals.push_back(o.str());
5570 0 : return form;
5571 0 : }
5572 :
5573 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink1()
5574 : {
5575 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link1);
5576 0 : form.description = "RX CDR Unlock Count Link 1";
5577 0 : std::stringstream o;
5578 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_1, form.value);
5579 0 : form.vals.push_back(o.str());
5580 0 : return form;
5581 0 : }
5582 :
5583 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink2()
5584 : {
5585 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link2);
5586 0 : form.description = "RX CDR Unlock Count Link 2";
5587 0 : std::stringstream o;
5588 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_2, form.value);
5589 0 : form.vals.push_back(o.str());
5590 0 : return form;
5591 0 : }
5592 :
5593 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink3()
5594 : {
5595 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link3);
5596 0 : form.description = "RX CDR Unlock Count Link 3";
5597 0 : std::stringstream o;
5598 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_3, form.value);
5599 0 : form.vals.push_back(o.str());
5600 0 : return form;
5601 0 : }
5602 :
5603 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink4()
5604 : {
5605 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link4);
5606 0 : form.description = "RX CDR Unlock Count Link 4";
5607 0 : std::stringstream o;
5608 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_4, form.value);
5609 0 : form.vals.push_back(o.str());
5610 0 : return form;
5611 0 : }
5612 :
5613 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink5()
5614 : {
5615 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link5);
5616 0 : form.description = "RX CDR Unlock Count Link 5";
5617 0 : std::stringstream o;
5618 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_5, form.value);
5619 0 : form.vals.push_back(o.str());
5620 0 : return form;
5621 0 : }
5622 :
5623 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountCFOLink()
5624 : {
5625 0 : auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_CFOLink);
5626 0 : form.description = "RX CDR Unlock Count CFO Link";
5627 0 : std::stringstream o;
5628 0 : o << std::dec << ReadRXCDRUnlockCount(DTC_Link_CFO, form.value);
5629 0 : form.vals.push_back(o.str());
5630 0 : return form;
5631 0 : }
5632 :
5633 0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorUnlockCount(std::optional<uint32_t> val)
5634 : {
5635 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuatorLossOfLockCount);
5636 : }
5637 :
5638 0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorUnlockCount()
5639 : {
5640 0 : WriteRegister_(1, DTC_Register_JitterAttenuatorLossOfLockCount);
5641 0 : }
5642 :
5643 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorUnlockCount()
5644 : {
5645 0 : auto form = CreateFormatter(DTC_Register_JitterAttenuatorLossOfLockCount);
5646 0 : form.description = "RX Jitter Attenuator Unlock Count";
5647 0 : std::stringstream o;
5648 0 : o << std::dec << ReadJitterAttenuatorUnlockCount(form.value);
5649 0 : form.vals.push_back(o.str());
5650 0 : return form;
5651 0 : }
5652 :
5653 0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLinkEventStartCharacterErrorCount(std::optional<uint32_t> val)
5654 : {
5655 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkEventStartErrorCount);
5656 : }
5657 :
5658 0 : void DTCLib::DTC_Registers::ClearRXCFOLinkEventStartCharacterErrorCount()
5659 : {
5660 0 : WriteRegister_(0, DTC_Register_CFOLinkEventStartErrorCount);
5661 0 : }
5662 :
5663 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLinkEventStartCharacterErrorCount()
5664 : {
5665 0 : auto form = CreateFormatter(DTC_Register_CFOLinkEventStartErrorCount);
5666 0 : form.description = "CFO Link Event Start Error Count";
5667 0 : std::stringstream o;
5668 0 : o << std::dec << ReadRXCFOLinkEventStartCharacterErrorCount(form.value);
5669 0 : form.vals.push_back(o.str());
5670 0 : return form;
5671 0 : }
5672 :
5673 0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLink40MHzCharacterErrorCount(std::optional<uint32_t> val)
5674 : {
5675 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLink40MHzErrorCount);
5676 : }
5677 :
5678 0 : void DTCLib::DTC_Registers::ClearRXCFOLink40MHzCharacterErrorCount()
5679 : {
5680 0 : WriteRegister_(0, DTC_Register_CFOLink40MHzErrorCount);
5681 0 : }
5682 :
5683 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLink40MHzCharacterErrorCount()
5684 : {
5685 0 : auto form = CreateFormatter(DTC_Register_CFOLink40MHzErrorCount);
5686 0 : form.description = "CFO Link 40 MHz Error Count";
5687 0 : std::stringstream o;
5688 0 : o << std::dec << ReadRXCFOLink40MHzCharacterErrorCount(form.value);
5689 0 : form.vals.push_back(o.str());
5690 0 : return form;
5691 0 : }
5692 :
5693 0 : uint32_t DTCLib::DTC_Registers::ReadInputBufferFragmentDumpCount(std::optional<uint32_t> val)
5694 : {
5695 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferDropCount);
5696 : }
5697 :
5698 0 : void DTCLib::DTC_Registers::ClearInputBufferFragmentDumpCount()
5699 : {
5700 0 : WriteRegister_(0, DTC_Register_InputBufferDropCount);
5701 0 : }
5702 :
5703 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatInputBufferFragmentDumpCount()
5704 : {
5705 0 : auto form = CreateFormatter(DTC_Register_InputBufferDropCount);
5706 0 : form.description = "Input Buffer Fragment Drop Count";
5707 0 : std::stringstream o;
5708 0 : o << std::dec << ReadInputBufferFragmentDumpCount(form.value);
5709 0 : form.vals.push_back(o.str());
5710 0 : return form;
5711 0 : }
5712 :
5713 0 : uint32_t DTCLib::DTC_Registers::ReadOutputBufferFragmentDumpCount(std::optional<uint32_t> val)
5714 : {
5715 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferDropCount);
5716 : }
5717 :
5718 0 : void DTCLib::DTC_Registers::ClearOutputBufferFragmentDumpCount()
5719 : {
5720 0 : WriteRegister_(0, DTC_Register_OutputBufferDropCount);
5721 0 : }
5722 :
5723 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatOutputBufferFragmentDumpCount()
5724 : {
5725 0 : auto form = CreateFormatter(DTC_Register_OutputBufferDropCount);
5726 0 : form.description = "Output Buffer Fragment Drop Count";
5727 0 : std::stringstream o;
5728 0 : o << std::dec << ReadOutputBufferFragmentDumpCount(form.value);
5729 0 : form.vals.push_back(o.str());
5730 0 : return form;
5731 0 : }
5732 :
5733 0 : uint32_t DTCLib::DTC_Registers::ReadROCDCSResponseTimer(std::optional<uint32_t> val)
5734 : {
5735 0 : __SS__ << "The SetROCDCSResponseTimer register was removed as of December 2023 and set to a 1ms constant value in the DTC. Do not use." << __E__;
5736 0 : __SS_THROW__;
5737 : return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCDCSTimerPreset);
5738 0 : }
5739 :
5740 0 : void DTCLib::DTC_Registers::SetROCDCSResponseTimer(uint32_t timer)
5741 : {
5742 0 : __SS__ << "The SetROCDCSResponseTimer register was removed as of December 2023 and set to a 1ms constant value in the DTC. Do not use." << __E__;
5743 0 : __SS_THROW__;
5744 : WriteRegister_(timer, DTC_Register_ROCDCSTimerPreset);
5745 0 : }
5746 :
5747 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCDCSResponseTimerPreset()
5748 : {
5749 0 : auto form = CreateFormatter(DTC_Register_ROCDCSTimerPreset);
5750 0 : form.description = "ROC DCS Response Timer Preset (*5ns)";
5751 0 : std::stringstream o;
5752 0 : o << std::dec << ReadROCDCSResponseTimer(form.value);
5753 0 : form.vals.push_back(o.str());
5754 0 : return form;
5755 0 : }
5756 :
5757 0 : void DTCLib::DTC_Registers::SetSoftwareDataRequest(const DTC_EventWindowTag& ts)
5758 : {
5759 0 : auto timestamp = ts.GetEventWindowTag();
5760 0 : auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
5761 0 : timestamp >>= 32;
5762 0 : auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
5763 :
5764 0 : WriteRegister_(timestampHigh, DTC_Register_DataRequest_High);
5765 0 : WriteRegister_(timestampLow, DTC_Register_DataRequest_Low); // this triggers the DR
5766 0 : }
5767 :
5768 0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadSoftwareDataRequest(std::optional<uint32_t> val)
5769 : {
5770 0 : auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_DataRequest_Low);
5771 0 : DTC_EventWindowTag output;
5772 0 : output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_DataRequest_High)));
5773 0 : return output;
5774 0 : }
5775 :
5776 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestLow()
5777 : {
5778 0 : auto form = CreateFormatter(DTC_Register_DataRequest_Low);
5779 0 : form.description = "Software Data Request Low";
5780 0 : std::stringstream o;
5781 0 : o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_Low);
5782 0 : form.vals.push_back(o.str());
5783 0 : return form;
5784 0 : }
5785 :
5786 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestHigh()
5787 : {
5788 0 : auto form = CreateFormatter(DTC_Register_DataRequest_High);
5789 0 : form.description = "Software Data Request High";
5790 0 : std::stringstream o;
5791 0 : o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_High);
5792 0 : form.vals.push_back(o.str());
5793 0 : return form;
5794 0 : }
5795 :
5796 : // FPGA PROM Program Status Register
5797 : /// <summary>
5798 : /// Read the full bit on the FPGA PROM FIFO
5799 : /// </summary>
5800 : /// <returns>the full bit on the FPGA PROM FIFO</returns>
5801 0 : bool DTCLib::DTC_Registers::ReadFPGAPROMProgramFIFOFull(std::optional<uint32_t> val)
5802 : {
5803 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
5804 0 : return dataSet[1];
5805 : }
5806 :
5807 : /// <summary>
5808 : /// Read whether the FPGA PROM is ready for data
5809 : /// </summary>
5810 : /// <returns>whether the FPGA PROM is ready for data</returns>
5811 0 : bool DTCLib::DTC_Registers::ReadFPGAPROMReady(std::optional<uint32_t> val)
5812 : {
5813 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
5814 0 : return dataSet[0];
5815 : }
5816 :
5817 : /// <summary>
5818 : /// Formats the register's current value for register dumps
5819 : /// </summary>
5820 : /// <returns>RegisterFormatter object containing register information</returns>
5821 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGAPROMProgramStatus()
5822 : {
5823 0 : auto form = CreateFormatter(DTC_Register_FPGAPROMProgramStatus);
5824 0 : form.description = "FPGA PROM Program Status";
5825 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5826 0 : form.vals.push_back(std::string("FPGA PROM Program FIFO Full: [") + (ReadFPGAPROMProgramFIFOFull(form.value) ? "x" : " ") +
5827 : "]");
5828 0 : form.vals.push_back(std::string("FPGA PROM Ready: [") + (ReadFPGAPROMReady(form.value) ? "x" : " ") + "]");
5829 0 : return form;
5830 0 : }
5831 :
5832 : // FPGA Core Access Register
5833 : /// <summary>
5834 : /// Performs the chants necessary to reload the DTC firmware
5835 : /// </summary>
5836 0 : void DTCLib::DTC_Registers::ReloadFPGAFirmware()
5837 : {
5838 0 : WriteRegister_(0xFFFFFFFF, DTC_Register_FPGACoreAccess);
5839 0 : while (ReadFPGACoreAccessFIFOFull())
5840 : {
5841 0 : usleep(10);
5842 : }
5843 0 : WriteRegister_(0xAA995566, DTC_Register_FPGACoreAccess);
5844 0 : while (ReadFPGACoreAccessFIFOFull())
5845 : {
5846 0 : usleep(10);
5847 : }
5848 0 : WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
5849 0 : while (ReadFPGACoreAccessFIFOFull())
5850 : {
5851 0 : usleep(10);
5852 : }
5853 0 : WriteRegister_(0x30020001, DTC_Register_FPGACoreAccess);
5854 0 : while (ReadFPGACoreAccessFIFOFull())
5855 : {
5856 0 : usleep(10);
5857 : }
5858 0 : WriteRegister_(0x00000000, DTC_Register_FPGACoreAccess);
5859 0 : while (ReadFPGACoreAccessFIFOFull())
5860 : {
5861 0 : usleep(10);
5862 : }
5863 0 : WriteRegister_(0x30008001, DTC_Register_FPGACoreAccess);
5864 0 : while (ReadFPGACoreAccessFIFOFull())
5865 : {
5866 0 : usleep(10);
5867 : }
5868 0 : WriteRegister_(0x0000000F, DTC_Register_FPGACoreAccess);
5869 0 : while (ReadFPGACoreAccessFIFOFull())
5870 : {
5871 0 : usleep(10);
5872 : }
5873 0 : WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
5874 0 : }
5875 :
5876 : /// <summary>
5877 : /// Read the FPGA Core Access FIFO Full bit
5878 : /// </summary>
5879 : /// <returns>Whether the FPGA Core Access FIFO is full</returns>
5880 0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOFull(std::optional<uint32_t> val)
5881 : {
5882 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
5883 0 : return dataSet[1];
5884 : }
5885 :
5886 : /// <summary>
5887 : /// Read the FPGA Core Access FIFO Empty bit
5888 : /// </summary>
5889 : /// <returns>Whether the FPGA Core Access FIFO is empty</returns>
5890 0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOEmpty(std::optional<uint32_t> val)
5891 : {
5892 0 : std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
5893 0 : return dataSet[0];
5894 : }
5895 :
5896 : /// <summary>
5897 : /// Formats the register's current value for register dumps
5898 : /// </summary>
5899 : /// <returns>RegisterFormatter object containing register information</returns>
5900 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGACoreAccess()
5901 : {
5902 0 : auto form = CreateFormatter(DTC_Register_FPGACoreAccess);
5903 0 : form.description = "FPGA Core Access";
5904 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
5905 0 : form.vals.push_back(std::string("FPGA Core Access FIFO Full: [") + (ReadFPGACoreAccessFIFOFull(form.value) ? "x" : " ") + "]");
5906 0 : form.vals.push_back(std::string("FPGA Core Access FIFO Empty: [") + (ReadFPGACoreAccessFIFOEmpty(form.value) ? "x" : " ") +
5907 : "]");
5908 :
5909 0 : return form;
5910 0 : }
5911 :
5912 0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
5913 : {
5914 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5915 0 : return data[9];
5916 : }
5917 :
5918 0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
5919 : {
5920 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5921 0 : return data[8];
5922 : }
5923 :
5924 0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
5925 : {
5926 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5927 0 : return data[7];
5928 : }
5929 :
5930 0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
5931 : {
5932 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5933 0 : return data[6];
5934 : }
5935 :
5936 0 : bool DTCLib::DTC_Registers::ReadLatchedSpareSMAInputOKError(std::optional<uint32_t> val)
5937 : {
5938 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5939 0 : return data[5];
5940 : }
5941 :
5942 0 : void DTCLib::DTC_Registers::ClearLatchedSpareSMAInputOKError()
5943 : {
5944 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5945 0 : data[5] = 1;
5946 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
5947 0 : }
5948 :
5949 0 : bool DTCLib::DTC_Registers::ReadLatchedEventMarkerSMAInputOKError(std::optional<uint32_t> val)
5950 : {
5951 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5952 0 : return data[4];
5953 : }
5954 :
5955 0 : void DTCLib::DTC_Registers::ClearLatchedEventMarkerSMASMAInputOKError()
5956 : {
5957 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5958 0 : data[4] = 1;
5959 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
5960 0 : }
5961 :
5962 0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
5963 : {
5964 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5965 0 : return data[3];
5966 : }
5967 :
5968 0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink3()
5969 : {
5970 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5971 0 : data[3] = 1;
5972 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
5973 0 : }
5974 :
5975 0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
5976 : {
5977 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5978 0 : return data[2];
5979 : }
5980 :
5981 0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink2()
5982 : {
5983 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5984 0 : data[2] = 1;
5985 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
5986 0 : }
5987 :
5988 0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
5989 : {
5990 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5991 0 : return data[1];
5992 : }
5993 :
5994 0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink1()
5995 : {
5996 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
5997 0 : data[1] = 1;
5998 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
5999 0 : }
6000 :
6001 0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
6002 : {
6003 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
6004 0 : return data[0];
6005 : }
6006 :
6007 0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink0()
6008 : {
6009 0 : std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
6010 0 : data[0] = 1;
6011 0 : WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
6012 0 : }
6013 :
6014 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSlowOpticalLinkControlStatus()
6015 : {
6016 0 : auto form = CreateFormatter(DTC_Register_SFPControlStatus);
6017 0 : form.description = "Slow Optical Link Control Status";
6018 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
6019 0 : form.vals.push_back(std::string("RX OK SOL Link 3: [") + (ReadRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
6020 0 : form.vals.push_back(std::string("RX OK SOL Link 2: [") + (ReadRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
6021 0 : form.vals.push_back(std::string("RX OK SOL Link 1: [") + (ReadRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
6022 0 : form.vals.push_back(std::string("RX OK SOL Link 0: [") + (ReadRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
6023 0 : form.vals.push_back(std::string("Latched Spare SMA Input: [") + (ReadLatchedSpareSMAInputOKError(form.value) ? "x" : " ") + "]");
6024 0 : form.vals.push_back(std::string("Latched Event Marker Input: [") + (ReadLatchedEventMarkerSMAInputOKError(form.value) ? "x" : " ") + "]");
6025 0 : form.vals.push_back(std::string("Latched RX OK SOL Link 3: [") + (ReadLatchedRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
6026 0 : form.vals.push_back(std::string("Latched RX OK SOL Link 2: [") + (ReadLatchedRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
6027 0 : form.vals.push_back(std::string("Latched RX OK SOL Link 1: [") + (ReadLatchedRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
6028 0 : form.vals.push_back(std::string("Latched RX OK SOL Link 0: [") + (ReadLatchedRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
6029 0 : return form;
6030 0 : }
6031 :
6032 0 : bool DTCLib::DTC_Registers::ReadSERDESInduceErrorEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
6033 : {
6034 0 : std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
6035 0 : return data[link];
6036 : }
6037 :
6038 0 : void DTCLib::DTC_Registers::EnableSERDESInduceError(DTC_Link_ID const& link)
6039 : {
6040 0 : SetBit_(DTC_Register_DiagSERDESErrorEnable, link, true);
6041 0 : }
6042 :
6043 0 : void DTCLib::DTC_Registers::DisableSERDESInduceError(DTC_Link_ID const& link)
6044 : {
6045 0 : std::bitset<32> data = ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
6046 0 : data[link] = 0;
6047 0 : WriteRegister_(data.to_ulong(), DTC_Register_DiagSERDESErrorEnable);
6048 0 : }
6049 :
6050 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorEnable()
6051 : {
6052 0 : auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
6053 0 : form.description = "SERDES Induce Error Enable";
6054 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
6055 0 : for (auto r : DTC_ROC_Links)
6056 0 : form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
6057 0 : (ReadSERDESInduceErrorEnable(r, form.value) ? "x" : " ") + "]");
6058 :
6059 0 : return form;
6060 0 : }
6061 :
6062 0 : uint32_t DTCLib::DTC_Registers::ReadSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, std::optional<uint32_t> val)
6063 : {
6064 0 : switch (link)
6065 : {
6066 0 : case DTC_Link_0:
6067 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket0);
6068 0 : case DTC_Link_1:
6069 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket1);
6070 0 : case DTC_Link_2:
6071 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket2);
6072 0 : case DTC_Link_3:
6073 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket3);
6074 0 : case DTC_Link_4:
6075 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket4);
6076 0 : case DTC_Link_5:
6077 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket5);
6078 0 : default: {
6079 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6080 0 : __SS_THROW__;
6081 0 : }
6082 : }
6083 : }
6084 :
6085 0 : void DTCLib::DTC_Registers::SetSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, uint32_t sequence)
6086 : {
6087 0 : switch (link)
6088 : {
6089 0 : case DTC_Link_0:
6090 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket0);
6091 0 : break;
6092 0 : case DTC_Link_1:
6093 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket1);
6094 0 : break;
6095 0 : case DTC_Link_2:
6096 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket2);
6097 0 : break;
6098 0 : case DTC_Link_3:
6099 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket3);
6100 0 : break;
6101 0 : case DTC_Link_4:
6102 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket4);
6103 0 : break;
6104 0 : case DTC_Link_5:
6105 0 : WriteRegister_(sequence, DTC_Register_DiagSERDESPacket5);
6106 0 : break;
6107 0 : default: {
6108 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6109 0 : __SS_THROW__;
6110 0 : }
6111 : }
6112 0 : }
6113 :
6114 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink0()
6115 : {
6116 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket0);
6117 0 : form.description = "Link 0 Induced Error Sequence Number";
6118 0 : std::stringstream o;
6119 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_0, form.value);
6120 0 : form.vals.push_back(o.str());
6121 0 : return form;
6122 0 : }
6123 :
6124 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink1()
6125 : {
6126 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket1);
6127 0 : form.description = "Link 1 Induced Error Sequence Number";
6128 0 : std::stringstream o;
6129 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_1, form.value);
6130 0 : form.vals.push_back(o.str());
6131 0 : return form;
6132 0 : }
6133 :
6134 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink2()
6135 : {
6136 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket2);
6137 0 : form.description = "Link 2 Induced Error Sequence Number";
6138 0 : std::stringstream o;
6139 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_2, form.value);
6140 0 : form.vals.push_back(o.str());
6141 0 : return form;
6142 0 : }
6143 :
6144 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink3()
6145 : {
6146 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket3);
6147 0 : form.description = "Link 3 Induced Error Sequence Number";
6148 0 : std::stringstream o;
6149 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_3, form.value);
6150 0 : form.vals.push_back(o.str());
6151 0 : return form;
6152 0 : }
6153 :
6154 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink4()
6155 : {
6156 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket4);
6157 0 : form.description = "Link 4 Induced Error Sequence Number";
6158 0 : std::stringstream o;
6159 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_4, form.value);
6160 0 : form.vals.push_back(o.str());
6161 0 : return form;
6162 0 : }
6163 :
6164 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink5()
6165 : {
6166 0 : auto form = CreateFormatter(DTC_Register_DiagSERDESPacket5);
6167 0 : form.description = "Link 5 Induced Error Sequence Number";
6168 0 : std::stringstream o;
6169 0 : o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_5, form.value);
6170 0 : form.vals.push_back(o.str());
6171 0 : return form;
6172 0 : }
6173 :
6174 : // DTCLib::DTC_DDRFlags DTCLib::DTC_Registers::ReadDDRFlags(uint8_t buffer_id)
6175 : // {
6176 : // return DTC_DDRFlags(ReadDDRLinkBufferFullFlags()[buffer_id],
6177 : // ReadDDRLinkBufferEmptyFlags()[buffer_id],
6178 : // ReadDDRLinkBufferHalfFullFlags()[buffer_id],
6179 : // ReadDDREventBuilderBufferFullFlags()[buffer_id],
6180 : // ReadDDREventBuilderBufferEmptyFlags()[buffer_id],
6181 : // ReadDDREventBuilderBufferHalfFullFlags()[buffer_id]);
6182 : // }
6183 :
6184 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferFullFlags()
6185 : // {
6186 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags0);
6187 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags1);
6188 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags2);
6189 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags3);
6190 : // std::bitset<128> out;
6191 : // for (size_t ii = 0; ii < 32; ++ii)
6192 : // {
6193 : // out[ii] = (word0 >> ii) & 0x1;
6194 : // out[ii + 32] = (word1 >> ii) & 0x1;
6195 : // out[ii + 64] = (word2 >> ii) & 0x1;
6196 : // out[ii + 96] = (word3 >> ii) & 0x1;
6197 : // }
6198 : // return out;
6199 : // }
6200 :
6201 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferEmptyFlags()
6202 : // {
6203 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags0);
6204 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags1);
6205 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags2);
6206 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags3);
6207 : // std::bitset<128> out;
6208 : // for (size_t ii = 0; ii < 32; ++ii)
6209 : // {
6210 : // out[ii] = (word0 >> ii) & 0x1;
6211 : // out[ii + 32] = (word1 >> ii) & 0x1;
6212 : // out[ii + 64] = (word2 >> ii) & 0x1;
6213 : // out[ii + 96] = (word3 >> ii) & 0x1;
6214 : // }
6215 : // return out;
6216 : // }
6217 :
6218 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferHalfFullFlags()
6219 : // {
6220 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags0);
6221 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags1);
6222 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags2);
6223 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags3);
6224 : // std::bitset<128> out;
6225 : // for (size_t ii = 0; ii < 32; ++ii)
6226 : // {
6227 : // out[ii] = (word0 >> ii) & 0x1;
6228 : // out[ii + 32] = (word1 >> ii) & 0x1;
6229 : // out[ii + 64] = (word2 >> ii) & 0x1;
6230 : // out[ii + 96] = (word3 >> ii) & 0x1;
6231 : // }
6232 : // return out;
6233 : // }
6234 :
6235 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferFullFlags()
6236 : // {
6237 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags0);
6238 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags1);
6239 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags2);
6240 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags3);
6241 : // std::bitset<128> out;
6242 : // for (size_t ii = 0; ii < 32; ++ii)
6243 : // {
6244 : // out[ii] = (word0 >> ii) & 0x1;
6245 : // out[ii + 32] = (word1 >> ii) & 0x1;
6246 : // out[ii + 64] = (word2 >> ii) & 0x1;
6247 : // out[ii + 96] = (word3 >> ii) & 0x1;
6248 : // }
6249 : // return out;
6250 : // }
6251 :
6252 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferEmptyFlags()
6253 : // {
6254 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags0);
6255 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags1);
6256 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags2);
6257 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags3);
6258 : // std::bitset<128> out;
6259 : // for (size_t ii = 0; ii < 32; ++ii)
6260 : // {
6261 : // out[ii] = (word0 >> ii) & 0x1;
6262 : // out[ii + 32] = (word1 >> ii) & 0x1;
6263 : // out[ii + 64] = (word2 >> ii) & 0x1;
6264 : // out[ii + 96] = (word3 >> ii) & 0x1;
6265 : // }
6266 : // return out;
6267 : // }
6268 :
6269 : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferHalfFullFlags()
6270 : // {
6271 : // uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags0);
6272 : // uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags1);
6273 : // uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags2);
6274 : // uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags3);
6275 : // std::bitset<128> out;
6276 : // for (size_t ii = 0; ii < 32; ++ii)
6277 : // {
6278 : // out[ii] = (word0 >> ii) & 0x1;
6279 : // out[ii + 32] = (word1 >> ii) & 0x1;
6280 : // out[ii + 64] = (word2 >> ii) & 0x1;
6281 : // out[ii + 96] = (word3 >> ii) & 0x1;
6282 : // }
6283 : // return out;
6284 : // }
6285 :
6286 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags0()
6287 : // {
6288 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
6289 : // form.description = "DDR Link Buffer Empty Flags 0-31";
6290 : // return form;
6291 : // }
6292 :
6293 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags1()
6294 : // {
6295 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
6296 : // form.description = "DDR Link Buffer Empty Flags 63-32";
6297 : // return form;
6298 : // }
6299 :
6300 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags2()
6301 : // {
6302 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
6303 : // form.description = "DDR Link Buffer Empty Flags 95-64";
6304 : // return form;
6305 : // }
6306 :
6307 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags3()
6308 : // {
6309 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
6310 : // form.description = "DDR Link Buffer Empty Flags 127-96";
6311 : // return form;
6312 : // }
6313 :
6314 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags0()
6315 : // {
6316 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
6317 : // form.description = "DDR Link Buffer Half-Full Flags 0-31";
6318 : // return form;
6319 : // }
6320 :
6321 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags1()
6322 : // {
6323 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
6324 : // form.description = "DDR Link Buffer Half-Full Flags 63-32";
6325 : // return form;
6326 : // }
6327 :
6328 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags2()
6329 : // {
6330 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
6331 : // form.description = "DDR Link Buffer Half-Full Flags 95-64";
6332 : // return form;
6333 : // }
6334 :
6335 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags3()
6336 : // {
6337 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
6338 : // form.description = "DDR Link Buffer Half-Full Flags 127-96";
6339 : // return form;
6340 : // }
6341 :
6342 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags0()
6343 : // {
6344 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
6345 : // form.description = "DDR Link Buffer Full Flags 0-31";
6346 : // return form;
6347 : // }
6348 :
6349 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags1()
6350 : // {
6351 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
6352 : // form.description = "DDR Link Buffer Full Flags 63-32";
6353 : // return form;
6354 : // }
6355 :
6356 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags2()
6357 : // {
6358 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
6359 : // form.description = "DDR Link Buffer Full Flags 95-64";
6360 : // return form;
6361 : // }
6362 :
6363 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags3()
6364 : // {
6365 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
6366 : // form.description = "DDR Link Buffer Full Flags 127-96";
6367 : // return form;
6368 : // }
6369 :
6370 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags0()
6371 : // {
6372 : // auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags0);
6373 : // form.description = "DDR EVB Buffer Empty Flags 0-31";
6374 : // return form;
6375 : // }
6376 :
6377 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags1()
6378 : // {
6379 : // auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags1);
6380 : // form.description = "DDR EVB Buffer Empty Flags 63-32";
6381 : // return form;
6382 : // }
6383 :
6384 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags2()
6385 : // {
6386 : // auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags2);
6387 : // form.description = "DDR EVB Buffer Empty Flags 95-64";
6388 : // return form;
6389 : // }
6390 :
6391 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags3()
6392 : // {
6393 : // auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags3);
6394 : // form.description = "DDR EVB Buffer Empty Flags 127-96";
6395 : // return form;
6396 : // }
6397 :
6398 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags0()
6399 : // {
6400 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
6401 : // form.description = "DDR Link Buffer Half-Full Flags 0-31";
6402 : // return form;
6403 : // }
6404 :
6405 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags1()
6406 : // {
6407 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
6408 : // form.description = "DDR Link Buffer Half-Full Flags 63-32";
6409 : // return form;
6410 : // }
6411 :
6412 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags2()
6413 : // {
6414 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
6415 : // form.description = "DDR Link Buffer Half-Full Flags 95-64";
6416 : // return form;
6417 : // }
6418 :
6419 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags3()
6420 : // {
6421 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
6422 : // form.description = "DDR Link Buffer Half-Full Flags 127-96";
6423 : // return form;
6424 : // }
6425 :
6426 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags0()
6427 : // {
6428 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags0);
6429 : // form.description = "DDR Link Buffer Full Flags 0-31";
6430 : // return form;
6431 : // }
6432 :
6433 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags1()
6434 : // {
6435 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags1);
6436 : // form.description = "DDR Link Buffer Full Flags 63-32";
6437 : // return form;
6438 : // }
6439 :
6440 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags2()
6441 : // {
6442 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags2);
6443 : // form.description = "DDR Link Buffer Full Flags 95-64";
6444 : // return form;
6445 : // }
6446 :
6447 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags3()
6448 : // {
6449 : // auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags3);
6450 : // form.description = "DDR Link Buffer Full Flags 127-96";
6451 : // return form;
6452 : // }
6453 :
6454 0 : uint32_t DTCLib::DTC_Registers::ReadDataPendingDiagnosticTimer(DTC_Link_ID const& link, std::optional<uint32_t> val)
6455 : {
6456 0 : switch (link)
6457 : {
6458 0 : case DTC_Link_0:
6459 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link0);
6460 0 : case DTC_Link_1:
6461 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link1);
6462 0 : case DTC_Link_2:
6463 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link2);
6464 0 : case DTC_Link_3:
6465 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link3);
6466 0 : case DTC_Link_4:
6467 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link4);
6468 0 : case DTC_Link_5:
6469 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link5);
6470 0 : default: {
6471 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6472 0 : __SS_THROW__;
6473 0 : }
6474 : }
6475 : }
6476 :
6477 0 : void DTCLib::DTC_Registers::ResetDataPendingDiagnosticTimerFIFO(DTC_Link_ID const& link)
6478 : {
6479 0 : switch (link)
6480 : {
6481 0 : case DTC_Link_0:
6482 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link0);
6483 0 : break;
6484 0 : case DTC_Link_1:
6485 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link1);
6486 0 : break;
6487 0 : case DTC_Link_2:
6488 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link2);
6489 0 : break;
6490 0 : case DTC_Link_3:
6491 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link3);
6492 0 : break;
6493 0 : case DTC_Link_4:
6494 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link4);
6495 0 : break;
6496 0 : case DTC_Link_5:
6497 0 : WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link5);
6498 0 : break;
6499 0 : default: {
6500 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6501 0 : __SS_THROW__;
6502 0 : }
6503 : }
6504 0 : }
6505 :
6506 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink0()
6507 : {
6508 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link0);
6509 0 : form.description = "Data Pending Diagnostic Timer Link 0";
6510 0 : std::stringstream o;
6511 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_0, form.value);
6512 0 : form.vals.push_back(o.str());
6513 0 : return form;
6514 0 : }
6515 :
6516 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink1()
6517 : {
6518 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link1);
6519 0 : form.description = "Data Pending Diagnostic Timer Link 1";
6520 0 : std::stringstream o;
6521 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_1, form.value);
6522 0 : form.vals.push_back(o.str());
6523 0 : return form;
6524 0 : }
6525 :
6526 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink2()
6527 : {
6528 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link2);
6529 0 : form.description = "Data Pending Diagnostic Timer Link 2";
6530 0 : std::stringstream o;
6531 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_2, form.value);
6532 0 : form.vals.push_back(o.str());
6533 0 : return form;
6534 0 : }
6535 :
6536 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink3()
6537 : {
6538 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link3);
6539 0 : form.description = "Data Pending Diagnostic Timer Link 3";
6540 0 : std::stringstream o;
6541 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_3, form.value);
6542 0 : form.vals.push_back(o.str());
6543 0 : return form;
6544 0 : }
6545 :
6546 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink4()
6547 : {
6548 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link4);
6549 0 : form.description = "Data Pending Diagnostic Timer Link 4";
6550 0 : std::stringstream o;
6551 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_4, form.value);
6552 0 : form.vals.push_back(o.str());
6553 0 : return form;
6554 0 : }
6555 :
6556 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink5()
6557 : {
6558 0 : auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link5);
6559 0 : form.description = "Data Pending Diagnostic Timer Link 5";
6560 0 : std::stringstream o;
6561 0 : o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_5, form.value);
6562 0 : form.vals.push_back(o.str());
6563 0 : return form;
6564 0 : }
6565 :
6566 0 : uint32_t DTCLib::DTC_Registers::ReadSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
6567 : {
6568 : DTC_Register reg;
6569 0 : switch (link)
6570 : {
6571 0 : case DTC_Link_0:
6572 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
6573 0 : break;
6574 0 : case DTC_Link_1:
6575 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
6576 0 : break;
6577 0 : case DTC_Link_2:
6578 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
6579 0 : break;
6580 0 : case DTC_Link_3:
6581 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
6582 0 : break;
6583 0 : case DTC_Link_4:
6584 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
6585 0 : break;
6586 0 : case DTC_Link_5:
6587 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
6588 0 : break;
6589 0 : case DTC_Link_CFO:
6590 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
6591 0 : break;
6592 0 : default: {
6593 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6594 0 : __SS_THROW__;
6595 0 : }
6596 : }
6597 0 : return val.has_value() ? *val : ReadRegister_(reg);
6598 : }
6599 0 : void DTCLib::DTC_Registers::ClearSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link)
6600 : {
6601 : DTC_Register reg;
6602 0 : switch (link)
6603 : {
6604 0 : case DTC_Link_0:
6605 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
6606 0 : break;
6607 0 : case DTC_Link_1:
6608 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
6609 0 : break;
6610 0 : case DTC_Link_2:
6611 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
6612 0 : break;
6613 0 : case DTC_Link_3:
6614 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
6615 0 : break;
6616 0 : case DTC_Link_4:
6617 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
6618 0 : break;
6619 0 : case DTC_Link_5:
6620 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
6621 0 : break;
6622 0 : case DTC_Link_CFO:
6623 0 : reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
6624 0 : break;
6625 0 : default: {
6626 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6627 0 : __SS_THROW__;
6628 0 : }
6629 : }
6630 0 : WriteRegister_(1, reg);
6631 0 : }
6632 :
6633 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink0()
6634 : {
6635 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0);
6636 0 : form.description = "SERDES Character Not In Table Error Count Link 0";
6637 0 : std::stringstream o;
6638 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_0);
6639 0 : form.vals.push_back(o.str());
6640 0 : return form;
6641 0 : }
6642 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink1()
6643 : {
6644 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1);
6645 0 : form.description = "SERDES Character Not In Table Error Count Link 1";
6646 0 : std::stringstream o;
6647 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_1);
6648 0 : form.vals.push_back(o.str());
6649 0 : return form;
6650 0 : }
6651 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink2()
6652 : {
6653 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2);
6654 0 : form.description = "SERDES Character Not In Table Error Count Link 2";
6655 0 : std::stringstream o;
6656 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_2);
6657 0 : form.vals.push_back(o.str());
6658 0 : return form;
6659 0 : }
6660 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink3()
6661 : {
6662 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3);
6663 0 : form.description = "SERDES Character Not In Table Error Count Link 3";
6664 0 : std::stringstream o;
6665 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_3);
6666 0 : form.vals.push_back(o.str());
6667 0 : return form;
6668 0 : }
6669 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink4()
6670 : {
6671 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4);
6672 0 : form.description = "SERDES Character Not In Table Error Count Link 4";
6673 0 : std::stringstream o;
6674 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_4);
6675 0 : form.vals.push_back(o.str());
6676 0 : return form;
6677 0 : }
6678 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink5()
6679 : {
6680 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5);
6681 0 : form.description = "SERDES Character Not In Table Error Count Link 5";
6682 0 : std::stringstream o;
6683 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_5);
6684 0 : form.vals.push_back(o.str());
6685 0 : return form;
6686 0 : }
6687 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountCFOLink()
6688 : {
6689 0 : auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink);
6690 0 : form.description = "SERDES Character Not In Table Error Count CFO Link";
6691 0 : std::stringstream o;
6692 0 : o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_CFO);
6693 0 : form.vals.push_back(o.str());
6694 0 : return form;
6695 0 : }
6696 :
6697 0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXDisparityErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
6698 : {
6699 : DTC_Register reg;
6700 0 : switch (link)
6701 : {
6702 0 : case DTC_Link_0:
6703 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
6704 0 : break;
6705 0 : case DTC_Link_1:
6706 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
6707 0 : break;
6708 0 : case DTC_Link_2:
6709 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
6710 0 : break;
6711 0 : case DTC_Link_3:
6712 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
6713 0 : break;
6714 0 : case DTC_Link_4:
6715 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
6716 0 : break;
6717 0 : case DTC_Link_5:
6718 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
6719 0 : break;
6720 0 : case DTC_Link_CFO:
6721 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
6722 0 : break;
6723 0 : default: {
6724 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6725 0 : __SS_THROW__;
6726 0 : }
6727 : }
6728 0 : return val.has_value() ? *val : ReadRegister_(reg);
6729 : }
6730 0 : void DTCLib::DTC_Registers::ClearSERDESRXDisparityErrorCount(DTC_Link_ID const& link)
6731 : {
6732 : DTC_Register reg;
6733 0 : switch (link)
6734 : {
6735 0 : case DTC_Link_0:
6736 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
6737 0 : break;
6738 0 : case DTC_Link_1:
6739 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
6740 0 : break;
6741 0 : case DTC_Link_2:
6742 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
6743 0 : break;
6744 0 : case DTC_Link_3:
6745 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
6746 0 : break;
6747 0 : case DTC_Link_4:
6748 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
6749 0 : break;
6750 0 : case DTC_Link_5:
6751 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
6752 0 : break;
6753 0 : case DTC_Link_CFO:
6754 0 : reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
6755 0 : break;
6756 0 : default: {
6757 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6758 0 : __SS_THROW__;
6759 0 : }
6760 : }
6761 0 : WriteRegister_(1, reg);
6762 0 : }
6763 :
6764 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink0()
6765 : {
6766 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link0);
6767 0 : form.description = "SERDES RX Disparity Error Count Link 0";
6768 0 : std::stringstream o;
6769 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_0, form.value);
6770 0 : form.vals.push_back(o.str());
6771 0 : return form;
6772 0 : }
6773 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink1()
6774 : {
6775 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link1);
6776 0 : form.description = "SERDES RX Disparity Error Count Link 1";
6777 0 : std::stringstream o;
6778 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_1, form.value);
6779 0 : form.vals.push_back(o.str());
6780 0 : return form;
6781 0 : }
6782 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink2()
6783 : {
6784 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link2);
6785 0 : form.description = "SERDES RX Disparity Error Count Link 2";
6786 0 : std::stringstream o;
6787 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_2, form.value);
6788 0 : form.vals.push_back(o.str());
6789 0 : return form;
6790 0 : }
6791 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink3()
6792 : {
6793 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link3);
6794 0 : form.description = "SERDES RX Disparity Error Count Link 3";
6795 0 : std::stringstream o;
6796 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_3, form.value);
6797 0 : form.vals.push_back(o.str());
6798 0 : return form;
6799 0 : }
6800 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink4()
6801 : {
6802 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link4);
6803 0 : form.description = "SERDES RX Disparity Error Count Link 4";
6804 0 : std::stringstream o;
6805 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_4, form.value);
6806 0 : form.vals.push_back(o.str());
6807 0 : return form;
6808 0 : }
6809 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink5()
6810 : {
6811 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link5);
6812 0 : form.description = "SERDES RX Disparity Error Count Link 5";
6813 0 : std::stringstream o;
6814 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_5, form.value);
6815 0 : form.vals.push_back(o.str());
6816 0 : return form;
6817 0 : }
6818 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountCFOLink()
6819 : {
6820 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_CFOLink);
6821 0 : form.description = "SERDES RX Disparity Error Count CFO Link";
6822 0 : std::stringstream o;
6823 0 : o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_CFO, form.value);
6824 0 : form.vals.push_back(o.str());
6825 0 : return form;
6826 0 : }
6827 :
6828 0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXPRBSErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
6829 : {
6830 : DTC_Register reg;
6831 0 : switch (link)
6832 : {
6833 0 : case DTC_Link_0:
6834 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
6835 0 : break;
6836 0 : case DTC_Link_1:
6837 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
6838 0 : break;
6839 0 : case DTC_Link_2:
6840 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
6841 0 : break;
6842 0 : case DTC_Link_3:
6843 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
6844 0 : break;
6845 0 : case DTC_Link_4:
6846 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
6847 0 : break;
6848 0 : case DTC_Link_5:
6849 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
6850 0 : break;
6851 0 : case DTC_Link_CFO:
6852 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
6853 0 : break;
6854 0 : default: {
6855 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6856 0 : __SS_THROW__;
6857 0 : }
6858 : }
6859 0 : return val.has_value() ? *val : ReadRegister_(reg);
6860 : }
6861 0 : void DTCLib::DTC_Registers::ClearSERDESRXPRBSErrorCount(DTC_Link_ID const& link)
6862 : {
6863 : DTC_Register reg;
6864 0 : switch (link)
6865 : {
6866 0 : case DTC_Link_0:
6867 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
6868 0 : break;
6869 0 : case DTC_Link_1:
6870 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
6871 0 : break;
6872 0 : case DTC_Link_2:
6873 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
6874 0 : break;
6875 0 : case DTC_Link_3:
6876 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
6877 0 : break;
6878 0 : case DTC_Link_4:
6879 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
6880 0 : break;
6881 0 : case DTC_Link_5:
6882 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
6883 0 : break;
6884 0 : case DTC_Link_CFO:
6885 0 : reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
6886 0 : break;
6887 0 : default: {
6888 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6889 0 : __SS_THROW__;
6890 0 : }
6891 : }
6892 0 : WriteRegister_(1, reg);
6893 0 : }
6894 :
6895 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink0()
6896 : {
6897 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link0);
6898 0 : form.description = "SERDES RX PRBS Error Count Link 0";
6899 0 : std::stringstream o;
6900 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_0, form.value);
6901 0 : form.vals.push_back(o.str());
6902 0 : return form;
6903 0 : }
6904 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink1()
6905 : {
6906 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link1);
6907 0 : form.description = "SERDES RX PRBS Error Count Link 1";
6908 0 : std::stringstream o;
6909 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_1, form.value);
6910 0 : form.vals.push_back(o.str());
6911 0 : return form;
6912 0 : }
6913 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink2()
6914 : {
6915 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link2);
6916 0 : form.description = "SERDES RX PRBS Error Count Link 2";
6917 0 : std::stringstream o;
6918 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_2, form.value);
6919 0 : form.vals.push_back(o.str());
6920 0 : return form;
6921 0 : }
6922 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink3()
6923 : {
6924 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link3);
6925 0 : form.description = "SERDES RX PRBS Error Count Link 3";
6926 0 : std::stringstream o;
6927 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_3, form.value);
6928 0 : form.vals.push_back(o.str());
6929 0 : return form;
6930 0 : }
6931 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink4()
6932 : {
6933 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link4);
6934 0 : form.description = "SERDES RX PRBS Error Count Link 4";
6935 0 : std::stringstream o;
6936 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_4, form.value);
6937 0 : form.vals.push_back(o.str());
6938 0 : return form;
6939 0 : }
6940 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink5()
6941 : {
6942 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link5);
6943 0 : form.description = "SERDES RX PRBS Error Count Link 5";
6944 0 : std::stringstream o;
6945 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_5, form.value);
6946 0 : form.vals.push_back(o.str());
6947 0 : return form;
6948 0 : }
6949 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountCFOLink()
6950 : {
6951 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_CFOLink);
6952 0 : form.description = "SERDES RX PRBS Error Count CFO Link";
6953 0 : std::stringstream o;
6954 0 : o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_CFO, form.value);
6955 0 : form.vals.push_back(o.str());
6956 0 : return form;
6957 0 : }
6958 :
6959 0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXCRCErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
6960 : {
6961 : DTC_Register reg;
6962 0 : switch (link)
6963 : {
6964 0 : case DTC_Link_0:
6965 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
6966 0 : break;
6967 0 : case DTC_Link_1:
6968 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
6969 0 : break;
6970 0 : case DTC_Link_2:
6971 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
6972 0 : break;
6973 0 : case DTC_Link_3:
6974 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
6975 0 : break;
6976 0 : case DTC_Link_4:
6977 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
6978 0 : break;
6979 0 : case DTC_Link_5:
6980 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
6981 0 : break;
6982 0 : case DTC_Link_CFO:
6983 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
6984 0 : break;
6985 0 : default: {
6986 0 : __SS__ << "Illegal link index provided: " << link << __E__;
6987 0 : __SS_THROW__;
6988 0 : }
6989 : }
6990 0 : return val.has_value() ? *val : ReadRegister_(reg);
6991 : }
6992 0 : void DTCLib::DTC_Registers::ClearSERDESRXCRCErrorCount(DTC_Link_ID const& link)
6993 : {
6994 : DTC_Register reg;
6995 0 : switch (link)
6996 : {
6997 0 : case DTC_Link_0:
6998 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
6999 0 : break;
7000 0 : case DTC_Link_1:
7001 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
7002 0 : break;
7003 0 : case DTC_Link_2:
7004 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
7005 0 : break;
7006 0 : case DTC_Link_3:
7007 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
7008 0 : break;
7009 0 : case DTC_Link_4:
7010 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
7011 0 : break;
7012 0 : case DTC_Link_5:
7013 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
7014 0 : break;
7015 0 : case DTC_Link_CFO:
7016 0 : reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
7017 0 : break;
7018 0 : default: {
7019 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7020 0 : __SS_THROW__;
7021 0 : }
7022 : }
7023 0 : WriteRegister_(1, reg);
7024 0 : }
7025 :
7026 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink0()
7027 : {
7028 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link0);
7029 0 : form.description = "SERDES RX CRC Error Count Link 0";
7030 0 : std::stringstream o;
7031 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_0, form.value);
7032 0 : form.vals.push_back(o.str());
7033 0 : return form;
7034 0 : }
7035 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink1()
7036 : {
7037 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link1);
7038 0 : form.description = "SERDES RX CRC Error Count Link 1";
7039 0 : std::stringstream o;
7040 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_1, form.value);
7041 0 : form.vals.push_back(o.str());
7042 0 : return form;
7043 0 : }
7044 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink2()
7045 : {
7046 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link2);
7047 0 : form.description = "SERDES RX CRC Error Count Link 2";
7048 0 : std::stringstream o;
7049 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_2, form.value);
7050 0 : form.vals.push_back(o.str());
7051 0 : return form;
7052 0 : }
7053 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink3()
7054 : {
7055 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link3);
7056 0 : form.description = "SERDES RX CRC Error Count Link 3";
7057 0 : std::stringstream o;
7058 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_3, form.value);
7059 0 : form.vals.push_back(o.str());
7060 0 : return form;
7061 0 : }
7062 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink4()
7063 : {
7064 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link4);
7065 0 : form.description = "SERDES RX CRC Error Count Link 4";
7066 0 : std::stringstream o;
7067 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_4, form.value);
7068 0 : form.vals.push_back(o.str());
7069 0 : return form;
7070 0 : }
7071 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink5()
7072 : {
7073 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link5);
7074 0 : form.description = "SERDES RX CRC Error Count Link 5";
7075 0 : std::stringstream o;
7076 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_5, form.value);
7077 0 : form.vals.push_back(o.str());
7078 0 : return form;
7079 0 : }
7080 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountCFOLink()
7081 : {
7082 0 : auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_CFOLink);
7083 0 : form.description = "SERDES RX CRC Error Count CFO Link";
7084 0 : std::stringstream o;
7085 0 : o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_CFO, form.value);
7086 0 : form.vals.push_back(o.str());
7087 0 : return form;
7088 0 : }
7089 :
7090 : // SERDES RX CRC Error Control
7091 0 : bool DTCLib::DTC_Registers::ReadEnableInduceSERDESRXCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
7092 : {
7093 0 : auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
7094 0 : return dataSet[link];
7095 : }
7096 0 : void DTCLib::DTC_Registers::EnableInduceSERDESRXCRCError(DTC_Link_ID const& link)
7097 : {
7098 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
7099 0 : dataSet[link] = 1;
7100 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
7101 0 : }
7102 0 : void DTCLib::DTC_Registers::DisableInduceSERDESRXCRCError(DTC_Link_ID const& link)
7103 : {
7104 0 : auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
7105 0 : dataSet[link] = 0;
7106 0 : WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
7107 0 : }
7108 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorControl()
7109 : {
7110 0 : auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
7111 0 : form.description = "SERDES RX CRC Error Control";
7112 0 : form.vals.push_back("([ x = 1 (hi) ])"); // translation
7113 0 : for (auto r : DTC_ROC_Links)
7114 0 : form.vals.push_back(std::string("Induce Error Link ") + std::to_string(r) + ": [" +
7115 0 : (ReadEnableInduceSERDESRXCRCError(r, form.value) ? "x" : " ") + "]");
7116 :
7117 0 : form.vals.push_back(std::string("Incude Error CFO Link: [") +
7118 0 : (ReadEnableInduceSERDESRXCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
7119 :
7120 0 : return form;
7121 0 : }
7122 :
7123 0 : uint32_t DTCLib::DTC_Registers::ReadEVBSERDESRXPacketErrorCounter(std::optional<uint32_t> val)
7124 : {
7125 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_EBVSERDES_RXPacketErrorCount);
7126 : }
7127 0 : void DTCLib::DTC_Registers::ClearEVBSERDESRXPacketErrorCounter()
7128 : {
7129 0 : WriteRegister_(1, DTC_Register_EBVSERDES_RXPacketErrorCount);
7130 0 : }
7131 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESRXPacketErrorCounter()
7132 : {
7133 0 : auto form = CreateFormatter(DTC_Register_EBVSERDES_RXPacketErrorCount);
7134 0 : form.description = "EVB SERDES RX Packet Error Counter";
7135 0 : std::stringstream o;
7136 0 : o << std::dec << ReadEVBSERDESRXPacketErrorCounter(form.value);
7137 0 : form.vals.push_back(o.str());
7138 0 : return form;
7139 0 : }
7140 :
7141 : // Jitter Attenuator SERDES RX Recovered Clock LOS Counter
7142 0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorRecoveredClockLOSCount(std::optional<uint32_t> val)
7143 : {
7144 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
7145 : }
7146 0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorRecoeveredClockLOSCount()
7147 : {
7148 0 : WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
7149 0 : }
7150 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorRecoveredClockLOSCount()
7151 : {
7152 0 : auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
7153 0 : form.description = "Jitter Attenuator SERDES RX Recovered Clock LOS Counter";
7154 0 : std::stringstream o;
7155 0 : o << std::dec << ReadJitterAttenuatorRecoveredClockLOSCount(form.value);
7156 0 : form.vals.push_back(o.str());
7157 0 : return form;
7158 0 : }
7159 :
7160 : // Jitter Attenuator SERDES RX External Clock LOS Counter
7161 0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorExternalClockLOSCount(std::optional<uint32_t> val)
7162 : {
7163 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
7164 : }
7165 0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorExternalClockLOSCount()
7166 : {
7167 0 : WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
7168 0 : }
7169 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorExternalClockLOSCount()
7170 : {
7171 0 : auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
7172 0 : form.description = "Jitter Attenuator SERDES RX External Clock LOS Counter";
7173 0 : std::stringstream o;
7174 0 : o << std::dec << ReadJitterAttenuatorExternalClockLOSCount(form.value);
7175 0 : form.vals.push_back(o.str());
7176 0 : return form;
7177 0 : }
7178 :
7179 : // ROC Emulator Interpacket Delay
7180 0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorInterpacketDelay(DTC_Link_ID const& link, std::optional<uint32_t> val)
7181 : {
7182 : DTC_Register reg;
7183 0 : switch (link)
7184 : {
7185 0 : case DTC_Link_0:
7186 0 : reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
7187 0 : break;
7188 : // case DTC_Link_1:
7189 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
7190 : // break;
7191 : // case DTC_Link_2:
7192 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
7193 : // break;
7194 : // case DTC_Link_3:
7195 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
7196 : // break;
7197 : // case DTC_Link_4:
7198 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
7199 : // break;
7200 : // case DTC_Link_5:
7201 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
7202 : // break;
7203 0 : default: {
7204 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7205 0 : __SS_THROW__;
7206 0 : }
7207 : }
7208 0 : return val.has_value() ? *val : ReadRegister_(reg);
7209 : }
7210 0 : void DTCLib::DTC_Registers::SetROCEmulatorInterpacketDelay(DTC_Link_ID const& link, uint32_t delay)
7211 : {
7212 : DTC_Register reg;
7213 0 : switch (link)
7214 : {
7215 0 : case DTC_Link_0:
7216 0 : reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
7217 0 : break;
7218 : // case DTC_Link_1:
7219 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
7220 : // break;
7221 : // case DTC_Link_2:
7222 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
7223 : // break;
7224 : // case DTC_Link_3:
7225 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
7226 : // break;
7227 : // case DTC_Link_4:
7228 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
7229 : // break;
7230 : // case DTC_Link_5:
7231 : // reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
7232 : // break;
7233 0 : default: {
7234 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7235 0 : __SS_THROW__;
7236 0 : }
7237 : }
7238 0 : WriteRegister_(delay, reg);
7239 0 : }
7240 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink0()
7241 : {
7242 0 : auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link0);
7243 0 : form.description = "ROC Emulator Interpacket Delay all Links (*5ns)";
7244 0 : std::stringstream o;
7245 0 : o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_0, form.value);
7246 0 : form.vals.push_back(o.str());
7247 0 : return form;
7248 0 : }
7249 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink1()
7250 : // {
7251 : // auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link1);
7252 : // form.description = "ROC Emulator Interpacket Delay Link 1 (*5ns)";
7253 : // std::stringstream o;
7254 : // o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_1, form.value);
7255 : // form.vals.push_back(o.str());
7256 : // return form;
7257 : // }
7258 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink2()
7259 : // {
7260 : // auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link2);
7261 : // form.description = "ROC Emulator Interpacket Delay Link 2 (*5ns)";
7262 : // std::stringstream o;
7263 : // o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_2, form.value);
7264 : // form.vals.push_back(o.str());
7265 : // return form;
7266 : // }
7267 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink3()
7268 : // {
7269 : // auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link3);
7270 : // form.description = "ROC Emulator Interpacket Delay Link 3 (*5ns)";
7271 : // std::stringstream o;
7272 : // o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_3, form.value);
7273 : // form.vals.push_back(o.str());
7274 : // return form;
7275 : // }
7276 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink4()
7277 : // {
7278 : // auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link4);
7279 : // form.description = "ROC Emulator Interpacket Delay Link 4 (*5ns)";
7280 : // std::stringstream o;
7281 : // o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_4, form.value);
7282 : // form.vals.push_back(o.str());
7283 : // return form;
7284 : // }
7285 : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink5()
7286 : // {
7287 : // auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link5);
7288 : // form.description = "ROC Emulator Interpacket Delay Link 5 (*5ns)";
7289 : // std::stringstream o;
7290 : // o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_5, form.value);
7291 : // form.vals.push_back(o.str());
7292 : // return form;
7293 : // }
7294 :
7295 : // TX Data Request Packet Count
7296 0 : uint32_t DTCLib::DTC_Registers::ReadTXEventWindowMarkerCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7297 : {
7298 0 : return val.has_value() ? *val : ReadRegister_(GetTXEventWindowMarkerCountLinkRegister(link));
7299 : } // end ReadTXEventWindowMarkerCount()
7300 :
7301 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXEventWindowMarkerCountLink(DTC_Link_ID const& link)
7302 : {
7303 0 : auto form = CreateFormatter(GetTXEventWindowMarkerCountLinkRegister(link));
7304 0 : if (link == DTC_Link_CFO)
7305 0 : form.description = "CFO Event Window Marker (EWM) Count";
7306 : else
7307 0 : form.description = "EWM TX Count on Link " +
7308 0 : std::to_string((GetTXEventWindowMarkerCountLinkRegister(link) -
7309 0 : GetTXEventWindowMarkerCountLinkRegister(DTC_Link_0)) /
7310 0 : 4);
7311 0 : std::stringstream o;
7312 0 : o << std::dec << ReadTXEventWindowMarkerCount(link, form.value);
7313 0 : form.vals.push_back(o.str());
7314 0 : return form;
7315 0 : } // end FormatTXEventWindowMarkerCountLink()
7316 :
7317 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXEventWindowMarkerCountLinkRegister(DTC_Link_ID const& link)
7318 : {
7319 : DTC_Register reg;
7320 0 : switch (link)
7321 : {
7322 0 : case DTC_Link_0:
7323 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link0;
7324 0 : break;
7325 0 : case DTC_Link_1:
7326 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link1;
7327 0 : break;
7328 0 : case DTC_Link_2:
7329 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link2;
7330 0 : break;
7331 0 : case DTC_Link_3:
7332 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link3;
7333 0 : break;
7334 0 : case DTC_Link_4:
7335 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link4;
7336 0 : break;
7337 0 : case DTC_Link_5:
7338 0 : reg = DTC_Register_TXEventWindowMarkerCount_Link5;
7339 0 : break;
7340 0 : case DTC_Link_CFO:
7341 0 : reg = DTC_Register_CFOTXEventWindowMarkerCount_Link6;
7342 0 : break;
7343 0 : default: {
7344 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7345 : ss << "\n\nThe stack trace is as follows:\n"
7346 0 : << otsStyleStackTrace() << __E__;
7347 0 : __SS_THROW__;
7348 0 : }
7349 : }
7350 0 : return reg;
7351 : } // end GetTXEventWindowMarkerCountLinkRegister()
7352 :
7353 : // TX Null Heartbeat Packet Count
7354 0 : uint32_t DTCLib::DTC_Registers::ReadTXNullHeartbeatCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7355 : {
7356 0 : return val.has_value() ? *val : ReadRegister_(GetTXNullHeartbeatCountLinkRegister(link));
7357 : } // end ReadTXNullHeartbeatCount()
7358 :
7359 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXNullHeartbeatCountLink(DTC_Link_ID const& link)
7360 : {
7361 0 : auto form = CreateFormatter(GetTXNullHeartbeatCountLinkRegister(link));
7362 0 : form.description = "Tx Null HBPs on Link " +
7363 0 : std::to_string((GetTXNullHeartbeatCountLinkRegister(link) -
7364 0 : GetTXNullHeartbeatCountLinkRegister(DTC_Link_0)) /
7365 0 : 4);
7366 0 : std::stringstream o;
7367 0 : o << std::dec << ReadTXNullHeartbeatCount(link, form.value);
7368 0 : form.vals.push_back(o.str());
7369 0 : return form;
7370 0 : } // end FormatTXNullHeartbeatCountLink()
7371 :
7372 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXNullHeartbeatCountLinkRegister(DTC_Link_ID const& link)
7373 : {
7374 : DTC_Register reg;
7375 0 : switch (link)
7376 : {
7377 0 : case DTC_Link_0:
7378 0 : reg = DTC_Register_TXNullHeartbeatCount_Link0;
7379 0 : break;
7380 0 : case DTC_Link_1:
7381 0 : reg = DTC_Register_TXNullHeartbeatCount_Link1;
7382 0 : break;
7383 0 : case DTC_Link_2:
7384 0 : reg = DTC_Register_TXNullHeartbeatCount_Link2;
7385 0 : break;
7386 0 : case DTC_Link_3:
7387 0 : reg = DTC_Register_TXNullHeartbeatCount_Link3;
7388 0 : break;
7389 0 : case DTC_Link_4:
7390 0 : reg = DTC_Register_TXNullHeartbeatCount_Link4;
7391 0 : break;
7392 0 : case DTC_Link_5:
7393 0 : reg = DTC_Register_TXNullHeartbeatCount_Link5;
7394 0 : break;
7395 0 : default: {
7396 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7397 : ss << "\n\nThe stack trace is as follows:\n"
7398 0 : << otsStyleStackTrace() << __E__;
7399 0 : __SS_THROW__;
7400 0 : }
7401 : }
7402 0 : return reg;
7403 : } // end GetTXNullHeartbeatCountLinkRegister()
7404 :
7405 : // TX Data Request Packet Count
7406 0 : uint32_t DTCLib::DTC_Registers::ReadTXDataRequestPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7407 : {
7408 0 : return val.has_value() ? *val : ReadRegister_(GetTXDataRequestPacketCountLinkRegister(link));
7409 : } // end ReadTXDataRequestPacketCount()
7410 :
7411 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDataRequestPacketCountLink(DTC_Link_ID const& link)
7412 : {
7413 0 : auto form = CreateFormatter(GetTXDataRequestPacketCountLinkRegister(link));
7414 0 : form.description = "DRP TX Count on Link " +
7415 0 : std::to_string((GetTXDataRequestPacketCountLinkRegister(link) -
7416 0 : GetTXDataRequestPacketCountLinkRegister(DTC_Link_0)) /
7417 0 : 4);
7418 0 : std::stringstream o;
7419 0 : o << std::dec << ReadTXDataRequestPacketCount(link, form.value);
7420 0 : form.vals.push_back(o.str());
7421 0 : return form;
7422 0 : } // end FormatTXEventWindowMarkerCountLink()
7423 :
7424 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXDataRequestPacketCountLinkRegister(DTC_Link_ID const& link)
7425 : {
7426 : DTC_Register reg;
7427 0 : switch (link)
7428 : {
7429 0 : case DTC_Link_0:
7430 0 : reg = DTC_Register_TXDataRequestPacketCount_Link0;
7431 0 : break;
7432 0 : case DTC_Link_1:
7433 0 : reg = DTC_Register_TXDataRequestPacketCount_Link1;
7434 0 : break;
7435 0 : case DTC_Link_2:
7436 0 : reg = DTC_Register_TXDataRequestPacketCount_Link2;
7437 0 : break;
7438 0 : case DTC_Link_3:
7439 0 : reg = DTC_Register_TXDataRequestPacketCount_Link3;
7440 0 : break;
7441 0 : case DTC_Link_4:
7442 0 : reg = DTC_Register_TXDataRequestPacketCount_Link4;
7443 0 : break;
7444 0 : case DTC_Link_5:
7445 0 : reg = DTC_Register_TXDataRequestPacketCount_Link5;
7446 0 : break;
7447 0 : default: {
7448 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7449 : ss << "\n\nThe stack trace is as follows:\n"
7450 0 : << otsStyleStackTrace() << __E__;
7451 0 : __SS_THROW__;
7452 0 : }
7453 : }
7454 0 : return reg;
7455 : } // end GetTXDataRequestPacketCountLinkRegister()
7456 :
7457 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOTXClockMarkerCountLink6()
7458 : {
7459 0 : auto form = CreateFormatter(DTC_Register_CFOTXClockMarkerCount_Link6);
7460 0 : form.description = "CFO Clock Marker Count";
7461 0 : std::stringstream o;
7462 0 : o << std::dec << ReadCFOTXClockMarkerCountLink6(form.value);
7463 0 : form.vals.push_back(o.str());
7464 0 : return form;
7465 0 : } // end FormatCFOTXClockMarkerCountLink6()
7466 :
7467 0 : uint32_t DTCLib::DTC_Registers::ReadCFOTXClockMarkerCountLink6(std::optional<uint32_t> val)
7468 : {
7469 0 : return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOTXClockMarkerCount_Link6);
7470 : } // end ReadCFOTXClockMarkerCountLink6()
7471 :
7472 : // TX Heartbeat Packet Count
7473 0 : uint32_t DTCLib::DTC_Registers::ReadTXHeartbeatPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7474 : {
7475 0 : return val.has_value() ? *val : ReadRegister_(GetTXHeartbeatPacketCountLinkRegister(link));
7476 : } // end ReadTXHeartbeatPacketCount()
7477 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXHeartbeatPacketCountLink(DTC_Link_ID const& link)
7478 : {
7479 0 : auto form = CreateFormatter(GetTXHeartbeatPacketCountLinkRegister(link));
7480 0 : if (link == DTC_Link_CFO)
7481 0 : form.description = "CFO Heartbeat Packet (HBP) Count";
7482 : else
7483 0 : form.description = "HBP TX Counter Link " +
7484 0 : std::to_string((GetTXHeartbeatPacketCountLinkRegister(link) -
7485 0 : GetTXHeartbeatPacketCountLinkRegister(DTC_Link_0)) /
7486 0 : 4);
7487 0 : std::stringstream o;
7488 0 : o << std::dec << ReadTXHeartbeatPacketCount(DTC_Link_0, form.value);
7489 0 : form.vals.push_back(o.str());
7490 0 : return form;
7491 0 : } // end FormatTXHeartbeatPacketCountLink()
7492 :
7493 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXHeartbeatPacketCountLinkRegister(DTC_Link_ID const& link)
7494 : {
7495 : DTC_Register reg;
7496 0 : switch (link)
7497 : {
7498 0 : case DTC_Link_0:
7499 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link0;
7500 0 : break;
7501 0 : case DTC_Link_1:
7502 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link1;
7503 0 : break;
7504 0 : case DTC_Link_2:
7505 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link2;
7506 0 : break;
7507 0 : case DTC_Link_3:
7508 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link3;
7509 0 : break;
7510 0 : case DTC_Link_4:
7511 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link4;
7512 0 : break;
7513 0 : case DTC_Link_5:
7514 0 : reg = DTC_Register_TXHeartbeatPacketCount_Link5;
7515 0 : break;
7516 0 : case DTC_Link_CFO:
7517 0 : reg = DTC_Register_CFOTXHeartbeatPacketCount_Link5;
7518 0 : break;
7519 0 : default: {
7520 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7521 0 : __SS_THROW__;
7522 0 : }
7523 : }
7524 0 : return reg;
7525 : } // end GetTXHeartbeatPacketCountLinkRegister()
7526 :
7527 : // RX Data Header Packet Count
7528 0 : uint32_t DTCLib::DTC_Registers::ReadRXDataHeaderPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7529 : {
7530 0 : return val.has_value() ? *val : ReadRegister_(GetRXDataHeaderPacketCountLinkRegister(link));
7531 : } // end ReadRXDataHeaderPacketCount()
7532 :
7533 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataHeaderPacketCountLink(DTC_Link_ID const& link)
7534 : {
7535 0 : auto form = CreateFormatter(GetRXDataHeaderPacketCountLinkRegister(link));
7536 0 : form.description = "ROC DH RX Count on Link " +
7537 0 : std::to_string((GetRXDataHeaderPacketCountLinkRegister(link) -
7538 0 : GetRXDataHeaderPacketCountLinkRegister(DTC_Link_0)) /
7539 0 : 4);
7540 0 : std::stringstream o;
7541 0 : o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
7542 0 : form.vals.push_back(o.str());
7543 0 : return form;
7544 0 : } // end FormatRXDataHeaderPacketCountLink()
7545 :
7546 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataHeaderPacketCountLinkRegister(DTC_Link_ID const& link)
7547 : {
7548 : DTC_Register reg;
7549 0 : switch (link)
7550 : {
7551 0 : case DTC_Link_0:
7552 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link0;
7553 0 : break;
7554 0 : case DTC_Link_1:
7555 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link1;
7556 0 : break;
7557 0 : case DTC_Link_2:
7558 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link2;
7559 0 : break;
7560 0 : case DTC_Link_3:
7561 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link3;
7562 0 : break;
7563 0 : case DTC_Link_4:
7564 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link4;
7565 0 : break;
7566 0 : case DTC_Link_5:
7567 0 : reg = DTC_Register_RXDataHeaderPacketCount_Link5;
7568 0 : break;
7569 0 : default: {
7570 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7571 0 : __SS_THROW__;
7572 0 : }
7573 : }
7574 0 : return reg;
7575 : } // end GetRXDataHeaderPacketCountLinkRegister()
7576 :
7577 : // RX Data Packet Count
7578 0 : uint32_t DTCLib::DTC_Registers::ReadRXDataPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
7579 : {
7580 0 : return val.has_value() ? *val : ReadRegister_(GetRXDataPacketCountLinkRegister(link));
7581 : } // end ReadRXDataPacketCount()
7582 :
7583 0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataPacketCountLink(DTC_Link_ID const& link)
7584 : {
7585 0 : auto form = CreateFormatter(GetRXDataPacketCountLinkRegister(link));
7586 0 : form.description = "ROC DP RX Count on Link " +
7587 0 : std::to_string((GetRXDataPacketCountLinkRegister(link) -
7588 0 : GetRXDataPacketCountLinkRegister(DTC_Link_0)) /
7589 0 : 4);
7590 0 : std::stringstream o;
7591 0 : o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
7592 0 : form.vals.push_back(o.str());
7593 0 : return form;
7594 0 : } // end FormatRXDataPacketCountLink()
7595 :
7596 0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataPacketCountLinkRegister(DTC_Link_ID const& link)
7597 : {
7598 : DTC_Register reg;
7599 0 : switch (link)
7600 : {
7601 0 : case DTC_Link_0:
7602 0 : reg = DTC_Register_RXDataPacketCount_Link0;
7603 0 : break;
7604 0 : case DTC_Link_1:
7605 0 : reg = DTC_Register_RXDataPacketCount_Link1;
7606 0 : break;
7607 0 : case DTC_Link_2:
7608 0 : reg = DTC_Register_RXDataPacketCount_Link2;
7609 0 : break;
7610 0 : case DTC_Link_3:
7611 0 : reg = DTC_Register_RXDataPacketCount_Link3;
7612 0 : break;
7613 0 : case DTC_Link_4:
7614 0 : reg = DTC_Register_RXDataPacketCount_Link4;
7615 0 : break;
7616 0 : case DTC_Link_5:
7617 0 : reg = DTC_Register_RXDataPacketCount_Link5;
7618 0 : break;
7619 0 : default: {
7620 0 : __SS__ << "Illegal link index provided: " << link << __E__;
7621 0 : __SS_THROW__;
7622 0 : }
7623 : }
7624 0 : return reg;
7625 : } // end GetRXDataPacketCountLinkRegister()
7626 :
7627 : // EVB Diagnostic RX Packet FIFO
7628 0 : uint64_t DTCLib::DTC_Registers::ReadEVBDiagnosticFIFO(std::optional<uint32_t> val)
7629 : {
7630 0 : uint64_t ret = val.has_value() ? *val : ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_High);
7631 0 : ret = (ret << 32) + ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_Low);
7632 0 : return ret;
7633 : }
7634 0 : void DTCLib::DTC_Registers::ClearEVBDiagnosticFIFO()
7635 : {
7636 0 : WriteRegister_(0, DTC_Register_EVBDiagnosticRXPacket_Low);
7637 0 : }
7638 :
7639 : // Event Mode Lookup Table
7640 : /// <summary>
7641 : /// Set all event mode words to the given value
7642 : /// </summary>
7643 : /// <param name="data">Value for all event mode words</param>
7644 0 : void DTCLib::DTC_Registers::SetAllEventModeWords(uint32_t data)
7645 : {
7646 0 : for (uint16_t address = DTC_Register_EventModeLookupTableStart; address <= DTC_Register_EventModeLookupTableEnd;
7647 0 : address += 4)
7648 : {
7649 0 : auto retry = 3;
7650 : int errorCode;
7651 : do
7652 : {
7653 0 : errorCode = device_.write_register(address, 100, data);
7654 0 : --retry;
7655 0 : } while (retry > 0 && errorCode != 0);
7656 0 : if (errorCode != 0)
7657 : {
7658 0 : __SS__ << "Error writing register " << address;
7659 0 : __SS_THROW__;
7660 : // throw DTC_IOErrorException(errorCode);
7661 0 : }
7662 : }
7663 0 : }
7664 :
7665 : /// <summary>
7666 : /// Set a given event mode word
7667 : /// </summary>
7668 : /// <param name="which">Word index to write</param>
7669 : /// <param name="data">Data for word</param>
7670 0 : void DTCLib::DTC_Registers::SetEventModeWord(uint8_t which, uint32_t data)
7671 : {
7672 0 : uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
7673 0 : if (address <= DTC_Register_EventModeLookupTableEnd)
7674 : {
7675 0 : auto retry = 3;
7676 : int errorCode;
7677 : do
7678 : {
7679 0 : errorCode = device_.write_register(address, 100, data);
7680 0 : --retry;
7681 0 : } while (retry > 0 && errorCode != 0);
7682 0 : if (errorCode != 0)
7683 : {
7684 0 : __SS__ << "Error writing register " << address;
7685 0 : __SS_THROW__;
7686 : // throw DTC_IOErrorException(errorCode);
7687 0 : }
7688 : }
7689 0 : }
7690 :
7691 : /// <summary>
7692 : /// Read an event mode word from the Event Mode lookup table
7693 : /// </summary>
7694 : /// <param name="which">Word index to read</param>
7695 : /// <returns>Value of the given event mode word</returns>
7696 0 : uint32_t DTCLib::DTC_Registers::ReadEventModeWord(uint8_t which)
7697 : {
7698 0 : uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
7699 0 : if (address <= DTC_Register_EventModeLookupTableEnd)
7700 : {
7701 0 : auto retry = 3;
7702 : int errorCode;
7703 : uint32_t data;
7704 : do
7705 : {
7706 0 : errorCode = device_.read_register(address, 100, &data);
7707 0 : --retry;
7708 0 : } while (retry > 0 && errorCode != 0);
7709 0 : if (errorCode != 0)
7710 : {
7711 0 : __SS__ << "Error writing register " << address;
7712 0 : __SS_THROW__;
7713 : // throw DTC_IOErrorException(errorCode);
7714 0 : }
7715 :
7716 0 : return data;
7717 : }
7718 0 : return 0;
7719 : }
7720 :
7721 : // Oscillator Programming (DDR and SERDES)
7722 : /// <summary>
7723 : /// Set the given oscillator to the given frequency, calculating a new program in the process.
7724 : /// </summary>
7725 : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
7726 : /// <param name="targetFrequency">New frequency to program, in Hz</param>
7727 : /// <returns>Whether the oscillator was changed (Will not reset if already set to desired frequency)</returns>
7728 0 : bool DTCLib::DTC_Registers::SetNewOscillatorFrequency(DTC_OscillatorType oscillator, double targetFrequency)
7729 : {
7730 0 : auto currentFrequency = 0; // As of 2023 DTCs, can not read frequency back (it was doing nothing, just a scratch register) // ReadCurrentFrequency(oscillator);
7731 0 : auto currentProgram = ReadCurrentProgram(oscillator);
7732 0 : __COUT__ << "Target Frequency: " << targetFrequency << ", Current Frequency: " << currentFrequency
7733 0 : << ", Current Program: " << std::showbase << std::hex << currentProgram;
7734 :
7735 : // Check if targetFrequency is essentially the same as the current frequency...
7736 0 : if (fabs(currentFrequency - targetFrequency) < targetFrequency * 30 / 1000000)
7737 : {
7738 0 : __COUT_INFO__ << "New frequency and old frequency are within 30 ppm of each other, not reprogramming!";
7739 0 : return false;
7740 : }
7741 :
7742 0 : auto newParameters = CalculateFrequencyForProgramming_(targetFrequency, currentFrequency, currentProgram);
7743 0 : if (newParameters == 0)
7744 : {
7745 0 : __COUT_WARN__ << "New program calculated as 0! Check parameters!";
7746 0 : return false;
7747 : }
7748 0 : WriteCurrentProgram(newParameters, oscillator);
7749 : // WriteCurrentFrequency(targetFrequency, oscillator); //As of 2023 DTCs, can not write frequency back (it was doing nothing, just a scratch register)
7750 0 : return true;
7751 : }
7752 :
7753 : /// <summary>
7754 : /// Read the current RFREQ and dividers of the given oscillator clock
7755 : /// </summary>
7756 : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
7757 : /// <returns>64-bit integer contianing current oscillator program</returns>
7758 0 : uint64_t DTCLib::DTC_Registers::ReadCurrentProgram(DTC_OscillatorType oscillator)
7759 : {
7760 0 : switch (oscillator)
7761 : {
7762 0 : case DTC_OscillatorType_SERDES:
7763 0 : return ReadSERDESOscillatorParameters_();
7764 0 : case DTC_OscillatorType_Timing:
7765 0 : return ReadTimingOscillatorParameters_();
7766 : // case DTC_OscillatorType_DDR:
7767 : // return ReadDDROscillatorParameters_();
7768 0 : default:
7769 0 : __SS__ << "Invalid DTC_OscillatorType to read: " + std::to_string(oscillator);
7770 0 : __SS_THROW__;
7771 : }
7772 : return 0;
7773 : }
7774 :
7775 : /// <summary>
7776 : /// Writes a program for the given oscillator crystal. This function should be paired with a call to
7777 : /// WriteCurrentFrequency so that subsequent programming attempts work as expected.
7778 : /// </summary>
7779 : /// <param name="program">64-bit integer with new RFREQ and dividers</param>
7780 : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
7781 0 : void DTCLib::DTC_Registers::WriteCurrentProgram(uint64_t program, DTC_OscillatorType oscillator)
7782 : {
7783 0 : switch (oscillator)
7784 : {
7785 0 : case DTC_OscillatorType_SERDES:
7786 0 : SetSERDESOscillatorParameters_(program);
7787 0 : break;
7788 0 : case DTC_OscillatorType_Timing:
7789 0 : SetTimingOscillatorParameters_(program);
7790 0 : break;
7791 : // case DTC_OscillatorType_DDR:
7792 : // SetDDROscillatorParameters_(program);
7793 : // break;
7794 0 : default:
7795 0 : __SS__ << "Invalid DTC_OscillatorType to program: " + std::to_string(oscillator);
7796 0 : __SS_THROW__;
7797 : }
7798 0 : }
7799 :
7800 : // Private Functions
7801 0 : void DTCLib::DTC_Registers::VerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite)
7802 : {
7803 : // verify register readback
7804 : if (1)
7805 : {
7806 : // uint32_t readbackReturnValue = ReadRegister_(address);
7807 : // uint32_t readbackValue = readbackReturnValue;
7808 : // uint32_t readbackValue = ReadRegister_(address);
7809 :
7810 0 : switch (address) // handle special register checks by masking of DONT-CARE bits, or else check full 32 bits
7811 : {
7812 : //---------- DTC only registers
7813 0 : case DTC_Register_CFOLinkErrorFlags: // CFO Sample Permanent Offset 2:0
7814 0 : dataToWrite &= 0x03;
7815 0 : readbackValue &= 0x03;
7816 0 : break;
7817 0 : case DTC_Register_CFOMarkerEnables: // CFO emulator marker enables: 5:0 enables clock marker, 13:8 is event
7818 : // marker per ROC link for some reason, now event marker is not returned
7819 : // (FIXME?)
7820 0 : dataToWrite &= 0x03f;
7821 0 : readbackValue &= 0x03f;
7822 0 : break;
7823 0 : case DTC_Register_RXCDRUnlockCount_CFOLink: // write clears 32-bit CDR unlock counter, but can read back errors
7824 : // immediately, so don't check
7825 : case DTC_Register_JitterAttenuatorLossOfLockCount:
7826 0 : return;
7827 0 : case DTC_Register_JitterAttenuatorCSR: // 0x9308 bit-0 is reset, input select bit-5:4, bit-8 is LOL, bit-11:9
7828 : // (input LOS).. only check input select bits
7829 0 : dataToWrite &= (3 << 4);
7830 0 : readbackValue &= (3 << 4);
7831 0 : break;
7832 0 : case DTC_Register_CFOEmulation_EventMode2: // only lower 16-bits are R/W
7833 0 : dataToWrite &= 0x0000ffff;
7834 0 : readbackValue &= 0x0000ffff;
7835 0 : break;
7836 0 : case DTC_Register_DetEmulation_Control1: // self clearing bit-1, so return immediately
7837 0 : return;
7838 0 : case DTC_Register_EVBStats: // addrs for write, data on read
7839 0 : return;
7840 :
7841 0 : default:; // do direct comparison of each bit
7842 : } // end readback verification address case handling
7843 :
7844 0 : if (readbackValue != dataToWrite)
7845 : {
7846 : try
7847 : {
7848 0 : __SS__ << "Write check mismatch - "
7849 0 : << "write value 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(dataToWrite)
7850 0 : << " to register 0x" << std::setw(4) << std::setfill('0') << std::setprecision(4) << std::hex << static_cast<uint32_t>(address) << "... read back 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(readbackValue) << std::endl
7851 0 : << std::endl
7852 0 : << "If you do not understand this error, try checking the DTC firmware version: " << ReadDesignDate() << std::endl;
7853 0 : __SS_ONLY_THROW__;
7854 0 : }
7855 0 : catch (const std::runtime_error& e)
7856 : {
7857 0 : std::stringstream ss;
7858 0 : ss << e.what();
7859 : ss << "\n\nThe stack trace is as follows:\n"
7860 0 : << otsStyleStackTrace() << __E__;
7861 0 : __SS_THROW__;
7862 0 : }
7863 : }
7864 : // return readbackReturnValue;
7865 : } // end verify register readback
7866 : } // end VerifyRegisterWrite_()
7867 :
7868 0 : int DTCLib::DTC_Registers::DecodeHighSpeedDivider_(int input)
7869 : {
7870 0 : switch (input)
7871 : {
7872 0 : case 0:
7873 0 : return 4;
7874 0 : case 1:
7875 0 : return 5;
7876 0 : case 2:
7877 0 : return 6;
7878 0 : case 3:
7879 0 : return 7;
7880 0 : case 5:
7881 0 : return 9;
7882 0 : case 7:
7883 0 : return 11;
7884 0 : default:
7885 0 : return -1;
7886 : }
7887 : }
7888 :
7889 0 : int DTCLib::DTC_Registers::EncodeHighSpeedDivider_(int input)
7890 : {
7891 0 : switch (input)
7892 : {
7893 0 : case 4:
7894 0 : return 0;
7895 0 : case 5:
7896 0 : return 1;
7897 0 : case 6:
7898 0 : return 2;
7899 0 : case 7:
7900 0 : return 3;
7901 0 : case 9:
7902 0 : return 5;
7903 0 : case 11:
7904 0 : return 7;
7905 0 : default:
7906 0 : return -1;
7907 : }
7908 : }
7909 :
7910 0 : int DTCLib::DTC_Registers::EncodeOutputDivider_(int input)
7911 : {
7912 0 : if (input == 1) return 0;
7913 0 : int temp = input / 2;
7914 0 : return (temp * 2) - 1;
7915 : }
7916 :
7917 0 : uint64_t DTCLib::DTC_Registers::CalculateFrequencyForProgramming_(double targetFrequency, double currentFrequency,
7918 : uint64_t currentProgram)
7919 : {
7920 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: targetFrequency=" << targetFrequency << ", currentFrequency=" << currentFrequency
7921 0 : << ", currentProgram=" << std::showbase << std::hex << static_cast<unsigned long long>(currentProgram);
7922 0 : auto currentHighSpeedDivider = DecodeHighSpeedDivider_((currentProgram >> 45) & 0x7);
7923 0 : auto currentOutputDivider = DecodeOutputDivider_((currentProgram >> 38) & 0x7F);
7924 0 : auto currentRFREQ = DecodeRFREQ_(currentProgram & 0x3FFFFFFFFF);
7925 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Current HSDIV=" << currentHighSpeedDivider << ", N1=" << currentOutputDivider << ", RFREQ=" << currentRFREQ;
7926 0 : const auto minFreq = 4850000000; // Hz
7927 0 : const auto maxFreq = 5670000000; // Hz
7928 :
7929 0 : auto fXTAL = currentFrequency * currentHighSpeedDivider * currentOutputDivider / currentRFREQ;
7930 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: fXTAL=" << fXTAL;
7931 :
7932 0 : std::vector<int> hsdiv_values = {11, 9, 7, 6, 5, 4};
7933 0 : std::vector<std::pair<int, double>> parameter_values;
7934 0 : for (auto hsdiv : hsdiv_values)
7935 : {
7936 0 : auto minN = minFreq / (targetFrequency * hsdiv);
7937 0 : if (minN > 128) break;
7938 :
7939 0 : auto thisN = 2;
7940 0 : if (minN < 1) thisN = 1;
7941 0 : while (thisN < minN)
7942 : {
7943 0 : thisN += 2;
7944 : }
7945 0 : auto fdco_new = hsdiv * thisN * targetFrequency;
7946 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Adding solution: HSDIV=" << hsdiv << ", N1=" << thisN << ", fdco_new=" << fdco_new;
7947 0 : parameter_values.push_back(std::make_pair(thisN, fdco_new));
7948 : }
7949 :
7950 0 : auto counter = -1;
7951 0 : auto newHighSpeedDivider = 0;
7952 0 : auto newOutputDivider = 0;
7953 0 : auto newRFREQ = 0.0;
7954 :
7955 0 : for (auto values : parameter_values)
7956 : {
7957 0 : ++counter;
7958 0 : if (values.second > maxFreq) continue;
7959 :
7960 0 : newHighSpeedDivider = hsdiv_values[counter];
7961 0 : newOutputDivider = values.first;
7962 0 : newRFREQ = values.second / fXTAL;
7963 0 : break;
7964 : }
7965 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: HSDIV=" << newHighSpeedDivider << ", N1=" << newOutputDivider << ", RFREQ=" << newRFREQ;
7966 :
7967 0 : if (EncodeHighSpeedDivider_(newHighSpeedDivider) == -1)
7968 : {
7969 0 : __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid HSDIV " << newHighSpeedDivider << "!";
7970 0 : return 0;
7971 : }
7972 0 : if (newOutputDivider > 128 || newOutputDivider < 0)
7973 : {
7974 0 : __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid N1 " << newOutputDivider << "!";
7975 0 : return 0;
7976 : }
7977 0 : if (newRFREQ <= 0)
7978 : {
7979 0 : __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid RFREQ " << newRFREQ << "!";
7980 0 : return 0;
7981 : }
7982 :
7983 0 : auto output = (static_cast<uint64_t>(EncodeHighSpeedDivider_(newHighSpeedDivider)) << 45) +
7984 0 : (static_cast<uint64_t>(EncodeOutputDivider_(newOutputDivider)) << 38) + EncodeRFREQ_(newRFREQ);
7985 0 : TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: " << std::showbase << std::hex << static_cast<unsigned long long>(output);
7986 0 : return output;
7987 0 : }
7988 :
7989 0 : uint64_t DTCLib::DTC_Registers::ReadSERDESOscillatorParameters_()
7990 : {
7991 0 : uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7)) << 40) +
7992 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8)) << 32) +
7993 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9)) << 24) +
7994 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10)) << 16) +
7995 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11)) << 8) +
7996 0 : static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12));
7997 0 : return data;
7998 : }
7999 :
8000 0 : uint64_t DTCLib::DTC_Registers::ReadTimingOscillatorParameters_()
8001 : {
8002 0 : uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7)) << 40) +
8003 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8)) << 32) +
8004 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9)) << 24) +
8005 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10)) << 16) +
8006 0 : (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11)) << 8) +
8007 0 : static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12));
8008 0 : return data;
8009 : }
8010 :
8011 : // uint64_t DTCLib::DTC_Registers::ReadDDROscillatorParameters_()
8012 : // {
8013 : // uint64_t data = (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7)) << 40) +
8014 : // (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8)) << 32) +
8015 : // (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9)) << 24) +
8016 : // (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10)) << 16) +
8017 : // (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11)) << 8) +
8018 : // static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12));
8019 : // return data;
8020 : // }
8021 :
8022 0 : void DTCLib::DTC_Registers::SetSERDESOscillatorParameters_(uint64_t program)
8023 : {
8024 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0x10);
8025 :
8026 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7, static_cast<uint8_t>(program >> 40));
8027 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8, static_cast<uint8_t>(program >> 32));
8028 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9, static_cast<uint8_t>(program >> 24));
8029 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10, static_cast<uint8_t>(program >> 16));
8030 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11, static_cast<uint8_t>(program >> 8));
8031 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12, static_cast<uint8_t>(program));
8032 :
8033 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0);
8034 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x87, 0x40);
8035 0 : }
8036 :
8037 0 : void DTCLib::DTC_Registers::SetTimingOscillatorParameters_(uint64_t program)
8038 : {
8039 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0x10);
8040 :
8041 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7, static_cast<uint8_t>(program >> 40));
8042 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8, static_cast<uint8_t>(program >> 32));
8043 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9, static_cast<uint8_t>(program >> 24));
8044 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10, static_cast<uint8_t>(program >> 16));
8045 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11, static_cast<uint8_t>(program >> 8));
8046 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12, static_cast<uint8_t>(program));
8047 :
8048 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0);
8049 0 : WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x87, 0x40);
8050 0 : }
8051 :
8052 : // void DTCLib::DTC_Registers::SetDDROscillatorParameters_(uint64_t program)
8053 : // {
8054 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0x10);
8055 :
8056 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7, static_cast<uint8_t>(program >> 40));
8057 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8, static_cast<uint8_t>(program >> 32));
8058 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9, static_cast<uint8_t>(program >> 24));
8059 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10, static_cast<uint8_t>(program >> 16));
8060 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11, static_cast<uint8_t>(program >> 8));
8061 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12, static_cast<uint8_t>(program));
8062 :
8063 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0);
8064 : // WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x87, 0x40);
8065 : // }
8066 :
8067 0 : bool DTCLib::DTC_Registers::WaitForLinkReady_(DTC_Link_ID const& link, size_t interval, double timeout /*seconds*/)
8068 : {
8069 0 : auto start = std::chrono::steady_clock::now();
8070 0 : auto last_print = start;
8071 0 : bool ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
8072 :
8073 0 : while (!ready)
8074 : {
8075 0 : usleep(interval);
8076 0 : ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
8077 0 : if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - last_print).count() > 5.0)
8078 : {
8079 0 : __COUT__ << "DTC_Registers: WaitForLinkReady_: ROC Link " << link << ": PLL Locked: " << std::boolalpha << ReadSERDESPLLLocked(link) << ", RX Reset Done: " << ReadResetRXSERDESDone(link) << ", TX Reset Done: " << ReadResetTXSERDESDone(link) << ", CDR Lock: " << ReadSERDESRXCDRLock(link);
8080 0 : last_print = std::chrono::steady_clock::now();
8081 : }
8082 0 : if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - start).count() > timeout)
8083 : {
8084 0 : __COUT_ERR__ << "DTC_Registers: WaitForLinkReady_ ABORTING: ROC Link " << link << ": PLL Locked: " << std::boolalpha << ReadSERDESPLLLocked(link) << ", RX Reset Done: " << ReadResetRXSERDESDone(link) << ", TX Reset Done: " << ReadResetTXSERDESDone(link) << ", CDR Lock: " << ReadSERDESRXCDRLock(link);
8085 0 : return false;
8086 : }
8087 : }
8088 0 : return true;
8089 : }
|