00001
00002
00038 #include <ctime>
00039 #include <iostream>
00040
00041 using namespace std;
00042
00043 #include "TimModule.h"
00044
00045 #ifdef RCDAQ
00046 #include "TIMModule/TIMException.h"
00047 #endif // RCDAQ
00048
00049
00050
00051 namespace SctPixelRod {
00052
00053
00054
00056
00057 TimException::TimException( std::string descriptor, int data1, int data2 ) :
00058 BaseException( descriptor ) {
00059
00060 m_data1 = data1;
00061 m_data2 = data2;
00062 setType( TIM );
00063
00064 #ifdef RCDAQ
00065 throw TIMException (TIMException::TIMBusError);
00066 #endif // RCDAQ
00067 }
00068
00069 void TimException::what( std::ostream& os ) {
00070
00071 os << "TimException: " << getDescriptor() << endl;
00072 os << "Data1: " << getData1() << endl;
00073 os << "Data2: " << getData2() << endl;
00074 }
00075
00076
00077
00078
00079
00080
00081
00083
00087 TimModule::TimModule( UINT32 baseAddr, UINT32 mapSize, VmeInterface & vme ) :
00088 VmeModule( baseAddr, mapSize, vme ) {
00089
00090 m_serialNumber = 0xFFFFFFFF;
00091
00092 if (&vme == 0) throw TimException( "TimModule has no VmeInterface", 0, 0 );
00093
00094 try {
00095 m_vmePort = new VmePort( baseAddr, mapSize, VmeInterface::A32, vme );
00096
00097 m_vmePort->setExceptionTrapping( true );
00098 }
00099 catch (bad_alloc) {
00100 throw TimException( "TimModule caught bad_alloc", 0, 0 );
00101 }
00102 catch (VmeException x) {
00103 throw TimException( "TimModule caught VmeException",
00104 x.getErrorClass(), x.getErrorCode() );
00105 }
00106 }
00107
00108
00109
00113 TimModule::~TimModule() {
00114
00115 delete m_vmePort;
00116 m_vmePort = 0;
00117 }
00118
00119
00120
00121
00122
00123
00124
00128 void TimModule::initialize() {
00129
00130
00131 regLoad( TIM_REG_TRIGGER_BCID, TIM_BCID_OFFSET << 12 );
00132 regLoad( TIM_REG_ROD_MASK, 0xFFFF );
00133 fetchTimID();
00134
00135
00136 if(m_serialNumber>=0x26) {
00137 loadBitSet(TIM_REG_DEBUG_CTL,TIM_BIT_DEBUGCTL_FVDISABLE);
00138 }
00139
00140 loadFrequencyTrig( 10. );
00141 loadFrequencyFECR( 0.1 );
00142
00143 setupVME();
00144 }
00145
00146
00147
00153 void TimModule::reset() throw (TimException &) {
00154
00155 regLoad( TIM_REG_COMMAND, TIM_BIT_VRESET );
00156 int timeLeft = regTimeout( TIM_REG_COMMAND, TIM_BIT_VRESET, 0, 100 );
00157 if (timeLeft < 1) throw TimException( "TimModule reset bit timeout", 0, 0 );
00158
00159
00160
00161
00162 fetchTimID();
00163 if(m_serialNumber>=0x26) {
00164 loadBitSet(TIM_REG_DEBUG_CTL,TIM_BIT_DEBUGCTL_CSBDISABLE);
00165
00166 int timeLeft = regTimeout(TIM_REG_STATUS3,TIM_BIT_STATUS3_PLLSTABLE,TIM_BIT_STATUS3_PLLSTABLE,1000);
00167 if (timeLeft < 1) throw TimException( "TimModule PLL stable bit timeout", 0, 0 );
00168 }
00169
00170 }
00171
00172
00173
00178 void TimModule::status() {
00179
00180 statusPrint( cout );
00181 }
00182
00183
00187 UINT32 TimModule::fetchL1ID() {
00188
00189 const UINT32 lo = regFetch( TIM_REG_TRIGGER_IDLO );
00190 const UINT32 hi = regFetch( TIM_REG_TRIGGER_IDHI );
00191 UINT32 l1id;
00192
00193 if (m_firmware < 9) l1id = (lo & 0x0FFF) + ((hi & 0x0FFF) << 12);
00194 else l1id = (lo & 0xFFFF) + ((hi & 0x00FF) << 16);
00195 return l1id;
00196 }
00197
00198
00199
00203 UINT16 TimModule::fetchTimID() {
00204
00205 const UINT16 timID = regFetch( TIM_REG_TIM_ID );
00206
00207 m_serialNumber = timID & 0xFF;
00208 m_firmware = timID >> 8;
00209
00210 if (m_serialNumber == 0 || m_firmware == 0 ||
00211 m_serialNumber == 0xFF || m_firmware == 0xFF)
00212 throw TimException( "TimModule finds illegal TIM ID register",
00213 m_serialNumber, m_firmware );
00214
00215 if (m_serialNumber >= 0x20) m_firmware += 0xF00;
00216
00217 return timID;
00218 }
00219
00220
00221
00225 void TimModule::intTrigStart( const double frequency ) {
00226
00227 loadFrequencyTrig( frequency );
00228 loadBitSet( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00229 }
00230
00231
00232
00236 void TimModule::intTrigStart( const TimMaskFrequency frequency ) {
00237
00238 loadByteLo( TIM_REG_FREQUENCY, frequency );
00239 loadBitSet( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00240 }
00241
00242
00243
00247 void TimModule::intTrigStop(void) {
00248
00249 loadBitClear( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00250 }
00251
00252
00253
00257 void TimModule::issueCommand( const TimBitCommand mask ) {
00258
00259 if (mask <= TIM_VSPA) loadBitClear( TIM_REG_COMMAND, mask );
00260 loadBitSet( TIM_REG_COMMAND, mask );
00261 if (mask <= TIM_VSPA) loadBitClear( TIM_REG_COMMAND, mask );
00262 }
00263
00264
00265
00270 void TimModule::issueVCAL( const UINT8 pipelineDelay ) {
00271
00272 loadByteLo( TIM_REG_DELAY, pipelineDelay );
00273 issueCommand( TIM_VCAL );
00274 }
00275
00276
00277
00282 void TimModule::loadBitSet( const TimRegister addr, const UINT16 mask ) {
00283
00284 UINT16 value = vmeFetch( addr );
00285 vmeLoad( addr, value | mask );
00286 }
00287
00288
00289
00294 void TimModule::loadBitClear( const TimRegister addr, const UINT16 mask ) {
00295
00296 UINT16 value = vmeFetch( addr );
00297 vmeLoad( addr, value & ~mask );
00298 }
00299
00300
00301
00306 void TimModule::loadByteHi( const TimRegister addr, const UINT8 byte ) {
00307
00308 UINT16 value = vmeFetch( addr );
00309 vmeLoad( addr, (value & 0x00FF) | (byte << 8) );
00310 }
00311
00312
00313
00318 void TimModule::loadByteLo( const TimRegister addr, const UINT8 byte ) {
00319
00320 UINT16 value = vmeFetch( addr );
00321 vmeLoad( addr, (value & 0xFF00) | byte );
00322 }
00323
00324
00325
00329 void TimModule::loadFrequencyFECR( const double frequency ) {
00330
00331 const int freq = int (frequency * 1000.);
00332
00333 int pattern = TIM_MASK_FECR_0_100HZ;
00334 int chooser = 0;
00335
00336 for (int i = 0; i < TIM_FREQ_SIZE; i++) {
00337 if (TIM_FECR_FREQUENCY[i][1] <= freq &&
00338 TIM_FECR_FREQUENCY[i][1] > chooser) {
00339 chooser = TIM_FECR_FREQUENCY[i][1];
00340 pattern = TIM_FECR_FREQUENCY[i][0];
00341 }
00342 }
00343
00344 loadByteHi( TIM_REG_FREQUENCY, pattern );
00345 }
00346
00347
00348
00352 void TimModule::loadFrequencyTrig( const double frequency ) {
00353
00354 const int freq = int (frequency * 1000.);
00355
00356 int pattern = TIM_MASK_TRIG_10_0KHZ;
00357 int chooser = 0;
00358
00359 for (int i = 0; i < TIM_FREQ_SIZE; i++) {
00360 if (TIM_TRIG_FREQUENCY[i][1] <= freq &&
00361 TIM_TRIG_FREQUENCY[i][1] > chooser) {
00362 chooser = TIM_TRIG_FREQUENCY[i][1];
00363 pattern = TIM_TRIG_FREQUENCY[i][0];
00364 }
00365 }
00366
00367 loadByteLo( TIM_REG_FREQUENCY, pattern );
00368 }
00369
00370
00371
00375 void TimModule::msleep( const double milliSecs ) {
00376
00377 clock_t delay = clock_t( milliSecs * CLOCKS_PER_SEC / 1000. );
00378 clock_t start = clock();
00379
00380 while (clock() - start < delay)
00381 ;
00382 }
00383
00384
00385
00389 UINT16 TimModule::regFetch( const TimRegister addr ) {
00390
00391 UINT16 data = vmeFetch( addr );
00392 return data;
00393 }
00394
00395
00396
00400 void TimModule::regLoad( const TimRegister addr, const UINT16 data ) {
00401
00402 vmeLoad( addr, data );
00403 }
00404
00405
00406
00410 int TimModule::regTimeout( const TimRegister addr, const int mask1,
00411 const int mask2, const int timeout ) {
00412
00413 int timeLeft = timeout;
00414
00415 while (timeLeft > 0 && (regFetch( addr ) & mask1) != mask2) {
00416 timeLeft --;
00417 msleep( 1.);
00418 }
00419 return timeLeft;
00420 }
00421
00422
00423
00427 void TimModule::seqRun( const UINT16 size ) {
00428
00429 regLoad( TIM_REG_SEQ_END, size - 1 );
00430 regLoad( TIM_REG_SEQ_CONTROL, TIM_BIT_SEQ_RESET );
00431 regLoad( TIM_REG_SEQ_CONTROL, 0 );
00432 regLoad( TIM_REG_SEQ_CONTROL, TIM_BIT_SEQ_GO | TIM_BIT_SEQ_EN_ALL );
00433
00434 }
00435
00436
00437
00441 void TimModule::seqFetch( const UINT16 size, UINT16 buffer[] ) {
00442
00443 for (int i = 0; i < size; i++) {
00444 buffer[i] = vmeFetch( TIM_SEQ_ADDR + i*2 );
00445 }
00446 }
00447
00448
00449
00453 void TimModule::seqLoad( const UINT16 size, const UINT16 buffer[] ) {
00454
00455 UINT16 data;
00456 for (int i = 0; i < size; i++) {
00457 data = buffer[i];
00458 vmeLoad( TIM_SEQ_ADDR + i*2, data );
00459 }
00460 }
00461
00462
00463
00467 void TimModule::setupTTC() {
00468
00469
00470 regLoad( TIM_REG_RUN_ENABLES, TIM_BIT_EN_ID | TIM_BIT_EN_TYPE | 0xFF );
00471 regLoad( TIM_REG_COMMAND, TIM_BIT_EN_TTC );
00472 regLoad( TIM_REG_ENABLES, 0 );
00473
00474 int timeLeft = regTimeout( TIM_REG_TTC_STATUS, TIM_BIT_TTC_READY,
00475 TIM_BIT_TTC_READY, 1000 );
00476 if (timeLeft < 1) throw TimException( "TimModule TTC Ready timeout", 0, 0 );
00477 }
00478
00479
00480
00484 void TimModule::setupVME() {
00485
00486
00487 regLoad( TIM_REG_RUN_ENABLES, TIM_BIT_EN_ID | TIM_BIT_EN_TYPE );
00488 regLoad( TIM_REG_COMMAND, 0 );
00489 regLoad( TIM_REG_ENABLES, 0 );
00490 }
00491
00492
00493
00497 void TimModule::statusPrint( ostream& os ) {
00498
00499 os << "TIM status" << endl;
00500
00501 os << " Serial Number: " << m_serialNumber;
00502 os << " Version: " << m_firmware;
00503 os << endl;
00504 hex(os);
00505 os << " L1ID: " << fetchL1ID();
00506 os << " BCID: " << regFetch( TIM_REG_TRIGGER_BCID );
00507 os << " status: " << regFetch( TIM_REG_STATUS );
00508 os << endl;
00509 dec(os);
00510 }
00511
00512
00513
00517 UINT16 TimModule::vmeFetch( const UINT32 addr )
00518 throw (VmeException &) {
00519
00520 UINT16 data = 0;
00521 bool trying = true;
00522 bool error = false;
00523
00524 while (trying) {
00525 try {
00526 data = m_vmePort->read16( addr );
00527 trying = false;
00528 }
00529 catch (VmeException & vmeFailed) {
00530 if (error) throw vmeFailed;
00531 error = true;
00532 }
00533 }
00534 if (error) cerr << "TimModule::vmeFetch recovers from VmeException" << endl;
00535 return data;
00536 }
00537
00538
00539
00543 void TimModule::vmeLoad( const UINT32 addr, const UINT16 data )
00544 throw (VmeException & ) {
00545
00546 bool trying = true;
00547 bool error = false;
00548
00549 while (trying) {
00550 try {
00551 m_vmePort->write16( addr, data );
00552
00553 trying = false;
00554 }
00555 catch (VmeException & vmeFailed) {
00556 if (error) throw vmeFailed;
00557 error = true;
00558 }
00559 }
00560 if (error) cerr << "TimModule::vmeLoad recovers from VmeException" << endl;
00561 }
00562
00563 }
00564
00565
00566
00571 using namespace SctPixelRod;
00572
00573 namespace std {
00574
00575 ostream& operator<<( ostream& os, TimModule& tim ) {
00576
00577 tim.statusPrint( os );
00578
00579 return os;
00580 }
00581
00582 }