pxar
 All Classes Namespaces Functions Variables Typedefs Friends
api.cc
1 
5 #include "api.h"
6 #include "hal.h"
7 #include "log.h"
8 #include "timer.h"
9 #include "helper.h"
10 #include "dictionaries.h"
11 #include <algorithm>
12 #include <fstream>
13 #include <cmath>
14 #include "constants.h"
15 #include "config.h"
16 
17 using namespace pxar;
18 
19 pxarCore::pxarCore(std::string usbId, std::string logLevel) :
20  _daq_running(false),
21  _daq_buffersize(DTB_SOURCE_BUFFER_SIZE),
22  _daq_startstop_warning(false)
23 {
24 
25  LOG(logQUIET) << "Instanciating API for " << PACKAGE_STRING;
26 
27  // Set up the libpxar API/HAL logging mechanism:
28  Log::ReportingLevel() = Log::FromString(logLevel);
29  LOG(logINFO) << "Log level: " << logLevel;
30 
31  // Get a new HAL instance with the DTB USB ID passed to the API constructor:
32  _hal = new hal(usbId);
33 
34  // Get the DUT up and running:
35  _dut = new dut();
36 }
37 
39  delete _dut;
40  delete _hal;
41 }
42 
43 std::string pxarCore::getVersion() { return PACKAGE_STRING; }
44 
45 bool pxarCore::initTestboard(std::vector<std::pair<std::string,uint8_t> > sig_delays,
46  std::vector<std::pair<std::string,double> > power_settings,
47  std::vector<std::pair<std::string,uint8_t> > pg_setup) {
48 
49  // Check the HAL status before doing anything else:
50  if(!_hal->compatible()) return false;
51 
52  // Collect and check the testboard configuration settings
53 
54  // Power settings:
55  checkTestboardPower(power_settings);
56 
57  // Signal Delays:
58  checkTestboardDelays(sig_delays);
59 
60  // Prepare Pattern Generator:
61  verifyPatternGenerator(pg_setup);
62 
63  // Call the HAL to do the job:
64  _hal->initTestboard(_dut->sig_delays,_dut->pg_setup,_dut->pg_sum,_dut->va,_dut->vd,_dut->ia,_dut->id);
65  return true;
66 }
67 
68 void pxarCore::setTestboardDelays(std::vector<std::pair<std::string,uint8_t> > sig_delays) {
69  if(!_hal->status()) {
70  LOG(logERROR) << "Signal delays not updated!";
71  return;
72  }
73  checkTestboardDelays(sig_delays);
74  _hal->setTestboardDelays(_dut->sig_delays);
75  LOG(logDEBUGAPI) << "Testboard signal delays updated.";
76 }
77 
78 void pxarCore::setPatternGenerator(std::vector<std::pair<std::string,uint8_t> > pg_setup) {
79  if(!_hal->status()) {
80  LOG(logERROR) << "Pattern generator not updated!";
81  return;
82  }
83  verifyPatternGenerator(pg_setup);
84  _hal->SetupPatternGenerator(_dut->pg_setup,_dut->pg_sum);
85  LOG(logDEBUGAPI) << "Pattern generator verified and updated.";
86 }
87 
88 void pxarCore::setTestboardPower(std::vector<std::pair<std::string,double> > power_settings) {
89  if(!_hal->status()) {
90  LOG(logERROR) << "Voltages/current limits not upated!";
91  return;
92  }
93  checkTestboardPower(power_settings);
94  _hal->setTestboardPower(_dut->va,_dut->vd,_dut->ia,_dut->id);
95  LOG(logDEBUGAPI) << "Voltages/current limits updated.";
96 }
97 
98 bool pxarCore::initDUT(uint8_t hubid,
99  std::string tbmtype,
100  std::vector<std::vector<std::pair<std::string,uint8_t> > > tbmDACs,
101  std::string roctype,
102  std::vector<std::vector<std::pair<std::string,uint8_t> > > rocDACs,
103  std::vector<std::vector<pixelConfig> > rocPixels) {
104  std::vector<uint8_t> rocI2Cs;
105  return initDUT(hubid, tbmtype, tbmDACs, roctype, rocDACs, rocPixels, rocI2Cs);
106 }
107 
108 bool pxarCore::initDUT(uint8_t hubid,
109  std::string tbmtype,
110  std::vector<std::vector<std::pair<std::string,uint8_t> > > tbmDACs,
111  std::string roctype,
112  std::vector<std::vector<std::pair<std::string,uint8_t> > > rocDACs,
113  std::vector<std::vector<pixelConfig> > rocPixels,
114  std::vector<uint8_t> rocI2Cs) {
115 
116  // Check if the HAL is ready:
117  if(!_hal->status()) return false;
118 
119  // Verification/sanitry checks of supplied DUT configuration values
120 
121  // Check if I2C addresses were supplied - if so, check size agains sets of DACs:
122  if(!rocI2Cs.empty()) {
123  if(rocI2Cs.size() != rocDACs.size()) {
124  LOG(logCRITICAL) << "Hm, we have " << rocI2Cs.size() << " I2C addresses but " << rocDACs.size() << " DAC configs.";
125  LOG(logCRITICAL) << "This cannot end well...";
126  throw InvalidConfig("Mismatch between number of I2C addresses and DAC configurations");
127  }
128  LOG(logDEBUGAPI) << "I2C addresses for all ROCs are provided as user input.";
129  }
130  else { LOG(logDEBUGAPI) << "I2C addresses will be automatically generated."; }
131 
132  // Check size of rocDACs and rocPixels against each other
133  if(rocDACs.size() != rocPixels.size()) {
134  LOG(logCRITICAL) << "Hm, we have " << rocDACs.size() << " DAC configs but " << rocPixels.size() << " pixel configs.";
135  LOG(logCRITICAL) << "This cannot end well...";
136  throw InvalidConfig("Mismatch between number of DAC and pixel configurations");
137  }
138  // check for presence of DAC/pixel configurations
139  if (rocDACs.size() == 0 || rocPixels.size() == 0){
140  LOG(logCRITICAL) << "No DAC/pixel configurations for any ROC supplied!";
141  throw InvalidConfig("No DAC/pixel configurations for any ROC supplied");
142  }
143  // check individual pixel configs
144  for(std::vector<std::vector<pixelConfig> >::iterator rocit = rocPixels.begin();rocit != rocPixels.end(); rocit++){
145  // check pixel configuration sizes
146  if ((*rocit).size() == 0){
147  LOG(logWARNING) << "No pixel configured for ROC "<< static_cast<int>(rocit - rocPixels.begin()) << "!";
148  }
149  if ((*rocit).size() > 4160){
150  LOG(logCRITICAL) << "Too many pixels (N_pixel="<< rocit->size() <<" > 4160) configured for ROC "<< static_cast<int>(rocit - rocPixels.begin()) << "!";
151  throw InvalidConfig("Too many pixels (>4160) configured");
152  }
153  // check individual pixel configurations
154  int nduplicates = 0;
155  for(std::vector<pixelConfig>::iterator pixit = rocit->begin(); pixit != rocit->end(); pixit++){
156  if (std::count_if(rocit->begin(),rocit->end(),findPixelXY(pixit->column(),pixit->row())) > 1){
157  LOG(logCRITICAL) << "Config for pixel in column " << static_cast<int>(pixit->column()) << " and row "<< static_cast<int>(pixit->row()) << " present multiple times in ROC " << static_cast<int>(rocit-rocPixels.begin()) << "!";
158  nduplicates++;
159  }
160  }
161  if (nduplicates>0){
162  throw InvalidConfig("Duplicate pixel configurations present");
163  }
164 
165  // check for pixels out of range
166  if (std::count_if((*rocit).begin(),(*rocit).end(),findPixelBeyondXY(51,79)) > 0) {
167  LOG(logCRITICAL) << "Found pixels with values for column and row outside of valid address range on ROC "<< static_cast<int>(rocit - rocPixels.begin()) << "!";
168  throw InvalidConfig("Found pixels with values for column and row outside of valid address range");
169  }
170  }
171 
172  LOG(logDEBUGAPI) << "We have " << rocDACs.size() << " DAC configs and " << rocPixels.size() << " pixel configs, with " << rocDACs.at(0).size() << " and " << rocPixels.at(0).size() << " entries for the first ROC, respectively.";
173 
174  // First initialized the API's DUT instance with the information supplied.
175 
176  // Store the hubId:
177  _dut->hubId = hubid;
178 
179  // Initialize TBMs:
180  LOG(logDEBUGAPI) << "Received settings for " << tbmDACs.size() << " TBM cores.";
181 
182  for(std::vector<std::vector<std::pair<std::string,uint8_t> > >::iterator tbmIt = tbmDACs.begin(); tbmIt != tbmDACs.end(); ++tbmIt) {
183 
184  LOG(logDEBUGAPI) << "Processing TBM Core " << static_cast<int>(tbmIt - tbmDACs.begin());
185  // Prepare a new TBM configuration
186  tbmConfig newtbm;
187 
188  // Set the TBM type (get value from dictionary)
189  newtbm.type = stringToDeviceCode(tbmtype);
190  if(newtbm.type == 0x0) return false;
191 
192  // Loop over all the DAC settings supplied and fill them into the TBM dacs
193  for(std::vector<std::pair<std::string,uint8_t> >::iterator dacIt = (*tbmIt).begin(); dacIt != (*tbmIt).end(); ++dacIt) {
194 
195  // Fill the register pairs with the register id from the dictionary:
196  uint8_t tbmregister, value = dacIt->second;
197  if(!verifyRegister(dacIt->first, tbmregister, value, TBM_REG)) continue;
198 
199  // Check if this is fore core alpha or beta:
200  if((tbmIt - tbmDACs.begin())%2 == 0) { tbmregister = 0xE0 | tbmregister; } // alpha core
201  else { tbmregister = 0xF0 | tbmregister; } // beta core
202 
203  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
204  ret = newtbm.dacs.insert( std::make_pair(tbmregister,value) );
205  if(ret.second == false) {
206  LOG(logWARNING) << "Overwriting existing DAC \"" << dacIt->first
207  << "\" value " << static_cast<int>(ret.first->second)
208  << " with " << static_cast<int>(value);
209  newtbm.dacs[tbmregister] = value;
210  }
211  }
212 
213  // Done. Enable bit is already set by tbmConfig constructor.
214  _dut->tbm.push_back(newtbm);
215  }
216 
217  // Check number of configured TBM cores. If we only got one register vector, we re-use it for the second TBM core:
218  if(_dut->tbm.size() == 1) {
219  LOG(logDEBUGAPI) << "Only register settings for one TBM core supplied. Duplicating to second core.";
220  // Prepare a new TBM configuration and copy over all settings:
221  tbmConfig newtbm;
222  newtbm.type = _dut->tbm.at(0).type;
223 
224  for(std::map<uint8_t,uint8_t>::iterator reg = _dut->tbm.at(0).dacs.begin(); reg != _dut->tbm.at(0).dacs.end(); ++reg) {
225  uint8_t tbmregister = reg->first;
226  // Flip the last bit of the TBM core identifier:
227  tbmregister ^= (1u << 4);
228  newtbm.dacs.insert(std::make_pair(tbmregister,reg->second));
229  }
230  _dut->tbm.push_back(newtbm);
231  }
232 
233  // Check if we have any TBM present to select termination for the DTB RDA/Tout input:
234  if(!_dut->tbm.empty()) {
235  // We have RDA input from a TBM, this needs LCDS termination:
236  _hal->SigSetLCDS();
237  LOG(logDEBUGAPI) << "RDA/Tout DTB input termination set to LCDS.";
238  }
239  else {
240  // We expect the direct TokenOut signal from a ROC which needs LVDS termination:
241  _hal->SigSetLVDS();
242  LOG(logDEBUGAPI) << "RDA/Tout DTB input termination set to LVDS.";
243  }
244 
245  // Initialize ROCs:
246  for(std::vector<std::vector<std::pair<std::string,uint8_t> > >::iterator rocIt = rocDACs.begin(); rocIt != rocDACs.end(); ++rocIt){
247 
248  // Prepare a new ROC configuration
249  rocConfig newroc;
250  // Set the ROC type (get value from dictionary)
251  newroc.type = stringToDeviceCode(roctype);
252  if(newroc.type == 0x0) return false;
253 
254  // If no I2C addresses have been supplied, we just assume they are consecutively numbered:
255  if(rocI2Cs.empty()) { newroc.i2c_address = static_cast<uint8_t>(rocIt - rocDACs.begin()); }
256  // if we have adresses, let's pick the right one and assign it:
257  else { newroc.i2c_address = static_cast<uint8_t>(rocI2Cs.at(rocIt - rocDACs.begin())); }
258  LOG(logDEBUGAPI) << "I2C address for the next ROC is: " << static_cast<int>(newroc.i2c_address);
259 
260  // Loop over all the DAC settings supplied and fill them into the ROC dacs
261  for(std::vector<std::pair<std::string,uint8_t> >::iterator dacIt = (*rocIt).begin(); dacIt != (*rocIt).end(); ++dacIt){
262  // Fill the DAC pairs with the register from the dictionary:
263  uint8_t dacRegister, dacValue = dacIt->second;
264  if(!verifyRegister(dacIt->first, dacRegister, dacValue, ROC_REG)) continue;
265 
266  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
267  ret = newroc.dacs.insert( std::make_pair(dacRegister,dacValue) );
268  if(ret.second == false) {
269  LOG(logWARNING) << "Overwriting existing DAC \"" << dacIt->first
270  << "\" value " << static_cast<int>(ret.first->second)
271  << " with " << static_cast<int>(dacValue);
272  newroc.dacs[dacRegister] = dacValue;
273  }
274  }
275 
276  // Loop over all pixelConfigs supplied:
277  for(std::vector<pixelConfig>::iterator pixIt = rocPixels.at(rocIt - rocDACs.begin()).begin(); pixIt != rocPixels.at(rocIt - rocDACs.begin()).end(); ++pixIt) {
278  // Check the trim value to be within boundaries:
279  if((*pixIt).trim() > 15) {
280  LOG(logWARNING) << "Pixel "
281  << static_cast<int>((*pixIt).column()) << ", "
282  << static_cast<int>((*pixIt).row())<< " trim value "
283  << static_cast<int>((*pixIt).trim()) << " exceeds limit. Set to 15.";
284  (*pixIt).setTrim(15);
285  }
286  // Push the pixelConfigs into the rocConfig:
287  newroc.pixels.push_back(*pixIt);
288  }
289 
290  // Done. Enable bit is already set by rocConfig constructor.
291  _dut->roc.push_back(newroc);
292  }
293 
294  // All data is stored in the DUT struct, now programming it.
295  _dut->_initialized = true;
296  return programDUT();
297 }
298 
300 
301  if(!_dut->_initialized) {
302  LOG(logERROR) << "DUT not initialized, unable to program it.";
303  return false;
304  }
305 
306  // First thing to do: startup DUT power if not yet done
307  _hal->Pon();
308 
309  // Start programming the devices here!
310  _hal->setHubId(_dut->hubId);
311 
312  std::vector<tbmConfig> enabledTbms = _dut->getEnabledTbms();
313  if(!enabledTbms.empty()) {LOG(logDEBUGAPI) << "Programming TBMs...";}
314  for (std::vector<tbmConfig>::iterator tbmit = enabledTbms.begin(); tbmit != enabledTbms.end(); ++tbmit){
315  _hal->initTBMCore((*tbmit).type,(*tbmit).dacs);
316  }
317 
318  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
319  if(!enabledRocs.empty()) {LOG(logDEBUGAPI) << "Programming ROCs...";}
320  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
321  _hal->initROC(rocit->i2c_address,(*rocit).type, (*rocit).dacs);
322  }
323 
324  // As last step, mask all pixels in the device and detach all double column readouts:
325  MaskAndTrim(false);
326  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
327  _hal->AllColumnsSetEnable(rocit->i2c_address,true);
328  }
329  // Also clear all calibrate signals:
330  SetCalibrateBits(false);
331 
332  // The DUT is programmed, everything all right:
333  _dut->_programmed = true;
334 
335  return true;
336 }
337 
338 // API status function, checks HAL and DUT statuses
340  if(_hal->status() && _dut->status()) return true;
341  return false;
342 }
343 
344 // Lookup register and check value range
345 bool pxarCore::verifyRegister(std::string name, uint8_t &id, uint8_t &value, uint8_t type) {
346 
347  // Convert the name to lower case for comparison:
348  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
349 
350  // Get singleton DAC dictionary object:
351  RegisterDictionary * _dict = RegisterDictionary::getInstance();
352 
353  // And get the register value from the dictionary object:
354  id = _dict->getRegister(name,type);
355 
356  // Check if it was found:
357  if(id == type) {
358  LOG(logERROR) << "Invalid register name \"" << name << "\".";
359  return false;
360  }
361 
362  // Read register value limit:
363  uint8_t regLimit = _dict->getSize(id, type);
364  if(value > regLimit) {
365  LOG(logWARNING) << "Register range overflow, set register \""
366  << name << "\" (" << static_cast<int>(id) << ") to "
367  << static_cast<int>(regLimit) << " (was: " << static_cast<int>(value) << ")";
368  value = static_cast<uint8_t>(regLimit);
369  }
370 
371  // LOG(logDEBUGAPI) << "Verified register \"" << name << "\" (" << static_cast<int>(id) << "): "
372  // << static_cast<int>(value) << " (max " << static_cast<int>(regLimit) << ")";
373  return true;
374 }
375 
376 // Return the device code for the given name, return 0x0 if invalid:
377 uint8_t pxarCore::stringToDeviceCode(std::string name) {
378 
379  // Convert the name to lower case for comparison:
380  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
381  LOG(logDEBUGAPI) << "Looking up device type for \"" << name << "\"";
382 
383  // Get singleton device dictionary object:
384  DeviceDictionary * _devices = DeviceDictionary::getInstance();
385 
386  // And get the device code from the dictionary object:
387  uint8_t _code = _devices->getDevCode(name);
388  LOG(logDEBUGAPI) << "Device type return: " << static_cast<int>(_code);
389 
390  if(_code == 0x0) {LOG(logERROR) << "Unknown device \"" << static_cast<int>(_code) << "\"!";}
391  return _code;
392 }
393 
394 
395 // DTB functions
396 
397 bool pxarCore::flashTB(std::string filename) {
398 
399  if(_hal->status() || _dut->status()) {
400  LOG(logERROR) << "The testboard should only be flashed without initialization"
401  << " and with all attached DUTs powered down.";
402  LOG(logERROR) << "Please power cycle the testboard and flash directly after startup!";
403  return false;
404  }
405 
406  // Try to open the flash file
407  std::ifstream flashFile;
408 
409  LOG(logINFO) << "Trying to open " << filename;
410  flashFile.open(filename.c_str(), std::ifstream::in);
411  if(!flashFile.is_open()) {
412  LOG(logERROR) << "Could not open specified DTB flash file \"" << filename<< "\"!";
413  return false;
414  }
415 
416  // Call the HAL routine to do the flashing:
417  bool status = false;
418  status = _hal->flashTestboard(flashFile);
419  flashFile.close();
420 
421  return status;
422 }
423 
425  if(!_hal->status()) {return 0;}
426  return _hal->getTBia();
427 }
428 
430  if(!_hal->status()) {return 0;}
431  return _hal->getTBva();
432 }
433 
435  if(!_hal->status()) {return 0;}
436  return _hal->getTBid();
437 }
438 
440  if(!_hal->status()) {return 0;}
441  return _hal->getTBvd();
442 }
443 
444 
446  _hal->HVoff();
447 }
448 
450  _hal->HVon();
451 }
452 
454  _hal->Poff();
455  // Reset the programmed state of the DUT (lost by turning off power)
456  _dut->_programmed = false;
457 }
458 
460  // Power is turned on when programming the DUT.
461  // Re-program the DUT after power has been switched on:
462  programDUT();
463 }
464 
465 bool pxarCore::SignalProbe(std::string probe, std::string name) {
466 
467  if(!_hal->status()) {return false;}
468 
469  // Get singleton Probe dictionary object:
470  ProbeDictionary * _dict = ProbeDictionary::getInstance();
471 
472  // Convert the probe name to lower case for comparison:
473  std::transform(probe.begin(), probe.end(), probe.begin(), ::tolower);
474 
475  // Convert the name to lower case for comparison:
476  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
477 
478  // Digital signal probes:
479  if(probe.compare(0,1,"d") == 0) {
480 
481  // And get the register value from the dictionary object:
482  uint8_t signal = _dict->getSignal(name,PROBE_DIGITAL);
483  LOG(logDEBUGAPI) << "Digital probe signal lookup for \"" << name
484  << "\" returned signal: " << static_cast<int>(signal);
485 
486  // Select the correct probe for the output:
487  if(probe.compare("d1") == 0) {
488  _hal->SignalProbeD1(signal);
489  return true;
490  }
491  else if(probe.compare("d2") == 0) {
492  _hal->SignalProbeD2(signal);
493  return true;
494  }
495  }
496  // Analog signal probes:
497  else if(probe.compare(0,1,"a") == 0) {
498 
499  // And get the register value from the dictionary object:
500  uint8_t signal = _dict->getSignal(name, PROBE_ANALOG);
501  LOG(logDEBUGAPI) << "Analog probe signal lookup for \"" << name
502  << "\" returned signal: " << static_cast<int>(signal);
503 
504  // Select the correct probe for the output:
505  if(probe.compare("a1") == 0) {
506  _hal->SignalProbeA1(signal);
507  return true;
508  }
509  else if(probe.compare("a2") == 0) {
510  _hal->SignalProbeA2(signal);
511  return true;
512  }
513  else if (probe.compare("adc") == 0) {
514  _hal->SignalProbeADC(signal, 0);
515  return true;
516  }
517  }
518 
519  LOG(logERROR) << "Invalid probe name \"" << probe << "\" selected!";
520  return false;
521 }
522 
523 
524 
525 std::vector<uint16_t> pxarCore::daqADC(std::string signalName, uint8_t gain, uint16_t nSample, uint8_t source, uint8_t start){
526 
527  vector<uint16_t> data;
528  if(!_hal->status()) {return data;}
529 
530  ProbeDictionary * _dict = ProbeDictionary::getInstance();
531  std::transform(signalName.begin(), signalName.end(), signalName.begin(), ::tolower);
532  uint8_t signal = _dict->getSignal(signalName, PROBE_ANALOG);
533 
534  data = _hal->daqADC(signal, gain, nSample, source, start);
535  return data;
536 }
537 
539  // Return the accumulated number of decoding errors:
540  return _hal->daqStatistics();
541 }
542 
543 
544 // TEST functions
545 
546 bool pxarCore::setDAC(std::string dacName, uint8_t dacValue, uint8_t rocID) {
547 
548  if(!status()) {return false;}
549 
550  // Get the register number and check the range from dictionary:
551  uint8_t dacRegister;
552  if(!verifyRegister(dacName, dacRegister, dacValue, ROC_REG)) return false;
553 
554  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
555  std::vector<rocConfig>::iterator rocit;
556  for (rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
557 
558  // Set the DAC only in the given ROC (even if that is disabled!)
559  // WE ARE NOT USING the I2C address to identify the ROC currently:
560  //if(rocit->i2c_address == rocI2C) {
561  // But its ROC ID being just counted up from the first:
562  if(static_cast<int>(rocit - _dut->roc.begin()) == rocID) {
563 
564  // Update the DUT DAC Value:
565  ret = rocit->dacs.insert(std::make_pair(dacRegister,dacValue));
566  if(ret.second == true) {
567  LOG(logWARNING) << "DAC \"" << dacName << "\" was not initialized. Created with value " << static_cast<int>(dacValue);
568  }
569  else {
570  rocit->dacs[dacRegister] = dacValue;
571  LOG(logDEBUGAPI) << "DAC \"" << dacName << "\" updated with value " << static_cast<int>(dacValue);
572  }
573 
574  _hal->rocSetDAC(rocit->i2c_address,dacRegister,dacValue);
575  break;
576  }
577  }
578 
579  // We might not have found this ROC:
580  if(rocit == _dut->roc.end()) {
581  LOG(logERROR) << "ROC@I2C " << static_cast<int>(rocID) << " does not exist in the DUT!";
582  return false;
583  }
584 
585  return true;
586 }
587 
588 bool pxarCore::setDAC(std::string dacName, uint8_t dacValue) {
589 
590  if(!status()) {return false;}
591 
592  // Get the register number and check the range from dictionary:
593  uint8_t dacRegister;
594  if(!verifyRegister(dacName, dacRegister, dacValue, ROC_REG)) return false;
595 
596  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
597  // Set the DAC for all active ROCs:
598  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
599 
600  // Check if this ROC is marked active:
601  if(!rocit->enable()) { continue; }
602 
603  // Update the DUT DAC Value:
604  ret = rocit->dacs.insert(std::make_pair(dacRegister,dacValue));
605  if(ret.second == true) {
606  LOG(logWARNING) << "DAC \"" << dacName << "\" was not initialized. Created with value " << static_cast<int>(dacValue);
607  }
608  else {
609  rocit->dacs[dacRegister] = dacValue;
610  LOG(logDEBUGAPI) << "DAC \"" << dacName << "\" updated with value " << static_cast<int>(dacValue);
611  }
612 
613  _hal->rocSetDAC(rocit->i2c_address,dacRegister,dacValue);
614  }
615 
616  return true;
617 }
618 
619 uint8_t pxarCore::getDACRange(std::string dacName) {
620 
621  // Get the register number and check the range from dictionary:
622  uint8_t dacRegister;
623  uint8_t val = 0;
624  if(!verifyRegister(dacName, dacRegister, val, ROC_REG)) return 0;
625 
626  // Get singleton DAC dictionary object:
627  RegisterDictionary * _dict = RegisterDictionary::getInstance();
628 
629  // Read register value limit:
630  return _dict->getSize(dacRegister, ROC_REG);
631 }
632 
633 bool pxarCore::setTbmReg(std::string regName, uint8_t regValue, uint8_t tbmid) {
634 
635  if(!status()) {return 0;}
636 
637  // Get the register number and check the range from dictionary:
638  uint8_t _register;
639  if(!verifyRegister(regName, _register, regValue, TBM_REG)) return false;
640 
641  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
642  if(_dut->tbm.size() > static_cast<size_t>(tbmid)) {
643  // Set the register only in the given TBM (even if that is disabled!)
644 
645  // Get the core (alpha/beta) from one of the registers:
646  _register |= _dut->tbm.at(tbmid).dacs.begin()->first&0xF0;
647 
648  // Update the DUT register Value:
649  ret = _dut->tbm.at(tbmid).dacs.insert(std::make_pair(_register,regValue));
650  if(ret.second == true) {
651  LOG(logWARNING) << "Register \"" << regName << "\" (" << std::hex << static_cast<int>(_register) << std::dec << ") was not initialized. Created with value " << static_cast<int>(regValue);
652  }
653  else {
654  _dut->tbm.at(tbmid).dacs[_register] = regValue;
655  LOG(logDEBUGAPI) << "Register \"" << regName << "\" (" << std::hex << static_cast<int>(_register) << std::dec << ") updated with value " << static_cast<int>(regValue);
656  }
657 
658  _hal->tbmSetReg(_register,regValue);
659  }
660  else {
661  LOG(logERROR) << "TBM " << tbmid << " is not existing in the DUT!";
662  return false;
663  }
664  return true;
665 }
666 
667 bool pxarCore::setTbmReg(std::string regName, uint8_t regValue) {
668 
669  for(size_t tbms = 0; tbms < _dut->tbm.size(); ++tbms) {
670  if(!setTbmReg(regName, regValue, tbms)) return false;
671  }
672  return true;
673 }
674 
675 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getPulseheightVsDAC(std::string dacName, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers) {
676 
677  // No step size provided - scanning all DACs with step size 1:
678  return getPulseheightVsDAC(dacName, 1, dacMin, dacMax, flags, nTriggers);
679 }
680 
681 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getPulseheightVsDAC(std::string dacName, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers) {
682 
683  if(!status()) {return std::vector< std::pair<uint8_t, std::vector<pixel> > >();}
684 
685  // Check DAC range
686  if(dacMin > dacMax) {
687  // Swapping the range:
688  LOG(logWARNING) << "Swapping upper and lower bound.";
689  uint8_t temp = dacMin;
690  dacMin = dacMax;
691  dacMax = temp;
692  }
693 
694  // Get the register number and check the range from dictionary:
695  uint8_t dacRegister;
696  if(!verifyRegister(dacName, dacRegister, dacMax, ROC_REG)) {
697  return std::vector< std::pair<uint8_t, std::vector<pixel> > >();
698  }
699 
700  // Setup the correct _hal calls for this test
701  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacScan;
702  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacScan;
703  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsDacScan;
704  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsDacScan;
705 
706  // We want the pulse height back from the Map function, no internal flag needed.
707 
708  // Load the test parameters into vector
709  std::vector<int32_t> param;
710  param.push_back(static_cast<int32_t>(dacRegister));
711  param.push_back(static_cast<int32_t>(dacMin));
712  param.push_back(static_cast<int32_t>(dacMax));
713  param.push_back(static_cast<int32_t>(flags));
714  param.push_back(static_cast<int32_t>(nTriggers));
715  param.push_back(static_cast<int32_t>(dacStep));
716 
717  // check if the flags indicate that the user explicitly asks for serial execution of test:
718  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
719  // repack data into the expected return format
720  std::vector< std::pair<uint8_t, std::vector<pixel> > > result = repackDacScanData(data,dacStep,dacMin,dacMax,nTriggers,flags,false);
721 
722  // Reset the original value for the scanned DAC:
723  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
724  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
725  uint8_t oldDacValue = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dacName);
726  LOG(logDEBUGAPI) << "Reset DAC \"" << dacName << "\" to original value " << static_cast<int>(oldDacValue);
727  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dacRegister,oldDacValue);
728  }
729 
730  return result;
731 }
732 
733 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getEfficiencyVsDAC(std::string dacName, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers) {
734 
735  // No step size provided - scanning all DACs with step size 1:
736  return getEfficiencyVsDAC(dacName, 1, dacMin, dacMax, flags, nTriggers);
737 }
738 
739 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getEfficiencyVsDAC(std::string dacName, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers) {
740 
741  if(!status()) {return std::vector< std::pair<uint8_t, std::vector<pixel> > >();}
742 
743  // Check DAC range
744  if(dacMin > dacMax) {
745  // Swapping the range:
746  LOG(logWARNING) << "Swapping upper and lower bound.";
747  uint8_t temp = dacMin;
748  dacMin = dacMax;
749  dacMax = temp;
750  }
751 
752  // Get the register number and check the range from dictionary:
753  uint8_t dacRegister;
754  if(!verifyRegister(dacName, dacRegister, dacMax, ROC_REG)) {
755  return std::vector< std::pair<uint8_t, std::vector<pixel> > >();
756  }
757 
758  // Setup the correct _hal calls for this test
759  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacScan;
760  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacScan;
761  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsDacScan;
762  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsDacScan;
763 
764  // Load the test parameters into vector
765  std::vector<int32_t> param;
766  param.push_back(static_cast<int32_t>(dacRegister));
767  param.push_back(static_cast<int32_t>(dacMin));
768  param.push_back(static_cast<int32_t>(dacMax));
769  param.push_back(static_cast<int32_t>(flags));
770  param.push_back(static_cast<int32_t>(nTriggers));
771  param.push_back(static_cast<int32_t>(dacStep));
772 
773  // check if the flags indicate that the user explicitly asks for serial execution of test:
774  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
775  // repack data into the expected return format
776  std::vector< std::pair<uint8_t, std::vector<pixel> > > result = repackDacScanData(data,dacStep,dacMin,dacMax,nTriggers,flags,true);
777 
778  // Reset the original value for the scanned DAC:
779  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
780  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
781  uint8_t oldDacValue = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dacName);
782  LOG(logDEBUGAPI) << "Reset DAC \"" << dacName << "\" to original value " << static_cast<int>(oldDacValue);
783  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dacRegister,oldDacValue);
784  }
785 
786  return result;
787 }
788 
789 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getThresholdVsDAC(std::string dacName, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
790  // Get the full DAC range for scanning:
791  uint8_t dac1min = 0;
792  uint8_t dac1max = getDACRange(dacName);
793  uint8_t dacStep = 1;
794  return getThresholdVsDAC(dacName, dacStep, dac1min, dac1max, dac2name, dacStep, dac2min, dac2max, flags, nTriggers);
795 }
796 
797 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getThresholdVsDAC(std::string dac1name, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
798  // No threshold level provided - set threshold to 50%:
799  uint8_t threshold = 50;
800  return getThresholdVsDAC(dac1name, dac1step, dac1min, dac1max, dac2name, dac2step, dac2min, dac2max, threshold, flags, nTriggers);
801 }
802 
803 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::getThresholdVsDAC(std::string dac1name, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint8_t threshold, uint16_t flags, uint16_t nTriggers) {
804 
805  if(!status()) {return std::vector< std::pair<uint8_t, std::vector<pixel> > >();}
806 
807  // Check DAC ranges
808  if(dac1min > dac1max) {
809  // Swapping the range:
810  LOG(logWARNING) << "Swapping upper and lower bound.";
811  uint8_t temp = dac1min;
812  dac1min = dac1max;
813  dac1max = temp;
814  }
815  if(dac2min > dac2max) {
816  // Swapping the range:
817  LOG(logWARNING) << "Swapping upper and lower bound.";
818  uint8_t temp = dac2min;
819  dac2min = dac2max;
820  dac2max = temp;
821  }
822 
823  // Get the register number and check the range from dictionary:
824  uint8_t dac1register, dac2register;
825  if(!verifyRegister(dac1name, dac1register, dac1max, ROC_REG)) {
826  return std::vector< std::pair<uint8_t, std::vector<pixel> > >();
827  }
828  if(!verifyRegister(dac2name, dac2register, dac2max, ROC_REG)) {
829  return std::vector< std::pair<uint8_t, std::vector<pixel> > >();
830  }
831 
832  // Check the threshold percentage level provided:
833  if(threshold == 0 || threshold > 100) {
834  LOG(logCRITICAL) << "Threshold level of " << static_cast<int>(threshold) << "% is not possible!";
835  return std::vector< std::pair<uint8_t, std::vector<pixel> > >();
836  }
837 
838  // Setup the correct _hal calls for this test
839  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacDacScan;
840  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacDacScan;
841  // In Principle these functions exist, but they would take years to run and fill up the buffer
842  HalMemFnRocSerial rocfn = NULL; // &hal::SingleRocAllPixelsDacDacScan;
843  HalMemFnRocParallel multirocfn = NULL; // &hal::MultiRocAllPixelsDacDacScan;
844 
845  // Load the test parameters into vector
846  std::vector<int32_t> param;
847  param.push_back(static_cast<int32_t>(dac1register));
848  param.push_back(static_cast<int32_t>(dac1min));
849  param.push_back(static_cast<int32_t>(dac1max));
850  param.push_back(static_cast<int32_t>(dac2register));
851  param.push_back(static_cast<int32_t>(dac2min));
852  param.push_back(static_cast<int32_t>(dac2max));
853  param.push_back(static_cast<int32_t>(flags));
854  param.push_back(static_cast<int32_t>(nTriggers));
855  param.push_back(static_cast<int32_t>(dac1step));
856  param.push_back(static_cast<int32_t>(dac2step));
857 
858  // check if the flags indicate that the user explicitly asks for serial execution of test:
859  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
860  // repack data into the expected return format
861  std::vector< std::pair<uint8_t, std::vector<pixel> > > result = repackThresholdDacScanData(data,dac1step,dac1min,dac1max,dac2step,dac2min,dac2max,threshold,nTriggers,flags);
862 
863  // Reset the original value for the scanned DAC:
864  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
865  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
866  uint8_t oldDac1Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac1name);
867  uint8_t oldDac2Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac2name);
868  LOG(logDEBUGAPI) << "Reset DAC \"" << dac1name << "\" to original value " << static_cast<int>(oldDac1Value);
869  LOG(logDEBUGAPI) << "Reset DAC \"" << dac2name << "\" to original value " << static_cast<int>(oldDac2Value);
870  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac1register,oldDac1Value);
871  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac2register,oldDac2Value);
872  }
873 
874  return result;
875 }
876 
877 
878 std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > pxarCore::getPulseheightVsDACDAC(std::string dac1name, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
879 
880  // No step size provided - scanning all DACs with step size 1:
881  return getPulseheightVsDACDAC(dac1name, 1, dac1min, dac1max, dac2name, 1, dac2min, dac2max, flags, nTriggers);
882 }
883 
884 std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > pxarCore::getPulseheightVsDACDAC(std::string dac1name, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
885 
886  if(!status()) {return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();}
887 
888  // Check DAC ranges
889  if(dac1min > dac1max) {
890  // Swapping the range:
891  LOG(logWARNING) << "Swapping upper and lower bound.";
892  uint8_t temp = dac1min;
893  dac1min = dac1max;
894  dac1max = temp;
895  }
896  if(dac2min > dac2max) {
897  // Swapping the range:
898  LOG(logWARNING) << "Swapping upper and lower bound.";
899  uint8_t temp = dac2min;
900  dac2min = dac2max;
901  dac2max = temp;
902  }
903 
904  // Get the register number and check the range from dictionary:
905  uint8_t dac1register, dac2register;
906  if(!verifyRegister(dac1name, dac1register, dac1max, ROC_REG)) {
907  return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();
908  }
909  if(!verifyRegister(dac2name, dac2register, dac2max, ROC_REG)) {
910  return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();
911  }
912 
913  // Setup the correct _hal calls for this test
914  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacDacScan;
915  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacDacScan;
916  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsDacDacScan;
917  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsDacDacScan;
918 
919  // Load the test parameters into vector
920  std::vector<int32_t> param;
921  param.push_back(static_cast<int32_t>(dac1register));
922  param.push_back(static_cast<int32_t>(dac1min));
923  param.push_back(static_cast<int32_t>(dac1max));
924  param.push_back(static_cast<int32_t>(dac2register));
925  param.push_back(static_cast<int32_t>(dac2min));
926  param.push_back(static_cast<int32_t>(dac2max));
927  param.push_back(static_cast<int32_t>(flags));
928  param.push_back(static_cast<int32_t>(nTriggers));
929  param.push_back(static_cast<int32_t>(dac1step));
930  param.push_back(static_cast<int32_t>(dac2step));
931 
932  // check if the flags indicate that the user explicitly asks for serial execution of test:
933  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
934  // repack data into the expected return format
935  std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > result = repackDacDacScanData(data,dac1step,dac1min,dac1max,dac2step,dac2min,dac2max,nTriggers,flags,false);
936 
937  // Reset the original value for the scanned DAC:
938  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
939  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
940  uint8_t oldDac1Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac1name);
941  uint8_t oldDac2Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac2name);
942  LOG(logDEBUGAPI) << "Reset DAC \"" << dac1name << "\" to original value " << static_cast<int>(oldDac1Value);
943  LOG(logDEBUGAPI) << "Reset DAC \"" << dac2name << "\" to original value " << static_cast<int>(oldDac2Value);
944  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac1register,oldDac1Value);
945  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac2register,oldDac2Value);
946  }
947 
948  return result;
949 }
950 
951 std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > pxarCore::getEfficiencyVsDACDAC(std::string dac1name, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
952 
953  // No step size provided - scanning all DACs with step size 1:
954  return getEfficiencyVsDACDAC(dac1name, 1, dac1min, dac1max, dac2name, 1, dac2min, dac2max, flags, nTriggers);
955 }
956 
957 std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > pxarCore::getEfficiencyVsDACDAC(std::string dac1name, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers) {
958 
959  if(!status()) {return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();}
960 
961  // Check DAC ranges
962  if(dac1min > dac1max) {
963  // Swapping the range:
964  LOG(logWARNING) << "Swapping upper and lower bound.";
965  uint8_t temp = dac1min;
966  dac1min = dac1max;
967  dac1max = temp;
968  }
969  if(dac2min > dac2max) {
970  // Swapping the range:
971  LOG(logWARNING) << "Swapping upper and lower bound.";
972  uint8_t temp = dac2min;
973  dac2min = dac2max;
974  dac2max = temp;
975  }
976 
977  // Get the register number and check the range from dictionary:
978  uint8_t dac1register, dac2register;
979  if(!verifyRegister(dac1name, dac1register, dac1max, ROC_REG)) {
980  return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();
981  }
982  if(!verifyRegister(dac2name, dac2register, dac2max, ROC_REG)) {
983  return std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > >();
984  }
985 
986  // Setup the correct _hal calls for this test
987  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacDacScan;
988  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacDacScan;
989  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsDacDacScan;
990  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsDacDacScan;
991 
992  // Load the test parameters into vector
993  std::vector<int32_t> param;
994  param.push_back(static_cast<int32_t>(dac1register));
995  param.push_back(static_cast<int32_t>(dac1min));
996  param.push_back(static_cast<int32_t>(dac1max));
997  param.push_back(static_cast<int32_t>(dac2register));
998  param.push_back(static_cast<int32_t>(dac2min));
999  param.push_back(static_cast<int32_t>(dac2max));
1000  param.push_back(static_cast<int32_t>(flags));
1001  param.push_back(static_cast<int32_t>(nTriggers));
1002  param.push_back(static_cast<int32_t>(dac1step));
1003  param.push_back(static_cast<int32_t>(dac2step));
1004 
1005  // check if the flags indicate that the user explicitly asks for serial execution of test:
1006  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
1007  // repack data into the expected return format
1008  std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > result = repackDacDacScanData(data,dac1step,dac1min,dac1max,dac2step,dac2min,dac2max,nTriggers,flags,true);
1009 
1010  // Reset the original value for the scanned DAC:
1011  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
1012  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
1013  uint8_t oldDac1Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac1name);
1014  uint8_t oldDac2Value = _dut->getDAC(static_cast<size_t>(rocit - enabledRocs.begin()),dac2name);
1015  LOG(logDEBUGAPI) << "Reset DAC \"" << dac1name << "\" to original value " << static_cast<int>(oldDac1Value);
1016  LOG(logDEBUGAPI) << "Reset DAC \"" << dac2name << "\" to original value " << static_cast<int>(oldDac2Value);
1017  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac1register,oldDac1Value);
1018  _hal->rocSetDAC(static_cast<uint8_t>(rocit - enabledRocs.begin()),dac2register,oldDac2Value);
1019  }
1020 
1021  return result;
1022 }
1023 
1024 std::vector<pixel> pxarCore::getPulseheightMap(uint16_t flags, uint16_t nTriggers) {
1025 
1026  if(!status()) {return std::vector<pixel>();}
1027 
1028  // Setup the correct _hal calls for this test
1029  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelCalibrate;
1030  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelCalibrate;
1031  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsCalibrate;
1032  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsCalibrate;
1033 
1034  // Load the test parameters into vector
1035  std::vector<int32_t> param;
1036  param.push_back(static_cast<int32_t>(flags));
1037  param.push_back(static_cast<int32_t>(nTriggers));
1038 
1039  // check if the flags indicate that the user explicitly asks for serial execution of test:
1040  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
1041 
1042  // Repacking of all data segments into one long map vector:
1043  std::vector<pixel> result = repackMapData(data, nTriggers, flags,false);
1044 
1045  return result;
1046 }
1047 
1048 std::vector<pixel> pxarCore::getEfficiencyMap(uint16_t flags, uint16_t nTriggers) {
1049 
1050  if(!status()) {return std::vector<pixel>();}
1051 
1052  // Setup the correct _hal calls for this test
1053  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelCalibrate;
1054  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelCalibrate;
1055  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsCalibrate;
1056  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsCalibrate;
1057 
1058  // Load the test parameters into vector
1059  std::vector<int32_t> param;
1060  param.push_back(static_cast<int32_t>(flags));
1061  param.push_back(static_cast<int32_t>(nTriggers));
1062 
1063  // check if the flags indicate that the user explicitly asks for serial execution of test:
1064  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
1065 
1066  // Repacking of all data segments into one long map vector:
1067  std::vector<pixel> result = repackMapData(data, nTriggers, flags, true);
1068 
1069  return result;
1070 }
1071 
1072 std::vector<pixel> pxarCore::getThresholdMap(std::string dacName, uint16_t flags, uint16_t nTriggers) {
1073  // Get the full DAC range for scanning:
1074  uint8_t dacMin = 0;
1075  uint8_t dacMax = getDACRange(dacName);
1076  uint8_t dacStep = 1;
1077  return getThresholdMap(dacName, dacStep, dacMin, dacMax, flags, nTriggers);
1078 }
1079 
1080 std::vector<pixel> pxarCore::getThresholdMap(std::string dacName, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers) {
1081  // No threshold level provided - set threshold to 50%:
1082  uint8_t threshold = 50;
1083  return getThresholdMap(dacName, dacStep, dacMin, dacMax, threshold, flags, nTriggers);
1084 }
1085 
1086 std::vector<pixel> pxarCore::getThresholdMap(std::string dacName, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint8_t threshold, uint16_t flags, uint16_t nTriggers) {
1087 
1088  if(!status()) {return std::vector<pixel>();}
1089 
1090  // Scan the maximum DAC range for threshold:
1091  uint8_t dacRegister;
1092  if(!verifyRegister(dacName, dacRegister, dacMax, ROC_REG)) {
1093  return std::vector<pixel>();
1094  }
1095 
1096  // Check the threshold percentage level provided:
1097  if(threshold == 0 || threshold > 100) {
1098  LOG(logCRITICAL) << "Threshold level of " << static_cast<int>(threshold) << "% is not possible!";
1099  return std::vector<pixel>();
1100  }
1101 
1102  // Setup the correct _hal calls for this test, a threshold map is a 1D dac scan:
1103  HalMemFnPixelSerial pixelfn = &hal::SingleRocOnePixelDacScan;
1104  HalMemFnPixelParallel multipixelfn = &hal::MultiRocOnePixelDacScan;
1105  HalMemFnRocSerial rocfn = &hal::SingleRocAllPixelsDacScan;
1106  HalMemFnRocParallel multirocfn = &hal::MultiRocAllPixelsDacScan;
1107 
1108  // Load the test parameters into vector
1109  std::vector<int32_t> param;
1110  param.push_back(static_cast<int32_t>(dacRegister));
1111  param.push_back(static_cast<int32_t>(dacMin));
1112  param.push_back(static_cast<int32_t>(dacMax));
1113  param.push_back(static_cast<int32_t>(flags));
1114  param.push_back(static_cast<int32_t>(nTriggers));
1115  param.push_back(static_cast<int32_t>(dacStep));
1116 
1117  // check if the flags indicate that the user explicitly asks for serial execution of test:
1118  std::vector<Event*> data = expandLoop(pixelfn, multipixelfn, rocfn, multirocfn, param, flags);
1119 
1120  // Repacking of all data segments into one long map vector:
1121  std::vector<pixel> result = repackThresholdMapData(data, dacStep, dacMin, dacMax, threshold, nTriggers, flags);
1122 
1123  return result;
1124 }
1125 
1126 std::vector<std::vector<uint16_t> > pxarCore::daqGetReadback() {
1127 
1128  std::vector<std::vector<uint16_t> > values;
1129  if(!status()) { return values; }
1130 
1131  values = _hal->daqReadback();
1132  LOG(logDEBUGAPI) << "Decoders provided readback values for " << values.size() << " ROCs.";
1133  return values;
1134 }
1135 
1136 
1137 // DAQ functions
1138 
1140  return daqStart(_daq_buffersize,true);
1141 }
1142 
1143 bool pxarCore::daqStart(const int buffersize, const bool init) {
1144 
1145  if(!status()) {return false;}
1146  if(daqStatus()) {return false;}
1147 
1148  // Clearing previously initialized DAQ sessions:
1149  _hal->daqClear();
1150 
1151  // Check requested buffer size:
1152  if(buffersize > DTB_SOURCE_BUFFER_SIZE) {
1153  LOG(logWARNING) << "Requested buffer size too large, setting to max. " \
1154  << DTB_SOURCE_BUFFER_SIZE;
1155  _daq_buffersize = DTB_SOURCE_BUFFER_SIZE;
1156  }
1157  else { _daq_buffersize = buffersize; }
1158 
1159 
1160  LOG(logDEBUGAPI) << "Starting new DAQ session...";
1161 
1162  // Check if we want to program the DUT or just leave it:
1163  if(init) {
1164  // Setup the configured mask and trim state of the DUT:
1165  MaskAndTrim(true);
1166 
1167  // Set Calibrate bits in the PUCs (we use the testrange for that):
1168  SetCalibrateBits(true);
1169 
1170  // Attaching all columns to the readout:
1171  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
1172  _hal->AllColumnsSetEnable(rocit->i2c_address,true);
1173  }
1174  }
1175  else if(!_daq_startstop_warning){
1176  LOG(logWARNING) << "Not unmasking DUT, not setting Calibrate bits!";
1177  _daq_startstop_warning = true;
1178  }
1179 
1180  // Check the DUT if we have TBMs enabled or not and choose the right deserializer:
1181  uint8_t type = 0x0;
1182  if(!_dut->tbm.empty()) { type = _dut->tbm.at(0).type; }
1183 
1184  // And start the DAQ session:
1185  _hal->daqStart(_dut->sig_delays[SIG_DESER160PHASE],type,buffersize);
1186 
1187  _daq_running = true;
1188  return true;
1189 }
1190 
1192 {
1193 
1194  uint8_t perFull;
1195 
1196  return daqStatus(perFull);
1197 
1198 }
1199 
1200 bool pxarCore::daqStatus(uint8_t & perFull) {
1201 
1202  // Check if a DAQ session is running:
1203  if(!_daq_running) {
1204  LOG(logDEBUGAPI) << "DAQ not running!";
1205  return false;
1206  }
1207 
1208  // Check if we still have enough buffer memory left (with some safety margin).
1209  // Only filling buffer up to 90% in order not to lose data.
1210  uint32_t filled_buffer = _hal->daqBufferStatus();
1211  perFull = static_cast<uint8_t>(static_cast<float>(filled_buffer)/_daq_buffersize*100.0);
1212  if(filled_buffer > 0.9*_daq_buffersize) {
1213  LOG(logWARNING) << "DAQ buffer about to overflow!";
1214  return false;
1215  }
1216 
1217  LOG(logDEBUGAPI) << "Everything alright, buffer size " << filled_buffer
1218  << "/" << _daq_buffersize;
1219  return true;
1220 }
1221 
1222 uint16_t pxarCore::daqTrigger(uint32_t nTrig, uint16_t period) {
1223 
1224  if(!daqStatus()) { return 0; }
1225  // Pattern Generator loop doesn't work for delay periods smaller than
1226  // the pattern generator duration, so limit it to that:
1227  if(period < _dut->pg_sum) {
1228  period = _dut->pg_sum;
1229  LOG(logWARNING) << "Loop period setting too small for configured "
1230  << "Pattern generator. "
1231  << "Forcing loop delay to " << period << " clk";
1232  LOG(logWARNING) << "To suppress this warning supply a larger delay setting";
1233  }
1234  // Just passing the call to the HAL, not doing anything else here:
1235  _hal->daqTrigger(nTrig,period);
1236  return period;
1237 }
1238 
1239 uint16_t pxarCore::daqTriggerLoop(uint16_t period) {
1240 
1241  if(!daqStatus()) { return 0; }
1242 
1243  // Pattern Generator loop doesn't work for delay periods smaller than
1244  // the pattern generator duration, so limit it to that:
1245  if(period < _dut->pg_sum) {
1246  period = _dut->pg_sum;
1247  LOG(logWARNING) << "Loop period setting too small for configured "
1248  << "Pattern generator. "
1249  << "Forcing loop delay to " << period << " clk";
1250  LOG(logWARNING) << "To suppress this warning supply a larger delay setting";
1251  }
1252  _hal->daqTriggerLoop(period);
1253  LOG(logDEBUGAPI) << "Loop period set to " << period << " clk";
1254  return period;
1255 }
1256 
1258 
1259  // Just halt the pattern generator loop:
1260  _hal->daqTriggerLoopHalt();
1261 }
1262 
1263 std::vector<uint16_t> pxarCore::daqGetBuffer() {
1264 
1265  // Reading out all data from the DTB and returning the raw blob.
1266  std::vector<uint16_t> buffer = _hal->daqBuffer();
1267  return buffer;
1268 }
1269 
1270 std::vector<rawEvent> pxarCore::daqGetRawEventBuffer() {
1271 
1272  // Reading out all data from the DTB and returning the raw blob.
1273  // Select the right readout channels depending on the number of TBMs
1274  std::vector<rawEvent> data = std::vector<rawEvent>();
1275  std::vector<rawEvent*> buffer = _hal->daqAllRawEvents();
1276 
1277  // Dereference all vector entries and give data back:
1278  for(std::vector<rawEvent*>::iterator it = buffer.begin(); it != buffer.end(); ++it) {
1279  data.push_back(**it);
1280  delete *it;
1281  }
1282  return data;
1283 }
1284 
1285 std::vector<Event> pxarCore::daqGetEventBuffer() {
1286 
1287  // Reading out all data from the DTB and returning the decoded Event buffer.
1288  // Select the right readout channels depending on the number of TBMs
1289  std::vector<Event> data = std::vector<Event>();
1290  std::vector<Event*> buffer = _hal->daqAllEvents();
1291 
1292  // Dereference all vector entries and give data back:
1293  for(std::vector<Event*>::iterator it = buffer.begin(); it != buffer.end(); ++it) {
1294  data.push_back(**it);
1295  delete *it;
1296  }
1297  return data;
1298 }
1299 
1301 
1302  // Check DAQ status:
1303  if(!daqStatus()) { return Event(); }
1304 
1305  // Return the next decoded Event from the FIFO buffer:
1306  Event * evt = _hal->daqEvent();
1307  Event ret = *evt;
1308  delete evt;
1309  return ret;
1310 }
1311 
1313 
1314  // Check DAQ status:
1315  if(!daqStatus()) { return rawEvent(); }
1316 
1317  // Return the next raw data record from the FIFO buffer:
1318  rawEvent * evt = _hal->daqRawEvent();
1319  rawEvent ret = *evt;
1320  delete evt;
1321  return ret;
1322 }
1323 
1325  return daqStop(true);
1326 }
1327 
1328 bool pxarCore::daqStop(const bool init) {
1329 
1330  if(!status()) {return false;}
1331  if(!_daq_running) {
1332  LOG(logINFO) << "No DAQ running, not executing daqStop command.";
1333  return false;
1334  }
1335 
1336  _daq_running = false;
1337 
1338  // Stop all active DAQ channels:
1339  _hal->daqStop();
1340 
1341  // If the init flag is set, mask and clear the DUT again:
1342  if(init) {
1343  // Mask all pixels in the device again:
1344  MaskAndTrim(false);
1345 
1346  // Reset all the Calibrate bits and signals:
1347  SetCalibrateBits(false);
1348 
1349  // Detaching all columns to the readout:
1350  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
1351  _hal->AllColumnsSetEnable(rocit->i2c_address,false);
1352  }
1353  }
1354  else if(!_daq_startstop_warning){
1355  LOG(logWARNING) << "Not unmasking DUT, not setting Calibrate bits!";
1356  _daq_startstop_warning = true;
1357  }
1358 
1359  return true;
1360 }
1361 
1362 
1363 std::vector<Event*> pxarCore::expandLoop(HalMemFnPixelSerial pixelfn, HalMemFnPixelParallel multipixelfn, HalMemFnRocSerial rocfn, HalMemFnRocParallel multirocfn, std::vector<int32_t> param, uint16_t flags) {
1364 
1365  // pointer to vector to hold our data
1366  std::vector<Event*> data = std::vector<Event*>();
1367 
1368  // Start test timer:
1369  timer t;
1370 
1371  // Check if all pixels are configured the same way on all ROCs. If this is not the case, we need to run this in FLAG_FORCE_SERIAL mode:
1372  std::vector<uint8_t> enabledRocs = _dut->getEnabledRocIDs();
1373  for(std::vector<uint8_t>::iterator rc = enabledRocs.begin(); rc != enabledRocs.end(); ++rc) {
1374  // Compare the configuration of the first ROC with all others:
1375  if(!comparePixelConfiguration(_dut->getEnabledPixels(enabledRocs.at(0)),_dut->getEnabledPixels(*rc))) {
1376  flags |= FLAG_FORCE_SERIAL;
1377  LOG(logDEBUGAPI) << "Not all ROCs have their pixels configured the same way. "
1378  << "Running in FLAG_FORCE_SERIAL mode.";
1379  break;
1380  }
1381  }
1382 
1383  // Do the masking/unmasking&trimming for all ROCs first.
1384  // Unless we are running in FLAG_FORCE_UNMASKED mode, we need to transmit the new trim values to the NIOS core and mask the whole DUT:
1385  if((flags & FLAG_FORCE_UNMASKED) == 0) {
1386  MaskAndTrimNIOS();
1387  MaskAndTrim(false);
1388  }
1389  // If we run in FLAG_FORCE_SERIAL mode, mask the whole DUT:
1390  else if((flags & FLAG_FORCE_SERIAL) != 0) { MaskAndTrim(false); }
1391  // Else just trim all the pixels:
1392  else { MaskAndTrim(true); }
1393 
1394  // Check if we might use parallel routine on whole module: more than one ROC
1395  // must be enabled and parallel execution not disabled by user
1396  if ((_dut->getNEnabledRocs() > 1) && ((flags & FLAG_FORCE_SERIAL) == 0)) {
1397 
1398  // Get the I2C addresses for all enabled ROCs from the config:
1399  std::vector<uint8_t> rocs_i2c = _dut->getEnabledRocI2Caddr();
1400 
1401  // Check if all pixels are enabled:
1402  if (_dut->getAllPixelEnable() && multirocfn != NULL) {
1403  LOG(logDEBUGAPI) << "\"The Loop\" contains one call to \'multirocfn\'";
1404 
1405  // execute call to HAL layer routine
1406  data = CALL_MEMBER_FN(*_hal,multirocfn)(rocs_i2c, param);
1407  } // ROCs parallel
1408  // Otherwise call the Pixel Parallel function several times:
1409  else if (multipixelfn != NULL) {
1410 
1411  // Get one of the enabled ROCs:
1412  std::vector<uint8_t> enabledRocs = _dut->getEnabledRocIDs();
1413  std::vector<Event*> rocdata = std::vector<Event*>();
1414  std::vector<pixelConfig> enabledPixels = _dut->getEnabledPixels(enabledRocs.front());
1415 
1416  LOG(logDEBUGAPI) << "\"The Loop\" contains "
1417  << enabledPixels.size() << " calls to \'multipixelfn\'";
1418 
1419  for (std::vector<pixelConfig>::iterator px = enabledPixels.begin(); px != enabledPixels.end(); ++px) {
1420  // execute call to HAL layer routine and store data in buffer
1421  std::vector<Event*> buffer = CALL_MEMBER_FN(*_hal,multipixelfn)(rocs_i2c, px->column(), px->row(), param);
1422 
1423  // merge pixel data into roc data storage vector
1424  if (rocdata.empty()){
1425  rocdata = buffer; // for first time call
1426  } else {
1427  // Add buffer vector to the end of existing Event data:
1428  rocdata.reserve(rocdata.size() + buffer.size());
1429  rocdata.insert(rocdata.end(), buffer.begin(), buffer.end());
1430  }
1431  } // pixel loop
1432  // append rocdata to main data storage vector
1433  if (data.empty()) data = rocdata;
1434  else {
1435  data.reserve(data.size() + rocdata.size());
1436  data.insert(data.end(), rocdata.begin(), rocdata.end());
1437  }
1438  } // Pixels parallel
1439  } // Parallel functions
1440 
1441  // Either we only have one ROC enabled or we force serial test execution:
1442  else {
1443 
1444  // -> single ROC / ROC-by-ROC operation
1445  // check if all pixels are enabled
1446  // if so, use routine that accesses whole ROC
1447  if (_dut->getAllPixelEnable() && rocfn != NULL){
1448 
1449  // loop over all enabled ROCs
1450  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
1451 
1452  LOG(logDEBUGAPI) << "\"The Loop\" contains " << enabledRocs.size() << " calls to \'rocfn\'";
1453 
1454  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit) {
1455 
1456  // If we have serial execution make sure to trim the ROC if we requested forceUnmasked:
1457  if(((flags & FLAG_FORCE_SERIAL) != 0) && ((flags & FLAG_FORCE_UNMASKED) != 0)) { MaskAndTrim(true,rocit); }
1458 
1459  // execute call to HAL layer routine and save returned data in buffer
1460  std::vector<Event*> rocdata = CALL_MEMBER_FN(*_hal,rocfn)(rocit->i2c_address, param);
1461  // append rocdata to main data storage vector
1462  if (data.empty()) data = rocdata;
1463  else {
1464  data.reserve(data.size() + rocdata.size());
1465  data.insert(data.end(), rocdata.begin(), rocdata.end());
1466  }
1467  } // roc loop
1468  }
1469  else if (pixelfn != NULL) {
1470 
1471  // -> we operate on single pixels
1472  // loop over all enabled ROCs
1473  std::vector<rocConfig> enabledRocs = _dut->getEnabledRocs();
1474 
1475  LOG(logDEBUGAPI) << "\"The Loop\" contains " << enabledRocs.size() << " enabled ROCs.";
1476 
1477  for (std::vector<rocConfig>::iterator rocit = enabledRocs.begin(); rocit != enabledRocs.end(); ++rocit){
1478  std::vector<Event*> rocdata = std::vector<Event*>();
1479  std::vector<pixelConfig> enabledPixels = _dut->getEnabledPixels(static_cast<uint8_t>(rocit - enabledRocs.begin()));
1480 
1481 
1482  LOG(logDEBUGAPI) << "\"The Loop\" for the current ROC contains " \
1483  << enabledPixels.size() << " calls to \'pixelfn\'";
1484 
1485  for (std::vector<pixelConfig>::iterator pixit = enabledPixels.begin(); pixit != enabledPixels.end(); ++pixit) {
1486  // execute call to HAL layer routine and store data in buffer
1487  std::vector<Event*> buffer = CALL_MEMBER_FN(*_hal,pixelfn)(rocit->i2c_address, pixit->column(), pixit->row(), param);
1488  // merge pixel data into roc data storage vector
1489  if (rocdata.empty()){
1490  rocdata = buffer; // for first time call
1491  } else {
1492  // Add buffer vector to the end of existing Event data:
1493  rocdata.reserve(rocdata.size() + buffer.size());
1494  rocdata.insert(rocdata.end(), buffer.begin(), buffer.end());
1495  }
1496  } // pixel loop
1497  // append rocdata to main data storage vector
1498  if (data.empty()) data = rocdata;
1499  else {
1500  data.reserve(data.size() + rocdata.size());
1501  data.insert(data.end(), rocdata.begin(), rocdata.end());
1502  }
1503  } // roc loop
1504  }// single pixel fnc
1505  else {
1506  LOG(logCRITICAL) << "LOOP EXPANSION FAILED -- NO MATCHING FUNCTION TO CALL?!";
1507  // do NOT throw an exception here: this is not a runtime problem
1508  // but can only be a bug in the code -> this could not be handled by unwinding the stack
1509 
1510  // Mask device, clear leftover calibrate signals:
1511  MaskAndTrim(false);
1512  SetCalibrateBits(false);
1513  return data;
1514  }
1515  } // single roc fnc
1516 
1517  // check that we ended up with data
1518  if (data.empty()){
1519  LOG(logCRITICAL) << "NO DATA FROM TEST FUNCTION -- are any TBMs/ROCs/PIXs enabled?!";
1520  // Mask device, clear leftover calibrate signals:
1521  MaskAndTrim(false);
1522  SetCalibrateBits(false);
1523  return data;
1524  }
1525 
1526  // Test is over, mask the whole device again and clear leftover calibrate signals:
1527  MaskAndTrim(false);
1528  SetCalibrateBits(false);
1529 
1530  // Print timer value:
1531  LOG(logINFO) << "Test took " << t << "ms.";
1532 
1533  return data;
1534 } // expandLoop()
1535 
1536 
1537 std::vector<Event*> pxarCore::condenseTriggers(std::vector<Event*> data, uint16_t nTriggers, bool efficiency) {
1538 
1539  std::vector<Event*> packed;
1540 
1541  if(data.size()%nTriggers != 0) {
1542  LOG(logCRITICAL) << "Data size does not correspond to " << nTriggers << " triggers! Aborting data processing!";
1543  return packed;
1544  }
1545 
1546  for(std::vector<Event*>::iterator Eventit = data.begin(); Eventit!= data.end(); Eventit += nTriggers) {
1547 
1548  Event * evt = new Event();
1549  std::map<pixel,uint16_t> pxcount = std::map<pixel,uint16_t>();
1550  std::map<pixel,double> pxmean = std::map<pixel,double>();
1551  std::map<pixel,double> pxm2 = std::map<pixel,double>();
1552 
1553  for(std::vector<Event*>::iterator it = Eventit; it != Eventit+nTriggers; ++it) {
1554 
1555  // Loop over all contained pixels:
1556  for(std::vector<pixel>::iterator pixit = (*it)->pixels.begin(); pixit != (*it)->pixels.end(); ++pixit) {
1557 
1558  // Check if we have that particular pixel already in:
1559  std::vector<pixel>::iterator px = std::find_if(evt->pixels.begin(),
1560  evt->pixels.end(),
1561  findPixelXY(pixit->column(), pixit->row(), pixit->roc()));
1562  // Pixel is known:
1563  if(px != evt->pixels.end()) {
1564  if(efficiency) { px->setValue(px->value()+1); }
1565  else {
1566  // Calculate the variance incrementally:
1567  double delta = pixit->value() - pxmean[*px];
1568  pxmean[*px] += delta/pxcount[*px];
1569  pxm2[*px] += delta*(pixit->value() - pxmean[*px]);
1570  pxcount[*px]++;
1571  }
1572  }
1573  // Pixel is new:
1574  else {
1575  if(efficiency) { pixit->setValue(1); }
1576  else {
1577  // Initialize counters and temporary variables:
1578  pxcount.insert(std::make_pair(*pixit,1));
1579  pxmean.insert(std::make_pair(*pixit,pixit->value()));
1580  pxm2.insert(std::make_pair(*pixit,0));
1581  }
1582  evt->pixels.push_back(*pixit);
1583  }
1584  }
1585 
1586  // Delete the original data, not needed anymore:
1587  delete *it;
1588  }
1589 
1590  // Calculate mean and variance for the pulse height depending on the
1591  // number of triggers received:
1592  if(!efficiency) {
1593  for(std::vector<pixel>::iterator px = evt->pixels.begin(); px != evt->pixels.end(); ++px) {
1594  px->setValue(pxmean[*px]); // The mean
1595  px->setVariance(pxm2[*px]/(pxcount[*px] - 1)); // The variance
1596  }
1597  }
1598  packed.push_back(evt);
1599  }
1600 
1601  return packed;
1602 }
1603 
1604 std::vector<pixel> pxarCore::repackMapData (std::vector<Event*> data, uint16_t nTriggers, uint16_t flags, bool efficiency) {
1605 
1606  // Keep track of the pixel to be expected:
1607  uint8_t expected_column = 0, expected_row = 0;
1608 
1609  std::vector<pixel> result;
1610  LOG(logDEBUGAPI) << "Simple Map Repack of " << data.size() << " data blocks, returning " << (efficiency ? "efficiency" : "averaged pulse height") << ".";
1611 
1612  // Measure time:
1613  timer t;
1614 
1615  // First reduce triggers, we have #nTriggers Events which belong together:
1616  std::vector<Event*> packed = condenseTriggers(data, nTriggers, efficiency);
1617 
1618  // Loop over all Events we have:
1619  for(std::vector<Event*>::iterator Eventit = packed.begin(); Eventit!= packed.end(); ++Eventit) {
1620 
1621  // For every Event, loop over all contained pixels:
1622  for(std::vector<pixel>::iterator pixit = (*Eventit)->pixels.begin(); pixit != (*Eventit)->pixels.end(); ++pixit) {
1623  // Check for pulsed pixels being present:
1624  if((flags&FLAG_CHECK_ORDER) != 0) {
1625  if(pixit->column() != expected_column || pixit->row() != expected_row) {
1626 
1627  // With the full chip unmasked we want to know if the pixel in question was amongst the ones recorded:
1628  if((flags&FLAG_FORCE_UNMASKED) != 0) { LOG(logDEBUGPIPES) << "This is a background hit: " << (*pixit); }
1629  else {
1630  // With only the pixel in question unmasked we want to warn about other appeareances:
1631  LOG(logERROR) << "This pixel doesn't belong here: " << (*pixit) << ". Expected [" << static_cast<int>(expected_column) << "," << static_cast<int>(expected_row) << ",x]";
1632  }
1633 
1634  // Convention: set a negative pixel value for out-of-order pixel hits:
1635  pixit->setValue(-1*pixit->value());
1636  }
1637  }
1638  result.push_back(*pixit);
1639  } // loop over pixels
1640 
1641  if((flags&FLAG_CHECK_ORDER) != 0) {
1642  expected_row++;
1643  if(expected_row >= ROC_NUMROWS) { expected_row = 0; expected_column++; }
1644  if(expected_column >= ROC_NUMCOLS) { expected_row = 0; expected_column = 0; }
1645  }
1646  } // loop over Events
1647 
1648  // Sort the output map by ROC->col->row - just because we are so nice:
1649  if((flags&FLAG_NOSORT) == 0) { std::sort(result.begin(),result.end()); }
1650 
1651  // Cleanup temporary data:
1652  for(std::vector<Event*>::iterator it = packed.begin(); it != packed.end(); ++it) { delete *it; }
1653 
1654  LOG(logDEBUGAPI) << "Correctly repacked Map data for delivery.";
1655  LOG(logDEBUGAPI) << "Repacking took " << t << "ms.";
1656  return result;
1657 }
1658 
1659 std::vector< std::pair<uint8_t, std::vector<pixel> > > pxarCore::repackDacScanData (std::vector<Event*> data, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint16_t nTriggers, uint16_t /*flags*/, bool efficiency){
1660 
1661  std::vector< std::pair<uint8_t, std::vector<pixel> > > result;
1662 
1663  // Measure time:
1664  timer t;
1665 
1666  // First reduce triggers, we have #nTriggers Events which belong together:
1667  std::vector<Event*> packed = condenseTriggers(data, nTriggers, efficiency);
1668 
1669  if(packed.size() % static_cast<size_t>((dacMax-dacMin)/dacStep+1) != 0) {
1670  LOG(logCRITICAL) << "Data size not as expected! " << packed.size() << " data blocks do not fit to " << static_cast<int>((dacMax-dacMin)/dacStep+1) << " DAC values!";
1671  return result;
1672  }
1673 
1674  LOG(logDEBUGAPI) << "Packing DAC range " << static_cast<int>(dacMin) << " - " << static_cast<int>(dacMax) << " (step size " << static_cast<int>(dacStep) << "), data has " << packed.size() << " entries.";
1675 
1676  // Prepare the result vector
1677  for(size_t dac = dacMin; dac <= dacMax; dac += dacStep) { result.push_back(std::make_pair(dac,std::vector<pixel>())); }
1678 
1679  size_t currentDAC = dacMin;
1680  // Loop over the packed data and separate into DAC ranges, potentially several rounds:
1681  for(std::vector<Event*>::iterator Eventit = packed.begin(); Eventit!= packed.end(); ++Eventit) {
1682  if(currentDAC > dacMax) { currentDAC = dacMin; }
1683  result.at((currentDAC-dacMin)/dacStep).second.insert(result.at((currentDAC-dacMin)/dacStep).second.end(),
1684  (*Eventit)->pixels.begin(),
1685  (*Eventit)->pixels.end());
1686  currentDAC += dacStep;
1687  }
1688 
1689  // Cleanup temporary data:
1690  for(std::vector<Event*>::iterator it = packed.begin(); it != packed.end(); ++it) { delete *it; }
1691 
1692  LOG(logDEBUGAPI) << "Correctly repacked DacScan data for delivery.";
1693  LOG(logDEBUGAPI) << "Repacking took " << t << "ms.";
1694  return result;
1695 }
1696 
1697 std::vector<pixel> pxarCore::repackThresholdMapData (std::vector<Event*> data, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint8_t thresholdlevel, uint16_t nTriggers, uint16_t flags) {
1698 
1699  std::vector<pixel> result;
1700  // Vector of pixels for which a threshold has already been found
1701  std::vector<pixel> found;
1702 
1703  // Threshold is the the given efficiency level "thresholdlevel"
1704  // Using ceiling function to take higher threshold when in doubt.
1705  uint16_t threshold = static_cast<uint16_t>(ceil(static_cast<float>(nTriggers)*thresholdlevel/100));
1706  LOG(logDEBUGAPI) << "Scanning for threshold level " << threshold << ", "
1707  << ((flags&FLAG_RISING_EDGE) == 0 ? "falling":"rising") << " edge";
1708 
1709  // Measure time:
1710  timer t;
1711 
1712  // First, pack the data as it would be a regular Dac Scan:
1713  std::vector<std::pair<uint8_t,std::vector<pixel> > > packed_dac = repackDacScanData(data, dacStep, dacMin, dacMax, nTriggers, flags, true);
1714 
1715  // Efficiency map:
1716  std::map<pixel,uint8_t> oldvalue;
1717 
1718  // Then loop over all pixels and DAC settings, start from the back if we are looking for falling edge.
1719  // This ensures that we end up having the correct edge, even if the efficiency suddenly changes from 0 to max.
1720  std::vector<std::pair<uint8_t,std::vector<pixel> > >::iterator it_start;
1721  std::vector<std::pair<uint8_t,std::vector<pixel> > >::iterator it_end;
1722  int increase_op;
1723  if((flags&FLAG_RISING_EDGE) != 0) { it_start = packed_dac.begin(); it_end = packed_dac.end(); increase_op = 1; }
1724  else { it_start = packed_dac.end()-1; it_end = packed_dac.begin()-1; increase_op = -1; }
1725 
1726  for(std::vector<std::pair<uint8_t,std::vector<pixel> > >::iterator it = it_start; it != it_end; it += increase_op) {
1727  // For every DAC value, loop over all pixels:
1728  for(std::vector<pixel>::iterator pixit = it->second.begin(); pixit != it->second.end(); ++pixit) {
1729  // Check if for this pixel a threshold has been found already and we can skip the rest:
1730  std::vector<pixel>::iterator px_found = std::find_if(found.begin(),
1731  found.end(),
1732  findPixelXY(pixit->column(), pixit->row(), pixit->roc()));
1733  if(px_found != found.end()) continue;
1734 
1735  // Check if we have that particular pixel already in the result vector:
1736  std::vector<pixel>::iterator px = std::find_if(result.begin(),
1737  result.end(),
1738  findPixelXY(pixit->column(), pixit->row(), pixit->roc()));
1739 
1740  // Pixel is known:
1741  if(px != result.end()) {
1742  // Calculate efficiency deltas and slope:
1743  uint8_t delta_old = abs(oldvalue[*px] - threshold);
1744  uint8_t delta_new = abs(static_cast<uint8_t>(pixit->value()) - threshold);
1745  bool positive_slope = (static_cast<uint8_t>(pixit->value()) - oldvalue[*px] > 0 ? true : false);
1746 
1747  // Check which value is closer to the threshold. Only if the slope is positive AND
1748  // the new delta between value and threshold is *larger* then the old delta, we
1749  // found the threshold. If slope is negative, we just have a ripple in the DAC's
1750  // distribution:
1751  if(positive_slope && !(delta_new < delta_old)) {
1752  found.push_back(*pixit);
1753  continue;
1754  }
1755 
1756  // No threshold found yet, update the DAC threshold value for the pixel:
1757  px->setValue(it->first);
1758  // Update the oldvalue map:
1759  oldvalue[*px] = static_cast<uint8_t>(pixit->value());
1760  }
1761  // Pixel is new, just adding it:
1762  else {
1763  // If the pixel is above threshold at first appearance, the respective
1764  // DAC value is set as its threshold:
1765  if(pixit->value() >= threshold) { found.push_back(*pixit); }
1766 
1767  // Store the pixel with original efficiency
1768  oldvalue.insert(std::make_pair(*pixit,pixit->value()));
1769 
1770  // Push pixel to result vector with current DAC as value field:
1771  pixit->setValue(it->first);
1772  result.push_back(*pixit);
1773  }
1774  }
1775  }
1776 
1777  // Check for pixels that have not reached the threshold at all:
1778  for(std::vector<pixel>::iterator px = result.begin(); px != result.end(); ++px) {
1779  std::vector<pixel>::iterator px_found = std::find_if(found.begin(),
1780  found.end(),
1781  findPixelXY(px->column(), px->row(), px->roc()));
1782  // The pixel is in the "found" vector, which means it crossed threshold at some point:
1783  if(px_found != found.end()) continue;
1784 
1785  // The pixel is not in and never reached the threshold. We set the return value to
1786  // "dacMax" (rising edge) or "dacMin" (falling edge):
1787  if((flags&FLAG_RISING_EDGE) != 0) { px->setValue(dacMax); }
1788  else { px->setValue(dacMin); }
1789  LOG(logWARNING) << "No threshold found for " << (*px);
1790  }
1791 
1792  // Sort the output map by ROC->col->row - just because we are so nice:
1793  if((flags&FLAG_NOSORT) == 0) { std::sort(result.begin(),result.end()); }
1794 
1795  LOG(logDEBUGAPI) << "Correctly repacked&analyzed ThresholdMap data for delivery.";
1796  LOG(logDEBUGAPI) << "Repacking took " << t << "ms.";
1797  return result;
1798 }
1799 
1800 std::vector<std::pair<uint8_t,std::vector<pixel> > > pxarCore::repackThresholdDacScanData (std::vector<Event*> data, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint8_t thresholdlevel, uint16_t nTriggers, uint16_t flags) {
1801 
1802  std::vector<std::pair<uint8_t,std::vector<pixel> > > result;
1803  // Map of pixels with already assigned threshold (key is the dac2 value):
1804  std::map<uint8_t,std::vector<pixel> > found;
1805 
1806  // Threshold is the the given efficiency level "thresholdlevel":
1807  // Using ceiling function to take higher threshold when in doubt.
1808  uint16_t threshold = static_cast<uint16_t>(ceil(static_cast<float>(nTriggers)*thresholdlevel/100));
1809  LOG(logDEBUGAPI) << "Scanning for threshold level " << threshold << ", "
1810  << ((flags&FLAG_RISING_EDGE) == 0 ? "falling":"rising") << " edge";
1811 
1812  // Measure time:
1813  timer t;
1814 
1815  // First, pack the data as it would be a regular DacDac Scan:
1816  std::vector<std::pair<uint8_t,std::pair<uint8_t,std::vector<pixel> > > > packed_dacdac = repackDacDacScanData(data,dac1step,dac1min,dac1max,dac2step,dac2min,dac2max,nTriggers,flags,true);
1817 
1818  // Efficiency map:
1819  std::map<uint8_t,std::map<pixel,uint8_t> > oldvalue;
1820 
1821  // Then loop over all pixels and DAC settings, start from the back if we are looking for falling edge.
1822  // This ensures that we end up having the correct edge, even if the efficiency suddenly changes from 0 to max.
1823  std::vector<std::pair<uint8_t,std::pair<uint8_t,std::vector<pixel> > > >::iterator it_start;
1824  std::vector<std::pair<uint8_t,std::pair<uint8_t,std::vector<pixel> > > >::iterator it_end;
1825  int increase_op;
1826  if((flags&FLAG_RISING_EDGE) != 0) { it_start = packed_dacdac.begin(); it_end = packed_dacdac.end(); increase_op = 1; }
1827  else { it_start = packed_dacdac.end()-1; it_end = packed_dacdac.begin()-1; increase_op = -1; }
1828 
1829  for(std::vector<std::pair<uint8_t,std::pair<uint8_t,std::vector<pixel> > > >::iterator it = it_start; it != it_end; it += increase_op) {
1830 
1831  // For every DAC/DAC entry, loop over all pixels:
1832  for(std::vector<pixel>::iterator pixit = it->second.second.begin(); pixit != it->second.second.end(); ++pixit) {
1833 
1834  // Find the current DAC2 value in the result vector (simple replace for find_if):
1835  std::vector<std::pair<uint8_t, std::vector<pixel> > >::iterator dac;
1836  for(dac = result.begin(); dac != result.end(); ++dac) { if(it->second.first == dac->first) break; }
1837 
1838  // Didn't find the DAC2 value:
1839  if(dac == result.end()) {
1840  result.push_back(std::make_pair(it->second.first,std::vector<pixel>()));
1841  dac = result.end() - 1;
1842  // Also add an entry for bookkeeping:
1843  found.insert(std::make_pair(it->second.first,std::vector<pixel>()));
1844  oldvalue.insert(std::make_pair(it->second.first,std::map<pixel,uint8_t>()));
1845  }
1846 
1847  // Check if for this pixel a threshold has been found already and we can skip the rest:
1848  std::vector<pixel>::iterator px_found = std::find_if(found[dac->first].begin(),
1849  found[dac->first].end(),
1850  findPixelXY(pixit->column(), pixit->row(), pixit->roc()));
1851  if(px_found != found[dac->first].end()) continue;
1852 
1853  // Check if we have that particular pixel already in:
1854  std::vector<pixel>::iterator px = std::find_if(dac->second.begin(),
1855  dac->second.end(),
1856  findPixelXY(pixit->column(), pixit->row(), pixit->roc()));
1857 
1858  // Pixel is known:
1859  if(px != dac->second.end()) {
1860  // Calculate efficiency deltas and slope:
1861  uint8_t delta_old = abs(oldvalue[dac->first][*px] - threshold);
1862  uint8_t delta_new = abs(static_cast<uint8_t>(pixit->value()) - threshold);
1863  bool positive_slope = (static_cast<uint8_t>(pixit->value()) - oldvalue[dac->first][*px] > 0 ? true : false);
1864 
1865  // Check which value is closer to the threshold. Only if the slope is positive AND
1866  // the new delta between value and threshold is *larger* then the old delta, we
1867  // found the threshold. If slope is negative, we just have a ripple in the DAC's
1868  // distribution:
1869  if(positive_slope && !(delta_new < delta_old)) {
1870  found[dac->first].push_back(*pixit);
1871  continue;
1872  }
1873 
1874  // No threshold found yet, update the DAC threshold value for the pixel:
1875  px->setValue(it->first);
1876  // Update the oldvalue map:
1877  oldvalue[dac->first][*px] = static_cast<uint8_t>(pixit->value());
1878  }
1879  // Pixel is new, just adding it:
1880  else {
1881  // If the pixel is above threshold at first appearance, the respective
1882  // DAC value is set as its threshold:
1883  if(pixit->value() >= threshold) { found[dac->first].push_back(*pixit); }
1884 
1885  // Store the pixel with original efficiency
1886  oldvalue[dac->first].insert(std::make_pair(*pixit,pixit->value()));
1887  // Push pixel to result vector with current DAC as value field:
1888  pixit->setValue(it->first);
1889  dac->second.push_back(*pixit);
1890  }
1891  }
1892  }
1893 
1894  // Check for pixels that have not reached the threshold at all:
1895  for(std::vector<std::pair<uint8_t,std::vector<pixel> > >::iterator dac = result.begin(); dac != result.end(); ++dac) {
1896 
1897  for(std::vector<pixel>::iterator px = dac->second.begin(); px != dac->second.end(); px++) {
1898  std::vector<pixel>::iterator px_found = std::find_if(found[dac->first].begin(),
1899  found[dac->first].end(),
1900  findPixelXY(px->column(), px->row(), px->roc()));
1901  // The pixel is in the "found" vector, which means it crossed threshold at some point:
1902  if(px_found != found[dac->first].end()) continue;
1903 
1904  // The pixel is not in and never reached the threshold. We set the return value to
1905  // "dacMax" (rising edge) or "dacMin" (falling edge):
1906  if((flags&FLAG_RISING_EDGE) != 0) { px->setValue(dac2max); }
1907  else { px->setValue(dac2min); }
1908  LOG(logWARNING) << "No threshold found for " << (*px) << " at DAC value " << static_cast<int>(dac->first);
1909  }
1910  }
1911 
1912  // Sort the output map by DAC values and ROC->col->row - just because we are so nice:
1913  if((flags&FLAG_NOSORT) == 0) { std::sort(result.begin(),result.end()); }
1914 
1915  LOG(logDEBUGAPI) << "Correctly repacked&analyzed ThresholdDacScan data for delivery.";
1916  LOG(logDEBUGAPI) << "Repacking took " << t << "ms.";
1917  return result;
1918 }
1919 
1920 std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > pxarCore::repackDacDacScanData (std::vector<Event*> data, uint8_t dac1step, uint8_t dac1min, uint8_t dac1max, uint8_t dac2step, uint8_t dac2min, uint8_t dac2max, uint16_t nTriggers, uint16_t /*flags*/, bool efficiency) {
1921  std::vector< std::pair<uint8_t, std::pair<uint8_t, std::vector<pixel> > > > result;
1922 
1923  // Measure time:
1924  timer t;
1925 
1926  // First reduce triggers, we have #nTriggers Events which belong together:
1927  std::vector<Event*> packed = condenseTriggers(data, nTriggers, efficiency);
1928 
1929  if(packed.size() % static_cast<size_t>(((dac1max-dac1min)/dac1step+1)*((dac2max-dac2min)/dac2step+1)) != 0) {
1930  LOG(logCRITICAL) << "Data size not as expected! " << packed.size() << " data blocks do not fit to " << static_cast<int>(((dac1max-dac1min)/dac1step+1)*((dac2max-dac2min)/dac2step+1)) << " DAC values!";
1931  return result;
1932  }
1933 
1934  LOG(logDEBUGAPI) << "Packing DAC range [" << static_cast<int>(dac1min) << " - " << static_cast<int>(dac1max)
1935  << ", step size " << static_cast<int>(dac1step) << "]x["
1936  << static_cast<int>(dac2min) << " - " << static_cast<int>(dac2max)
1937  << ", step size " << static_cast<int>(dac2step)
1938  << "], data has " << packed.size() << " entries.";
1939 
1940  // Prepare the result vector
1941  for(size_t dac1 = dac1min; dac1 <= dac1max; dac1 += dac1step) {
1942  std::pair<uint8_t,std::vector<pixel> > dacpair;
1943  for(size_t dac2 = dac2min; dac2 <= dac2max; dac2 += dac2step) {
1944  dacpair = std::make_pair(dac2,std::vector<pixel>());
1945  result.push_back(std::make_pair(dac1,dacpair));
1946  }
1947  }
1948 
1949  size_t current1dac = dac1min;
1950  size_t current2dac = dac2min;
1951 
1952  // Loop over the packed data and separeate into DAC ranges, potentially several rounds:
1953  int i = 0;
1954  for(std::vector<Event*>::iterator Eventit = packed.begin(); Eventit!= packed.end(); ++Eventit) {
1955  if(current2dac > dac2max) {
1956  current2dac = dac2min;
1957  current1dac += dac1step;
1958  }
1959  if(current1dac > dac1max) { current1dac = dac1min; }
1960 
1961  result.at((current1dac-dac1min)/dac1step*((dac2max-dac2min)/dac2step+1) + (current2dac-dac2min)/dac2step).second.second.insert(result.at((current1dac-dac1min)/dac1step*((dac2max-dac2min)/dac2step+1) + (current2dac-dac2min)/dac2step).second.second.end(),
1962  (*Eventit)->pixels.begin(),
1963  (*Eventit)->pixels.end());
1964  i++;
1965  current2dac += dac2step;
1966  }
1967 
1968  // Cleanup temporary data:
1969  for(std::vector<Event*>::iterator it = packed.begin(); it != packed.end(); ++it) { delete *it; }
1970 
1971  LOG(logDEBUGAPI) << "Correctly repacked DacDacScan data for delivery.";
1972  LOG(logDEBUGAPI) << "Repacking took " << t << "ms.";
1973  return result;
1974 }
1975 
1976 // Update mask and trim bits for the full DUT in NIOS structs:
1977 void pxarCore::MaskAndTrimNIOS() {
1978 
1979  // First transmit all configured I2C addresses:
1980  _hal->SetupI2CValues(_dut->getRocI2Caddr());
1981 
1982  // Now run over all existing ROCs and transmit the pixel trim/mask data:
1983  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
1984  _hal->SetupTrimValues(rocit->i2c_address,rocit->pixels);
1985  }
1986 }
1987 
1988 // Mask/Unmask and trim all ROCs:
1989 void pxarCore::MaskAndTrim(bool trim) {
1990  // Run over all existing ROCs:
1991  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
1992  MaskAndTrim(trim,rocit);
1993  }
1994 }
1995 
1996 // Mask/Unmask and trim one ROC:
1997 void pxarCore::MaskAndTrim(bool trim, std::vector<rocConfig>::iterator rocit) {
1998 
1999  // This ROC is supposed to be trimmed as configured, so let's trim it:
2000  if(trim) {
2001  LOG(logDEBUGAPI) << "ROC@I2C " << static_cast<int>(rocit->i2c_address) << " features "
2002  << static_cast<int>(std::count_if(rocit->pixels.begin(),rocit->pixels.end(),configMaskSet(true)))
2003  << " masked pixels.";
2004  LOG(logDEBUGAPI) << "Unmasking and trimming ROC@I2C " << static_cast<int>(rocit->i2c_address) << " in one go.";
2005  _hal->RocSetMask(rocit->i2c_address,false,rocit->pixels);
2006  return;
2007  }
2008  else {
2009  LOG(logDEBUGAPI) << "Masking ROC@I2C " << static_cast<int>(rocit->i2c_address) << " in one go.";
2010  _hal->RocSetMask(rocit->i2c_address,true);
2011  return;
2012  }
2013 }
2014 
2015 // Program the calibrate bits in ROC PUCs:
2016 void pxarCore::SetCalibrateBits(bool enable) {
2017 
2018  // Run over all existing ROCs:
2019  for (std::vector<rocConfig>::iterator rocit = _dut->roc.begin(); rocit != _dut->roc.end(); ++rocit) {
2020 
2021  LOG(logDEBUGAPI) << "Configuring calibrate bits in all enabled PUCs of ROC@I2C " << static_cast<int>(rocit->i2c_address);
2022  // Check if the signal has to be turned on or off:
2023  if(enable) {
2024  // Loop over all pixels in this ROC and set the Cal bit:
2025  for(std::vector<pixelConfig>::iterator pxit = rocit->pixels.begin(); pxit != rocit->pixels.end(); ++pxit) {
2026  if(pxit->enable() == true) { _hal->PixelSetCalibrate(rocit->i2c_address,pxit->column(),pxit->row(),0); }
2027  }
2028 
2029  }
2030  // Clear the signal for the full ROC:
2031  else {_hal->RocClearCalibrate(rocit->i2c_address);}
2032  }
2033 }
2034 
2035 void pxarCore::checkTestboardDelays(std::vector<std::pair<std::string,uint8_t> > sig_delays) {
2036 
2037  // Take care of the signal delay settings:
2038  std::map<uint8_t,uint8_t> delays;
2039  for(std::vector<std::pair<std::string,uint8_t> >::iterator sigIt = sig_delays.begin(); sigIt != sig_delays.end(); ++sigIt) {
2040 
2041  // Fill the signal timing pairs with the register from the dictionary:
2042  uint8_t sigRegister, sigValue = sigIt->second;
2043  if(!verifyRegister(sigIt->first,sigRegister,sigValue,DTB_REG)) continue;
2044 
2045  std::pair<std::map<uint8_t,uint8_t>::iterator,bool> ret;
2046  ret = delays.insert( std::make_pair(sigRegister,sigValue) );
2047  if(ret.second == false) {
2048  LOG(logWARNING) << "Overwriting existing DTB delay setting \"" << sigIt->first
2049  << "\" value " << static_cast<int>(ret.first->second)
2050  << " with " << static_cast<int>(sigValue);
2051  delays[sigRegister] = sigValue;
2052  }
2053  }
2054  // Store these validated parameters in the DUT
2055  _dut->sig_delays = delays;
2056 }
2057 
2058 void pxarCore::checkTestboardPower(std::vector<std::pair<std::string,double> > power_settings) {
2059 
2060  // Read the power settings and make sure we got all, these here are the allowed limits:
2061  double va = 2.5, vd = 3.0, ia = 3.0, id = 3.0;
2062  for(std::vector<std::pair<std::string,double> >::iterator it = power_settings.begin(); it != power_settings.end(); ++it) {
2063  std::transform((*it).first.begin(), (*it).first.end(), (*it).first.begin(), ::tolower);
2064 
2065  if((*it).second < 0) {
2066  LOG(logERROR) << "Negative value for power setting \"" << (*it).first << "\". Using default limit.";
2067  continue;
2068  }
2069 
2070  if((*it).first.compare("va") == 0) {
2071  if((*it).second > va) { LOG(logWARNING) << "Limiting \"" << (*it).first << "\" to " << va; }
2072  else { va = (*it).second; }
2073  _dut->va = va;
2074  }
2075  else if((*it).first.compare("vd") == 0) {
2076  if((*it).second > vd) { LOG(logWARNING) << "Limiting \"" << (*it).first << "\" to " << vd; }
2077  else {vd = (*it).second; }
2078  _dut->vd = vd;
2079  }
2080  else if((*it).first.compare("ia") == 0) {
2081  if((*it).second > ia) { LOG(logWARNING) << "Limiting \"" << (*it).first << "\" to " << ia; }
2082  else { ia = (*it).second; }
2083  _dut->ia = ia;
2084  }
2085  else if((*it).first.compare("id") == 0) {
2086  if((*it).second > id) { LOG(logWARNING) << "Limiting \"" << (*it).first << "\" to " << id; }
2087  else { id = (*it).second; }
2088  _dut->id = id;
2089  }
2090  else { LOG(logERROR) << "Unknown power setting " << (*it).first << "! Skipping.";}
2091  }
2092 
2093  if(va < 0.01 || vd < 0.01 || ia < 0.01 || id < 0.01) {
2094  LOG(logCRITICAL) << "Power settings are not sufficient. Please check and re-configure!";
2095  throw InvalidConfig("Power settings are not sufficient. Please check and re-configure.");
2096  }
2097 }
2098 
2099 void pxarCore::verifyPatternGenerator(std::vector<std::pair<std::string,uint8_t> > &pg_setup) {
2100 
2101  std::vector<std::pair<uint16_t,uint8_t> > patterns;
2102 
2103  // Get the Pattern Generator dictionary for lookup:
2104  PatternGeneratorDictionary * _dict = PatternGeneratorDictionary::getInstance();
2105 
2106  // Check total length of the pattern generator:
2107  if(pg_setup.size() > 256) {
2108  LOG(logCRITICAL) << "Pattern too long (" << pg_setup.size() << " entries) for pattern generator. "
2109  << "Only 256 entries allowed!";
2110  throw InvalidConfig("Pattern too long for pattern generator. Please check and re-configure.");
2111  }
2112  else { LOG(logDEBUGAPI) << "Pattern generator setup with " << pg_setup.size() << " entries provided."; }
2113 
2114  // Some booleans to keep track of PG content:
2115  bool have_trigger = false;
2116  bool have_tbmreset = false;
2117 
2118  // Loop over all entries provided:
2119  for(std::vector<std::pair<std::string,uint8_t> >::iterator it = pg_setup.begin(); it != pg_setup.end(); ++it) {
2120 
2121  // Check for current element if delay is zero:
2122  if(it->second == 0 && it != pg_setup.end() -1 ) {
2123  LOG(logCRITICAL) << "Found delay = 0 on early entry! This stops the pattern generator at position "
2124  << static_cast<int>(it - pg_setup.begin()) << ".";
2125  throw InvalidConfig("Found delay = 0 on early entry! This stops the pattern generator.");
2126  }
2127 
2128  // Check last entry for PG stop signal (delay = 0):
2129  if(it == pg_setup.end() - 1 && it->second != 0) {
2130  LOG(logWARNING) << "No delay = 0 found on last entry. Setting last delay to 0 to stop the pattern generator.";
2131  it->second = 0;
2132  }
2133 
2134  // Convert the name to lower case for comparison:
2135  std::transform(it->first.begin(), it->first.end(), it->first.begin(), ::tolower);
2136 
2137  std::istringstream signals(it->first);
2138  std::string s;
2139  uint16_t signal = 0;
2140  // Tokenize the signal string into single PG signals, separated by ";":
2141  while (std::getline(signals, s, ';')) {
2142  // Get the signal from the dictionary object:
2143  uint16_t sig = _dict->getSignal(s);
2144  if(sig != PG_ERR) signal += sig;
2145  else {
2146  LOG(logCRITICAL) << "Could not find pattern generator signal \"" << s << "\" in the dictionary!";
2147  throw InvalidConfig("Wrong pattern generator signal provided.");
2148  }
2149 
2150  // Check for some specific signals:
2151  if(sig == PG_TRG) have_trigger = true;
2152  if(sig == PG_REST) have_tbmreset = true;
2153 
2154  LOG(logDEBUGAPI) << "Found PG signal " << s << " (" << std::hex << sig << std::dec << ")";
2155  }
2156  patterns.push_back(std::make_pair(signal,it->second));
2157  }
2158 
2159  // If there is no trigger, no data is requested and read out from any detector:
2160  if(!have_trigger) {
2161  LOG(logWARNING) << "Pattern generator does not contain a trigger signal. "
2162  << "No data is expected from the DUT!";
2163  }
2164  // If a TBM Reset is present the TBM event counter gets reset every cycle, so
2165  // we can't use the event id to check for missing events in the readout:
2166  if(have_tbmreset) {
2167  LOG(logWARNING) << "Pattern generator contains TBM Reset signal. "
2168  << "No event number cross checks possible.";
2169  }
2170 
2171  // Store the Pattern Generator commands in the DUT:
2172  _dut->pg_setup = patterns;
2173  // Calculate the sum of all delays and store it:
2174  _dut->pg_sum = getPatternGeneratorDelaySum(_dut->pg_setup);
2175 }
2176 
2177 uint32_t pxarCore::getPatternGeneratorDelaySum(std::vector<std::pair<uint16_t,uint8_t> > &pg_setup) {
2178 
2179  uint32_t delay_sum = 0;
2180  // Total cycle time is sum of delays plus once clock cycle for the actual command:
2181  for(std::vector<std::pair<uint16_t,uint8_t> >::iterator it = pg_setup.begin(); it != pg_setup.end(); ++it) { delay_sum += (*it).second + 1; }
2182  // Add one more clock cycle:
2183  delay_sum++;
2184  LOG(logDEBUGAPI) << "Sum of Pattern generator delays: " << delay_sum << " clk";
2185  return delay_sum;
2186 }
2187 
2188 bool pxarCore::setExternalClock(bool enable) {
2189 
2190  LOG(logDEBUGAPI) << "Setting clock to " << (enable ? "external" : "internal") << " source.";
2191  if(enable) {
2192  // Try to set the clock to external source:
2193  if(_hal->IsClockPresent()) { _hal->SetClockSource(CLK_SRC_EXT); return true; }
2194  else LOG(logCRITICAL) << "DTB reports that no external clock is present!";
2195  return false;
2196  }
2197  else {
2198  // Set the clock to internal source:
2199  _hal->SetClockSource(CLK_SRC_INT);
2200  return true;
2201  }
2202 }
2203 
2204 void pxarCore::setSignalMode(std::string signal, uint8_t mode) {
2205 
2206  uint8_t sigRegister, value = 0;
2207  if(!verifyRegister(signal, sigRegister, value, DTB_REG)) return;
2208 
2209  LOG(logDEBUGAPI) << "Setting signal " << signal << " ("
2210  << static_cast<int>(sigRegister) << ") to mode "
2211  << static_cast<int>(mode) << ".";
2212  _hal->SigSetMode(sigRegister, mode);
2213 }
2214 
2215 void pxarCore::setClockStretch(uint8_t src, uint16_t delay, uint16_t width)
2216 {
2217  LOG(logDEBUGAPI) << "Set Clock Stretch " << static_cast<int>(src) << " " << static_cast<int>(delay) << " " << static_cast<int>(width);
2218  _hal->SetClockStretch(src,width,delay);
2219 
2220 }
2221 
2222 uint16_t pxarCore::GetADC( uint8_t rpc_par1 ){
2223 
2224  if( ! status() ) { return 0; }
2225 
2226  return _hal->GetADC( rpc_par1 );
2227 
2228 }
std::vector< pixel > getPulseheightMap(uint16_t flags, uint16_t nTriggers)
Definition: api.cc:1024
void Poff()
Definition: api.cc:453
bool setExternalClock(bool enable)
Definition: api.cc:2188
void setPatternGenerator(std::vector< std::pair< std::string, uint8_t > > pg_setup)
Definition: api.cc:78
bool daqStart()
Definition: api.cc:1139
void daqTriggerLoopHalt()
Definition: api.cc:1257
std::vector< std::pair< uint8_t, std::vector< pixel > > > getPulseheightVsDAC(std::string dacName, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:675
bool setDAC(std::string dacName, uint8_t dacValue, uint8_t rocI2C)
Definition: api.cc:546
double getTBva()
Definition: api.cc:429
~pxarCore()
Definition: api.cc:38
statistics getStatistics()
Definition: api.cc:538
std::vector< std::pair< uint8_t, std::vector< pixel > > > getThresholdVsDAC(std::string dacName, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:789
double getTBid()
Definition: api.cc:434
uint8_t getDACRange(std::string dacName)
Definition: api.cc:619
std::vector< uint8_t > getEnabledRocI2Caddr()
Definition: dut.cc:227
bool comparePixelConfiguration(const std::vector< pixelConfig > pxA, const std::vector< pixelConfig > pxB)
Definition: helper.h:141
bool SignalProbe(std::string probe, std::string name)
Definition: api.cc:465
std::vector< std::vector< uint16_t > > daqGetReadback()
Definition: api.cc:1126
pxarCore(std::string usbId="*", std::string logLevel="WARNING")
Definition: api.cc:19
std::vector< rocConfig > getEnabledRocs()
Definition: dut.cc:204
bool programDUT()
Definition: api.cc:299
void setSignalMode(std::string signal, uint8_t mode)
Definition: api.cc:2204
void setTestboardDelays(std::vector< std::pair< std::string, uint8_t > > sig_delays)
Definition: api.cc:68
void HVon()
Definition: api.cc:449
uint16_t daqTriggerLoop(uint16_t period=1000)
Definition: api.cc:1239
std::vector< std::pair< uint8_t, std::vector< pixel > > > getEfficiencyVsDAC(std::string dacName, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:733
dut * _dut
Definition: api.h:728
std::vector< pixel > getThresholdMap(std::string dacName, uint8_t dacStep, uint8_t dacMin, uint8_t dacMax, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:1080
void setTestboardPower(std::vector< std::pair< std::string, double > > power_settings)
Definition: api.cc:88
std::vector< std::pair< uint8_t, std::pair< uint8_t, std::vector< pixel > > > > getPulseheightVsDACDAC(std::string dac1name, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:878
Event daqGetEvent()
Definition: api.cc:1300
std::vector< uint8_t > getEnabledRocIDs()
Definition: dut.cc:214
void SetCalibrateBits(bool enable)
Definition: api.cc:2016
bool daqStop()
Definition: api.cc:1324
void HVoff()
Definition: api.cc:445
void Pon()
Definition: api.cc:459
bool getAllPixelEnable()
Definition: dut.cc:271
bool flashTB(std::string filename)
Definition: api.cc:397
uint16_t GetADC(uint8_t rpc_par1)
Definition: api.cc:2222
bool setTbmReg(std::string regName, uint8_t regValue, uint8_t tbmid)
Definition: api.cc:633
std::vector< uint16_t > daqGetBuffer()
Definition: api.cc:1263
std::vector< std::pair< uint8_t, std::pair< uint8_t, std::vector< pixel > > > > getEfficiencyVsDACDAC(std::string dac1name, uint8_t dac1min, uint8_t dac1max, std::string dac2name, uint8_t dac2min, uint8_t dac2max, uint16_t flags, uint16_t nTriggers)
Definition: api.cc:951
std::vector< pixel > getEfficiencyMap(uint16_t flags, uint16_t nTriggers)
Definition: api.cc:1048
size_t getNEnabledRocs()
Definition: dut.cc:74
std::vector< pixelConfig > getEnabledPixels(size_t rocid)
Definition: dut.cc:124
std::string getVersion()
Definition: api.cc:43
std::vector< uint8_t > getRocI2Caddr()
Definition: dut.cc:240
double getTBia()
Definition: api.cc:424
Definition: api.h:879
bool initDUT(uint8_t hubId, std::string tbmtype, std::vector< std::vector< std::pair< std::string, uint8_t > > > tbmDACs, std::string roctype, std::vector< std::vector< std::pair< std::string, uint8_t > > > rocDACs, std::vector< std::vector< pixelConfig > > rocPixels, std::vector< uint8_t > rocI2Cs)
Definition: api.cc:108
uint8_t getDAC(size_t rocId, std::string dacName)
Definition: dut.cc:314
void setClockStretch(uint8_t src, uint16_t delay, uint16_t width)
Definition: api.cc:2215
bool status()
Definition: dut.cc:571
std::vector< Event > daqGetEventBuffer()
Definition: api.cc:1285
double getTBvd()
Definition: api.cc:439
uint16_t daqTrigger(uint32_t nTrig=1, uint16_t period=0)
Definition: api.cc:1222
rawEvent daqGetRawEvent()
Definition: api.cc:1312
bool status()
Definition: api.cc:339
bool daqStatus()
Definition: api.cc:1191
std::vector< tbmConfig > getEnabledTbms()
Definition: dut.cc:253
std::vector< Event * >(hal::* HalMemFnRocParallel)(std::vector< uint8_t > rocids, std::vector< int32_t > parameter)
Definition: api.h:107
bool initTestboard(std::vector< std::pair< std::string, uint8_t > > sig_delays, std::vector< std::pair< std::string, double > > power_settings, std::vector< std::pair< std::string, uint8_t > > pg_setup)
Definition: api.cc:45
std::vector< rawEvent > daqGetRawEventBuffer()
Definition: api.cc:1270