Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

TimSequin.cxx

Go to the documentation of this file.
00001 //File: TimSequin.cxx
00002 
00018 #include <iostream>
00019 #include <iomanip>
00020 
00021 using namespace std;
00022 
00023 #include "TimSequin.h"
00024 
00025 namespace SctPixelRod {
00026 
00027 enum Name { NONE = -999 };
00028 
00029 static const int s_masks[2]   =  { TIM_SID, TIM_STT };
00030 static const int s_words[2]   =  {  2,  1 };
00031 static const int s_bits[2][2] = {{ 24, 12 },{ 10, 0 }};
00032 
00033 // ************************* Class TimSequin *********************************
00034 
00036 
00042 // Constructors, destructor, and assignment
00043 
00044 // ------------------------- Constructor -------------------------------------
00045 
00046 TimSequin::TimSequin() {
00047 
00048   reset();
00049 }
00050 
00051 // ------------------------- Destructor --------------------------------------
00052 
00053 TimSequin::~TimSequin() {
00054 }
00055 
00056 // ---------------------------------------------------------------------------
00057 
00058 // Accessor functions
00059 
00060 // ------------------------- getBuffer ---------------------------------------
00061 
00062 int TimSequin::getBuffer( const UINT16 size, UINT16 buffer[] ) {
00063 
00064   const int n = (m_size > size) ? size : m_size;
00065 
00066   for (int i = 0; i < n; i++) {
00067     buffer[i] = m_buffer[i];
00068   }
00069   return n;
00070 }
00071 
00072 // ------------------------- setBuffer ---------------------------------------
00073 
00074 int TimSequin::setBuffer( const UINT16 size, const UINT16 buffer[] ) {
00075 
00076   m_size = (size > TIM_SEQ_SIZE) ? TIM_SEQ_SIZE : size;
00077 
00078   for (int i = 0; i < m_size; i++) {
00079     m_buffer[i] = buffer[i];
00080   }
00081   return m_size;
00082 }
00083 
00084 // ---------------------------------------------------------------------------
00085 
00086 // Member methods
00087 
00088 // ------------------------- addByBunch --------------------------------------
00089 
00090 void TimSequin::addByBunch( const TimBitBackplane mask, const int bcid ) {
00091 
00092   if (m_lastBCR == NONE) m_lastBCR = - (bcid + m_offset);
00093 
00094   int index = getIndex( bcid, m_lastBCR, m_offset );
00095 
00096   addByIndex( mask, index );
00097 }
00098 
00099 // ------------------------- addByIndex --------------------------------------
00100 
00101 void TimSequin::addByIndex( const TimBitBackplane mask, const int index ) {
00102 
00103   if (index >= 0) m_buffer[index] |= mask; // serial bits may already be set
00104   if (index >= m_size) m_size = index + 1;
00105 
00106   UINT32 ids[3] = { 0, 0, 0x3FF };
00107   int delays[2] = { 1, 1 };
00108 
00109   switch (mask) {
00110     case TIM_ECR:
00111       m_l1id = TIM_L1ID_FIRST;
00112       break;
00113     case TIM_BCR:
00114       m_lastBCR = index;
00115       break;
00116     case TIM_CAL:
00117       break;
00118     case TIM_L1A:
00119       if (m_lastBCR == NONE) {
00120           m_lastBCR = getBCID( index, 0, m_offset ); // set BCID = 0
00121       }
00122       ids[0] = m_l1id ++;
00123       ids[1] = getBCID( index, m_lastBCR, m_offset );
00124       addTrigger( index, ids, delays );
00125       break;
00126     default :
00127       break;
00128   }
00129 }
00130 
00131 // ------------------------- addTrigger --------------------------------------
00132 
00133 void TimSequin::addTrigger(
00134   const int    index, 
00135   const UINT32 ids[3],
00136   const int    delays[2]
00137 ) {
00138 
00139   const  int size    = TIM_SEQ_SIZE;
00140   static int lastL1A = NONE;
00141   static int next[2] = { 0, 0 };
00142 
00143   if (m_lastBCR == NONE) {
00144       m_lastBCR = getBCID( index, 0, m_offset ); // set BCID = 0
00145   }
00146   if (index >= 0 && index < size) {
00147     if (lastL1A != NONE && m_buffer[lastL1A] == 0) {
00148         lastL1A =  NONE;
00149         next[0] = 0;
00150         next[1] = 0;
00151     }
00152     else {
00153         lastL1A = index;
00154     }
00155     m_buffer[index] |= TIM_L1A; // serial bits may already be set
00156 
00157     for (int i = 0; i < 2; i++) { // loop over serial stream
00158       if (next[i] < index + delays[i]) {
00159           next[i] = index + delays[i]; // start bit index
00160       }
00161       if (next[i] >= 0 && next[i] < size) {
00162           m_buffer[ next[i] ++ ] |= s_masks[i]; // set start bit:
00163       }                             // may = last stop bit for tests only
00164       for (int j = 0; j < s_words[i] && j < 2; j++) { // loop over word
00165         INT32 id = ids[ j + i * s_words[0] ];
00166         int  k;
00167         for (k = next[i];
00168              k < next[i] + s_bits[i][j] && k < size;
00169              k++) {                              // loop over bit
00170           if (id & 01) m_buffer[k] |= s_masks[i];
00171           id >>= 1;
00172         }
00173         next[i] = k;             // next bit index
00174       }
00175       if (delays[i]) next[i] ++; // stop bit index
00176       if (next[i] > m_size) m_size = next[i];
00177     }
00178     if (!delays[0]) m_size ++; // account for delay of 0
00179   }
00180 }
00181 
00182 // ------------------------- fill --------------------------------------------
00183 
00184 void TimSequin::fill( const UINT16 size, const UINT16 value ) {
00185 
00186   const int n = (size > TIM_SEQ_SIZE) ? TIM_SEQ_SIZE : size;
00187 
00188   for (int i = 0; i < n; i++) {
00189     m_buffer[i] = value;
00190   }
00191 }
00192 
00193 // ------------------------- getBCID -----------------------------------------
00194 
00195 int TimSequin::getBCID( const int iL1A, const int iBCR, const int offset ) {
00196 
00197   return (iL1A - iBCR - offset);
00198 }
00199 
00200 // ------------------------- getIndex ----------------------------------------
00201 
00202 int TimSequin::getIndex( const int bcid, const int iBCR, const int offset ) {
00203 
00204   return (bcid + iBCR + offset);
00205 }
00206 
00207 // ------------------------- reset -------------------------------------------
00208 
00209 // This method is a reset!
00210 
00211 void TimSequin::reset() {
00212 
00213   m_size    = 0;
00214   m_l1id    = TIM_L1ID_FIRST;
00215   m_lastBCR = NONE;
00216   m_offset  = TIM_BCID_OFFSET;
00217 
00218   for (int i = 0; i < TIM_SEQ_SIZE; i++) m_buffer[i] = 0;
00219 }
00220 
00221 // ------------------------- scan --------------------------------------------
00222 
00223 TimScanResults TimSequin::scan( const TimScanControl control ) {
00224 
00225 // NB data buffer is not declared volatile, ie it should not point to TIM RAM
00226 
00227   TimScanResults results;
00228   unsigned char *data;
00229   int byte;
00230   const int report   = control.print;
00231   int       nextL1ID = control.nextL1ID;
00232   int       nextBCID = control.nextBCID;
00233   int       nextTTID = control.nextTTID;
00234   const int incr = sizeof( m_buffer[0] );
00235   const int size = control.size * incr;
00236 
00237   int next[2] = { -1, -1 }; // next index
00238   int countData = 0;
00239   int countL1A = 0;
00240   int countECR = 0;
00241   int countBCR = 0;
00242   int countCAL = 0;
00243   int nextCMD  = 0;
00244   int lastL1A  = NONE;
00245   int lastBCR  = NONE;
00246   int lastCAL  = NONE;
00247 
00248   int l1id = NONE, bcid = NONE, ttid = NONE;
00249   int j;
00250 
00251   if (control.byte == 0) byte = 0; // source
00252   else                   byte = 1; // sink
00253   m_scanErrors = 0;
00254 
00255   data = (unsigned char *) m_buffer;
00256 
00257   if (report) {
00258     cout << endl << "Scan report:" << endl;
00259     cout <<  "byte "  << byte
00260          << " size "  << size
00261          << " incr "  << incr
00262          << " orbit " << control.orbit
00263          << endl;
00264   }
00265 
00266   for (int i = byte; i < size; i += incr) {
00267     if (data[i]) { // != 0
00268       countData ++;
00269       if (data[i] & TIM_SID && i > next[0]) {
00270         m_scanError( "SerialID: index want", i / incr, next[0] / incr );
00271       }
00272       if (data[i] & TIM_STT && i > next[1]) {
00273         m_scanError( "SerialTT: index want", i / incr, next[1] / incr );
00274       }
00275       if (data[i] & TIM_CMD) {
00276         const int index = i / incr;
00277         int countCMDs = 0;
00278         //  NB last nextCMD value taken if multiCMD
00279         if (index < nextCMD) {
00280           m_scanError( "deadtime: index want", index, nextCMD );
00281         }
00282         if (data[i] & TIM_RES) {
00283           countCMDs ++;
00284           m_scanError( "reserved: index data", index, data[i] );
00285         }
00286         if (data[i] & TIM_ECR) {
00287           countECR ++;
00288           countCMDs ++;
00289           nextCMD = index + TIM_ECR_DEADTIME;
00290           nextL1ID = TIM_L1ID_FIRST;
00291           if (report) m_scanPrintCMD( "ECR index", index, index, "\n" );
00292         }
00293         if (data[i] & TIM_BCR) {
00294           countBCR ++;
00295           countCMDs ++;
00296           nextCMD = index + TIM_BCR_DEADTIME;
00297           if (lastBCR != NONE && index != lastBCR + control.orbit) {
00298             m_scanError( "BCRorbit: index want", index,
00299                           lastBCR + control.orbit );
00300           }
00301           lastBCR = index;
00302           if (report) m_scanPrintCMD( "BCR index", index, index, "\n" );
00303         }
00304         if (data[i] & TIM_CAL) {
00305           countCAL ++;
00306           countCMDs ++;
00307           nextCMD = index + TIM_CAL_DEADTIME;
00308           lastCAL = index;
00309           if (report) m_scanPrintCMD( "CAL index", index, index, "\n" );
00310         }
00311         if (data[i] & TIM_L1A) {
00312           countL1A ++;
00313           countCMDs ++;
00314           nextCMD = index + TIM_L1A_DEADTIME;
00315           lastL1A = index;
00316           if (lastBCR != NONE) {
00317             nextBCID = getBCID( index, lastBCR, control.offset );
00318           }
00319           if (lastCAL != NONE && index != lastCAL + control.pipeline) {
00320             m_scanError( "pipeline: index want", index,
00321                           lastCAL + control.pipeline );
00322           }
00323           lastCAL = NONE;
00324 
00325           INT32 ids[2][2] = {{ NONE,NONE },{ NONE,NONE }};
00326           int  stop[2]    =  { NONE,NONE };
00327           int start[2];
00328 
00329           for (int is = 0; is < 2; is++) { // loop over serial stream
00330 
00331             // Scan for serial start bit (allow starting on last stop bit)
00332 
00333             if (next[is] < i) next[is] = i;
00334             for (j = next[is];
00335                  j < size && (data[j] & s_masks[is]) == 0;
00336                  j += incr)
00337                 ;
00338             if (j < size) start[is] = j / incr; // start bit index
00339             else          start[is] = 0;
00340             next[is] = j + incr; // next bit index may be > size
00341 
00342             // Scan serial stream until stop bit reached
00343 
00344             for (int iw = 0;
00345                      iw < s_words[is] && iw < 2;
00346                      iw++) { // loop over word
00347               INT32 id = 0;
00348               const int bitSetMask = 01 << (s_bits[is][iw] - 1);
00349 
00350               for (j = next[is];
00351                    j < next[is] + s_bits[is][iw] * incr;
00352                    j += incr) { // loop over bit
00353                 id >>= 1;
00354                 if (j < size && (data[j] & s_masks[is])) id += bitSetMask;
00355               }
00356               ids [is][iw] = id;
00357               next[is] = j;      // next bit index may be >> size
00358             }
00359             if (j >= size) {
00360               if (stop[is] == NONE) {
00361                 m_scanError( "overflow: index loop", j/incr, is );
00362               }
00363             }
00364             else {
00365               if (data[j] & s_masks[is]) {
00366                 m_scanError( "stop bit: index data", j/incr, data[j] );
00367               }
00368             }
00369             stop[is] = j / incr; // stop bit index (j = next[is])
00370           }
00371 
00372           l1id = ids[0][0];
00373           bcid = ids[0][1];
00374           ttid = ids[1][0];
00375           if (report) m_scanPrintL1A( index, start, stop, bcid, l1id, ttid );
00376           if (nextL1ID != NONE && l1id != nextL1ID) {
00377             m_scanError( "nextL1ID: L1id  want", l1id, nextL1ID );
00378           }
00379           nextL1ID = l1id + 1;
00380 
00381           if (lastBCR == NONE) {
00382               lastBCR = getBCID( lastL1A, bcid, control.offset );
00383               if (lastBCR + control.orbit < 0) lastBCR += control.orbit;
00384           } //    lastBCR may be negative
00385           else {
00386             if (bcid != ((nextBCID + control.orbit) % control.orbit)) {
00387               m_scanError( "nextBCID: BCid  want", bcid, nextBCID );
00388             }
00389           }
00390           if (nextTTID != NONE && ttid != nextTTID) {
00391             m_scanError( "nextTYPE: TTid  want", ttid, nextTTID );
00392           }
00393         }
00394         if (countCMDs != 1) {
00395           m_scanError( "multiCMD: index cmds", index, countCMDs );
00396         }
00397       }
00398     }
00399   }
00400   if (report) cout << "Scan end: non-zero bytes " << countData
00401                    << " errors " << m_scanErrors << endl;
00402 
00403   results.lastL1ID =  l1id;
00404   results.lastBCID =  bcid;
00405   results.lastTTID =  ttid;
00406   results.indexL1A =  lastL1A;
00407   results.countL1A = countL1A;
00408   results.countECR = countECR;
00409   results.countBCR = countBCR;
00410   results.countCAL = countCAL;
00411   results.bitCount = countData;
00412   results.errors   = m_scanErrors;
00413 
00414   return results;
00415 }
00416 
00417 // ------------------------- scanDefaults ------------------------------------
00418 
00419 TimScanControl TimSequin::scanDefaults() {
00420 
00421   TimScanControl control;
00422 
00423   control.size     = TIM_SEQ_SIZE;
00424   control.byte     = 1;
00425   control.print    = 0;
00426   control.offset   = m_offset;
00427   control.orbit    = 0x1000;
00428   control.pipeline = TIM_CAL_DEADTIME;
00429   control.nextL1ID = NONE;
00430   control.nextBCID = NONE; // not implemented ***
00431   control.nextTTID = NONE;
00432 
00433   return control;
00434 }
00435 
00436 // ------------------------- scanRun -----------------------------------------
00437 
00438 int TimSequin::scanRun() {
00439 
00440   static TimScanControl control = scanDefaults();
00441 
00442   control.offset   = m_offset;
00443   control.pipeline = TIM_CAL_DEADTIME;
00444   control.orbit    = m_lastBCR + 1;
00445 
00446   control.size  = m_size;
00447   control.byte  = 0;
00448   control.print = 1;
00449 
00450   TimScanResults results = scan( control );
00451 
00452   return results.errors;
00453 }
00454 
00455 // ---------------------------------------------------------------------------
00456 
00457 // Private methods
00458 
00459 // ------------------------- m_scanError -------------------------------------
00460 
00461 void TimSequin::m_scanError( const char *s, const int x, const int y ) {
00462 
00463   m_scanErrors ++;
00464 
00465   cout << "SCAN ERROR: " << s
00466        << hex << " " << setw(4) << x
00467               << " " << setw(4) << y
00468        << dec << " diff " << x - y << endl;
00469 }
00470 
00471 // ------------------------- m_scanPrintCMD ----------------------------------
00472 
00473 void TimSequin::m_scanPrintCMD( const char *s, const int x, const int y,
00474                                 const char *c ) {
00475   cout << s << " "
00476        << dec << setw(5) << x << " " << setfill('0')
00477        << hex << setw(4) << y <<  c  << setfill(' ')
00478        << dec;
00479 }
00480 
00481 // ------------------------- m_scanPrintL1A ----------------------------------
00482 
00483 void TimSequin::m_scanPrintL1A( const int index, const int start[2],
00484      const int stop[2], const int bcid, const int l1id, const int ttid ) {
00485 
00486   cout.setf(ios::uppercase);
00487 
00488   m_scanPrintCMD( "L1A index", index, index, " " );
00489 
00490   cout << hex << setiosflags(ios::uppercase) << setfill('0');
00491 
00492   cout << " start " << setw(4) << start[0]
00493        << " stop "  << setw(4) <<  stop[0]
00494        << " BCID "  << setw(3) <<  bcid
00495        << " L1ID "  << setw(6) <<  l1id
00496        << endl;
00497 
00498   cout << "                     "
00499        << " start " << setw(4) << start[1]
00500        << " stop "  << setw(4) <<  stop[1]
00501        << " TTID "  << setw(3) <<  ttid
00502        << endl;
00503 
00504   cout << dec << setfill(' ');
00505 }
00506 
00507 } // End namespace SctPixelRod

Generated on Sun Jun 27 19:57:31 2004 for TimModule by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002