DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
WIB Class Reference

#include <WIB.hh>

Inheritance diagram for WIB:
[legend]
Collaboration diagram for WIB:
[legend]

Public Types

enum  WIB_DAQ_t { UNKNOWN , RCE , FELIX }

Public Member Functions

 WIB (std::string const &address, std::string const &WIBAddressTable="WIB.adt", std::string const &FEMBAddressTable="FEMB.adt", bool fullStart=true)
 ~WIB ()
void FullStart ()
void InitializeWIB ()
void ResetWIB (bool reset_udp=false)
void InitializeDTS (uint8_t PDTSsource=0, uint8_t clockSource=0, uint32_t PDTSAlignment_timeout=0)
void EnableDAQLink (uint8_t iDAQLink)
void EnableDAQLink_Lite (uint8_t iDAQLink, uint8_t enable)
void StartSyncDTS ()
void ResetWIBAndCfgDTS (uint8_t localClock, uint8_t PDTS_TGRP, uint8_t PDTSsource=0, uint32_t PDTSAlignment_timeout=0)
void CheckedResetWIBAndCfgDTS (uint8_t localClock, uint8_t PDTS_TGRP, uint8_t PDTSsource=0, uint32_t PDTSAlignment_timeout=0)
void StartStreamToDAQ (bool l1=true, bool l2=true, bool l3=false, bool l4=false)
void PDTSInRunningState ()
void EnableFEMBCNC ()
void DisableFEMBCNC ()
void FEMBPower (uint8_t iFEMB, bool turnOn)
void SourceFEMB (uint64_t iDAQLink, uint64_t real)
void StartEventBuilder (uint8_t mask=0xF)
void StopEventBuilder (uint8_t mask=0xF)
void WriteQSFP (uint16_t address, uint32_t value, uint8_t byte_count)
uint32_t ReadQSFP (uint16_t address, uint8_t byte_count)
void WriteDTS_CDS (uint16_t address, uint32_t value, uint8_t byte_count=4, bool ignore_error=false)
uint32_t ReadDTS_CDS (uint16_t address, uint8_t byte_count=4)
float ConfigureDTSCDS (uint8_t source=0)
void WriteDTS_SI5344 (uint16_t address, uint32_t value, uint8_t byte_count=4)
uint32_t ReadDTS_SI5344 (uint16_t address, uint8_t byte_count=4)
void SetDTS_SI5344Page (uint8_t page)
uint8_t GetDTS_SI5344Page ()
uint8_t GetDTS_SI5344AddressPage (uint16_t address)
void LoadConfigDTS_SI5344 (std::string const &fileName)
void ResetSi5344 ()
void SelectSI5344 (uint64_t input, bool enable)
void SelectSI5342 (uint64_t input, bool enable)
void WriteDAQ_SI5342 (uint16_t address, uint32_t value, uint8_t byte_count=4)
uint32_t ReadDAQ_SI5342 (uint16_t address, uint8_t byte_count=4)
void SetDAQ_SI5342Page (uint8_t page)
uint8_t GetDAQ_SI5342Page ()
uint8_t GetDAQ_SI5342AddressPage (uint16_t address)
void LoadConfigDAQ_SI5342 (std::string const &fileName)
void ResetSi5342 ()
std::vector< uint32_t > CaptureHistory (std::string const &address)
std::vector< uint128_t > CaptureHistory (std::string const &address, size_t wordCount)
uint32_t ReadLocalFlash (uint16_t address)
std::vector< uint32_t > ReadLocalFlash (uint16_t address, size_t n)
void WriteLocalFlash (uint16_t address, uint32_t data)
void WriteLocalFlash (uint16_t address, std::vector< uint32_t > const &data)
void FlashCheckBusy ()
void ReadFlash (std::string const &fileName, uint8_t update_percentage=101)
void WriteFlash (std::vector< uint32_t > data, uint8_t update_percentage=101)
void ProgramFlash (std::string const &fileName, uint8_t update_percentage=101)
void EraseFlash (bool print_updates=false)
void CheckFlash (std::vector< uint32_t > data, uint8_t update_percentage=101)
std::vector< data_8b10b_t > ReadOutCDLinkSpyBuffer ()
std::vector< data_8b10b_t > ReadDAQLinkSpyBuffer (uint8_t iDAQLink, uint8_t trigger_mode=0)
void SetupFEMBExtClock (uint8_t iFEMB)
 Setup FEMB External Clock.
void WriteFEMBPhase (uint8_t iFEMB, uint16_t clk_phase_data)
bool TryFEMBPhases (uint8_t iFEMB, std::vector< uint16_t > phases)
bool HuntFEMBPhase (uint8_t iFEMB, uint16_t clk_phase_data_start)
void ConfigFEMB (uint8_t iFEMB, std::vector< uint32_t > fe_config, std::vector< uint16_t > clk_phases, uint8_t pls_mode=0, uint8_t pls_dac_val=0, uint8_t start_frame_mode_sel=1, uint8_t start_frame_swap=1)
 Setup FEMB in real or pulser data mode.
void ConfigFEMBFakeData (uint8_t iFEMB, uint8_t fake_mode, uint32_t fake_word, uint8_t femb_number, std::vector< uint32_t > fake_samples, uint8_t start_frame_mode_sel=1, uint8_t start_frame_swap=1)
 Setup FEMB in fake data mode.
void ConfigFEMBMode (uint8_t iFEMB, uint32_t pls_cs, uint32_t dac_sel, uint32_t fpga_dac, uint32_t asic_dac, uint32_t mon_cs)
uint16_t SetupFEMBASICs (uint8_t iFEMB, uint8_t gain, uint8_t shape, uint8_t highBaseline, bool highLeakage, bool leakagex10, bool acCoupling, bool buffer, bool useExtClock, uint8_t internalDACControl, uint8_t internalDACValue)
 Setup FEMB ASICs.
void SetupFPGAPulser (uint8_t iFEMB, uint8_t dac_val)
void SetupInternalPulser (uint8_t iFEMB)
uint16_t SetupASICPulserBits (uint8_t iFEMB)
uint16_t SetupFEMBASICs (uint8_t iFEMB, std::vector< uint32_t > registerList)
 Setup FEMB ASICs.
void ConfigWIBFakeData (bool enableFakeFEMB1, bool enableFakeFEMB2, bool enableFakeFEMB3, bool enableFakeFEMB4, bool counter)
void SetFEMBFakeCOLDATAMode (uint8_t iFEMB, uint8_t iCD, bool mode=0)
uint8_t GetFEMBFakeCOLDATAMode (uint8_t iFEMB, uint8_t iCD)
void SetFEMBStreamSource (uint8_t iFEMB, uint8_t iStream, bool real=true)
uint8_t GetFEMBStreamSource (uint8_t iFEMB, uint8_t iStream)
void SetEventBuilderDebugMode (uint8_t mask=0xF)
uint8_t GetEventBuilderDebugMode ()
char GetFEMBChar (uint8_t iFEMB)
char GetDAQLinkChar (uint8_t iDAQLink)
char GetFEMBCDChar (uint8_t iCD)
bool CheckDAQLinkInRange (uint8_t iDAQLink)
bool CheckFEMBInRange (uint8_t iFEMB)
bool CheckFEMBStreamInRange (uint8_t iStream)
bool CheckFEMBCDInRange (uint8_t iCD)
uint8_t GetFEMBCount ()
WIB_DAQ_t GetDAQMode ()
void SetContinueOnFEMBRegReadError (bool enable)
void SetContinueOnFEMBSPIError (bool enable)
void SetContinueOnFEMBSyncError (bool enable)
void SetContinueIfListOfFEMBClockPhasesDontSync (bool enable)
Public Member Functions inherited from WIBBase
 WIBBase (std::string const &address, std::string const &WIBAddressTable, std::string const &FEMBAddressTable)
 ~WIBBase ()
std::string GetAddress ()
uint32_t Read (uint16_t address)
uint32_t ReadWithRetry (uint16_t address)
uint32_t Read (std::string const &address)
uint32_t ReadWithRetry (std::string const &address)
void Write (uint16_t address, uint32_t value)
void WriteWithRetry (uint16_t address, uint32_t value)
void Write (std::string const &address, uint32_t value)
void WriteWithRetry (std::string const &address, uint32_t value)
void Write (uint16_t address, std::vector< uint32_t > const &values)
void Write (std::string const &address, std::vector< uint32_t > const &values)
void Write (uint16_t address, uint32_t const *values, size_t word_count)
void Write (std::string const &address, uint32_t const *values, size_t word_count)
uint32_t ReadI2C (std::string const &base_address, uint16_t I2C_aaddress, uint8_t byte_count=4)
void WriteI2C (std::string const &base_address, uint16_t I2C_address, uint32_t data, uint8_t byte_count=4, bool ignore_error=false)
std::vector< std::string > GetNames (std::string const &regex)
std::vector< std::string > GetFEMBNames (std::string const &regex)
std::vector< std::string > GetAddresses (uint16_t lower, uint16_t upper)
std::vector< std::string > GetFEMBAddresses (uint16_t lower, uint16_t upper)
std::vector< std::string > GetTableNames (std::string const &regex)
std::vector< Item const * > GetTagged (std::string const &tag)
std::vector< Item const * > GetFEMBTagged (std::string const &tag)
uint32_t ReadFEMB (int iFEMB, uint16_t address)
uint32_t ReadFEMB (int iFEMB, std::string const &address)
void WriteFEMB (int iFEMB, uint16_t address, uint32_t value)
void WriteFEMB (int iFEMB, std::string const &address, uint32_t value)
void WriteFEMBBits (int iFEMB, uint16_t address, uint32_t pos, uint32_t mask, uint32_t value)
void EnableADC (uint64_t iFEMB, uint64_t enable)
Item const * GetItem (std::string const &)
Item const * GetFEMBItem (int iFEMB, std::string const &)
int GetSVNVersion ()

Public Attributes

bool started

Private Member Functions

 WIB ()
 WIB (const WIB &other)
WIB & operator= (const WIB &)

Private Attributes

WIB_DAQ_t DAQMode
uint8_t FEMBCount
uint8_t FEMBStreamCount
uint8_t FEMBCDACount
uint8_t DAQLinkCount
bool ContinueOnFEMBRegReadError
bool ContinueOnFEMBSPIError
bool ContinueOnFEMBSyncError
bool ContinueIfListOfFEMBClockPhasesDontSync

Detailed Description

Definition at line 26 of file WIB.hh.

Member Enumeration Documentation

◆ WIB_DAQ_t

Enumerator
UNKNOWN 
RCE 
FELIX 

Definition at line 208 of file WIB.hh.

@ UNKNOWN
Definition WIB.hh:208
@ FELIX
Definition WIB.hh:208
@ RCE
Definition WIB.hh:208

Constructor & Destructor Documentation

◆ WIB() [1/3]

WIB::WIB ( std::string const & address,
std::string const & WIBAddressTable = "WIB.adt",
std::string const & FEMBAddressTable = "FEMB.adt",
bool fullStart = true )

Definition at line 7 of file WIB.cpp.

11 : WIBBase(address, WIBAddressTable, FEMBAddressTable)
14 , FEMBCDACount(2)
19{
20
21 if (fullStart) {
22 // Figure out what kind of WIB firmware we are dealing with
23 FEMBCount = Read("SYSTEM.FEMB_COUNT");
24 DAQLinkCount = Read("SYSTEM.DAQ_LINK_COUNT");
25 // Hardcoded lookup for RCE and FELIX
26 if ((FEMBCount == 4) && (DAQLinkCount == 4)) {
27 DAQMode = RCE;
28 } else if ((FEMBCount == 4) && (DAQLinkCount == 2)) {
29 DAQMode = FELIX;
30 }
31 // TODO check FEMBStreamCount and FEMCDACount from registers on the WIB
32 // TODO create those registers
33 Write("POWER.ENABLE.MASTER_BIAS", 1);
34 started = true;
35 }
36}
uint32_t Read(uint16_t address)
Definition WIBBase.cpp:147
void Write(uint16_t address, uint32_t value)
Definition WIBBase.cpp:168
bool ContinueOnFEMBRegReadError
Definition WIB.hh:237
uint8_t FEMBCDACount
Definition WIB.hh:234
bool ContinueOnFEMBSyncError
Definition WIB.hh:239
bool ContinueOnFEMBSPIError
Definition WIB.hh:238
uint8_t FEMBStreamCount
Definition WIB.hh:233
WIB_DAQ_t DAQMode
Definition WIB.hh:231
bool ContinueIfListOfFEMBClockPhasesDontSync
Definition WIB.hh:240
bool started
Definition WIB.hh:33
uint8_t FEMBCount
Definition WIB.hh:232
uint8_t DAQLinkCount
Definition WIB.hh:235

◆ ~WIB()

WIB::~WIB ( )

Definition at line 38 of file WIB.cpp.

38{}

◆ WIB() [2/3]

WIB::WIB ( )
private

◆ WIB() [3/3]

WIB::WIB ( const WIB & other)
private

Member Function Documentation

◆ CaptureHistory() [1/2]

std::vector< uint32_t > WIB::CaptureHistory ( std::string const & address)

Definition at line 4 of file WIB_History.cpp.

5{
6 std::vector<uint32_t> ret;
7 uint32_t val;
8 while ((val = Read(address)) & 0x1) {
9 ret.push_back(val);
10 }
11 return ret;
12}

◆ CaptureHistory() [2/2]

std::vector< uint128_t > WIB::CaptureHistory ( std::string const & address,
size_t wordCount )

Definition at line 15 of file WIB_History.cpp.

16{
17 std::vector<uint128_t> ret;
18 bool capture = true;
19 uint16_t addr = GetItem(address)->address;
20 while (capture) {
21 uint128_t val = 0;
22 // Read address last since it causes the incr.
23 for (size_t offset = wordCount; offset > 0; offset--) {
24 val |= uint128_t(Read(addr + (offset - 1)) << 32 * (offset - 1));
25 }
26 ret.push_back(val);
27 if (!(val & 0x1)) {
28 break;
29 }
30 }
31 return ret;
32}
unsigned __int128 uint128_t
Definition WIB.hh:14
uint16_t address
Item const * GetItem(std::string const &)
Definition WIBBase.cpp:125
double offset

◆ CheckDAQLinkInRange()

bool WIB::CheckDAQLinkInRange ( uint8_t iDAQLink)

Definition at line 521 of file WIB.cpp.

522{
523 if (!((iDAQLink > 0) && (iDAQLink <= DAQLinkCount))) {
524 BUException::WIB_INDEX_OUT_OF_RANGE e;
525 e.Append("DAQ Link\n");
526 throw e;
527 }
528 return true;
529}

◆ CheckedResetWIBAndCfgDTS()

void WIB::CheckedResetWIBAndCfgDTS ( uint8_t localClock,
uint8_t PDTS_TGRP,
uint8_t PDTSsource = 0,
uint32_t PDTSAlignment_timeout = 0 )

Definition at line 289 of file WIB.cpp.

290{
291 if (DAQMode == UNKNOWN) {
292 BUException::WIB_DAQMODE_UNKNOWN e;
293 throw e;
294 }
295 if (localClock > 1) {
296 BUException::WIB_BAD_ARGS e;
297 e.Append("localClock > 1; must be 0 (for DTS) or 1 (for local clock)\n");
298 throw e;
299 }
300 if (PDTSsource > 1) {
301 BUException::WIB_BAD_ARGS e;
302 e.Append("PDTSsource > 1; must be 0 (for backplane) or 1 (for front panel)\n");
303 throw e;
304 }
305 if (16 <= PDTS_TGRP) {
306 BUException::WIB_BAD_ARGS e;
307 e.Append("PDTS TGRP > 15; must be 0 to 15\n");
308 throw e;
309 }
310
311 bool reset_check = false;
312 // Check if we are already in a good state
313 if (localClock > 0) {
314 printf("Checking if locked on local clock\n");
315 reset_check = ((Read("DTS.CONVERT_CONTROL.EN_FAKE") != 1) || (Read("DTS.CCONVERT_CONTROL.LOCAL_TIMESTAMP") != 1) ||
316 (Read("FEMB_CNC.CNC_CLOCK_SELECT") != 1)
317 // || (Read("FEMB_CNC.ENABLE_DTS_CMDS") != 1)
318 || (Read("DTS.SI5344.INPUT_SELECT") != 1) || (Read("DTS.SI5344.ENABLE") != 1));
319 if (!reset_check) {
320 printf("Already in a good state\n");
321 } else {
322 printf("Need to reset for local clocking\n");
323 }
324 } else {
325 printf("Checking if locked on PDTS\n");
326 reset_check = ((Read("DTS.PDTS_TGRP") != PDTS_TGRP) || (Read("FEMB_CNC.CNC_CLOCK_SELECT") != 1) ||
327 (Read("DTS.PDTS_ENABLE") != 1) || (Read("DTS.CDS.LOL") != 0) || (Read("DTS.CDS.LOS") != 0) ||
328 (ReadWithRetry("DTS.SI5344.INPUT_SELECT") != 0) || (ReadWithRetry("DTS.SI5344.LOS") != 0) ||
329 (ReadWithRetry("DTS.SI5344.LOL") != 0) || (ReadWithRetry("DTS.SI5344.ENABLE") != 1) ||
330 (ReadWithRetry("DTS.PDTS_STATE") != 0x8));
331 if (!reset_check) {
332 printf("Already in a good state\n");
333 } else {
334 printf("Need to reset for PDTS\n");
335 }
336 }
337
338 // Check the SI5342 if we're attached to FELIX
339 if (DAQMode == FELIX) {
340
341 if ((Read("DAQ.SI5342.ENABLE") == 0) || (Read("DAQ.SI5342.INPUT_SELECT") != 1) || (Read("DAQ.SI5342.LOL") == 1) ||
342 (Read("DAQ.SI5342.LOS_XAXB") == 1) || (Read("DAQ.SI5342.LOS_2") == 1)) {
343 printf("Need to reset for SI5342\n");
344 reset_check = true;
345 } else {
346 printf("SI5342 in good state\n");
347 }
348 }
349
350 if (reset_check) {
351 // get this register so we can leave it in the state it started in
352 uint32_t slow_control_dnd = Read("SYSTEM.SLOW_CONTROL_DND");
353
354 ResetWIB();
355 Write("SYSTEM.SLOW_CONTROL_DND", 1);
356
357 for (size_t iFEMB = 1; iFEMB <= 4; iFEMB++) {
358 FEMBPower(iFEMB, 0);
359 }
360
361 // make sure everything DTS is off
362 Write("DTS.CONVERT_CONTROL.HALT", 1);
363 Write("DTS.CONVERT_CONTROL.ENABLE", 0);
364 Write("DTS.CONVERT_CONTROL.START_SYNC", 0);
365 sleep(1);
366
367 if (localClock > 0) {
368 printf("Configuring local clock\n");
369 // Configure the SI5344 to use the local oscillator instead of the PDTS
370 LoadConfigDTS_SI5344("default");
371 sleep(1);
372 SelectSI5344(1, 1);
373 sleep(1);
374 Write("DTS.CONVERT_CONTROL.EN_FAKE", 1);
375 Write("DTS.CONVERT_CONTROL.LOCAL_TIMESTAMP", 1);
376 Write("FEMB_CNC.CNC_CLOCK_SELECT", 1);
377 // Write("FEMB_CNC.ENABLE_DTS_CMDS",1);
378 sleep(1);
379 } else {
380 // Configure the clocking for the PDTS (assumes the PDTS is sending idle or something)
381 printf("Configuring DTS\n");
382 Write("DTS.PDTS_TGRP", PDTS_TGRP);
383 printf("Using timing group 0x%X\n", PDTS_TGRP);
384 InitializeDTS(PDTSsource, 0, PDTSAlignment_timeout);
385 sleep(1);
386 Write("FEMB_CNC.CNC_CLOCK_SELECT", 1);
387 sleep(1);
388 // We are ready for the PDTS, start searching
389 Write("DTS.PDTS_ENABLE", 1);
390 sleep(1);
391 }
392
393 Write("SYSTEM.SLOW_CONTROL_DND", slow_control_dnd);
394 }
395 // Now we have the 128MHz clock
396 std::cout << "Resetting DAQ Links" << std::endl;
397 size_t nLinks = 4;
398 if (DAQMode == FELIX) {
399 nLinks = 2;
400 }
401 for (size_t iLink = 1; iLink <= nLinks; ++iLink) {
402 std::cout << iLink << std::endl;
403 EnableDAQLink_Lite(iLink, 0);
404 }
405
406 Write("FEMB1.DAQ.ENABLE", 0);
407 Write("FEMB2.DAQ.ENABLE", 0);
408 Write("FEMB3.DAQ.ENABLE", 0);
409 Write("FEMB4.DAQ.ENABLE", 0);
410}
#define sleep(x)
Definition WIB_FEMB.cpp:12
uint32_t ReadWithRetry(uint16_t address)
Definition WIBBase.cpp:142
void ResetWIB(bool reset_udp=false)
Definition WIB.cpp:154
void LoadConfigDTS_SI5344(std::string const &fileName)
void InitializeDTS(uint8_t PDTSsource=0, uint8_t clockSource=0, uint32_t PDTSAlignment_timeout=0)
Definition WIB_DTS.cpp:12
void EnableDAQLink_Lite(uint8_t iDAQLink, uint8_t enable)
Definition WIB.cpp:87
void SelectSI5344(uint64_t input, bool enable)
void FEMBPower(uint8_t iFEMB, bool turnOn)
Definition WIB.cpp:462

◆ CheckFEMBCDInRange()

bool WIB::CheckFEMBCDInRange ( uint8_t iCD)

Definition at line 616 of file WIB.cpp.

617{
618 if (!((iCDA > 0) && (iCDA <= FEMBCDACount))) {
619 BUException::WIB_INDEX_OUT_OF_RANGE e;
620 e.Append("FEMB CDA");
621 throw e;
622 }
623 return true;
624}

◆ CheckFEMBInRange()

bool WIB::CheckFEMBInRange ( uint8_t iFEMB)

Definition at line 563 of file WIB.cpp.

564{
565 if (!((iFEMB > 0) && (iFEMB <= FEMBCount))) {
566 BUException::WIB_INDEX_OUT_OF_RANGE e;
567 e.Append("FEMB\n");
568 throw e;
569 }
570 return true;
571}

◆ CheckFEMBStreamInRange()

bool WIB::CheckFEMBStreamInRange ( uint8_t iStream)

Definition at line 605 of file WIB.cpp.

606{
607 if (!((iStream > 0) && (iStream <= FEMBStreamCount))) {
608 BUException::WIB_INDEX_OUT_OF_RANGE e;
609 e.Append("FEMB Stream");
610 throw e;
611 }
612 return true;
613}

◆ CheckFlash()

void WIB::CheckFlash ( std::vector< uint32_t > data,
uint8_t update_percentage = 101 )

Definition at line 301 of file WIB_Flash.cpp.

302{
303 bool print_updates = false;
304 if (update_percentage < 100) {
305 print_updates = true;
306 }
307 size_t update_delta = (update_percentage * float(16 * 1024 * 1024 / 4)) / 100;
308 size_t next_update = update_delta;
309
310 if (print_updates) {
311 fprintf(stderr, " Checking flash\n");
312 fprintf(stderr, " [");
313 for (size_t i = 0; i < 100.0 / update_percentage; i++) {
314 fprintf(stderr, "=");
315 }
316 fprintf(stderr, "]\n [");
317 }
318 // program flash in groups of 64 32bit words (256 bytes)
319 uint32_t flashAddress = 0;
320 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address;
321
322 for (size_t currentBlockStartIndex = 0; currentBlockStartIndex < 16 * 1024 * 1024 / 4;) {
324
325 // Find size of this block to write (usually just 64 (256bytes)), but the last one might be smaller.
326 size_t blockSize = std::min(size_t(64), flashData.size() - currentBlockStartIndex);
327 // Set adddress
328 WriteWithRetry("FLASH.ADDRESS", flashAddress);
329 // set block size (in bytes and is 1 less than value; 0 means 1 byte, 255 means 256 bytes)
330 WriteWithRetry("FLASH.BYTE_COUNT", (blockSize * sizeof(uint32_t)) - 1);
331 // Start read
332 WriteWithRetry("FLASH.RUN_COMMAND", 0x5);
333
335
336 // Check the data.
337 for (size_t iBlockWord = 0; iBlockWord < blockSize; iBlockWord++) {
338 // flashData: Address in WIB register map of this 32bit word
339 // ReadWithRetry: Data from the flash for this word
340 uint32_t dataRead;
341 if ((dataRead = ReadWithRetry(blockRegMapAddress + iBlockWord)) !=
342 flashData[currentBlockStartIndex + iBlockWord]) {
343 BUException::WIB_FLASH_ERROR e;
344 char errorbuffer[] = "Error on index 0xXXXXXXXX: 0xXXXXXXXX != 0xXXXXXXXX";
345 snprintf(errorbuffer,
346 strlen(errorbuffer),
347 "Error on index 0x%08X: 0x%08X != 0x%08X",
348 flashAddress,
349 dataRead,
350 flashData[currentBlockStartIndex + iBlockWord]);
351 e.Append(errorbuffer);
352 throw e;
353 }
354 }
355 currentBlockStartIndex += blockSize;
356 flashAddress += blockSize * sizeof(uint32_t);
357
358 if (print_updates && (currentBlockStartIndex > next_update)) {
359 fprintf(stderr, "=");
360 next_update += update_delta;
361 }
362 }
363 if (print_updates) {
364 printf("]\n");
365 printf(" Check passed\n");
366 }
367}
void WriteWithRetry(uint16_t address, uint32_t value)
Definition WIBBase.cpp:163
void FlashCheckBusy()

◆ ConfigFEMB()

void WIB::ConfigFEMB ( uint8_t iFEMB,
std::vector< uint32_t > fe_config,
std::vector< uint16_t > clk_phases,
uint8_t pls_mode = 0,
uint8_t pls_dac_val = 0,
uint8_t start_frame_mode_sel = 1,
uint8_t start_frame_swap = 1 )

Setup FEMB in real or pulser data mode.

Sets up iFEMB (index from 1) fe_config: list of options to configure the FE ASICs: Gain: 0,1,2,3 for 4.7, 7.8, 14, 25 mV/fC, respectively Shaping Time: 0,1,2,3 for 0.5, 1, 2, 3 us, respectively High Baseline: 0 for 200 mV, 1 for 900 mV, 2 for 200 mV on collection and 900 mV on induction High Leakage: 0 for 100 pA, 1 for 500 pA Leakage x 10: if 1, multiply leakage times 10 AC Coupling : 0 for DC coupling, 1 for AC coupling (between FE and ADC) Buffer: 0 for disable and bypass, 1 for use (between FE and ADC) Use External Clock: 0 ADC use internal clock, 1 ADC use FPGA clocking (almost always want 1) clk_phases: a list of 16 bit values to try for the ADC clock phases. Tries these values until the sync check bits are all 0, and hunts for good values if these all fail. The most significant byte is ADC_ASIC_CLK_PHASE_SELECT (register 6) while the least significant byte is ADC_ASIC_CLK_PHASE_SELECT (register 15) pls_mode: pulser mode select: 0 off, 1 FE ASIC internal pulser, 2 FPGA pulser pls_dac_val: pulser DAC value (amplitude) 6-bits in ASIC test pulse mode, 5-bits in FPGA test pulse mode start_frame_mode_sel: 1 to make data frame start the way BU WIB firmware expects start_frame_swap: 1 to reverse the start bits

Definition at line 38 of file WIB_FEMB.cpp.

45{
46
47 if (iFEMB < 1 || iFEMB > 4) {
48 BUException::WIB_BAD_ARGS e;
49 std::stringstream expstr;
50 expstr << "ConfigFEMB: iFEMB should be between 1 and 4: " << int(iFEMB);
51 e.Append(expstr.str().c_str());
52 throw e;
53 }
54 if (pls_mode > 2) {
55 BUException::WIB_BAD_ARGS e;
56 std::stringstream expstr;
57 expstr << "ConfigFEMB: pls_dac_mode is allowed to be 0 (off), 1 (FPGA), 2 (internal), but is: " << int(pls_mode);
58 e.Append(expstr.str().c_str());
59 throw e;
60 }
61 if (start_frame_mode_sel > 1 || start_frame_swap > 1) {
62 BUException::WIB_BAD_ARGS e;
63 std::stringstream expstr;
64 expstr << "ConfigFEMB: start_frame_mode_sel and start_frame_swap must be 0 or 1";
65 e.Append(expstr.str().c_str());
66 throw e;
67 }
68
69 if (fe_config.size() != 8) {
70
71 BUException::WIB_BAD_ARGS e;
72 std::stringstream expstr;
73 expstr << "Error: Expecting 9 Front End configuration options:" << std::endl
74 << "\t0: Gain" << std::endl
75 << "\t1: Shaping Time" << std::endl
76 << "\t2: High Baseline" << std::endl
77 << "\t3: High Leakage" << std::endl
78 << "\t4: Leakage x 10" << std::endl
79 << "\t5: AC Coupling" << std::endl
80 << "\t6: Buffer" << std::endl
81 << "\t7: Use External Clock" << std::endl;
82 e.Append(expstr.str().c_str());
83 throw e;
84 } else {
85 std::cout << "Front End configuration options:" << std::endl
86 << "\t0:" << std::setw(22) << std::setfill(' ') << "Gain " << fe_config[0] << std::endl
87 << "\t1:" << std::setw(22) << std::setfill(' ') << "Shaping Time " << fe_config[1] << std::endl
88 << "\t2:" << std::setw(22) << std::setfill(' ') << "High Baseline " << fe_config[2] << std::endl
89 << "\t3:" << std::setw(22) << std::setfill(' ') << "High Leakage " << fe_config[3] << std::endl
90 << "\t4:" << std::setw(22) << std::setfill(' ') << "Leakage x 10 " << fe_config[4] << std::endl
91 << "\t5:" << std::setw(22) << std::setfill(' ') << "AC Coupling " << fe_config[5] << std::endl
92 << "\t6:" << std::setw(22) << std::setfill(' ') << "Buffer " << fe_config[6] << std::endl
93 << "\t8:" << std::setw(22) << std::setfill(' ') << "Use External Clock " << fe_config[7] << std::endl;
94 }
95
96 std::cout << "Pulser Mode: " << int(pls_mode) << " and DAC Value: " << int(pls_dac_val) << std::endl;
97
98 // get this register so we can leave it in the state it started in
99 uint32_t slow_control_dnd = Read("SYSTEM.SLOW_CONTROL_DND");
100 Write("SYSTEM.SLOW_CONTROL_DND", 1);
101
102 if (ReadFEMB(iFEMB, "VERSION_ID") == ReadFEMB(iFEMB, "SYS_RESET")) { // can't read register if equal
104 std::cout << "Error: Can't read registers from FEMB " << int(iFEMB) << std::endl;
105 return;
106 }
107 BUException::FEMB_REG_READ_ERROR e;
108 std::stringstream expstr;
109 expstr << " for FEMB: " << int(iFEMB);
110 e.Append(expstr.str().c_str());
111 throw e;
112 }
113
114 WriteFEMB(iFEMB, "REG_RESET", 1);
115 sleep(1);
116
117 WriteFEMB(iFEMB, "START_FRAME_MODE_SELECT", start_frame_mode_sel);
118 sleep(1);
119 WriteFEMB(iFEMB, "START_FRAME_SWAP", start_frame_swap);
120
121 if (fe_config[7]) { // use external clock
122 SetupFEMBExtClock(iFEMB);
123 }
124 sleep(0.05);
125
126 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
127 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
128
129 // These are all Jack's WIB addresses, need to figure out Dan's addresses for functionality
131 // Write(1, 0);
132 // Write(1, 0);
133 // Write(1, 2);
134 // Write(1, 2);
135 // Write(1, 0);
136 // Write(1, 0);
137 //
139 // Write(18, 0x8000);
140 // Write(18, 0x8000);
141
142 // Reset SPI
143 //
144 sleep(0.005);
145 WriteFEMB(iFEMB, "ADC_ASIC_RESET", 0x1);
146 sleep(0.005);
147 WriteFEMB(iFEMB, "ADC_ASIC_RESET", 0x1);
148 sleep(0.005);
149 WriteFEMB(iFEMB, "FE_ASIC_RESET", 0x1);
150 sleep(0.005);
151 WriteFEMB(iFEMB, "FE_ASIC_RESET", 0x1);
152 sleep(0.005);
153
154 // Set ADC latch_loc
155 uint32_t REG_LATCHLOC1_4_data = 0x04040404;
156 uint32_t REG_LATCHLOC5_8_data = 0x04040404;
157
158 WriteFEMB(iFEMB, "ADC_LATCH_LOC_0TO3", REG_LATCHLOC1_4_data);
159 WriteFEMB(iFEMB, "ADC_LATCH_LOC_4TO7", REG_LATCHLOC5_8_data);
160
161 // Setup pulser
162 uint8_t internal_daq_value = 0;
163 if (pls_mode == 1) // internal, FE ASIC, 6 bits
164 {
165 if (pls_dac_val >= 63) {
166 BUException::WIB_BAD_ARGS e;
167 std::stringstream expstr;
168 expstr << "ConfigFEMB: pls_dac_val is 6 bits for internal DAC, must be 0-63, but is: " << int(pls_dac_val);
169 e.Append(expstr.str().c_str());
170 throw e;
171 }
172 internal_daq_value = pls_dac_val;
173 SetupInternalPulser(iFEMB);
174 } else if (pls_mode == 2) // external, FPGA, 5 bits
175 {
176 if (pls_dac_val >= 32) {
177 BUException::WIB_BAD_ARGS e;
178 std::stringstream expstr;
179 expstr << "ConfigFEMB: pls_dac_val is 5 bits for FPGA DAC, must be 0-31, but is: " << int(pls_dac_val);
180 e.Append(expstr.str().c_str());
181 throw e;
182 }
183 SetupFPGAPulser(iFEMB, pls_dac_val);
184 }
185
186 // Setup ASICs
187 SetupFEMBASICs(iFEMB,
188 fe_config[0],
189 fe_config[1],
190 fe_config[2],
191 fe_config[3],
192 fe_config[4],
193 fe_config[5],
194 fe_config[6],
195 fe_config[7],
196 pls_mode,
197 internal_daq_value);
198 std::cout << "FEMB " << int(iFEMB) << " Successful SPI config" << std::endl;
199
200 // Try to sync ADCs
201 if (clk_phases.size() == 0) {
202 clk_phases.push_back(0xFFFF);
203 }
204 if (!TryFEMBPhases(iFEMB, clk_phases)) {
206 std::cout << "Warning: FEMB " << int(iFEMB)
207 << " ADC FIFO not synced from expected phases, trying to hunt for phases" << std::endl;
208 if (!HuntFEMBPhase(iFEMB, clk_phases.at(0))) {
210 std::cout << "Error: FEMB " << int(iFEMB) << " ADC FIFO could not be synced even after hunting" << std::endl;
211 } else {
212 uint16_t adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
213 BUException::FEMB_ADC_SYNC_ERROR e;
214 std::stringstream expstr;
215 expstr << " after hunting. ";
216 expstr << " FEMB: " << int(iFEMB);
217 expstr << " sync: " << std::bitset<16>(adc_fifo_sync);
218 expstr << " phases: ";
219 expstr << std::hex << std::setfill('0') << std::setw(2) << ReadFEMB(iFEMB, "ADC_ASIC_CLK_PHASE_SELECT");
220 expstr << std::hex << std::setfill('0') << std::setw(2) << ReadFEMB(iFEMB, "ADC_ASIC_CLK_PHASE_SELECT_2");
221 e.Append(expstr.str().c_str());
222 throw e;
223 }
224 } // if ! HuntFEMBPhase
225 } // if ContinueIfListOfFEMBClockPhasesDontSync
226 else // ContinueIfListOfFEMBClockPhasesDontSync
227 {
228 uint16_t adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
229 BUException::FEMB_ADC_SYNC_ERROR e;
230 std::stringstream expstr;
231 expstr << " after trying all in list. ";
232 expstr << " FEMB: " << int(iFEMB);
233 expstr << " sync: " << std::bitset<16>(adc_fifo_sync);
234 expstr << " phases tried: " << std::endl;
235 for (size_t iclk_phase = 0; iclk_phase < clk_phases.size(); iclk_phase++) {
236 expstr << " " << std::hex << std::setfill('0') << std::setw(4) << clk_phases[iclk_phase] << std::endl;
237 }
238 e.Append(expstr.str().c_str());
239 throw e;
240 } // else ContinueIfListOfFEMBClockPhasesDontSync
241 } // if ! TryFEMBPhases
242 uint16_t adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
243 std::cout << "FEMB " << int(iFEMB) << " Final ADC FIFO sync: " << std::bitset<16>(adc_fifo_sync) << std::endl;
244 std::cout << "FEMB " << int(iFEMB) << " Final Clock Phases: " << std::hex << std::setfill('0') << std::setw(2)
245 << ReadFEMB(iFEMB, "ADC_ASIC_CLK_PHASE_SELECT") << std::hex << std::setfill('0') << std::setw(2)
246 << ReadFEMB(iFEMB, "ADC_ASIC_CLK_PHASE_SELECT_2") << std::endl;
247
248 // time stamp reset
249 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
250 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
251
252 // These are all Jack's WIB addresses, need to figure out Dan's addresses for functionality
254 // Write(1, 0);
255 // Write(1, 0);
256 // Write(1, 2);
257 // Write(1, 2);
258 // Write(1, 0);
259 // Write(1, 0);
260 //
262 // Write(18, 0x8000);
263 // Write(18, 0x8000);
264
265 Write("SYSTEM.SLOW_CONTROL_DND", slow_control_dnd);
266}
void WriteFEMB(int iFEMB, uint16_t address, uint32_t value)
Definition WIBBase.cpp:227
uint32_t ReadFEMB(int iFEMB, uint16_t address)
Definition WIBBase.cpp:204
bool TryFEMBPhases(uint8_t iFEMB, std::vector< uint16_t > phases)
void SetupFEMBExtClock(uint8_t iFEMB)
Setup FEMB External Clock.
Definition WIB_FEMB.cpp:372
bool HuntFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data_start)
void SetupInternalPulser(uint8_t iFEMB)
Definition WIB_FEMB.cpp:946
void SetupFPGAPulser(uint8_t iFEMB, uint8_t dac_val)
Definition WIB_FEMB.cpp:929
uint16_t SetupFEMBASICs(uint8_t iFEMB, uint8_t gain, uint8_t shape, uint8_t highBaseline, bool highLeakage, bool leakagex10, bool acCoupling, bool buffer, bool useExtClock, uint8_t internalDACControl, uint8_t internalDACValue)
Setup FEMB ASICs.
Definition WIB_FEMB.cpp:619

◆ ConfigFEMBFakeData()

void WIB::ConfigFEMBFakeData ( uint8_t iFEMB,
uint8_t fake_mode,
uint32_t fake_word,
uint8_t femb_number,
std::vector< uint32_t > fake_samples,
uint8_t start_frame_mode_sel = 1,
uint8_t start_frame_swap = 1 )

Setup FEMB in fake data mode.

Sets up iFEMB (index from 1) in fake data mode fake_mode: 0 for real data, 1 for fake word, 2 for fake waveform, 3 for channel indicator (FEMB, chip, channel), 4 for channel indicator (counter, chip, channel) fake_word: 12 bit wrd to use when in fake word mode femb_number: femb number to use in fake_mode 3 fake_samples: vector of samples to use in fake_mode 2

Sets up iFEMB (index from 1) in fake data mode fake_mode: 0 for real data, 1 for fake word, 2 for fake waveform, 3 for channel indicator (FEMB, chip, channel), 4 for channel indicator (counter, chip, channel) fake_word: 12 bit wrd to use when in fake word mode femb_number: femb number to use in fake_mode 3, 4 bits fake_samples: vector of samples to use in fake_mode 2

Definition at line 278 of file WIB_FEMB.cpp.

285{
286
287 if (iFEMB < 1 || iFEMB > 4) {
288 BUException::WIB_BAD_ARGS e;
289 std::stringstream expstr;
290 expstr << "ConfigFEMBFakeData: iFEMB should be between 1 and 4: " << int(iFEMB);
291 e.Append(expstr.str().c_str());
292 throw e;
293 }
294 if (start_frame_mode_sel > 1 || start_frame_swap > 1) {
295 BUException::WIB_BAD_ARGS e;
296 std::stringstream expstr;
297 expstr << "ConfigFEMBFakeData: start_frame_mode_sel and start_frame_swap must be 0 or 1";
298 e.Append(expstr.str().c_str());
299 throw e;
300 }
301 if (fake_mode == 1 && fake_word > 0xFFF) {
302 BUException::WIB_BAD_ARGS e;
303 std::stringstream expstr;
304 expstr << "ConfigFEMBFakeData: fake_word must be only 12 bits i.e. <= 4095, is: " << fake_word;
305 e.Append(expstr.str().c_str());
306 throw e;
307 }
308 if (fake_mode == 2 && fake_samples.size() != 256) {
309 BUException::WIB_BAD_ARGS e;
310 std::stringstream expstr;
311 expstr << "ConfigFEMBFakeData: femb_samples must be 255 long, is: " << fake_samples.size();
312 e.Append(expstr.str().c_str());
313 throw e;
314 }
315 if (fake_mode == 3 && femb_number > 0xF) {
316 BUException::WIB_BAD_ARGS e;
317 std::stringstream expstr;
318 expstr << "ConfigFEMBFakeData: femb_number must be only 4 bits i.e. <= 15, is: " << int(femb_number);
319 e.Append(expstr.str().c_str());
320 throw e;
321 }
322
323 // get this register so we can leave it in the state it started in
324 uint32_t slow_control_dnd = Read("SYSTEM.SLOW_CONTROL_DND");
325 Write("SYSTEM.SLOW_CONTROL_DND", 1);
326
327 WriteFEMB(iFEMB, "REG_RESET", 1);
328 sleep(1);
329
330 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 0);
331 sleep(1);
332
333 WriteFEMB(iFEMB, "START_FRAME_MODE_SELECT", start_frame_mode_sel);
334 sleep(1);
335 WriteFEMB(iFEMB, "START_FRAME_SWAP", start_frame_swap);
336 sleep(0.05);
337
338 // time stamp reset
339 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
340 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
341
342 // Now do the Fake data mode setup
343 if (fake_mode == 1) {
344 WriteFEMB(iFEMB, "DATA_TEST_PATTERN", fake_word);
345 }
346 if (fake_mode == 2) {
347 // Put waveform in FEMB registers
348 for (size_t iSample = 0; iSample < 256; iSample++) {
349 WriteFEMB(iFEMB, 0x300 + iSample, fake_samples.at(iSample));
350 sleep(0.005);
351 }
352 }
353 if (fake_mode == 3) {
354 WriteFEMB(iFEMB, "FEMB_NUMBER", femb_number);
355 }
356 WriteFEMB(iFEMB, "FEMB_TST_SEL", fake_mode);
357
358 // time stamp reset
359 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
360 WriteFEMB(iFEMB, "TIME_STAMP_RESET", 1);
361
362 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 9);
363
364 Write("SYSTEM.SLOW_CONTROL_DND", slow_control_dnd);
365}

◆ ConfigFEMBMode()

void WIB::ConfigFEMBMode ( uint8_t iFEMB,
uint32_t pls_cs,
uint32_t dac_sel,
uint32_t fpga_dac,
uint32_t asic_dac,
uint32_t mon_cs = 0 )

Definition at line 1139 of file WIB_FEMB.cpp.

1145{
1146 uint32_t tp_sel;
1147 if (mon_cs == 0) {
1148 tp_sel = ((asic_dac & 0x01) << 1) + (fpga_dac & 0x01) + ((dac_sel & 0x1) << 8);
1149 } else {
1150 tp_sel = 0x402;
1151 }
1152 WriteFEMB(iFEMB, 16, tp_sel & 0x0000FFFF);
1153 WriteFEMB(iFEMB, 18, 0x11);
1154 uint32_t pls_cs_value = 0x00;
1155 if (pls_cs == 0)
1156 pls_cs_value = 0x11; // disable all
1157 else if (pls_cs == 1)
1158 pls_cs_value = 0x10; // internal pls
1159 else if (pls_cs == 2)
1160 pls_cs_value = 0x01; // external pls
1161
1162 WriteFEMB(iFEMB, 18, pls_cs_value);
1163}

◆ ConfigureDTSCDS()

float WIB::ConfigureDTSCDS ( uint8_t source = 0)

Definition at line 48 of file WIB_CDS.cpp.

49{
50 if (source > 1) {
51 BUException::WIB_BAD_ARGS e;
52 e.Append("Bad DTS CDS clock source");
53 throw e;
54 }
55
56 // Set timing system source (FP:0 BP:1)
57 WriteWithRetry("DTS.CDS.INPUT_SELECT", source);
58
59 // Reset the I2C firmware
60 WriteWithRetry("DTS.CDS.I2C.RESET", 1);
61 // Reset the CDS chip (ADN2814)
62 WriteDTS_CDS(0x9, 0x20, 1);
63 usleep(500000);
64
65 // Reset the I2C firmware
66 WriteWithRetry("DTS.CDS.I2C.RESET", 1);
67 // Un reset
68 WriteDTS_CDS(0x9, 0x00, 1, true);
69 // Reset the I2C firmware
70 WriteWithRetry("DTS.CDS.I2C.RESET", 1);
71 usleep(1000000);
72
73 // read bits 8 downto 1 from reg 3
74 uint16_t dataRateLookup = uint16_t(ReadDTS_CDS(0x3, 1)) << 1;
75 // Read bit 0 from reg 4
76 dataRateLookup |= uint16_t(ReadDTS_CDS(0x4, 1)) & 0x1;
77 if (dataRateLookup >= COURSE_DATARATE_SIZE) {
78 return -1;
79 }
80 return courseDataRates[dataRateLookup];
81}
static float courseDataRates[COURSE_DATARATE_SIZE]
Definition WIB_CDS.cpp:7
#define COURSE_DATARATE_SIZE
Definition WIB_CDS.cpp:6
uint32_t ReadDTS_CDS(uint16_t address, uint8_t byte_count=4)
Definition WIB_CDS.cpp:42
void WriteDTS_CDS(uint16_t address, uint32_t value, uint8_t byte_count=4, bool ignore_error=false)
Definition WIB_CDS.cpp:37

◆ ConfigWIBFakeData()

void WIB::ConfigWIBFakeData ( bool enableFakeFEMB1,
bool enableFakeFEMB2,
bool enableFakeFEMB3,
bool enableFakeFEMB4,
bool counter )

Definition at line 5 of file WIB_FAKE_CD.cpp.

10{ // counter==true: counter instead of COLDATA frame, else samples in COLDATA frame
11
12 if (DAQMode == FELIX) {
13 // Don't allow fake mode on only half of a FELIX link
14 if ((enableFakeFEMB1 ^ enableFakeFEMB2) || (enableFakeFEMB3 ^ enableFakeFEMB4)) {
15 BUException::WIB_FAKE_DATA_ON_HALF_FELIX_LINK e;
16 throw e;
17 }
18 }
19
20 // Setup the FEMBs/Links
21 for (size_t iFEMB = 1; iFEMB <= FEMBCount; iFEMB++) {
22 for (size_t iCDA = 1; iCDA <= FEMBCDACount; iCDA++) {
23 SetFEMBFakeCOLDATAMode(iFEMB, iCDA, counter);
24 }
25 }
26
27 for (size_t iStream = 1; iStream <= FEMBStreamCount; iStream++) {
28 SetFEMBStreamSource(1, iStream, !enableFakeFEMB1);
29 SetFEMBStreamSource(2, iStream, !enableFakeFEMB2);
30 SetFEMBStreamSource(3, iStream, !enableFakeFEMB3);
31 SetFEMBStreamSource(4, iStream, !enableFakeFEMB4);
32 }
33
34 uint64_t enableWord1 = 0;
35 uint64_t enableWord2 = 0;
36 uint64_t enableWord3 = 0;
37 uint64_t enableWord4 = 0;
38 if (enableFakeFEMB1)
39 enableWord1 = 0xF;
40 if (enableFakeFEMB2)
41 enableWord2 = 0xF;
42 if (enableFakeFEMB3)
43 enableWord3 = 0xF;
44 if (enableFakeFEMB4)
45 enableWord4 = 0xF;
46 SourceFEMB(1, enableWord1);
47 SourceFEMB(2, enableWord2);
48 SourceFEMB(3, enableWord3);
49 SourceFEMB(4, enableWord4);
50}
void SetFEMBStreamSource(uint8_t iFEMB, uint8_t iStream, bool real=true)
void SourceFEMB(uint64_t iDAQLink, uint64_t real)
Definition WIB.cpp:652
void SetFEMBFakeCOLDATAMode(uint8_t iFEMB, uint8_t iCD, bool mode=0)

◆ DisableFEMBCNC()

void WIB::DisableFEMBCNC ( )

Definition at line 513 of file WIB.cpp.

514{
515 // Enable the clock and control stream to the FEMBs
516 Write("FEMB_CNC.CNC_CLOCK_SELECT", 0);
517 Write("FEMB_CNC.CNC_COMMAND_SELECT", 0);
518}

◆ EnableDAQLink()

void WIB::EnableDAQLink ( uint8_t iDAQLink)

Definition at line 59 of file WIB.cpp.

60{
61 // CHeck if we know how to dael with this firmware
62 if (!((DAQMode == RCE) || (DAQMode == FELIX))) {
63 // Not RCE or FELIX firmware, return
64 BUException::WIB_FEATURE_NOT_SUPPORTED e;
65 e.Append("Automatic DAQLink configuration not supported with this firmware.\n");
66 throw e;
67 }
68
69 // Build the base string for this DAQLINK
70 std::string base("DAQ_LINK_");
71 base.push_back(GetDAQLinkChar(iDAQLink));
72 base.append(".CONTROL.");
73 printf("%s\n", base.c_str());
74
75 // set the CD stream enable mask from that
76 uint32_t enable_mask = 0;
77 for (size_t iStream = 0; iStream < (4 * FEMBCount / DAQLinkCount); iStream++) {
78 enable_mask <<= 0x1;
79 }
80
81 Write(base + "ENABLE_CDA_STREAM", enable_mask);
82
83 Write(base + "ENABLE", 0x1);
84}
char GetDAQLinkChar(uint8_t iDAQLink)
Definition WIB.cpp:532

◆ EnableDAQLink_Lite()

void WIB::EnableDAQLink_Lite ( uint8_t iDAQLink,
uint8_t enable )

Definition at line 87 of file WIB.cpp.

88{
89 // CHeck if we know how to dael with this firmware
90 if (!((DAQMode == RCE) || (DAQMode == FELIX))) {
91 // Not RCE or FELIX firmware, return
92 BUException::WIB_FEATURE_NOT_SUPPORTED e;
93 e.Append("Automatic DAQLink configuration not supported with this firmware.\n");
94 throw e;
95 }
96
97 // Build the base string for this DAQLINK
98 std::string base("DAQ_LINK_");
99 base.push_back(GetDAQLinkChar(iDAQLink));
100 base.append(".CONTROL.");
101
102 uint8_t stream = 0;
103 if (enable) {
104 if (DAQMode == RCE)
105 stream = 0xF;
106 else
107 stream = 0xFF;
108 }
109
110 Write(base + "ENABLE_CDA_STREAM", stream);
111 Write(base + "ENABLE", enable);
112}

◆ EnableFEMBCNC()

void WIB::EnableFEMBCNC ( )

Definition at line 506 of file WIB.cpp.

507{
508 // Enable the clock and control stream to the FEMBs
509 Write("FEMB_CNC.CNC_CLOCK_SELECT", 1);
510 Write("FEMB_CNC.CNC_COMMAND_SELECT", 1);
511}

◆ EraseFlash()

void WIB::EraseFlash ( bool print_updates = false)

Definition at line 195 of file WIB_Flash.cpp.

196{
197 if (print_updates) {
198 fprintf(stderr, " Erase flash\n");
199 }
200 WriteWithRetry("FLASH.RUN_COMMAND", 0x7);
201 size_t iTimeout = FLASH_TIMEOUT;
202 while (ReadWithRetry("FLASH.BUSY") && (iTimeout != 0)) {
203 iTimeout--;
204 usleep(100000);
205 }
206 if (iTimeout == 0) {
207 BUException::WIB_FLASH_TIMEOUT e;
208 // throw an exception
209 e.Append("Program (erase): FLASH.BUSY");
210 throw e;
211 // throw an exception
212 }
213}
#define FLASH_TIMEOUT
Definition WIB_Flash.cpp:7

◆ FEMBPower()

void WIB::FEMBPower ( uint8_t iFEMB,
bool turnOn )

Definition at line 462 of file WIB.cpp.

463{
464 std::string reg = "POWER.ENABLE.FEMB";
465 reg.push_back(GetFEMBChar(iFEMB));
466 if (turnOn) {
467 Write(reg, 0x1F);
468 } else {
469 Write(reg, 0x0);
470 }
471}
char GetFEMBChar(uint8_t iFEMB)
Definition WIB.cpp:574

◆ FlashCheckBusy()

void WIB::FlashCheckBusy ( )

Definition at line 370 of file WIB_Flash.cpp.

371{
372 size_t iTimeout = FLASH_TIMEOUT;
373 while (ReadWithRetry("FLASH.BUSY") && (iTimeout != 0)) {
374 iTimeout--;
375 usleep(10000);
376 }
377 if (iTimeout == 0) {
378 BUException::WIB_FLASH_TIMEOUT e;
379 // throw an exception
380 e.Append("Read: FLASH.BUSY");
381 throw e;
382 }
383}

◆ FullStart()

void WIB::FullStart ( )

Definition at line 41 of file WIB.cpp.

42{
43 // Figure out what kind of WIB firmware we are dealing with
44 FEMBCount = Read("SYSTEM.FEMB_COUNT");
45 DAQLinkCount = Read("SYSTEM.DAQ_LINK_COUNT");
46 // Hardcoded lookup for RCE and FELIX
47 if ((FEMBCount == 4) && (DAQLinkCount == 4)) {
48 DAQMode = RCE;
49 } else if ((FEMBCount == 4) && (DAQLinkCount == 2)) {
50 DAQMode = FELIX;
51 }
52 // TODO check FEMBStreamCount and FEMCDACount from registers on the WIB
53 // TODO create those registers
54 Write("POWER.ENABLE.MASTER_BIAS", 1);
55 started = true;
56}

◆ GetDAQ_SI5342AddressPage()

uint8_t WIB::GetDAQ_SI5342AddressPage ( uint16_t address)

Definition at line 40 of file WIB_SI5342.cpp.

41{
42 return uint8_t((address >> 8) & 0xFF);
43}

◆ GetDAQ_SI5342Page()

uint8_t WIB::GetDAQ_SI5342Page ( )

Definition at line 34 of file WIB_SI5342.cpp.

35{
36 return uint8_t(ReadDAQ_SI5342(0x1, 1) & 0xFF);
37}
uint32_t ReadDAQ_SI5342(uint16_t address, uint8_t byte_count=4)

◆ GetDAQLinkChar()

char WIB::GetDAQLinkChar ( uint8_t iDAQLink)

Definition at line 532 of file WIB.cpp.

533{
534 char c = '0';
535 // Check if the link is in range given DAQLinkCount (throws)
536 CheckDAQLinkInRange(iDAQLink);
537 // Convert the numeric daq link number to a char
538 switch (iDAQLink) {
539 case 1:
540 c = '1';
541 break;
542 case 2:
543 c = '2';
544 break;
545 case 3:
546 c = '3';
547 break;
548 case 4:
549 c = '4';
550 break;
551 default:
552 BUException::WIB_INDEX_OUT_OF_RANGE e;
553 e.Append("DAQ Link\n");
554 char estr[] = "0";
555 estr[0] = c;
556 e.Append(estr);
557 throw e;
558 }
559 return c;
560}
bool CheckDAQLinkInRange(uint8_t iDAQLink)
Definition WIB.cpp:521

◆ GetDAQMode()

WIB_DAQ_t WIB::GetDAQMode ( )
inline

Definition at line 219 of file WIB.hh.

219{return DAQMode;}

◆ GetDTS_SI5344AddressPage()

uint8_t WIB::GetDTS_SI5344AddressPage ( uint16_t address)

Definition at line 40 of file WIB_SI5344.cpp.

41{
42 return uint8_t((address >> 8) & 0xFF);
43}

◆ GetDTS_SI5344Page()

uint8_t WIB::GetDTS_SI5344Page ( )

Definition at line 34 of file WIB_SI5344.cpp.

35{
36 return uint8_t(ReadDTS_SI5344(0x1, 1) & 0xFF);
37}
uint32_t ReadDTS_SI5344(uint16_t address, uint8_t byte_count=4)

◆ GetEventBuilderDebugMode()

uint8_t WIB::GetEventBuilderDebugMode ( )

◆ GetFEMBCDChar()

char WIB::GetFEMBCDChar ( uint8_t iCD)

Definition at line 627 of file WIB.cpp.

628{
629 char c = '0';
630 // Check if the link is in range given FEMBCount (throws)
632 // Convert the numeric daq link number to a char
633 switch (iCD) {
634 case 1:
635 c = '1';
636 break;
637 case 2:
638 c = '2';
639 break;
640 default:
641 BUException::WIB_INDEX_OUT_OF_RANGE e;
642 e.Append("FEMB CDA\n");
643 char estr[] = "0";
644 estr[0] = c;
645 e.Append(estr);
646 throw e;
647 }
648 return c;
649}
bool CheckFEMBCDInRange(uint8_t iCD)
Definition WIB.cpp:616

◆ GetFEMBChar()

char WIB::GetFEMBChar ( uint8_t iFEMB)

Definition at line 574 of file WIB.cpp.

575{
576 char c = '0';
577 // Check if the link is in range given FEMBCount (throws)
578 CheckFEMBInRange(iFEMB);
579 // Convert the numeric daq link number to a char
580 switch (iFEMB) {
581 case 1:
582 c = '1';
583 break;
584 case 2:
585 c = '2';
586 break;
587 case 3:
588 c = '3';
589 break;
590 case 4:
591 c = '4';
592 break;
593 default:
594 BUException::WIB_INDEX_OUT_OF_RANGE e;
595 e.Append("FEMB\n");
596 char estr[] = "0";
597 estr[0] = c;
598 e.Append(estr);
599 throw e;
600 }
601 return c;
602}
bool CheckFEMBInRange(uint8_t iFEMB)
Definition WIB.cpp:563

◆ GetFEMBCount()

uint8_t WIB::GetFEMBCount ( )
inline

Definition at line 218 of file WIB.hh.

218{return FEMBCount;}

◆ GetFEMBFakeCOLDATAMode()

uint8_t WIB::GetFEMBFakeCOLDATAMode ( uint8_t iFEMB,
uint8_t iCD )

Definition at line 92 of file WIB_FAKE_CD.cpp.

93{
94 std::string base("FEMB0.DAQ.FAKE_CD.CD0.");
95 base[4] = GetFEMBChar(iFEMB);
96 base[20] = GetFEMBCDChar(iCD);
97
98 return Read(base + "FAKE_MODE");
99}
char GetFEMBCDChar(uint8_t iCD)
Definition WIB.cpp:627

◆ GetFEMBStreamSource()

uint8_t WIB::GetFEMBStreamSource ( uint8_t iFEMB,
uint8_t iStream )

Definition at line 53 of file WIB_FAKE_CD.cpp.

54{
56 std::string base = "FEMB0.DAQ.FAKE_CD.RX_DATA_SOURCE";
57 base[4] = GetFEMBChar(iFEMB);
58 // Read the current settings
59 uint32_t data = Read(base);
60 return (data >> (iStream - 1)) & 0x1;
61}
bool CheckFEMBStreamInRange(uint8_t iStream)
Definition WIB.cpp:605

◆ HuntFEMBPhase()

bool WIB::HuntFEMBPhase ( uint8_t iFEMB,
uint16_t clk_phase_data_start )

Definition at line 1081 of file WIB_FEMB.cpp.

1082{
1083 uint32_t clk_phase_data0 = (clk_phase_data_start >> 8) & 0xFF;
1084 uint32_t clk_phase_data1 = clk_phase_data_start & 0xFF;
1085 uint32_t adc_fifo_sync = 1;
1086
1087 uint32_t a_cs[8] = { 0xc000, 0x3000, 0x0c00, 0x0300, 0x00c0, 0x0030, 0x000c, 0x0003 };
1088
1089 uint32_t a_mark[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
1090
1091 uint32_t a_cnt[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1092
1093 while (adc_fifo_sync) {
1094 sleep(0.001);
1095 adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
1096 sleep(0.001);
1097 adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
1098 sleep(0.001);
1099
1100 std::cout << "FEMB " << int(iFEMB) << " ADC FIFO sync: " << std::bitset<16>(adc_fifo_sync) << std::endl;
1101
1102 if (adc_fifo_sync == 0) {
1103 std::cout << "FEMB " << int(iFEMB) << " Successful SPI config and ADC FIFO synced" << std::endl;
1104 // std::cout << " ADC_ASIC_CLK_PHASE_SELECT: " << std::hex << std::setw(2) << std::setfill('0') <<
1105 // clk_phase_data0 << std::endl; std::cout << " ADC_ASIC_CLK_PHASE_SELECT_2: " << std::hex << std::setw(2) <<
1106 // std::setfill('0') << clk_phase_data1 << std::endl;
1107 std::cout << " phase: " << std::hex << std::setw(2) << std::setfill('0') << clk_phase_data0;
1108 std::cout << std::hex << std::setw(2) << std::setfill('0') << clk_phase_data1 << std::endl;
1109 return true;
1110 } else {
1111 std::cout << "ERROR: sync not zero: " << std::bitset<16>(adc_fifo_sync) << std::endl;
1112 for (int i = 0; i < 8; ++i) {
1113 uint32_t a = adc_fifo_sync & a_cs[i];
1114 uint32_t a_mark_xor = 0;
1115 if (a != 0) {
1116 a_cnt[i]++;
1117 a_mark_xor = a_mark[i] ^ 0xFF;
1118 if (a_cnt[i] == 1 || a_cnt[i] == 3) {
1119 clk_phase_data0 = ((clk_phase_data0 & a_mark[i]) ^ a_mark[i]) + (clk_phase_data0 & a_mark_xor);
1120 } else if (a_cnt[i] == 2 || a_cnt[i] == 4) {
1121 clk_phase_data1 = ((clk_phase_data1 & a_mark[i]) ^ a_mark[i]) + (clk_phase_data1 & a_mark_xor);
1122 } else if (a_cnt[i] >= 5) {
1123 return false;
1124 }
1125 } else {
1126 continue;
1127 }
1128 }
1129 uint16_t clk_phase_to_write = 0;
1130 clk_phase_to_write |= (clk_phase_data0 & 0xFF) << 8;
1131 clk_phase_to_write |= clk_phase_data1;
1132 WriteFEMBPhase(iFEMB, clk_phase_to_write);
1133 }
1134 }
1135 return false;
1136}
void WriteFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data)
Definition WIB_FEMB.cpp:963

◆ InitializeDTS()

void WIB::InitializeDTS ( uint8_t PDTSsource = 0,
uint8_t clockSource = 0,
uint32_t PDTSAlignment_timeout = 0 )

Definition at line 12 of file WIB_DTS.cpp.

13{
14 // Disable the PDTS
15 WriteWithRetry("DTS.PDTS_ENABLE", 0x0);
16
17 // Disable SI5344 outputs (fixed by SI5344 config)
18 WriteWithRetry("DTS.SI5344.ENABLE", 0);
19 // Disable SI5344 (fixed by SI5344 config)
20 WriteWithRetry("DTS.SI5344.RESET", 1);
21
22 // Reset the I2C firmware
23 WriteWithRetry("DTS.CDS.I2C.RESET", 1);
24
25 if (0 == clockSource) {
26 printf("Using PDTS for DUNE timing.\n\nConfiguring clock and data separator\n");
27 // Bring up the CDS
28 float frequency = 0;
29 try {
30 frequency = ConfigureDTSCDS(PDTSsource);
31 } catch (BUException::exBase& e) {
32 frequency = 0;
33 e.Append("Failed to communicate with the DTS CDS via I2C\n");
34 throw;
35 }
36 uint32_t LOL = Read("DTS.CDS.LOL");
37 uint32_t LOS = Read("DTS.CDS.LOS");
38 printf("CDS frequency %f\n", frequency);
39 printf("CDS LOL=%d LOS=%d\n", LOL, LOS);
40
41 // Check for the correct frequency, not in LOS, and not in LOL
42 // if( (2.4136e+08 == frequency) &&
43 if (LOL || LOS) {
44 BUException::WIB_DTS_ERROR e;
45 e.Append("Failed to configure CDS chip\n");
46 throw e;
47 }
48 } else {
49 printf("Using local OSC for DUNE timing\n");
50 }
51 // CDS is up
52
53 printf("\nConfiguring SI5344.\n");
54
55 // Set the SI5344 source
56 WriteWithRetry("DTS.SI5344.INPUT_SELECT", clockSource);
57 // Configure Si5344 with default config file
58 // Do the I2C configuration
59 try {
61 } catch (BUException::exBase& e) {
62 // Disable SI5344 outputs
63 WriteWithRetry("DTS.SI5344.ENABLE", 0);
64 // Disable SI5344
65 WriteWithRetry("DTS.SI5344.RESET", 1);
66
67 e.Append("Error in LoadConfigDTS_SI5344\n");
68 throw;
69 }
70
71 usleep(100000);
72
73 // Check that SI5344 is locked on
74 if (ReadWithRetry("DTS.SI5344.LOS") || ReadWithRetry("DTS.SI5344.LOL")) {
75 // Disable SI5344 outputs
76 WriteWithRetry("DTS.SI5344.ENABLE", 0);
77 // Disable SI5344
78 WriteWithRetry("DTS.SI5344.RESET", 1);
79
80 // Throw
81 BUException::WIB_DTS_ERROR e;
82 e.Append("Failed to configure the SI5344 chip correctly\n");
83 throw e;
84 }
85
86 // Enable the clock for FPGA
87 WriteWithRetry("DTS.SI5344.ENABLE", 1);
88 usleep(100000);
89
90 char const* const PDTSStates[] = { "W_RST", "W_LINK", "W_FREQ", "W_ADJUST", "W_ALIGN", "W_LOCK", "W_PHASE", "W_RDY",
91 "RUN", "0x9", "0xA", "0xB", "ERR_R", "ERR_T", "ERR_P", "0xF" };
92
93 if (0 == clockSource) {
94 printf("\nSetup PDTS.\n");
95 bool timeout_exists = true;
96 if (PDTSAlignment_timeout == 0)
97 timeout_exists = false;
98
99 auto start_time = std::chrono::high_resolution_clock::now();
100 bool timed_out = false;
101
102 while ((timeout_exists == false) || timed_out == false) {
103 // Using PDTS, set that up.
104 usleep(500000);
105 WriteWithRetry("DTS.PDTS_ENABLE", 1);
106 usleep(500000); // needed in new PDTS system to get to a good state before giving up and trying a new phase.
107
108 // See if we've locked
109 uint32_t pdts_state = ReadWithRetry("DTS.PDTS_STATE");
110 printf("PDTS state: %s (0x%01X)\n", PDTSStates[pdts_state & 0xF], pdts_state);
111 if ((pdts_state < 0x6) || (pdts_state > 0x8)) {
112 WriteWithRetry("DTS.PDTS_ENABLE", 0);
113 // dynamic post-amble
114 Write("DTS.SI5344.I2C.RESET", 1);
116 Write("DTS.SI5344.I2C.RESET", 1);
117 WriteDTS_SI5344(0x1C, 0x1, 1);
118 } else if (0x6 == pdts_state) {
119 ers::info(dunedaq::wibmod::WaitingForAlignment(ERS_HERE));
120 } else if (0x7 == pdts_state) {
121 ers::info(dunedaq::wibmod::WaitingForTimestamp(ERS_HERE));
122 } else {
123 return; // 0x8 == pdts_state
124 }
125 auto now = std::chrono::high_resolution_clock::now();
126 auto duration = now - start_time;
127 if (duration.count() > PDTSAlignment_timeout)
128 timed_out = true;
129 }
130 // If we get here something went wrong
131 Write("DTS.SI5344.I2C.RESET", 1);
133 Write("DTS.SI5344.I2C.RESET", 1);
134 WriteDTS_SI5344(0x1C, 0x1, 1);
135
136 BUException::WIB_DTS_ERROR e;
137 e.Append("Failed to configure the PDTS correctly within timeout\n");
138 throw e;
139 }
140}
#define ERS_HERE
void Append(const char *buffer)
void SetDTS_SI5344Page(uint8_t page)
void WriteDTS_SI5344(uint16_t address, uint32_t value, uint8_t byte_count=4)
Definition WIB_SI5344.cpp:9
float ConfigureDTSCDS(uint8_t source=0)
Definition WIB_CDS.cpp:48
Cannot add TPSet with start_time
void info(const Issue &issue)
Definition ers.hpp:121

◆ InitializeWIB()

void WIB::InitializeWIB ( )

Definition at line 144 of file WIB.cpp.

145{
146 // run resets
147 Write("SYSTEM.RESET", 0xFF);
148 // Set clock settings
149 Write("POWER.ENABLE.MASTER_BIAS", 0x1); // Turn on DC/DC converter
150}

◆ LoadConfigDAQ_SI5342()

void WIB::LoadConfigDAQ_SI5342 ( std::string const & fileName)

Definition at line 46 of file WIB_SI5342.cpp.

47{
48 std::ifstream confFile(fileName.c_str());
49 BUException::WIB_BAD_ARGS badFile;
50
51 if (confFile.fail()) {
52 // Failed to topen filename, add it to the exception
53 badFile.Append("Bad SI5342 config file name:");
54 badFile.Append(fileName.c_str());
55
56 // Try the default
57 if (getenv("WIBMOD_SHARE") != NULL) {
58 std::string envBasedFileName = getenv("WIBMOD_SHARE");
59 envBasedFileName += "/config/WIB1/config/";
60 envBasedFileName += SI5342_CONFIG_FILENAME;
61 confFile.open(envBasedFileName.c_str());
62 if (confFile.fail()) {
63 badFile.Append("Bad env based filename:");
64 badFile.Append(envBasedFileName.c_str());
65 }
66 }
67 }
68
69 if (confFile.fail()) {
70 // We are still failing to open our file
71 throw badFile;
72 }
73
74 // Make sure the chip isn't in reset
75 if (Read("DAQ.SI5342.RESET") != 0) {
76 Write("DAQ.SI5342.RESET", 0x0);
77 usleep(50000);
78 }
79
80 // Reset the I2C firmware
81 Write("DAQ.SI5342.I2C.RESET", 1);
82
83 std::vector<std::pair<uint16_t, uint8_t>> writes;
84 while (!confFile.eof()) {
85 std::string line;
86 std::getline(confFile, line);
87 if (line.size() == 0) {
88 continue;
89 } else if (line[0] == '#') {
90 continue;
91 } else if (line[0] == 'A') {
92 continue;
93 } else {
94 if (line.find(',') == std::string::npos) {
95 printf("Skipping bad line: \"%s\"\n", line.c_str());
96 continue;
97 }
98 uint16_t address = strtoul(line.substr(0, line.find(',')).c_str(), NULL, 16);
99 uint8_t data = strtoul(line.substr(line.find(',') + 1).c_str(), NULL, 16);
100 writes.push_back(std::pair<uint16_t, uint8_t>(address, data));
101 }
102 }
103
104 // Disable the SI5342 output
105 Write("DAQ.SI5342.ENABLE", 0x0);
106
107 uint8_t page = GetDAQ_SI5342Page();
108 unsigned int percentDone = 0;
109
110 printf("\n[==================================================]\n");
111 fprintf(stderr, " ");
112 for (size_t iWrite = 0; iWrite < writes.size(); iWrite++) {
113
114 if (page != GetDAQ_SI5342AddressPage(writes[iWrite].first)) {
115 page = GetDAQ_SI5342AddressPage(writes[iWrite].first);
116 SetDAQ_SI5342Page(page);
117 usleep(100000);
118 }
119
120 if (iWrite == 3) {
121 usleep(300000);
122 }
123
124 uint8_t address = writes[iWrite].first & 0xFF;
125 uint32_t data = (writes[iWrite].second) & 0xFF;
126 uint8_t iData = 1;
127
128 for (size_t iTries = 10; iTries > 0; iTries--) {
129 try {
130 WriteDAQ_SI5342(address, data, iData);
131 } catch (BUException::WIB_ERROR& e) {
132 // Reset the I2C firmware
133 Write("DAQ.SI5342.I2C.RESET", 1);
134 if (iTries == 1) {
135 e.Append("\nTried 3 times\n");
136 throw;
137 }
138 }
139 }
140 if ((100 * iWrite) / writes.size() > percentDone) {
141 fprintf(stderr, "#");
142 percentDone += 2;
143 }
144 }
145 printf("\n");
146}
#define SI5342_CONFIG_FILENAME
Definition WIB_SI5342.cpp:6
uint8_t GetDAQ_SI5342Page()
uint8_t GetDAQ_SI5342AddressPage(uint16_t address)
void WriteDAQ_SI5342(uint16_t address, uint32_t value, uint8_t byte_count=4)
Definition WIB_SI5342.cpp:9
void SetDAQ_SI5342Page(uint8_t page)
Invalid address

◆ LoadConfigDTS_SI5344()

void WIB::LoadConfigDTS_SI5344 ( std::string const & fileName)

Definition at line 46 of file WIB_SI5344.cpp.

47{
48 std::ifstream confFile(fileName.c_str());
49 BUException::WIB_BAD_ARGS badFile;
50
51 if (confFile.fail()) {
52 // Failed to topen filename, add it to the exception
53 badFile.Append("Bad SI5344 config file name:");
54 badFile.Append(fileName.c_str());
55
56 // Try the default
57 if (getenv("WIBMOD_SHARE") != NULL) {
58 std::string envBasedFileName = getenv("WIBMOD_SHARE");
59 envBasedFileName += "/config/WIB1/config/";
60 envBasedFileName += SI5344_CONFIG_FILENAME;
61 confFile.open(envBasedFileName.c_str());
62 if (confFile.fail()) {
63 badFile.Append("Bad env based filename:");
64 badFile.Append(envBasedFileName.c_str());
65 }
66 }
67 }
68
69 if (confFile.fail()) {
70 // We are still failing to open our file
71 throw badFile;
72 }
73
74 // Make sure the chip isn't in reset
75 if (Read("DTS.SI5344.RESET") != 0) {
76 Write("DTS.SI5344.RESET", 0x0);
77 usleep(50000);
78 }
79
80 // Reset the I2C firmware
81 Write("DTS.SI5344.I2C.RESET", 1);
82
83 std::vector<std::pair<uint16_t, uint8_t>> writes;
84 while (!confFile.eof()) {
85 std::string line;
86 std::getline(confFile, line);
87 if (line.size() == 0) {
88 continue;
89 } else if (line[0] == '#') {
90 continue;
91 } else if (line[0] == 'A') {
92 continue;
93 } else {
94 if (line.find(',') == std::string::npos) {
95 printf("Skipping bad line: \"%s\"\n", line.c_str());
96 continue;
97 }
98 uint16_t address = strtoul(line.substr(0, line.find(',')).c_str(), NULL, 16);
99 uint8_t data = strtoul(line.substr(line.find(',') + 1).c_str(), NULL, 16);
100 writes.push_back(std::pair<uint16_t, uint8_t>(address, data));
101 }
102 }
103
104 // Disable the SI5344 output
105 Write("DTS.SI5344.ENABLE", 0x0);
106
107 uint8_t page = GetDTS_SI5344Page();
108 unsigned int percentDone = 0;
109
110 printf("\n[==================================================]\n");
111 fprintf(stderr, " ");
112 for (size_t iWrite = 0; iWrite < writes.size(); iWrite++) {
113
114 if (page != GetDTS_SI5344AddressPage(writes[iWrite].first)) {
115 page = GetDTS_SI5344AddressPage(writes[iWrite].first);
116 SetDTS_SI5344Page(page);
117 usleep(100000);
118 }
119
120 if (iWrite == 3) {
121 usleep(300000);
122 }
123
124 uint8_t address = writes[iWrite].first & 0xFF;
125 uint32_t data = (writes[iWrite].second) & 0xFF;
126 uint8_t iData = 1;
127
128 for (size_t iTries = 10; iTries > 0; iTries--) {
129 try {
130 WriteDTS_SI5344(address, data, iData);
131 } catch (BUException::WIB_ERROR& e) {
132 // Reset the I2C firmware
133 Write("DTS.SI5344.I2C.RESET", 1);
134 if (iTries == 1) {
135 e.Append("\nTried 10 times\n");
136 throw;
137 }
138 }
139 }
140 if ((100 * iWrite) / writes.size() > percentDone) {
141 fprintf(stderr, "#");
142 percentDone += 2;
143 }
144 }
145 printf("\n");
146}
#define SI5344_CONFIG_FILENAME
Definition WIB_SI5344.cpp:6
uint8_t GetDTS_SI5344AddressPage(uint16_t address)
uint8_t GetDTS_SI5344Page()

◆ operator=()

WIB & WIB::operator= ( const WIB & )
private

◆ PDTSInRunningState()

void WIB::PDTSInRunningState ( )

Definition at line 151 of file WIB_DTS.cpp.

152{
153 if (Read("DTS.PDTS_STATE") != 0x8) {
154 BUException::WIB_DTS_ERROR e;
155 e.Append("WIB is not in PDTS state RUN(0x8)\n");
156 throw e;
157 }
158}

◆ ProgramFlash()

void WIB::ProgramFlash ( std::string const & fileName,
uint8_t update_percentage = 101 )

Definition at line 216 of file WIB_Flash.cpp.

217{
218 WriteWithRetry("SYSTEM.SLOW_CONTROL_DND", 1);
219
220 bool print_updates = false;
221 if (update_percentage < 100) {
222 print_updates = true;
223 }
224
225 // Load data and validate
226 if (print_updates) {
227 fprintf(stderr, " Reading file: %s\n", fileName.c_str());
228 }
229 // std::vector<uint32_t> flashData = firmwareFromDumpFile(fileName);
230 std::vector<uint32_t> flashData = firmwareFromIntelHexFile(fileName);
231
232 // erase flash
233 EraseFlash(print_updates);
234
235 // Load data into flash.
236 WriteFlash(flashData, update_percentage);
237
238 // Validate flash
239 CheckFlash(flashData, update_percentage);
240 WriteWithRetry("SYSTEM.SLOW_CONTROL_DND", 0);
241}
static std::vector< uint32_t > firmwareFromIntelHexFile(std::string const &iHexFileName)
Definition WIB_Flash.cpp:97
void EraseFlash(bool print_updates=false)
void WriteFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)
void CheckFlash(std::vector< uint32_t > data, uint8_t update_percentage=101)

◆ ReadDAQ_SI5342()

uint32_t WIB::ReadDAQ_SI5342 ( uint16_t address,
uint8_t byte_count = 4 )

Definition at line 14 of file WIB_SI5342.cpp.

15{
16 return ReadI2C("DAQ.SI5342.I2C", address, byte_count);
17}
uint32_t ReadI2C(std::string const &base_address, uint16_t I2C_aaddress, uint8_t byte_count=4)
Definition WIBBase.cpp:44

◆ ReadDAQLinkSpyBuffer()

std::vector< data_8b10b_t > WIB::ReadDAQLinkSpyBuffer ( uint8_t iDAQLink,
uint8_t trigger_mode = 0 )

Definition at line 22 of file WIB_spybuffer.cpp.

23{
24 // TODO read DAQ link count
25 std::string base("DAQ_LINK_");
26 base.push_back(GetDAQLinkChar(iDAQLink));
27 base.append(".SPY_BUFFER.");
28
29 // Check if there is an active capture
30 if (ReadWithRetry(base + "CAPTURING_DATA")) {
31 BUException::WIB_BUSY e;
32 e.Append(base);
33 e.Append(" is busy\n");
34 throw e;
35 }
36 // The spy buffer isn't busy, so let's make sure the fifo is empty
37 while (!ReadWithRetry(base + "EMPTY")) {
38 // Read out a workd from the fifo
39 WriteWithRetry(base + "DATA", 0x0);
40 }
41
42 // write trigger mode
43 WriteWithRetry(base + "TRIGGER_MODE", trigger_mode & 0x1);
44
45 // Start the capture
46 Write(base + "START", 0x1);
47
48 // Wait for capture to finish
49 while (ReadWithRetry(base + "CAPTURING_DATA")) {
50 }
51
52 // Read out the data
53 std::vector<data_8b10b_t> ret;
54
55 while (!ReadWithRetry(base + "EMPTY")) {
56 // read out the k-chars
57 uint32_t k_data = ReadWithRetry(base + "K_DATA");
58 // read out the data
59 uint32_t data = ReadWithRetry(base + "DATA");
60
61 // printf("0x%08X 0x%08X\n",k_data,data);
62
63 for (size_t iWord = 0; iWord < 4; iWord++) {
64 ret.push_back(data_8b10b_t((k_data >> iWord) & 0x1, (data >> (iWord * 8) & 0xFF)));
65 }
66 // mark word as read
67 Write(base + "DATA", 0x0);
68 }
69 return ret;
70}
data_8b10b_t(uint8_t _k, uint8_t _d)
Definition WIB.hh:21

◆ ReadDTS_CDS()

uint32_t WIB::ReadDTS_CDS ( uint16_t address,
uint8_t byte_count = 4 )

Definition at line 42 of file WIB_CDS.cpp.

43{
44 return ReadI2C("DTS.CDS.I2C", address, byte_count);
45}

◆ ReadDTS_SI5344()

uint32_t WIB::ReadDTS_SI5344 ( uint16_t address,
uint8_t byte_count = 4 )

Definition at line 14 of file WIB_SI5344.cpp.

15{
16 return ReadI2C("DTS.SI5344.I2C", address, byte_count);
17}

◆ ReadFlash()

void WIB::ReadFlash ( std::string const & fileName,
uint8_t update_percentage = 101 )

Definition at line 129 of file WIB_Flash.cpp.

130{
131 bool print_updates = false;
132 if (update_percentage < 100) {
133 print_updates = true;
134 }
135 size_t update_delta = (update_percentage * float(16 * 1024 * 1024 / 4)) / 100;
136 size_t next_update = update_delta;
137
138 FILE* outFile = fopen(fileName.c_str(), "w");
139 if (outFile == NULL) {
140 BUException::WIB_BAD_ARGS e;
141 e.Append("Failed to create: ");
142 e.Append(fileName);
143 throw e;
144 }
145
146 if (print_updates) {
147 fprintf(stderr, " Reading flash\n");
148 fprintf(stderr, " [");
149 for (size_t i = 0; i < 100.0 / update_percentage; i++) {
150 fprintf(stderr, "=");
151 }
152 fprintf(stderr, "]\n [");
153 }
154 // program flash in groups of 64 32bit words (256 bytes)
155 uint32_t address = 0;
156
157 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address;
158 size_t blockSize = 64;
159 // set block size
160 WriteWithRetry("FLASH.BYTE_COUNT", 255);
161
162 for (size_t iWord = 0; iWord < 16 * 1024 * 1024 / 4;) {
164
165 // Set adddress
166 WriteWithRetry("FLASH.ADDRESS", address);
167 // Start read
168 WriteWithRetry("FLASH.RUN_COMMAND", 0x5);
169
171
172 // Readout the data
173 for (size_t iWordRead = 0; iWordRead < blockSize; iWordRead++) {
174 fprintf(outFile, "0x%06X 0x%08X\n", uint32_t(iWord), ReadWithRetry(blockRegMapAddress + iWordRead));
175 iWord++;
176 }
177
178 // iWord+= blockSize;
179 address += blockSize * 4;
180
181 if (print_updates && (iWord > next_update)) {
182 // printf(" % 3f%% done\n",float(iWord)/float(flashData.size()));
183 fprintf(stderr, "=");
184 next_update += update_delta;
185 }
186 }
187 if (print_updates) {
188 printf("]\n");
189 printf(" done\n");
190 }
191 fclose(outFile);
192}

◆ ReadLocalFlash() [1/2]

uint32_t WIB::ReadLocalFlash ( uint16_t address)

Definition at line 5 of file WIB_localFlash.cpp.

6{
7 // load the address
8 Write("SYSTEM.FLASH.ADDRESS", address);
9 // start the read transaction
10 Write("SYSTEM.FLASH.RW", 1);
11 Write("SYSTEM.FLASH.RUN", 1);
12
13 // Wait for transaction to finish
14 while (Read("SYSTEM.FLASH.DONE") == 0) {
15 printf("busy\n");
16 // sleep for 1ms
17 usleep(1000);
18 }
19
20 return Read("SYSTEM.FLASH.RD_DATA");
21}

◆ ReadLocalFlash() [2/2]

std::vector< uint32_t > WIB::ReadLocalFlash ( uint16_t address,
size_t n )

Definition at line 24 of file WIB_localFlash.cpp.

25{
26 std::vector<uint32_t> readData;
27 size_t current_address = address;
28 size_t end_address = current_address + n;
29 for (; current_address < end_address; current_address++) {
30 readData.push_back(ReadLocalFlash(current_address));
31 }
32 return readData;
33}
uint32_t ReadLocalFlash(uint16_t address)

◆ ReadOutCDLinkSpyBuffer()

std::vector< data_8b10b_t > WIB::ReadOutCDLinkSpyBuffer ( )

Definition at line 5 of file WIB_spybuffer.cpp.

6{
7 if (Read("FEMB_SPY.FIFO_EMPTY")) {
8 BUException::WIB_ERROR e;
9 e.Append("CD Spy fifo is empty!");
10 throw e;
11 }
12
13 std::vector<data_8b10b_t> data;
14 while (!Read("FEMB_SPY.FIFO_EMPTY")) {
15 uint32_t val = Read("FEMB_SPY.DATA");
16 data.push_back(data_8b10b_t((val >> 8) & 0x1, uint8_t(val & 0xff)));
17 }
18 return data;
19}

◆ ReadQSFP()

uint32_t WIB::ReadQSFP ( uint16_t address,
uint8_t byte_count )

Definition at line 12 of file WIB_QSFP.cpp.

13{
14 return ReadI2C("DAQ.QSFP.I2C", address, byte_count);
15}

◆ ResetSi5342()

void WIB::ResetSi5342 ( )

Definition at line 20 of file WIB_SI5342.cpp.

21{
22 Write("DAQ.SI5342.RESET", 0x1);
23 Write("DAQ.SI5342.RESET", 0x0);
24 usleep(100000);
25}

◆ ResetSi5344()

void WIB::ResetSi5344 ( )

Definition at line 20 of file WIB_SI5344.cpp.

21{
22 Write("DTS.SI5344.RESET", 0x1);
23 Write("DTS.SI5344.RESET", 0x0);
24 usleep(100000);
25}

◆ ResetWIB()

void WIB::ResetWIB ( bool reset_udp = false)

Definition at line 154 of file WIB.cpp.

155{
156
157 if (reset_udp) {
158 // Resetting the UDP will stop the reply packet which will cause an error.
159 try {
160 Write("SYSTEM.RESET.UDP_RESET", 1);
161 } catch (BUException::BAD_REPLY& e) {
162 // do nothing
163 }
164 // Since we don't know this happened since we lack a udp response, do it again.
165 // This could be extended to read register REG
166 usleep(10000);
167 try {
168 Write("SYSTEM.RESET.UDP_RESET", 1);
169 } catch (BUException::BAD_REPLY& e) {
170 // do nothing
171 }
172 usleep(10000);
173 }
174
175 // Reset the control register
176 WriteWithRetry("SYSTEM.RESET.CONTROL_REGISTER_RESET", 1);
177 usleep(1000);
178
179 // If this is felix, make sure we configure the SI5342
180 if (DAQMode == FELIX) {
181 Write("DAQ.SI5342.RESET", 1);
182 usleep(10000);
183 Write("DAQ.SI5342.RESET", 0);
184 usleep(10000);
185 printf("Configuring SI5342 for FELIX\n");
186 LoadConfigDAQ_SI5342("default"); // use the default config file for the SI5342
187 usleep(10000); // Wait for
188 SelectSI5342(1, // Set input to be local oscillator for FELIX clock
189 1); // enable the output of the SI5342
190 }
191
192 // Reset the Eventbuilder PLL
193 Write("SYSTEM.RESET.EB_PLL_RESET", 1);
194 usleep(10000);
195
196 // Reset the DAQ path
197 Write("SYSTEM.RESET.DAQ_PATH_RESET", 1);
198
199 usleep(10000);
200
201 // Set clock settings
202 Write("DTS.CMD_COUNT_RESET", 0xFFFFFFFF);
203 Write("DTS.CMD_COUNT_RESET", 0);
204
205 // Halt signals
206 Write("DTS.CONVERT_CONTROL.HALT", 1);
207 Write("DTS.CONVERT_CONTROL.ENABLE", 0);
208
209 // Make sure DC/DC is on
210 Write("POWER.ENABLE.MASTER_BIAS", 1);
211}
void SelectSI5342(uint64_t input, bool enable)
void LoadConfigDAQ_SI5342(std::string const &fileName)

◆ ResetWIBAndCfgDTS()

void WIB::ResetWIBAndCfgDTS ( uint8_t localClock,
uint8_t PDTS_TGRP,
uint8_t PDTSsource = 0,
uint32_t PDTSAlignment_timeout = 0 )

Definition at line 214 of file WIB.cpp.

215{
216 if (DAQMode == UNKNOWN) {
217 BUException::WIB_DAQMODE_UNKNOWN e;
218 throw e;
219 }
220 if (localClock > 1) {
221 BUException::WIB_BAD_ARGS e;
222 e.Append("localClock > 1; must be 0 (for DTS) or 1 (for local clock)\n");
223 throw e;
224 }
225 if (PDTSsource > 1) {
226 BUException::WIB_BAD_ARGS e;
227 e.Append("PDTSsource > 1; must be 0 (for backplane) or 1 (for front panel)\n");
228 throw e;
229 }
230 if (16 <= PDTS_TGRP) {
231 BUException::WIB_BAD_ARGS e;
232 e.Append("PDTS TGRP > 15; must be 0 to 15\n");
233 throw e;
234 }
235
236 // get this register so we can leave it in the state it started in
237 uint32_t slow_control_dnd = Read("SYSTEM.SLOW_CONTROL_DND");
238
239 ResetWIB();
240 Write("SYSTEM.SLOW_CONTROL_DND", 1);
241 sleep(1);
242
243 for (size_t iFEMB = 1; iFEMB <= 4; iFEMB++) {
244 FEMBPower(iFEMB, 0);
245 }
246
247 // make sure everything DTS is off
248 Write("DTS.CONVERT_CONTROL.HALT", 1);
249 Write("DTS.CONVERT_CONTROL.ENABLE", 0);
250 Write("DTS.CONVERT_CONTROL.START_SYNC", 0);
251 sleep(1);
252
253 if (localClock > 0) {
254 printf("Configuring local clock\n");
255 // Configure the SI5344 to use the local oscillator instead of the PDTS
256 LoadConfigDTS_SI5344("default");
257 sleep(1);
258 SelectSI5344(1, 1);
259 sleep(1);
260 Write("DTS.CONVERT_CONTROL.EN_FAKE", 1);
261 Write("DTS.CONVERT_CONTROL.LOCAL_TIMESTAMP", 1);
262 Write("FEMB_CNC.CNC_CLOCK_SELECT", 1);
263 // Write("FEMB_CNC.ENABLE_DTS_CMDS",1);
264 sleep(1);
265 } else {
266 // Configure the clocking for the PDTS (assumes the PDTS is sending idle or something)
267 printf("Configuring DTS\n");
268 Write("DTS.PDTS_TGRP", PDTS_TGRP);
269 printf("Using timing group 0x%X\n", PDTS_TGRP);
270 InitializeDTS(PDTSsource, 0, PDTSAlignment_timeout);
271 sleep(1);
272 Write("FEMB_CNC.CNC_CLOCK_SELECT", 1);
273 sleep(1);
274 // We are ready for the PDTS, start searching
275 Write("DTS.PDTS_ENABLE", 1);
276 sleep(1);
277 }
278
279 // Now we have the 128MHz clock
280 Write("FEMB1.DAQ.ENABLE", 0);
281 Write("FEMB2.DAQ.ENABLE", 0);
282 Write("FEMB3.DAQ.ENABLE", 0);
283 Write("FEMB4.DAQ.ENABLE", 0);
284
285 Write("SYSTEM.SLOW_CONTROL_DND", slow_control_dnd);
286}

◆ SelectSI5342()

void WIB::SelectSI5342 ( uint64_t input,
bool enable )

Definition at line 149 of file WIB_SI5342.cpp.

150{
151 Write("DAQ.SI5342.INPUT_SELECT", input);
152 Write("DAQ.SI5342.ENABLE", uint64_t(enable));
153}

◆ SelectSI5344()

void WIB::SelectSI5344 ( uint64_t input,
bool enable )

Definition at line 149 of file WIB_SI5344.cpp.

150{
151 Write("DTS.SI5344.INPUT_SELECT", input);
152 Write("DTS.SI5344.ENABLE", uint64_t(enable));
153}

◆ SetContinueIfListOfFEMBClockPhasesDontSync()

void WIB::SetContinueIfListOfFEMBClockPhasesDontSync ( bool enable)

Definition at line 1184 of file WIB_FEMB.cpp.

1185{
1187}
enable(obj, enable, buf_en, tx_en, link)

◆ SetContinueOnFEMBRegReadError()

void WIB::SetContinueOnFEMBRegReadError ( bool enable)

Definition at line 1166 of file WIB_FEMB.cpp.

1167{
1169}

◆ SetContinueOnFEMBSPIError()

void WIB::SetContinueOnFEMBSPIError ( bool enable)

Definition at line 1172 of file WIB_FEMB.cpp.

1173{
1175}

◆ SetContinueOnFEMBSyncError()

void WIB::SetContinueOnFEMBSyncError ( bool enable)

Definition at line 1178 of file WIB_FEMB.cpp.

1179{
1181}

◆ SetDAQ_SI5342Page()

void WIB::SetDAQ_SI5342Page ( uint8_t page)

Definition at line 28 of file WIB_SI5342.cpp.

29{
30 WriteDAQ_SI5342(0x1, page, 1);
31}

◆ SetDTS_SI5344Page()

void WIB::SetDTS_SI5344Page ( uint8_t page)

Definition at line 28 of file WIB_SI5344.cpp.

29{
30 WriteDTS_SI5344(0x1, page, 1);
31}

◆ SetEventBuilderDebugMode()

void WIB::SetEventBuilderDebugMode ( uint8_t mask = 0xF)

◆ SetFEMBFakeCOLDATAMode()

void WIB::SetFEMBFakeCOLDATAMode ( uint8_t iFEMB,
uint8_t iCD,
bool mode = 0 )

Definition at line 81 of file WIB_FAKE_CD.cpp.

82{
83 std::string base("FEMB0.DAQ.FAKE_CD.CD0.");
84 base[4] = GetFEMBChar(iFEMB);
85 base[20] = GetFEMBCDChar(iCD);
86
87 // Set this COLDATA ASIC
88 Write(base + "FAKE_MODE", uint32_t(mode));
89}

◆ SetFEMBStreamSource()

void WIB::SetFEMBStreamSource ( uint8_t iFEMB,
uint8_t iStream,
bool real = true )

Definition at line 63 of file WIB_FAKE_CD.cpp.

64{
66 std::string base = "FEMB0.DAQ.FAKE_CD.RX_DATA_SOURCE";
67 base[4] = GetFEMBChar(iFEMB);
68 // Read the current settings
69 uint32_t data = Read(base);
70 // update the mask
71 iStream--; // iStream is 1-4, but we want bits 0 to 3
72 if (real) {
73 data &= ~(0x1 << iStream);
74 } else {
75 data |= 0x1 << iStream;
76 }
77 Write(base, data);
78}

◆ SetupASICPulserBits()

uint16_t WIB::SetupASICPulserBits ( uint8_t iFEMB)

Definition at line 837 of file WIB_FEMB.cpp.

838{
839
840 const uint32_t REG_SPI_BASE_WRITE = 0x200; // 512
841 const uint32_t REG_SPI_BASE_READ = 0x250; // 592
842 uint16_t adc_sync_status = 0xFFFF;
843
844 size_t nASICs = 8;
845 unsigned nTries = 3;
846 for (unsigned iSPIWrite = 0; iSPIWrite < nTries; iSPIWrite++) {
847 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 0); // Turn off STREAM_EN and ADC_DATA_EN
848 sleep(0.1);
849
850 std::cout << "ASIC SPI Write Registers..." << std::endl;
851
852 uint8_t value = 0x2;
853 uint8_t mask = 0x3;
854 uint8_t pos = 24;
855 std::vector<uint32_t> vals(nASICs);
856 for (size_t iASIC = 0; iASIC < nASICs; iASIC++) {
857 uint32_t address = (REG_SPI_BASE_WRITE + 9 * iASIC + 8);
858 std::cout << "Writing address " << std::hex << std::setfill('0') << std::setw(8) << address << std::endl;
859 // WriteFEMBBits(iFEMB, address, pos, mask, value);
860
861 // Bit-wise calculation of register val
862 uint32_t shiftVal = value & mask;
863 uint32_t regMask = (mask << pos);
864 uint32_t initVal = ReadFEMB(iFEMB, address);
865 uint32_t newVal = ((initVal & ~(regMask)) | (shiftVal << pos));
866 vals[iASIC] = newVal;
867 WriteFEMB(iFEMB, address, newVal);
868
869 sleep(0.01);
870 }
871
872 // run the SPI programming
873 sleep(0.1);
874 WriteFEMB(iFEMB, "WRITE_ASIC_SPI", 1);
875 sleep(0.1);
876
877 if (iSPIWrite == nTries - 1) {
878 // Now check readback
879 bool spi_mismatch = false;
880 for (unsigned iSPIRead = 0; iSPIRead < 2; iSPIRead++) {
881 std::cout << "ASIC SPI Readback..." << std::endl;
882 std::vector<uint32_t> regsReadback(nASICs);
883 for (size_t iASIC = 0; iASIC < nASICs; iASIC++) {
884 uint32_t regReadback = ReadFEMB(iFEMB, (REG_SPI_BASE_READ + 9 * iASIC + 8));
885 regsReadback[iASIC] = regReadback;
886 sleep(0.01);
887 }
888
889 std::cout << "ASIC SPI register number, write val, read val:" << std::endl;
890 spi_mismatch = false;
891 for (size_t iASIC = 0; iASIC < nASICs; iASIC++) {
892 std::cout << std::dec << std::setfill(' ') << std::setw(3) << iASIC << " " << std::hex << std::setfill('0')
893 << std::setw(8) << vals[iASIC] << " " << std::hex << std::setfill('0') << std::setw(8)
894 << regsReadback[iASIC] << std::endl;
895 if (vals[iASIC] != regsReadback[iASIC]) {
896 spi_mismatch = true;
897 size_t asicFailNum = 0;
898 if (iASIC > 0)
899 asicFailNum = (iASIC - 1);
900 std::cout << "FE-ADC ASIC " << asicFailNum << " SPI faled" << std::endl;
901 } // if regs don't match
902 } // for iReg
903 if (!spi_mismatch)
904 break;
905 } // for iSPIRead
906 if (spi_mismatch) {
907 BUException::WIB_ERROR e;
908 e.Append("SPI programming failure");
909 throw e;
910 } // if spi_mismatch
911 } // if iSPIWrite == 1
912 sleep(0.1);
913
914 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 9); // STREAM_EN and ADC_DATA_EN
915 sleep(0.05);
916 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 9); // STREAM_EN and ADC_DATA_EN
917 sleep(0.1);
918
919 adc_sync_status = (uint16_t)ReadFEMB(iFEMB, "ADC_ASIC_SYNC_STATUS");
920
921 // The real sync check can happen here in Shanshan's code
922
923 } // for iSPIWrite
924
925 return adc_sync_status;
926}

◆ SetupFEMBASICs() [1/2]

uint16_t WIB::SetupFEMBASICs ( uint8_t iFEMB,
std::vector< uint32_t > registerList )

Setup FEMB ASICs.

Sets up iFEMB (index from 1) ASICs

registerList is a list of 71 32bit registers to program the FE and ADC ASICs

returns adc sync status 16 bits, one for each serial link between ADC and FPGA. There are 2 per ADC

Definition at line 551 of file WIB_FEMB.cpp.

552{
553
554 const size_t REG_SPI_BASE = 512;
555 const size_t NREGS = 71;
556
557 if (registerList.size() != NREGS) {
558 BUException::FEMB_FIRMWARE_VERSION_MISMATCH e;
559 std::stringstream expstr;
560 expstr << "SetupFEMBASICs expects : " << NREGS << " argument is: " << registerList.size();
561 e.Append(expstr.str().c_str());
562 throw e;
563 }
564
565 // turn off HS data before register writes
566 WriteFEMB(iFEMB, "STREAM_EN", 0);
567 sleep(2);
568
569 for (size_t iReg = 0; iReg < NREGS; iReg++) {
570 WriteFEMB(iFEMB, REG_SPI_BASE + iReg, registerList[iReg]);
571 }
572
574 // run the SPI programming
576
577 WriteFEMB(iFEMB, "ADC_ASIC_RESET", 1);
578 sleep(0.01);
579 WriteFEMB(iFEMB, "FE_ASIC_RESET", 1);
580 sleep(0.01);
581 WriteFEMB(iFEMB, "WRITE_ADC_ASIC_SPI", 1);
582 sleep(0.01);
583 WriteFEMB(iFEMB, "WRITE_ADC_ASIC_SPI", 1);
584 sleep(0.01);
585 WriteFEMB(iFEMB, "WRITE_FE_ASIC_SPI", 1);
586 sleep(0.01);
587 WriteFEMB(iFEMB, "WRITE_FE_ASIC_SPI", 1);
588 sleep(0.01);
589
590 uint16_t adc_sync_status = (uint16_t)ReadFEMB(iFEMB, "ADC_ASIC_SYNC_STATUS");
593
594 // turn HS link back on
595 sleep(2);
596 WriteFEMB(iFEMB, "STREAM_EN", 1);
597
598 return adc_sync_status;
599}

◆ SetupFEMBASICs() [2/2]

uint16_t WIB::SetupFEMBASICs ( uint8_t iFEMB,
uint8_t gain,
uint8_t shape,
uint8_t highBaseline,
bool highLeakage,
bool leakagex10,
bool acCoupling,
bool buffer,
bool useExtClock,
uint8_t internalDACControl,
uint8_t internalDACValue )

Setup FEMB ASICs.

Sets up iFEMB (index from 1) ASICs

gain: 0,1,2,3 for 4.7, 7.8, 14, 25 mV/fC, respectively shaping time: 0,1,2,3 for 0.5, 1, 2, 3 us, respectively highBaseline is 900mV for 1, 200mV for 0, and appropriately for each plane for 2 highLeakage is 500pA for true, 100pA for false leakagex10 multiplies leakage x10 if true acCoupling: FE is AC coupled to ADC if true, DC if false buffer: FE to ADC buffer on if true, off and bypassed if false useExtClock: ADC uses external (FPGA) clock if true, internal if false internalDACControl: 0 for disabled, 1 for internal FE ASIC pulser, 2 for external FPGA pulser internalDACValue: 6 bit value for amplitude to use with internal pulser

returns adc sync status 16 bits, one for each serial link between ADC and FPGA. There are 2 per ADC

Definition at line 619 of file WIB_FEMB.cpp.

630{
631
632 (void)buffer; // to make compiler not complain about unused arguments
633
634 if (gain > 3) {
635 BUException::WIB_BAD_ARGS e;
636 std::stringstream expstr;
637 expstr << "gain should be between 0 and 3, but is: " << int(gain);
638 e.Append(expstr.str().c_str());
639 throw e;
640 }
641 if (shape > 3) {
642 BUException::WIB_BAD_ARGS e;
643 std::stringstream expstr;
644 expstr << "shape should be between 0 and 3, but is: " << int(shape);
645 e.Append(expstr.str().c_str());
646 throw e;
647 }
648
649 const size_t REG_SPI_BASE_WRITE = 0x200; // 512
650 const size_t REG_SPI_BASE_READ = 0x250; // 592
651 // 0x48 registers total, 72 in hex
652
653 bool bypassOutputBuffer = true; // if false might blow up protoDUNE
654 bool useOutputMonitor = false; // if true might blow up protoDUNE
655 bool useCh16HighPassFilter = false;
656 bool monitorBandgapNotTemp = false;
657 bool monitorTempBandgapNotSignal = false;
658 bool useTestCapacitance = (bool)internalDACControl;
659
660 // Flip bits of gain
661 if (gain == 0x1)
662 gain = 0x2;
663 else if (gain == 0x2)
664 gain = 0x1;
665
666 // Shape
667 if (shape == 0x0)
668 shape = 0x2; // 0.5 us
669 else if (shape == 0x1)
670 shape = 0x0; // 1 us
671 else if (shape == 0x2)
672 shape = 0x3; // 2 us
673 else if (shape == 0x3)
674 shape = 0x1; // 3 us
675
676 FE_ASIC_reg_mapping fe_map;
677 if (highBaseline > 1) {
678 // Set them all to high baseline
679 fe_map.set_board(useTestCapacitance,
680 0,
681 gain,
682 shape,
683 useOutputMonitor,
684 !bypassOutputBuffer,
685 !highLeakage,
686 monitorBandgapNotTemp,
687 monitorTempBandgapNotSignal,
688 useCh16HighPassFilter,
689 leakagex10,
690 acCoupling,
691 internalDACControl,
692 internalDACValue);
693 // Now just set collection channels to low baseline
694 fe_map.set_collection_baseline(1);
695 } else {
696 fe_map.set_board(useTestCapacitance,
697 ~highBaseline,
698 gain,
699 shape,
700 useOutputMonitor,
701 !bypassOutputBuffer,
702 !highLeakage,
703 monitorBandgapNotTemp,
704 monitorTempBandgapNotSignal,
705 useCh16HighPassFilter,
706 leakagex10,
707 acCoupling,
708 internalDACControl,
709 internalDACValue);
710 }
711 ADC_ASIC_reg_mapping adc_map;
712 uint8_t offsetCurrentValue = 0;
713 bool pcsr = 0;
714 bool pdsr = 0;
715 bool adcSleep = 0;
716 bool useADCTestInput = 0;
717 bool f4 = 0;
718 bool f5 = 0;
719 bool lsbCurrentStearingPartialNotFull = 0;
720 bool clk0 = 0;
721 if (useExtClock)
722 clk0 = 1;
723 bool clk1 = 0;
724 bool freq = 0;
725 bool enableOffsetCurrent = 0;
726 bool f0 = 0;
727 bool f1 = 0;
728 bool f2 = 0;
729 bool f3 = 0;
730 adc_map.set_board(offsetCurrentValue,
731 pcsr,
732 pdsr,
733 adcSleep,
734 useADCTestInput,
735 f4,
736 f5,
737 lsbCurrentStearingPartialNotFull,
738 0,
739 0,
740 0,
741 0,
742 0,
743 clk0,
744 clk1,
745 freq,
746 enableOffsetCurrent,
747 f0,
748 f1,
749 f2,
750 f3);
751 ASIC_reg_mapping map;
752 map.set_board(fe_map, adc_map);
753 map.get_regs();
754 const std::vector<uint32_t> regs = map.get_regs();
755 const size_t nRegs = regs.size();
756
757 uint16_t adc_sync_status = 0xFFFF;
758
759 for (unsigned iSPIWrite = 0; iSPIWrite < 2; iSPIWrite++) {
760 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 0); // Turn off STREAM_EN and ADC_DATA_EN
761 sleep(0.1);
762
763 std::cout << "ASIC SPI Write Registers..." << std::endl;
764 for (size_t iReg = 0; iReg < nRegs; iReg++) {
765 WriteFEMB(iFEMB, REG_SPI_BASE_WRITE + iReg, regs[iReg]);
766 sleep(0.01);
767 }
768
769 // run the SPI programming
770 sleep(0.1);
771 WriteFEMB(iFEMB, "WRITE_ASIC_SPI", 1);
772 sleep(0.1);
773
774 if (iSPIWrite == 1) {
775 // Now check readback
776 bool spi_mismatch = false;
777 for (unsigned iSPIRead = 0; iSPIRead < 2; iSPIRead++) {
778 std::cout << "ASIC SPI Readback..." << std::endl;
779 std::vector<uint32_t> regsReadback(nRegs);
780 for (size_t iReg = 0; iReg < nRegs; iReg++) {
781 uint32_t regReadback = ReadFEMB(iFEMB, REG_SPI_BASE_READ + iReg);
782 regsReadback[iReg] = regReadback;
783 sleep(0.01);
784 }
785
786 bool verbose = false;
787 if (verbose)
788 std::cout << "ASIC SPI register number, write val, read val:" << std::endl;
789 spi_mismatch = false;
790 for (size_t iReg = 0; iReg < nRegs; iReg++) {
791 if (verbose) {
792 std::cout << std::dec << std::setfill(' ') << std::setw(3) << iReg << " " << std::hex << std::setfill('0')
793 << std::setw(8) << regs[iReg] << " " << std::hex << std::setfill('0') << std::setw(8)
794 << regsReadback[iReg] << std::endl;
795 } // if verbose
796 if (regs[iReg] != regsReadback[iReg]) {
797 spi_mismatch = true;
798 size_t asicFailNum = 0;
799 if (iReg > 0)
800 asicFailNum = (iReg - 1) / 9;
801 std::cout << "FE-ADC ASIC " << asicFailNum << " SPI faled" << std::endl;
802 } // if regs don't match
803 } // for iReg
804 if (!spi_mismatch)
805 break;
806 } // for iSPIRead
807 if (spi_mismatch) {
809 std::cout << "FEMB ASIC SPI readback mismatch--problems communicating with ASICs for FEMB: " << int(iFEMB)
810 << std::endl;
811 } else {
812 BUException::FEMB_SPI_READBACK_MISMATCH e;
813 std::stringstream expstr;
814 expstr << " for FEMB: " << int(iFEMB);
815 e.Append(expstr.str().c_str());
816 throw e;
817 }
818 } // if spi_mismatch
819 } // if iSPIWrite == 1
820 sleep(0.1);
821
822 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 9); // STREAM_EN and ADC_DATA_EN
823 sleep(0.05);
824 WriteFEMB(iFEMB, "STREAM_AND_ADC_DATA_EN", 9); // STREAM_EN and ADC_DATA_EN
825 sleep(0.1);
826
827 adc_sync_status = (uint16_t)ReadFEMB(iFEMB, "ADC_ASIC_SYNC_STATUS");
828
829 // The real sync check can happen here in Shanshan's code
830
831 } // for iSPIWrite
832
833 return adc_sync_status;
834}
void set_board(uint8_t d=0, uint8_t pcsr=0, uint8_t pdsr=0, uint8_t slp=0, uint8_t tstin=0, uint8_t f4=0, uint8_t f5=0, uint8_t slsb=0, uint8_t res4=0, uint8_t res3=0, uint8_t res2=0, uint8_t res1=0, uint8_t res0=0, uint8_t clk0=0, uint8_t clk1=0, uint8_t frqc=0, uint8_t engr=0, uint8_t f0=0, uint8_t f1=0, uint8_t f2=0, uint8_t f3=0)
std::vector< uint32_t > get_regs() const
void set_board(const FE_ASIC_reg_mapping &fe_map, const ADC_ASIC_reg_mapping &adc_map)
void set_collection_baseline(uint8_t snc)
void set_board(uint8_t sts=0, uint8_t snc=0, uint8_t sg=0, uint8_t st=0, uint8_t smn=0, uint8_t sdf=0, uint8_t slk0=0, uint8_t stb1=0, uint8_t stb=0, uint8_t s16=0, uint8_t slk1=0, uint8_t sdc=0, uint8_t swdac=0, uint8_t dac=0)
Unknown serialization type<< t,((char) t)) template< typename T > inline std::string datatype_to_string() { return "Unknown";} namespace serialization { template< typename T > struct is_serializable :std::false_type {};enum SerializationType { kMsgPack };inline SerializationType from_string(const std::string s) { if(s=="msgpack") return kMsgPack;throw UnknownSerializationTypeString(ERS_HERE, s);} constexpr uint8_t serialization_type_byte(SerializationType stype) { switch(stype) { case kMsgPack:return 'M';default:throw UnknownSerializationTypeEnum(ERS_HERE);} } constexpr SerializationType DEFAULT_SERIALIZATION_TYPE=kMsgPack;template< class T > std::vector< uint8_t > serialize(const T &obj, SerializationType stype=DEFAULT_SERIALIZATION_TYPE) { switch(stype) { case kMsgPack:{ msgpack::sbuffer buf;msgpack::pack(buf, obj);std::vector< uint8_t > ret(buf.size()+1);ret[0]=serialization_type_byte(stype);std::copy(buf.data(), buf.data()+buf.size(), ret.begin()+1);return ret;} default:throw UnknownSerializationTypeEnum(ERS_HERE);} } template< class T, typename CharType=unsigned char > T deserialize(const std::vector< CharType > &v) { switch(v[0]) { case serialization_type_byte(kMsgPack):{ try { msgpack::object_handle oh=msgpack::unpack(const_cast< char * >(reinterpret_cast< const char * >(v.data()+1)), v.size() - 1,[](msgpack::type::object_type, std::size_t, void *) -> bool

◆ SetupFEMBExtClock()

void WIB::SetupFEMBExtClock ( uint8_t iFEMB)

Setup FEMB External Clock.

Sets up iFEMB (index from 1) external clock parameters

Definition at line 372 of file WIB_FEMB.cpp.

373{
374
375 // EXTERNAL CLOCK VARIABLES
376 uint32_t clk_period = 5; // ns
377 uint32_t clk_dis = 0; // 0 --> enable, 1 disable
378 uint32_t d14_rst_oft = 0 / clk_period;
379 uint32_t d14_rst_wdt = (45 / clk_period);
380 uint32_t d14_rst_inv = 1;
381 uint32_t d14_read_oft = 480 / clk_period;
382 uint32_t d14_read_wdt = 20 / clk_period;
383 uint32_t d14_read_inv = 1;
384 uint32_t d14_idxm_oft = 230 / clk_period;
385 uint32_t d14_idxm_wdt = 270 / clk_period;
386 uint32_t d14_idxm_inv = 0;
387 uint32_t d14_idxl_oft = 480 / clk_period;
388 uint32_t d14_idxl_wdt = 20 / clk_period;
389 uint32_t d14_idxl_inv = 0;
390 uint32_t d14_idl0_oft = 50 / clk_period;
391 uint32_t d14_idl0_wdt = (190 / clk_period) - 1;
392 uint32_t d14_idl1_oft = 480 / clk_period;
393 uint32_t d14_idl1_wdt = 20 / clk_period;
394 uint32_t d14_idl_inv = 0;
395
396 uint32_t d58_rst_oft = 0 / clk_period;
397 uint32_t d58_rst_wdt = (45 / clk_period);
398 uint32_t d58_rst_inv = 1;
399 uint32_t d58_read_oft = 480 / clk_period;
400 uint32_t d58_read_wdt = 20 / clk_period;
401 uint32_t d58_read_inv = 1;
402 uint32_t d58_idxm_oft = 230 / clk_period;
403 uint32_t d58_idxm_wdt = 270 / clk_period;
404 uint32_t d58_idxm_inv = 0;
405 uint32_t d58_idxl_oft = 480 / clk_period;
406 uint32_t d58_idxl_wdt = 20 / clk_period;
407 uint32_t d58_idxl_inv = 0;
408 uint32_t d58_idl0_oft = 50 / clk_period;
409 uint32_t d58_idl0_wdt = (190 / clk_period) - 1;
410 uint32_t d58_idl1_oft = 480 / clk_period;
411 uint32_t d58_idl1_wdt = 20 / clk_period;
412 uint32_t d58_idl_inv = 0;
413
414 // external clock phase -- Version 320
415 /*uint32_t d14_read_step = 7;
416 uint32_t d14_read_ud = 0;
417 uint32_t d14_idxm_step = 3;
418 uint32_t d14_idxm_ud = 0;
419 uint32_t d14_idxl_step = 1;
420 uint32_t d14_idxl_ud = 1;
421 uint32_t d14_idl0_step = 5;
422 uint32_t d14_idl0_ud = 0;
423 uint32_t d14_idl1_step = 2;
424 uint32_t d14_idl1_ud = 0;
425 uint32_t d14_phase_en = 1;
426
427 uint32_t d58_read_step = 1;
428 uint32_t d58_read_ud = 1;
429 uint32_t d58_idxm_step = 0;
430 uint32_t d58_idxm_ud = 0;
431 uint32_t d58_idxl_step = 5;
432 uint32_t d58_idxl_ud = 1;
433 uint32_t d58_idl0_step = 6;
434 uint32_t d58_idl0_ud = 0;
435 uint32_t d58_idl1_step = 5;
436 uint32_t d58_idl1_ud = 0;
437 uint32_t d58_phase_en = 1;*/
438 // Version 323
439 uint32_t d14_read_step = 11;
440 uint32_t d14_read_ud = 0;
441 uint32_t d14_idxm_step = 9;
442 uint32_t d14_idxm_ud = 0;
443 uint32_t d14_idxl_step = 7;
444 uint32_t d14_idxl_ud = 0;
445 uint32_t d14_idl0_step = 12;
446 uint32_t d14_idl0_ud = 0;
447 uint32_t d14_idl1_step = 10;
448 uint32_t d14_idl1_ud = 0;
449 uint32_t d14_phase_en = 1;
450
451 uint32_t d58_read_step = 0;
452 uint32_t d58_read_ud = 0;
453 uint32_t d58_idxm_step = 5;
454 uint32_t d58_idxm_ud = 0;
455 uint32_t d58_idxl_step = 4;
456 uint32_t d58_idxl_ud = 1;
457 uint32_t d58_idl0_step = 3;
458 uint32_t d58_idl0_ud = 0;
459 uint32_t d58_idl1_step = 4;
460 uint32_t d58_idl1_ud = 0;
461 uint32_t d58_phase_en = 1;
462
463 // END EXTERNAL CLOCK VARIABLES
464
465 // config timing
466 uint32_t d14_inv =
467 (d14_rst_inv << 0) + (d14_read_inv << 1) + (d14_idxm_inv << 2) + (d14_idxl_inv << 3) + (d14_idl_inv << 4);
468 uint32_t d58_inv =
469 (d58_rst_inv << 0) + (d58_read_inv << 1) + (d58_idxm_inv << 2) + (d58_idxl_inv << 3) + (d58_idl_inv << 4);
470 uint32_t d_inv = d58_inv + (d14_inv << 5);
471
472 uint32_t addr_data;
473
474 addr_data = clk_dis + (d_inv << 16);
475 WriteFEMB(iFEMB, 21, addr_data);
476
477 addr_data = d58_rst_oft + (d14_rst_oft << 16);
478 WriteFEMB(iFEMB, 22, addr_data);
479
480 addr_data = d58_rst_wdt + (d14_rst_wdt << 16);
481 WriteFEMB(iFEMB, 23, addr_data);
482
483 addr_data = d58_read_oft + (d14_read_oft << 16);
484 WriteFEMB(iFEMB, 24, addr_data);
485
486 addr_data = d58_read_wdt + (d14_read_wdt << 16);
487 WriteFEMB(iFEMB, 25, addr_data);
488
489 addr_data = d58_idxm_oft + (d14_idxm_oft << 16);
490 WriteFEMB(iFEMB, 26, addr_data);
491
492 addr_data = d58_idxm_wdt + (d14_idxm_wdt << 16);
493 WriteFEMB(iFEMB, 27, addr_data);
494
495 addr_data = d58_idxl_oft + (d14_idxl_oft << 16);
496 WriteFEMB(iFEMB, 28, addr_data);
497
498 addr_data = d58_idxl_wdt + (d14_idxl_wdt << 16);
499 WriteFEMB(iFEMB, 29, addr_data);
500
501 addr_data = d58_idl0_oft + (d14_idl0_oft << 16);
502 WriteFEMB(iFEMB, 30, addr_data);
503
504 addr_data = d58_idl0_wdt + (d14_idl0_wdt << 16);
505 WriteFEMB(iFEMB, 31, addr_data);
506
507 addr_data = d58_idl1_oft + (d14_idl1_oft << 16);
508 WriteFEMB(iFEMB, 32, addr_data);
509
510 addr_data = d58_idl1_wdt + (d14_idl1_wdt << 16);
511 WriteFEMB(iFEMB, 33, addr_data);
512
513 // config phase
514 for (size_t i = 0; i < 4; i++) {
515 addr_data = d14_read_step + (d14_idxm_step << 16);
516 WriteFEMB(iFEMB, 35, addr_data);
517
518 addr_data = d14_idxl_step + (d14_idl0_step << 16);
519 WriteFEMB(iFEMB, 36, addr_data);
520
521 d14_phase_en = d14_phase_en ^ 1;
522 uint32_t d14_ud = d14_read_ud + (d14_idxm_ud << 1) + (d14_idxl_ud << 2) + (d14_idl0_ud << 3) + (d14_idl1_ud << 4) +
523 (d14_phase_en << 15);
524 addr_data = d14_idl1_step + (d14_ud << 16);
525 WriteFEMB(iFEMB, 37, addr_data);
526
527 addr_data = d58_read_step + (d58_idxm_step << 16);
528 WriteFEMB(iFEMB, 38, addr_data);
529
530 addr_data = d58_idxl_step + (d58_idl0_step << 16);
531 WriteFEMB(iFEMB, 39, addr_data);
532
533 d58_phase_en = d58_phase_en ^ 1;
534 uint32_t d58_ud = d58_read_ud + (d58_idxm_ud << 1) + (d58_idxl_ud << 2) + (d58_idl0_ud << 3) + (d58_idl1_ud << 4) +
535 (d58_phase_en << 15);
536 addr_data = d58_idl1_step + (d58_ud << 16);
537 WriteFEMB(iFEMB, 40, addr_data);
538 }
539 sleep(0.05);
540}

◆ SetupFPGAPulser()

void WIB::SetupFPGAPulser ( uint8_t iFEMB,
uint8_t dac_val )

Definition at line 929 of file WIB_FEMB.cpp.

930{
931 std::cout << "FEMB " << int(iFEMB) << " Configuring FPGA pulser with DAC value: " << int(dac_val) << std::endl;
932
933 WriteFEMB(iFEMB, "ASIC_TP_EN", 0);
934 WriteFEMB(iFEMB, "FPGA_TP_EN", 1);
935
936 WriteFEMB(iFEMB, "DAC_SELECT", 1);
937 WriteFEMB(iFEMB, "TEST_PULSE_AMPLITUDE", dac_val);
938 WriteFEMB(iFEMB, "TEST_PULSE_DELAY", 219);
939 WriteFEMB(iFEMB, "TEST_PULSE_PERIOD", 497);
940
941 WriteFEMB(iFEMB, "INT_TP_EN", 0);
942 WriteFEMB(iFEMB, "EXT_TP_EN", 1);
943}

◆ SetupInternalPulser()

void WIB::SetupInternalPulser ( uint8_t iFEMB)

Definition at line 946 of file WIB_FEMB.cpp.

947{
948 std::cout << "FEMB " << int(iFEMB) << " Configuring internal pulser" << std::endl;
949
950 WriteFEMB(iFEMB, "DAC_SELECT", 0);
951 WriteFEMB(iFEMB, "TEST_PULSE_AMPLITUDE", 0);
952 WriteFEMB(iFEMB, "TEST_PULSE_DELAY", 219);
953 WriteFEMB(iFEMB, "TEST_PULSE_PERIOD", 497);
954
955 WriteFEMB(iFEMB, "INT_TP_EN", 0);
956 WriteFEMB(iFEMB, "EXT_TP_EN", 1);
957
958 WriteFEMB(iFEMB, "FPGA_TP_EN", 0);
959 WriteFEMB(iFEMB, "ASIC_TP_EN", 1);
960}

◆ SourceFEMB()

void WIB::SourceFEMB ( uint64_t iDAQLink,
uint64_t real )

Definition at line 652 of file WIB.cpp.

653{
654 if (iFEMB < 1) {
655 printf("FEMB index out of range < 1\n");
656 return;
657 }
658
659 /* if(DAQMode == RCE && iFEMB > 4){
660 printf("FEMB index out of range > 4 (RCE) \n");
661 return;}
662 if(DAQMode == FELIX && iFEMB > 2){
663 printf("FEMB index out of range > 2 (FELIX) \n");
664 return;}
665 */
666 std::string address("FEMB");
667 address.push_back(GetFEMBChar(iFEMB));
668 address.append(".DAQ.FAKE_CD.FAKE_SOURCE");
669 Write(address, real);
670}

◆ StartEventBuilder()

void WIB::StartEventBuilder ( uint8_t mask = 0xF)

◆ StartStreamToDAQ()

void WIB::StartStreamToDAQ ( bool l1 = true,
bool l2 = true,
bool l3 = false,
bool l4 = false )

Definition at line 413 of file WIB.cpp.

414{
415 if (DAQMode == UNKNOWN) {
416 BUException::WIB_DAQMODE_UNKNOWN e;
417 throw e;
418 }
419 WriteWithRetry("DTS.CONVERT_CONTROL.HALT", 1);
420 WriteWithRetry("DTS.CONVERT_CONTROL.ENABLE", 0);
421
422 // get this register so we can leave it in the state it started in
423 uint32_t slow_control_dnd = Read("SYSTEM.SLOW_CONTROL_DND");
424 Write("SYSTEM.SLOW_CONTROL_DND", 1);
425
426 sleep(1);
427 Write("FEMB_CNC.FEMB_STOP", 1);
428 sleep(1);
429 Write("SYSTEM.RESET.DAQ_PATH_RESET", 1);
430 sleep(1);
431
432 // Enable DAQ links
433 if (DAQMode == FELIX) {
434 if (link1_enabled)
435 EnableDAQLink_Lite(1, 1);
436 if (link2_enabled)
437 EnableDAQLink_Lite(2, 1);
438 } else {
439 if (link3_enabled)
440 EnableDAQLink_Lite(3, 1);
441 if (link4_enabled)
442 EnableDAQLink_Lite(4, 1);
443 }
444
445 // Enable the FEMB to align to idle and wait for convert
446 Write("FEMB1.DAQ.ENABLE", 0xF);
447 Write("FEMB2.DAQ.ENABLE", 0xF);
448 Write("FEMB3.DAQ.ENABLE", 0xF);
449 Write("FEMB4.DAQ.ENABLE", 0xF);
450
451 // Start sending characters from the FEMB
452 Write("FEMB_CNC.ENABLE_DTS_CMDS", 1);
453 StartSyncDTS();
454 // Write("FEMB_CNC.TIMESTAMP_RESET",1);
455 // Write("FEMB_CNC.FEMB_START",1);
456 // Write("SYSTEM.RESET.FEMB_COUNTER_RESET",1);
457
458 Write("SYSTEM.SLOW_CONTROL_DND", slow_control_dnd);
459}
void StartSyncDTS()
Definition WIB_DTS.cpp:143

◆ StartSyncDTS()

void WIB::StartSyncDTS ( )

Definition at line 143 of file WIB_DTS.cpp.

144{
145 WriteWithRetry("DTS.CONVERT_CONTROL.HALT", 0);
146 WriteWithRetry("DTS.CONVERT_CONTROL.ENABLE", 1);
147 WriteWithRetry("DTS.CONVERT_CONTROL.START_SYNC", 1);
148}

◆ StopEventBuilder()

void WIB::StopEventBuilder ( uint8_t mask = 0xF)

◆ TryFEMBPhases()

bool WIB::TryFEMBPhases ( uint8_t iFEMB,
std::vector< uint16_t > phases )

Definition at line 1049 of file WIB_FEMB.cpp.

1050{
1051
1052 size_t nPhases = phases.size();
1053 std::cout << "Searching " << nPhases << " sets of phases:" << std::endl;
1054 for (size_t ip = 0; ip < nPhases; ++ip) {
1055 uint16_t phase = phases.at(ip);
1056 std::cout << "Set " << ip << std::endl;
1057 std::cout << "\t Phase: " << std::hex << std::setw(4) << phase << std::endl;
1058
1059 WriteFEMBPhase(iFEMB, phase);
1060 // If it made it this far, it found the correct readback val
1061 sleep(0.001);
1062 uint32_t adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
1063 sleep(0.001);
1064 adc_fifo_sync = (ReadFEMB(iFEMB, 6) & 0xFFFF0000) >> 16;
1065 sleep(0.001);
1066
1067 std::cout << "FEMB " << int(iFEMB) << " ADC FIFO sync: " << std::bitset<16>(adc_fifo_sync) << std::endl;
1068
1069 if (adc_fifo_sync == 0) {
1070 std::cout << "FEMB " << int(iFEMB) << " ADC FIFO synced" << std::endl;
1071 std::cout << " phase: " << std::hex << std::setw(4) << std::setfill('0') << (uint32_t)phase << std::endl;
1072 return true;
1073 }
1074 }
1075
1076 // std::cout << "Could not find successful phase" << std::endl;
1077 return false;
1078}

◆ WriteDAQ_SI5342()

void WIB::WriteDAQ_SI5342 ( uint16_t address,
uint32_t value,
uint8_t byte_count = 4 )

Definition at line 9 of file WIB_SI5342.cpp.

10{
11 WriteI2C("DAQ.SI5342.I2C", address, value, byte_count);
12}
void WriteI2C(std::string const &base_address, uint16_t I2C_address, uint32_t data, uint8_t byte_count=4, bool ignore_error=false)
Definition WIBBase.cpp:81

◆ WriteDTS_CDS()

void WIB::WriteDTS_CDS ( uint16_t address,
uint32_t value,
uint8_t byte_count = 4,
bool ignore_error = false )

Definition at line 37 of file WIB_CDS.cpp.

38{
39 WriteI2C("DTS.CDS.I2C", address, value, byte_count, ignore_error);
40}

◆ WriteDTS_SI5344()

void WIB::WriteDTS_SI5344 ( uint16_t address,
uint32_t value,
uint8_t byte_count = 4 )

Definition at line 9 of file WIB_SI5344.cpp.

10{
11 WriteI2C("DTS.SI5344.I2C", address, value, byte_count);
12}

◆ WriteFEMBPhase()

void WIB::WriteFEMBPhase ( uint8_t iFEMB,
uint16_t clk_phase_data )

Definition at line 963 of file WIB_FEMB.cpp.

964{
965
966 uint32_t clk_phase_data0 = (clk_phase_data >> 8) & 0xFF;
967 uint32_t clk_phase_data1 = clk_phase_data & 0xFF;
968
969 uint32_t data;
970 uint32_t read_back;
971 int count = 0;
972 sleep(0.001);
973 for (int i = 0; i < 10; ++i) {
974
975 data = (~(clk_phase_data0)) & 0xFF;
976 WriteFEMB(iFEMB, 6, data);
977 sleep(0.001);
978 read_back = ReadFEMB(iFEMB, 6);
979 sleep(0.001);
980 if ((read_back & 0xFF) == ((~(clk_phase_data0)) & 0xFF)) {
981 break;
982 } else {
983 count++;
984 }
985 }
986 if (count >= 10) {
987 std::cout << "readback val for 0 is different from written data " << std::endl;
988 // Put in system exit?
989 }
990 count = 0;
991 for (int i = 0; i < 10; ++i) {
992
993 data = (~(clk_phase_data1)) & 0xFF;
994 WriteFEMB(iFEMB, 15, data);
995 sleep(0.001);
996 read_back = ReadFEMB(iFEMB, 15);
997 sleep(0.001);
998 if ((read_back & 0xFF) == ((~(clk_phase_data1)) & 0xFF)) {
999 break;
1000 } else {
1001 count++;
1002 }
1003 }
1004 if (count >= 10) {
1005 std::cout << "readback val for 1 is different from written data " << std::endl;
1006 // Put in system exit?
1007 }
1008 count = 0;
1009 for (int i = 0; i < 10; ++i) {
1010
1011 data = clk_phase_data0;
1012 WriteFEMB(iFEMB, 6, data);
1013 sleep(0.001);
1014
1015 read_back = ReadFEMB(iFEMB, 6);
1016 sleep(0.001);
1017 if ((read_back & 0xFF) == ((clk_phase_data0) & 0xFF)) {
1018 break;
1019 } else {
1020 count++;
1021 }
1022 }
1023 if (count >= 10) {
1024 std::cout << "readback val for 2 is different from written data " << std::endl;
1025 // Put in system exit?
1026 }
1027 count = 0;
1028 for (int i = 0; i < 10; ++i) {
1029
1030 data = clk_phase_data1;
1031 WriteFEMB(iFEMB, 15, data);
1032 sleep(0.001);
1033
1034 read_back = ReadFEMB(iFEMB, 6);
1035 sleep(0.001);
1036 if ((read_back & 0xFF) == ((clk_phase_data1) & 0xFF)) {
1037 break;
1038 } else {
1039 count++;
1040 }
1041 }
1042 if (count >= 10) {
1043 std::cout << "readback val for 3 is different from written data " << std::endl;
1044 // Put in system exit?
1045 }
1046}

◆ WriteFlash()

void WIB::WriteFlash ( std::vector< uint32_t > data,
uint8_t update_percentage = 101 )

Definition at line 244 of file WIB_Flash.cpp.

245{
246 // Setup display if needed
247 bool print_updates = false;
248 if (update_percentage < 100) {
249 print_updates = true;
250 }
251 size_t update_delta = (update_percentage * float(flashData.size())) / 100;
252 size_t next_update = update_delta;
253 if (print_updates) {
254 fprintf(stderr, " Programming flash\n");
255 fprintf(stderr, " [");
256 for (size_t i = 0; i < 100.0 / update_percentage; i++) {
257 fprintf(stderr, "=");
258 }
259 fprintf(stderr, "]\n [");
260 }
261
262 // program flash in groups of 64 32bit words (256 bytes)
263 uint32_t blockRegMapAddress = GetItem("FLASH.DATA00")->address; // Address of first of 64 32bit words
264 uint32_t flashAddress = 0; // Address in flash that we are writing to.
265
266 for (size_t currentBlockStartIndex = 0; currentBlockStartIndex < flashData.size();) {
268
269 // Find size of this block to write (usually just 64 (256bytes)), but the last one might be smaller.
270 size_t blockSize = std::min(size_t(64), flashData.size() - currentBlockStartIndex);
271 // Set adddress
272 WriteWithRetry("FLASH.ADDRESS", flashAddress);
273 // set block size (in bytes and is 1 less than value; 0 means 1 byte, 255 means 256 bytes)
274 WriteWithRetry("FLASH.BYTE_COUNT", (blockSize * sizeof(uint32_t)) - 1);
275
276 // Write block of data
277 for (size_t iBlockWord = 0; iBlockWord < blockSize; iBlockWord++) {
278 // arg1: Address in WIB register map of this 32bit word
279 // arg2: Data for this 32bit word reg map address in data vector
280 WriteWithRetry(blockRegMapAddress + iBlockWord, flashData[currentBlockStartIndex + iBlockWord]);
281 }
282 // Do the block write
283 WriteWithRetry("FLASH.RUN_COMMAND", 0x1);
284 currentBlockStartIndex += blockSize;
285 flashAddress += blockSize * sizeof(uint32_t);
286
287 // Update the screen if needed
288 if (print_updates && (currentBlockStartIndex > next_update)) {
289 fprintf(stderr, "=");
290 next_update += update_delta;
291 }
292 }
293 // Update the screen if needed
294 if (print_updates) {
295 fprintf(stderr, "]\n");
296 fprintf(stderr, " done\n");
297 }
298}

◆ WriteLocalFlash() [1/2]

void WIB::WriteLocalFlash ( uint16_t address,
std::vector< uint32_t > const & data )

Definition at line 54 of file WIB_localFlash.cpp.

55{
56 for (size_t iWord = 0; iWord < data.size(); iWord++) {
57 WriteLocalFlash(address, data[iWord]);
58 address++;
59 }
60}
void WriteLocalFlash(uint16_t address, uint32_t data)

◆ WriteLocalFlash() [2/2]

void WIB::WriteLocalFlash ( uint16_t address,
uint32_t data )

Definition at line 36 of file WIB_localFlash.cpp.

37{
38 // load the address
39 Write("SYSTEM.FLASH.ADDRESS", address);
40 // load the data to write
41 Write("SYSTEM.FLASH.WR_DATA", data);
42
43 // start the read transaction
44 Write("SYSTEM.FLASH.RW", 0);
45 Write("SYSTEM.FLASH.RUN", 1);
46 // Wait for finish
47 while (Read("SYSTEM.FLASH.DONE") == 0) {
48 // sleep for 1ms
49 usleep(1000);
50 }
51}

◆ WriteQSFP()

void WIB::WriteQSFP ( uint16_t address,
uint32_t value,
uint8_t byte_count )

Definition at line 7 of file WIB_QSFP.cpp.

8{
9 WriteI2C("DAQ.QSFP.I2C", address, value, byte_count);
10}

Member Data Documentation

◆ ContinueIfListOfFEMBClockPhasesDontSync

bool WIB::ContinueIfListOfFEMBClockPhasesDontSync
private

Definition at line 240 of file WIB.hh.

◆ ContinueOnFEMBRegReadError

bool WIB::ContinueOnFEMBRegReadError
private

Definition at line 237 of file WIB.hh.

◆ ContinueOnFEMBSPIError

bool WIB::ContinueOnFEMBSPIError
private

Definition at line 238 of file WIB.hh.

◆ ContinueOnFEMBSyncError

bool WIB::ContinueOnFEMBSyncError
private

Definition at line 239 of file WIB.hh.

◆ DAQLinkCount

uint8_t WIB::DAQLinkCount
private

Definition at line 235 of file WIB.hh.

◆ DAQMode

WIB_DAQ_t WIB::DAQMode
private

Definition at line 231 of file WIB.hh.

◆ FEMBCDACount

uint8_t WIB::FEMBCDACount
private

Definition at line 234 of file WIB.hh.

◆ FEMBCount

uint8_t WIB::FEMBCount
private

Definition at line 232 of file WIB.hh.

◆ FEMBStreamCount

uint8_t WIB::FEMBStreamCount
private

Definition at line 233 of file WIB.hh.

◆ started

bool WIB::started

Definition at line 33 of file WIB.hh.


The documentation for this class was generated from the following files: