00001
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
00034
00036
00042
00043
00044
00045
00046 TimSequin::TimSequin() {
00047
00048 reset();
00049 }
00050
00051
00052
00053 TimSequin::~TimSequin() {
00054 }
00055
00056
00057
00058
00059
00060
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
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
00087
00088
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
00100
00101 void TimSequin::addByIndex( const TimBitBackplane mask, const int index ) {
00102
00103 if (index >= 0) m_buffer[index] |= mask;
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 );
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
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 );
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;
00156
00157 for (int i = 0; i < 2; i++) {
00158 if (next[i] < index + delays[i]) {
00159 next[i] = index + delays[i];
00160 }
00161 if (next[i] >= 0 && next[i] < size) {
00162 m_buffer[ next[i] ++ ] |= s_masks[i];
00163 }
00164 for (int j = 0; j < s_words[i] && j < 2; j++) {
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++) {
00170 if (id & 01) m_buffer[k] |= s_masks[i];
00171 id >>= 1;
00172 }
00173 next[i] = k;
00174 }
00175 if (delays[i]) next[i] ++;
00176 if (next[i] > m_size) m_size = next[i];
00177 }
00178 if (!delays[0]) m_size ++;
00179 }
00180 }
00181
00182
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
00194
00195 int TimSequin::getBCID( const int iL1A, const int iBCR, const int offset ) {
00196
00197 return (iL1A - iBCR - offset);
00198 }
00199
00200
00201
00202 int TimSequin::getIndex( const int bcid, const int iBCR, const int offset ) {
00203
00204 return (bcid + iBCR + offset);
00205 }
00206
00207
00208
00209
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
00222
00223 TimScanResults TimSequin::scan( const TimScanControl control ) {
00224
00225
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 };
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;
00252 else byte = 1;
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]) {
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
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++) {
00330
00331
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;
00339 else start[is] = 0;
00340 next[is] = j + incr;
00341
00342
00343
00344 for (int iw = 0;
00345 iw < s_words[is] && iw < 2;
00346 iw++) {
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) {
00353 id >>= 1;
00354 if (j < size && (data[j] & s_masks[is])) id += bitSetMask;
00355 }
00356 ids [is][iw] = id;
00357 next[is] = j;
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;
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 }
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
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;
00431 control.nextTTID = NONE;
00432
00433 return control;
00434 }
00435
00436
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
00458
00459
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
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
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 }