Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Related Pages

crate.cxx

00001 
00007 #include <unistd.h>
00008 #include <time.h>
00009 
00010 #include <iostream>
00011 #include <fstream>
00012 
00013 #include "Sct/SctNames.h"
00014 #include "Sct/Env.h"
00015 
00016 #include "RodCrate/RodModule.h"
00017 #include "RodCrate/BocCard.h"
00018 #include "RodCrate/TimModule.h"              // For TimMaskFrequency
00019 // #include "VmeInterface/VmeInterface.h"
00020 
00021 #include "sctConf/configXMLImpl.h"
00022 
00023 #include "../VmeInterface/DummyVmeInterface.h"
00024 #ifndef USE_DUMMY_VME
00025 #include "../VmeInterface/RCCVmeInterface.h"
00026 #endif
00027 
00028 #include "VmeDecode.h"
00029 
00030 #include "SctApiDebug.h"
00031 
00032 #include "SctApiConsts.h"
00033 #include "crateImpl.h"
00034 
00035 #include "extraScans.h"
00036 
00037 #ifdef USE_THREADS
00038 #include <boost/bind.hpp>
00039 #endif
00040 
00041 // For modify BOC params
00042 #include "ABCD/ABCDscans.h"
00043 
00044 using namespace SctPixelRod;
00045 using namespace SctConfiguration;
00046 // All std namespace are qualified explicitly
00047 
00048 namespace SctApi {
00049 /*
00050 The constructor. Tell this crate which partition it belongs to.
00051 This creates a VmeInterface.
00052 */
00053 CrateImpl::CrateImpl(unsigned int partition, unsigned int crate, 
00054                      boost::shared_ptr<Configuration> newConf) : 
00055   rodMap(), tim(0), config(newConf), vme(0), 
00056   partition(partition), crate(crate), mrs(0), 
00057   m_stopPolling(false), m_enablePolling(true)
00058 {
00059   // Create VME interface
00060   std::cout << "Initialising VME interface ... \n";
00061 
00062   MRSStream *tempMrs = 0;
00063 
00064   if(::Sct::SctNames::isMrsValid()) {
00065     tempMrs = &(::Sct::SctNames::Mrs());
00066     std::cerr << "Crate " << partition << ", " << crate << " found temporary mrs server\n";
00067   } else {
00068     std::cerr << "Crate " << partition << ", " << crate << " no mrs server, going to standalone mode\n";
00069   }
00070 
00071   if(config->isDummyCrate(partition, crate)) { 
00072     vme = new SctPixelRod::DummyVmeInterface();
00073 
00074     if(tempMrs) {
00075       *tempMrs << "CRATE_DUMMY"  << MRS_WARNING << MRS_QUALIF("SCTAPI") << MRS_TEXT("Using DUMMY interface") << ENDM;
00076     }
00077 #ifdef USE_DUMMY_VME
00078   } else {
00079     if(tempMrs) {
00080       *tempMrs << "CRATE_DUMMY"  << MRS_ERROR << MRS_QUALIF("SCTAPI") << MRS_TEXT("Non dummy crate requested, support not compiled!") << ENDM;
00081     }
00082 
00083     throw CrateException("RCC support not compiled");
00084   }
00085 #else
00086   } else {
00087     // Recent versions of VmeInterface check return code and throw exception
00088     try {
00089       vme = new SctPixelRod::RCCVmeInterface();
00090     } catch (VmeException &v) {
00091       Utility::decodeVme(v);
00092       std::cerr << "Interface not opened exception, check host and VME drivers. Crate initialisation failed!!\n";
00093 
00094       if(tempMrs) {
00095         *tempMrs << "CRATEINIT_FAILED" << MRS_ERROR << MRS_QUALIF("SCTAPI") << MRS_TEXT("Crate initialisation failed (VME interface)") << ENDM;
00096       }
00097 
00098       throw CrateException("Interface not found");
00099     }
00100 
00101     // Old versions don't, so we have to do it here
00102     if(vme->getLastErrcode() == 515) {
00103       // Failed to open interface (probably not running on an SBC!)
00104       std::cerr << "Interface not opened error, check host and VME drivers. Crate initialisation failed!!\n";
00105 
00106       if(tempMrs) {
00107         *tempMrs << "CRATEINIT_FAILED" << MRS_ERROR << MRS_QUALIF("SCTAPI") << MRS_TEXT("Crate initialisation failed (VME interface)") << ENDM;
00108       }
00109 
00110       throw CrateException("Interface not found");
00111     }
00112     //    std::cout << "Last error " << vme->getLastErrcode() << " (" << vme->getErrorMessage(vme->getLastErrcode()) << std::endl;
00113 
00114     if(tempMrs) {
00115       *tempMrs << "CRATEINIT_SUCCESS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << MRS_TEXT("Successfully initialised VME interface") << ENDM;
00116     }
00117   }
00118 #endif
00119 
00120   std::cout << " ... Done\n";
00121 
00122   if(config.get() == 0) {
00123     std::cout << "Load configuration\n";
00124     config.reset(new ConfigurationXMLImpl());
00125   }
00126 
00127 #if USE_THREADS
00128   pollThread.reset(new boost::thread(boost::bind(&CrateImpl::pollingLoop, this)));
00129 #endif
00130 }
00131 
00132 /*
00133 The destructor. Delete all the RodModules and VmeInterface
00134 */
00135 CrateImpl::~CrateImpl() {
00136   // First make sure the polling is not using them
00137 #if USE_THREADS
00138   m_stopPolling = true;
00139   pollThread->join();
00140 #endif
00141 
00142   for(RodMap::const_iterator i=rodMap.begin();i!=rodMap.end();i++){
00143     std::cout << "RodModule on shutdown " << *(i->second.second) << std::endl;
00144     delete i->second.first;    //RodStatus
00145     delete i->second.second;   //RodModule
00146   }
00147   delete tim;
00148 
00149   delete vme;
00150 }
00151 
00152 void CrateImpl::rodInitialiseThread(int rod) {
00153   if(initialiseRod(rod) != 0) {
00154     std::cout << "Initialisation of rod  " << rod << " failed!\n";
00155     return;
00156   }
00157 
00158   rodCounter ++;
00159 
00160   if(initialiseBOC(rod) == 0) {
00161     if(Debug::getInstance()->checkDebugOption(DEBUG_DIAG)) {
00162       std::cout << "Should have initialised BOC now" << std::endl;
00163     }
00164   } // Else unsuccessful
00165 }
00166 
00167 int CrateImpl::initialiseCrate() {
00168   if(!initialiseTim()) {
00169     std::cout << "TIM initialise successful\n";
00170   }
00171 
00172   std::list<unsigned int> rods;
00173   try {
00174     rods = config->listRodsInCrate(partition, crate);
00175   } catch(ConfigurationException &c) {
00176     std::cout << "No RODs in this crate\n";
00177     std::cout << c.what() << std::endl;
00178 
00179     return 0;
00180   }
00181 
00182   std::cout << "Found configuration for " << rods.size() << " rods\n";
00183 
00184   std::list<boost::shared_ptr<boost::thread> > rodInitThreads;
00185 
00186   rodCounter = 0;
00187 
00188   for(std::list<unsigned int>::const_iterator r=rods.begin(); 
00189       r!=rods.end(); 
00190       r++) {
00191 
00192     rodInitThreads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&CrateImpl::rodInitialiseThread, this, *r))));
00193   }
00194 
00195   for(std::list<boost::shared_ptr<boost::thread> >::const_iterator thread = rodInitThreads.begin();
00196       thread != rodInitThreads.end(); 
00197       thread ++) {
00198 
00199     if(*thread) {
00200       (*thread)->join();
00201     } else {
00202       std::cout << " Null pointer to thread!\n";
00203     }
00204   }
00205 
00206   int totalRods = rodCounter;
00207 
00208   return totalRods;
00209 }
00210 
00211 
00212 /*
00213   Create a TimModule object using information from the Configuration.
00214 */
00215 int CrateImpl::initialiseTim() {
00216   std::cout << "Load configuration for tim\n";
00217 
00218   TimConfig timConf;
00219   try {
00220     timConf = config->getTimConfig(partition, crate);
00221   } catch(ConfigurationException &c) {
00222     tim = 0;
00223     return -1;
00224   }
00225 
00226   try {
00227     // Create TimModule and initialize it
00228     std::cout << "Initialise TIM\n";
00229 
00230     tim = new SctPixelRod::TimModule(timConf.baseAddress, timMapSize, *vme);
00231 
00232     std::cout << "Constructed\n";
00233 
00234     tim->reset();
00235     tim->initialize();
00236 
00237     std::cout << "Initialised\n";
00238 
00239     std::cout << "Started TIM\n";
00240     tim->status();
00241 
00242     // Switch TIM trigger frequency to something not the default (600kHz!)
00243     timSetFrequency(timConf.trigFrequency, timConf.resetFrequency);
00244   } catch (SctPixelRod::TimException &r) {
00245     tim = 0;
00246 
00247     std::cerr << "While initialising TIM " << partition << " " << crate << ":\n";
00248     std::cerr << "Got TimException: " << std::endl;
00249     std::cerr << r.getDescriptor() << ", " << r.getData1() << ", " << r.getData2() << std::endl;
00250     std::cerr << "Continuing...\n";
00251   } catch (VmeException &v) {
00252     tim = 0;
00253 
00254     std::cout << "VmeException initialising TIM:\n";
00255     Utility::decodeVme(v);
00256 
00257     return -9;
00258   } catch (...) {
00259     tim = 0;
00260 
00261     std::cerr << "Unknown exception initialising TIM\n";
00262 
00263     return -6;
00264   }
00265 
00266   return 0;
00267 }
00268 
00269 
00270 std::list<unsigned> CrateImpl::getListOfRods() const{
00271   std::list<unsigned> rods;
00272   for (RodMap::const_iterator item = rodMap.begin();
00273       item != rodMap.end();
00274        item++) {
00275     rods.push_back(item->first);
00276   }
00277   return rods;
00278 }
00279 
00280 /*
00281   Create a RodModule object using information from the Configuration.
00282 */
00283 int CrateImpl::initialiseRod(unsigned int rod) {
00284   int returnValue = 0;
00285 
00286   char *returnReason = "none  specified";
00287 
00288   int slave = 0;
00289 
00290   // 1 is not a valid address!
00291   unsigned long rodAddress=1;
00292 
00293   std::cout << "Load configuration for rod\n";
00294 
00295   if(config->isDummyCrate(partition, crate)) {
00296     // Don't create a RODModule!
00297     //  But return success so a ROD is counted
00298     return 0;
00299   }
00300 
00301 
00302   SctPixelRod::RodModule* rodObject;
00303 
00304   try {
00305     SctConfiguration::RodConfig rodConf;
00306 
00307     rodConf = config->getRodConfig(partition, crate, rod);
00308 
00309     rodAddress = rodConf.baseAddress;
00310 
00311     // Create RodModule and initialize it
00312     std::cout << "Initialise ROD " << rod << " at 0x" << std::hex << rodConf.baseAddress << std::dec << std::endl;
00313 
00314     rodObject = new SctPixelRod::RodModule(rodConf.baseAddress, 
00315                                            rodMapSize, 
00316                                            *vme, 
00317                                            numSlaves);
00318 
00319     std::cout << "Constructed\n";
00320 
00321     if(rodConf.resetLevel > 1) {
00322       std::cout << "*** ROD reset level " << rodConf.resetLevel << " (not reset) **** \n";
00323       std::cout << "*** Debug, ROD not reset **** \n";
00324       rodObject->initialize(false);  // Don't reset the ROD!
00325     } else {
00326       std::cout << "Doing full ROD reset...\n";
00327       // The true is a new feature to reset the ROD (what it always used to do!)
00328       rodObject->initialize(true);   // Use true to reset the ROD!
00329       std::cout << " ... done\n";
00330     }
00331 
00332     std::cout << "Initialised\n";
00333 
00334     std::cout << "Started ROD\n";
00335 
00336     rodObject->status();
00337 
00338     while(rodObject->textHandler() == TEXT_RQ_SET) {
00339       doTextBuffer(*rodObject);
00340       // textstate now TEXT_IDLE, check for multiple text buffers in while statement
00341     }
00342 
00343     RodStatus *currStatus = new RodStatus;
00344     currStatus->slaves = 0;
00345 #if USE_THREADS
00346     currStatus->currState = MYPRIM_STATE_IDLE;
00347     //     std::cout << "STATE: Initialising state to IDLE\n";
00348 #endif
00349 
00350 #if USE_ROD_MODULE_SLAVES
00351     int startedSlaves = 0;
00352 
00353     // Initialize slaves requested by config
00354     try {
00355       for(slave=0;  slave < rodConf.numSlaves; slave++) {
00356         if(rodConf.slaves[slave].ipramFile != "") {
00357           string ip(rodConf.slaves[slave].ipramFile);
00358           ip = Sct::Env::substituteVariables(ip);
00359 
00360           string id(rodConf.slaves[slave].idramFile);
00361           id = Sct::Env::substituteVariables(id);
00362 
00363           string ext(rodConf.slaves[slave].extFile);
00364           ext = Sct::Env::substituteVariables(ext);
00365 
00366           std::cerr << "Starting slave " << slave << std::endl;
00367           std::cerr << "((" << ip << ", " << id << ", " << ext << ")\n";
00368 
00369           rodObject->initSlaveDsp(ip, id, ext, slave, 'v');
00370 
00371           RodOutList *outList = rodObject->getOutList();
00372           if(outList) {
00373             unsigned long* outBody = outList->getBody();
00374 
00375             if(outBody) {
00376               if(outBody[3] != PRIM_LIST_REVISION) {
00377                 std::cout << "Prim list revision disagrees\n";
00378               }
00379 
00380               if(outBody[6] != START_SLAVE_EXECUTING) {
00381                 std::cout << "Prim ID not start slave!\n";
00382               }
00383 
00384               if(outBody[8] != slave) {
00385                 std::cout << "Start slave says slave 0x" << std::hex << outBody[8] << std::dec << " started not " << slave << std::endl;
00386               }
00387             } else {
00388               std::cout << "No body from start slave outlist!\n";
00389             }
00390           } else {
00391             std::cout << "No response from start slave!\n";
00392           }
00393           startedSlaves ++;
00394           currStatus->slaves |= 1<<slave;
00395         }
00396       }
00397     } catch (SctPixelRod::NoImageFile &f) {
00398       std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << " slave " << slave << ":\n";
00399       std::cerr << "No image file exception " << f.getFileName() << std::endl;
00400       std::cerr << "Continuing...\n";
00401 
00402       if(startedSlaves < 1) {
00403         *mrs << "ROD Slave Initialisation Failure" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
00404              << MRS_PARAM<const char *>("Filename", f.getFileName().c_str())
00405              << ENDM;
00406       }
00407     } catch (SctPixelRod::RodException &r) {
00408       std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << " slave " << slave << ":\n";
00409       std::cerr << "Bad ROD exception: " << std::endl;
00410       std::cerr << r.getDescriptor() << ", " << r.getData1() << ", " << r.getData2() << std::endl;
00411       std::cerr << "Continuing...\n";
00412     }
00413 
00414     std::cout << "Started " << startedSlaves << " ROD slave DSPs\n";
00415 #endif
00416 
00417     rodMap.insert(std::make_pair(rod, std::make_pair(currStatus, rodObject)));
00418 
00419     std::cout << "ROD " << rod << " initialised\n";
00420 
00421     if(mrs) {
00422       *mrs << "ROD_INIT" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
00423            << MRS_PARAM<int>("number", rod)
00424            << MRS_PARAM<int>("slot", rodObject->getSlot())
00425            << MRS_TEXT("ROD Initialised")
00426            << ENDM;
00427     }
00428   } catch(ConfigurationException &c) {
00429     std::cout << "Configuration error for rod " << rod << "\n";
00430     std::cout << "\t" << c.what() << std::endl;
00431     returnValue = -1;
00432     returnReason = "Error in configuration database";
00433   } catch (SctPixelRod::PrimListException &p) {
00434     std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << ":\n";
00435     std::cerr << "Exception sending primlist:\n";
00436     std::cerr << p.getDescriptor() << " " << p.getData1() << ", " << p.getData2() << std::endl;
00437 
00438     returnReason = "PrimList exception";
00439     returnValue = -2;
00440   } catch (SctPixelRod::HpiException &h) {    
00441     std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << ":\n";
00442     std::cerr << "HpiException:\n";
00443     std::hex(std::cerr);
00444     std::cerr << h.getDescriptor() << '\n';
00445     std::cerr << "calcAddr: " << h.getCalcAddr() << ", readAddr: " << 
00446       h.getReadAddr() << '\n';
00447     std::dec(std::cerr);
00448 
00449     returnReason = "HPI exception";
00450     returnValue = -3;
00451   } catch (SctPixelRod::RodException &r) {
00452     std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << ":\n";
00453     std::cerr << "Rod Exception\n";
00454     std::cerr << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2()
00455               << '\n';
00456 
00457     returnReason = "ROD exception";
00458     returnValue = -4;
00459   } catch (SctPixelRod::NoImageFile &f) { // This will be caught in the slave section!
00460     std::cerr << "While initialising ROD " << partition << " " << crate << " " << rod << " slave " << slave << ":\n";
00461     std::cerr << "No image file exception " << f.getFileName() << std::endl;
00462 
00463     returnReason = "NoImageFile exception";
00464     returnValue = -5;
00465   } catch (VmeException &v) {
00466     std::cout << "VmeException initialising ROD:\n";
00467     Utility::decodeVme(v);
00468 
00469     returnReason = "VmeException";
00470 
00471     returnValue = -9;
00472   } catch (...) {
00473     std::cerr << "Unknown exception initialising ROD\n";
00474     returnValue = -6;
00475   }
00476 
00477   if(returnValue < 0) {
00478     if(mrs) {
00479       *mrs << "RODINIT_FAIL" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
00480            << MRS_TEXT("ROD init failure")
00481            << MRS_PARAM<const char *>("reason", returnReason)
00482            << MRS_PARAM<int>("number", rod);
00483       if(rodAddress != 1) 
00484         *mrs << MRS_PARAM<int>("address", rodAddress);
00485       *mrs << ENDM;
00486     }
00487   }
00488 
00489   return returnValue;
00490 }
00491 
00492 /*
00493   Initialise a BOC using information from the Configuration.
00494 */
00495 int CrateImpl::initialiseBOC(unsigned int rod) {
00496   BocCard* bocCard;
00497 
00498   try {
00499     //     SctConfiguration::RodConfig rodConf = config->getRodConfig(partition, crate, rod);
00500 
00501     //     if(!rodConf.bocPresent) {
00502     //       std::cout << "Skipping BOC (configuration says not present)\n";
00503     //       return -2;
00504     //     }
00505   } catch(ConfigurationException &c) {
00506     std::cout << "Request to initialise BOC with unconfigured rod\n";
00507     return -1;
00508   }
00509 
00510   if(RODPresent(rod)) {
00511     try {
00512       std::cout << "Initialise BOC " << rod << std::endl;
00513 
00514       bocCard = getRod(rod)->getBocCard();
00515 
00516       if(bocCard == 0) {
00517         // Jumper on ROD set for no BOC 
00518         return -2;
00519       }
00520 
00521       bocCard->initialize();
00522       bocCard->status(); // temporary
00523 
00524     } catch (VmeException &v) {
00525       std::cout << "VmeException initialising BOC:\n";
00526       Utility::decodeVme(v);
00527       return -9;
00528     } catch (BocException &b) {
00529       std::cout << "BocException initialising BOC:\n";
00530       std::cout << b << std::endl;
00531       return -9;
00532     } catch (...) {
00533       std::cerr << "Unknown exception initialising BOC\n";
00534       return -6;
00535     }
00536 
00537     configureBOC(rod);
00538   } else {
00539     std::cout << "Request for non-existent BOC " << partition << " " << crate << " " << rod << std::endl;
00540     return -1;
00541   }
00542 
00543   return 0;
00544 }
00545 
00546 /*
00547   Set up a BOC parameters according to information from the Configuration.
00548 */
00549 int CrateImpl::configureBOC(unsigned int rod) {
00550   if(!RODPresent(rod) || getRod(rod)->getBocCard() == 0) {
00551     std::cout << " configureBOC called on missing ROD/BOC " << rod << std::endl;
00552     throw CrateException("Trying to configure missing BOC");
00553   }
00554 
00555   BocCard *bocCard = getRod(rod)->getBocCard();
00556 
00557 
00558   std::cout << " *************  Turning lasers on ROD " << rod << " ON  ***************\n";
00559 
00560   BOCGlobalConfig globalConf = config->getBOCGlobalConfig(partition, crate, rod);
00561   for(int r=0; r<9; r++) {
00562     if(globalConf.validMask & 1<<r) {
00563       switch(r) {
00564       case 0:
00565         bocCard->setClockControl(globalConf.clockControl);
00566         break;
00567       case 1:
00568         bocCard->setRxDataMode(globalConf.rxDataMode);
00569         break;
00570       case 2:
00571         if(globalConf.rxDacClear)
00572           bocCard->clearRxDac();
00573         break;
00574       case 3:
00575         if(globalConf.txDacClear)
00576           bocCard->clearTxDac();
00577         break;
00578       case 4:
00579         bocCard->setVernierFinePhase(globalConf.vernierFinePhase);
00580         break;
00581       case 5:
00582         bocCard->setVernierClockPhase0(globalConf.vernierClockPhase0);
00583         break;
00584       case 6:
00585         bocCard->setVernierClockPhase1(globalConf.vernierClockPhase1);
00586         break;
00587       case 7:
00588         bocCard->setBpmClockPhase(globalConf.bpmClockPhase);
00589         break;
00590       case 8:
00591         bocCard->setBregClockPhase(globalConf.bregClockPhase);
00592         break;
00593       }
00594     }
00595   }
00596 
00597   unsigned char *mappings = config->getFibreMappings(partition, crate, rod);
00598 
00599   for(int channel=0;channel<48;channel++){
00600     // How far we got
00601     int step = 0;
00602 
00603     try {
00604       BOCChannelConfig channelConfig = config->getBOCConfig(partition, crate, rod, channel);
00605       std::cout << " Data for channel " << channel << std::endl;
00606 
00607       // NB - fibre mapping hopefully now not hard wired
00608       int txChannel = mappings[channel * 3 + 0];
00609       int rx0Channel = mappings[channel * 3 + 1];
00610       int rx1Channel = mappings[channel * 3 + 2];
00611 
00612       // Neither fibre is DATA_LINK_OFF
00613       if(rx0Channel <= 95 && rx1Channel <= 95 
00614      // Check for stated condition
00615      && (((rx0Channel / 2) != (rx1Channel / 2)) || (rx0Channel == rx1Channel))) {
00616         std::cout << "Illegal rx fibre mappings for channel " << channel << std::endl;
00617         std::cout << "  rx fibres must be mapped in consecutive pairs and low fibre must be even\n";
00618         if(mrs) {
00619           *mrs << "CRATE_FIBRES"  << MRS_WARNING << MRS_QUALIF("SCTAPI")
00620                << MRS_TEXT("RX fibres must be mapped in consecutive pairs and low fibre must be even") 
00621                << MRS_PARAM<int>("channel", channel)
00622                << MRS_PARAM<int>("fibre0", rx0Channel)
00623                << MRS_PARAM<int>("fibre1", rx1Channel)
00624                << MRS_PARAM<int>("partition", partition)
00625                << MRS_PARAM<int>("crate", crate)
00626                << MRS_PARAM<int>("rod", rod)
00627                << ENDM;
00628         }
00629       }
00630 
00631       //        std::cout << txChannel << " " << rx0Channel << " " << rx1Channel << std::endl;
00632 
00633       // Configure clock/command output
00634       bocCard->setLaserCurrent(txChannel,   channelConfig.current);
00635       step ++;
00636       bocCard->setBpmFineDelay(txChannel,   (channelConfig.delay&0xff) );
00637       step ++;
00638       bocCard->setBpmCoarseDelay(txChannel, ((channelConfig.delay>>8)&0xff));
00639       step ++;
00640       bocCard->setBpmMarkSpace(txChannel,   channelConfig.markSpace);
00641       step ++;
00642 
00643       // Configure data reception
00644       if((unsigned char)rx0Channel != (unsigned char)DATA_LINK_OFF) {
00645     bocCard->setRxThreshold(rx0Channel, channelConfig.threshold0);
00646         step ++;
00647     bocCard->setRxDataDelay(rx0Channel, channelConfig.delay0);
00648         step ++;
00649       }
00650       if((unsigned char)rx1Channel != (unsigned char)DATA_LINK_OFF) {
00651     bocCard->setRxThreshold(rx1Channel, channelConfig.threshold1);
00652         step ++;
00653     bocCard->setRxDataDelay(rx1Channel, channelConfig.delay1);
00654         step ++;
00655       }
00656     } catch(ConfigurationException &c) {
00657       // This would be worth saying if a module was attached
00658       //         std::cout << "No channel data for BOC " << rod << " channel " << channel << std::endl;
00659     } catch(BaseException &b) {
00660       std::cout << "Exception setting channel data for BOC step " << step << " ROD (" << rod << " channel " << channel << "): " << b << std::endl;
00661     }
00662   }
00663 
00664   delete [] mappings;
00665 
00666   return 0;
00667 }
00668 
00674 int CrateImpl::sendPrimList(unsigned int rod, boost::shared_ptr<PrimListWrapper> prim) {
00675   if(RODPresent(rod)) {   // If there's a rod presumably there's a data structure with it...
00676 #if USE_THREADS
00677     if(m_stopPolling) {
00678       std::cerr << "PRIM LIST: Send prim list called when polling stopped\n";
00679       throw(CrateException("Called sendPrimList with polling stopped"));
00680     }
00681 
00682     {
00683       RodStatus &stat = getRodData(rod);
00684       boost::mutex::scoped_lock lock(stat.mutex);
00685 
00686       getRod(rod)->deleteOutList();
00687 
00688       {
00689         boost::mutex::scoped_lock lock(primQueue_mutex);
00690         stat.listQueue.push_back(prim);
00691         primQueue_notEmpty.notify_one();
00692       }
00693 
00694       //       std::cout << "STATE: Changing state to LOADED\n";
00695       if(stat.currState == MYPRIM_STATE_IDLE) {
00696         stat.currState = MYPRIM_STATE_LOADED;
00697       } else {
00698 #warning "Throw exception?"
00699         std::cerr << "PRIM LIST: Sending prim list when not idle! (" << stat.currState << ")!\n";
00700         stat.currState = MYPRIM_STATE_LOADED;
00701         return -10;
00702       }
00703     }  // Release lock
00704 #else
00705     try {
00706       // So the result can't be confused with any previous
00707       getRod(rod)->deleteOutList();
00708       getRod(rod)->sendPrimList(prim->list.get());
00709     } catch (SctPixelRod::PrimListException &p) {
00710       std::cerr << "While sending primlist " << partition << " " << crate << " " << rod << ":\n";
00711       std::cerr << "Exception sending primlist:\n";
00712       std::cerr << p.getDescriptor() << " " << p.getData1() << ", " << p.getData2() << std::endl;
00713       return -6;
00714     } catch (SctPixelRod::HpiException &h) {    
00715       std::cerr << "While sending primlist " << partition << " " << crate << " " << rod << ":\n";
00716       std::cerr << "HpiException:\n";
00717       std::hex(std::cerr);
00718       std::cerr << h.getDescriptor() << '\n';
00719       std::cerr << "calcAddr: " << h.getCalcAddr() << ", readAddr: " << 
00720         h.getReadAddr() << '\n';
00721       std::dec(std::cerr);
00722       return -2;
00723     } catch (SctPixelRod::RodException &r) {
00724       std::cerr << "While sending primlist " << partition << " " << crate << " " << rod << ":\n";
00725       std::cerr << "Rod Exception\n";
00726       std::cerr << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2()
00727                 << '\n';
00728       return -3;
00729     } catch (SctPixelRod::NoImageFile &f) {
00730       std::cerr << "While sending primlist " << partition << " " << crate << " " << rod << ":\n";
00731       std::cerr << "No image file exception " << f.getFileName() << std::endl;
00732       return -4;
00733     } catch (...) {
00734       std::cerr << "Unknown exception sending primlist to ROD\n";
00735       return -5;
00736     }
00737     //    std::cout << "Status after sendPrimList is: " << *(getRod(rod));
00738 
00739 #endif
00740   } else {
00741     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
00742     return -1;
00743   }
00744 
00745   return 0;
00746 }
00747 
00751 int CrateImpl::sendPrimListAll(boost::shared_ptr<PrimListWrapper> prim) {
00752 #if USE_THREADS
00753   {
00754     boost::mutex::scoped_lock lock(primQueue_mutex);
00755     listQueueAll.push_back(prim);
00756     primQueue_notEmpty.notify_one();
00757   }
00758 
00759   return 0;
00760 #else
00761   int result = 0;
00762   for(RodMap::const_iterator item = rodMap.begin();
00763       item != rodMap.end();
00764       item++) {
00765     int rod = item->first;
00766 
00767     int newResult = sendPrimList(rod, prim);
00768     if(result == 0) result = newResult;
00769   }
00770 
00771   return result;
00772 #endif
00773 }
00774 
00775 void CrateImpl::primListControl(unsigned int index, PLControl function) {
00776   if(RODPresent(index)) {
00777     SctPixelRod::RodModule &rod = *(getRod(index));
00778 
00779     switch(function) {
00780     case C_PL_STOP:
00781       rod.setVmeCommandRegBit(CR_ABORT);
00782       break;
00783     case C_PL_PAUSE:
00784       rod.setVmeCommandRegBit(CR_PAUSE);
00785       break;
00786     case C_PL_RESUME:
00787       rod.setVmeCommandRegBit(CR_RESUME);
00788       break;
00789     case C_PL_CANCEL:
00790       rod.clearVmeCommandRegBit(CR_IN_LIST_RDY);
00791       break;
00792     }
00793   }
00794 }
00795 
00796 /*
00797   Await response from a ROD within this crate
00798 */
00799 int CrateImpl::awaitResponse(unsigned int rod, int timeout) {
00800   // Preliminary implementation from EchoTest
00801   // Wait for ROD to begin executing and then wait for it to finish executing
00802   // Check for error messages in text buffer and read them out if they exist.
00803 
00804   using namespace SctPixelRod;
00805 
00806   bool timedout = false;
00807 
00808   time_t start_time = time(0);
00809 
00810   if(RODPresent(rod)) {
00811 #if USE_THREADS
00812     //     RodPrimState returnPState;
00813     /* Using threads we let the polling thread handle the text buffers
00814        and all the communication with the ROD 
00815     */
00816 
00817     RodStatus &status = getRodData(rod);
00818 
00819     // Shouldn't be called in the idle state...
00820     //  but for sendPrimListAll can get here before changing state.
00821 
00822     try {
00823       // Assign value to prevent warnings
00824       RodPrimState localState = MYPRIM_STATE_EXECUTING;
00825       do {
00826         if((time(0) - start_time) > timeout) {
00827           timedout = true;
00828           std::cout << "Timeout from wait complete\n";
00829 
00830           SctPixelRod::RodModule &myRod = *getRod(rod);
00831           std::cout << "  Current state is ";
00832           switch(myRod.getPrimState()) {
00833           case PRIM_IDLE: std::cout << "IDLE"; break;
00834           case PRIM_LOADED: std::cout << "LOADED"; break;
00835           case PRIM_EXECUTING: std::cout << "EXECUTING"; break;
00836           case PRIM_WAITING: std::cout << "WAITING"; break;
00837           case PRIM_PAUSED: std::cout << "PAUSED"; break;
00838           }
00839           std::cout << std::endl;
00840           std::cout << "  Local state is ";
00841           switch(localState) {
00842           case MYPRIM_STATE_LOADED: std::cout << "LOADED"; break;
00843           case MYPRIM_STATE_EXECUTING: std::cout << "EXECUTING"; break;
00844           case MYPRIM_STATE_COMPLETE: std::cout << "COMPLETE"; break;
00845           case MYPRIM_STATE_IDLE: std::cout << "IDLE"; break;
00846           }
00847           std::cout << std::endl;
00848         }
00849 
00850         // Yield when haven't got the lock...
00851         sched_yield();
00852 
00853         {
00854           boost::mutex::scoped_lock statLock(status.mutex);
00855           localState = status.currState;
00856         }
00857       } while ((localState != MYPRIM_STATE_COMPLETE)
00858                &&(!timedout));
00859       //      std::cout << "AwaitResponse: done wait or idle " << status.currState << "\n";
00860 
00861       {
00862         boost::mutex::scoped_lock statLock(status.mutex);
00863         status.currState = MYPRIM_STATE_IDLE;
00864         //         std::cout << "STATE: Changing state to IDLE\n";
00865 
00866         //         std::cout << "Current length of queue " << status.listQueue.size() << std::endl;
00867         //         std::cout << "Current RodModule state  " << getRod(rod)->getPrimState() << std::endl;
00868       }
00869 
00870       if(timedout) {
00871         std::cout << "Timed out at " << timeout << " seconds\n";
00872         return -200;
00873 #warning "If timeout then should try to abort primitive..."
00874       }
00875     } catch (BaseException &b) {
00876       std::cerr << "In await response " << partition << " " << crate << " " << rod << ":\n";
00877       std::cerr << "Exception: " << b << std::endl;
00878       return -6;
00879     } catch (...) {
00880       std::cerr << "Unknown exception in await response\n";
00881       return -2;
00882     }
00883 #else  // No threads
00884     // Create a buffer for test messages
00885     PrimState returnPState;
00886     TextBuffState returnTState;
00887 
00888     SctPixelRod::RodModule* rod0 = getRod(rod);
00889 
00890     try {
00891       int exceptCount = 0;
00892       do {
00893         // If there's an exception here its probably OK to try again a bit later
00894         try {
00895           returnPState = rod0->primHandler();
00896           returnTState = rod0->textHandler();
00897           exceptCount = 0;
00898 
00899           while (returnTState == TEXT_RQ_SET) {
00900             doTextBuffer(*rod0);
00901             // textState is cleared to TEXT_IDLE
00902             // Check there isn't another text buffer
00903             returnTState = rod0->textHandler();
00904           }
00905 
00906           if((time(0) - start_time) > timeout) {
00907             timedout = true;
00908             std::cout << "Timeout from wait execute\n";
00909           }
00910         } catch(VmeException &e) {
00911           exceptCount ++;
00912           if(exceptCount < 2) {
00913             std::cout << "Caught an exception, trying ignoring\n";
00914             rod0->sleep(100);
00915           } else {
00916             std::cout << " Repeat of exception, throwing anyway\n";
00917             throw;
00918           }
00919         }
00920       } while ((returnPState != PRIM_EXECUTING) && (!timedout));
00921       do {
00922         returnPState = rod0->primHandler();
00923 
00924         if((time(0) - start_time) > timeout) {
00925           timedout = true;
00926           std::cout << "Timeout from wait finish\n";
00927         }
00928       } while ((returnPState != PRIM_WAITING)&&(returnPState != PRIM_IDLE) &&(!timedout));
00929 
00930       if(timedout) {
00931         std::cout << "Timed out at " << timeout << " seconds\n";
00932         return -200;
00933 #warning "If timeout then should try to abort primitive..."
00934       }
00935     } catch (PrimListException &p) {
00936       std::cerr << "In await response " << partition << " " << crate << " " << rod << ":\n";
00937       std::cerr << "Exception sending primlist:\n";
00938       std::cerr << p.getDescriptor() << " " << p.getData1() << ", " << p.getData2() << std::endl;
00939       return -6;
00940     } catch (HpiException &h) {    
00941       std::cerr << "In await response " << partition << " " << crate << " " << rod << ":\n";
00942       std::cerr << "HpiException:\n";
00943       std::hex(std::cerr);
00944       std::cerr << h.getDescriptor() << '\n';
00945       std::cerr << "calcAddr: " << h.getCalcAddr() << ", readAddr: " << 
00946         h.getReadAddr() << '\n';
00947       std::dec(std::cerr);
00948       return -5;
00949     } catch (VmeException &v) {
00950       std::cout << "VmeException in await response:\n";
00951       Utility::decodeVme(v);
00952 
00953       return -9;
00954     } catch (RodException &r) {
00955       std::cerr << "In await response " << partition << " " << crate << " " << rod << ":\n";
00956       std::cerr << "Rod Exception\n";
00957       std::cerr << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2()
00958                 << '\n';
00959       return -4;
00960     } catch (NoImageFile &f) {
00961       std::cerr << "In await response " << partition << " " << crate << " " << rod << ":\n";
00962       std::cerr << "No image file exception " << f.getFileName() << std::endl;
00963       return -3;
00964     } catch (...) {
00965       std::cerr << "Unknown exception in await response\n";
00966       return -2;
00967     }
00968     //    std::cout << "Status at end of awaitResponse: " << *rod0;
00969 #endif
00970   } else {
00971     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
00972 
00973     return -1;
00974   }
00975 
00976   return 0;
00977 }
00978 
00979 /*
00980   Await response from all RODs within this crate
00981 */
00982 int CrateImpl::awaitResponseAll(int timeout) {
00983   int result = 0;
00984   for(RodMap::const_iterator item = rodMap.begin();
00985       item != rodMap.end();
00986       item++) {
00987     int rod = item->first;
00988 
00989     int newResult = awaitResponse(rod, timeout);
00990     if(result == 0) result = newResult;
00991   }
00992 
00993   return 0;
00994 }
00995 
00996 /*
00997   Get the last response from a ROD within this crate
00998 */
00999 boost::shared_ptr<RodOutList> CrateImpl::getResponse(unsigned int rod) {
01000   RodOutList *result = 0;
01001 
01002   if(RODPresent(rod)) {
01003     // This doesn't actually talk to the ROD just copies memory...
01004     RodOutList *response = getRod(rod)->getOutList();
01005 
01006     if(response) {
01007       result = new RodOutList(response->getLength());
01008 
01009       unsigned long *oldBody = response->getBody();
01010       unsigned long *newBody = result->getBody();
01011 
01012       for(int i=0; i<result->getLength(); i++) {
01013         newBody[i] = oldBody[i];
01014       }
01015 
01016       getRod(rod)->deleteOutList();
01017     } else {
01018       std::cout << "**** No response found when expected\n";
01019       result = 0;
01020     }
01021   } else {
01022     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01023     result = 0;
01024   }
01025 
01026   return boost::shared_ptr<RodOutList>(result);
01027 }
01028 
01029 void CrateImpl::setMrsStream(MRSStream *stream) 
01030 {
01031   std::cerr << "Crate " << partition << ", " << crate << " using mrs server\n";
01032   mrs = stream;
01033 }
01034 
01035 /*
01036   Read the message buffer if there is anything there
01037 */
01038 bool CrateImpl::getRodMessage(unsigned int rod, char *buffer, unsigned long &length) {
01039   bool complete = true;
01040 
01041   char myBuffer[TEXT_BUFF_SIZE];
01042   long myLength;
01043 
01044   TEXT_BUFFER_TYPE dummy;
01045   if(RODPresent(rod)) {
01046     if(getRod(rod)->textHandler() == TEXT_READOUT) {
01047       getRod(rod)->getTextBuffer(myBuffer, myLength, dummy);
01048       getRod(rod)->clearTextBuffer();
01049 
01050       // Copy across what's allowed
01051       for(unsigned int i=0; i<length || i<(unsigned long)myLength; i++) {
01052         buffer[i] = myBuffer[i];
01053       }
01054 
01055       if(length < (unsigned long)myLength) {
01056         complete = false;
01057       } else {
01058         length = myLength;
01059       }
01060     } else {
01061       buffer[0] = '\0';
01062       length = 0;
01063       complete = false;
01064     }
01065   }
01066 
01067   return complete;
01068 }
01069 
01070 /*
01071   Write a block of master dsp memory 
01072 */
01073 int CrateImpl::mdspBlockWrite(unsigned int rod, long dspStart, unsigned long* buffer, unsigned long numWords) {
01074   if(RODPresent(rod)) {
01075     try {
01076       getRod(rod)->mdspBlockWrite(dspStart, buffer, numWords);
01077     } catch(BaseException &b) {
01078       std::cout << "Exception writing mdsp\n";
01079       std::cout << b;
01080       return -3;
01081     } catch(...) {
01082       std::cout << "Exception writing mdsp\n";
01083       return -2;
01084     }
01085   } else {
01086     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01087     return -1;
01088   }
01089 
01090   return 0;
01091 }
01092 
01093 /*
01094   Read a block of master dsp memory 
01095 */
01096 int CrateImpl::mdspBlockRead(unsigned int rod, long dspStart, unsigned long* buffer, unsigned long numWords) {
01097   if(RODPresent(rod)) {
01098     try {
01099 //       std::cout << "Calling RodModule::mdspBlockRead(0x" << std::hex << dspStart << ", " << buffer << ", " << std::dec << numWords << ");\n";
01100       getRod(rod)->mdspBlockRead(dspStart, buffer, numWords);
01101     } catch(BaseException &b) {
01102       std::cout << "Exception reading mdsp\n";
01103       std::cout << b;
01104       std::cout << "0x" << std::hex << dspStart << ", " << std::dec << numWords << std::endl;
01105       return -3;
01106     } catch(...) {
01107       std::cout << "Unknown exception reading mdsp\n";
01108       std::cout << "0x" << std::hex << dspStart << ", " << std::dec << numWords << std::endl;
01109       return -2;
01110     }
01111   } else {
01112     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01113     return -1;
01114   }
01115 
01116   return 0;
01117 }
01118 
01119 /*
01120   Read a block of slave dsp memory 
01121 */
01122 int CrateImpl::slvBlockWrite(unsigned int rod, long dspStart, unsigned long* buffer, unsigned long numWords, long dspNumber) {
01123   if(RODPresent(rod)) {
01124     try {
01125       getRod(rod)->slvBlockWrite(dspStart, buffer, numWords, dspNumber);
01126     } catch(BaseException &b) {
01127       std::cout << "Exception writing to slave\n";
01128       std::cout << b;
01129       return -3;
01130     } catch(...) {
01131       std::cout << "Exception writing to slave\n";
01132       return -2;
01133     }
01134   } else {
01135     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01136     return -1;
01137   }
01138   return -0;
01139 }
01140 
01141 /*
01142   Read a block of slave dsp memory 
01143 */
01144 int CrateImpl::slvBlockRead(unsigned int rod, long dspStart, unsigned long* buffer, unsigned long numWords, long dspNumber) {
01145   if(RODPresent(rod)) {
01146     try {
01147       RodModule &r = *getRod(rod);
01148 #warning "Get lock so nobody else comes in and does something"
01149       unsigned long val = r.readRodStatusReg(2);
01150       // Turn off mdsp polling of that slave
01151       r.mdspSingleWrite(STATUS_REG[2], val & (~(1<<dspNumber)));
01152       r.slvBlockRead(dspStart, buffer, numWords, dspNumber);
01153       r.mdspSingleWrite(STATUS_REG[2], val);
01154     } catch(BaseException &b) {
01155       std::cout << "Exception reading slave\n";
01156       std::cout << b;
01157       return -3;
01158     } catch(...) {
01159       std::cout << "Exception reading slave\n";
01160       return -2;
01161     }
01162   } else {
01163     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01164     return -1;
01165   }
01166   return 0;
01167 }
01168 
01169 unsigned long CrateImpl::readRodStatusReg(unsigned int rod, long regNumber) {
01170   unsigned long result = 0;
01171 
01172   if(RODPresent(rod)) {
01173     try {
01174       result = getRod(rod)->readRodStatusReg(regNumber);
01175     } catch(BaseException &b) {
01176       std::cout << "Exception reading rod status\n";
01177       std::cout << b;
01178     } catch(...) {
01179       std::cout << "Exception reading rod status\n";
01180     }
01181   } else {
01182     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01183   }
01184   return result;
01185 }
01186 
01187 unsigned long CrateImpl::readRodCommandReg(unsigned int rod, long regNumber) {
01188   unsigned long result = 0;
01189 
01190   if(RODPresent(rod)) {
01191     try {
01192       result = getRod(rod)->readRodCommandReg(regNumber);
01193     } catch(BaseException &b) {
01194       std::cout << "Exception reading rod command\n";
01195       std::cout << b;
01196     } catch(...) {
01197       std::cout << "Exception reading rod command\n";
01198     }
01199   } else {
01200     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01201   }
01202   return result;
01203 }
01204 
01205 unsigned long CrateImpl::dspSingleRead(unsigned int rod, const unsigned long dspAddr, long dspNumber) {
01206   unsigned long result = 0;
01207 
01208   if(RODPresent(rod)) {
01209     try {
01210       if(dspNumber == -1) {
01211         result = getRod(rod)->mdspSingleRead(dspAddr);
01212       } else {
01213         result = getRod(rod)->slvSingleRead(dspAddr, dspNumber);
01214       } 
01215     } catch(BaseException &b) {
01216       std::cout << "Exception dsp single read\n";
01217       std::cout << b;
01218     } catch(...) {
01219       std::cout << "Exception dsp single read\n";
01220     }
01221   } else {
01222     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01223   }
01224   return result;
01225 }
01226 
01227 int CrateImpl::dspSingleWrite(unsigned int rod, unsigned long dspAddr, unsigned long buffer, long dspNumber) {
01228   if(RODPresent(rod)) {
01229     try {
01230       if(dspNumber == -1) {
01231         getRod(rod)->mdspSingleWrite(dspAddr, buffer);
01232       } else {
01233         getRod(rod)->slvSingleWrite(dspAddr, buffer, dspNumber);
01234       }
01235     } catch(BaseException &b) {
01236       std::cout << "Exception dsp single write\n";
01237       std::cout << b;
01238     } catch(...) {
01239       std::cout << "Exception dsp single write\n";
01240       return -2;
01241     }
01242   } else {
01243     std::cout << "Request for non-existent ROD " << partition << " " << crate << " " << rod << std::endl;
01244     return -1;
01245   }
01246 
01247   return 0;
01248 }
01249 
01250 void CrateImpl::status() {
01251   std::cout << "TIM status\n";
01252   if(tim) 
01253     tim->status();
01254   std::cout << std::endl;
01255 
01256   if(rodMap.size() == 0) {
01257     if(mrs) {
01258       *mrs << "CRATE_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01259            << MRS_PARAM<int>("partition", partition) << MRS_PARAM<int>("crate", crate) 
01260            << MRS_TEXT("No RODs loaded") << ENDM;
01261     }
01262   }
01263 
01264   for(RodMap::const_iterator item = rodMap.begin();
01265       item != rodMap.end();
01266       item++) {
01267     RodModule &rod = *(item->second.second);
01268 
01269     try {
01270       //       SctConfiguration::RodConfig rodConf = config->getRodConfig(partition, crate, item->first);
01271       //       if(rodConf.bocPresent) {
01272       std::cout << "BOC status\n";
01273       if(rod.getBocCard() != 0) {
01274         rod.getBocCard()->status();
01275 
01276         if(mrs) {
01277           *mrs << "BOC_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01278                << MRS_PARAM<int>("partition", partition) << MRS_PARAM<int>("crate", crate) 
01279                << MRS_PARAM<int>("slot", rod.getSlot()) 
01280                << MRS_TEXT("BOC loaded") << ENDM;
01281         }
01282       } else {
01283         std::cout << "*********** No BOC status (BOC not present!!!!)\n";
01284       }
01285     } catch(ConfigurationException &c) {
01286       std::cout << "Request for status on unconfigured ROD! (impossible)\n";
01287       return;
01288     }
01289 
01290     if(mrs) {
01291       *mrs << "ROD_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01292            << MRS_PARAM<int>("partition", partition) << MRS_PARAM<int>("crate", crate) 
01293            << MRS_PARAM<int>("slot", rod.getSlot()) 
01294            << MRS_TEXT("ROD loaded") << ENDM;
01295     }
01296 
01297     std::cout << "ROD status\n";
01298     rod.status();
01299 
01300     if(rod.readRodStatusBit(0, SR_RUNNING)) {
01301       std::cout << "Running ";
01302     }
01303     if(rod.readRodStatusBit(0, SR_BUSY)) {
01304       std::cout << "Busy ";
01305     }
01306     if(rod.readRodStatusBit(0, SR_PAUSED)) {
01307       std::cout << "Paused ";
01308     }
01309     if(rod.readRodStatusBit(0, SR_OUT_LIST_RDY)) {
01310       std::cout << "Out list ready ";
01311     }
01312     if(rod.readRodStatusBit(0, SR_EXECUTING)) {
01313       std::cout << "Executing \n";
01314       unsigned long sr2 = rod.readRodStatusReg(1);
01315 
01316       std::cout << "Current Primitive index = " << ((sr2 & 0xfffff0) >> 4) << std::endl;
01317       std::cout << "Current List index = " << (sr2 & 0xf);
01318     }
01319 
01320     std::cout << std::endl;
01321   }
01322 }
01323 
01324 /* 
01325    Lookup the RodModule object to send instructions to.
01326    Return 0 if not found.
01327 */
01328 SctPixelRod::RodModule *CrateImpl::getRod(unsigned int rod) const {
01329   RodMap::const_iterator found;
01330 
01331   found = rodMap.find(rod);
01332   if(found == rodMap.end()) return 0;
01333   else return found->second.second;
01334 }
01335 
01336 const RodStatus &CrateImpl::getRodData(unsigned int rod) const {
01337   RodMap::const_iterator found;
01338 
01339   found = rodMap.find(rod);
01340   if(found == rodMap.end()) {
01341 //     std::cerr << "AJB ERROR Hello world" 
01342 //               <<  __FILE__ << ":" <<__LINE__ << std::endl;
01343     std::cerr << " getRodData called on missing ROD " << rod << std::endl;
01344     throw CrateException("Asked for data on non-existant ROD (const)");
01345   }
01346   else return *(found->second.first);
01347 }
01348 
01349 RodStatus &CrateImpl::getRodData(unsigned int rod) {
01350   RodMap::const_iterator found;
01351 
01352   found = rodMap.find(rod);
01353   if(found == rodMap.end()) {
01354 //     std::cerr << "AJB ERROR Hello world" 
01355 //               <<  __FILE__ << ":" <<__LINE__ << std::endl;
01356     std::cerr << " getRodData (const) called on missing ROD " << rod << std::endl;
01357     throw CrateException("Asked for data on non-existant ROD");
01358   }
01359   else return *(found->second.first);
01360 }
01361 
01362 void CrateImpl::doTextBuffer(SctPixelRod::RodModule &rod) {
01363   TEXT_BUFFER_TYPE myTextType;
01364   TextBuffState returnTState;
01365 
01366   std::cout << "Got some text: crate: " << crate << " rod slot: " << rod.getSlot() << "\n";
01367   do {
01368     returnTState = rod.textHandler();
01369   } while (returnTState != TEXT_READOUT);
01370 
01371   const int maxMessagesIWantToSee=20;
01372   const bool showMeSomeMessagesIfPossible=true;
01373 
01374   static int numberOfMessagesIHaveSeen=0;
01375 
01376   
01377   if (showMeSomeMessagesIfPossible) {
01378     const int moderateSizedIntegerMuchBiggerThanOne=10;
01379     if (numberOfMessagesIHaveSeen<maxMessagesIWantToSee+moderateSizedIntegerMuchBiggerThanOne) {
01380       // we don't want to bother incrementing after we have exceeded maxMessagesIWantToSee messages, and can also avoid loop-back problems at the same time.
01381       ++numberOfMessagesIHaveSeen;
01382     };  
01383   };
01384 
01385   const int showMeSomeMessagesNOW = showMeSomeMessagesIfPossible&&(numberOfMessagesIHaveSeen<=maxMessagesIWantToSee);
01386 
01387   const bool textToMrs=((bool)mrs && showMeSomeMessagesNOW);
01388   if(textToMrs) {
01389     *mrs << "TEXTBUFF_ARRIVE" << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI")
01390          << MRS_PARAM<int>("partition", partition)
01391          << MRS_PARAM<int>("crate", crate)
01392          << MRS_PARAM<int>("rodSlot", rod.getSlot());
01393   }
01394 
01395   char * myTextBuffer = new char[TEXT_BUFF_SIZE];
01396   long myTextLength;
01397 
01398   rod.getTextBuffer(myTextBuffer, myTextLength, myTextType);
01399   rod.clearTextBuffer();
01400 
01401   std::string type;
01402   switch(myTextType) {
01403   case TEXT_ERR: type = "ERROR"; break;
01404   case TEXT_INFO: type = "INFO"; break;
01405   case TEXT_DIAG: type = "DIAG"; break;
01406   case TEXT_XFER: type = "TRANSFER"; break;
01407   case TEXT_UNDEF: type = "**Undefined**"; break;
01408   }
01409 
01410   std::cout << "Text " << type << " : " << myTextLength << std::endl;
01411   if(textToMrs) {
01412     *mrs << MRS_PARAM<const char *>("Type", type.c_str());
01413   }
01414 
01415   if(myTextLength != 32768) {
01416     std::ostringstream message;    
01417     std::ostringstream short_message;
01418     for (int i=0; i<myTextLength; i++) {
01419       message << myTextBuffer[i];
01420       if (myTextBuffer[i]!='\n' && i<100) short_message << myTextBuffer[i];
01421     }
01422     std::cout << message.str();
01423     myTextBuffer[myTextLength] = 0;
01424     if(textToMrs) {
01425       *mrs << MRS_TEXT(short_message.str().c_str())
01426            << MRS_PARAM<const char *>("Text", myTextBuffer);
01427     }
01428   } else {
01429     std::cout << "Buffersize suspiciously precisely 32768...\n";
01430     if(textToMrs) {
01431       *mrs << MRS_TEXT("Buffersize suspiciously precisely 32768...");
01432     }
01433 
01434     if (false) {
01435       std::string fileName = Sct::SctNames::getLogDir() + "/SctApi32k" + type + "BufferDump.txt";
01436       std::ofstream outFile(fileName.c_str(), std::ios::binary | std::ios::app);
01437       time_t currTime = time(0);
01438       outFile << "Rod: " << rod.getSerialNumber() << " Time: " << ctime(&currTime) << std::endl;
01439       outFile.write(myTextBuffer, myTextLength);
01440       outFile << "\nEnd of dump\n";
01441     }
01442   }
01443 
01444   std::cout << std::endl;
01445 
01446 #warning "This should use debug level instead, but that's in SctApi not Crate!"
01447 #ifdef DEBUG
01448   std::ofstream outFile((type + "BufferDump.txt").c_str(), std::ios::binary | std::ios::app);
01449   outFile << "\nBuffer block length " << myTextLength << " rod " << rod.getSerialNumber() << std::endl;
01450   time_t currTime = time(0);
01451   outFile << "Time " << ctime(&currTime);
01452   outFile.write(myTextBuffer, myTextLength);
01453 #endif
01454 
01455   if(textToMrs) {
01456     *mrs << ENDM;
01457   }
01458 
01459   delete [] myTextBuffer;
01460 }
01461 
01462 void CrateImpl::printBOCSetup(unsigned int rod) {
01463   if(RODPresent(rod)) {
01464     if(getRod(rod)->getBocCard() == 0) {
01465       std::cerr << " printBOCSetup called on missing BOC " << rod << std::endl;
01466       throw CrateException("No BOC for print setup");
01467     }
01468 
01469     BocCard &bocCard = *(getRod(rod)->getBocCard());
01470 
01471     std::cout.fill('0');
01472     for(int c=0; c<48; c++) {
01473       std::cout << "Channel ";
01474       std::cout.width(2);
01475       std::cout << c << ":  I 0x";
01476       std::cout << std::hex;
01477       std::cout.width(2);
01478       std::cout << bocCard.getLaserCurrent(c) << " Delay 0x";
01479       std::cout.width(2);
01480       std::cout << bocCard.getBpmFineDelay(c) << "/0x";
01481       std::cout.width(2);
01482       std::cout << bocCard.getBpmCoarseDelay(c)
01483                 << " M/S 0x";
01484       std::cout.width(2);
01485       std::cout << bocCard.getBpmMarkSpace(c);
01486       std::cout << "  Input 0: Th 0x";
01487       std::cout.width(2);
01488       std::cout << bocCard.getRxThreshold(c*2) << " Delay 0x";
01489       std::cout.width(2);
01490       std::cout << bocCard.getRxDataDelay(c*2)
01491                 << "  Input 1: Th 0x";
01492       std::cout.width(2);
01493       std::cout << bocCard.getRxThreshold(c*2+1) << " Delay 0x";
01494       std::cout.width(2);
01495       std::cout << bocCard.getRxDataDelay(c*2+1)
01496                 << std::endl;
01497     }
01498     std::cout.fill(' ');
01499     std::cout << std::dec;
01500   }
01501 }
01502 
01503 std::vector<SctConfiguration::BOCChannelConfig> CrateImpl::currentBOCSetup(unsigned int rod) {
01504   std::vector<SctConfiguration::BOCChannelConfig> result;
01505 
01506   if(RODPresent(rod)) {
01507     if(getRod(rod)->getBocCard() == 0) {
01508       std::cerr << " currentBOCSetup called on missing BOC " << rod << std::endl;
01509       throw CrateException("No BOC to get setup from");
01510     }
01511 
01512     BocCard &bocCard = *(getRod(rod)->getBocCard());
01513 
01514     for(int c=0; c<48; c++) {
01515       SctConfiguration::BOCChannelConfig chan;
01516 
01517       chan.current = bocCard.getLaserCurrent(c);
01518       chan.delay =  (bocCard.getBpmCoarseDelay(c) << 8) + bocCard.getBpmFineDelay(c);
01519       chan.markSpace = bocCard.getBpmMarkSpace(c);
01520       chan.threshold0 = bocCard.getRxThreshold(c*2);
01521       chan.delay0 = bocCard.getRxDataDelay(c*2);
01522       chan.threshold1 = bocCard.getRxThreshold(c*2+1);
01523       chan.delay1 = bocCard.getRxDataDelay(c*2+1);
01524 
01525       result.push_back(chan);
01526     }
01527   }
01528 
01529   return result;
01530 }
01531 
01532 void CrateImpl::printBOCRegisters(unsigned int rod) {
01533   if(RODPresent(rod)) {
01534     if(getRod(rod)->getBocCard() == 0) {
01535       std::cerr << " printBOCRegisters called on missing BOC " << rod << std::endl;
01536       throw CrateException("No BOC for print registers");
01537     }
01538 
01539     BocCard &bocCard = *(getRod(rod)->getBocCard());
01540 
01541     std::cout << std::hex;
01542 
01543     std::cout << "BOC register dump\n";
01544 
01545     std::cout << "Clock control  0x" << bocCard.getClockControl() << std::endl;
01546     std::cout << "RX data mode   0x" << bocCard.getRxDataMode() << std::endl;
01547     std::cout << "RX DAC clear   0x" << bocCard.getRxDacClear() << std::endl;
01548     std::cout << "TX DAC clear   0x" << bocCard.getTxDacClear() << std::endl;
01549     std::cout << "Vernier fine   0x" << bocCard.getVernierFinePhase() << std::endl;
01550     std::cout << "Vernier clk 0  0x" << bocCard.getVernierClockPhase0() << std::endl;
01551     std::cout << "Vernier clk 1  0x" << bocCard.getVernierClockPhase1() << std::endl;
01552     std::cout << "BPM clk phase  0x" << bocCard.getBpmClockPhase() << std::endl;
01553     std::cout << "BReg clk phase 0x" << bocCard.getBregClockPhase() << std::endl;
01554     std::cout << "BOC reset      0x" << bocCard.getBocReset() << std::endl;
01555     std::cout << "BPM reset      0x" << bocCard.getBpmReset() << std::endl;
01556     std::cout << "BOC status     0x" << bocCard.getBocStatusRegister() << std::endl;
01557 
01558     std::cout << std::dec;
01559   } else {
01560     std::cout << "No ROD found\n";
01561   }
01562 }
01563 
01564 SctConfiguration::BOCGlobalConfig CrateImpl::currentBOCRegisters(unsigned int rod) {
01565   BOCGlobalConfig result;
01566 
01567   if(RODPresent(rod)) {
01568     if(getRod(rod)->getBocCard() == 0) {
01569       std::cerr << " currentBOCRegisters called on missing BOC " << rod << std::endl;
01570       throw CrateException("No BOC for current registers");
01571     }
01572 
01573     BocCard &bocCard = *(getRod(rod)->getBocCard());
01574 
01575     result.validMask = 0x1ff;
01576     result.clockControl = bocCard.getClockControl();
01577     result.rxDataMode = bocCard.getRxDataMode();
01578     result.rxDacClear = bocCard.getRxDacClear();
01579     result.txDacClear = bocCard.getTxDacClear();
01580     result.vernierFinePhase = bocCard.getVernierFinePhase();
01581     result.vernierClockPhase0 = bocCard.getVernierClockPhase0();
01582     result.vernierClockPhase1 = bocCard.getVernierClockPhase1();
01583     result.bpmClockPhase = bocCard.getBpmClockPhase();
01584     result.bregClockPhase = bocCard.getBregClockPhase();
01585 
01586     // Also getBocReset, getBpmReset and getBocStatusRegister
01587   }
01588 
01589   return result;
01590 }
01591 
01592 void CrateImpl::saveBOCSetup(unsigned int rod, BankType bank) {
01593   getRodData(rod).savedBocSetup[bank] = currentBOCSetup(rod);
01594 }
01595 
01596 void CrateImpl::saveBOCRegisters(unsigned int rod, BankType bank) {
01597   getRodData(rod).savedBocRegisters[bank].reset(new BOCGlobalConfig(currentBOCRegisters(rod)));
01598 }
01599 
01600 void CrateImpl::restoreBOCSetup(unsigned int rod, BankType bank) {
01601   BocCard *bocCard = getRod(rod)->getBocCard();
01602 
01603   std::vector<SctConfiguration::BOCChannelConfig> &setup = getRodData(rod).savedBocSetup[bank];
01604 
01605 //   char *mappings = config->getFibreMappings(partition, crate, rod);
01606 
01607   for(int channel=0;channel<48;channel++){
01608     try {
01609       BOCChannelConfig channelConfig = setup[channel];
01610 
01611       std::cout << " Restoring channel " << channel << std::endl;
01612 
01613       int txChannel = channel;
01614       int rx0Channel = channel * 2;
01615       int rx1Channel = channel * 2 + 1;
01616 
01617       // Configure clock/command output
01618       bocCard->setLaserCurrent(txChannel,   channelConfig.current);
01619       bocCard->setBpmFineDelay(txChannel,   (channelConfig.delay&0xff) );
01620       bocCard->setBpmCoarseDelay(txChannel, ((channelConfig.delay>>8)&0xff));
01621       bocCard->setBpmMarkSpace(txChannel,   channelConfig.markSpace);
01622 
01623       // Configure data reception
01624       // Don't need to check for DATA_LINK_OFF as rx?Channel is generated locally
01625       bocCard->setRxThreshold(rx0Channel, channelConfig.threshold0);
01626       bocCard->setRxDataDelay(rx0Channel, channelConfig.delay0);
01627 
01628       bocCard->setRxThreshold(rx1Channel, channelConfig.threshold1);
01629       bocCard->setRxDataDelay(rx1Channel, channelConfig.delay1);
01630     } catch(BaseException &b) {
01631       std::cout << "Exception setting channel data for BOC " << " ROD (" << rod << " channel " << channel << "): " << b << std::endl;
01632     }
01633   }
01634 }
01635 
01636 void CrateImpl::restoreBOCRegisters(unsigned int rod, BankType bank) {
01637   BocCard *bocCard = getRod(rod)->getBocCard();
01638 
01639   BOCGlobalConfig &globalConf = *getRodData(rod).savedBocRegisters[bank];
01640   for(int r=0; r<9; r++) {
01641     if(globalConf.validMask & 1<<r) {
01642       switch(r) {
01643       case 0:
01644         bocCard->setClockControl(globalConf.clockControl);
01645         break;
01646       case 1:
01647         bocCard->setRxDataMode(globalConf.rxDataMode);
01648         break;
01649       case 2:
01650         if(globalConf.rxDacClear)
01651           bocCard->clearRxDac();
01652         break;
01653       case 3:
01654         if(globalConf.txDacClear)
01655           bocCard->clearTxDac();
01656         break;
01657       case 4:
01658         bocCard->setVernierFinePhase(globalConf.vernierFinePhase);
01659         break;
01660       case 5:
01661         bocCard->setVernierClockPhase0(globalConf.vernierClockPhase0);
01662         break;
01663       case 6:
01664         bocCard->setVernierClockPhase1(globalConf.vernierClockPhase1);
01665         break;
01666       case 7:
01667         bocCard->setBpmClockPhase(globalConf.bpmClockPhase);
01668         break;
01669       case 8:
01670         bocCard->setBregClockPhase(globalConf.bregClockPhase);
01671         break;
01672       }
01673     }
01674   }
01675 }
01676 
01677 // Check that the BOC lasers are on
01678 /*
01679   status = 0xe2
01680   status = 0x82 when crate interlock not off
01681   status = 0xa0 when on board interlock not off
01682 */
01683 bool CrateImpl::checkBOCLasersOn(unsigned int rod) { 
01684   //   unsigned long status = getRod(rod)->getBocCard()->getBocStatusRegister();
01685 
01686   //   return status == 0xe2;
01687 
01688   if(RODPresent(rod)) {
01689     if(getRod(rod)->getBocCard() == 0) {
01690       return false; // Ie it won't work ... (but because the BOC's not there!...)
01691     }
01692     return getRod(rod)->getBocCard()->getInterlockStatus();
01693   } else {
01694     return false; // Ie it won't work ... (but because the ROD's not configured...)
01695   }
01696 }
01697 
01698 void CrateImpl::enterBOCClockBy2Mode(unsigned int rod) {
01699   if(RODPresent(rod)) {
01700     if(getRod(rod)->getBocCard() == 0) {
01701       std::cerr << " enterBOCClockBy2Mode called on missing BOC " << rod << std::endl;
01702       throw CrateException("No BOC for enter clock/2");
01703     }
01704 
01705     BocCard &bocCard = *(getRod(rod)->getBocCard());
01706 
01707     bocCard.setRxDataMode(1);
01708     bocCard.setClockControl(2);
01709   }
01710 }
01711 
01712 void CrateImpl::leaveBOCClockBy2Mode(unsigned int rod) {
01713   if(RODPresent(rod)) {
01714     if(getRod(rod)->getBocCard() == 0) {
01715       std::cerr << " leaveBOCClockBy2Mode called on missing BOC " << rod << std::endl;
01716       throw CrateException("No BOC for leave clock/2");
01717     }
01718 
01719     BocCard &bocCard = *(getRod(rod)->getBocCard());
01720 
01721     bocCard.setRxDataMode(0);
01722     bocCard.setClockControl(0);
01723   }
01724 }
01725 
01726 std::vector<double> CrateImpl::getBOCMonitorArray(unsigned int rod) {
01727   if(!RODPresent(rod)) {
01728     std::cerr << " getBOCMonitorArray called on missing BOC " << rod << std::endl;
01729     throw CrateException("No BOC for getBOCMonitorArray");
01730   }
01731 
01732   if(getRod(rod)->getBocCard() == 0) {
01733     std::cerr << " getBOCMonitorArray called on missing BOC " << rod << std::endl;
01734     throw CrateException("No BOC for getBOCMonitorArray");
01735   }
01736 
01737   BocCard &bocCard = *(getRod(rod)->getBocCard());
01738 
01739   std::vector<double> result;
01740 
01741   for(int i=0; i<12; i++) {
01742     result.push_back(bocCard.getMonitorAdc(i));
01743   }
01744 
01745   return result;
01746 }
01747 
01748 void CrateImpl::modifyBOCParam(unsigned int type, unsigned int val, bool raw) {
01749   for(RodMap::const_iterator ri = rodMap.begin();
01750       ri!=rodMap.end();
01751       ri++) {
01752     int rod = ri->first;
01753     BocCard &bocCard = *(getRod(rod)->getBocCard());
01754     switch(type) {
01755       // Global BOC registers
01756     case SCT_SCAN_BOC_BPM_PHASE:
01757       bocCard.setBpmClockPhase(val);
01758       break;
01759     case SCT_SCAN_BOC_BREG_PHASE:
01760       bocCard.setBregClockPhase(val);
01761       break;
01762     case SCT_SCAN_BOC_V0_PHASE:
01763       bocCard.setVernierClockPhase0(val);
01764       break;
01765     case SCT_SCAN_BOC_V1_PHASE:
01766       bocCard.setVernierClockPhase1(val);
01767       break;
01768     case SCT_SCAN_BOC_V_PHASES:
01769       bocCard.setVernierClockPhases(val);
01770       break;
01771     case SCT_SCAN_BOC_VRN_FINE:
01772       bocCard.setVernierFinePhase(val);
01773       break;
01774       // Useful scans for finding modules...
01775     case SCT_SCAN_TX_CHANNELS:
01776       setupScanTx(rod, val);
01777       break;
01778     case SCT_SCAN_RAW_TX_CHANNELS:
01779       setupScanRawTx(rod, val);
01780       break;
01781     default:
01782       // All the others are done per channel
01783       for(int channel=0; channel<48; channel++) {
01784         modifyBOCParam(rod, channel, type, val, raw);
01785       }
01786     }
01787   }
01788 }
01789 
01790 void CrateImpl::modifyBOCParam(unsigned int rod, unsigned int channel, unsigned int type, unsigned int val, bool raw) {
01791   if(RODPresent(rod)) {
01792     if(!getRod(rod)->getBocCard()) {
01793       std::cerr << " modifyBOCParam called on missing BOC " << rod << std::endl;
01794       throw CrateException("No BOC for modify BOC param");
01795     }
01796 
01797     BocCard &bocCard = *(getRod(rod)->getBocCard());
01798 
01799     // Raw channels don't need look up
01800     int txFibre = channel;
01801     int rxFibre1 = channel * 2 + 0;
01802     int rxFibre2 = channel * 2 + 1;
01803 
01804     if(!raw) {
01805       unsigned char *mappings;
01806 
01807       try { 
01808         mappings = config->getFibreMappings(partition, crate, rod);
01809       }  catch(ConfigurationException &c) {
01810         std::cout << "No fibre mappings for appropriate module: \n";
01811         std::cout << c.what() << std::endl;
01812         return;
01813       }
01814 
01815       txFibre = mappings[channel * 3];
01816       rxFibre1 = mappings[channel * 3 + 1];
01817       rxFibre2 = mappings[channel * 3 + 2];
01818     }
01819 
01820     try {
01821       switch(type) {
01822       case ST_RX_DELAY0:
01823         if(rxFibre1 != DATA_LINK_OFF) bocCard.setRxDataDelay(rxFibre1, val);
01824         break;
01825       case ST_RX_DELAY1:
01826         if(rxFibre2 != DATA_LINK_OFF) bocCard.setRxDataDelay(rxFibre2, val);
01827         break;
01828       case ST_RX_DELAY:
01829         if(rxFibre1 != DATA_LINK_OFF) bocCard.setRxDataDelay(rxFibre1, val);
01830         if(rxFibre2 != DATA_LINK_OFF) bocCard.setRxDataDelay(rxFibre2, val);
01831         break;
01832 
01833       case ST_RX_THRESHOLD0:
01834         if(rxFibre1 != DATA_LINK_OFF) bocCard.setRxThreshold(rxFibre1, val);
01835         break;
01836       case ST_RX_THRESHOLD1:
01837         if(rxFibre2 != DATA_LINK_OFF) bocCard.setRxThreshold(rxFibre2, val);
01838         break;
01839       case ST_RX_THRESHOLD:
01840         if(rxFibre1 != DATA_LINK_OFF) bocCard.setRxThreshold(rxFibre1, val);
01841         if(rxFibre2 != DATA_LINK_OFF) bocCard.setRxThreshold(rxFibre2, val);
01842         break;
01843 
01844       case ST_TX_CURRENT:
01845         if(txFibre != DATA_LINK_OFF) bocCard.setLaserCurrent(txFibre, val);
01846         break;
01847       case ST_TX_MARKSPACE:
01848         if(txFibre != DATA_LINK_OFF) bocCard.setBpmMarkSpace(txFibre, val);
01849         break;
01850       case ST_TX_DELAY:
01851         if(txFibre != DATA_LINK_OFF) bocCard.setBpmCoarseDelay(txFibre, (val&0xff00) >> 8);
01852         if(txFibre != DATA_LINK_OFF) bocCard.setBpmFineDelay(txFibre, (val&0xff));
01853         break;
01854       case ST_TX_COARSE:
01855         if(txFibre != DATA_LINK_OFF) bocCard.setBpmCoarseDelay(txFibre, val);
01856         break;
01857       case ST_TX_FINE:
01858         if(txFibre != DATA_LINK_OFF) bocCard.setBpmFineDelay(txFibre, val);
01859         break;
01860 
01861         // Extra scans
01862       case SCT_SCAN_BOC_BPM_PHASE:
01863         bocCard.setBpmClockPhase(val);
01864         break;
01865       case SCT_SCAN_BOC_BREG_PHASE:
01866         bocCard.setBregClockPhase(val);
01867         break;
01868       case SCT_SCAN_BOC_V0_PHASE:
01869         bocCard.setVernierClockPhase0(val);
01870         break;
01871       case SCT_SCAN_BOC_V1_PHASE:
01872         bocCard.setVernierClockPhase1(val);
01873         break;
01874       case SCT_SCAN_BOC_V_PHASES:
01875         bocCard.setVernierClockPhases(val);
01876         break;
01877       case SCT_SCAN_BOC_VRN_FINE:
01878         bocCard.setVernierFinePhase(val);
01879         break;
01880 
01881         // Useful scans for finding modules...
01882       case SCT_SCAN_TX_CHANNELS:
01883         setupScanTx(rod, val);
01884         break;
01885 
01886       case SCT_SCAN_RAW_TX_CHANNELS:
01887         setupScanRawTx(rod, val);
01888         break;
01889 
01890       default:
01891         break;
01892       }
01893     } catch(BocException &b) {
01894       std::cout << "BocException in modifyBOCParam: " << b << std::endl;
01895       throw CrateException("BOCException in modify");
01896     }
01897   }
01898 }
01899 
01900 void CrateImpl::lasersOff() {
01901   for(RodMap::const_iterator ri = rodMap.begin();
01902       ri!=rodMap.end();
01903       ri++) {
01904     if(ri->second.second->getBocCard() == 0) {
01905       std::cerr << " Missing BOC in lasersOff\n";
01906       continue;
01907 //       throw CrateException("No BOC for lasers off");
01908     }
01909 
01910     BocCard &bocCard = *(ri->second.second->getBocCard());
01911 
01912     for(int i=0; i<48; i++) {
01913       bocCard.setLaserCurrent(i, 0);
01914     }
01915   }
01916 }
01917 
01918 void CrateImpl::timSetFrequency(double trigFreq, double rstFreq) {
01919   if(tim) {
01920     std::cout << "Setting TIM frequencies: " << trigFreq << "kHz " << rstFreq << "Hz\n";
01921     int highBits;
01922 
01923     // std:: needed because of ROOT (I think)
01924     int power = (int)std::ceil(std::log10(trigFreq/8.0));
01925     std::cout << "trigPower " << power << std::endl;
01926     double trigBase;
01927     switch(power) {
01928     case 2: highBits = 0; trigBase = trigFreq / 10; break;
01929     case 1: highBits = 1; trigBase = trigFreq / 1; break;
01930     case 0: highBits = 2; trigBase = trigFreq / 0.1; break;
01931     case -1: highBits = 3; trigBase = trigFreq / 0.01; break;
01932     default:
01933       if(power<-1) { highBits = 3; trigBase = trigFreq / 0.01; }
01934       else { highBits = 0; trigBase = trigFreq / 10; }
01935     }
01936 
01937     std::cout << "trigBase " << trigBase << std::endl;
01938     int lowBits =  static_cast<int>(60.0 / trigBase);
01939 
01940     if(lowBits == 1) lowBits = 0;
01941     if(lowBits == 10) lowBits = 1;
01942     if(lowBits > 6) lowBits = 7;
01943 
01944     int trigNibble = (lowBits & 0x7) + ((highBits & 0xf) << 3);
01945     std::cout << "trigNibble " << trigNibble << " (" << lowBits << ", " << highBits << ")\n";
01946 
01947     // Decode reset frequency
01948 
01949 
01950     // std:: needed because of ROOT (I think)
01951     power = (int)std::ceil(std::log10(rstFreq/8.0));
01952     std::cout << "rstPower " << power << std::endl;
01953     double rstBase;
01954     switch(power) {
01955     case 2: highBits = 0; rstBase = rstFreq / 100; break;
01956     case 1: highBits = 1; rstBase = rstFreq / 10; break;
01957     case 0: highBits = 2; rstBase = rstFreq / 1; break;
01958     case -1: highBits = 3; rstBase = rstFreq / 0.1; break;
01959     default:
01960       if(power<-1) { highBits = 3; rstBase = rstFreq / 0.1; }
01961       else { highBits = 0; rstBase = rstFreq / 100; }
01962     }
01963 
01964     std::cout << "rstBase " << rstBase << std::endl;
01965 
01966     lowBits =  (int)(6.0 / rstBase);
01967 
01968     if(lowBits == 1) lowBits = 0;
01969     if(lowBits == 10) lowBits = 1;
01970     if(lowBits > 6) lowBits = 7;
01971 
01972     int rstNibble = (lowBits & 0x7) + ((highBits & 0xf) << 3);
01973     std::cout << "rstNibble " << rstNibble << " (" << lowBits << ", " << highBits << ")\n";
01974 
01975     tim->regLoad(TIM_REG_FREQUENCY, trigNibble + (rstNibble << 8));
01976   }
01977 }
01978 
01979 void CrateImpl::freeTriggers() {
01980   if(tim) {
01981     // Enable L1As
01982     tim->loadBitSet(TIM_REG_ENABLES, SctPixelRod::TIM_BIT_EN_INT_TRIG);
01983   }
01984 }
01985 
01986 void CrateImpl::stopTriggers() {
01987   if(tim)
01988     tim->intTrigStop();
01989 }
01990 
01991 void CrateImpl::timL1A() {
01992   if(tim) {
01993     tim->issueCommand(SctPixelRod::TIM_VTRG);
01994     usleep(1);
01995     tim->loadBitClear(TIM_REG_COMMAND, SctPixelRod::TIM_VTRG);
01996   }
01997 }
01998 
01999 void CrateImpl::timCalL1A(int delay) {
02000   if(tim)
02001     tim->issueVCAL(delay);
02002 }
02003 
02004 
02005 void CrateImpl::timECR() {
02006   if(tim) {
02007     tim->issueCommand(SctPixelRod::TIM_VECR);
02008     // Manually send TIM ECR
02009     //     tapi.timRegLoad(0, 0, 2, 0x04); 
02010     timRegLoad(2, 0x0);
02011   }
02012 }
02013 
02014 void CrateImpl::timBCR() {
02015   if(tim) {
02016     tim->issueCommand(SctPixelRod::TIM_VBCR);
02017     // Manually send TIM BCR
02018     //    tapi.timRegLoad(0, 0, 2, 0x08); 
02019     timRegLoad(2, 0x0);
02020   }
02021 }
02022 
02023 void CrateImpl::timFER() {
02024   if(tim) {
02025     tim->issueCommand(SctPixelRod::TIM_VFER);
02026     // Manually send TIM FER
02027     // tapi.timRegLoad(0, 0, 2, 0x20); 
02028     timRegLoad(2, 0x0);
02029   }
02030 }
02031 
02032 void CrateImpl::sendTimBurst(int count) {
02033   if(tim) {
02034     // Load count
02035     tim->regLoad(TIM_REG_BURST_COUNT, count);
02036     // Enable burst mode
02037     tim->loadBitSet(TIM_REG_COMMAND, 0x200);
02038 
02039     // Use single L1A
02040     tim->loadBitSet(TIM_REG_ENABLES, SctPixelRod::TIM_BIT_EN_INT_TRIG);
02041 
02042     // Start burst
02043     tim->loadBitSet(TIM_REG_COMMAND, 0x400);
02044 
02045 //     std::cout << "Status is " << std::hex << tim->regFetch(TIM_REG_STATUS) << std::dec << std::endl;
02046 
02047     // Wait for burst to finish
02048     while(tim->regFetch(TIM_REG_STATUS) & 0x10)
02049       ;
02050 
02051 //     std::cout << "Status now " << std::hex << tim->regFetch(TIM_REG_STATUS) << std::dec << std::endl;
02052 
02053     // Stop burst
02054     tim->loadBitClear(TIM_REG_COMMAND, 0x400);
02055 
02056     // Stop triggers before leaving burst mode
02057     tim->loadBitClear(TIM_REG_ENABLES, SctPixelRod::TIM_BIT_EN_INT_TRIG);
02058 
02059     // Disable burst mode
02060     tim->loadBitClear(TIM_REG_COMMAND, 0x200);
02061   }
02062 }
02063 
02064 void CrateImpl::timVerbose() {
02065   for(int r = 0; r<0x34; r+=2) {
02066     std::cout.width(2);
02067     std::cout << std::hex << r << std::dec 
02068               << ": 0x" << std::hex << tim->regFetch((SctPixelRod::TimRegister)r) << std::dec << std::endl;
02069   }
02070 }
02071 
02072 void CrateImpl::timRegLoad(int reg, UINT16 val) {
02073   if(tim) {
02074     tim->regLoad(SctPixelRod::TimRegister(reg), val);
02075   }
02076 }
02077 
02078 UINT16 CrateImpl::timRegRead(int reg) {
02079   if(tim) {
02080     return tim->regFetch(SctPixelRod::TimRegister(reg));
02081   } else {
02082     return 0;
02083   }
02084 }
02085 
02086 bool CrateImpl::slavePresent(int rod, int index) const {
02087   bool present;
02088 
02089   if(!RODPresent(rod)) 
02090     present = false;   // The ROD's not present so the slave definitely isn't!
02091   else {
02092     present = (getRodData(rod).slaves & (1<<index))?true:false;
02093   }
02094 
02095   return present;
02096 }
02097 
02098 void CrateImpl::slaveStarted(int rod, int slave){
02099   getRodData(rod).slaves |= 1<<slave;
02100 }
02101 
02102 bool CrateImpl::RODPresent(int rod) const {
02103   return getRod(rod);
02104 }
02105 
02106 long CrateImpl::getRodSlot(int rod) const {
02107   return getRod(rod)->getSlot();
02108 }
02109 
02110 int CrateImpl::getRodRevision(int rod) const {
02111   return getRod(rod)->getRevision();
02112 }
02113 
02114 void CrateImpl::stopPolling() {
02115   m_enablePolling = false;
02116 }
02117 
02118 void CrateImpl::resumePolling() {
02119   m_enablePolling = true;
02120 }
02121 
02122 void CrateImpl::setupScanTx(unsigned int rod, unsigned int channel) {
02123   BocCard &bocCard = *(getRod(rod)->getBocCard());
02124 
02125   UINT32 iBuffer[48];
02126 
02127   unsigned char *mappings;
02128   try {
02129     mappings = config->getFibreMappings(partition, crate, rod);
02130   } catch(ConfigurationException &c) {
02131     std::cout << "No mapping data for channel this rod\n";
02132     return;
02133   }
02134 
02135   // Turn all channels off
02136   for(unsigned int ch=0;ch<48;ch++){
02137     if(ch == channel) continue;
02138     int txChannel = mappings[ch * 3 + 0];
02139     iBuffer[txChannel] = 0;
02140   }
02141 
02142   try {
02143     BOCChannelConfig channelConfig = config->getBOCConfig(partition, crate, rod, channel);
02144 
02145     int txChannel = mappings[channel * 3 + 0];
02146     iBuffer[txChannel] = channelConfig.current;
02147   } catch(ConfigurationException &c) {
02148     std::cout << "No current configuration for channel " << channel << " leaving at 0\n";
02149   }
02150 
02151   // Configure clock/command outputs in one go
02152   bocCard.setLaserCurrent(0, iBuffer, 48);
02153 }
02154 
02155 void CrateImpl::setupScanRawTx(unsigned int rod, unsigned int channel) {
02156   BocCard &bocCard = *(getRod(rod)->getBocCard());
02157 
02158   UINT32 iBuffer[48];
02159 
02160   // Turn all channels off
02161   for(unsigned int ch=0;ch<48;ch++){
02162     // Except the current channel...
02163     if(ch == channel) {
02164 #warning "This shouldn't be a constant current! (where should it come from though? Configuration may not be right...)"
02165       iBuffer[ch] = 0x90;
02166     } else {
02167       iBuffer[ch] = 0; 
02168     }
02169   }
02170 
02171   // Configure clock/command output
02172   bocCard.setLaserCurrent(0, iBuffer, 48);
02173 }
02174 
02175 } // End of namespace SctApi

Generated on Fri Sep 16 18:01:50 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5