pxar
 All Classes Namespaces Functions Variables Typedefs Friends
PixTestTiming.cc
1 #include <iostream>
2 #include <bitset>
3 #include <stdlib.h>
4 #include <algorithm>
5 
6 #include <TStopwatch.h>
7 #include <TMarker.h>
8 #include <TStyle.h>
9 #include <TBox.h>
10 #include <TMath.h>
11 
12 #include "PixTestTiming.hh"
13 #include "PixUtil.hh"
14 #include "timer.h"
15 #include "log.h"
16 #include "helper.h"
17 #include "constants.h"
18 #include "math.h"
19 
20 using namespace std;
21 using namespace pxar;
22 
23 ClassImp(PixTestTiming)
24 
25 //------------------------------------------------------------------------------
26 PixTestTiming::PixTestTiming(PixSetup *a, std::string name) : PixTest(a, name)
27 {
28  PixTest::init();
29  init();
30 }
31 
32 //------------------------------------------------------------------------------
33 PixTestTiming::PixTestTiming() : PixTest() {}
34 
35 bool PixTestTiming::setParameter(string parName, string sval) {
36  bool found(false);
37  std::transform(parName.begin(), parName.end(), parName.begin(), ::tolower);
38  for (unsigned int i = 0; i < fParameters.size(); ++i) {
39  if (fParameters[i].first == parName) {
40  found = true;
41  if (!parName.compare("fastscan")) {
42  PixUtil::replaceAll(sval, "checkbox(", "");
43  PixUtil::replaceAll(sval, ")", "");
44  fFastScan = atoi(sval.c_str());
45  LOG(logDEBUG) << "fFastScan: " << fFastScan;
46  setToolTips();
47  }
48  if (!parName.compare("targetclk")) {
49  fTargetClk = atoi(sval.c_str());
50  LOG(logDEBUG) << "PixTestTiming::PixTest() targetclk = " << fTargetClk;
51  }
52  if (!parName.compare("ntrig")) {
53  fNTrig = atoi(sval.c_str());
54  LOG(logDEBUG) << "PixTestTiming::PixTest() ntrig = " << fNTrig;
55  }
56  break;
57  }
58  }
59  return found;
60 }
61 
62 void PixTestTiming::init()
63 {
64  LOG(logDEBUG) << "PixTestTiming::init()";
65 
66  fDirectory = gFile->GetDirectory(fName.c_str());
67  if (!fDirectory)
68  fDirectory = gFile->mkdir(fName.c_str());
69  fDirectory->cd();
70 }
71 
73 {
74  fTestTip = string(Form("scan testboard parameter settings and check for valid readout\n")
75  + string("TO BE IMPLEMENTED!!")); //FIXME
76  fSummaryTip = string("summary plot to be implemented"); //FIXME
77 }
78 
79 void PixTestTiming::bookHist(string name)
80 {
81  fDirectory->cd();
82  LOG(logDEBUG) << "nothing done with " << name;
83 }
84 
85 PixTestTiming::~PixTestTiming()
86 {
87  LOG(logDEBUG) << "PixTestTiming dtor";
88  std::list<TH1*>::iterator il;
89  fDirectory->cd();
90  for (il = fHistList.begin(); il != fHistList.end(); ++il)
91  {
92  LOG(logINFO) << "Write out " << (*il)->GetName();
93  (*il)->SetDirectory(fDirectory);
94  (*il)->Write();
95  }
96 }
97 
98 // ----------------------------------------------------------------------
100 
101  fDirectory->cd();
102  PixTest::update();
103  bigBanner(Form("PixTestTiming::doTest()"));
104 
105  ClkSdaScan();
106  TH1 *h1 = (*fDisplayedHist);
107  h1->Draw(getHistOption(h1).c_str());
108  PixTest::update();
109 
110  PhaseScan();
111  h1 = (*fDisplayedHist);
112  h1->Draw(getHistOption(h1).c_str());
113  PixTest::update();
114 
115  LevelScan();
116  h1 = (*fDisplayedHist);
117  h1->Draw(getHistOption(h1).c_str());
118  PixTest::update();
119 
120  // -- save DACs!
121  saveParameters();
122  TimingTest();
123 
124  LOG(logINFO) << "PixTestTiming::doTest() done";
125 }
126 
127 //------------------------------------------------------------------------------
128 void PixTestTiming::ClkSdaScan() {
129 
130 
131  // Start test timer
132  timer t;
133 
134  cacheDacs();
135  fDirectory->cd();
136  PixTest::update();
137  banner(Form("PixTestTiming::ClkSdaScan()"));
138 
139  //Make a histogram
140  TH2D *h1(0);
141  h1 = bookTH2D("ClkSdaScan","ClkSdaScan", 20, -0.5, 19.5, 20, -0.5, 19.5);
142  h1->SetDirectory(fDirectory);
143  setTitles(h1, "Clk", "Sda");
144  fHistOptions.insert(make_pair(h1, "colz"));
145 
146  //Turn of Vana
147  fApi->setDAC("vana", 0);
148  pxar::mDelay(2000);
149  double IA = fApi->getTBia();
150 
151  //Scan the Clock and SDA to find the working values. iclk starts at fTargetClk and ends at fTargetClk-1. Both sda and clk ranges are limited to 0-19.
152  int GoodSDA = -1;
153  int GoodClk = -1;
154  map<int, vector<int> > goodclksdalist;
155  for (int i = 0; i < 20; i++) {
156  int iclk = (i+fTargetClk) % 20;
157  vector<int> goodsdalist;
158  for (int j = 0; j < 20; j++) {
159  int isda = (j+iclk+15) % 20;
160  fApi->setTestboardDelays(getDelays(iclk,isda));
161  LOG(logDEBUG) << "Checking Clk: " << iclk << " Sda: " << isda;
162  fApi->setDAC("vana", 70);
163  pxar::mDelay(10);
164  double NewIA = fApi->getTBia();
165  if (TMath::Abs(NewIA-IA) > 0.005) {
166  h1->Fill(iclk,isda); //Need 5mA change in current to see if ROCs are programmable
167  GoodClk=iclk;
168  GoodSDA=isda;
169  goodsdalist.push_back(isda);
170  if (fFastScan) break;
171  }
172  fApi->setDAC("vana", 0);
173  pxar::mDelay(10);
174  }
175  goodclksdalist[iclk]=goodsdalist;
176  if (fFastScan && GoodClk != -1) break;
177  }
178 
179  //Overly complicated algorithm to figure out the best SDA.
180  //Normally there are 7 sda settings that work, and this selects the middle one.
181  //It's completcated because the working SDA settings can be 0, 1, 2, 3, 4, 18, and 19. The center most value is 1.
182  if (GoodClk != -1) {
183  if (!fFastScan) {
184  GoodClk = -1;
185  for (int i = 0; i < 20; i++) {
186  int iclk = (i+fTargetClk) % 20;
187  if (goodclksdalist.count(iclk)) {
188  GoodClk = iclk;
189  vector<int> goodsdalist = goodclksdalist[iclk];
190  if (goodsdalist.size() == 1) {
191  GoodSDA=goodsdalist[0];
192  } else {
193  sort(goodsdalist.begin(),goodsdalist.end());
194  for (size_t isda=1; isda<goodsdalist.size(); isda++) if (TMath::Abs(goodsdalist[isda]-goodsdalist[isda-1])>1) goodsdalist[isda] -= 20;
195  sort(goodsdalist.begin(),goodsdalist.end());
196  GoodSDA=goodsdalist[goodsdalist.size()/2];
197  if (GoodSDA<0) GoodSDA+=20;
198  break;
199  }
200  }
201  }
202  }
203 
204  //Print out good values and set them on the test board.
205  vector<pair<string,uint8_t> > GoodDelays = getDelays(GoodClk,GoodSDA);
206  LOG(logINFO) << "SDA delay found at clock:" << GoodClk;
207  for(vector<pair<string,uint8_t> >::iterator idelay = GoodDelays.begin(); idelay != GoodDelays.end(); ++idelay) {
208  LOG(logINFO) << idelay->first << ": " << int(idelay->second);
209  fPixSetup->getConfigParameters()->setTbParameter(idelay->first, idelay->second);
210  }
211  fApi->setTestboardDelays(GoodDelays);
212  } else LOG(logERROR) << "No working SDA setting found!";
213 
214  //Draw the plot
215  h1->Draw("colz");
216  fHistList.push_back(h1);
217  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h1);
218  PixTest::update();
219  restoreDacs();
220 
221  // Print timer value:
222  LOG(logINFO) << "Test took " << t << " ms.";
223  LOG(logINFO) << "PixTestTiming::ClkSdaScan() done.";
224 }
225 
226 //------------------------------------------------------------------------------
227 void PixTestTiming::PhaseScan() {
228 
229  // Start test timer
230  timer t;
231 
232  banner(Form("PixTestTiming::PhaseScan()"));
233  fDirectory->cd();
234  PixTest::update();
235 
236  //Make histograms
237  TH2D *h1(0);
238  TH2D *h2(0);
239 
240  //Set Number of Port (Probably won't work for TBM09 and is untested)
241  int nPorts = 2;
242  if (fPixSetup->getConfigParameters()->getTbmType() == "tbm09") nPorts=1;
243 
244  // Setup a new pattern with only res and token:
245  vector<pair<string, uint8_t> > pg_setup;
246  //pg_setup.push_back(make_pair("resetroc", 25));
247  pg_setup.push_back(make_pair("resettbm", 25));
248  pg_setup.push_back(make_pair("trigger", 0));
249  fApi->setPatternGenerator(pg_setup);
250  fTrigBuffer = 3;
251  uint16_t period = 300;
252  vector<rawEvent> daqRawEv;
253 
254  //Get the number of TBMs, Total ROCs, and ROCs per TBM
255  int nTBMs = fApi->_dut->getNTbms();
256  vector<uint8_t> rocIds = fApi->_dut->getEnabledRocI2Caddr();
257  vector<int> nROCs;
258  vector <vector<int> > nROCsPort;
259  vector<TH2D*> phasehists;
260  vector<map <int, int> > TBMROCPhases;
261  for (int itbm = 0; itbm < nTBMs; itbm++) {
262  fApi->setTbmReg("basea", 0, itbm); //Reset the ROC delays
263  nROCs.push_back(0);
264  vector<int> InitnROCPorts;
265  InitnROCPorts.assign(nPorts, 0);
266  nROCsPort.push_back(InitnROCPorts);
267  map<int, int> TBMROCPhaseMap;
268  TBMROCPhases.push_back(TBMROCPhaseMap);
269  h1 = bookTH2D(Form("TBMPhaseScan%d",itbm),Form("TBM %d Phase Scan",itbm), 8, -0.5, 7.5, 8, -0.5, 7.5);
270  h1->SetDirectory(fDirectory);
271  setTitles(h1, "160MHz Phase", "400 MHz Phase");
272  fHistOptions.insert(make_pair(h1, "colz"));
273  h1->SetMinimum(0);
274  phasehists.push_back(h1);
275  }
276 
277  //Count up the ROCs on each TBM Core
278  //8, 4 and 12 are all magic numbers! Number of expected ROCs per TBM, number of ROCs per port, and number of ports should be in the dut or ConfigParameters!
279  for (size_t iROC=0; iROC<rocIds.size(); iROC++) {
280  if (rocIds[iROC]<8) {
281  nROCs[0]++;
282  if (rocIds[iROC]<4) nROCsPort[0].at(0)++;
283  else nROCsPort[0].at(1)++;
284  } else {
285  nROCs[1]++;
286  if (rocIds[iROC]<12) nROCsPort[1].at(0)++;
287  else nROCsPort[1].at(1)++;
288  }
289  }
290 
291  // Loop through all possible TBM phase settings.
292  bool goodTBMPhase = false;
293  for (int iclk160 = 0; iclk160 < 8 && !(goodTBMPhase && fFastScan); iclk160++) {
294  for (int iclk400 = 0; iclk400 < 8 && !(goodTBMPhase && fFastScan); iclk400++) {
295  uint8_t delaysetting = iclk160<<5 | iclk400<<2;
296  fApi->setTbmReg("basee", delaysetting, 0); //Set TBM 160-400 MHz Clock Phase
297  LOG(logINFO) << "160MHz Phase: " << iclk160 << " 400MHz Phase: " << iclk400 << " Delay Setting: " << bitset<8>(delaysetting).to_string();
298  fApi->daqStart();
299  fApi->daqTrigger(fTrigBuffer,period); //Read in fTrigBuffer events and throw them away, first event is generally bad.
300  daqRawEv = fApi->daqGetRawEventBuffer();
301  for (int itbm = 0; itbm < nTBMs; itbm++) fApi->setTbmReg("basea", 0, itbm); //Reset the ROC delays
302  //Loop through each TBM core and count the number of ROC headers on the core for all 256 delay settings
303  vector<int> GoodROCDelays;
304  for (int itbm = 0; itbm < nTBMs; itbm++) {
305  int MaxGoodROCSize=0;
306  bool goodROCDelay = false;
307  for (int delaytht = 0; delaytht < 4 && !goodROCDelay; delaytht++) {
308  if (delaytht==2) continue;
309  h2 = bookTH2D(Form("ROCPhaseScan_clk160_%d_clk400_%d_TBM_%d_delay_%d", iclk160, iclk400, itbm, delaytht),
310  Form("ROC Phase Scan: TBM %d Phase: %s THT Delay: %s", itbm, bitset<8>(delaysetting).to_string().c_str(), bitset<2>(delaytht).to_string().c_str()),
311  8, -0.5, 7.5, 8, -0.5, 7.5);
312  setTitles(h2, "ROC Port 0", "ROC Port 1");
313  h2->SetDirectory(fDirectory);
314  h2->SetMinimum(0);
315  h2->SetMaximum(nROCs[itbm]);
316  fHistOptions.insert(make_pair(h2, "colz"));
317  for (int iport = 0; iport < nPorts; iport++) {
318  for (int idelay = 0; idelay < 8; idelay++) {
319  int ROCDelay = (iport==0) ? (delaytht << 6) | idelay : (delaytht << 6) | (idelay << 3);
320  LOG(logDEBUG) << "Testing ROC Delay: " << bitset<8>(ROCDelay).to_string() << " For TBM Core: " << itbm;
321  fApi->setTbmReg("basea", ROCDelay, itbm);
322  fApi->daqTrigger(fNTrig,period);
323  daqRawEv = fApi->daqGetRawEventBuffer();
324  LOG(logDEBUG) << "Events in Data Buffer: " << daqRawEv.size();
325  if (int(daqRawEv.size()) < fNTrig) continue; //Grab fNTrig triggers
326  for (int ievent = 0; ievent<fNTrig; ievent++) {
327  rawEvent event = daqRawEv.at(ievent);
328  LOG(logDEBUG) << "Event: " << event;
329  vector<int> tbmheaders;
330  vector<int> tbmtrailers;
331  int header=0;
332  for (int idata = 0; idata < int(event.data.size()); idata++) {
333  if (event.data.at(idata) >> 8 == 160) tbmheaders.push_back(idata); //Look for TBM Header a0
334  if (event.data.at(idata) >> 8 == 192) tbmtrailers.push_back(idata); //Look for TBM Trailer c0, maybe should be c000
335  if (header==0 && int(tbmheaders.size())==itbm+1 && int(tbmtrailers.size())==itbm && event.data.at(idata) >> 12 == 4) header = event.data.at(idata); //Grab the first object that looks like a header between the correct header and trailer
336  }
337  if (int(tbmheaders.size()) != nTBMs || int(tbmtrailers.size()) != nTBMs || header==0) continue; //Skip event if the correct number of TBM headers and trailer are not present or if a ROC header could not be found.
338  int rocheader_count = 0;
339  int StartData = tbmheaders[itbm]+2;
340  int StopData = tbmtrailers[itbm]-2;
341  for (int jport=0; jport<nPorts; jport++) {
342  if (jport < iport) StartData += nROCsPort[itbm][jport];
343  if (jport > iport) StopData -= nROCsPort[itbm][jport];
344  }
345  for (int idata = StartData; idata <= StopData; idata++) if (event.data.at(idata) >> 2 == header >> 2) rocheader_count++; //Count the number of ROCs on each TBM Core for each port
346  LOG(logDEBUG) << rocheader_count << " ROC headers (" << hex << (header) << dec << ") found for TBM Core " << itbm << " for Port " << iport << ". Looking for " << nROCsPort[itbm][iport] << ".";
347  for (int ibin=0; ibin<8; ibin++) {
348  if (iport==0) h2->Fill(idelay, ibin, rocheader_count);
349  if (iport==1) h2->Fill(ibin, idelay, rocheader_count);
350  }
351  }
352  }
353  }
354  pair <int, int> GoodRegion = getGoodRegion(h2, nROCs[itbm]*fNTrig);
355  LOG(logDEBUG) << h2->GetTitle() << " - Size: " << GoodRegion.first << " Delay: " << GoodRegion.second;
356  h2->Scale(1/float(fNTrig));
357  if (GoodRegion.first > MaxGoodROCSize) {
358  MaxGoodROCSize = GoodRegion.first;
359  int ROCDelay = (delaytht << 6) | GoodRegion.second;
360  if (int(GoodROCDelays.size()) < itbm+1) GoodROCDelays.push_back(ROCDelay);
361  else GoodROCDelays[itbm] = ROCDelay;
362  if (fFastScan && GoodRegion.first > 0) {
363  goodROCDelay = true;
364  fPixSetup->getConfigParameters()->setTbmDac("basea", ROCDelay, itbm);
365  }
366  }
367  //Draw the plot
368  if (GoodRegion.first) {
369  h2->SetMinimum(0);
370  h2->Draw(getHistOption(h2).c_str());
371  fHistList.push_back(h2);
372  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h2);
373  PixTest::update();
374  }
375  }
376  phasehists[itbm]->Fill(iclk160, iclk400, MaxGoodROCSize);
377  if (int(GoodROCDelays.size())==itbm+1) { // Use the good ROC delays, or reset the ROCs to 0
378  TBMROCPhases[itbm][delaysetting] = GoodROCDelays[itbm];
379  fApi->setTbmReg("basea", GoodROCDelays[itbm], itbm);
380  fPixSetup->getConfigParameters()->setTbmDac("basea", GoodROCDelays[itbm], itbm);
381  } else fApi->setTbmReg("basea", 0, itbm);
382  }
383  fApi->daqStop();
384  if (int(GoodROCDelays.size())==nTBMs){
385  goodTBMPhase = true;
386  if (fFastScan) fPixSetup->getConfigParameters()->setTbmDac("basee", delaysetting, 0);
387  LOG(logINFO) << "Good timings found for TBMPhase basee: " << bitset<8>(delaysetting).to_string();
388  for (int itbm = 0; itbm < nTBMs; itbm++) LOG(logINFO) << "ROCPhase TBM Core " << itbm << " basea: " << bitset<8>(GoodROCDelays[itbm]).to_string();
389  }
390  }
391  }
392 
393  banner(Form("PixTestTiming::Phase Scan Completed"));
394 
395  if (!fFastScan) {
396  int MaxBinSum = 0;
397  pair<int, int> BestBin(0,0);
398  for (int xbin=1; xbin<=phasehists[0]->GetNbinsX(); xbin++) {
399  for (int ybin=1; ybin<=phasehists[0]->GetNbinsY(); ybin++) {
400  double BinSum = 0;
401  for (int itbm=0; itbm<nTBMs; itbm++) BinSum += phasehists[itbm]->GetBinContent(xbin,ybin);
402  if (BinSum > MaxBinSum) {
403  MaxBinSum = BinSum;
404  BestBin = make_pair(xbin-1, ybin-1);
405  }
406  }
407  }
408  int delaysetting = BestBin.first<<5 | BestBin.second<<2;
409  fApi->setTbmReg("basee", delaysetting, 0);
410  fPixSetup->getConfigParameters()->setTbmDac("basee", delaysetting, 0);
411  LOG(logINFO) << "Final timing for TBMPhase basee: " << bitset<8>(delaysetting).to_string();
412  for (int itbm = 0; itbm < nTBMs; itbm++) {
413  fApi->setTbmReg("basea", TBMROCPhases[itbm][delaysetting], itbm);
414  fPixSetup->getConfigParameters()->setTbmDac("basea", TBMROCPhases[itbm][delaysetting], itbm);
415  LOG(logINFO) << "ROCPhase TBM Core " << itbm << " basea: " << bitset<8>(TBMROCPhases[itbm][delaysetting]).to_string();
416  }
417  }
418 
419  // Reset the pattern generator to the configured default:
420  fApi->setPatternGenerator(fPixSetup->getConfigParameters()->getTbPgSettings());
421 
422  if (!goodTBMPhase) {
423  LOG(logERROR) << "No working TBM-ROC Phase found. Verify you have disabled bypassed ROCs in pXar on the h/w tab.";
424  for (int itbm = 0; itbm < nTBMs; itbm++) LOG(logERROR) << "PhaseScan searched for " << nROCs[itbm] << " ROCs on TBM Core " << itbm << ".";
425  }
426 
427  //Draw TBM Phase Map
428  for (int itbm = 0; itbm < nTBMs && !fFastScan; itbm++) {
429  phasehists[itbm]->Draw(getHistOption(phasehists[itbm]).c_str());
430  fHistList.push_back(phasehists[itbm]);
431  fDisplayedHist = find(fHistList.begin(), fHistList.end(), phasehists[itbm]);
432  PixTest::update();
433  }
434 
435  // Print timer value:
436  LOG(logINFO) << "Test took " << t << " ms.";
437  LOG(logINFO) << "PixTestTiming::PhaseScan() done.";
438 }
439 
440 //------------------------------------------------------------------------------
441 void PixTestTiming::TimingTest() {
442 
443  // Start test timer
444  timer t;
445 
446  banner(Form("PixTestTiming::TimingTest()"));
447 
448  size_t nTBMs = fApi->_dut->getNTbms();
449  size_t nROCs = fApi->_dut->getEnabledRocI2Caddr().size();
450 
451  // Setup a new pattern with only res and token:
452  vector<pair<string, uint8_t> > pg_setup;
453  pg_setup.push_back(make_pair("resetroc", 25));
454  pg_setup.push_back(make_pair("trigger", 0));
455  fApi->setPatternGenerator(pg_setup);
456  fTrigBuffer = 3;
457  uint16_t period = 300;
458  vector<rawEvent> daqRawEv;
459  fApi->daqStart();
460  fApi->daqTrigger(fTrigBuffer,period); //Read in fTrigBuffer events and throw them away, first event is generally bad.
461  daqRawEv = fApi->daqGetRawEventBuffer();
462  fApi->daqTrigger(fNTrig,period);
463  daqRawEv = fApi->daqGetRawEventBuffer();
464  fApi->daqStop();
465  LOG(logINFO) << daqRawEv.size() << " events found. " << fNTrig << " events expected.";
466  int ngoodevents = 0;
467  for (size_t ievent=0; ievent<daqRawEv.size(); ievent++) {
468  banner(Form("Decoding Event Number %d", int(ievent)),logDEBUG);
469  rawEvent event = daqRawEv.at(ievent);
470  LOG(logDEBUG) << "Event: " << event;
471  vector<int> tbmheaders;
472  vector<int> tbmtrailers;
473  vector<int> rocheaders;
474  for (int idata=0; idata < int(event.data.size()); idata++) {
475  if (event.data.at(idata) >> 8 == 160) tbmheaders.push_back(idata);
476  if (event.data.at(idata) >> 8 == 192) tbmtrailers.push_back(idata); //192 is c0, maybe it shoud be 49152 (c0000)
477  if (event.data.at(idata) >> 12 == 4) rocheaders.push_back(idata);
478  }
479  LOG(logDEBUG) << tbmheaders.size() << " TBM Headers found. " << nTBMs << " TBM Headers expected.";
480  LOG(logDEBUG) << tbmtrailers.size() << " TBM Trailers found. " << nTBMs << " TBM Trailers expected.";
481  LOG(logDEBUG) << rocheaders.size() << " ROC Headers found. " << nROCs << " ROC Headers expected." << endl;
482  if (tbmheaders.size()==nTBMs && tbmtrailers.size()==nTBMs && rocheaders.size()==nROCs) ngoodevents++; //Number of ROC Headers and TBM Headers and Trailer must be correct
483  }
484  fApi->setPatternGenerator(fPixSetup->getConfigParameters()->getTbPgSettings());
485  LOG(logINFO) << Form("The fraction of properly decoded events is %4.2f%%: ", float(ngoodevents)/fNTrig*100) << ngoodevents << "/" << fNTrig;
486  LOG(logINFO) << "Test took " << t << " ms.";
487  LOG(logINFO) << "PixTestTiming::TimingTest() done.";
488 
489 }
490 
491 //------------------------------------------------------------------------------
492 void PixTestTiming::LevelScan() {
493 
494  // Start test timer
495  timer t;
496 
497  fDirectory->cd();
498  PixTest::update();
499  banner(Form("PixTestTiming::LevelScan()"));
500 
501  //The Buffer and Period
502  fTrigBuffer = 3;
503  uint16_t period = 300;
504 
505  //Make a histogram
506  TH1D *h1(0);
507  h1 = bookTH1D("LevelScan","Level Scan", 16, -0.5, 15.5);
508  h1->SetDirectory(fDirectory);
509  setTitles(h1, "DTB Level", "Good Events");
510 
511  //Get the normal info
512  size_t nTBMs = fApi->_dut->getNTbms();
513  size_t nROCs = fApi->_dut->getEnabledRocI2Caddr().size();
514 
515  // Setup a new pattern with only res and token:
516  vector<pair<string, uint8_t> > pg_setup;
517  pg_setup.push_back(make_pair("resetroc", 25));
518  pg_setup.push_back(make_pair("trigger", 0));
519  fApi->setPatternGenerator(pg_setup);
520 
521  //Get Intial TBM Parameters
522  vector<pair<string, uint8_t> > InitTBMParameters = fPixSetup->getConfigParameters()->getTbParameters();
523 
524  vector<uint8_t> GoodLevels;
525  vector<rawEvent> daqRawEv;
526  daqRawEv = fApi->daqGetRawEventBuffer();
527  for (uint8_t ilevel=15; ilevel>3; ilevel--){
528  LOG(logDEBUG) << "Testing Level: " << int(ilevel);
529  fPixSetup->getConfigParameters()->setTbParameter("level", ilevel);
530  fApi->setTestboardDelays(fPixSetup->getConfigParameters()->getTbParameters());
531  fApi->daqStart();
532  fApi->daqTrigger(fTrigBuffer,period); //Read in fTrigBuffer events and throw them away, first event is generally bad.
533  daqRawEv = fApi->daqGetRawEventBuffer();
534  fApi->daqTrigger(fNTrig,period);
535  daqRawEv = fApi->daqGetRawEventBuffer();
536  fApi->daqStop();
537  int ngoodevents = 0;
538  for (size_t ievent=0; ievent<daqRawEv.size(); ievent++) {
539  rawEvent event = daqRawEv.at(ievent);
540  LOG(logDEBUG) << "Event: " << event;
541  vector<int> tbmheaders;
542  vector<int> tbmtrailers;
543  vector<int> rocheaders;
544  for (int idata=0; idata < int(event.data.size()); idata++) {
545  if (event.data.at(idata) >> 8 == 160) tbmheaders.push_back(idata);
546  if (event.data.at(idata) >> 8 == 192) tbmtrailers.push_back(idata); //192 is c0, maybe it shoud be 49152 (c0000)
547  if (event.data.at(idata) >> 12 == 4) rocheaders.push_back(idata);
548  }
549  if (tbmheaders.size()==nTBMs && tbmtrailers.size()==nTBMs && rocheaders.size()==nROCs) ngoodevents++; //Number of ROC Headers and TBM Headers and Trailer must be correct
550  }
551  if (ngoodevents) h1->Fill(int(ilevel), ngoodevents);
552  if (ngoodevents==fNTrig) GoodLevels.push_back(ilevel);
553  }
554 
555  if (GoodLevels.size()) {
556  uint8_t MeanLevel = 0;
557  if (GoodLevels.size()==1) MeanLevel = GoodLevels.front();
558  else MeanLevel = GoodLevels[GoodLevels.size()/2]; //Pick the median functional level (hope there's no gaps)
559  fPixSetup->getConfigParameters()->setTbParameter("level", MeanLevel);
560  fApi->setTestboardDelays(fPixSetup->getConfigParameters()->getTbParameters());
561  LOG(logINFO) << "DTB Level set to " << int(MeanLevel);
562  } else {
563  LOG(logERROR) << "No working level found! Verify you have disabled bypassed ROCs in pXar on the h/w tab.";
564  LOG(logERROR) << "Level scan searched for " << nROCs << " total ROCs and " << nTBMs << " TBM Headers and Trailers.";
565  fApi->setTestboardDelays(InitTBMParameters);
566  }
567 
568  //Draw the plot
569  h1->Draw();
570  fHistList.push_back(h1);
571  fDisplayedHist = find(fHistList.begin(), fHistList.end(), h1);
572  PixTest::update();
573 
574  fApi->setPatternGenerator(fPixSetup->getConfigParameters()->getTbPgSettings());
575  LOG(logINFO) << "Test took " << t << " ms.";
576  LOG(logINFO) << "PixTestTiming::LevelScan() done.";
577 
578 }
579 
580 //------------------------------------------------------------------------------
581 vector<pair<string,uint8_t> > PixTestTiming::getDelays(uint8_t clk, uint8_t sda) {
582  vector<pair<string,uint8_t> > sigdelays;
583  sigdelays.push_back(make_pair("clk", clk%20));
584  sigdelays.push_back(make_pair("ctr", clk%20));
585  sigdelays.push_back(make_pair("sda", sda%20));
586  sigdelays.push_back(make_pair("tin", (clk+5)%20));
587  return sigdelays;
588 }
589 
590 // ----------------------------------------------------------------------
591 pair <int, int> PixTestTiming::getGoodRegion(TH2D* hist, int hits) {
592 
593  if (hist->GetEntries()==0) return make_pair(0,0);
594 
595  int MaxGoodRegionSize=0;
596  int GoodROCDelay=0;
597  for (int startbinx=1; startbinx<=hist->GetNbinsX(); startbinx++) {
598  for (int startbiny=1; startbiny<=hist->GetNbinsY(); startbiny++) {
599  if (int(hist->GetBinContent(startbinx,startbiny))!=hits) continue;
600  for (int regionsize=0; regionsize<8; regionsize++) {
601  bool regiongood = true;
602  for (int xoffset=0; xoffset<=regionsize && regiongood; xoffset++) {
603  for (int yoffset=0; yoffset<=regionsize && regiongood; yoffset++) {
604  int checkbinx = (startbinx+xoffset>8) ? startbinx+xoffset-8 : startbinx+xoffset;
605  int checkbiny = (startbiny+yoffset>8) ? startbiny+yoffset-8 : startbiny+yoffset;
606  if (int(hist->GetBinContent(checkbinx,checkbiny))!=hits) regiongood=false;
607  }
608  }
609  if (regiongood && regionsize+1>MaxGoodRegionSize) {
610  MaxGoodRegionSize=regionsize+1;
611  GoodROCDelay = (startbinx-1+regionsize/2)%8 | (startbiny-1+regionsize/2)%8<<3;
612  }
613  }
614  }
615  }
616 
617  return make_pair(MaxGoodRegionSize, GoodROCDelay);
618 
619 }
620 
621 // ----------------------------------------------------------------------
622 void PixTestTiming::saveParameters() {
623  LOG(logINFO) << "PixTestTiming:: Write Tbm parameters to file.";
624  fPixSetup->getConfigParameters()->writeTbParameterFile();
625  for (unsigned int itbm = 0; itbm < fApi->_dut->getNTbms(); itbm += 2) {
626  fPixSetup->getConfigParameters()->writeTbmParameterFile(itbm, fApi->_dut->getTbmDACs(itbm), fApi->_dut->getTbmDACs(itbm+1));
627  }
628 }
629 
630 // ----------------------------------------------------------------------
631 void PixTestTiming::runCommand(string command) {
632  transform(command.begin(), command.end(), command.begin(), ::tolower);
633  LOG(logDEBUG) << "running command: " << command;
634  if (!command.compare("clocksdascan")) {
635  ClkSdaScan();
636  return;
637  }
638  if (!command.compare("phasescan")) {
639  PhaseScan();
640  return;
641  }
642  if (!command.compare("saveparameters")) {
643  saveParameters();
644  return;
645  }
646  if (!command.compare("timingtest")) {
647  TimingTest();
648  return;
649  }
650  if (!command.compare("levelscan")) {
651  LevelScan();
652  return;
653  }
654  LOG(logDEBUG) << "did not find command ->" << command << "<-";
655 }
static void replaceAll(std::string &str, const std::string &from, const std::string &to)
in str, replace all occurences of from to to
Definition: PixUtil.cc:24
void runCommand(std::string)
allow execution of any button in the test
void setPatternGenerator(std::vector< std::pair< std::string, uint8_t > > pg_setup)
Definition: api.cc:78
bool daqStart()
Definition: api.cc:1139
std::map< TH1 *, std::string > fHistOptions
options can be stored with each histogram
Definition: PixTest.hh:308
size_t getNTbms()
Definition: dut.cc:119
bool setDAC(std::string dacName, uint8_t dacValue, uint8_t rocI2C)
Definition: api.cc:546
PixSetup * fPixSetup
all necessary stuff in one place
Definition: PixTest.hh:290
std::vector< uint8_t > getEnabledRocI2Caddr()
Definition: dut.cc:227
std::vector< std::pair< std::string, std::string > > fParameters
the parameters of this test
Definition: PixTest.hh:302
void setTestboardDelays(std::vector< std::pair< std::string, uint8_t > > sig_delays)
Definition: api.cc:68
TDirectory * fDirectory
where the root histograms will end up
Definition: PixTest.hh:306
void restoreDacs(bool verbose=false)
restore all DACs
Definition: PixTest.cc:771
dut * _dut
Definition: api.h:728
bool daqStop()
Definition: api.cc:1324
std::list< TH1 * >::iterator fDisplayedHist
pointer to the histogram currently displayed
Definition: PixTest.hh:309
TH1D * bookTH1D(std::string sname, std::string title, int nbins, double xmin, double xmax)
book a TH1D, adding version information to the name and title
Definition: PixTest.cc:895
virtual std::string getHistOption(TH1 *)
get the hist display options (if stored in fHistOptions)
Definition: PixTest.cc:941
void cacheDacs(bool verbose=false)
cache all DACs
Definition: PixTest.cc:760
bool setTbmReg(std::string regName, uint8_t regValue, uint8_t tbmid)
Definition: api.cc:633
std::list< TH1 * > fHistList
list of histograms available in PixTab::next and PixTab::previous
Definition: PixTest.hh:307
void setTitles(TH1 *h, const char *sx, const char *sy, float size=0.05, float xoff=1.1, float yoff=1.1, float lsize=0.05, int font=42)
utility to set histogram titles
Definition: PixTest.cc:649
void setToolTips()
implement this to provide updated tool tips if the user changes test parameters
TH2D * bookTH2D(std::string sname, std::string title, int nbinsx, double xmin, double xmax, int nbinsy, double ymin, double max)
book a TH2D, adding version information to the name and title
Definition: PixTest.cc:903
double getTBia()
Definition: api.cc:424
virtual bool setParameter(std::string parName, std::string sval)
set the string value of a parameter
void update()
signal to PixTab to update the canvas
Definition: PixTest.cc:569
pxar::pxarCore * fApi
pointer to the API
Definition: PixTest.hh:289
uint16_t daqTrigger(uint32_t nTrig=1, uint16_t period=0)
Definition: api.cc:1222
void init()
sets all test parameters
Definition: PixTest.cc:62
void doTest()
function connected to "DoTest" button of PixTab
std::vector< std::pair< std::string, uint8_t > > getTbmDACs(size_t tbmId)
Definition: dut.cc:348
std::vector< rawEvent > daqGetRawEventBuffer()
Definition: api.cc:1270
void mDelay(uint32_t ms)
Definition: helper.h:40