00001
00002
00053 #include <ctime>
00054 #include <iostream>
00055
00056 using namespace std;
00057
00058 #include "TimModule.h"
00059
00060 #ifdef RCDAQ
00061 #include "TIMModule/TIMException.h"
00062 #endif // RCDAQ
00063
00064
00065
00066 namespace SctPixelRod {
00067
00068
00069
00071
00072 TimException::TimException( std::string descriptor, int data1, int data2 ) :
00073 BaseException( descriptor ) {
00074
00075 m_data1 = data1;
00076 m_data2 = data2;
00077 setType( TIM );
00078
00079 #ifdef RCDAQ
00080 throw TIMException (TIMException::TIMBusError);
00081 #endif // RCDAQ
00082 }
00083
00084 void TimException::what( std::ostream& os ) {
00085
00086 os << "TimException: " << getDescriptor() << endl;
00087 os << "Data1: " << getData1() << endl;
00088 os << "Data2: " << getData2() << endl;
00089 }
00090
00091
00092
00093
00094
00095
00096
00098
00102 TimModule::TimModule( UINT32 baseAddr, UINT32 mapSize, VmeInterface & vme ) :
00103 VmeModule( baseAddr, mapSize, vme ) {
00104
00105 m_serialNumber = 0xFFFFFFFF;
00106
00107 if (&vme == 0) throw TimException( "TimModule has no VmeInterface", 0, 0 );
00108
00109 try {
00110 m_vmePort = new VmePort( baseAddr, mapSize, VmeInterface::A32, vme );
00111
00112 m_vmePort->setExceptionTrapping( true );
00113 }
00114 catch (bad_alloc) {
00115 throw TimException( "TimModule caught bad_alloc", 0, 0 );
00116 }
00117 catch (VmeException x) {
00118 throw TimException( "TimModule caught VmeException",
00119 x.getErrorClass(), x.getErrorCode() );
00120 }
00121 }
00122
00123
00124
00128 TimModule::~TimModule() {
00129
00130 delete m_vmePort;
00131 m_vmePort = 0;
00132 }
00133
00134
00135
00136
00137
00138
00139
00143 void TimModule::initialize() {
00144
00145
00146 regLoad( TIM_REG_BCID, TIM_BCID_OFFSET << 12 );
00147 regLoad( TIM_REG_RB_MASK, 0xFFFF );
00148 fetchTimID();
00149
00150
00151
00152
00153 loadFrequencyTrig( 10. );
00154 loadFrequencyFECR( 0.1 );
00155
00156 setupVME();
00157 }
00158
00159
00160
00166 void TimModule::reset() throw (TimException &) {
00167
00168 regLoad( TIM_REG_COMMAND, TIM_BIT_VRESET );
00169 int timeLeft = regTimeout( TIM_REG_COMMAND, TIM_BIT_VRESET, 0, 100 );
00170 if (timeLeft < 1) throw TimException( "TimModule reset bit timeout", 0, 0 );
00171
00172
00173
00174
00175 fetchTimID();
00176 if(m_serialNumber>=0x26) {
00177 loadBitSet(TIM_REG_DEBUG_CTL,TIM_BIT_DEBUGCTL_CSBDISABLE);
00178
00179 int timeLeft = regTimeout(TIM_REG_STATUS3,TIM_BIT_STATUS3_PLLSTABLE,TIM_BIT_STATUS3_PLLSTABLE,1000);
00180 if (timeLeft < 1) throw TimException( "TimModule PLL stable bit timeout", 0, 0 );
00181 }
00182
00183 }
00184
00185
00186
00191 void TimModule::status() {
00192
00193 statusPrint( cout );
00194 }
00195
00196
00200 UINT32 TimModule::fetchL1ID() {
00201
00202 const UINT32 lo = regFetch( TIM_REG_L1IDL );
00203 const UINT32 hi = regFetch( TIM_REG_L1IDH );
00204 UINT32 l1id;
00205
00206 if (m_firmware < 9) l1id = (lo & 0x0FFF) + ((hi & 0x0FFF) << 12);
00207 else l1id = (lo & 0xFFFF) + ((hi & 0x00FF) << 16);
00208 return l1id;
00209 }
00210
00211
00212
00216 UINT16 TimModule::fetchTimID() {
00217
00218 const UINT16 timID = regFetch( TIM_REG_TIM_ID );
00219
00220 m_serialNumber = timID & 0xFF;
00221 m_firmware = timID >> 8;
00222
00223 if (m_serialNumber == 0 || m_firmware == 0 ||
00224 m_serialNumber == 0xFF || m_firmware == 0xFF)
00225 throw TimException( "TimModule finds illegal TIM ID register",
00226 m_serialNumber, m_firmware );
00227
00228 if (m_serialNumber >= 0x20) m_firmware += 0xF00;
00229
00230 return timID;
00231 }
00232
00233
00234
00238 void TimModule::intTrigStart( const double frequency ) {
00239
00240 loadFrequencyTrig( frequency );
00241 loadBitSet( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00242 }
00243
00244
00245
00249 void TimModule::intTrigStart( const TimMaskFrequency frequency ) {
00250
00251 loadByteLo( TIM_REG_FREQUENCY, frequency );
00252 loadBitSet( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00253 }
00254
00255
00256
00260 void TimModule::intTrigStop(void) {
00261
00262 loadBitClear( TIM_REG_ENABLES, TIM_BIT_EN_INT_TRIG );
00263 }
00264
00265
00266
00270 void TimModule::issueCommand( const TimBitCommand mask ) {
00271
00272 if (mask <= TIM_VSPA) loadBitClear( TIM_REG_COMMAND, mask );
00273 loadBitSet( TIM_REG_COMMAND, mask );
00274 if (mask <= TIM_VSPA) loadBitClear( TIM_REG_COMMAND, mask );
00275 }
00276
00277
00278
00283 void TimModule::issueVCAL( const UINT8 pipelineDelay ) {
00284
00285 loadByteLo( TIM_REG_DELAYS, pipelineDelay );
00286 issueCommand( TIM_VCAL );
00287 }
00288
00289
00290
00295 void TimModule::loadBitSet( const TimRegister addr, const UINT16 mask ) {
00296
00297 UINT16 value = vmeFetch( addr );
00298 vmeLoad( addr, value | mask );
00299 }
00300
00301
00302
00307 void TimModule::loadBitClear( const TimRegister addr, const UINT16 mask ) {
00308
00309 UINT16 value = vmeFetch( addr );
00310 vmeLoad( addr, value & ~mask );
00311 }
00312
00313
00314
00319 void TimModule::loadByteHi( const TimRegister addr, const UINT8 byte ) {
00320
00321 UINT16 value = vmeFetch( addr );
00322 vmeLoad( addr, (value & 0x00FF) | (byte << 8) );
00323 }
00324
00325
00326
00331 void TimModule::loadByteLo( const TimRegister addr, const UINT8 byte ) {
00332
00333 UINT16 value = vmeFetch( addr );
00334 vmeLoad( addr, (value & 0xFF00) | byte );
00335 }
00336
00337
00338
00342 void TimModule::loadFrequencyFECR( const double frequency ) {
00343
00344 const int freq = int (frequency * 1000.);
00345
00346 int pattern = TIM_MASK_FECR_0_100HZ;
00347 int chooser = 0;
00348
00349 for (int i = 0; i < TIM_FREQ_SIZE; i++) {
00350 if (TIM_FECR_FREQUENCY[i][1] <= freq &&
00351 TIM_FECR_FREQUENCY[i][1] > chooser) {
00352 chooser = TIM_FECR_FREQUENCY[i][1];
00353 pattern = TIM_FECR_FREQUENCY[i][0];
00354 }
00355 }
00356
00357 loadByteHi( TIM_REG_FREQUENCY, pattern >> 8 );
00358 }
00359
00360
00361
00365 void TimModule::loadFrequencyTrig( const double frequency ) {
00366
00367 const int freq = int (frequency * 1000.);
00368
00369 int pattern = TIM_MASK_TRIG_10_0KHZ;
00370 int chooser = 0;
00371
00372 for (int i = 0; i < TIM_FREQ_SIZE; i++) {
00373 if (TIM_TRIG_FREQUENCY[i][1] <= freq &&
00374 TIM_TRIG_FREQUENCY[i][1] > chooser) {
00375 chooser = TIM_TRIG_FREQUENCY[i][1];
00376 pattern = TIM_TRIG_FREQUENCY[i][0];
00377 }
00378 }
00379
00380 loadByteLo( TIM_REG_FREQUENCY, pattern );
00381 }
00382
00383
00384
00388 void TimModule::msleep( const double milliSecs ) {
00389
00390 clock_t delay = clock_t( milliSecs * CLOCKS_PER_SEC / 1000. );
00391 clock_t start = clock();
00392
00393 while (clock() - start < delay)
00394 ;
00395 }
00396
00397
00398
00402 UINT16 TimModule::regFetch( const TimRegister addr ) {
00403
00404 UINT16 data = vmeFetch( addr );
00405 return data;
00406 }
00407
00408
00409
00413 void TimModule::regLoad( const TimRegister addr, const UINT16 data ) {
00414
00415 vmeLoad( addr, data );
00416 }
00417
00418
00419
00423 int TimModule::regTimeout( const TimRegister addr, const int mask1,
00424 const int mask2, const int timeout ) {
00425
00426 int timeLeft = timeout;
00427
00428 while (timeLeft > 0 && (regFetch( addr ) & mask1) != mask2) {
00429 timeLeft --;
00430 msleep( 1.);
00431 }
00432 return timeLeft;
00433 }
00434
00435
00436
00440 void TimModule::seqRun( const UINT16 size ) {
00441
00442 regLoad( TIM_REG_SEQ_END, size - 1 );
00443 regLoad( TIM_REG_SEQ_CTL, TIM_BIT_SEQ_RESET );
00444 regLoad( TIM_REG_SEQ_CTL, 0 );
00445 regLoad( TIM_REG_SEQ_CTL, TIM_BIT_SEQ_GO | TIM_BIT_SEQ_EN_ALL );
00446
00447 }
00448
00449
00450
00454 void TimModule::seqFetch( const UINT16 size, UINT16 buffer[] ) {
00455
00456 for (int i = 0; i < size; i++) {
00457 buffer[i] = vmeFetch( TIM_SEQ_ADDR + i*2 );
00458 }
00459 }
00460
00461
00462
00466 void TimModule::seqLoad( const UINT16 size, const UINT16 buffer[] ) {
00467
00468 UINT16 data;
00469 for (int i = 0; i < size; i++) {
00470 data = buffer[i];
00471 vmeLoad( TIM_SEQ_ADDR + i*2, data );
00472 }
00473 }
00474
00475
00476
00480 void TimModule::setupTTC() {
00481
00482
00483 regLoad( TIM_REG_RUN_ENABLE, TIM_BIT_EN_ID | TIM_BIT_EN_TYPE | 0xFF );
00484 regLoad( TIM_REG_COMMAND, TIM_BIT_EN_TTC );
00485 regLoad( TIM_REG_ENABLES, 0 );
00486
00487 int timeLeft = regTimeout( TIM_REG_TTC_STATUS, TIM_BIT_TTC_READY,
00488 TIM_BIT_TTC_READY, 1000 );
00489 if (timeLeft < 1) throw TimException( "TimModule TTC Ready timeout", 0, 0 );
00490 }
00491
00492
00493
00497 void TimModule::setupVME() {
00498
00499
00500 regLoad( TIM_REG_RUN_ENABLE, TIM_BIT_EN_ID | TIM_BIT_EN_TYPE );
00501 regLoad( TIM_REG_COMMAND, 0 );
00502 regLoad( TIM_REG_ENABLES, 0 );
00503 }
00504
00505
00506
00510 void TimModule::statusPrint( ostream& os ) {
00511
00512 os << "TIM status" << endl;
00513
00514 os << " Serial Number: " << m_serialNumber;
00515 os << " Version: " << m_firmware;
00516 os << endl;
00517 hex(os);
00518 os << " L1ID: " << fetchL1ID();
00519 os << " BCID: " << regFetch( TIM_REG_BCID );
00520 os << " status: " << regFetch( TIM_REG_STATUS );
00521 os << endl;
00522 dec(os);
00523 }
00524
00525
00526
00530 UINT16 TimModule::vmeFetch( const UINT32 addr )
00531 throw (VmeException &) {
00532
00533 UINT16 data = 0;
00534 bool trying = true;
00535 bool error = false;
00536
00537 while (trying) {
00538 try {
00539 data = m_vmePort->read16( addr );
00540 trying = false;
00541 }
00542 catch (VmeException & vmeFailed) {
00543 if (error) throw vmeFailed;
00544 error = true;
00545 }
00546 }
00547 if (error) cerr << "TimModule::vmeFetch recovers from VmeException" << endl;
00548 return data;
00549 }
00550
00551
00552
00556 void TimModule::vmeLoad( const UINT32 addr, const UINT16 data )
00557 throw (VmeException & ) {
00558
00559 bool trying = true;
00560 bool error = false;
00561
00562 while (trying) {
00563 try {
00564 m_vmePort->write16( addr, data );
00565
00566 trying = false;
00567 }
00568 catch (VmeException & vmeFailed) {
00569 if (error) throw vmeFailed;
00570 error = true;
00571 }
00572 }
00573 if (error) cerr << "TimModule::vmeLoad recovers from VmeException" << endl;
00574 }
00575
00576 }
00577
00578
00579
00584 using namespace SctPixelRod;
00585
00586 namespace std {
00587
00588 ostream& operator<<( ostream& os, TimModule& tim ) {
00589
00590 tim.statusPrint( os );
00591
00592 return os;
00593 }
00594
00595 }