pxar
All Classes Namespaces Functions Variables Typedefs Friends
PixTestCmd.cc
1 // -- author: Wolfram Erdmann
2 // opens up a command line window
3 
4 #include "PixTestCmd.hh"
5 #include "log.h"
6 #include "constants.h"
7 
8 #if (defined WIN32)
9 #include <Windows4Root.h> //needed before any ROOT header
10 #endif
11 
12 #include <TGLayout.h>
13 #include <TGClient.h>
14 #include <TGFrame.h>
15 
16 #include <iostream>
17 #include <fstream>
18 #include <algorithm>
19 #include <bitset>
20 
21 // #define DEBUG
22 
23 using namespace std;
24 using namespace pxar;
25 
26 ClassImp(PixTestCmd)
27 
28 //------------------------------------------------------------------------------
29 PixTestCmd::PixTestCmd( PixSetup *a, std::string name )
30 : PixTest(a, name)
31 {
32  PixTest::init();
33  init();
34 }
35 
36 //------------------------------------------------------------------------------
37 PixTestCmd::PixTestCmd() : PixTest()
38 {
39 }
40 
41 //------------------------------------------------------------------------------
42 bool PixTestCmd::setParameter( string parName, string sval )
43 {
44  if (parName == sval) return true; // silence the compiler warnings
45  return true;
46 }
47 
48 //------------------------------------------------------------------------------
49 void PixTestCmd::init()
50 {
51  LOG(logINFO) << "PixTestCmd::init()";
52  fDirectory = gFile->GetDirectory( fName.c_str() );
53  if( !fDirectory )
54  fDirectory = gFile->mkdir( fName.c_str() );
55  fDirectory->cd();
56 }
57 
58 // ----------------------------------------------------------------------
60 {
61  fTestTip = string( "void");
62  fSummaryTip = string("nothing to summarize here");
63 }
64 
65 //------------------------------------------------------------------------------
66 void PixTestCmd::bookHist(string name)
67 {
68  LOG(logDEBUG) << "nothing done with " << name;
69 }
70 
71 //------------------------------------------------------------------------------
72 PixTestCmd::~PixTestCmd()
73 {
74  LOG(logDEBUG) << "PixTestCmd dtor";
75  std::list<TH1*>::iterator il;
76  fDirectory->cd();
77  for( il = fHistList.begin(); il != fHistList.end(); ++il ) {
78  LOG(logINFO) << "Write out " << (*il)->GetName();
79  (*il)->SetDirectory(fDirectory);
80  (*il)->Write();
81  }
82 
83  // dump the history file for future use
84  ofstream fout(".history");
85  for(unsigned int i=max(0,(int)cmdHistory.size()-100); i<cmdHistory.size(); i++){
86  fout << cmdHistory[i] << endl;
87  }
88 
89 }
90 
91 void PixTestCmd::DoTextField(){
92  string s=commandLine->GetText();
93  transcript->SetForegroundColor(1);
94  transcript->AddLine((">"+s).c_str());
95  commandLine->SetText("");
96 
97  int stat = cmd->exec( s );
98  string reply=cmd->out.str();
99  if (reply.size()>0){
100 
101  // try color coding, doesn't really work with TGTextView
102  if(stat==0){
103  transcript->SetForegroundColor(0x0000ff);
104  }else{
105  transcript->SetForegroundColor(0xff0000);
106  }
107 
108  // break multiline output into lines
109  std::stringstream ss( reply );
110  std::string line;
111  int linecount=0;
112  while(std::getline(ss,line,'\n')){
113  transcript->AddLine( line.c_str() );
114  linecount++;
115  if (linecount>100000){
116  cout << "are you sure, this is line " << linecount << "\n" << line.c_str() << endl;
117  }
118  }
119  }
120 
121  transcript->ShowBottom();
122 
123  if ( (cmdHistory.size()==0) || (! (cmdHistory.back()==s))){
124  cmdHistory.push_back(s);
125  }
126  historyIndex=cmdHistory.size();
127 
128 }
129 void PixTestCmd::DoUpArrow(){
130  if (historyIndex>0) historyIndex--;
131  if (cmdHistory.size()>historyIndex){
132  commandLine->SetText(cmdHistory[historyIndex].c_str());
133  }
134 }
135 
136 void PixTestCmd::DoDnArrow(){
137  if (historyIndex<cmdHistory.size()){
138  historyIndex++;
139  }
140  if(historyIndex<cmdHistory.size()){
141  commandLine->SetText(cmdHistory[historyIndex].c_str());
142  }else{
143  commandLine->SetText("");
144  }
145 }
146 
147 void PixTestCmd::createWidgets(){
148  const TGWindow *main = gClient->GetRoot();
149  unsigned int w=600;
150  tf = new TGTransientFrame(gClient->GetRoot(), main, 600, 800);//w,h
151 
152  // == Transcript ============================================================================================
153 
154  textOutputFrame = new TGHorizontalFrame(tf, w, 400);
155  transcript = new TGTextView(textOutputFrame, w, 400);
156  textOutputFrame->AddFrame(transcript, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
157 
158  tf->AddFrame(textOutputFrame, new TGLayoutHints(kLHintsExpandX| kLHintsExpandY, 10, 10, 2, 2));
159 
160 
161  // == Command Line =============================================================================================
162 
163  cmdLineFrame = new TGHorizontalFrame(tf, w, 100);
164  commandLine = new TGTextEntry(cmdLineFrame, new TGTextBuffer(60));
165  commandLine->Connect("ReturnPressed()", "PixTestCmd", this, "DoTextField()");
166  commandLine->Connect("CursorOutUp()", "PixTestCmd", this, "DoUpArrow()");
167  commandLine->Connect("CursorOutDown()", "PixTestCmd", this, "DoDnArrow()");
168  cmdLineFrame->AddFrame(commandLine, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
169  tf->AddFrame(cmdLineFrame, new TGLayoutHints(kLHintsExpandX, 10, 10, 2, 2));
170  transcript->AddLine("Welcome to psi46expert!");
171  tf->MapSubwindows();
172  tf->Resize(tf->GetDefaultSize());
173  tf->MapWindow();
174 }
175 
176 //------------------------------------------------------------------------------
177 
179 {
180  LOG(logINFO) << "PixTestCmd::doTest() " ;
181 
182  fDirectory->cd();
183  fHistList.clear();
184 
185  // read the history file for future use
186  ifstream inputFile(".history");
187  if ( inputFile.is_open()){
188  string line;
189  while( getline( inputFile, line ) ){
190  cmdHistory.push_back(line);
191  }
192  historyIndex = cmdHistory.size();
193  }
194 
195  PixTest::update();
196 
197  createWidgets();
198  cmd = new CmdProc( );
199  cmd->setApi(fApi, fPixSetup);
200 
201  PixTest::update();
202  //fDisplayedHist = find( fHistList.begin(), fHistList.end(), h1 );
203 
204 }
205 
206 
207 
208 
209 
210 
211 /*====================================================================*/
212 /* command processor code */
213 /*====================================================================*/
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224 
225 
226 #include <sstream>
227 #include <string>
228 #include <iomanip>
229 
230 #include <iostream>
231 #include <fstream>
232 #include "dictionaries.h"
233 
234 /********************** Token handling with macros ********/
235 string Token::front(bool expand){
236  string t="";
237  if (stack.empty()){
238  t=token.front();
239  }else{
240  t=stack.back().front();
241  }
242  if (!expand) return t;
243  mi = macros->find(t);
244  if (mi==macros->end()) return t;
245  token.pop_front(); // remove the macro token!
246  stack.push_back(mi->second);
247  return front();
248 }
249 
250 void Token::pop_front(){
251  if (stack.empty()){
252  token.pop_front();
253  }else{
254  if(stack.back().empty()){cerr << "bug alert" << endl; return;}
255  stack.back().pop_front();
256  if (stack.back().empty()){stack.pop_back();};
257  }
258 }
259 void Token::push_front(string s){
260  if (stack.empty()){
261  token.push_front(s);
262  }else{
263  stack.back().push_front(s);
264  }
265 }
266 
267 bool Token::assignment(string& name){
268  // two-symbol-look-ahead kludge for assignments
269  // returns the name in front of the assignment operator if there is one
270  // otherwise restores the token queue as if nothing ever happened
271  name = front(false);
272  pop_front();
273  if (!(empty())&& (front(false)=="=")){
274  pop_front();
275  return true;
276  }else{
277  //restore and return false
278  push_front(name);
279  return false;
280  }
281 }
282 
283 /***** generic parser tools, mostly recycled from psi46expert/syscmd *****/
284 
285 bool StrToI(string word, int & v)
286 /* convert strings to integers. Numbers are assumed to
287  be integers unless preceded by "0x", in which
288  case they are taken to be hexadecimal,
289  the return value is false if an error occured
290 */
291 
292 {
293  const char * digits = "0123456789abcdef";
294  int base;
295  int i;
296  const char * d0 = strchr(digits, '0');
297 
298  int len = word.size();
299  if ((len>0) && (word[0] == '$')) {
300  base = 16;
301  i = 1;
302  } else if ((len>1) && (word[0] == '0') && (word[1] == 'x')) {
303  base = 16;
304  i = 2;
305  } else if ((len>1) && (word[0] == 'b') && ((word[1]== '0')||(word[1])=='1')) {
306  base = 2;
307  i = 1;
308  } else {
309  base = 10;
310  i = 0;
311  }
312 
313 
314  int a = 0;
315  const char * d;
316  while ((i < len) && ((d = strchr(digits, word[i])) != NULL) && (d-d0<base) ) {
317  a = base * a + d - d0;
318  i++;
319  }
320 
321  v = a;
322  if (i == len) {return true; } else { return false;}
323 
324 }
325 
326 
327 int Arg::varvalue =0;
328 
329 
330 bool IntList::parse(Token & token, const bool append){
331  /* parse a list of integers (rocs, rows, columns..), such as
332  * 1:5,8:16 or 1,2,5,7
333  * hexadecimal values are allowed (see StrToI)
334  * equivalent of parseIntegerList in SysCmd with wildcard support
335  */
336  if (!append) ranges.clear();
337 
338  if ( (token.front()=="*") ){
339  token.pop_front();
340  ranges.push_back( make_pair( IMIN, IMAX ) );
341  singleValue = UNDEFINED;
342  }else if( (token.front()=="%") ){
343  token.pop_front();
344  ranges.push_back( make_pair( IVAR, IVAR ) );
345  singleValue = IVAR;
346  }else{
347  int i1,i2 ; // for ranges
348  do {
349  if (token.front()==":"){
350  cout << "this shouldn't really happen anymore" << endl;
351  i1 = IMIN;
352  i2 = IMAX; // in case nothing else follows
353  }else if( token.front()=="~" ){
354  i1=IMIN;
355  token.pop_front();
356  }else{
357  if ( StrToI(token.front(), i1)) {
358  token.pop_front();
359  }else{
360  return false; // not an IntList
361  }
362  }
363  // optionally followed by :i2 to define a range
364  if ( (!token.empty()) && (token.front()==":")){
365  token.pop_front();
366  if (token.empty()){
367  i2=IMAX;
368  }else{
369  if (StrToI(token.front(), i2)) {
370  token.pop_front();
371  }else if(token.front()=="~"){
372  token.pop_front();
373  i2=IMAX;
374  }else{
375  cout << "syntax error parsing integer list" << endl;
376  return false;
377  }
378  }
379  }else{
380  i2=i1; // just one value
381  }
382  ranges.push_back( make_pair( i1, i2 ) );
383  if ((ranges.size()==1) && (i1==i2)){
384  singleValue = i1;
385  }else{
386  singleValue = UNDEFINED;
387  }
388 
389  // continue until no more comma separated list elements found
390  if ( (!token.empty()) && (token.front()==",")){
391  token.pop_front();
392  }else{
393  break;
394  }
395  } while (!token.empty());
396  // end of the list reached
397  }
398 #ifdef DEBUG
399  cout << "IntList #ranges=" << ranges.size() << " single=" << (!(singleValue==UNDEFINED)) << endl;
400  for(unsigned int i=0; i<ranges.size(); i++){cout << ranges[i].first << ":" << ranges[i].second << endl;}
401  cout << "---------" << endl;
402 #endif
403  return true;
404 }
405 
406 vector<int> IntList::getVect(const int imin, const int imax){
407  vector<int> IntList;
408  for(unsigned int j=0; j<ranges.size(); j++){
409  int i1 = ranges[j].first;
410  int i2 = ranges[j].second;
411 
412  if( i1 == IMIN ){ i1=imin;}
413  else if (i1 == IVAR ){ i1=Arg::varvalue;}
414 
415  if( i2 == IMAX ){ i2=imax;}
416  else if(i2 == IVAR){ i2=Arg::varvalue;}
417 
418  for(int i=i1; i<i2+1; i++){
419  IntList.push_back(i);
420  }
421  }
422  return IntList;
423 }
424 
425 
426 
427 
428 bool is_whitespace(unsigned int i, const string & s){
429  if ( i<s.size() ){
430  return (s[i]==' ') || (s[i]=='\n')||(s[i]=='\t');
431  }else{
432  return false;
433  }
434 }
435 
436 
437 string findchar(char c, unsigned int & i, string s){
438  // starting from position i, find the next occurence of character
439  // c in in string s and return everything up-to (but excluding) c
440  // as a string, afterwards
441  // on exit, i points to c
442  string word;
443  while( i<s.size() && !(s[++i]==c)){
444  word.push_back(s[i]);
445  }
446  return word;
447 }
448 
449 
450 
451 deque <string > getWords(const string & s){
452  // chop a string into words
453  deque<string> words;
454  unsigned int i=0;
455  const char * symbols="\",:()[];=\n";
456 
457  while( is_whitespace(i,s) ){i++;};
458 
459  string word="";
460  while( i<s.size() ){
461 
462 
463  if (s[i]=='"'){
464  word = findchar('"',i,s);
465  if ((i<s.size()) && (s[i]=='"')) i++;
466  }else if ( strchr(symbols, s[i]) != NULL){
467  word.push_back(s[i++]);
468  }else{
469  while( (i<s.size()) && (! is_whitespace(i,s))
470  && (strchr(symbols, s[i]) == NULL) ) {
471  word.push_back(s[i++]);
472  }
473  }
474 
475  if(word==":"){
476  // special treatment of whitespace around colons to allow
477  // Beats range notation such as pixe 5: 7:10
478  if((i>1)&& is_whitespace(i-2,s)){
479  words.push_back("~");
480  }
481  words.push_back(word);
482  if( (i>=s.size()) || is_whitespace(i,s) ){
483  words.push_back("~");
484  }
485  }else{
486  words.push_back(word);
487  }
488 
489  word="";
490  while( is_whitespace(i,s) ){i++;};
491 
492  }
493 
494 #ifdef DEBUG
495  cout<< "getwords" <<endl;
496  for(unsigned int i=0; i< words.size(); i++){ cout << i << " " << words[i] << endl;}
497 #endif
498 
499  return words;
500 }
501 
502 string Target::str(){
503  stringstream s;
504  s<<"["<<name;
505  if (name=="roc"){
506  if(!expanded) { expand(0, 15);}
507  for(unsigned int i=0; i<ivalues.size()-1; i++){
508  s<< " " << ivalues[i] << ",";
509  }
510  s<<" "<<ivalues[ivalues.size()-1];
511  }
512  s<<"]";
513  return s.str();
514 }
515 
516 /*********************** syntax element parsers ***********************/
517 
518 bool Target::parse(Token & token){
519 
520  if (token.empty()) return false;
521 
522  name = token.front();
523  if ((name=="roc")||(name=="do")) {
524  token.pop_front();
525  if (!token.empty()){
526  lvalues.parse( token );
527  }
528  return true;
529  }else if ((name=="tbm") || (name=="tbma") || (name=="tbmb") || (name=="tb")) {
530  token.pop_front();
531  return true;
532  }else{
533  return false; // not a target
534  }
535  return false;
536 }
537 
538 
539 bool Statement::parse(Token & token){
540  /*
541  statement := [ [<target>] [<keyword> <arguments>* | block] ]
542  | <name> "=" [value | block]
543  */
544  if (token.empty()) return false;
545 
546  if ( token.assignment( name ) ){
547  isAssignment = true;
548  if (token.front()=="["){
549 
550  // macro definition
551  deque<string> macro;
552  int n=0;
553  do{
554  string t=token.front();
555  if(t=="["){ n++;} else if (t=="]"){ n--;}
556  macro.push_back(t);
557  token.pop_front();
558  }while((n>0)&&(!token.empty()));
559 
560  if (n==0){
561  cout << "Statement::parse adding macro " << name << endl;
562  token.add_macro(name, macro);
563  return true;
564  }else{
565  cerr << "error in macro definition" << endl;
566  return false;
567  }
568 
569  }else{
570  block=NULL;
571  //cout << "value list definition not implemented yet" <<endl;
572  //return parseIntegerList(token, values); // dummy code
573  }
574  return false; // shouldn't get here
575  }
576 
577  isAssignment=false;
578  has_localTarget = localTarget.parse( token );
579 
580 
581  if (token.empty()){
582  // nothing follows
583  block=NULL;
584  keyword.keyword="";
585  }else{
586 
587  // ... followed by keyword or block ?
588  if( token.front()=="["){
589 
590  // parse block
591  block = new Block();
592  block->parse( token );
593 
594  }else if (!(token.front()==";")){
595 
596  // parse keyword + args
597  block=NULL;
598  keyword = Keyword( token.front() );
599  token.pop_front();
600  IntList IntList;
601  while( (!token.empty()) && !( (token.front()==";") || (token.front()=="]") || (token.front()==">") ) ){
602  if (IntList.parse(token)){
603  keyword.argv.push_back(IntList);
604  }else{
605  keyword.argv.push_back(token.front());
606  token.pop_front();
607  }
608  }
609 
610  }else{
611  cerr << "syntax error?" << endl;
612  return false;
613  }
614 
615  // redirection ?
616  if(!(token.empty()) && (token.front()==">")){
617  token.pop_front();
618  if (!(token.empty())){
619  out_filename = token.front();
620  token.pop_front();
621  redirected=true;
622  }else{
623  cerr << "expected filename after '>' " << endl;
624  return false;
625  }
626  }
627  }
628  return true;
629 }
630 
631 
632 
633 bool Block::parse(Token & token){
634  /*
635  block := "[" <statement> ( ";" <statement> )* "]"
636  */
637  if (token.empty()) return false;
638  stmts.clear();
639  if ( !(token.front()=="[") ) return false;
640  token.pop_front();
641 
642  while( !token.empty() ){
643  Statement * st = new Statement();
644  bool stat = st->parse( token );
645  if (! stat) return false;
646  stmts.push_back( st );
647 
648  if (!token.empty()){
649  if (token.front()=="]"){
650  token.pop_front();
651  break;
652  } else if (token.front()==";"){
653  token.pop_front();
654  }else{
655  cerr << "expected ';' instead of " << token.front() << endl;
656  return false;
657  }
658  }
659 
660  }
661  //cout << "parsed block with size " << stmts.size() << endl;
662  return true;
663 }
664 
665 
666 /*********************** keyword decoding helpers**********************/
667 
668 
669 bool Keyword::match(const char * s, int & value){
670  return (kw(s)) && (narg()==1) && (argv[0].getInt(value));
671 }
672 
673 bool Keyword::match(const char * s, int & value, const char * s1){
674  return (kw(s)) && (narg()==2) && (argv[0].getInt(value)) && (argv[1].scmp(s1)) ;
675 }
676 
677 bool Keyword::match(const char * s1, const char * s2, int & value){
678  return (kw(s1)) && (narg()==2) && (argv[0].scmp(s2)) && (argv[1].getInt(value));
679 }
680 
681 bool Keyword::match(const char * s, const char * s1){
682  if (narg() !=1 ) return false;
683  return (kw(s)) && (narg()==1) && (argv[0].scmp(s1));
684 }
685 
686 bool Keyword::match(const char * s, const char * s1, string & s2){
687  if (narg() !=1 ) return false;
688  return (kw(s)) && (narg()==2) && (argv[0].scmp(s1)) && (argv[1].getString(s2));
689 }
690 
691 
692 bool Keyword::match(const char * s, string & s1, vector<string> & options, ostream & err){
693  if (narg() !=1 ) return false;
694  s1 = "";
695  if ( (kw(s)) && (narg()==1) ){
696  for(unsigned int i=0; i<options.size(); i++){
697  if ( argv[0].svalue==options[i] ){
698  s1 = argv[0].svalue;
699  return true;
700  }
701  }
702  err << "possible options for keyword "<< s << " are :\n";
703  for(unsigned int i=0; i<options.size(); i++){
704  err << " " <<options[i];
705  }
706  err << "\n";
707  return false;
708  }
709  return false;
710 }
711 
712 
713 bool Keyword::greedy_match(const char * s1, string & s2){
714  if (! kw(s1) ) return false;
715  s2="";
716  for(unsigned int i=0; i<narg(); i++){ s2+=argv[i].str();}
717  return true;
718 }
719 
720 bool Keyword::match(const char * s, int & value1, int & value2){
721  return (kw(s)) && (narg()==2) && (argv[0].getInt(value1)) && (argv[1].getInt(value2));
722 }
723 
724 bool Keyword::match(const char * s, int & value1, int & value2, int & value3){
725  return (kw(s)) && (narg()==3) && (argv[0].getInt(value1)) && (argv[1].getInt(value2)) && (argv[2].getInt(value3));
726 }
727 
728 bool Keyword::greedy_match(const char * s1, int& value1, int& value2, int& value3, string & s2){
729  return (kw(s1)) && (narg()>2) && (argv[0].getInt(value1))
730  && (argv[1].getInt(value2)) && (argv[2].getInt(value3))
731  && concat(3, s2 );
732 }
733 
734 bool Keyword::match(const char * s1, string & s2){
735  return (kw(s1)) && (narg()==1) && (argv[0].getString(s2));
736 }
737 
738 
739 bool Keyword::match(const char * s, vector<int> & v1, vector<int> & v2){
740  return (kw(s)) && (narg()==2) && (argv[0].getVect(v1)) && (argv[1].getVect(v2));
741 }
742 
743 bool Keyword::match(const char * s, vector<int> & v1, const int i1min, const int i1max,
744  vector<int> & v2, const int i2min, const int i2max){
745  return (kw(s)) && (narg()==2) && (argv[0].getVect(v1, i1min, i1max)) && (argv[1].getVect(v2, i2min, i2max));
746 }
747 
748 string Keyword::str(){
749  stringstream s;
750  s << keyword << "(";
751  for(unsigned int i=0; i<narg(); i++){
752  s << argv[i].str();
753  if (i+1<narg()) s <<",";
754  }
755  s << ")";
756  return s.str();
757 }
758 /****************** execution / processing **************************/
759 
760 
761 bool Block::exec(CmdProc * proc, Target & target){
762  bool success=true;
763  for (unsigned int i=0; i<stmts.size(); i++){
764  success |= stmts[i]->exec(proc, target);
765  }
766  return success;
767 }
768 
769 
770 
771 bool Statement::exec(CmdProc * proc, Target & target){
772 
773 
774  if (isAssignment){
775  //proc->setVariable( targets.name, block );
776  return true;
777 
778  }else{
779 
780 
781  if( has_localTarget && (block==NULL) && (keyword.keyword=="") ){
782  // just a target definition, set the default
783  proc->setDefaultTarget( localTarget );
784  proc->out << "target set to " << proc->defaultTarget.str();
785  return true;
786  }
787 
788  Target useTarget;
789  if( has_localTarget ){
790  useTarget = localTarget;
791  }else{
792  useTarget = target;
793  }
794 
795 
796  bool stat=false;
797  if ( (block==NULL) && !(keyword.keyword=="") ){
798  // keyword + arguments ==> execute
799  if(useTarget.name=="roc"){
800  useTarget.expand( 0, 15 );
801  for(unsigned int i=0; i<useTarget.size(); i++){
802  Target t = useTarget.get(i);
803  if (! (proc->process(keyword, t, has_localTarget))) return false;
804  }
805  stat = true;
806  }else if(useTarget.name=="do"){
807  useTarget.expand(0, 100);
808  for(unsigned int i=0; i< useTarget.size(); i++){
809  Target t = useTarget.get(i);
810  Arg::varvalue = t.value();
811  if (!(proc->process(keyword, t, false) )) return false;
812  }
813  stat = true;
814  }else{
815  stat = proc->process(keyword, useTarget, has_localTarget);
816  }
817 
818  }else if (!(block==NULL) ){
819 
820  // block
821  if(useTarget.name=="roc"){
822  useTarget.expand( 0, 15 );
823  for(unsigned int i=0; i< useTarget.size(); i++){
824  Target t = useTarget.get(i);
825  if (!(block->exec(proc, t) )) return false;
826  }
827  stat = true;
828  }else if(useTarget.name=="do"){
829  useTarget.expand(0, 100);
830  for(unsigned int i=0; i< useTarget.size(); i++){
831  Target t = useTarget.get(i);
832  Arg::varvalue = t.value();
833  if (!(block->exec(proc, t) )) return false;
834  }
835  stat = true;
836  }else{
837  stat = block->exec(proc, useTarget);
838  }
839 
840  }else{
841 
842  // should not be here
843  stat = false;
844 
845  }
846 
847  if( redirected ){
848  ofstream fout;
849  fout.open( out_filename.c_str());
850  if(fout){
851  fout << proc->out.str();
852  proc->out.str("");
853  fout.close();
854  }else{
855  cerr << "unable to open " << out_filename << endl;
856  }
857  }
858  return stat;
859 
860  }
861  return false;// should not get here
862 }
863 
864 
865 
866 /* Command Processor */
867 const unsigned int CmdProc::fnDAC_names=19;
868 const char * const CmdProc::fDAC_names[CmdProc::fnDAC_names] =
869  {"vdig","vana","vsh","vcomp","vwllpr","vwllsh","vhlddel","vtrim","vthrcomp",
870  "vibias_bus","phoffset","vcomp_adc","phscale","vicolor","vcal",
871  "caldel","ctrlreg","wbc","readback"};
872 
873 int CmdProc::fGetBufMethod = 1;
874 int CmdProc::fPrerun=0;
875 bool CmdProc::fFW35=false;
876 
877 void CmdProc::init()
878 {
879  /* note: fApi may not be defined yet !*/
880  verbose=false;
881  defaultTarget = Target("roc",0);
882  _dict = RegisterDictionary::getInstance();
883  _probeDict = ProbeDictionary::getInstance();
884  fA_names = _probeDict->getAllAnalogNames();
885  fD_names = _probeDict->getAllDigitalNames();
886  fGetBufMethod = 1;
887  fPixelConfigNeeded = true;
888  fTCT = 105;
889  fTRC = 10;
890  fTTK = 30;
891  fBufsize = 100000;
892  fSeq = 7; // pg sequence bits
893  fPeriod = 0;
894  fPgRunning = false;
895  //fSignalLevel=255;
896  macros["start"] = getWords("[roc * mask; roc * cald; reset tbm; seq 14]");
897  macros["startroc"] = getWords("[mask; seq 15; arm 20 20; tct 106; vcal 200; adc]");
898  macros["tbmonly"] = getWords("[reset tbm; tbm disable triggers; seq 10; adc]");
899  out.str("");
900 }
901 
902 void CmdProc::setApi(pxar::pxarCore * api, PixSetup * setup){
903  /* set api instance and do related setups */
904  fApi = api;
905  fPixSetup = setup;
906 
907  ConfigParameters *p = fPixSetup->getConfigParameters();
908  if (fSigdelaysSetup.size()==0){
909  fSigdelaysSetup = p->getTbSigDelays();
910  fSigdelays = p->getTbSigDelays();
911  }
912 
913 }
914 
915 
916 CmdProc::CmdProc(CmdProc * p)
917 {
918  init();
919  verbose = p->verbose;
920  defaultTarget = p->defaultTarget;
921  fSeq = p->fSeq;
922  fPeriod = p->fPeriod;
923  fPgRunning = p->fPgRunning;
924  fTCT = p->fTCT;
925  fTRC = p->fTRC;
926  fTTK = p->fTTK;
927  //fSignalLevel = p->fSignalLevel;
928  fBufsize=p->fBufsize;
929  macros = p->macros;
930  fSigdelaysSetup = p->fSigdelaysSetup;
931  setApi( p->fApi, p->fPixSetup);
932  //fApi = p->fApi;
933  //fPixSetup = p->fPixSetup;
934 }
935 
936 CmdProc::~CmdProc(){
937 }
938 
939 /**************** implement some hardware functionalities *************/
940 
941 
942 int CmdProc::tbmset(int address, int value){
943 
944  /* emulate direct access via register address */
945  uint8_t core;
946  uint8_t base = (address & 0xF0);
947  if( base == 0xF0){ core = 1;}
948  else if(base==0xE0){ core = 0;}
949  else {out << "bad tbm register address "<< hex << address << dec << "\n"; return 1;};
950 
951  uint8_t idx = (address & 0x0F) >> 1;
952  const char* apinames[] = {"base0", "base2", "base4","invalid","base8","basea","basec","basee"};
953  fApi->setTbmReg( apinames[ idx], value, core );
954 
955  return 0; // nonzero values for errors
956 }
957 
958 int CmdProc::tbmget(string name, const uint8_t core, uint8_t & value){
959  /* get a tbm register value as cached by the api
960  */
961 
962  int error=1;
963  std::vector< std::pair<std::string,uint8_t> > regs = fApi->_dut->getTbmDACs(core);
964  for(unsigned int i=0; i<regs.size(); i++){
965  if (name==regs[i].first){ value = regs[i].second; error=0;}
966  }
967 
968  return error; // nonzero values for errors
969 }
970 
971 
972 int CmdProc::tbmset(string name, uint8_t cores, int value, uint8_t valueMask){
973  /* set a tbm register, allow setting a subset of bits (thoese where mask=1)
974  * the default value of mask is 0xff, i.e. all bits are changed
975  * the cores = 0:TBMA, 1:TBMB, >1 TBMA+TBMB
976  *
977  */
978  if ((value & (~valueMask) )>0) {
979  out << "Warning! tbm set value " << hex << (int) value
980  << " has bits outside mask ("<<hex<< (int) valueMask << ")\n";
981  }
982 
983  uint8_t coreMask = 3;
984  if (cores==0){coreMask=1;} else if(cores==1){ coreMask=2;}
985 
986  int err=1;
987  //out << "tbmset" << name << " " << (int) coreMask << " " << value << " " << bitset<8>(valueMask) << "\n";
988  for(size_t core=0; core<2; core++){
989  if ( ((coreMask >> core) & 1) == 1 ){
990  std::vector< std::pair<std::string,uint8_t> > regs = fApi->_dut->getTbmDACs(core);
991  if (regs.size()==0) {
992  out << "TBM registers not set !?! This is not going to work.\n";
993  }
994  for(unsigned int i=0; i<regs.size(); i++){
995  if (name==regs[i].first){
996  // found it , do something
997  uint8_t present = regs[i].second;
998  uint8_t update = value & valueMask;
999  update |= (present & (~valueMask) );
1000  if(verbose){
1001  out << "changing tbm reg " << name << "["<<core<<"]";
1002  out << " from 0x" << hex << (int) regs[i].second;
1003  out << " to 0x" << hex << (int) update << "\n";
1004  }
1005  fApi->setTbmReg( name, update, core );
1006  err=0;
1007  }
1008  }
1009  }
1010  }
1011  return err; // nonzero values for errors
1012 }
1013 
1014 
1015 int CmdProc::tbmsetbit(string name, uint8_t coreMask, int bit, int value){
1016  /* set individual bits */
1017  return tbmset(name, coreMask, (value & 1)<<bit, 1<<bit);
1018 }
1019 
1020 
1021 
1022 int CmdProc::countHits(){
1023  int nhit=0;
1024  vector<DRecord > data;
1025  int stat = runDaq(fBuf, 1, 0, 0);
1026  if (stat>0) return -1;
1027  stat = getData(fBuf, data, 0);
1028  if (stat>0) return -2;
1029  for(unsigned int i=0; i<data.size(); i++){
1030  if (data[i].type==0) nhit++;
1031  }
1032  return nhit;
1033 }
1034 
1035 
1036 
1037 int CmdProc::countErrors(unsigned int ntrig, int ftrigkhz, int nroc, bool setup){
1038  int stat = runDaq(fBuf, ntrig, ftrigkhz, 0, setup);
1039  if (stat>0) return -1; // no data
1040  vector<DRecord > data;
1041  data.clear();
1042  stat = getData(fBuf, data, 0, nroc);
1043  if (stat>0){
1044  return stat;
1045  }else{
1046  if (fNumberOfEvents==ntrig) return 0;
1047  if(verbose) cout << "number of events (" << fNumberOfEvents << ") does not match triggers "<< ntrig << endl;
1048  return 999;
1049  }
1050 }
1051 
1052 
1053 int CmdProc::countGood(unsigned int nloop, unsigned int ntrig, int ftrigkhz, int nroc){
1054  tbmset("base4", 2, 0x80);// reset once
1055  int good=0;
1056  setupDaq(ntrig, ftrigkhz, 0);
1057  for(unsigned int k=0; k<nloop; k++){
1058  if (fFW35) tbmset("base4", 2, 0x80); // temp fix, avoid event counter reaching 255
1059  if(fPrerun>0) runDaq(fPrerun, 10);
1060  int nerr=countErrors(ntrig, ftrigkhz, nroc,false);
1061  if(nerr==0){
1062  good++;
1063  }
1064  for( unsigned int i=0;i<8; i++){
1065  fDeser400XOR1sum[i] += ( (fDeser400XOR1 >> i) & 1);
1066  }
1067  }
1068  restoreDaq();
1069  return good;
1070 }
1071 
1072 
1073 int CmdProc::tctscan(unsigned int tctmin, unsigned int tctmax){
1074  unsigned int tct0 = fTCT;
1075 
1076  if (tctmin==tctmax){
1077  tctmin = (fTCT>20) ? fTCT - 20 : 0;
1078  tctmax = fTCT + 20;
1079  }
1080 
1081  std::vector< uint8_t > rocids = fApi->_dut->getRocI2Caddr();
1082  if (rocids.size()==0){
1083  out << "no rocs connected?\n";
1084  return 0;
1085  }
1086 
1087  int wbc=fApi->_dut->getDAC(rocids[0], "wbc");
1088 
1089 
1090  // avoid the reset region in scans
1091  if(( (fSeq & 0x40)>0 ) && (tctmin < (wbc - fTRC) )){
1092  tctmin = wbc-fTRC;
1093  }
1094 
1095 
1096  unsigned int tct1=tct0;
1097  int n1=0;
1098  for(fTCT = tctmin; fTCT<=tctmax; fTCT++){
1099  int nhit=0;
1100  for(unsigned i=0; i<10; i++) nhit +=countHits();
1101  if (nhit>0){
1102  out << "tct=" << dec << fTCT << " hits=" << nhit << "\n";
1103  if (nhit>n1){ n1=nhit; tct1=fTCT;}
1104  }
1105  }
1106 
1107  if (n1>0){
1108  out << "tct set to " << tct1 << "\n";
1109  fTCT = tct1;
1110  }else{
1111  out << "no hits found, leaving tct at " << dec << tct0 <<"\n";
1112  fTCT = tct0;
1113  }
1114  return 0;
1115 }
1116 
1117 int CmdProc::tbmscan(){
1118  uint8_t phasereg;
1119  int stat = tbmget("basee", 0, phasereg);
1120  if(stat>0){
1121  out << "error getting tbm delays from api \n";
1122  }
1123  uint8_t p400c= (phasereg>>2) & 7;
1124  uint8_t p160c= (phasereg>>5) & 7;
1125 
1126  uint8_t ntpreg;
1127  stat = tbmget("base0", 0, ntpreg);
1128  if(stat>0){
1129  out << "error getting base0 register from api \n";
1130  }
1131 
1132  int nroc=16;
1133  if( (ntpreg & 0x40) > 0 ){
1134  nroc=0;
1135  }
1136 
1137  out << "400\\160 0 1 2 3 4 5 6 7\n";
1138  for(uint8_t p400=0; p400<8; p400++){
1139  int xor1[8] = {0,0,0,0,0,0,0,0};
1140  out << " " << (int) p400 << " : ";
1141  for(uint8_t p160=0; p160<8; p160++){
1142  stat = tbmset("basee", 0, ((p160&7)<<5)+((p400&7)<<2));
1143  if(stat>0){
1144  out << "error setting delay base E " << hex << ((p160<<5)+(p400<<2)) << dec << "\n";
1145  }
1146  tbmset("base4", 2, 0x80);// reset once after changing phases
1147 
1148  int good= countGood(10, 100, 10, nroc);
1149  for(unsigned int i=0; i<8; i++){
1150  xor1[i] += good*fDeser400XOR1sum[i];
1151  }
1152  char c=' ';
1153  if (good==10){ c='+';}
1154  else if (good>7) { c='o' ;}
1155  else if (good>0) { c='.' ;}
1156 
1157  if((p160==p160c)&&(p400==p400c)){
1158  out << "(" << c << ")";
1159  }else{
1160  out << " " << c << " ";
1161  }
1162  }
1163 
1164  // only print phases when they can be real
1165  if( (ntpreg & 0x40) == 0 ){
1166  out << " ";
1167  for(unsigned int i=0; i<8; i++){
1168  out << dec<< setw(4) << xor1[7-i];
1169  }
1170  }
1171  out << "\n";
1172  }
1173  tbmset("basee",0,phasereg);
1174  return 0;
1175 }
1176 
1177 
1178 
1179 
1180 int CmdProc::rawscan(int level){
1181  uint8_t phasereg;
1182  int stat = tbmget("basee", 0, phasereg);
1183  if(stat>0){
1184  out << "error getting tbm delays from api \n";
1185  }
1186 
1187  uint8_t ntpreg;
1188  stat = tbmget("base0", 0, ntpreg);
1189  if(stat>0){
1190  out << "error getting base0 register from api \n";
1191  }
1192 
1193  out << "400\\160 0 1 2 3 4 5 6 7\n";
1194  for(uint8_t p400=0; p400<8; p400++){
1195  out << " " << (int) p400 << " : ";
1196  for(uint8_t p160=0; p160<8; p160++){
1197  stat = tbmset("basee", 0, ((p160&7)<<5)+((p400&7)<<2));
1198  if(stat>0){
1199  out << "error setting delay base E " << hex << ((p160<<5)+(p400<<2)) << dec << "\n";
1200  }
1201  tbmset("base4", 2, 0x80);// reset once after changing phases
1202 
1203  int stat = runDaq(fBuf, 100, 10, 0, true);
1204 
1205  int n=0;
1206  if (stat==0){
1207  if (level==0){
1208  n = fBuf.size();
1209  }else{
1210  for(unsigned int i=0; i<fBuf.size(); i++){
1211  if ((fBuf[i]&0xE000)==0xA000){
1212  n+=1;
1213  }
1214  }
1215  }
1216  }
1217 
1218  out << (dec) << setw(5) << n ;
1219  }
1220 
1221 
1222  out << "\n";
1223  }
1224  tbmset("basee",0,phasereg);
1225  return 0;
1226 }
1227 
1228 
1229 int CmdProc::rocscan(){
1230  uint8_t phasereg0, phasereg1;
1231  int stat = tbmget("basea", 0, phasereg0) + tbmget("basea", 1, phasereg1);
1232  if(stat>0){
1233  out << "failed to get tbm registers from api\n";
1234  }
1235 
1236  uint8_t thbits0= (phasereg0 & 0xC0);
1237  //uint8_t thbits1= (phasereg1 & 0xC0);
1238 
1239  out << "token 0 | 1 |\n";
1240  out << "h/t 0 | 1 | 0 | 1 |\n" ;
1241  out << "rocs:-----------------|\n";
1242  for(uint8_t dly=0; dly<8; dly++){
1243  out << " " << dec << (int) dly << " : ";
1244  for(uint8_t th=0; th<4; th++){
1245  tbmset("basea", 0, (th<<6) | (dly<<3) | (dly));
1246  tbmset("basea", 1, (th<<6) | (dly<<3) | (dly));
1247 
1248  int good=0; //
1249  for(unsigned int k=0; k<10; k++){
1250  good += ( (countErrors(100,1)==0) ? 1 : 0);
1251  }
1252  char c=' ';
1253  if (good==10){ c='+';}
1254  else if (good>7) { c='o' ;}
1255  else if (good>0) { c='.' ;}
1256 
1257  if( (dly==(phasereg0&0x7)) && (th==(thbits0>>6)) ){
1258  out << "(" << c << ")|";
1259  }else{
1260  out << " " << c << " |";
1261  }
1262 
1263  }
1264  out << "\n";
1265  }
1266  tbmset("basea",0,phasereg0);
1267  tbmset("basea",1,phasereg1);
1268  return 0;
1269 }
1270 
1271 
1272 
1273 int CmdProc::levelscan(){
1274 
1275  ConfigParameters *p = fPixSetup->getConfigParameters();
1276  if (fSigdelaysSetup.size()==0){
1277  fSigdelaysSetup = p->getTbSigDelays();
1278  fSigdelays = p->getTbSigDelays();
1279  }
1280  int l0=0;
1281  for(size_t i=0; i<fSigdelays.size(); i++){
1282  if (fSigdelays[i].first=="level"){ l0=fSigdelays[i].second;}
1283  }
1284  int nroc=16;
1285 
1286  for(unsigned int level=3; level<16; level++){
1287 
1288  setTestboardDelay("level", level);
1289  if (fFW35) tbmset("base4", 2, 0x80); // temp fix, avoid event counter reaching 255
1290 
1291  int good = countGood(100,1,0,nroc);
1292 
1293  out << dec << setw(3) << level << " : ";
1294  out << setw(5) << good << " ";
1295 
1296  for(unsigned int i=0; i<8; i++){
1297  out << dec<< setw(4) << fDeser400XOR1sum[7-i];
1298  }
1299  out << "\n";
1300 
1301  }
1302 
1303  setTestboardDelay("level",l0);
1304  return 0;
1305 }
1306 
1307 int CmdProc::setTestboardPower(string name, uint16_t value){
1308  std::vector<std::pair<std::string,double> > power_settings;
1309  power_settings.push_back(make_pair(name, 0.001*float(value)));
1310  try{
1311  fApi->setTestboardPower(power_settings);
1312  return 0;
1313  }catch(pxar::InvalidConfig){
1314  out << "invalid config \n";
1315  return 1;
1316  }
1317 
1318 }
1319 
1320 int CmdProc::setTestboardDelay(string name, uint8_t value){
1321 
1322  ConfigParameters *p = fPixSetup->getConfigParameters();
1323  if (fSigdelaysSetup.size()==0){
1324  fSigdelaysSetup = p->getTbSigDelays();
1325  fSigdelays = p->getTbSigDelays();
1326  }else{
1327  // FIXME check whether gui values have changed
1328  vector<pair<string,uint8_t> > sigdelays;
1329  sigdelays = p->getTbSigDelays();
1330  }
1331 
1332 
1333  for(size_t i=0; i<fSigdelays.size(); i++){
1334  if (fSigdelays[i].first==name){
1335  fSigdelays[i] = std::make_pair(name, value);
1336  }
1337  //cout << fSigdelays[i].first << " : " << (int) fSigdelays[i].second << endl;
1338  }
1339  fApi->setTestboardDelays( fSigdelays );
1340 
1341  return 0;
1342 }
1343 
1344 
1345 
1346 int CmdProc::bursttest(int ntrig, int trigsep, int nburst){
1347  burst(fBuf, ntrig, trigsep, nburst);
1348 
1349  vector<DRecord > data;
1350  int stat = getData(fBuf, data, 0);
1351 
1352  int n=0;
1353  for(unsigned int i=0; i<fBuf.size(); i++){
1354  if((fBuf[i]&0xe000)==0xa000) {
1355  if(i>0) out << "\n";
1356  out << dec << setfill(' ') << setw(4) << ++n << ": ";
1357  }
1358  out << setw(4) << setfill('0') << hex << fBuf[i] << " ";
1359  }
1360  out << setfill(' ') << endl;
1361  out << dec << stat << " errors\n";
1362  return 0;
1363 }
1364 
1365 
1366 
1367 int CmdProc::adctest(const string signalName){
1368 
1369  // part 1 , acquire data : delay scan
1370 
1371 
1372  uint8_t gain = GAIN_1;
1373  uint8_t source = 1; // pg_sync
1374  uint8_t start = 1; // wait
1375  double scale=0.5; // empirical for gain 1 ("+"-"-"), note that
1376  // a 50 Ohm terminated oscilloscope shows only half of that
1377  if ( signalName=="sda"){
1378  source = 2; // trigger on sda
1379  start = 7;
1380  }else if ( signalName=="rda"){
1381  source = 2; // trigger on sda
1382  start = 17;
1383  }else if ( signalName=="ctr"){
1384  vector< pair<string, uint8_t> > pgsetup;
1385  pgsetup.push_back( make_pair("sync", 20 ) );
1386  // give the adc something to look at
1387  pgsetup.push_back( make_pair("resr", 20 ) );
1388  pgsetup.push_back( make_pair("cal", 20 ) );
1389  pgsetup.push_back( make_pair("trg", 20 ) );
1390  pgsetup.push_back( make_pair("tok", 0 ) );
1391  fApi->setPatternGenerator(pgsetup);
1392  gain = GAIN_1;
1393  source = 1; // sync
1394  }else{
1395  vector< pair<string, uint8_t> > pgsetup;
1396  // no trigger! Need the idle pattern for TBM output
1397  // real readout is too fast. For single ROCs a token is needed.
1398  pgsetup.push_back( make_pair("resr", 20 ) );
1399  pgsetup.push_back( make_pair("sync;tok", 0 ) );
1400  fApi->setPatternGenerator(pgsetup);
1401  gain = GAIN_1;
1402  source = 1; // sync
1403  }
1404 
1405  uint16_t nSample = 1024;
1406  unsigned int nDly = 20; // stepsize 1.25 ns
1407  vector<int> y(nDly * nSample);
1408  int ymin=0xffff;
1409  int ymax=-ymin;
1410  vector<int> yhist(2048);
1411  vector<pair<string,uint8_t> > sigdelays;
1412  for(unsigned int dly=0; dly<nDly; dly++){
1413 
1414  sigdelays.clear();
1415  if(source==1){
1416  setTestboardDelay("clk", dly);
1417  setTestboardDelay("ctr", dly);
1418  setTestboardDelay("sda", dly+15);
1419  setTestboardDelay("tin", dly+5);
1420  /*
1421  sigdelays.push_back(std::make_pair("clk", dly));
1422  sigdelays.push_back(std::make_pair("ctr", dly));
1423  sigdelays.push_back(std::make_pair("sda", dly + 15));
1424  sigdelays.push_back(std::make_pair("tin", dly + 5));
1425  * */
1426  }else if(source==2){
1427  //sigdelays.push_back(std::make_pair("sda", dly ));
1428  setTestboardDelay("sda", dly);
1429  }
1430  //sigdelays.push_back(std::make_pair("level",fSignalLevel));
1431  //fApi->setTestboardDelays(sigdelays);
1432 
1433  vector<uint16_t> data = fApi->daqADC(signalName, gain, nSample, source, start);
1434 
1435  if (data.size()<nSample) {
1436  cout << "Warning, data size = " << data.size() << endl;
1437  }else{
1438  for(unsigned int i=0; i<nSample; i++){
1439  int raw = data[i] & 0x0fff;
1440  if (raw & 0x0800) raw |= 0xfffff000; // sign
1441  if (raw>ymax) ymax=raw;
1442  if (raw<ymin) ymin=raw;
1443  y[ nDly*i+ nDly-1-dly ]=raw;
1444  yhist[ raw/2 + 1024]++;
1445  }
1446  }
1447 
1448  }
1449 
1450  // restore delays, signals (modified by daqADC) and pg
1451  /*
1452  ConfigParameters *p = fPixSetup->getConfigParameters();
1453  sigdelays = p->getTbSigDelays();
1454  fApi->setTestboardDelays(sigdelays);
1455  * */
1456  setTestboardDelay("all");
1457 
1458 
1459  pg_restore();
1460 
1461 
1462  if (ymin<ymax){
1463  int ylo=ymin/2; for(; yhist[ylo+1024]<yhist[ylo+1+1024]; ylo++){}
1464  int yhi=ymax/2; for(; yhist[yhi+1024]<yhist[yhi-1+1024]; yhi--){}
1465  out << setw(6) << signalName
1466  << " low = " << fixed << setw(6) << setprecision(1) << ylo*scale*2 << " mV"
1467  << " high= " << fixed << setw(6) << setprecision(1) << yhi*scale*2 << " mV "
1468  << " amplitude = "<< fixed << setw(6) << setprecision(1) << (yhi-ylo)*scale*2 << " mVpp (differential)\n";
1469  }else{
1470  out << "no signal found\n";
1471  }
1472 
1473  return 0;
1474 }
1475 
1476 
1477 
1478 int CmdProc::pixDecodeRaw(int raw, int level){
1479  int ph(0), error(0),x(0),y(0);
1480  string s="";
1481 
1482  // direct copy from psi46test
1483  ph = (raw & 0x0f) + ((raw >> 1) & 0xf0);
1484  error = (raw & 0x10) ? 128 : 0;
1485  if((error==128)&&(level>0)){ s=", wrong stuffing bit";}
1486 
1487  int c1 = (raw >> 21) & 7; if (c1>=6) {error |= 16;};
1488  int c0 = (raw >> 18) & 7; if (c0>=6) {error |= 8;};
1489  int c = c1*6 + c0;
1490 
1491  int r2 = (raw >> 15) & 7; if (r2>=6) {error |= 4;};
1492  int r1 = (raw >> 12) & 7; if (r1>=6) {error |= 2;};
1493  int r0 = (raw >> 9) & 7; if (r0>=6) {error |= 1;};
1494  int r = (r2*6 + r1)*6 + r0;
1495 
1496  y = 80 - r/2; if ((unsigned int)y >= 80){ error |= 32; s+=", bad row";};
1497  x = 2*c + (r&1); if ((unsigned int)x >= 52) {error |= 64; s+=", bad column";};
1498  if(level>0){
1499  out << "( " << dec << setw(2) << setfill(' ') << x
1500  << ", "<< dec << setw(2) << setfill(' ') << y
1501  << ": "<< setw(3) << ph << ") ";
1502  }
1503  if((error>0)&&(level>0)){
1504  out << "error =" << error << " " << s;
1505  }
1506  return error;
1507 }
1508 
1509 
1510 int CmdProc::readRocs(uint8_t signal, double scale, std::string units){
1511  /* readback bits in the roc header(s), if signal is not 0xff,
1512  * program the readback register first, otherwise read back whatever
1513  * the readback register has previously been set-up for.
1514  * The latter mode is useful for the 'last dac' readback, while
1515  * the former is useful for analog readbacks (triggers the ADC)
1516  */
1517 
1518  if (signal<0xff){
1519  if ( ! (fApi->setDAC("readback", signal))){
1520  out << "Warning ! May have failed to write to readback register\n";
1521  }
1522  }
1523 
1524  pg_sequence( 3 ); // token+trigger
1525  fApi->daqStart(fBufsize, fPixelConfigNeeded);
1526  fApi->daqTrigger(100, fPeriod);
1527  fApi->daqGetRawEventBuffer();
1528  fApi->daqTrigger(16, fPeriod);
1529  std::vector<pxar::rawEvent> buf = fApi->daqGetRawEventBuffer();
1530  fApi->daqStop(false);
1531  if(buf.size()<16){
1532  out << "only got " << buf.size() << " events instead of 16 !\n";
1533  return 1;
1534  }
1535 
1536  size_t nRoc = 0;
1537  size_t nTBM = fApi->_dut->getNTbms();
1538 
1539  vector<uint16_t> values;
1540  vector<int> start;
1541  for(unsigned int i=0; i<buf.size(); i++){
1542  unsigned int iroc=0;
1543  for(unsigned int k=0; k<buf[i].data.size(); k++){
1544  uint16_t w = buf[i].data[k];
1545  // only look at roc headers
1546  if( ( (nTBM == 0) && (k==0) )
1547  || ( (nTBM > 0 ) && ((w & 0xf000)== 0x4000)) ){
1548  uint8_t D = (w & 1);
1549  uint8_t S = (w >>1) & 1;
1550  if(verbose && (iroc==0)) cout << "S,D=" << (int)S << "," << (int)D << endl;
1551  if (iroc==values.size()) { values.push_back(0); start.push_back(-1); }
1552  values[iroc] = ( values[iroc] << 1 ) + D;
1553  if (S==1){
1554  start[iroc]=i;
1555  }
1556  iroc++;
1557  }
1558  }
1559  if(iroc>nRoc) nRoc= iroc;
1560  }
1561 
1562  if(nRoc == 0){
1563 
1564  out << "readback failed, no roc headers!\n";
1565 
1566  }else{
1567 
1568  int average=0;
1569  int nvalid=0;
1570  for(uint8_t iroc=0; iroc<nRoc; iroc++){
1571  if(verbose){
1572  cout << "readback roc " << (int) iroc << " start=" << start[iroc]
1573  << " raw = " << bitset<16>( values[iroc] )
1574  << " aligned = " << bitset<16>((values[iroc] >> (15-start[iroc]) ) | (values[iroc]<<(start[iroc]+1))) << endl;
1575  }
1576  if(start[iroc]>=0){
1577  uint16_t value = (values[iroc] >> (15-start[iroc]) ) | (values[iroc]<<(start[iroc]+1));
1578  uint8_t rocid= (value & 0xF000) >> 12;
1579  uint8_t cmd = (value & 0x0F00) >> 8;
1580  uint8_t data = (value & 0x00FF);
1581  out << dec << fixed << setfill(' ') << setw(2) << (int) iroc
1582  << "(" << setw(2) << (int) rocid << ")" << ": "
1583  << fixed << setw(3) << (int) data;
1584  if(scale>0){
1585  out << " ~ " << fixed << setw(6) << setprecision(3) << data*scale
1586  << " " << units;
1587  }
1588  if ((cmd == signal)||(signal==0xff)){
1589  out << "\n";
1590  average += data;
1591  nvalid+=1;
1592  }else{
1593  out << " readback inconsistent " << (int)cmd << " <> " << (int) signal << "\n";
1594  }
1595  }else{
1596  out << dec << fixed << setfill(' ') << setw(2) << (int) iroc << " no startbit?\n";
1597  }
1598  }
1599  if((nRoc>1)&&(nvalid>0)){
1600  out << "average:" << dec<<fixed << setw(3) << int(average/nvalid);
1601  if(scale>0){
1602  out << " ~ " << fixed << setw(6) << setprecision(3) << float(average)/nvalid*scale
1603  << " " << units;
1604  }
1605  out << "\n";
1606  }
1607  }
1608 
1609  pg_restore();
1610  return 0;
1611 }
1612 
1613 
1614 
1615 
1616 int CmdProc::getBuffer(vector<uint16_t> & buf){
1617  fDeser400XOR1=0;
1618  fDeser400XOR2=0;
1619 
1620  if (fGetBufMethod==1){
1621  buf.clear();
1622  vector<rawEvent> vre = fApi->daqGetRawEventBuffer();
1623  for(unsigned int i=0; i<vre.size(); i++){
1624  for(unsigned int j=0; j<vre.at(i).GetSize(); j++){
1625  buf.push_back( vre.at(i)[j] );
1626  }
1627  }
1628  }else{
1629  buf.clear();
1630  buf = fApi->daqGetBuffer();
1631  }
1632  return 0;
1633 }
1634 
1635 
1636 
1637 int CmdProc::setupDaq(int ntrig, int ftrigkhz, int verbosity){
1638  /* setup pattern generator and daq
1639  * always call restoreDaq before returning control to Pxar
1640  */
1641 
1642  // warn user when no data expected
1643  if( (fApi->_dut->getNTbms()>0) && ((fSeq & 0x02 ) ==0 ) ){
1644  out << "The current sequence does not contain a trigger!\n";
1645  }else if( (fApi->_dut->getNTbms()==0) && ((fSeq & 0x01 ) ==0 ) ){
1646  out <<"The current sequence does not contain a token!\n";
1647  }
1648 
1649  int length=0;
1650  if((ntrig==1) || (ftrigkhz==0)){
1651  length=fBufsize;
1652  }else{
1653  length = 40000 / ftrigkhz;
1654  }
1655 
1656  pg_sequence( fSeq, length ); // set up the pattern generator
1657  bool stat = fApi->daqStart(fBufsize, fPixelConfigNeeded);
1658 
1659  for(unsigned int i=0; i<8; i++){ fDeser400XOR1sum[i]=0;}
1660 
1661  fPixelConfigNeeded = false;
1662  if (! stat ){
1663  if(verbosity>0){ out << "something wrong with daqstart !!!" << endl;}
1664  return 2;
1665  }
1666 
1667  if(verbose) out << "runDaq " << ftrigkhz << " " << length << " " << fPeriod << endl;
1668  int leff = 40* int(length / 40); // emulate testboards cDelay
1669  if(leff<length){
1670  out << "period will be truncated to " << dec<< leff << " BC = " << int(40000/leff) << " kHz !!" << endl;
1671  }
1672  return 0;
1673 
1674 }
1675 
1676 
1677 int CmdProc::restoreDaq(int verbosity){
1678  bool stat = fApi->daqStop(false);
1679  if( (! stat ) && (verbosity>0) ){
1680  out << "something wrong with daqstop !" <<endl;
1681  }
1682  pg_restore(); // undo any changes
1683  return 0;
1684 }
1685 
1686 
1687 int CmdProc::runDaq(vector<uint16_t> & buf, int ntrig, int ftrigkhz, int verbosity, bool setup){
1688  /* run ntrig sequences and get the raw data from the DTB */
1689 
1690  if(setup) setupDaq(ntrig, ftrigkhz, verbosity);
1691 
1692  fApi->daqTrigger(ntrig, fPeriod);
1693 
1694  getBuffer( buf );
1695  if(buf.size()==0){
1696  if (verbosity>0){ out << "no data !" << endl;}
1697  if (setup) restoreDaq(verbosity);
1698  return 1;
1699  }
1700 
1701  if(setup) restoreDaq(verbosity);
1702  return 0;
1703 }
1704 
1705 
1706 
1707 
1708 int CmdProc::runDaq(int ntrig, int ftrigkhz, int verbosity){
1709  /* run ntrig sequences but don't get the data */
1710 
1711  int length=0;
1712  if((ntrig==1) || (ftrigkhz==0)){
1713  length=0;
1714  }else{
1715  length = 40000 / ftrigkhz;
1716  }
1717 
1718  pg_sequence( fSeq, length ); // set up the pattern generator
1719  bool stat = fApi->daqStart(fBufsize, fPixelConfigNeeded);
1720  if (! stat ){
1721  if(verbosity>0){ out << "something wrong with daqstart !!!" << endl;}
1722  return 2;
1723  }
1724 
1725  if(verbose) out << "runDaq f=" << dec << ftrigkhz << " length=" << length << " fPeriod=" << fPeriod << endl;
1726  int leff = 40* int(length / 40); // emulate testboards cDelay
1727  if(leff<length){
1728  out << "period will be truncated to " << dec<< leff << " BC = " << int(40000/leff) << " kHz !!" << endl;
1729  }
1730  if (length>0){
1731  fApi->daqTrigger(ntrig, length);
1732  }else{
1733  // take the default (maximum)
1734  fApi->daqTrigger(ntrig, fPeriod);
1735  }
1736 
1737  fApi->daqStop(false);
1738  fPixelConfigNeeded = false;
1739  pg_restore(); // undo any changes
1740 
1741  return 0;
1742 }
1743 
1744 
1745 int CmdProc::burst(vector<uint16_t> & buf, int ntrig, int trigsep, int nburst, int verbosity){
1746  /* run ntrig sequences and get the raw data from the DTB */
1747 
1748  // warn user when no data expected
1749  if( (fApi->_dut->getNTbms()>0) && ((fSeq & 0x02 ) ==0 ) ){
1750  out << "The current sequence does not contain a trigger!\n";
1751  }else if( (fApi->_dut->getNTbms()==0) && ((fSeq & 0x01 ) ==0 ) ){
1752  out <<"The current sequence does not contain a token!\n";
1753  }
1754 
1755  if(verbose) out << dec << "burst ntrig=" << ntrig << " separation " << trigsep << " bursts " << nburst <<"\n";
1756  vector< pair<string, uint8_t> > pgsetup;
1757  pgsetup.push_back( make_pair("sync", 10) );
1758  pgsetup.push_back( make_pair("resr", fTRC) );
1759  pgsetup.push_back( make_pair("cal", fTCT ));
1760  for(int i=0; i<ntrig; i++){
1761  pgsetup.push_back( make_pair("trg", trigsep-1 ));
1762  }
1763  pgsetup.push_back( make_pair("token", 0));
1764 
1765  fPeriod = fBufsize;
1766 
1767  fApi->setPatternGenerator(pgsetup);
1768  bool stat = fApi->daqStart(fBufsize, fPixelConfigNeeded);
1769  if (! stat ){
1770  if(verbosity>0){ out << "something wrong with daqstart !!!" << endl;}
1771  return 2;
1772  }
1773 
1774  fApi->daqTrigger(nburst, fPeriod);
1775  getBuffer(buf);
1776  fApi->daqStop(false);
1777  fPixelConfigNeeded = false;
1778 
1779  if(buf.size()==0){
1780  if(verbosity>0){ out << "no data !" << endl;}
1781  return 1;
1782  }
1783  pg_restore(); // undo any changes
1784  return 0;
1785 
1786 }
1787 
1788 
1789 int CmdProc::getData(vector<uint16_t> & buf, vector<DRecord > & data, int verbosity, int nroc_expected){
1790  // pre-decoding and validity check of raw data in fBuf
1791  // returns the number of errors
1792  // record flags:
1793  // 0 (0x00) = hit 24 bits ("raw")
1794  // 4 (0x04) = roc header 12 bits
1795  // 10 (0x0a) = tbm header 16 bits
1796  // 14 (0x0e) = tbm trailer 16 bits
1797  // 16 = filler
1798  //
1799  // FIMXE, for >1 event this code required fGetBufMethod=1
1800 
1801  if(verbosity>100){
1802  for(unsigned int i=0; i< buf.size(); i++){
1803  out << hex << setw(4) << setfill('0') << buf[i] << " ";
1804  }
1805  out << dec << setfill(' ') << endl;
1806  }
1807 
1808  unsigned int nerr=0;
1809 
1810  data.clear();
1811  fDeser400err = 0;
1812  fDeser400XOR1 = 0;
1813  fDeser400XOR2 = 0;
1814  fNumberOfEvents = 0;
1815  int XOR1=0;
1816  int XOR2=0;
1817  fHeaderCount=0;
1818  unsigned int lastHeaderErrorCount=0;
1819  fHeadersWithErrors.clear(); // a list of headers) with errors
1820 
1821  unsigned int i=0;
1822  if ( fApi->_dut->getNTbms()>0 ) {
1823  uint8_t roc=0;
1824  uint8_t tbm=0;
1825  uint8_t nRocPerToken = 8; //for TBM08
1826  uint8_t maxTBM=2;
1827  bool tbm09 = (fApi->_dut->getTbmType() == "tbm09");
1828  if(tbm09){
1829  nRocPerToken = 4;
1830  maxTBM=4;
1831  }
1832  bool tbmHeaderSeen=false;
1833  unsigned int nevent=0;
1834 
1835 
1836  //cout << "getData maxTBM=" << dec<< (int) maxTBM << " rocs/token=" << (int) nRocPerToken << endl;
1837  unsigned int nloop=0;
1838  int fffCounter=0;
1839 
1840  while((i<buf.size())&&((nloop++)<buf.size())){
1841 
1842  uint16_t flag= ((buf[i]>>12)&0xE);
1843  if (buf[i]&0x1000) fDeser400err++;
1844  if ((buf[i]&0x0fff)==0xfff){
1845  fffCounter++;
1846  if (fffCounter>1000){
1847  if(verbosity>0) out << "junk data, decoding aborted\n";
1848  nerr++;
1849  return nerr + fDeser400err;
1850  }
1851  }else{
1852  fffCounter=0;
1853  }
1854 
1855 
1856  if( flag == 0xa ){ // TBM header
1857 
1858  tbmHeaderSeen=true;
1859 
1860  if((fHeaderCount>0)&&((nerr+fDeser400err)>lastHeaderErrorCount)){
1861  fHeadersWithErrors.push_back(fHeaderCount);
1862  lastHeaderErrorCount=nerr+fDeser400err;
1863  }
1864  fHeaderCount++;
1865 
1866  if (buf[i]&0x0f00) {
1867  nerr++; // should be 0
1868  if (verbosity>0) out << "illegal deser400 header record \n";
1869  }
1870 
1871  uint8_t h1=buf[i]&0xFF;
1872  i++;
1873  if(i>=buf.size()){
1874  if(verbosity>0) out << " unexpected end of data\n";
1875  nerr++;
1876  fHeadersWithErrors.push_back(fHeaderCount);
1877  return nerr + fDeser400err;
1878  }
1879 
1880  if (buf[i]&0x1000) fDeser400err++;
1881  if ((buf[i]&0xE000)==0x8000){
1882  uint8_t h2 = buf[i]&0xFF;
1883  data.push_back( DRecord( 0xa, (h1<<8 | h2), buf[i-1], buf[i]) );
1884  i++;
1885  }else{
1886  if(verbosity>0){
1887  out << " incomplete header ";
1888  out << hex << (int) buf[i-1] << " " << (int) buf[i] << dec << "\n";
1889  }
1890  nerr ++;
1891  //if(i<buf.size()) i++; // FIXME, only if necessary
1892  }
1893  continue;
1894  }// TBM header
1895 
1896 
1897  if( flag == 0x4 ){ // ROC header
1898 
1899  if( !tbmHeaderSeen ){
1900  nerr++;
1901  if(verbosity>0) out << "ROC header outside TBM header/trailer\n";
1902  }
1903 
1904  if(nroc_expected==0){
1905  nerr++;
1906  if(verbosity>0) out<< "no rocs expected\n";
1907  }else{
1908  roc ++;
1909  if( (buf[i]&0x0004)>0 ) {
1910  nerr++;
1911  if(verbosity>0) out << "zero-bit in roc header not zero\n";
1912  }
1913  data.push_back( DRecord(0x4, buf[i]&0x3, buf[i]) );
1914  uint8_t xordata = (buf[i] & 0x0ff0)>>4;
1915  if(xordata==0xff){
1916  nerr++;
1917  if(verbosity>0) out << "Deser400 phase error\n";
1918  }else{
1919  if ((tbm==0) && (roc==1)){
1920  XOR1 = xordata;
1921  fDeser400XOR1=xordata;
1922  }else if(( tbm<2 )&&(!(XOR1==xordata) )){
1923  nerr++;
1924  if (verbosity>0) out << "inconsistent XOR1 \n";
1925  }else if ((tbm==2)&&(roc==1)){
1926  XOR2=xordata;
1927  fDeser400XOR2=xordata;
1928  }else if((tbm>1)&&(!(XOR2==xordata) )){
1929  nerr++;
1930  if (verbosity>0) out << "inconsistent XOR2 \n";
1931  }
1932  }
1933  }
1934 
1935  i++;
1936  continue;
1937  }
1938 
1939 
1940  if (flag == 0x0){ // hit
1941  if (roc==0) {
1942  if(verbosity>0) out << "no hit expected here\n";
1943  nerr++;
1944  }
1945 
1946  int d1=buf[i++];
1947  if(i>=buf.size()){
1948  if(verbosity>0) out << " unexpected end of data\n";
1949  nerr++;
1950  fHeadersWithErrors.push_back(fHeaderCount);
1951  return nerr + fDeser400err;
1952  }
1953 
1954  if (buf[i]&0x1000) fDeser400err++;
1955 
1956  flag = (buf[i]>>12)&0xe;
1957  int d2=buf[i++];
1958  if (flag == 0x2) {
1959  uint32_t raw = ((d1 &0x0fff) << 12) + (d2 & 0x0fff);
1960  if( tbm09 && (roc == nRocPerToken) && (raw==0xffffff)){
1961  // tbm09 possible "zero" hit
1962  data.push_back( DRecord(15, raw, buf[i-2], buf[i-1]) );
1963  }else{
1964  data.push_back( DRecord(0x0, raw, buf[i-2], buf[i-1]) );
1965  }
1966 
1967  }else{
1968  if(verbosity>0) {
1969  out << " unexpected qualifier in ROC hit:" << (int) flag << " "
1970  << hex << setw(4) << setfill('0') << buf[i-1]
1971  << dec << setfill(' ') << " at position "<< i-1 << "\n";
1972  }
1973  nerr++;
1974  //if(i<buf.size()) i++; // FIXME, only if necessary
1975  //return nerr + fDeser400err;
1976  }
1977  continue;
1978  }
1979 
1980  if (flag == 0xe){
1981 
1982  tbmHeaderSeen=false;
1983  // TBM trailer
1984  if (buf[i]&0x0f00){
1985  nerr++;
1986  if(verbosity>0) out << "illegal data in deser400 trailer record \n";
1987  }
1988  int t1=buf[i++];
1989  if(i>=buf.size()){
1990  nerr++;
1991  if(verbosity>0) out << "unexpected end of data\n";
1992  return nerr + fDeser400err;
1993  }
1994 
1995  flag = (buf[i]>>12)&0xe;
1996  if (flag != 0xc ){
1997  if(verbosity>0) out << "unexpected qualifier " << (int) flag <<"in TBM trailer \n";
1998  continue;
1999  }
2000  if (buf[i]&0x1000) fDeser400err++;
2001  if (buf[i]&0x0f00) {
2002  nerr++;
2003  if(verbosity>0) out << "illegal data in deser400 trailer record \n";
2004  }
2005  int t2=buf[i++];
2006  data.push_back( DRecord(0xe, (t1&0xFF)<<8 | (t2&(0xff)), t1, t2) );
2007  tbm++;
2008 
2009  if (tbm==maxTBM){
2010  tbm=0; // new event, this depends on the getBuffer method
2011  nevent++;
2012  fDeser400XOR1=XOR1;
2013  fDeser400XOR2=XOR2;
2014  XOR1=0; // may change between events
2015  XOR2=0;
2016  }
2017 
2018  roc=0;
2019  continue;
2020  }
2021 
2022  if((verbose) || (verbosity>0)){
2023  out << "unexpected qualifier " << hex << (int) flag <<", skipped\n" << dec;
2024  }
2025  nerr++;
2026  i++;
2027 
2028  } // while i< buf.size()
2029 
2030  // debugging
2031  if ((nloop>=buf.size())&&(buf.size()>1000) ){
2032  cout << "stuck at i=" << dec << i << endl;
2033  cout << hex << (int) buf[i-1] << " " << (int) buf[i] << dec << endl;
2034  }
2035 
2036  //cout << "getData nevent=" << nevent << " headers=" << fHeaderCount << endl;
2037  fNumberOfEvents = nevent;
2038  if((fHeaderCount>0)&&((nerr+fDeser400err)>lastHeaderErrorCount)){
2039  fHeadersWithErrors.push_back(fHeaderCount);
2040  }
2041  }
2042 
2043  else if (fApi->_dut->getNTbms() == 0) {
2044  // single ROC
2045  while(i<buf.size() && (i<500) ){
2046 
2047  //if ( (buf[i] & 0x0ff8) == 0x07f8 ){
2048  if ( (buf[i] & 0x8000) == 0x8000 ){
2049  // roc header
2050  data.push_back(DRecord( 0x4, buf[i]&0x07, buf[i]));
2051  i++;
2052  }
2053  else if( (i+1)<buf.size() ){
2054  // hit
2055  uint32_t raw = ((buf[i] & 0x0fff) << 12) + (buf[i+1] & 0x0fff);
2056  data.push_back(DRecord( 0, raw, buf[i], buf[i+1] ) );
2057  i+=2;
2058  }else{
2059  out << "unexpected end of data\n";
2060  nerr++;
2061  return nerr + fDeser400err;
2062  }
2063  }
2064  }
2065 
2066  return nerr + fDeser400err;
2067 }
2068 
2069 
2070 int CmdProc::printData(vector<uint16_t> buf, int level){
2071  // produce a more or less decoded / annotated printout
2072 
2073  if(level >= 0){
2074  if(level>=0){
2075  for(unsigned int i=0; i<buf.size(); i++){
2076  if(fApi->_dut->getNTbms()>0){
2077  if ((buf[i]&0xE000)==0xA000){ out << "\n";}
2078  }
2079  out << " " <<hex << setw(4)<< setfill('0') << buf[i] << setfill(' ');
2080  }
2081  }
2082  out << "\n";
2083  }
2084 
2085 
2086  if (level>0){
2087  const int maxLines = 200;
2088 
2089  vector< DRecord > data;
2090  data.clear();
2091  int stat = getData(buf, data, 100);
2092 
2093  uint8_t roc=0;
2094  uint8_t tbm=0;
2095  uint8_t nRocPerToken = 8; // TBM08
2096  bool tbm09 = (fApi->_dut->getTbmType() == "tbm09");
2097  if(tbm09){
2098  nRocPerToken = 4;
2099  }
2100 
2101  int lines=0; // count lines, stop when limit reached
2102  int nstuff=0; // count consecutive dummy hits, print only once
2103 
2104  for(unsigned int i=0; (i<data.size())&&(lines<maxLines); i++){
2105 
2106  char deserStat=' ';
2107  if((data[i].w1 & 0x1000)>0){
2108  deserStat='*';
2109  }
2110 
2111  if (data[i].type==15){
2112  nstuff +=1;
2113  }else if(nstuff>0){
2114  out << setw(4) << setfill('0') << hex << data[i-1].w1
2115  << deserStat
2116  << setw(4) << setfill('0') << hex << data[i-1].w2
2117  << setfill(' ') << " ";
2118  if (nstuff==1){
2119  out << "zero hit\n";
2120  }else{
2121  out << dec << nstuff << " zero hits\n";
2122  }
2123  nstuff=0;
2124  lines++;
2125  }
2126 
2127 
2128  if (data[i].type==4){
2129 
2130  // ROC header, one 16 bit word
2131  out << setw(4) << setfill('0') << hex << data[i].w1 << setfill(' ')
2132  << deserStat << " ";
2133  out << "ROC header ";
2134  if (tbm>0){
2135  out << dec << setw(2) << (int)(roc+nRocPerToken*(tbm-1)) ;
2136  }else{
2137  out << dec << setw(2) << (int) roc;
2138  }
2139  out << " ,D=" << (data[i].data & 1);
2140  if ((data[i].data &2 )>0) { out << " S";}
2141  if((tbm==0)&&(fApi->_dut->getNTbms()>0)) out << ", Warning! TBM header expected first!";
2142  out << "\n";
2143  roc ++;
2144  lines++;
2145 
2146  }else if(!(data[i].type==15)){
2147 
2148  // all others are two 16 bit words
2149  out << setw(4) << setfill('0') << hex << data[i].w1
2150  << deserStat
2151  << setw(4) << setfill('0') << hex << data[i].w2
2152  << setfill(' ') << " ";
2153  lines++;
2154 
2155  if (data[i].type==0){
2156  out << "hit";
2157  stat = pixDecodeRaw(data[i].data, level);
2158  if(roc==0){
2159  out << " Warning! ROC header expected first!";
2160  }
2161  out << "\n";
2162 
2163  }else if (data[i].type==0xa){
2164 
2165  out << "TBM header, ";
2166  out << "event counter = " << dec << setfill(' ') << setw(3) << (data[i].data >>8);
2167  int h2 = data[i].data&0xFF;
2168  int dataId=(h2&0xC0)>>6;
2169  out << ", dataID=" << dec << setw(1) <<dataId << " ";
2170  if (dataId==2){
2171  out << ",mode=" << (int) ((h2&0x30)>>4);
2172  if(h2 & 8) { out << ", DisableTrigOut ";}
2173  if(h2 & 4) { out << ", DisableTrigIn ";}
2174  if(h2 & 2) { out << ", Pause ";}
2175  if(h2 & 1) { out << ", DisablePKAM ";}
2176  }else{
2177  out << ",value=" << hex << setw(2) << setfill('0') << (int)(h2&0x3F) << setfill(' ');
2178  }
2179  tbm++;
2180  out<<"\n";
2181 
2182  }else if (data[i].type==0xe){
2183  out << "TBM trailer";
2184  uint16_t t= data[i].data;
2185  if( t & 0x8000 ) { out << ", NoTokenPass";}
2186  if( t & 0x4000 ) { out << ", ResetTBM";}
2187  if( t & 0x2000 ) { out << ", ResetROC";}
2188  if( t & 0x1000 ) { out << ", SyncError";}
2189  if( t & 0x0800 ) { out << ", SyncTrigger";}
2190  if( t & 0x0400 ) { out << ", ClrTrgCntr";}
2191  if( t & 0x0200 ) { out << ", Cal";}
2192  if( t & 0x0100 ) { out << ", StackFullWarn";}
2193  if( t & 0x0080 ) { out << ", StackFullnow";}
2194  if( t & 0x0040 ) { out << ", PKAMReset";}
2195  out << ", StackCount=" << (int) (t&0x003F);
2196 
2197  roc=0;
2198  out<<"\n";
2199  }
2200  }
2201  }
2202  if(lines==maxLines){
2203  out << "dump aborted, line limit reached\n";
2204  }
2205 
2206  // count hits (even if the dump was aborted)
2207  int nhit=0;
2208  int nRocHeader=0;
2209  for(unsigned int i=0; i<data.size(); i++){
2210  if (data[i].type==0) nhit++;
2211  if (data[i].type==4) nRocHeader++;
2212  }
2213  if(nhit>0){
2214  out << dec << nhit << " hits \n";
2215  }
2216 
2217  if(stat-fDeser400err>0){
2218  out << dec << stat-fDeser400err << " decoding errors\n";
2219  }
2220  if(fDeser400err>0){
2221  out << dec << fDeser400err << " invalid 5-bit symbols!\n";
2222  }
2223  if((nRocHeader>0)&&(fApi->_dut->getNTbms()>0)){
2224  out << "XOR eye sdata 1 = " << bitset<8>(fDeser400XOR1) << endl;
2225  if(tbm09) out << "XOR eye sdata 2 = " << bitset<8>(fDeser400XOR2) << endl;
2226  }
2227  }
2228 
2229  return 0;
2230 }
2231 
2232 int CmdProc::sequence(int seq){
2233  // update the sequence, but only re-program the DTB if actually running
2234  fSeq = seq;
2235  if( fPgRunning ) pg_sequence(seq);
2236  return 0;
2237 }
2238 int CmdProc::pg_loop(int value){
2239  uint16_t delay = pg_sequence( fSeq );
2240  fApi->daqStart(fBufsize, false); // otherwise daqTriggerLoop does nothing (status())
2241  if(value==0){
2242  cout << "calling api->daqTriggerLoop " << fBufsize << endl;
2243  uint16_t retval = fApi->daqTriggerLoop( delay );
2244  cout << "return value " << retval << endl;
2245  }else{
2246  cout << "calling api->daqTriggerLoop " << value << endl;
2247  uint16_t retval = fApi->daqTriggerLoop( value );
2248  cout << "return value " << retval << endl;
2249  }
2250  fPgRunning = true;
2251  return 0;
2252 }
2253 
2254 int CmdProc::pg_stop(){
2255  fApi->daqTriggerLoopHalt();
2256  fApi->daqStop(false);
2257  fPgRunning = false;
2258  pg_restore();
2259  return 0;
2260 }
2261 
2262 
2263 
2264 int CmdProc::pg_sequence(int seq, int length){
2265  // configure the DTB pattern generator for a simple sequence
2266  // as other tests don't seem to take care of the pg configuration,
2267  // this must be undone afterwards (using pg_restore)
2268  // if length is 0 (default), the full buffersize is used for fPeriod
2269  // the calculated sequence length is returned as a return value
2270  vector< pair<string, uint8_t> > pgsetup;
2271  uint16_t delay = 15 + 7 + 8*3 + 7 + 8*6; // module minimal readout time, allow 8 hits
2272  if (seq & 0x20 ) { pgsetup.push_back( make_pair("resettbm", 10) ); delay+=11;}
2273  if (seq & 0x10 ) { pgsetup.push_back( make_pair("sync", 10) ); delay+=11;}
2274  if (seq & 0x40 ) { pgsetup.push_back( make_pair("resr", fTRC) ); delay+=fTRC+1; }
2275  if (seq & 0x08 ) { pgsetup.push_back( make_pair("resr", fTRC) ); delay+=fTRC+1; }
2276  if (seq & 0x04 ) { pgsetup.push_back( make_pair("cal", fTCT )); delay+=fTCT+1; }
2277  if (seq & 0x02 ) { pgsetup.push_back( make_pair("trg", fTTK )); delay+=fTTK+1;}
2278  if (seq & 0x01 ) { pgsetup.push_back( make_pair("token", 1)); delay+=1; }
2279  pgsetup.push_back(make_pair("none", 0));
2280 
2281 
2282  if (length==0){
2283  fPeriod = fBufsize;
2284  }else{
2285  fPeriod = length;
2286  }
2287 
2288  fApi->setPatternGenerator(pgsetup);
2289  return delay;
2290 }
2291 
2292 
2293 int CmdProc::pg_restore(){
2294  // restore the default pattern generator so that it works for other tests
2295  std::vector<std::pair<std::string,uint8_t> > pg_setup
2296  = fPixSetup->getConfigParameters()->getTbPgSettings();
2297  fApi->setPatternGenerator(pg_setup);
2298  return 0;
2299 }
2300 
2301 
2302 /**************** call-backs for script processing ***********************/
2303 
2304 int CmdProc::tb(Keyword kw){
2305  /* handle testboard commands
2306  * return -1 for unrecognized commands
2307  * return 0 for success
2308  * return >0 for errors
2309  */
2310 
2311  int step, pattern, delay, value;
2312  string s, comment, filename;
2313  if( kw.match("ia") ){ out << "ia=" << fApi->getTBia()<<"\n"; return 0;}
2314  if( kw.match("id") ){ out << "id=" << fApi->getTBid()<<"\n"; return 0;}
2315  if( kw.match("va") ){ out << "va=" << fApi->getTBva()<<"\n"; return 0;}
2316  if( kw.match("vd") ){ out << "vd=" << fApi->getTBvd()<<"\n"; return 0;}
2317  if( kw.match("set","vd", value)){ return setTestboardPower("vd", value); }
2318  if( kw.match("getia") ){ out << "ia=" << fApi->getTBia() <<"mA\n"; return 0;}
2319  if( kw.match("getid") ){ out << "id=" << fApi->getTBid() <<"mA\n"; return 0;}
2320  if( kw.match("hvon") ){ fApi->HVon(); return 0; }
2321  if( kw.match("hvoff") ){ fApi->HVoff(); return 0; }
2322  if( kw.match("pon") ){ fApi->Pon(); return 0; }
2323  if( kw.match("poff") ){ fApi->Poff(); return 0; }
2324  if( kw.match("d1", s, fD_names, out ) ){ fApi->SignalProbe("D1",s); return 0;}
2325  if( kw.match("d2", s, fD_names, out ) ){ fApi->SignalProbe("D2",s); return 0;}
2326  if( kw.match("a1", s, fA_names, out ) ){ fApi->SignalProbe("A1",s); return 0;}
2327  if( kw.match("a2", s, fA_names, out ) ){ fApi->SignalProbe("A2",s); return 0;}
2328  if( kw.match("adc", s, fA_names, out ) ){ fApi->SignalProbe("adc",s); return 0;}
2329  if( kw.match("clock","external") ){ fApi->setExternalClock(true); return 0;}
2330  if( kw.match("clock","internal") ){ fApi->setExternalClock(false); return 0;}
2331  if( kw.match("seq", pattern)){ sequence(pattern); return 0;}
2332  if( kw.match("seq","t")){ sequence( 2 ); return 0; }
2333  if( kw.match("seq","ct")){ sequence( 6 ); return 0; }
2334  if( kw.match("seq","rct")){ sequence( 14 ); return 0; }
2335  if( kw.match("seq","ctt")){ sequence( 7 ); return 0; }
2336  if( kw.match("seq","rctt")){ sequence( 15 ); return 0; }
2337  if( kw.match("pg","restore")){ return pg_restore();}
2338  if( kw.match("loop") ){ return pg_loop();}
2339  if( kw.match("loop", value) ){ return pg_loop(value);}
2340  if( kw.match("stop") ){ return pg_stop();}
2341  if( kw.match("pg","loop") ){ return pg_loop();}
2342  if( kw.match("pg","stop") ){ return pg_stop();}
2343  //if( kw.match("res"){ int s0=fSeq; sequence( 8 ); pg_single(); sequence(s0);}
2344  if( kw.match("sighi",s)){ fApi->setSignalMode(s,2); return 0;}
2345  if( kw.match("siglo",s)){ fApi->setSignalMode(s,1); return 0;}
2346  if( kw.match("signorm",s)){ fApi->setSignalMode(s,0); return 0;}
2347  if( kw.match("level",value)){ setTestboardDelay("level", value); return 0;}
2348  if( kw.match("clk",value)){ setTestboardDelay("clk", value); return 0;}
2349  if( kw.match("sda",value)){ setTestboardDelay("sda", value); return 0;}
2350  if( kw.match("ctr",value)){ setTestboardDelay("ctr", value); return 0;}
2351  if( kw.match("tbdly",value)){
2352  setTestboardDelay("clk",value);
2353  setTestboardDelay("ctr",value);
2354  setTestboardDelay("sda",value+15);
2355  setTestboardDelay("tin",value);
2356  return 0;
2357  }
2358  if( kw.match("adctest", s, fA_names, out ) ){ adctest(s); return 0;}
2359  if( kw.match("adctest") ){ adctest("clk"); adctest("ctr"); adctest("sda"); adctest("rda"); adctest("sdata1"); adctest("sdata2"); return 0;}
2360  if( kw.match("readrocs", value)){ return readRocs(value); }
2361  if( kw.match("readback")) { return readRocs();}
2362  if( kw.match("readback", "vd") ) { return readRocs(8, 0.016,"V"); }
2363  if( kw.match("readback", "va") ) { return readRocs(9, 0.016,"V"); }
2364  if( kw.match("readback", "vana")) { return readRocs(10, 0.008,"V"); }
2365  if( kw.match("readback", "vbg") ) { return readRocs(11, 0.008,"V"); }
2366  if( kw.match("readback", "iana")) { return readRocs(12, 0.24,"mA"); }
2367  if( kw.match("readback", "ia") ) { return readRocs(12, 0.24,"mA"); }
2368  if( kw.match("scan","tct")){ tctscan(); return 0;}
2369  if( kw.match("tct", value)){ fTCT=value; if (fSeq>0){sequence(fSeq);} return 0;}
2370  if( kw.match("ttk", value)){ fTTK=value; if (fSeq>0){sequence(fSeq);} return 0;}
2371  if( kw.match("trc", value)){ fTRC=value; if (fSeq>0){sequence(fSeq);} return 0;}
2372  if( kw.match("getbufmethod",value)){ fGetBufMethod=value; return 0;}
2373 
2374  if( kw.match("dread") ){
2375  fApi->daqStart(fBufsize, fPixelConfigNeeded);
2376  fApi->daqTrigger(1, fPeriod);
2377  std::vector<pxar::Event> buf = fApi->daqGetEventBuffer();
2378  fApi->daqStop(false);
2379  for(unsigned int i=0; i<buf.size(); i++){
2380  out << buf[i];
2381  }
2382  out << " ["<<buf.size()<<"]\n";
2383  fPixelConfigNeeded = false;
2384  return 0;
2385  }
2386  if( kw.match("raw") ){
2387  int stat = runDaq( fBuf, 1,0, 0 );
2388  if(stat==0){
2389  printData( fBuf, 0 );
2390  }else{
2391  out << " error getting data ("<<dec<<(int)stat<<")\n";
2392  printData(fBuf, 0);
2393  }
2394  return 0;
2395  }
2396  if( kw.match("adc")){
2397  int stat = runDaq( fBuf, 1, 0, 1 );
2398  if(stat==0){
2399  printData( fBuf, 1 );
2400  }else{
2401  out << " error getting data\n";
2402  printData(fBuf, 1);
2403  }
2404  return 0;
2405  }
2406 
2407 
2408 
2409  int ntrig, ftrigkhz;
2410  if( kw.match("errors", ntrig) ){
2411  int stat=countErrors(ntrig, 1, 16);
2412  if(stat<0){
2413  out << "no data\n";
2414  }else{
2415  out << dec<< (int) stat << "\n";
2416  }
2417  return 0;
2418  }
2419 
2420 
2421  if( kw.match("daq", ntrig, ftrigkhz) ){
2422 
2423  if(fPrerun>0) runDaq(ntrig, ftrigkhz);
2424  runDaq(fBuf, ntrig, ftrigkhz);
2425 
2426  vector<DRecord > data;
2427  int stat = getData(fBuf, data, 0);
2428 
2429  int n=0;
2430 
2431  if(fApi->_dut->getNTbms()==0){
2432  // single ROC
2433  for(unsigned int i=0; i<fBuf.size(); i++){
2434 
2435  if((fBuf[i]&0x8000)==0x8000){//((fBuf[i]&0x0ff8)==0x07f8) {
2436  if(i>0) out << "\n";
2437  out << dec << setfill(' ') << setw(4) << ++n << ": ";
2438  }
2439  out << setw(4) << setfill('0') << hex << fBuf[i] << " ";
2440  }
2441  out << setfill(' ') << endl;
2442  out<< dec << stat << " errors\n";
2443  }else{
2444  for(unsigned int i=0; i<fBuf.size(); i++){
2445 
2446  if((fBuf[i]&0xe000)==0xa000) {
2447  if(i>0) out << "\n";
2448  out << dec << setfill(' ') << setw(4) << ++n << ": ";
2449  }
2450  out << setw(4) << setfill('0') << hex << fBuf[i] << " ";
2451  }
2452  out << setfill(' ') << endl;
2453  if(stat==0){
2454  out << "no errors\n";
2455  }else{
2456  out<< dec << stat << " errors! header #=";
2457  for(unsigned int n=0; n<fHeadersWithErrors.size(); n++){
2458  out << fHeadersWithErrors[n] << " ";
2459  }
2460  out << "\n";
2461  }
2462  }
2463  return 0;
2464  }
2465 
2466  int trigsep, nburst;
2467  if( kw.match("burst", ntrig, trigsep, nburst) ){ return bursttest(ntrig, trigsep, nburst);}
2468  if( kw.match("burst", ntrig, trigsep) ){ return bursttest(ntrig, trigsep);}
2469  if( kw.match("burst",ntrig) ){ return bursttest(ntrig);}
2470 
2471 
2472  if( kw.greedy_match("pgset",step, pattern, delay, comment)){
2473  out << "pgset " << step << " " << pattern << " " << delay;
2474  return 0;
2475  }
2476 
2477  // some api functions for playing
2478  if (kw.match("daqstart")){ bool stat=fApi->daqStart(); out << "stat=" << stat << "\n"; return 0;}
2479  if (kw.match("daqstop")){ bool stat=fApi->daqStop();out << "stat=" << stat << "\n"; return 0;}
2480 
2481  return -1;
2482 }
2483 
2484 
2485 int CmdProc::roc( Keyword kw, int rocId){
2486  /* handle roc commands
2487  * return -1 for unrecognized commands
2488  * return 0 for success
2489  * return >0 for errors
2490  */
2491  vector<int> col, row;
2492  int value;
2493  for(unsigned int i=0; i<fnDAC_names; i++){
2494  if (kw.match(fDAC_names[i],value)){ fApi->setDAC(kw.keyword,value, rocId ); return 0 ; }
2495  }
2496  if (kw.match("vcal",value,"hi")){
2497  fApi->setDAC(kw.keyword,value, rocId );
2498  fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))|4, rocId);
2499  return 0 ;
2500  }
2501  if (kw.match("vcal",value,"lo")){
2502  fApi->setDAC(kw.keyword,value, rocId );
2503  fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))&0xfb, rocId);
2504  return 0 ;
2505  }
2506 
2507  if (kw.match("hirange")) {fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))|4, rocId);return 0 ;}
2508  if (kw.match("lorange")) {fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))&0xfb, rocId);return 0 ;}
2509  if (kw.match("disable") ) {fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))|2, rocId);return 0 ;}
2510  if (kw.match("enable")) {fApi->setDAC("ctrlreg", (fApi->_dut->getDAC(rocId, "ctrlreg"))&0xfd, rocId);return 0 ;}
2511  if (kw.match("mask") ) { fApi->_dut->maskAllPixels(true, rocId); fPixelConfigNeeded = true; return 0 ;}
2512  if (kw.match("cald") ) {fApi->SetCalibrateBits(false); fApi->_dut->testAllPixels(false, rocId); fPixelConfigNeeded = true; return 0 ;}
2513  //if (kw.match("cald") ) { fApi->_dut->testAllPixels(false, rocId); fPixelConfigNeeded = true; return 0 ;}
2514  if ( kw.match("arm", col, 0, 51, row, 0, 79)
2515  || kw.match("pixd", col, 0, 51, row, 0, 79)
2516  || kw.match("pixe", col, 0, 51, row, 0, 79)
2517  ){
2518  // testPixel(true) : pixelConfig.enable = true => cal-inject,reported "active" by info()
2519  // maskPixel(true/false) : pixelConfig.mask = true /false
2520  for(unsigned int c=0; c<col.size(); c++){
2521  for(unsigned int r=0; r<row.size(); r++){
2522  if(verbose) { cout << kw.keyword << " roc " << rocId << ": " << col[c] << "," << row[r] << endl; }
2523  if (kw.keyword=="arm"){
2524  fApi->_dut->testPixel(col[c], row[r], true, rocId);
2525  fApi->_dut->maskPixel(col[c], row[r], false, rocId);
2526  }else if (kw.keyword=="pixd"){
2527  if(verbose){out << "masked before pixd:"<<dec << fApi->_dut->getNMaskedPixels(rocId);}
2528  fApi->_dut->maskPixel(col[c], row[r], true, rocId);
2529  if(verbose){out << ", masked after pixd:"<<dec << fApi->_dut->getNMaskedPixels(rocId);}
2530  }else if (kw.keyword=="pixe"){
2531  if(verbose){out << "masked before pixe:"<<dec << fApi->_dut->getNMaskedPixels(rocId);}
2532  fApi->_dut->maskPixel(col[c], row[r], false, rocId);
2533  if(verbose){out << ", masked after pixe:"<<dec << fApi->_dut->getNMaskedPixels(rocId);}
2534  }
2535  }
2536  }
2537  fPixelConfigNeeded = true;
2538 
2539  return 0 ;
2540  }
2541 
2542 
2543  return -1;
2544 }
2545 
2546 
2547 int CmdProc::tbm(Keyword kw, int cores){
2548  /* handle tbm commands
2549  * core=0= TBMA, 1=TBMB, 2=both
2550  * return -1 for unrecognized commands
2551  * return 0 for success
2552  * return >0 for errors
2553  */
2554  if(verbose) { cout << "tbm " << kw.keyword << " ,cores =" << cores << endl;}
2555  int address, value, value1, value2, value3;
2556  if (kw.match("tbmset", address, value)) { return tbmset(address, value); }
2557  if (kw.match("enable", "pkam") ){ return tbmsetbit("base0",cores, 0, 0);}
2558  if (kw.match("disable","pkam") ){ return tbmsetbit("base0",cores, 0, 1);}
2559  if (kw.match("accept", "triggers") ){ return tbmsetbit("base0",cores, 4, 0);}
2560  if (kw.match("ignore", "triggers") ){ return tbmsetbit("base0",cores, 4, 1);}
2561  if (kw.match("enable", "triggers") ){ return tbmsetbit("base0",cores, 6, 0);}
2562  if (kw.match("disable","triggers") ){ return tbmsetbit("base0",cores, 6, 1);}
2563  if (kw.match("ntp") ){ return tbmsetbit("base0",cores, 6, 1);}
2564  if (kw.match("enable", "autoreset")){ return tbmsetbit("base0",cores, 7, 0);}
2565  if (kw.match("disable","autoreset")){ return tbmsetbit("base0",cores, 7, 1);}
2566  if (kw.match("mode","cal" ) ){ return tbmset("base2",cores, 0xC0);}
2567  if (kw.match("mode","clear") ){ return tbmset("base2",cores, 0x00);}
2568  if (kw.match("inject","trg") ){ return tbmset("base4",cores, 1);}
2569  if (kw.match("reset","roc") ){ return tbmset("base4",cores, (1<<2));}
2570  if (kw.match("inject","cal") ){ return tbmset("base4",cores, (1<<3));}
2571  if (kw.match("reset","tbm") ){ return tbmset("base4",cores, (1<<4));}
2572  if (kw.match("clear","stack") ){ return tbmset("base4",cores, (1<<5));}
2573  if (kw.match("clear","token") ){ return tbmset("base4",cores, (1<<6));}
2574  if (kw.match("clear","counter") ){ return tbmset("base4",cores, (1<<7));}
2575  if (kw.match("pkamcounter",value)){return tbmset("base8",cores, value);}
2576  if (kw.match("autoreset",value) ){return tbmset("basec",cores, value);}
2577  if (kw.match("dly",value) ){return tbmset("basea", cores,
2578  (value&0x7) | ((value&0x7)<<3) , 0x38 | 0x07 );}
2579  if (kw.match("dly0",value) ){return tbmset("basea", cores, (value&0x7) , 0x07);}
2580  if (kw.match("dly1",value) ){return tbmset("basea", cores, (value&0x7)<<3, 0x38);}
2581  if (kw.match("dlyhdr",value)){return tbmset("basea", cores, (value&0x1)<<6, 0x40);}
2582  if (kw.match("dlytok",value)){return tbmset("basea", cores, (value&0x1)<<7, 0x80);}
2583  if (kw.match("phase400",value) ){return tbmset("basee", 0, (value&0x7)<<2, 0x1c);}
2584  if (kw.match("phase160",value) ){return tbmset("basee", 0, (value&0x7)<<5, 0xe0);}
2585  if (kw.match("phases") ){
2586  uint8_t phases;
2587  out << " TOK H/T port 0 1\n";
2588  tbmget("basea", 0, phases);
2589  out << "rocs(A) : " << (int) (phases>>7) << " " << (int) ((phases>>6) &1) << " " << (int) ((phases>>3) &7)<<" " << (int) (phases &7) << "\n";
2590  tbmget("basea", 1, phases);
2591  out << "rocs(B) : " << (int) (phases>>7) << " " << (int) ((phases>>6) &1) << " " << (int) ((phases>>3) &7)<<" " << (int) (phases &7) << "\n";
2592  tbmget("basee",0, phases);
2593  out << "160 MHz : " << dec << (int) ( phases >> 5 ) << "\n";
2594  out << "400 MHz : " << dec << (int) ( (phases) >> 2 & 7) << "\n";
2595  return 0;
2596  }
2597  if (kw.match("phases",value1, value2) ){
2598  return tbmset("basee", 0, ((value1&0x7)<<5) | ((value2&0x7)<<2), 0xfc);
2599  }
2600  if (kw.match("phases",value1, value2,value3) ){
2601  tbmset("basea", cores, (value3&0x7) | ((value3&0x7)<<3) , 0x38 | 0x07 );
2602  tbmset("basee", 0, ((value1&0x7)<<5) | ((value2&0x7)<<2), 0xfc);
2603  return 0;
2604  }
2605  if (kw.match("scan","tbm")){ return tbmscan();}
2606  if (kw.match("scan","rocs")){ return rocscan();}
2607  if (kw.match("scan","level")){ return levelscan();}
2608  if (kw.match("scan","raw", value)){return rawscan(value);}
2609 
2610  return -1; // nothing done
2611 }
2612 
2613 
2614 bool CmdProc::process(Keyword keyword, Target target, bool forceTarget){
2615  /* process a parsed command line command
2616  * called by the exec method of Statements
2617  * if the forceTarget flag is True, the keyword is only processed by
2618  * the corresponding target, otherwise all of them are tried
2619  * */
2620 
2621  // debugging printout
2622  if (verbose){
2623  cout << "keyword --> " << keyword.str() << " " << target.str() << endl;
2624  }
2625 
2626  if (target.name=="do"){
2627  Arg::varvalue = target.value();
2628  }
2629 
2630  if (keyword.match("info")){
2631  fApi->_dut->info();
2632  return true;
2633  }
2634 
2635  if( keyword.match("macros")){
2636  // dump the list of macros
2637  for( map<string, deque<string> >::iterator it=macros.begin();
2638  it!=macros.end(); it++){
2639  out << it->first << ":";
2640  for( unsigned int i=0; i<it->second.size(); i++){
2641  out << it->second[i] << " ";
2642  }
2643  out << endl;
2644  }
2645  return true;
2646  }
2647 
2648  if( keyword.match("help") ){
2649  out << "Documentation can be found at ";
2650  out << "http://cms.web.psi.ch/phase1/software/cmdline.html\n";
2651  return true;
2652  }
2653 
2654  if( keyword.match("help","seq") ){
2655  out << "1=tok, 2=trg, 4=cal, 8=res, 16=sync, 32=reset-tbm\n";
2656  return true;
2657  }
2658 
2659 
2660  string filename;
2661 
2662  if (keyword.match("exec", filename)){
2663 
2664  // execute a file with a new command processor
2665  CmdProc * p = new CmdProc( this );
2666  ifstream inputFile( filename.c_str());
2667  if ( inputFile.is_open()) {
2668  string line;
2669  while( getline( inputFile, line ) ){
2670  p->exec(line);
2671  out << p->out.str();
2672  }
2673  delete p;
2674  return true;
2675 
2676  } else {
2677 
2678  out << " Unable to open file ";;
2679  return false;
2680  }
2681  }
2682 
2683  if (keyword.match("verbose")){ verbose=true; return true;}
2684  if (keyword.match("quiet")){ verbose=false; return true;}
2685  if (keyword.match("target")){ out << defaultTarget.str(); return true;}
2686  int value;
2687  if (keyword.match("prerun",value)){ fPrerun=value; return true;}
2688 
2689  string message;
2690  if ( keyword.match("echo","roc")){ out << "roc " << target.value() << "\n"; return true;}
2691  if ( keyword.match("echo","%")){ out << "%" << target.value() << "\n"; return true;}
2692  if ( keyword.greedy_match("echo", message) || keyword.greedy_match("log",message) ){
2693  out << message << "\n";
2694  return true;
2695  }
2696 
2697 
2698  int event;
2699  if ( keyword.match("decode", event)){
2700  vector<uint16_t> evbuf;
2701  int n=0;
2702  for(unsigned int i=0; i<fBuf.size(); i++){
2703 
2704  if(fApi->_dut->getNTbms()==0){
2705  if ((fBuf[i]&0x8000)==0x8000){n++;}
2706  }else{
2707  if ((fBuf[i]&0xe000)==0xa000){ n++;}
2708  }
2709  if (n==event) {evbuf.push_back( fBuf[i]); }
2710 
2711  }
2712 
2713  printData(evbuf, 1);
2714  return 0;
2715  }
2716 
2717  if ( keyword.greedy_match("decode", message) ){
2718 
2719  vector<uint16_t> buf;
2720  for(unsigned int i=0; i<keyword.narg(); i++){
2721  stringstream ss;
2722  ss << hex << keyword.argv[i].raw();
2723  uint16_t x=0;
2724  ss >> x;
2725  buf.push_back(x);
2726  }
2727  printData(buf, 1);
2728 
2729  return true;
2730  }
2731 
2732 
2733 
2734  int stat =0;
2735 
2736  // target explicitely specified
2737  if ( forceTarget ){
2738  if (target.name=="tb") {
2739  stat = tb( keyword );
2740  if ( stat >=0 ) return (stat==0);
2741  }
2742 
2743  else if (target.name=="tbm") {
2744  stat = tbm( keyword );
2745  if ( stat >=0 ) return (stat==0);
2746  }
2747 
2748  else if (target.name=="tbma") {
2749  stat = tbm( keyword, 0 );
2750  if ( stat >=0 ) return (stat==0);
2751  }
2752 
2753  else if (target.name=="tbmb") {
2754  stat = tbm( keyword, 1 );
2755  if ( stat >=0 ) return (stat==0);
2756  }
2757 
2758  else if (target.name=="roc") {
2759  stat = roc(keyword, target.value());
2760  if ( stat >=0 ) return (stat==0);
2761  }
2762  out << "unknown " << target.name << " command";
2763  return false;
2764  }
2765 
2766  // if not, resolve target by keyword
2767  stat = tb( keyword );
2768  if ( stat >=0 ) return (stat==0);
2769 
2770  stat = tbm( keyword ); // hmmm, how does that work for default targets?
2771  if ( stat >=0 ) return (stat==0);
2772 
2773 
2774  stat = roc(keyword, target.value());
2775  if ( stat >=0 ) return (stat==0);
2776 
2777  out << "unrecognized command";
2778  return false;
2779 }
2780 
2781 
2782 
2783 
2784 
2785 /* driver */
2786 int CmdProc::exec(std::string s){
2787  out.str("");
2788 
2789  // skip empty lines and comments
2790  if( (s.size()==0) || (s[0]=='#') || (s[0]=='-') ) return 0;
2791 
2792 
2793  // pre-processing: to lower
2794  std::string t="";
2795  for(unsigned int i=0; i<s.size(); i++){
2796  t.push_back( tolower( s[i] ));
2797  }
2798  s=t;
2799 
2800  // parse and execute a string, leads to call-backs to CmdProc::process
2801  Token words( getWords(s) );
2802 
2803  words.macros=&macros; // use the macro list of this CmdProc instance
2804 
2805  int j=0;
2806  //parse
2807  vector < Statement *> stmts;
2808  while( (!words.empty()) && (j++ < 2000)){
2809  Statement * c = new Statement;
2810  bool stat= c->parse( words );
2811  if( stat ){
2812  stmts.push_back( c );
2813  }
2814  if (!words.empty()) {
2815  if (words.front()==";") {
2816  words.pop_front();
2817  }else{
2818  out << "expected ';' instead of '" << words.front() << "'";
2819  return 1;
2820  }
2821  }
2822  }
2823 
2824  bool ok = true;
2825  for( unsigned int i=0; i<stmts.size(); i++){
2826  ok |= stmts[i]->exec(this, defaultTarget);
2827  }
2828 
2829  if (ok){
2830  return 0;
2831  }else{
2832  return 2;
2833  }
2834 }
2835 
2836 
2837 
2838 
2839 
size_t getNMaskedPixels(uint8_t rocid)
Definition: dut.cc:59
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
size_t getNTbms()
Definition: dut.cc:119
void daqTriggerLoopHalt()
Definition: api.cc:1257
bool setDAC(std::string dacName, uint8_t dacValue, uint8_t rocI2C)
Definition: api.cc:546
double getTBva()
Definition: api.cc:429
PixSetup * fPixSetup
all necessary stuff in one place
Definition: PixTest.hh:290
virtual bool setParameter(std::string parName, std::string sval)
set the string value of a parameter
Definition: PixTestCmd.cc:42
double getTBid()
Definition: api.cc:434
void doTest()
function connected to "DoTest" button of PixTab
Definition: PixTestCmd.cc:178
bool SignalProbe(std::string probe, std::string name)
Definition: api.cc:465
void testPixel(uint8_t column, uint8_t row, bool enable)
Definition: dut.cc:432
void info()
Definition: dut.cc:16
void maskAllPixels(bool mask, uint8_t rocid)
Definition: dut.cc:481
void setSignalMode(std::string signal, uint8_t mode)
Definition: api.cc:2204
void setToolTips()
implement this to provide updated tool tips if the user changes test parameters
Definition: PixTestCmd.cc:59
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 HVon()
Definition: api.cc:449
uint16_t daqTriggerLoop(uint16_t period=1000)
Definition: api.cc:1239
dut * _dut
Definition: api.h:728
void setTestboardPower(std::vector< std::pair< std::string, double > > power_settings)
Definition: api.cc:88
void testAllPixels(bool enable)
Definition: dut.cc:503
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 setTbmReg(std::string regName, uint8_t regValue, uint8_t tbmid)
Definition: api.cc:633
std::vector< uint16_t > daqGetBuffer()
Definition: api.cc:1263
std::list< TH1 * > fHistList
list of histograms available in PixTab::next and PixTab::previous
Definition: PixTest.hh:307
std::vector< uint8_t > getRocI2Caddr()
Definition: dut.cc:240
double getTBia()
Definition: api.cc:424
void maskPixel(uint8_t column, uint8_t row, bool mask)
Definition: dut.cc:397
void update()
signal to PixTab to update the canvas
Definition: PixTest.cc:569
uint8_t getDAC(size_t rocId, std::string dacName)
Definition: dut.cc:314
std::string getTbmType()
Definition: dut.cc:99
pxar::pxarCore * fApi
pointer to the API
Definition: PixTest.hh:289
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
void init()
sets all test parameters
Definition: PixTest.cc:62
std::vector< std::pair< std::string, uint8_t > > getTbmDACs(size_t tbmId)
Definition: dut.cc:348
std::vector< rawEvent > daqGetRawEventBuffer()
Definition: api.cc:1270