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

Generated on Mon Feb 6 14:01:18 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6