DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
WIB_FEMB.cpp
Go to the documentation of this file.
4#include "wibmod/WIB1/WIB.hh"
6#include <bitset>
7#include <iomanip>
8#include <iostream>
9#include <sstream>
10#include <unistd.h>
11
12#define sleep(x) usleep((useconds_t)x * 1e6)
13
37void
38WIB::ConfigFEMB(uint8_t iFEMB,
39 std::vector<uint32_t> fe_config,
40 std::vector<uint16_t> clk_phases,
41 uint8_t pls_mode,
42 uint8_t pls_dac_val,
43 uint8_t start_frame_mode_sel,
44 uint8_t start_frame_swap)
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}
267
277void
279 uint8_t fake_mode,
280 uint32_t fake_word,
281 uint8_t femb_number,
282 std::vector<uint32_t> fake_samples,
283 uint8_t start_frame_mode_sel,
284 uint8_t start_frame_swap)
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}
366
371void
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}
541
550uint16_t
551WIB::SetupFEMBASICs(uint8_t iFEMB, std::vector<uint32_t> registerList)
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}
600
618uint16_t
620 uint8_t gain,
621 uint8_t shape,
622 uint8_t highBaseline,
623 bool highLeakage,
624 bool leakagex10,
625 bool acCoupling,
626 bool buffer,
627 bool useExtClock,
628 uint8_t internalDACControl,
629 uint8_t internalDACValue)
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);
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}
835
836uint16_t
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}
927
928void
929WIB::SetupFPGAPulser(uint8_t iFEMB, uint8_t dac_val)
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}
944
945void
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}
961
962void
963WIB::WriteFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data)
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}
1047
1048bool
1049WIB::TryFEMBPhases(uint8_t iFEMB, std::vector<uint16_t> phases)
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}
1079
1080bool
1081WIB::HuntFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data_start)
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}
1137
1138void
1140 uint32_t pls_cs,
1141 uint32_t dac_sel,
1142 uint32_t fpga_dac,
1143 uint32_t asic_dac,
1144 uint32_t mon_cs = 0)
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}
1164
1165void
1170
1171void
1173{
1174 ContinueOnFEMBSPIError = enable;
1175}
1176
1177void
1179{
1180 ContinueOnFEMBSyncError = enable;
1181}
1182
1183void
#define sleep(x)
Definition WIB_FEMB.cpp:12
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)
void WriteFEMB(int iFEMB, uint16_t address, uint32_t value)
Definition WIBBase.cpp:227
uint32_t Read(uint16_t address)
Definition WIBBase.cpp:147
void Write(uint16_t address, uint32_t value)
Definition WIBBase.cpp:168
uint32_t ReadFEMB(int iFEMB, uint16_t address)
Definition WIBBase.cpp:204
bool TryFEMBPhases(uint8_t iFEMB, std::vector< uint16_t > phases)
bool ContinueOnFEMBRegReadError
Definition WIB.hh:237
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.
Definition WIB_FEMB.cpp:38
void SetContinueOnFEMBSyncError(bool enable)
bool ContinueOnFEMBSyncError
Definition WIB.hh:239
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)
void SetupFEMBExtClock(uint8_t iFEMB)
Setup FEMB External Clock.
Definition WIB_FEMB.cpp:372
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.
Definition WIB_FEMB.cpp:278
bool ContinueOnFEMBSPIError
Definition WIB.hh:238
bool HuntFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data_start)
void SetContinueIfListOfFEMBClockPhasesDontSync(bool enable)
void SetupInternalPulser(uint8_t iFEMB)
Definition WIB_FEMB.cpp:946
uint16_t SetupASICPulserBits(uint8_t iFEMB)
Definition WIB_FEMB.cpp:837
bool ContinueIfListOfFEMBClockPhasesDontSync
Definition WIB.hh:240
void SetContinueOnFEMBSPIError(bool enable)
void SetContinueOnFEMBRegReadError(bool enable)
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
void WriteFEMBPhase(uint8_t iFEMB, uint16_t clk_phase_data)
Definition WIB_FEMB.cpp:963