SctApi.cxx

00001 
00008 #include <iostream>
00009 #include <stdexcept>
00010 #include <cmath>
00011 #include <cstdio>  // For tempnam (and ScanResultWriter)
00012 #include <unistd.h>
00013 
00014 #include <sys/stat.h>   // mkdir etc
00015 #include <sys/types.h>
00016 
00017 #include <boost/bind.hpp>
00018 #include <boost/format.hpp>
00019 
00020 #include "SctApi.h"
00021 #include "SctApiConsts.h"
00022 #include "SctApiDebug.h"
00023 #include "SctApiHisto.h"
00024 #include "sctConf/configRegistry.h"
00025 #include "ScanDefImpl.h" // was SctApiImpl.h
00026 #include "TriggerImpl.h" // was SctApiImpl.h
00027 #include "crateImpl.h"
00028 #include "autoConfig.h"
00029 
00030 #include "primUtils.h"
00031 #include "primListWrapper.h"
00032 #include "PrimBuilder.h"
00033 
00034 #include "extraScans.h"
00035 #include "SctApiRodInfo.h"
00036 #include "SctApiCounters.h"
00037 
00038 #include "ScanResultWriter/scan.h"
00039 #include "Sct/SctNames.h"
00040 #include "Sct/FibreNumberConverters.h"
00041 
00042 #include "registerIndices.h"
00043 
00044 #include "Sct/AbcdScans.h"
00045 #include "Sct/AbcdChip.h"
00046 
00047 #include "CommonWithDsp/primParams.h"
00048 
00049 #include "RodCrate/RodModule.h"
00050 
00051 #include "VmeDecode.h"
00052 #include "RodCrate/TimDefine.h"
00053 
00054 #include <boost/date_time/posix_time/posix_time.hpp>
00055 
00056 #ifdef USE_IS
00057 #include "Sct/IoExceptions.h"
00058 #include "ScanResultWriter/dataTypes.h"
00059 #include <is/infoT.h>
00060 #include <is/info.h>
00061 #endif
00062 
00063 #include "utility.h"
00064 #include "SctApiException.h"
00065 #include "ModuleList.h"
00066 #include "DCSAccess.h"
00067 #include "SctApiDDC.h"
00068 #include "Idiosyncrasy.h"
00069 #include "Sct/MultiMessageDebugStream.h"
00070 
00071 using namespace std;
00072 using namespace SctPixelRod;
00073 using namespace SctConfiguration;
00074 using namespace SctApi::Utility;
00075 using namespace boost::posix_time;
00076 using boost::shared_ptr;
00077 using SctApi::ModuleList;
00078 
00079 // Some static methods
00080 static void handle_unexpected(void);
00081 
00082 namespace SctApi {
00083 
00084 const unsigned int SctApi::BAD_MODULE = 0xffffffff;
00085 
00086 /*
00087   // This version of the constructor is only called by TApi .. and so is the abnormal constructor
00088 
00089   The default constructor.
00090   This sets the unexpected handler to interpret all sorts of exceptions
00091 */
00092 SctApi::SctApi(const Idiosyncrasy & id) 
00093   : mrs(0),
00094 #if USE_IS
00095     m_isDict(), 
00096 #endif
00097     rodList(), rodInfoList(), moduleMap(), scanController(), lastScanController(),
00098     m_id(new Idiosyncrasy(id)),
00099     config(), 
00100     m_dcsAccess(new DCSAccessDummy), m_sctApiDDC(),
00101     debugPrimList(), crateObject(), 
00102     m_log(new Log(id.ucid())), lastDebugScan(), lastDebugScanEx(),
00103     scanNumber(0), runNumber(0)
00104 #if USE_SCAN_THREAD
00105     ,
00106     scanQueue_notEmpty(), scanQueue_mutex(), scanPollThread(),
00107     m_stopPolling(false), m_inScanLoop(false), m_inRawScanLoop(false),  m_initialisationThread(), m_is_initialised(false)
00108 #endif
00109 {
00110   cout << "Load configuration\n";
00111   std::string backend = "xml";
00112   SctConfiguration::FactoryManager::instance().loadPlugin(backend); 
00113   SctConfiguration::Factory &f = SctConfiguration::FactoryManager::instance().getFactory(backend);
00114   config.reset(f.defaultConfig());
00115   config->loadConfiguration("");
00116   m_sctApiDDC = boost::shared_ptr<SctApiDDC>(new SctApiDDC(config, m_log));
00117   setup();
00118 }
00119 
00121 SctApi::SctApi(const Idiosyncrasy & id, boost::shared_ptr<Configuration> newConf) 
00122   : mrs(0),
00123 #if USE_IS
00124     m_isDict(), 
00125 #endif
00126     rodList(), rodInfoList(), moduleMap(), scanController(), lastScanController(),
00127     m_id(new Idiosyncrasy(id)),
00128     config(), 
00129     m_dcsAccess(new DCSAccessDummy), m_sctApiDDC(),
00130     debugPrimList(), crateObject(), 
00131     m_log(new Log(id.ucid())), lastDebugScan(), lastDebugScanEx(),
00132     scanNumber(0), runNumber(0)
00133 #if USE_SCAN_THREAD
00134     ,
00135     scanQueue_notEmpty(), scanQueue_mutex(), scanPollThread(),
00136     m_stopPolling(false), m_inScanLoop(false), m_inRawScanLoop(false), m_initialisationThread(), m_is_initialised(false)
00137 #endif
00138 {
00139   config = newConf;
00140   m_sctApiDDC = boost::shared_ptr<SctApiDDC>(new SctApiDDC(config, m_log));
00141   setup();
00142 }
00143 
00144 /* The destructor. */
00145 SctApi::~SctApi() {
00146   {
00147     boost::mutex::scoped_lock lock(log().mutex());
00148     log() << "SctApi destructor\n";
00149     log() << "\t TIME " << second_clock::universal_time() << endl;
00150   }
00151 
00152 #if USE_SCAN_THREAD
00153   m_stopPolling = true;
00154   scanPollThread->join();
00155 #endif
00156 
00157 }
00158 
00159 bool SctApi::isInitialised(){
00160   return m_is_initialised;
00161 }
00162 
00163 SctApiConfigCache& SctApi::getModuleConfigCache(){
00164   return module_cache;
00165 }
00166 
00167 const Idiosyncrasy & SctApi::idiosyncrasy() {
00168   return *m_id;
00169 }
00170 
00171 const std::string SctApi::getHostName() const {
00172   char buffer[100];
00173   gethostname(buffer, 100);
00174   return std::string(buffer);
00175 }
00176 
00177 bool SctApi::hasFinishedScanning() {
00178   const std::string name 
00179     = this->idiosyncrasy().infoServiceNameOfScanStatusObject();
00180   
00181   const ISInfo::Status badlyTypedReturnValue 
00182     = m_isDict->contains(name);
00183 
00184   switch (badlyTypedReturnValue) {
00185   case ISInfo::NotFound:
00186     // so the IS server existed, but it doesn't contain the "scanning" remark, so probably scanning has stopped
00187     return true;
00188   case ISInfo::Success:
00189     // so the IS server existed, and it does contain the "scanning" remark, so scanning has not yet finished (it is still going on).
00190     return false;
00191   default:
00192     // Something else happened, which should worry us, because this suggests that the method is being called out of context.  Complain to the user, and do not change the state of the cache!  Most likely scanning is not taking place, so return true;
00193     {
00194       Sct::MultiMessageDebugStream m(true,false,true);
00195       m << "SctApi tried to figure out whether scanning had finished by looking for [" 
00196     << name
00197     << "] but there was a problem: an unusual ISInfo::Status (value "
00198     << badlyTypedReturnValue
00199     << ") was returned while querying IS.  Possible causes might include (but be limited to) running the sw without starting the appropriate is_servers, a software bug, or high network load causing poor CORBA connections, eg timeouts.  Making a guess that scanning is not taking place at the moment ...";
00200       m.flush();
00201     };
00202     return true;
00203   };
00204 };
00205 
00206 void SctApi::setup() 
00207 {
00208   Debug::getInstance(); // Make sure setupDebugOptions() is called early
00209 
00210   debugPrimList.reset(new PrimListWrapper);
00211 
00212   // Examine exceptions on the way to a crash...
00213   set_unexpected(handle_unexpected);
00214   cout << "Installed unexpected handler\n";
00215 
00216   {
00217     boost::mutex::scoped_lock lock(log().mutex());
00218     log() << "Initial setup complete\n";
00219   }
00220 
00221 #if USE_SCAN_THREAD
00222   scanPollThread.reset(new boost::thread(boost::bind(&SctApi::scanPollingThread, this)));
00223 #endif
00224 }
00225 
00226 void SctApi::setMrsStream(MRSStream *stream) 
00227 {
00228   mrs = stream;
00229 }
00230 
00231 #if USE_IS
00232 void SctApi::setIsDictionary()
00233 {
00234   m_isDict = 
00235     boost::shared_ptr<ISInfoDictionary>
00236     (new ISInfoDictionary(Sct::SctNames::getPartition()));
00237 }
00238 #endif
00239 
00240 // ROD Diagnostics
00241 
00242 // Read one ROD Status Register via HPI
00243 unsigned long SctApi::readRodStatusReg(unsigned int rod,
00244                                        long regNumber) {
00245   unsigned long result = 0;
00246 
00247   {
00248     boost::mutex::scoped_lock lock(log().mutex());
00249     log() << "readRodStatusReg " << regNumber << endl;
00250   }
00251 
00252   Crate *myCrate = getCrate();
00253   if(myCrate) {
00254     result = myCrate->readRodStatusReg(rod, regNumber);
00255   }
00256 
00257   return result;
00258 }
00259   
00260 // Read one ROD Command Register via HPI
00261 unsigned long SctApi::readRodCommandReg(unsigned int rod,
00262                                         long regNumber) {
00263   unsigned long result = 0;
00264 
00265   {
00266     boost::mutex::scoped_lock lock(log().mutex());
00267     log() << "readRodCommandReg\n";
00268   }
00269 
00270   Crate *myCrate = getCrate();
00271   if(myCrate) {
00272     result = myCrate->readRodCommandReg(rod, regNumber);
00273   }
00274 
00275   return result;
00276 }
00277 
00278 // Read a single 32b word from MasterDSP SDRAM via HPI
00279 unsigned long SctApi::dspSingleRead(unsigned int rod,
00280                                     const unsigned long dspAddr, long dspNumber) {
00281   unsigned long result = 0;
00282 
00283   {
00284     boost::mutex::scoped_lock lock(log().mutex());
00285     log() << "dspSingleRead 0x" << hex << dspAddr << dec << endl;
00286   }
00287   Crate *myCrate = getCrate();
00288   if(myCrate) {
00289     result = myCrate->dspSingleRead(rod, dspAddr, dspNumber);
00290   }
00291 
00292   return result;
00293 }
00294 
00295 // Write a single 32b word to MasterDSP SDRAM via HPI
00296 void SctApi::dspSingleWrite(unsigned int rod,
00297                             unsigned long dspAddr, unsigned long value, long dspNumber) {
00298   {
00299     boost::mutex::scoped_lock lock(log().mutex());
00300     log() << "dspSingleWrite 0x" << hex << dspAddr << " 0x" << value << dec << endl;
00301   }
00302   Crate *myCrate = getCrate();
00303   if(myCrate) {
00304     myCrate->dspSingleWrite(rod, dspAddr, value, dspNumber);
00305   }
00306 }
00307 
00308 ABCDModule *SctApi::lookupConfig(UINT32 mid) {
00309   {
00310     boost::mutex::scoped_lock lock(log().mutex());
00311     log() << "lookupconfig " << mid << endl;
00312   }
00313 
00314   if(moduleMap.find(mid) == moduleMap.end()) {
00315      std::cout << "AJB lookup config " << mid << " requests cache " << std::endl;
00316      cacheModuleConfig(mid);
00317   }
00318 
00319   ABCDModule *result = 0;
00320 
00321   if(moduleMap.find(mid) != moduleMap.end()) {
00322     result = &(moduleMap.find(mid)->second);
00323   }
00324 
00325   return result;
00326 }
00327 
00328 // This should be a nice and simple method, but lots of fixing up and checking goes on
00329 /*
00330   1) Given mid, find the serial number for lookup in configuration
00331   2) Check redundancy mappings and put into ROD information
00332   3) Get the module configuration from the database
00333    a) Fix up address for select
00334    b) If redundant off ROD assign OFF_ROD_TTC
00335    c) Formatters use different base for rx parameter
00336    d) Insert module group into configuration structure
00337   4) Retrieve and put into cache the module error mask
00338   5) Put configuration into moduleMap
00339   6) Report on current settings
00340  */
00341 void SctApi::cacheModuleConfig(UINT32 mid, std::string moduleName) {
00342   unsigned int partition, crate, rod, channel;
00343   getpcrc(mid, partition, crate, rod, channel);
00344 
00345   RodLabel label(partition, crate, rod);
00346 
00347   unsigned int mur, module;
00348 
00349   // First find out what this module is called
00350   try {
00351     if(checkDebugOption(DEBUG_DIAG))
00352       cout << "Looking for partition " << partition << " crate " << crate << " rod " << rod << " channel " << channel << endl;
00353     config->translateFromROD(partition, crate, rod, channel, 
00354                              mur, module);
00355 
00356     if(checkDebugOption(DEBUG_DIAG2))
00357       cout << "Found MUR " << mur << " module number " << module << endl;
00358   } catch(ConfigurationException &c) {
00359     cout << "Can't find module in MUR map: \n";
00360     cout << c.what() << endl;
00361 
00362     {
00363       boost::mutex::scoped_lock lock(log().mutex());
00364       log() << "  (Not found)\n";
00365     }
00366 
00367     throw;
00368   }
00369 
00370   if (moduleName=="") try {
00371     config->translateToSN(mur, module, moduleName);
00372 
00373     if(checkDebugOption(DEBUG_DIAG2))
00374       cout << "Found module name " << moduleName << endl;
00375     //        config->getModuleRodPosition(moduleName, partition, crate, rod, channel);
00376   } catch(ConfigurationException &c) {
00377     cout << "Module name not found: \n";
00378     cout << c.what() << endl;
00379 
00380     {
00381       boost::mutex::scoped_lock lock(log().mutex());
00382       log() << "  (Not found)\n";
00383     }
00384 
00385     throw;
00386   }
00387 
00388   // Got name, look at redundancy
00389   bool redundantOnROD = false;
00390 
00391   // If redundancy off-ROD then this is > 48
00392   unsigned int rchannel;
00393   unsigned int rpartition, rcrate, rrod;
00394 
00395   // Only valid for off-ROD redundancy
00396   unsigned long rmid;
00397 
00398   bool redundantValid;
00399 
00400   try {
00401     config->translateToRROD(mur, module, 
00402                             rpartition, rcrate, rrod, rchannel);
00403 
00404     if(partition == rpartition && crate == rcrate && rod == rrod) {
00405       redundantOnROD = true;
00406     } else {
00407       RodLabel label(partition, crate, rod);
00408       RodLabel rlabel(rpartition, rcrate, rrod);
00409 
00410       RodInfo & info(getRodInfo(label));
00411       RodInfo & rinfo(getRodInfo(rlabel));
00412       
00413       cout << "Off ROD module found for mid " << mid << " !!! rchannel was  = " << rchannel << endl;
00414 
00415       unsigned int newRchannel = 48 + rinfo.offRODTTC.size();
00416 #warning BRUCE HAS REALISED THAT SOME OF WHAT FOLLOWS EXPECTS THE UNMODIFIED VALUE OF rchannel, AND SOME OF WHAT FOLLOWS EXPECTS THE ABOE "VIRTUAL+48" rchannel SO THERE ARE ALMOST DEFINITELY BUGS IN THIS ROUTINE THAT WILL PREVENT REDUNDANT LINKS BEING HANDLED CORRECTLY! (Chris on behalf of Bruce)
00417 #warning "Bruce has had an attempt at fixing this problem, but nobody has tested it with a real system"
00418       rmid = Utility::packpcrc(rpartition, rcrate, rrod, newRchannel);
00419 
00420       info.offRODTTC[mid] = rmid;
00421       rinfo.offRODRX[rmid] = mid;
00422       cout << "    rchannel now = " << newRchannel << " rmid = " << rmid << endl;
00423     }
00424 
00425     redundantValid = true;
00426   } catch(ConfigurationException &c) {
00427     redundantValid = false;
00428     cout << "Module redundancy not found: \n";
00429     cout << c.what() << endl;
00430 
00431     {
00432       boost::mutex::scoped_lock lock(log().mutex());
00433       log() << "  (Not found)\n";
00434     }
00435 
00436     // We can live with this (as long as select not set...?)
00437   }
00438 
00439   // Got the module serial number, now get the configuration
00440   ABCDModule configuration; 
00441   try {
00442     configuration = config->getModuleConfig(moduleName);
00443 
00444     // Fix up chip address for select
00445 
00446     // Only modules with sn like 20220nn0200nnn are guaranteed to have select line connected correctly
00447     // Others like 20220nn0100nnn may not
00448 //     if(moduleName[8] == '2') {
00449       if(configuration.select) {
00450         for(int c=0; c<12; c++) {
00451           configuration.chip[c].address |= 0x10;
00452         }
00453     configuration.mid=rmid; // Added AJB 19/4/2005 - is this right?
00454       } else {
00455        for(int c=0; c<12; c++) {
00456           configuration.chip[c].address &= ~0x10;
00457         }
00458     configuration.mid=mid; // Added AJB 19/4/2005
00459       } 
00460       // } // Otherwise select line on module might be hard-wired
00461 
00462     RodInfo & info(getRodInfo(label));
00463     // Fix up for off ROD redundancy
00464     {
00465       boost::recursive_mutex::scoped_lock lock(rodInfoListAccess);
00466       
00467       if (!info.fibreMappings.get()) {
00468     std::cout << "getting fibre mappings for rod " << rod << std::endl;
00469     info.fibreMappings.reset(config->getFibreMappings(partition, crate, rod));
00470       }
00471     }
00472     configuration.pTTC  = info.fibreMappings[channel * 3 + 0];
00473     if(redundantOnROD) {
00474       configuration.rTTC = info.fibreMappings[rchannel * 3 + 0];
00475     } else {
00476       configuration.rTTC = OFF_ROD_TTC;
00477     };
00478 
00479     // Fix formatter addressing
00480     unsigned char rx0 = info.fibreMappings[channel * 3 + 1];
00481    if(rx0 != DATA_LINK_OFF) {
00482      configuration.rx[0] = (rx0/12)*16 + rx0%12;
00483 
00484      if(rx0 < getRodInfo(label).minLink) {
00485        getRodInfo(label).minLink = rx0;
00486      }
00487    } else {
00488      configuration.rx[0] = DATA_LINK_OFF;
00489     }
00490 
00491     // Fix formatter addressing (receive 1)
00492     unsigned char rx1 = info.fibreMappings[channel * 3 + 2];
00493     if(rx1 != DATA_LINK_OFF) {
00494       configuration.rx[1] = (rx1/12)*16 + rx1%12;
00495 
00496       if(rx1 < getRodInfo(label).minLink) {
00497         getRodInfo(label).minLink = rx1;
00498       }
00499     } else {
00500       configuration.rx[1] = DATA_LINK_OFF;
00501     }
00502 
00503     // Get Module group
00504     configuration.groupId = config->getModuleGroup(moduleName);
00505 
00506 
00507     if(redundantValid && configuration.select) {
00508       // Get Module group of redundant partner
00509 
00510       try {
00511         string redModuleName;
00512 
00513         unsigned int newMur, newModule;
00514         config->translateFromROD(rpartition, rcrate, rrod, rchannel, 
00515                          newMur, newModule);
00516 
00517         config->translateToSN(newMur, newModule, redModuleName);
00518 
00519         if(checkDebugOption(DEBUG_DIAG2))
00520           cout << "Found redundant module name " << redModuleName << endl;
00521 
00522         int redGroup = config->getModuleGroup(redModuleName);
00523 
00524         if(redGroup != configuration.groupId) {
00525           configuration.groupId = redGroup;
00526 
00527           cout << "Module group changed, should be identical to redundant partner\n";
00528 
00529           if(mrs)
00530             *mrs << "MODULE_GROUP_CHANGED" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
00531                  << MRS_PARAM<const char *>("sn", moduleName.c_str())
00532                  << MRS_PARAM<const char *>("redSn", redModuleName.c_str())
00533                  << MRS_PARAM<int>("group", configuration.groupId)
00534                  << MRS_TEXT("Module group changed, should be identical to redundant partner")
00535                  << ENDM;
00536         }
00537       } catch(ConfigurationException &c) {
00538         cout << "Module name not found: \n";
00539         cout << c.what() << endl;
00540 
00541         {
00542           boost::mutex::scoped_lock lock(log().mutex());
00543           log() << "  (Not found)\n";
00544         }
00545       }
00546 
00547     }
00548 
00549     // Put error mask into ROD cache
00550     for(int l=0; l<2; l++) {
00551       const unsigned int zeroTo123Pos = configuration.rx[l];
00552       // We check the values before using it, doing this here makes the next bit less confusing
00553       const unsigned int zeroTo95Pos = Sct::FibreNumberConverters::from124FormatTo96Format(zeroTo123Pos);
00554       if (zeroTo123Pos==DATA_LINK_OFF) {
00555         // Don't put it in the map! 
00556         //  but otherwise this is valid ... no problem
00557       } else if(zeroTo123Pos <= 123 && zeroTo95Pos < 96) {
00558         // Good value, put in map
00559         unsigned int val = config->getModuleErrorMask(partition, crate, rod, channel, l);
00560         getRodInfo(label).linkErrorMasks[zeroTo95Pos] = val;
00561       } else {
00562         std::ostringstream os;
00563         os << "Bad fibre numbers for error mask values! Line " << __LINE__ << " of " << __FILE__ << " when 123pos = " << zeroTo123Pos << " and 95pos = " << zeroTo95Pos;
00564         if (mrs) {
00565           *mrs << "SctApi" << MRS_ERROR << MRS_TEXT(os.str()) << ENDM;
00566         } else {
00567           std::cout << "SctApi: ERROR " << os.str() << std::endl;
00568         }
00569       }
00570     }
00571 
00572     // Put fixed configuration into cache
00573     moduleMap.insert(make_pair(mid, configuration));
00574 
00575     if(redundantValid == true && redundantOnROD == false) {
00576       // Modify slightly for off-ROD configuration, and also put into cache
00577       configuration.rx[0] = DATA_LINK_OFF;
00578       configuration.rx[1] = DATA_LINK_OFF;
00579 
00580       // Only rTTC will get used, but overwrite pTTC with something valid
00581       configuration.pTTC = configuration.rTTC = rchannel;
00582 
00583       moduleMap.insert(make_pair(rmid, configuration));
00584       
00585       cout << "Off-ROD module configuration loaded " << rmid << " put in slot " << (int)configuration.pTTC << endl;
00586 
00587       if(mrs) {
00588         *mrs << "MODULE_LOADED" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
00589              << MRS_TEXT("Off-ROD module configuration loaded")
00590              << MRS_PARAM<int>("rmid", rmid)
00591              << MRS_PARAM<int>("moduleSlot", configuration.pTTC)
00592              << ENDM;
00593       }
00594     }
00595 
00596     // Now what did we end up with?
00597     cout << "\tpTTC = " << (int)configuration.pTTC << " rTTC = " << (int)configuration.rTTC 
00598          << " rx[0] = " << (int)configuration.rx[0] << " rx[1] = " << (int)configuration.rx[1] 
00599          << " group = " << (int)configuration.groupId;
00600 
00601     for(int l=0; l<2; l++) {
00602       const unsigned char link = l?rx1:rx0;
00603       if(link < 96) {
00604         int mask = getRodInfo(label).linkErrorMasks[link];
00605         cout << (l?" errorMask1 = 0x":" errorMask0 = 0x") << hex << mask << dec;
00606       }
00607     }
00608     cout << endl;
00609 
00610     if(mrs) {
00611       int link0 = configuration.rx[0];
00612       int link1 = configuration.rx[1];
00613 
00614       // Reverse translate formatter encoding
00615       if(link0 != DATA_LINK_OFF) 
00616         link0 = (link0/16) * 12 + link0%16;
00617       if(link1 != DATA_LINK_OFF) 
00618         link1 = (link1/16) * 12 + link1%16;
00619 
00620       *mrs << "MODULE_LOADED" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
00621            << MRS_PARAM<const char *>("sn", moduleName.c_str())
00622            << MRS_PARAM<int>("group", configuration.groupId)
00623            << MRS_PARAM<int>("select", configuration.select)
00624            << MRS_PARAM<int>("pTTC", configuration.pTTC)
00625            << MRS_PARAM<int>("rTTC", configuration.rTTC)
00626            << MRS_PARAM<int>("rx0", link0)
00627            << MRS_PARAM<int>("rx1", link1);
00628 
00629       for(int l=0; l<2; l++) {
00630         const unsigned char link = l?rx1:rx0;
00631         if(link < 96) {
00632           int mask = getRodInfo(label).linkErrorMasks[link];
00633           if(mask) {
00634             *mrs << MRS_PARAM<int>(l?"errorMask1":"errorMask0", mask);
00635           }
00636         }
00637       }
00638 
00639       *mrs << MRS_TEXT("Module configuration loaded")
00640            << ENDM;
00641     }
00642     
00643   } catch(ConfigurationException &c) {
00644     cout << "Module not initialised: \n";
00645     cout << c.what() << endl;
00646 
00647     {
00648       boost::mutex::scoped_lock lock(log().mutex());
00649       log() << "  (Not found)\n";
00650     }
00651 
00652     throw;
00653   }
00654 }
00655 
00656 ABCDModule *SctApi::retrieveModule(UINT32 mid) {
00657   {
00658     boost::mutex::scoped_lock lock(log().mutex());
00659     log() << "retrieveModule " << mid << endl;
00660   }
00661   return lookupConfig(mid);
00662 }
00663 
00664 // Create a prim list
00665 void SctApi::createDebugPrimList() {
00666   {
00667     boost::mutex::scoped_lock lock(log().mutex());
00668     log() << "createDebugPrimList\n";
00669   }
00670   debugPrimList->clear();
00671 }
00672 
00673 // Append a primitive to the prim list
00674 void SctApi::addDebugPrimList(unsigned long length, long index, long id, long version,
00675                               unsigned long * body) {
00676   {
00677     boost::mutex::scoped_lock lock(log().mutex());
00678     log() << "addDebugPrimList ID: " << id << " length: " << length << endl;
00679   }
00680   // Don't pass the body because we don't know where it came from...
00681   debugPrimList->addPrimitive(RodPrimitive((long)length, index, id, version, (long *)body));
00682 }
00683 
00684 // Send primlist
00685 void SctApi::sendDebugPrimList(unsigned int rod) {
00686   {
00687     boost::mutex::scoped_lock lock(log().mutex());
00688     log() << "sendDebugPrimList " << m_id->ucid() << " " << rod << endl;
00689   }
00690   sendPrimList(rod, debugPrimList);
00691 }
00692 
00693 // Send primlist to all rods
00694 void SctApi::sendDebugPrimListAll() {
00695   {
00696     boost::mutex::scoped_lock lock(log().mutex());
00697     log() << "sendDebugPrimListAll\n";
00698   }
00699 
00700   sendPrimListAll(debugPrimList);
00701 }
00702 
00703 void SctApi::sendDebugSlavePrimList(unsigned int rod,
00704                                     unsigned int slave, bool await, bool response) {
00705   {
00706     boost::mutex::scoped_lock lock(log().mutex());
00707     log() << "sendDebugSlavePrimList \n";
00708   }
00709   sendSlavePrimList(rod, debugPrimList, slave, await, response);
00710 }
00711 
00712 void SctApi::debugPrimListFromFile(string fileName) {
00713   ifstream fin(fileName.c_str(), ios::binary);
00714 
00715   unsigned long fileSize;
00716 
00717   // Get size of file
00718   fin.seekg(0, std::ios::end);  // go to end of file
00719   fileSize = fin.tellg();  // file size is current location
00720   fin.seekg(0, std::ios::beg);  // go back to beginning of file
00721 
00722   cout << "Loading file size: " << fileSize << endl;
00723 
00724   long *buffer = new long[fileSize];
00725 
00726   fin.read((char *)(buffer), fileSize);
00727 
00728   long listLength = buffer[0];
00729 //   long listIndex = buffer[1];
00730   long listNumPrims = buffer[2];
00731 //   long listPrimVersion = buffer[3];
00732 
00733   int offset = 4;
00734 
00735   debugPrimList->clear();
00736 
00737   for(int i=0; i<listNumPrims; i++) {
00738     long primLength = buffer[offset + 0];
00739     long primIndex = buffer[offset + 1];
00740     long primId = buffer[offset + 2];
00741     long primVersion = buffer[offset + 3];
00742 
00743     // Copy data to primitive
00744     debugPrimList->addPrimitive(primLength - 4, primIndex, primId, primVersion, buffer + offset + 4);
00745 
00746     offset += primLength;
00747     if(offset > listLength) {
00748       cout << "offset too big\n";
00749       return;
00750     }
00751   }
00752 }
00753 
00754 void SctApi::dumpDebugPrimList() {
00755   dumpPrimList(debugPrimList);
00756 }
00757 
00758 /*
00759   Initialise a module:
00760   Load configuration from database
00761   Send configuration to ROD
00762 
00763   return 0 for success
00764 */
00765 int SctApi::initialiseModule(string modulename, bool toRod) {
00766   {
00767     boost::mutex::scoped_lock lock(log().mutex());
00768     log() << "InitialiseModule " << modulename << endl << flush;
00769   }
00770   
00771   unsigned int partition, crate, rod, channel;
00772 
00773   // First find out where this module is
00774   try {
00775     unsigned int MUR, module;
00776     config->translateFromSN(modulename, MUR, module);
00777     config->translateToROD(MUR, module, partition, crate, rod, channel);
00778   } catch(ConfigurationException &c) {
00779     cout << "Module not initialised: \n";
00780     cout << c.what() << endl;
00781     return -1;
00782   }
00783 
00784   unsigned long mid=packpcrc(partition, crate, rod, channel);
00785 
00786   try {
00787     boost::mutex::scoped_lock lock(moduleMapAccess);
00788     //cache the module config from the config_service to the Crate Controller if necessary
00789     if (moduleMap.find(mid) == moduleMap.end()){
00790       cout << "Cache " << (toRod?"and Load ":"") << "module " << modulename << " at " <<
00791     partition << ", " << crate << ", " << rod << ", " << channel << " \n";
00792       
00793       cacheModuleConfig(mid, modulename);
00794     }
00795   } catch(ConfigurationException &c) {
00796     cout << "Module not initialised: \n";
00797     cout << c.what() << endl;
00798     return -2;
00799   }
00800 
00801   // Install configuration in ROD
00802   if(toRod){
00803     std::list<BankType> banks;
00804     banks.push_back(SCTAPI_BANK_PHYSICS);
00805     banks.push_back(SCTAPI_BANK_CALIBRATION);
00806     banks.push_back(SCTAPI_BANK_SCAN);
00807     setABCDModule(mid, banks);
00808   }
00809   return 0;
00810 }
00811 
00812 /*
00813    Initialise a rod from the configuration
00814  */
00815 int SctApi::initialiseRod(unsigned int rod) {
00816   cout << "Hopefully will later get config for " << Sct::URID(prt(),crt(), rod) << " at " << __FILE__ << " " << __LINE__ << endl;
00817   {
00818     boost::mutex::scoped_lock lock(log().mutex());
00819     log() << "InitialiseRod\n";
00820   }
00821   Crate *myCrate = getCrate();
00822   if(!myCrate) {
00823     cout << "Request for non-existent crate " << ucid() << endl;
00824     return -1;
00825   } else if(!getCrate()->RODPresent(rod)) {
00826     cout << "ROD can't be initialised further: " << ucid() << " " << rod << endl;
00827     return -2;
00828   } else {
00829     // Set up and start slaves
00830     SctConfiguration::RodConfig rodConf;
00831     try {
00832       cout << "Getting config for " << Sct::URID(prt(),crt(), rod) << " at " << __FILE__ << " " << __LINE__ << endl;
00833       rodConf = config->getRodConfig(prt(), crt(), rod);
00834     } catch(ConfigurationException &c) {
00835       cout << "No configuration for rod " << rod << endl;
00836       return -3;
00837     }
00838 
00839     { 
00840       // Set source id register
00841       shared_ptr<PrimListWrapper> srcIdList(new PrimListWrapper(1));
00842 
00843       PrimBuilder &builder = PrimBuilder::instance();
00844       int regId = 0x1a1;
00845 #ifdef SOURCE_ID
00846       regId = SOURCE_ID;
00847 #endif
00848       builder.writeRegister(srcIdList, regId, 0, 16, (crt() << 8) | rod);
00849 
00850       sendPrimList(rod, srcIdList);
00851       if(awaitResponse(rod, 1) != 0) {
00852     cout << "Setting source ID on ROD failed!\n";
00853       }
00854     }
00855 
00856     int startedSlaves = 0;
00857     int configuredSlaves = 0;
00858     for(int slave=0;  slave < numSlaves; slave++) {
00859       try {
00860         string ip;
00861         string id;
00862         string ext;
00863 
00864         if(rodConf.slaves[slave].ipramFile != "") {
00865           ip = rodConf.slaves[slave].ipramFile;
00866           id = rodConf.slaves[slave].idramFile;
00867           ext = rodConf.slaves[slave].extFile;
00868         } else {
00869           cout << " Trying defaults\n";
00870 
00871           int rev = getCrate()->getRodRevision(rod);
00872 
00873           char revChar = (char)(rev-0xa) + 'A';
00874 
00875           // Just load rev E DSP code?
00876           //   if(rev == 0xf) revChar = 'E';
00877 
00878           cout << " Slave config for Rev" << revChar << endl;
00879 
00880           SlaveConfig slaveConfig = config->getDefaultSlaveConfig(revChar);
00881           ip = slaveConfig.ipramFile;
00882           id = slaveConfig.idramFile;
00883           ext = slaveConfig.extFile;
00884 #warning "Assumes there are valid defaults..."
00885         }
00886 
00887         std::cerr << "Starting slave " << slave << std::endl;
00888         std::cerr << "(" << ip << ", " << id << ", " << ext << ")\n";
00889 
00890         configuredSlaves ++;
00891 
00892         // These changed for Rev E!
00893         if(getCrate()->getRodRevision(rod) >= 0xe) {
00894           writeSlaveFile(rod, slave, ip, 0);
00895           writeSlaveFile(rod, slave, id, 0x10000);
00896           writeSlaveFile(rod, slave, ext, 0xa0000000);
00897         } else {
00898           writeSlaveFile(rod, slave, ip, 0);
00899           writeSlaveFile(rod, slave, id, 0x80000000);
00900           writeSlaveFile(rod, slave, ext, 0x2000000);
00901         }
00902  
00903         startSlave(rod, slave);
00904 
00905         myCrate->slaveStarted(rod, slave);
00906 
00907         startedSlaves ++;
00908 
00909         cout << "Slave " << slave << " on rod " << rod << " configured at TIME " << second_clock::universal_time() << endl;
00910       } catch(ConfigurationException &c) {
00911         cout << "No configuration for slave " << slave << ": " << c.what() << endl;
00912 
00913         if(mrs) {
00914           *mrs << "ROD_SLAVE_INIT" << MRS_ERROR
00915                << MRS_TEXT((string("ROD slave configuration not found: ") + c.what()).c_str())
00916                << MRS_PARAM<int>("partition", prt())
00917                << MRS_PARAM<int>("crate", crt())
00918                << MRS_PARAM<int>("rod", rod)
00919                << MRS_PARAM<int>("slave", slave) 
00920                << ENDM;
00921         }
00922       } catch(SctApiException &s) {
00923         cout << "Slave start failed: " << s.what() << endl;
00924 
00925         if(mrs) {
00926           *mrs << "ROD_SLAVE_INIT" << MRS_ERROR
00927                << MRS_TEXT((string("ROD slave initialisation failed: ") + s.what()).c_str())
00928                << MRS_PARAM<int>("partition", prt())
00929                << MRS_PARAM<int>("crate", crt())
00930                << MRS_PARAM<int>("rod", rod)
00931                << MRS_PARAM<int>("slave", slave) 
00932                << ENDM;
00933         }
00934       }
00935     }
00936 
00937     if(mrs) {
00938       *mrs << "ROD_SLAVE_INIT";
00939       if(startedSlaves != configuredSlaves) {
00940         *mrs << MRS_ERROR
00941              << MRS_TEXT("ROD slave initialisation incomplete");
00942       } else {
00943         *mrs << MRS_INFORMATION
00944              << MRS_TEXT("All ROD slaves initialised");
00945       }
00946       *mrs << MRS_QUALIF("SCTAPI") 
00947            << MRS_PARAM<int>("partition", prt())
00948            << MRS_PARAM<int>("crate", crt())
00949            << MRS_PARAM<int>("rod", rod)
00950            << MRS_PARAM<int>("started", startedSlaves)
00951            << MRS_PARAM<int>("configuration", configuredSlaves)
00952            << ENDM;
00953     }
00954 
00955     cout << "Started " << startedSlaves << " slave DSPs\n";
00956 
00957     RodLabel currRod(prt(), crt(), rod);
00958 
00959     std::cout << "Not Reading out modules from ROD but actually adding rod << " << Sct::URID(prt(),crt(),rod) << " to rod list!" << std::endl;
00960 
00961     addRodToList(currRod);
00962     {
00963       const RodLabel & l = this->rodList.back(); //moo Moo
00964       std::cout << "Last rod added was " << Sct::URID(l.partition, l.crate, l.rod) << std::endl;
00965     }
00966   }
00967   return 0;
00968 }
00969 
00970 
00979 class PreLoadConfigurations{
00980 public:
00981   PreLoadConfigurations(SctApi* api) : api(api){}
00982   ~PreLoadConfigurations(){}
00983   void operator() (){
00984     bool success=false;
00985     try{
00986       ptime start_time(second_clock::universal_time());
00987       std::cout << "Started preloading module configurations at TIME " 
00988         << start_time << std::endl;
00989       api->m_preloadModuleConfigurationsStop=false;
00990       unsigned modules = api->preloadModuleConfigurations();
00991       ptime end_time(second_clock::universal_time());
00992       time_duration load_time=(end_time-start_time);
00993       std::cout << "Preloaded " << modules << " module configurations at TIME "
00994         << end_time << ". Took " << load_time.seconds() << " seconds" << std::endl;
00995       success=true;
00996     }catch(std::exception& e){
00997       std::cerr << e.what() << std::endl;
00998     }catch(...){
00999     }
01000     if (!success){
01001       std::cerr << api->ucid() << " Pre-load of module configurations FAILED!" << std::endl;
01002     }
01003   }
01004   SctApi* api;
01005 private:
01006   PreLoadConfigurations(){}
01007 };
01008 
01009 
01010 /*
01011    Initialise everything from the configuration.
01012    Uses initialiseRod and initialiseModule to do actual configuration
01013  */
01014 #define PRELOAD_MODULE_CONFIGURATIONS 1
01015 void SctApi::initialiseAll(int run) {
01016   //setDebugOption("diag");
01017   //setDebugOption("diag2");
01018   //setDebugOption("print_in_prim");
01019   //setDebugOption("module_config");
01020   m_is_initialised=false;
01021 
01022   runNumber = run;
01023 
01024 #if USE_SCAN_THREAD
01025   std::cout << "Initialisation using thread" << std::endl;
01026   scanPollThread.reset(new boost::thread(boost::bind(&SctApi::initialisationThread, this)));
01027 #else
01028   std::cout << "Initialisation without using thread" << std::endl;
01029   initialisationThread();
01030 #endif
01031 }
01032 
01033 void SctApi::initialisationThread(){
01034   {
01035     boost::mutex::scoped_lock lock(log().mutex());
01036     log() << "InitialiseAll " << runNumber << " foe " << m_id->ucid() << "\n";
01037   }
01038   cout << "********** SCT API initialisation started for " << m_id->ucid() <<" **********\n";
01039   {
01040     time_t startTime = time(NULL);
01041     struct tm broke = *(gmtime(&startTime));
01042 
01043     char buffer[25];
01044     strftime(buffer, 25, "%H:%M:%S %Y/%m/%d", &broke);
01045 
01046     cout << "***************** " << buffer << " **************\n";
01047   }
01048 
01049   unsigned int totalPartitions = 0;
01050   unsigned int totalCrates = 0;
01051   unsigned int totalRods = 0;
01052   unsigned int totalModules = 0;
01053 
01054   // Clear up from previous time if necessary
01055 
01056   crateObject.reset();
01057   moduleMap.clear();
01058   debugPrimList->clear();
01059   rodList.clear();
01060   module_cache.clearAll();
01061 
01062   // start pre-loading module configurations
01063 #if PRELOAD_MODULE_CONFIGURATIONS
01064     boost::thread initialisation_thread(PreLoadConfigurations(this));
01065 #endif
01066 
01067   // Read in configuration and act accordingly
01068   list<unsigned int> partitions; 
01069   try {
01070     partitions = config->listPartitions();
01071   } catch(ConfigurationException &c) {
01072     cout << "No partitions to initialise\n";
01073     cout << c.what() << endl;
01074     return;
01075   }
01076 
01077   cout << "Found configuration for " << partitions.size() << " partitions\n";
01078 
01079   for(list<unsigned int>::const_iterator p=partitions.begin();
01080       p!=partitions.end(); 
01081       p++) {
01082 
01083     list<unsigned int> crates; 
01084 
01085     try {
01086       crates = config->listCratesInPartition(*p);
01087     } catch(ConfigurationException &c) {
01088       cout << "No crates in this partition\n";
01089       cout << c.what() << endl;
01090       continue;
01091     }
01092 
01093     cout << "Found configuration for " << crates.size() << " crates\n";
01094 
01095     for(list<unsigned int>::const_iterator c=crates.begin(); 
01096         c!=crates.end(); 
01097         c++) {
01098 
01099       if (Sct::UCID(*p, *c)==ucid()) {
01100 
01101     cout << "Found a config for our own dear crate " << ucid() << endl;
01102     try {
01103       crateObject = boost::shared_ptr<Crate>(new CrateImpl(ucid(), config));
01104       
01105       if(mrs)
01106         getCrate()->setMrsStream(mrs);
01107       
01108       cout << ucid() << " Initialise crate at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
01109       // Setup VME and say HI to the TIM and all the RODs and BOCs (includes reset of the RODs)
01110       totalRods += getCrate()->initialiseCrate();
01111 
01112 #warning 'AJB WHAT ABOUT TIM2??'
01113       unsigned tim_debug_status = timReadRegister(TIM_REG_DEBUG_CTL);
01114       bool sw_disable = tim_debug_status & (1<<12);
01115       unsigned tim_busy_stat3 = timReadRegister(0x5A);
01116       bool hw_disable = tim_busy_stat3 & (1<<15);
01117 
01118       if (sw_disable || hw_disable){
01119         if (mrs) {
01120           *mrs << MRS_WARNING << "TIM_FFT_VETO_DISABLED" << MRS_QUALIF("SCTAPI")
01121            << MRS_PARAM<int>("partition",ucid().partition())
01122            << MRS_PARAM<int>("crate",ucid().crate())
01123            << MRS_PARAM<int>("hardware disable",hw_disable)
01124            << MRS_PARAM<int>("software disable",sw_disable)
01125            << MRS_PARAM<int>("overall disable",(sw_disable&&hw_disable))
01126            << MRS_TEXT("Tim Fixed Frequency Veto has been DISABLED! If the magnetic field is on this could be DANGEROUS TO MODULES!") << ENDM;
01127           
01128         }else{
01129           std::cout << "TIM FFTV disable : h/w disable=" << hw_disable 
01130             << " s/w disable=" << sw_disable << std::endl;
01131         }
01132       }
01133 
01134       list<unsigned int> rods;
01135       try {
01136         rods = config->listRodsInCrate(*p, *c);
01137       } catch(ConfigurationException &cex) {
01138         cout << "No RODs in this crate\n";
01139         cout << cex.what() << endl;
01140 
01141         if(mrs) {
01142           *mrs << "CRATE_WARNING" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
01143            << MRS_TEXT("No configuration for RODs while initialising crate")
01144            << MRS_PARAM<int>("partition", *p)
01145            << MRS_PARAM<int>("crate", *c)
01146            << ENDM;
01147         }
01148 
01149         continue;
01150       }
01151       
01152       //set flag to stop preloading module configurations.
01153           m_preloadModuleConfigurationsStop=true; 
01154 
01155             for(list<unsigned int>::const_iterator r=rods.begin(); 
01156           r!=rods.end(); 
01157           r++) {
01158         RodLabel label(*p, *c, *r);
01159         
01160         // This also does the slave setup
01161             cout << ucid() << " Start rod " << *r << " initialisation at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
01162       
01163         if(initialiseRod(*r) != 0) {
01164           cout << "Initialisation of rod  " << *r << " failed!\n";
01165           // Don't load modules...
01166           continue;
01167         }
01168         
01169         cout << ucid() << " Start rod " << *r << " module initialisation at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
01170 
01171         list<unsigned int> MURs;
01172         try {
01173           MURs = config->listMURSInRod(*p, *c, *r);
01174         } catch(ConfigurationException &cex) {
01175           cout << "No MURs for this ROD\n";
01176           cout << cex.what() << endl;
01177           if(mrs) {
01178         *mrs << "CRATE_WARNING" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
01179              << MRS_TEXT("Configuration for no modules while initialising ROD")
01180              << MRS_PARAM<int>("partition", *p)
01181              << MRS_PARAM<int>("crate", *c)
01182              << MRS_PARAM<int>("ROD", *r)
01183              << ENDM;
01184           }
01185           continue;
01186         }
01187         for(list<unsigned int>::const_iterator mur=MURs.begin(); 
01188         mur!=MURs.end(); 
01189         mur++) {
01190           
01191           list<string> modules;
01192           try {
01193         modules = config->listModulesInMUR(*p, *mur);
01194           } catch(ConfigurationException &c) {
01195         cout << "No modules for this MUR\n";
01196         cout << c.what() << endl;
01197         continue;
01198           }
01199           
01200           for(list<string>::const_iterator m=modules.begin(); 
01201           m!=modules.end(); 
01202           m++) {
01203         // do module initialiseation if necessary
01204         if(!initialiseModule(*m, true)) {
01205           totalModules ++;
01206         }
01207           }
01208         }
01209         cout << totalModules << " modules initialised at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
01210 
01211             testLinkOutSelect(*r, getRodInfo(label).minLink);
01212       }
01213       
01214       std::cout << getCrate()->status();
01215       totalCrates++;
01216       {
01217         Sct::MultiMessageDebugStream m(true,true);
01218         m << "Crate server for " << ucid() << " finished setting up VME and saying HI to the TIM and all the RODs and BOCs (includes reset of the RODs).";
01219       }
01220     } catch(...) {
01221       // Most likely VME initialisation failed (and crate already told MRS)
01222       cout << "Unexpected failure in crate initialisation\n";
01223       
01224       if(mrs) {
01225         *mrs << "CRATE_FAILED" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
01226          << MRS_TEXT("Unexpected failure initialising crate")
01227          << MRS_PARAM<int>("partition", *p)
01228          << MRS_PARAM<int>("crate", *c)
01229          << ENDM;
01230       }
01231     }
01232       } else {
01233     // *p and *c correspond to some other crate we are not interested in.
01234       };
01235     }
01236     totalPartitions ++;
01237   }
01238 
01239 #if PRELOAD_MODULE_CONFIGURATIONS
01240   initialisation_thread.join();
01241 #endif
01242 
01243   setErrorMasks();
01244   
01245   // Load modules first so we know which channels to unmask
01246   cout << "Setup for calibration...\n";
01247   calib_init();
01248 
01249   currentRunMode = SCTAPI_RUN_CALIBRATION;
01250   cout << "... Done\n";
01251 
01252   cout << "Initialisation counts:\n";
01253   cout << "\ttotalPartitions: " << totalPartitions << endl;
01254   cout << "\ttotalCrates: " << totalCrates << endl;
01255   cout << "\ttotalRods: " << totalRods << endl;
01256   cout << "\ttotalModules: " << totalModules << endl;
01257 
01258   if (totalCrates!=1) {
01259     Sct::MultiMessageDebugStream m(true,true,true);
01260     m.severity(MRS_ERROR);
01261     m << "CrateController for " << ucid() << " found not one but " << totalCrates << " configurations in the config database while attempting to initialiseAll.";
01262   };
01263 
01264   if(mrs) {
01265     *mrs << "SCTAPIINIT_COMPLETE" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01266          << MRS_TEXT("SCTAPI Initialisation counts")
01267          << MRS_PARAM<int>("partitions", totalPartitions)
01268          << MRS_PARAM<int>("crates", totalCrates)
01269          << MRS_PARAM<int>("rods", totalRods)
01270          << MRS_PARAM<int>("modules", totalModules)
01271          << ENDM;
01272   }
01273 
01274   m_is_initialised=true;
01275 
01276   cout << "************** SCT API initialised ****************\n";
01277   {
01278     time_t endTime = time(NULL);
01279     struct tm broke = *(gmtime(&endTime));
01280 
01281     char buffer[25];
01282     strftime(buffer, 25, "%H:%M:%S %Y/%m/%d", &broke);
01283 
01284     cout << "************** " << buffer << " ****************\n";
01285   }
01286 }
01287 
01288 void SctApi::startSlave(unsigned int rod, unsigned int slave)
01289 {
01290   cout << "Starting slave on " << slave << endl;
01291 
01292   shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01293 
01294   PrimBuilder::instance().startSlave(primList, slave);
01295 
01296   sendPrimList(rod, primList);
01297   awaitResponse(rod, 5);
01298 
01299   unsigned long length;
01300   unsigned long *result = getResponse(rod, length);
01301 
01302   if(result) {
01303     unsigned int slaveRet = result[8];
01304     delete [] result;
01305     if(slaveRet != slave) {
01306       cout << "Bad return (" << slaveRet << ") from start slave " << slave << " \n";
01307       throw SctApiException("Bad return value from start slave");
01308     }
01309   } else {
01310     cout << "Bad response from start slave\n";
01311     throw SctApiException("Missing return primitive from start slave");
01312   }
01313 }
01314 
01315 void SctApi::setRunNumber(UINT32 newRun) {
01316   bool needsUpdate = false;
01317   if(newRun < runNumber) {
01318     if(mrs) {
01319       *mrs << "SCTAPI_RUNNUMBER" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
01320            << MRS_TEXT("SCTAPI runnumber decrease")
01321            << MRS_PARAM<int>("oldRunNumber", runNumber)
01322            << MRS_PARAM<int>("newRunNumber", newRun)
01323            << MRS_PARAM<int>("newScanNumber", 0)
01324            << ENDM;
01325     }
01326     cout << "****  Run number has been decreased!!\n";
01327     runNumber = newRun;
01328     needsUpdate = true;
01329     scanNumber = 0;
01330   } else if(newRun == runNumber) {
01331     if(mrs) {
01332       *mrs << "SCTAPI_RUNNUMBER" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01333            << MRS_TEXT("SCTAPI runnumber unchanged")
01334            << MRS_PARAM<int>("oldRunNumber", runNumber)
01335            << MRS_PARAM<int>("newRunNumber", newRun)
01336            << MRS_PARAM<int>("newScanNumber", scanNumber)
01337            << ENDM;
01338     }
01339     cout << "**** Run number is unchanged scan number not reset!!!\n";
01340   } else {
01341     if(mrs) {
01342       *mrs << "SCTAPI_RUNNUMBER" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01343            << MRS_TEXT("SCTAPI runnumber changed")
01344            << MRS_PARAM<int>("oldRunNumber", runNumber)
01345            << MRS_PARAM<int>("newRunNumber", newRun)
01346            << MRS_PARAM<int>("newScanNumber", 0)
01347            << ENDM;
01348     }
01349     runNumber = newRun;
01350     needsUpdate = true;
01351     scanNumber = 0;
01352   }
01353 
01354   if(needsUpdate) {
01355     shared_ptr<PrimListWrapper> runNumberList(new PrimListWrapper(1));
01356 
01357     PrimBuilder &builder = PrimBuilder::instance();
01358     int regId = 0x1a2;
01359 #ifdef RUN_NUMBER
01360     regId = RUN_NUMBER;
01361 #endif
01362     builder.writeRegister(runNumberList, regId, 0, 32, runNumber);
01363 
01364     if(synchSendPrimListAll(runNumberList) != 0) {
01365       cout << "Update of run number on RODs failed!\n";
01366     }
01367   }
01368 }
01369 
01370 void SctApi::setScanNumber(UINT32 newScan) {
01371   if(mrs) {
01372     *mrs << "SCTAPI_SCANNUMBER" << MRS_INFORMATION << MRS_QUALIF("SCTAPI");
01373   }
01374 
01375   if(newScan < scanNumber) {
01376     cout << "**** Scan number has been decreased!!\n";
01377     if(mrs) {
01378       *mrs << MRS_TEXT("SCTAPI scannumber decreased");
01379     }
01380   } else {
01381     if(mrs) {
01382       *mrs << MRS_TEXT("SCTAPI scannumber changed");
01383     }
01384   }
01385 
01386   if(mrs) {
01387     *mrs << MRS_PARAM<int>("oldScanNumber", scanNumber)
01388          << MRS_PARAM<int>("newScanNumber", newScan)
01389          << ENDM;
01390   }
01391 
01392   scanNumber = newScan;
01393 }
01394 
01395 UINT32 SctApi::getRunNumber() {
01396   return runNumber;
01397 }
01398 
01399 UINT32 SctApi::getScanNumber() {
01400   return scanNumber;
01401 }
01402 
01403 ModuleList SctApi::getModuleList()  
01404 {
01405   ModuleList result;
01406 
01407   // Set up masks for modules
01408   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
01409       mi!=moduleMap.end();
01410       mi ++) {
01411     
01412     UINT32 currMid = mi->first;
01413     result.push_back(convertToString(currMid));
01414   }
01415 
01416   return result;
01417 }
01418 
01419 bool SctApi::isRODPresent(unsigned int rod) {
01420   bool result = false;
01421   if(getCrate()) {
01422     if(getCrate()->RODPresent(rod)) {
01423       result = true;
01424     }
01425   }
01426 
01427   return result;
01428 }
01429 
01430 void SctApi::startupModules() {
01431   // Turn power to standby1
01432   m_dcsAccess->toStandby1();
01433 
01434   // Check for clk/2 or event (its still running from last time)
01435   checkAllModulesProbe("2E");
01436 
01437   // Send configs
01438   sendAllABCDModules(SCTAPI_BANK_PHYSICS);
01439 
01440   // Check for event headers
01441   checkAllModulesProbe("E");
01442 
01443   // Power to standby2
01444   m_dcsAccess->toStandby2();
01445 }
01446 
01447 void SctApi::autoConfigure() {
01448   ::SctApi::AutoConf::AutoConfigurer configurer(*this);
01449   configurer.run();
01450 }
01451 
01452 /*
01453    Send a PrimList to a ROD
01454 
01455    This function exposes RodPrimList so make it private.
01456    Therefore to be used internally to this class.
01457 */
01458 void SctApi::sendPrimList(unsigned int rod,
01459                           shared_ptr<PrimListWrapper> prim) {
01460   {
01461     boost::mutex::scoped_lock lock(log().mutex());
01462     log() << "SendPrimList (" << m_id->ucid() << " " << rod << ")\n" << flush;
01463   }
01464 
01465   // This calls RodPrimList->bufferBuild
01466   dumpPrimList(prim);
01467 
01468   currentStats.primitiveLengthCounter += prim->list->getBufferLength();
01469   currentStats.primitiveCounter ++;
01470 
01471   updateISStats();
01472 
01473   if(getCrate()) {
01474     getCrate()->sendPrimList(rod, prim);
01475   } else {
01476     cout << "Request for non-existent crate " << m_id->ucid() << endl;
01477   }
01478 }
01479 
01480 int SctApi::synchSendPrimList(unsigned int rod, shared_ptr<PrimListWrapper> primList, int timeout) {
01481   // Send list
01482   sendPrimList(rod, primList);
01483  
01484   {
01485     boost::mutex::scoped_lock lock(log().mutex());
01486     log() << "synchSendPrimList sent" << endl;
01487   }
01488   int result = 0;
01489 
01490   // Wait for list, with no threads the awaitResponse starts the primitive...
01491   int responseCode = awaitResponse(rod, timeout);
01492   
01493   if(responseCode != 0) {
01494     cout << "Synchronous primitive list failed on crate "<< ucid()<<"\n";
01495     cout << " code = " << responseCode << endl;
01496     
01497     result = 1;
01498   }
01499   {
01500     boost::mutex::scoped_lock lock(log().mutex());
01501     log() << "synchSendPrimList returned " << result << endl;
01502   }
01503   
01504   return result;
01505 }
01506 
01507 /*
01508    Send a PrimList to all RODs in a crate
01509 
01510    This function exposes RodPrimList so make it private.
01511    Therefore to be used internally to this class.
01512 */
01513 void SctApi::sendPrimListAll(shared_ptr<PrimListWrapper> prim) {
01514   if(checkDebugOption(DEBUG_DIAG)){
01515     boost::mutex::scoped_lock lock(log().mutex());
01516     log() << "SendPrimListAll (" << m_id->ucid() << ")\n" << flush;
01517   }
01518 
01519   dumpPrimList(prim);
01520 
01521   if(getCrate()) {
01522     getCrate()->sendPrimListAll(prim);
01523   } else {
01524     cout << "Request for non-existent crate " << m_id->ucid() << endl;
01525   }
01526 }
01527 
01528 int SctApi::synchSendPrimListAll(shared_ptr<PrimListWrapper> primList, int timeout) {
01529   // Send list
01530   sendPrimListAll(primList);
01531  
01532   {
01533     boost::mutex::scoped_lock lock(log().mutex());
01534     log() << "synchSendPrimList sent" << endl;
01535   }
01536   int result = 0;
01537 
01538   // Wait for list, with no threads the awaitResponse starts the primitive...
01539   int responseCode = awaitResponseAll(timeout);
01540   
01541   if(responseCode != 0) {
01542     cout << "Synchronous primitive list failed on crate "<< ucid()<<"\n";
01543     cout << " code = " << responseCode << endl;
01544     
01545     result = 1;
01546   }
01547   {
01548     boost::mutex::scoped_lock lock(log().mutex());
01549     log() << "synchSendPrimList returned " << result << endl;
01550   }
01551   
01552   return result;
01553 }
01554 
01555 void SctApi::dumpPrimList(shared_ptr<PrimListWrapper> prim) {
01556   prim->list->bufferBuild();
01557 
01558   long buffLength = prim->list->getBufferLength();
01559   unsigned long* bufferStart = prim->list->getBuffer();
01560 
01561   if(checkDebugOption(DEBUG_DUMP_PRIM_BINARY))
01562     printMemoryBlock(log(), bufferStart, buffLength, 8);
01563 
01564   if(checkDebugOption(DEBUG_SAVE_PRIM)) {
01565     static int primCount = 0;
01566 
01567     string dirName = Sct::SctNames::getTempDir() + "/PrimLists";
01568 
01569     // Ignore success (0) or failure
01570     int mkRet = mkdir(dirName.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
01571     if(mkRet != 0) {
01572       // It's OK if it already exists
01573       if(errno != EEXIST) {
01574     perror(("Failed to create PrimLists directory in " + Sct::SctNames::getTempDir()).c_str());
01575       }
01576     }
01577 
01578     char *saveDir = getcwd(NULL, 0);
01579 
01580     int chRet = chdir(dirName.c_str());
01581     if(chRet != 0) {
01582       perror("Failed to change to PrimLists directory");
01583     }
01584 
01585     char fileName[100];
01586     sprintf(fileName, "PrimLists_%05d.bin", primCount++);
01587     ofstream fout(fileName, ios::binary | ios::trunc);
01588     fout.write((char*)&bufferStart[0], buffLength*4);
01589 
01590     int chRet2 = chdir(saveDir);
01591     if(chRet2 != 0) {
01592       perror("Failed to return to saved directory");
01593     }
01594 
01595     free(saveDir);
01596   }
01597 
01598   if(checkDebugOption(DEBUG_PRINT_IN_PRIM)) {
01599     // Pick between log and cout
01600     if(checkDebugOption(DEBUG_LOG_PRINT_PRIM)) {
01601       ::SctApi::printOutList(bufferStart, buffLength, true, 0, log(), 
01602                              checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01603     } else {
01604       ::SctApi::printOutList(bufferStart, buffLength, true, 0, cout, 
01605                              checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01606     }
01607   }
01608 }
01609 
01610 /*
01611    Shutdown anything that needs shutting down
01612    Send DCS to standby message
01613  */
01614 void SctApi::shutdownAll() {
01615   {
01616     boost::mutex::scoped_lock lock(log().mutex());
01617     log() << "SctApi told to shutdown\n";
01618     log() << "\t TIME " << second_clock::universal_time() << endl;
01619   }
01620   m_is_initialised=false;
01621 
01622   // What does shutdown involve?
01623   lasersOff(); //   ????
01624 
01625   if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
01626     standardRegisterDumpAll();
01627   }
01628 
01629   if(mrs) {
01630     *mrs << "SCTAPI_SHUTDOWN" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << MRS_TEXT("First ROD shut down") << ENDM;
01631   }
01632 
01633   {
01634     boost::mutex::scoped_lock lock(log().mutex());
01635     log() << "Shutdown sequence complete\n";
01636   }
01637 }
01638 
01639 /*
01640    Create a RodPrimList to send to the Master DSP which contains the RodPrimList which is passed as an argument
01641  */
01642 void SctApi::sendSlavePrimList(unsigned int rod,
01643                                shared_ptr<PrimListWrapper> prim, unsigned int slaveNumber, bool await, bool response) {
01644   {
01645     boost::mutex::scoped_lock lock(log().mutex());
01646     log() << "SendSlavePrimlist (" << m_id->ucid() << " " << rod << ")\n" << flush;
01647   }
01648 
01649   if((!getCrate())
01650      || (!getCrate()->slavePresent(rod, slaveNumber))) {
01651     cout << "***** Slave DSP (" << slaveNumber << ") was not initialised, please check the configuration and the Slave Image files\n";
01652     return;
01653   }
01654 
01655   shared_ptr<PrimListWrapper> container(new PrimListWrapper(1));
01656 
01657   PrimBuilder::instance().slavePrimList(container, prim, slaveNumber, await, response);
01658 
01659   try {
01660     container->list->bufferBuild();
01661   }
01662   catch (PrimListException &p) {
01663     cout << p.getDescriptor() << " ";
01664     cout << p.getData1() << ", " << p.getData2() << "\n";
01665   }
01666 
01667   sendPrimList(rod, container); 
01668 }
01669 
01670 /*
01671     Lookup the Crate object to send instructions to.
01672     Return 0 if not found.
01673  */
01674 Crate *SctApi::getCrate() const {
01675   return crateObject.get();
01676   /*
01677   map<pair<unsigned int, unsigned int>, Crate* >::const_iterator found;
01678 
01679   found = crateMap.find(make_pair(partition, crate));
01680   if(found == crateMap.end()) {
01681     cerr << "Crate not found in getCrate " << partition << ", " << crate << endl;
01682     throw SctApiException("Missing crate");
01683   }
01684   else return found->second;
01685   */
01686 }
01687 
01688 int SctApi::awaitResponse(unsigned int rod, int timeout) {
01689   int retVal = 0;
01690   {
01691     boost::mutex::scoped_lock lock(log().mutex());
01692     log() << "AwaitResponse\n";
01693   }
01694 
01695   if(getCrate()) {
01696     try {
01697       retVal = getCrate()->awaitResponse(rod, timeout);
01698     } catch(CrateException &c) {
01699       cout << "Crate exception in await response\n" << c.what() << endl;
01700       retVal = -1;
01701     } catch(BaseException &b) {
01702       cout << "Base exception in await response\n" << b << endl;
01703       retVal = -1;
01704     } catch(...) {
01705       cout << "Exception in await response\n";
01706       retVal = -1;
01707     }
01708 
01709     if(retVal != 0) {
01710       if(config->isDummyCrate(prt(), crt())) {
01711         //We can't wait if there is nothing there so don't signal an error
01712         //We only check here to prevent doing potentially a lot of unnecessary IPC calls...
01713         retVal = 0;
01714       } else {
01715         cout << "Problem during await response\n";
01716         cout << "Crate status " << ucid() << endl;
01717         try {
01718           cout << getCrate()->status();
01719         } catch(VmeException &v) {
01720           cout << "Exception getting crate status\n";
01721           ::SctApi::Utility::decodeVme(v);
01722         }
01723       }
01724     }
01725   } else {
01726     cout << "Request for non-existent crate " << m_id->ucid() << endl;
01727   }
01728 
01729   if(checkDebugOption(DEBUG_DIAG)){
01730     boost::mutex::scoped_lock lock(log().mutex());
01731     log() << "\tAwaitResponse: " << retVal << endl;
01732   }
01733 
01734   return retVal;
01735 }
01736 
01737 int SctApi::awaitResponseAll(int timeout) {
01738   int retVal = 0;
01739 
01740   if(checkDebugOption(DEBUG_DIAG)){
01741     boost::mutex::scoped_lock lock(log().mutex());
01742     log() << "AwaitResponse\n";
01743   }
01744 
01745   if(getCrate()) {
01746     try {
01747       retVal = getCrate()->awaitResponseAll(timeout);
01748     } catch(CrateException &c) {
01749       cout << "Crate exception in await response all\n" << c.what() << endl;
01750       retVal = -1;
01751     } catch(BaseException &b) {
01752       cout << "Base exception in await response all\n" << b << endl;
01753       retVal = -1;
01754     } catch(...) {
01755       cout << "Exception in await response all\n";
01756       retVal = -1;
01757     }
01758 
01759     if(retVal != 0) {
01760       cout << "Problem during await response all\n";
01761     }
01762   } else {
01763     cout << "Request for non-existent crate " << m_id->ucid() << endl;
01764   }
01765 
01766   return retVal;
01767 }
01768 
01769 unsigned long *SctApi::getResponse(unsigned int rod, 
01770                                    unsigned long &length) {
01771   unsigned long *result;
01772 
01773   if(checkDebugOption(DEBUG_DIAG_RESPONSE)){
01774     boost::mutex::scoped_lock lock(log().mutex());
01775     log() << "GetResponse\n";
01776   }
01777   if(getCrate()) {
01778     boost::shared_ptr<RodOutList> output = getCrate()->getResponse(rod);
01779 
01780     if(!output) {
01781       cout << "No response from crate\n";
01782       return NULL;
01783     }
01784 
01785     length = (unsigned long) output->getLength();
01786 
01787     currentStats.primitiveOutLengthCounter += length;
01788 
01789     updateISStats();
01790 
01791     if(checkDebugOption(DEBUG_DIAG_RESPONSE))
01792       cout << "Got response from crate length = " << length << endl;
01793 
01794     unsigned long *body = output->getBody();
01795 
01796     result = new unsigned long[length];
01797 
01798     for(unsigned int i=0; i<length; i++) {
01799       result[i] = body[i];
01800     }
01801 
01802     if(body[0] != length) {
01803       cout << "Bad outlist/outlength mismatch in returned outlist (" << m_id->ucid() << " " << rod << "): " << body[0] << " != " << length << endl;
01804       return NULL;
01805     }
01806 
01807     if(checkDebugOption(DEBUG_SAVE_PRIM)) {
01808       static int primCount = 0;
01809 
01810       string dirName = Sct::SctNames::getTempDir() + "/PrimLists";
01811 
01812       // Ignore success (0) or failure
01813       int mkRet = mkdir(dirName.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
01814       if(mkRet != 0) {
01815     // It's OK if it already exists
01816     if(errno != EEXIST) {
01817       perror(("Failed to create PrimLists directory for OutList: " + dirName).c_str());
01818     }
01819       }
01820 
01821       char *saveDir = getcwd(NULL, 0);
01822 
01823       int chRet = chdir(dirName.c_str());
01824       if(chRet != 0) {
01825     perror("Failed to create PrimLists directory for OutList");
01826       }
01827 
01828       char fileName[100];
01829       sprintf(fileName, "OutLists_%05d.bin", primCount++);
01830       ofstream fout(fileName, ios::binary | ios::trunc);
01831       fout.write((char*)result, length*4);
01832 
01833       int chRet2 = chdir(saveDir);
01834       if(chRet2 != 0) {
01835     perror("Failed to change back to saved directory");
01836       }
01837 
01838       free(saveDir);
01839     }
01840 
01841     if(checkDebugOption(DEBUG_PRINT_OUT_PRIM)) {
01842     // Pick between log and cout
01843       if(checkDebugOption(DEBUG_LOG_PRINT_PRIM)) {
01844         ::SctApi::printOutList(result, length, false, 0, log(), 
01845                                checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01846       } else {
01847         ::SctApi::printOutList(result, length, false, 0, cout, 
01848                                checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01849       }
01850     }
01851   } else {
01852     cout << "Request for non-existent crate " << m_id->ucid() << endl;
01853     return NULL;
01854   }
01855 
01856   return result;
01857 }
01858 
01859 /* Get a message from a ROD text buffer
01860    Returns whether the action was completed
01861 */
01862 bool SctApi::getRodMessage(unsigned int rod,
01863                            char *buffer, unsigned long &length) {
01864   {
01865     boost::mutex::scoped_lock lock(log().mutex());
01866     log() << "Get message\n";
01867   }
01868   if(getCrate()) {
01869     return getCrate()->getRodMessage(rod, buffer, length);
01870   } else {
01871     buffer[0] = 0;
01872     length = 0;
01873     return false;
01874   }
01875 }
01876 
01877 // Get ID number of module
01878 UINT32 SctApi::findModule(string sn) { 
01879   {
01880     boost::mutex::scoped_lock lock(log().mutex());
01881     log() << "findModule " << sn << endl;
01882   }
01883 
01884   unsigned int partition, crate, rod, channel;
01885 
01886   try {
01887     unsigned int mur, module;
01888     config->translateFromSN(sn, mur, module);
01889     config->translateToROD(mur, module, partition, crate, rod, channel);
01890   } catch(ConfigurationException &c) {
01891     cout << "Module not found\n";
01892     return BAD_MODULE;
01893   }
01894 
01895   return packpcrc(partition, crate, rod, channel);
01896 }
01897 
01898 string SctApi::convertToString(UINT32 mid) {
01899   {
01900     boost::mutex::scoped_lock lock(log().mutex());
01901     log() << "convertToString " << mid << endl;
01902   }
01903 
01904   unsigned int partition, crate, rod, channel;
01905   getpcrc(mid, partition, crate, rod, channel);
01906 
01907   if(channel >= 48) {
01908     return "Off-ROD       ";
01909   }
01910 
01911   string sn;
01912 
01913   try {
01914     unsigned int mur, module;
01915     config->translateFromROD(partition, crate, rod, channel, mur, module);
01916     config->translateToSN(mur, module, sn);
01917   } catch(ConfigurationException &c) {
01918     cout << "Module not found\n";
01919     return "BAD_MODULE    ";
01920   }
01921 
01922   return sn;
01923 }
01924 
01925 UINT32 SctApi::findModule(INT32 mur, INT32 module) {
01926   {
01927     boost::mutex::scoped_lock lock(log().mutex());
01928     log() << "findModule " << mur << " " << module << endl;
01929   }
01930 
01931   unsigned int partition, crate, rod, channel;
01932 
01933   try {
01934     config->translateToROD(mur, module,
01935                            partition, crate, rod, channel);
01936   } catch(ConfigurationException &c) {
01937     cout << "Module not found\n";
01938     return BAD_MODULE;
01939   }
01940 
01941   return packpcrc(partition, crate, rod, channel);
01942 }
01943 
01944 pair<INT32, INT32> SctApi::convertToMUR(UINT32 mid) {
01945   {
01946     boost::mutex::scoped_lock lock(log().mutex());
01947     log() << "convertToMUR " << mid << endl;
01948   }
01949 
01950   unsigned int partition, crate, rod, channel;
01951   getpcrc(mid, partition, crate, rod, channel);
01952 
01953   UINT32 mur;
01954   UINT32 module;
01955 
01956   try {
01957     config->translateFromROD(partition, crate, rod, channel, mur, module);
01958   } catch(ConfigurationException &c) {
01959     cout << "Module not found\n";
01960     return make_pair(BAD_MODULE, 0);
01961   }
01962 
01963   return make_pair(mur, module);
01964 }
01965 
01966 UINT32 SctApi::findBarrelModule(INT32 barrel, INT32 row, INT32 number) {
01967   {
01968     boost::mutex::scoped_lock lock(log().mutex());
01969     log() << "findBarrelModule " << barrel << " " << row << " " << number << endl;
01970   }
01971 
01972   unsigned int partition, crate, rod, channel;
01973 
01974   try {
01975     unsigned int mur, module;
01976     config->translateFromBarrel(barrel, row, number, mur, module);
01977     config->translateToROD(mur, module,
01978                            partition, crate, rod, channel);
01979   } catch(ConfigurationException &c) {
01980     cout << "Module not found\n";
01981     return BAD_MODULE;
01982   }
01983 
01984   return packpcrc(partition, crate, rod, channel); 
01985 }
01986 
01987 void SctApi::convertToBarrelModule(UINT32 mid, UINT32 &barrel, UINT32 &row, int &number) { 
01988   {
01989     boost::mutex::scoped_lock lock(log().mutex());
01990     log() << "convertToBarrelModule " << mid << endl;
01991   }
01992 
01993   unsigned int partition, crate, rod, channel;
01994   getpcrc(mid, partition, crate, rod, channel);
01995 
01996   try {
01997     unsigned int mur, module;
01998     config->translateFromROD(partition, crate, rod, channel, mur, module);
01999     config->translateToBarrel(mur, module, barrel, row, number);
02000   } catch(ConfigurationException &c) {
02001     cout << "Module not found\n";
02002 
02003     barrel = BAD_MODULE;
02004     return;
02005   }
02006 }
02007 
02008 UINT32 SctApi::findEndcapModule(INT32 disk, INT32 ring, INT32 number) {
02009   {
02010     boost::mutex::scoped_lock lock(log().mutex());
02011     log() << "findEndcapModule " << disk << " " << ring << " " << number << endl;
02012   }
02013   unsigned int partition, crate, rod, channel;
02014 
02015   try {
02016     unsigned int mur, module;
02017     config->translateFromEndcap(disk, ring, number, mur, module);
02018     config->translateToROD(mur, module,
02019                            partition, crate, rod, channel);
02020   } catch(ConfigurationException &c) {
02021     cout << "Module not found\n";
02022     return BAD_MODULE;
02023   }
02024 
02025   return packpcrc(partition, crate, rod, channel);
02026 }
02027 
02028 void SctApi::convertToEndcapModule(UINT32 mid, INT32 &disk, UINT32 &ring, UINT32 &number) {
02029   {
02030     boost::mutex::scoped_lock lock(log().mutex());
02031     log() << "convertToEndcapModule " << mid << endl;
02032   }
02033 
02034   unsigned int partition, crate, rod, channel;
02035   getpcrc(mid, partition, crate, rod, channel);
02036 
02037   try {
02038     unsigned int mur, module;
02039     config->translateFromROD(partition, crate, rod, channel, mur, module);
02040     config->translateToEndcap(mur, module, disk, ring, number);
02041   } catch(ConfigurationException &c) {
02042     cout << "Module not found\n";
02043     disk = BAD_MODULE;
02044     return;
02045   }
02046 }
02047 
02048 #warning "These should be due to notifications from the configuration???"
02049 
02050 void SctApi::loadConfiguration() {
02051   {
02052     boost::mutex::scoped_lock lock(log().mutex());
02053     log() << "loadConfiguration (default)\n";
02054   }
02055 
02056   cout << "Load configuration\n";
02057 #warning "Using feature of ConfigurationXmlImpl"
02058   loadConfiguration("");
02059 }
02060 
02061 void SctApi::loadConfiguration(string filename) {
02062   {
02063     boost::mutex::scoped_lock lock(log().mutex());
02064     log() << "loadConfiguration (" << filename << ")\n";
02065   }
02066 
02067   m_is_initialised=false;
02068   
02069   try {
02070     cout << "Load configuration\n";
02071     config->loadConfiguration(filename); 
02072   } catch(ConfigurationException &c) {
02073     cout << "Problem loading new configuration, check configuration service\n";
02074   }
02075 
02076   cout << "Remove module configuration cache\n";
02077 
02078   {
02079     boost::mutex::scoped_lock lock(moduleMapAccess);
02080     moduleMap.clear();
02081   }
02082 
02083   loadModuleConfigurations();
02084 }
02085 
02086 unsigned SctApi::preloadModuleConfigurations(){
02087   unsigned modulecount=0;
02088   unsigned partition = ucid().partition();
02089   unsigned crate = ucid().crate();
02090   list<unsigned int> rods;
02091   try {
02092     rods = config->listRodsInCrate(partition, crate);
02093   } catch(ConfigurationException &c) {
02094     cout << "No RODs in this crate\n";
02095     cout << c.what() << endl;
02096     return 0;
02097   }
02098   
02099   for(list<unsigned int>::const_iterator r=rods.begin(); 
02100       r!=rods.end(); 
02101       r++) {
02102     RodLabel rl(partition, crate, *r);
02103     {
02104       boost::recursive_mutex::scoped_lock lock(rodInfoListAccess);
02105       if (rodInfoList.find(rl)==rodInfoList.end()){
02106     RodInfo newInfo;
02107     rodInfoList.insert(make_pair(rl, newInfo));
02108       }
02109     }
02110 
02111     list<unsigned int> MURs;
02112     try {
02113       MURs = config->listMURSInRod(partition, crate, *r);
02114     } catch(ConfigurationException &c) {
02115       cout << "No MURs for this ROD\n";
02116       cout << c.what() << endl;
02117       continue;
02118     }
02119     
02120     for(list<unsigned int>::const_iterator mur=MURs.begin(); 
02121         mur!=MURs.end(); 
02122         mur++) {
02123 
02124       list<string> modules;
02125       try {
02126         modules = config->listModulesInMUR(partition, *mur);
02127       } catch(ConfigurationException &c) {
02128         cout << "No modules for this MUR\n";
02129         cout << c.what() << endl;
02130         continue;
02131       }
02132 
02133       for(list<string>::const_iterator m=modules.begin(); 
02134           m!=modules.end(); 
02135           m++) {
02136           if (m_preloadModuleConfigurationsStop) return modulecount;
02137           if (!initialiseModule(*m, false))++modulecount;
02138       }
02139     } 
02140   }
02141   return modulecount;
02142 }
02143 
02144 int SctApi::loadModuleConfigurations() {
02145   int moduleConfigurations = 0;
02146 
02147   // For each ROD
02148   for(list<RodLabel>::const_iterator rl = rodList.begin();
02149       rl!=rodList.end();
02150       rl++){
02151     list<unsigned int> MURs;
02152     try {
02153       MURs = config->listMURSInRod(rl->partition, rl->crate, rl->rod);
02154     } catch(ConfigurationException &c) {
02155       cout << "No MURs for this ROD\n";
02156       cout << c.what() << endl;
02157       continue;
02158     }
02159 
02160     for(list<unsigned int>::const_iterator mur=MURs.begin(); 
02161         mur!=MURs.end(); 
02162         mur++) {
02163 
02164       list<string> modules;
02165       try {
02166         modules = config->listModulesInMUR(rl->partition, *mur);
02167       } catch(ConfigurationException &c) {
02168         cout << "No modules for this MUR\n";
02169         cout << c.what() << endl;
02170         continue;
02171       }
02172 
02173       for(list<string>::const_iterator m=modules.begin(); 
02174           m!=modules.end(); 
02175           m++) {
02176         if(!initialiseModule(*m)) {
02177           moduleConfigurations ++;
02178         }
02179       }
02180     }
02181   }
02182 
02183   cout << "Setup for calibration...\n";
02184   calib_init();
02185 
02186   return moduleConfigurations;
02187 }
02188 
02189 void SctApi::storeModuleConfigurations(BankType bank) {
02190   for(std::map<UINT32, ABCDModule>::const_iterator i = moduleMap.begin(); 
02191       i != moduleMap.end(); 
02192       i++) {
02193     UINT32 mid=i->first;
02194     std::string sn = "unknown";
02195     try{
02196       sn = convertToString(mid);
02197       boost::shared_ptr<const SctApiConfigCache::ModuleBanks> banks = module_cache.getFromMid(mid);
02198       if (!banks.get()) throw SctApiException("Cant save - no banks for this module");
02199       boost::shared_ptr<const ABCDModule> module = banks->get(bank);
02200       if (!module.get()) throw SctApiException("Cant save - this bank dosent exist for this module");
02201       config->configureModuleFromStructure(sn, *module);
02202     }catch(std::exception& e){
02203       if (mrs){
02204     *mrs << "CONFIG_SAVE_ERROR" << MRS_TEXT(e.what()) << MRS_QUALIF("SCTAPI")
02205          << MRS_PARAM<int>("mid", mid) << MRS_PARAM<int>("bank", bank) 
02206          << MRS_PARAM<const char*>("sn",sn.c_str()) << ENDM;
02207       }
02208     }
02209   }
02210 }
02211 
02212 void SctApi::storeBOCConfigurations()
02213 {
02214   log() << "Storing BOC configurations" << endl;
02215   try{
02216     // This could use SctApi's own rodList instead?
02217     Crate* the_crate = getCrate();
02218     const list<unsigned> rods = the_crate->getListOfRods();
02219     
02220     for (list<unsigned>::const_iterator ri=rods.begin(); ri!=rods.end(); ++ri){
02221       const unsigned rod=*ri;
02222       BOCGlobalConfig global = the_crate->currentBOCRegisters(rod);
02223       config->configureBOC(prt(), crt(), rod, global);      
02224       
02225       vector<BOCChannelConfig> channels = currentBOCSetup(rod); 
02226       for(int ich=0; ich<48; ich++){
02227     try {
02228       unsigned MUR=0, position=0;
02229       config->translateFromROD(prt(), crt(), rod, ich, MUR, position);
02230       config->configureBOCChannel(MUR, position, channels[ich]);
02231     } catch(ConfigurationException &c) {
02232       // No module mapped to BOC channel
02233     }
02234       }
02235     }
02236   }catch(std::exception& e){
02237     log() << e.what() << endl;
02238     if(mrs) {
02239       *mrs << "STORE_BOC_ERROR" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
02240        << MRS_TEXT(e.what()) << ENDM;
02241     }
02242   }
02243 }
02244 
02245 void SctApi::configureBOC(unsigned int rod) {
02246   {
02247     boost::mutex::scoped_lock lock(log().mutex());
02248     log() << "ConfigureBOC called\n";
02249     log() << "\t TIME " << second_clock::universal_time() << endl;
02250   }
02251 
02252   try {
02253     if(getCrate())
02254       getCrate()->configureBOC(rod);
02255   } catch(CrateException &c) {
02256     throw SctApiException(c);
02257   }
02258 }
02259 
02260 std::vector<double> SctApi::getBOCMonitorArray(unsigned int rod) {
02261   {
02262     boost::mutex::scoped_lock lock(log().mutex());
02263     log() << "getBOCMonitorArray called\n";
02264   }
02265 
02266   if(getCrate()) 
02267     return getCrate()->getBOCMonitorArray(rod);
02268   else
02269     throw SctApiException("Failed to getBOCMonitorArray");
02270 }
02271 
02272 std::string SctApi::status() {
02273   std::ostringstream oss;
02274   {
02275     boost::mutex::scoped_lock lock(log().mutex());
02276     log() << "print all status\n";
02277   }
02278 
02279   oss << "SCTAPI status:\n";
02280   oss << "Run " << runNumber << " Scan " << scanNumber << endl;
02281 
02282 #if USE_THREADS
02283   oss << "Primitive thread engine enabled\n";
02284 #else
02285   oss << "Primitive thread engine disabed (dangerous in IPC)\n";
02286 #endif
02287 #if USE_SCAN_THREAD
02288   oss << "Scan polling thread enabled\n";
02289   oss << "Initialisation complete? " << (m_is_initialised ? "Y" : "N" ) << " \n";
02290 #else
02291   oss << "Scan polling thread disabled (doScan can timeout with IPC)\n";
02292 #endif
02293   if(mrs) {
02294     *mrs << "SCTAPI_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
02295          << MRS_PARAM<int>("run", runNumber) << MRS_PARAM<int>("scan", scanNumber) 
02296          << MRS_TEXT("Run numbers") << ENDM;
02297   }
02298 
02299   if(!getCrate()) {
02300     if(mrs) {
02301       *mrs << "SCTAPI_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
02302            << MRS_TEXT("No crates loaded") << ENDM;
02303     }
02304   }
02305   
02306   //  for(map<pair<unsigned int, unsigned int>, Crate* >::const_iterator crate = crateMap.begin();
02307   //   crate != crateMap.end();
02308   //   crate++)
02309   {
02310     oss << "Crate: " << ucid() << " to std::out...\n";
02311     oss << getCrate()->status();
02312   }
02313 
02314   oss << "Module configuration for " << moduleMap.size() << " modules:\n";
02315   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
02316       mi!=moduleMap.end();
02317       mi ++) {
02318     UINT32 mid = mi->first;
02319 
02320     string sn = convertToString(mid);
02321     ABCDModule *moduleConf = lookupConfig(mid);
02322     int group = moduleConf->groupId;
02323     int select = moduleConf->select;
02324     int prim = moduleConf->pTTC;
02325     int redun = moduleConf->rTTC;
02326     int link0 = moduleConf->rx[0];
02327     int link1 = moduleConf->rx[1];
02328 
02329     // Reverse translate formatter encoding
02330     if(link0 != DATA_LINK_OFF) 
02331       link0 = (link0/16) * 12 + link0%16;
02332     if(link1 != DATA_LINK_OFF) 
02333       link1 = (link1/16) * 12 + link1%16;
02334 
02335     oss.width(8);
02336     oss << mid << " " << sn << " Group: " << group << " Select: " << select;
02337     oss << "\t Pr: ";
02338     oss.width(2);
02339     oss << prim << " Red: ";
02340     oss.width(3);
02341     oss << redun << " Link 0/1: ";
02342     oss.width(3);
02343     oss << link0 << " ";
02344     oss.width(3);
02345     oss << link1 << endl;
02346 
02347     if(mrs) {
02348       *mrs << "MODULE_INFO" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
02349            << MRS_PARAM<const char *>("sn",sn.c_str()) << MRS_PARAM<int>("internalId",mid) 
02350            << MRS_PARAM<int>("group",group) << MRS_PARAM<int>("select",select)  
02351            << MRS_PARAM<int>("primary",prim) << MRS_PARAM<int>("redundancy",redun) 
02352            << MRS_PARAM<int>("link0rx",link0) << MRS_PARAM<int>("link1rx",link1) 
02353            << MRS_TEXT("Module status ")
02354            << ENDM;
02355     }
02356   }
02357 
02358   if(mrs) {
02359     *mrs << "SCTAPI_STATUS" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
02360          << MRS_PARAM<int>("run", runNumber) << MRS_PARAM<int>("scan", scanNumber) 
02361          << MRS_TEXT("Run numbers") << ENDM;
02362   }
02363   
02364   std::list<std::string> enabledDebug = listEnabledDebugOptions();
02365   if (enabledDebug.empty()){
02366     oss << "No debug options currently enabled\n";
02367   }else{
02368     oss << "Debug options currently enabled:" << endl;
02369     for (std::list<std::string>::const_iterator i=enabledDebug.begin(); i!=enabledDebug.end(); ++i){
02370       oss << "\t"<< *i << "\n"; 
02371     }
02372   }
02373   return oss.str();
02374 }
02375 
02376 // ****  Histogramming  ****
02377 void SctApi::defaultScan(int type) {
02378   {
02379     boost::mutex::scoped_lock lock(log().mutex());
02380     log() << "Send default scan number " << type << endl;
02381   }
02382   ScanDefImpl scan;
02383 
02384   long *evSetup;
02385   long *histSetup;
02386   long *histStart;
02387 
02388   shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
02389 
02390   int histStartLength;
02391 
02392   switch(type) {
02393   default:
02394   case 0:
02395     {
02396       // Event Trap Setup
02397       long setup[24] = {0x1,   0, 0x2000, 0, 
02398                         0x3, 0x1,      0, 0,
02399                           0,   0,      0, 0,
02400                         0x3,   0,      0, 1,               // Config, exclusion
02401                         0x1,   0,      0, 1,               // function, match
02402                           1,   0,      0, 0};              // modulus, remainder
02403 
02404       evSetup = new long[24];
02405       for(int i=0; i<24; i++) evSetup[i] = setup[i];
02406 
02407       // Setup histogram
02408       long setupH[] = {
02409         0x20d2000, 0, 0x60, 0x01010000, 0x20200101, 1, 0, 1, 
02410         0,         0,    0, 0x03f00000, 0x30f01000};
02411 
02412       histSetup = new long[13];
02413       for(int i=0; i<13; i++) histSetup[i] = setupH[i];
02414 
02415       // Start histogram
02416       long startHist[4 + 63] = {
02417         16, 107, 1, 1,
02418 
02419         // Task params
02420         // 
02421         0x01010001, 0x000f0001, 0x08040201,        0xf, 0x020d2000, 0x00200101, 0x0100000f,       1000, 
02422                 50,        0x0, 0x40a00000, 0x40a00000, 0x41200000, 0x40a00000, 0x42c80000, 0x40200000, 
02423         0x43160000, 0x40a00000, 0x43480000, 0x40a00000, 0x40a00000, 0x40a00000, 0x41200000, 0x40a00000,
02424 
02425         0x42c80000, 0x40200000, 0x43160000, 0x40a00000, 0x43480000, 0x40a00000,        0x0,        0x0,
02426         0x0070006a, 0x00640065, 0x00640064, 0x00000000, 0x81,              0x0,        0x0,        0x0,
02427         0x0,      // End of trigger sequence (1)
02428         0x00640064, 0x00640064, 0x00640064, 0, 0, 0, 0, 
02429         0, 0,      // End of trigger sequence (2)
02430         0,         // incCmd (2 bytes) etc 
02431         0, 0,      // incData
02432         0, 0, 0,
02433         0, 0, 0, 0, 0,      // End of control data (rest is up to max task structure size)
02434       };
02435 
02436       histStart = new long[4+63];
02437       for(int i=0; i<4+63; i++) histStart[i] = startHist[i];
02438 
02439       histStartLength = 67;
02440     }
02441     break;
02442   case 1:
02443     // A short nmask scan on module 0
02444     {
02445       // Event Trap Setup
02446       long setup[24] = {
02447         0x00000001, 0x00000000, 0x00002000, 0x00000000, 0x00000003, 0x00000000, 0x00000001, 0x00000000,
02448         0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 
02449         0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000};
02450 
02451       evSetup = new long[24];
02452       for(int i=0; i<24; i++) evSetup[i] = setup[i];
02453 
02454       // Setup histogram
02455       long setupH[] = {
02456         0x020d2000, 0x00000000, 0x00000008, 0x18090000, 0x00200101, 0x00000001, 0x00000000, 0x00000001, 
02457         0x00000000, 0x00000000, 0x00000000, 0x03f00000, 0x03f01000};
02458 
02459       histSetup = new long[13];
02460       for(int i=0; i<13; i++) histSetup[i] = setupH[i];
02461 
02462       // Start histogram
02463       long startHist[79] = {
02464         0x18090001, 0x000f0001, 
02465         0x000000ff, 0x0000f00f, 0x020d2000, 0x00200101, 0x0000000f, 0x0000040a, 0x00000008, 0x00000000, 
02466         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
02467         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
02468         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0070006a, 0x00640065, 
02469         0x00640064, 0x00000000, 0x00000082, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00640064, 
02470         0x00640064, 0x00640064, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
02471         0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
02472         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41800000, 0x42000000, 
02473         0x42400000, 0x42800000, 0x42a00000, 0x42c00000, 0x42e00000, 0x00000000, 0x41800000, 0x42000000, 
02474         0x42400000, 0x42800000, 0x42a00000, 0x42c00000, 0x42e00000 
02475       };
02476 
02477       histStart = new long[79];
02478       for(int i=0; i<79; i++) histStart[i] = startHist[i];
02479 
02480       histStartLength = 79;
02481 
02482 
02483       /* 000000ff 00000001 00000006 0000006f 0000001c 00000000 00000003 00000067 
02484 
02485          00000001 00000000 00002000 00000000 00000003 00000000 00000001 00000000 
02486          00000000 00000000 00000001 00000002 00000003 00000000 00000000 00000001 
02487          00000001 00000000 00000000 00000000 00000001 00000000 00000000 00000000 
02488 
02489          00000012 00000001 00002007 00000067 00000000 0000000a ffffffff ffffffff 
02490          0000000a 00000001 00000001 0000006f 00000004 00000000 00001000 00000065 
02491          0000000a 0000100e 00000007 00000002 00002008 00000067 00000000 00000001 
02492          00000001 00000066 00000001 00002007 00000067 00000000 0000005e ffffffff 
02493          ffffffff 0000005e 00000004 00000002 0000006f 00000011 00000002 00001002 
02494          00000068 020d2000 00000000 00000008 18090000 00200101 00000001 00000000 
02495          00000001 00000000 00000000 00000000 03f00000 03f01000 
02496 
02497          00000047 00000003 
02498          0000000c 00000065 00000020 00000064 00000001 00000001 00000000 00000000 
02499          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02500          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02501          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02502          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02503          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02504          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02505          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02506          00000000 00000000 00000000 00000000 00000000 0000005e 1a242170 00000007 
02507          00000002 00002008 00000067 00000000 00000001 00000001 00000057 00000000 
02508          0000000c 00000065 00000010 0000006b 00000001 00000001 18090001 000f0001 
02509          000000ff 0000f00f 020d2000 00200101 0000000f 0000040a 00000008 00000000 
02510          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02511          00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
02512          00000000 00000000 00000000 00000000 ffffffff ffffffff 0070006a 00640065 
02513          00640064 00000000 00000082 00000000 00000000 00000000 00000000 00640064 
02514          00640064 00640064 00000000 00000000 00000000 00000000 00000000 00000000 
02515          00000000 00000000 00000000 0000000f 00000000 00000000 00000000 00000000 
02516          00000000 00000000 00000000 00000000 00000000 00000000 41800000 42000000 
02517          42400000 42800000 42a00000 42c00000 42e00000 00000000 41800000 42000000 
02518          42400000 42800000 42a00000 42c00000 42e00000 000000ff 1a3ff509 
02519       */
02520       break;
02521     }
02522   }
02523 
02524   if(!getCrate() || !getCrate()->RODPresent(0)) {
02525     cout << "No configured ROD ! Aborting default scan\n";
02526     if(mrs) {
02527       *mrs << "ROD_NONEXIST" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
02528            << MRS_PARAM<int>("crate", 0) 
02529            << MRS_PARAM<int>("rod", 0)
02530            << MRS_TEXT("Aborting default scan (ROD not configured)") << ENDM;
02531     }
02532 
02533     return;
02534   }
02535 
02536   if(!getCrate()->checkBOCLasersOn(0)) {
02537     cout << "Trying to send default scan using BOC that has its lasers cut out (continuing)\n";
02538     if(mrs) {
02539       *mrs << "BOC_INTERLOCKED" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
02540            << MRS_PARAM<int>("crate", 0) 
02541            << MRS_PARAM<int>("rod", 0)
02542            << MRS_TEXT("Default scan continuing even though BOC interlocked") << ENDM;
02543     }
02544   }
02545 
02546   primList->addPrimitive(RodPrimitive(4+24, 1, 3, 103, evSetup),
02547                          evSetup);
02548 
02549   // Start event trap
02550   long trap[0] = {};
02551   shared_ptr<PrimListWrapper> sPrimList(new PrimListWrapper(2));
02552   sPrimList->addPrimitive(RodPrimitive(4, 0, 4096, 101, trap),
02553                           trap);
02554 
02555   PrimBuilder &builder = PrimBuilder::instance();
02556 
02557   builder.slavePrimList(primList, sPrimList, 0, true, true);
02558 
02559   // Can clear slave list because its fully built!
02560   sPrimList->clear();
02561   sPrimList->addPrimitive(RodPrimitive(4 + 13 /* + 2*3 */ , 3, 4098, 104, histSetup),
02562                           histSetup);
02563   builder.slavePrimList(primList, sPrimList, 0, true, true);
02564   
02565   long task[] = {32, 100, 1, 1, 0, 0};
02566   sPrimList->clear();
02567   sPrimList->addPrimitive(RodPrimitive(4 + 6, 4, 12, 101, task),
02568                           task);
02569   builder.slavePrimList(primList, sPrimList, 0, true, true);
02570 
02571   primList->addPrimitive(RodPrimitive(histStartLength + 4, 3, 12, 101, histStart),
02572                          histStart);
02573 
02574   {
02575     boost::mutex::scoped_lock lock(log().mutex());
02576     log() << "Send default scan list\n";
02577   }
02578   sendPrimList(0, primList);
02579   awaitResponse(0, 2);
02580 
02581 
02582   // Get result
02583   unsigned long length;
02584 
02585   unsigned long *result = getResponse(0, length);
02586 
02587   if(result) {
02588     cout << "Got response from default scan setup\n";
02589     // Pick between log and cout
02590     if(checkDebugOption(DEBUG_LOG_PRINT_PRIM)) {
02591       ::SctApi::printOutList(result, length, true, 0, log(), 
02592                    checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
02593     } else {
02594       ::SctApi::printOutList(result, length, true, 0, cout, 
02595                    checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
02596     }
02597 
02598     delete [] result;
02599   } else {
02600     cout << "No response from default scan setup\n";
02601   }
02602 
02603   // Poll histogram
02604 //    pollHistogramming(extra, scan.getScanPoints1().size(), scan.getNTrigs(), 5);
02605 
02606 //    // Read histogram
02607 //  #ifdef USE_IS
02608 //    readHistogramsToIS(scan, extra);
02609 //  #endif
02610 //    readHistogramsToFile(scan, extra);
02611 }
02612 
02613 void SctApi::tidyHistogramming() {
02614   {
02615     boost::mutex::scoped_lock lock(log().mutex());
02616     log() << "Brutal histogram stopping\n";
02617   }
02618 
02619   shared_ptr<PrimListWrapper> primList(new PrimListWrapper(2));
02620 
02621   PrimBuilder &builder = PrimBuilder::instance();
02622 
02623   builder.taskOp(primList, HISTOGRAM_CTRL_TASK, TASK_STOP, 0);
02624 
02625   for(list<RodLabel>::const_iterator rl = rodList.begin();
02626       rl!=rodList.end();
02627       rl++){
02628 
02629     unsigned int rod = rl->rod;
02630 
02631     {
02632       boost::mutex::scoped_lock lock(log().mutex());
02633       log() << "Tidy histogram on (" << ucid() << ", " << rod << ")\n";
02634       log() << "Stop HCT\n";
02635     }
02636     sendPrimList(rod, primList);
02637 
02638     awaitResponse(rod, 2);
02639     primList->clear();
02640 
02641     cout << "Done kill control task\n";
02642 
02643     for(int slaveNumber=0; slaveNumber<4; slaveNumber++) {
02644       shared_ptr<PrimListWrapper> slList(new PrimListWrapper(1));
02645 
02646       // Stop Slave histogramming task
02647 
02648       builder.taskOp(slList, HISTOGRAM_TASK, TASK_STOP, 0);
02649 
02650       builder.slavePrimList(primList, slList, slaveNumber, true, true);
02651       {
02652         boost::mutex::scoped_lock lock(log().mutex());
02653         log() << "Stop histo task (" << slaveNumber << ")\n";
02654       }
02655       sendPrimList(rod, primList);
02656       awaitResponse(rod, 2);
02657       slList->clear();
02658       primList->clear();
02659 
02660       cout << "Done kill histogram task\n";
02661 
02662       builder.stopEvTrap(slList);
02663 
02664       builder.slavePrimList(primList, slList, slaveNumber, true, true);
02665       {
02666         boost::mutex::scoped_lock lock(log().mutex());
02667         log() << "Stop ETS (" << slaveNumber << ")\n";
02668       }
02669       sendPrimList(rod, primList);
02670 
02671       awaitResponse(rod, 2);
02672       primList->clear();
02673 
02674       cout << "Done kill event trapping\n";
02675     }
02676 //     sendPrimList(rod, primList);
02677 //    awaitResponse(rod, 2);
02678   }
02679 }
02680 
02681 void SctApi::abortScan() {
02682   if(scanController) 
02683     scanController->abort();
02684 }
02685 
02686 void SctApi::rodMode(unsigned int rod,
02687                      int mode, int flag, int fifoSetup, int nBits, int delay, int message) {
02688   shared_ptr<PrimListWrapper> rodModeList(new PrimListWrapper(2));
02689 
02690   PrimBuilder::instance().rodMode(rodModeList, mode, flag, fifoSetup, nBits, delay, message);
02691 
02692   sendPrimList(rod, rodModeList);
02693 
02694   int responseCode = awaitResponse(rod, 1);
02695 
02696   if(responseCode != 0) {
02697     cout << "Set ROD mode failed!\n";
02698   }
02699 }
02700 
02701 void SctApi::setupModuleMask(unsigned int rod,
02702                              int port, int slvs) {
02703   shared_ptr<PrimListWrapper> maskList(new PrimListWrapper(1));
02704 
02705   setupModuleMask(port, slvs, maskList);
02706 
02707   sendPrimList(0, maskList);
02708   int responseCode = awaitResponse(0, 10);
02709 
02710   if(responseCode != 0) {
02711     cout << "Module mask setup unsuccessful\n";
02712   }
02713 }
02714 
02715 void SctApi::setupModuleMask(int port, int slvs, boost::shared_ptr<PrimListWrapper> primList) { 
02716   PrimBuilder::instance().masksFromConfig(primList, port);
02717   PrimBuilder::instance().masksToSlaves(primList, slvs);
02718 }
02719 
02720 void SctApi::calib_init() {
02721   // Put ROD in useful mode for running calibrations 
02722 #if (R_MODULE_MASK < 101)
02723   #error "Unsupported old MODULE_MASK version"
02724 #else 
02725   shared_ptr<PrimListWrapper> calibList(new PrimListWrapper(1));
02726 
02727 #if USE_DUAL_PORTS
02728   // Set up module masks for both ports
02729   setupModuleMask(SP_BOTH, 0xf, calibList);
02730 #else
02731   setupModuleMask(SP0, 0xf, calibList);
02732 #endif
02733 
02734   PrimBuilder &builder = PrimBuilder::instance();
02735   builder.writeRegister(calibList, RRIF_CMND_0, 0, 8, 0xff);    // Reset everything
02736   builder.writeRegister(calibList, RRIF_CMND_0, 0, 8, 0x78);
02737 
02738   if(synchSendPrimListAll(calibList) != 0) {
02739     cout << "Calib list moduleMask failed!\n";
02740   }
02741 
02742   shared_ptr<PrimListWrapper> rodModeList(new PrimListWrapper(1));
02743   PrimBuilder::instance().rodMode(rodModeList, CALIBRATION_MODE + CALIBRATION_SLINK_OVERRIDE_MODE, 
02744                                   0, 1, 1, 1, 1);
02745 
02746   if(synchSendPrimListAll(rodModeList) != 0) {
02747     cout << "Calib list Rod mode on failed!\n";
02748   }
02749 
02750 
02751   // Allow user to turn off slink in calibration mode
02752   shared_ptr<PrimListWrapper> postRodModeList(new PrimListWrapper(1));
02753   if(checkDebugOption(DEBUG_CALIB_NO_SLINK)) {
02754     builder.writeRegister(postRodModeList, RTR_CMND_STAT, RTR_INHIBIT_SLNK_WE_O, 1, 1);
02755   } else {
02756     builder.writeRegister(postRodModeList, RTR_CMND_STAT, RTR_INHIBIT_SLNK_WE_O, 1, 0);
02757   }
02758 //   if(checkDebugOption(DEBUG_CALIB_RTR_STOP_OUTPUT)) {
02759 //     builder.writeRegister(postRodModeList, RTR_CMND_STAT, RTR_STOP_OUTPUT_O, 1, 1);
02760 //   } else {
02761 //     builder.writeRegister(postRodModeList, RTR_CMND_STAT, RTR_STOP_OUTPUT_O, 1, 0);
02762 //   }
02763   if(synchSendPrimListAll(postRodModeList) != 0) {
02764     cout << "Calib init post rod mode failed!\n";
02765   }
02766 #endif  
02767 }
02768 
02769 void SctApi::print_calib(unsigned int rod) {
02770 #ifndef FMT_LINK_EN
02771   cout << "Register ids not known\n";
02772 #else
02773   cout << "Formatters\n";
02774 
02775   cout << hex;
02776 
02777   cout << " Enables\n";
02778 
02779   for(int a=0; a<8; a++) {
02780     int data = readRODRegister(rod, FMT_LINK_EN(a)) & 0xffff;
02781     cout.width(4);
02782     cout << data << " ";
02783   }
02784   cout << endl;
02785 
02786   cout << " Expanded\n";
02787   for(int a=0; a<8; a++) {
02788     int data = readRODRegister(rod, FMT_EXP_MODE_EN(a)) & 0xffff;
02789     cout.width(4);
02790     cout << hex;
02791     cout << data << " ";
02792   }
02793   cout << endl;
02794 
02795 //   cout << " Config mode\n";
02796 //   for(int a=0; a<8; a++) {
02797 //     int data = readRegister(a+0x10) & 0xffff;
02798 //     cout.width(4);
02799 //     cout << hex;
02800 //     cout << data << " ";
02801 //   }
02802 //   cout << endl;
02803 
02804 //   cout << " Edge mode\n";
02805 //   for(int a=0; a<8; a++) {
02806 //     int data = readRegister(a+0x18) & 0xffff;
02807 //     cout.width(4);
02808 //     cout << hex;
02809 //     cout << data << " ";
02810 //   }
02811 //   cout << endl;
02812 
02813 //   cout << " Time out\n";
02814 //   for(int a=0; a<8; a++) {
02815 //     int data = readRegister(a+0x20, false) & 0xff;
02816 //     cout.width(4);
02817 //     cout << hex;
02818 //     cout << data << " ";
02819 //   }
02820 //   cout << endl;
02821 
02822 //   cout << " Overflow limit\n";
02823 //   for(int a=0; a<8; a++) {
02824 //     int data = readRegister(a+0x28, false) & 0x7ff;
02825 //     cout.width(4);
02826 //     cout << hex;
02827 //     cout << data << " ";
02828 //   }
02829 //   cout << endl;
02830 
02831 //   cout << " H/T limit\n";
02832 //   for(int a=0; a<8; a++) {
02833 //     int data = readRegister(a+0x30, false) & 0x3ff;
02834 //     cout.width(4);
02835 //     cout << hex;
02836 //     cout << data << " ";
02837 //   }
02838 //   cout << endl;
02839 
02840 //   cout << " ROD busy limit\n";
02841 //   for(int a=0; a<8; a++) {
02842 //     int data = readRegister(a+0x38, false) & 0x3ff;
02843 //     cout.width(4);
02844 //     cout << hex;
02845 //     cout << data << " ";
02846 //   }
02847 //   cout << endl;
02848 
02849 //   cout << " Diagnostic link to LEMO\n";
02850 //   for(int a=0; a<8; a++) {
02851 //     int data = readRegister(a+0x70, false) & 0xf;
02852 //     cout.width(4);
02853 //     cout << hex;
02854 //     cout << data << " ";
02855 //   }
02856 //   cout << endl;
02857 
02858 //   cout << " Diagnostic mode bits read enable\n";
02859 //   for(int a=0; a<8; a++) {
02860 //     int data = readRegister(a+0x78, false) & 0x1;
02861 //     cout.width(4);
02862 //     cout << hex;
02863 //     cout << data << " ";
02864 //   }
02865 //   cout << endl;
02866 
02867   cout << "Link oocupancies\n";
02868   for(int fmt=0; fmt<8; fmt++) {
02869     for(int link=0; link<12; link++) {
02870       int val = readRODRegister(rod, FMT_LINK_OCC_CNT(fmt, link)) & 0x7ff;
02871       cout << " ";
02872       Utility::printHex(val, 3);
02873     }
02874     cout << endl;
02875   }
02876 
02877   cout << " Timeout error\n";
02878   for(int a=0; a<8; a++) {
02879     int data = readRODRegister(rod, FMT_TIMEOUT_ERR(a)) & 0xfff;
02880     cout.width(4);
02881     cout << hex;
02882     cout << data << " ";
02883   }
02884   cout << endl;
02885 
02886   cout << " Overflow error\n";
02887   for(int a=0; a<8; a++) {
02888     int data = readRODRegister(rod, FMT_DATA_OVERFLOW_ERR(a)) & 0xfff;
02889     cout.width(4);
02890     cout << hex;
02891     cout << data << " ";
02892   }
02893   cout << endl;
02894 
02895   cout << " H/T error\n";
02896   for(int a=0; a<8; a++) {
02897     int data = readRODRegister(rod, FMT_HEADER_TRAILER_ERR(a)) & 0xfff;
02898     cout.width(4);
02899     cout << hex;
02900     cout << data << " ";
02901   }
02902   cout << endl;
02903 
02904   cout << " ROD busy error\n";
02905   for(int a=0; a<8; a++) {
02906     int data = readRODRegister(rod, FMT_ROD_BUSY_ERR(a)) & 0xfff;
02907     cout.width(4);
02908     cout << hex;
02909     cout << data << " ";
02910   }
02911   cout << endl;
02912 
02913 //   cout << " Parsing mode (1 = Raw, 0 = normal) \n";
02914 //   for(int a=0; a<8; a++) {
02915 //     int data = readRegister(a+0x100, false) & 0xfff;
02916 //     cout.width(4);
02917 //     cout << hex;
02918 //     cout << data << " ";
02919 //   }
02920 //   cout << endl;
02921 
02922 //   cout << " Formatter status\n";
02923 //   for(int a=0; a<8; a++) {
02924 //     int data = readRegister(a+0x108, false) & 0xffff;
02925 //     tapi.printHex(data, 4);
02926 //     cout << " ";
02927 // //     cout.width(4);
02928 // //     cout << hex;
02929 // //     cout << data << " ";
02930 //   }
02931 //   cout << endl;
02932 
02933 //   cout << " Formatter version\n";
02934 //   for(int a=0; a<8; a++) {
02935 //     int data = readRegister(a+0x110, false) & 0xffff;
02936 //     cout.width(4);
02937 //     cout << hex;
02938 //     cout << data << " ";
02939 //   }
02940 //   cout << endl;
02941 
02942 //   cout << "EFB version\n";
02943 //   readRegister(0x1b2);
02944 
02945 //   cout << "RTR version\n";
02946 //   readRegister(0x205);
02947 
02948   cout << "RRIF version\n";
02949   cout << readRODRegister(rod, RRIF_CODE_VERSION) << endl;
02950   cout << "RRIF status 0\n";
02951   cout << readRODRegister(rod, RRIF_STATUS_0) << endl;
02952   cout << "RRIF status 1\n";
02953   cout << readRODRegister(rod, RRIF_STATUS_1) << endl;
02954 
02955   cout << "RRIF command 0\n";
02956   cout << readRODRegister(rod, RRIF_CMND_0) << endl;
02957   cout << "RRIF command 1\n";
02958   cout << readRODRegister(rod, RRIF_CMND_1) << endl;
02959 
02960   cout << "Output masks\n";
02961   cout << " ";
02962   Utility::printHex(readRODRegister(rod, FE_CMND_MASK_0_LO), 8);
02963   cout << endl;
02964   cout << " ";
02965   Utility::printHex(readRODRegister(rod, FE_CMND_MASK_0_HI), 8);
02966   cout << endl;
02967   cout << " ";
02968   Utility::printHex(readRODRegister(rod, FE_CMND_MASK_1_LO), 8);
02969   cout << endl;
02970   cout << " ";
02971   Utility::printHex(readRODRegister(rod, FE_CMND_MASK_1_HI), 8);
02972   cout << endl;
02973 
02974   cout << "L1ID for ports 0 and 1\n";
02975   Utility::printHex(readRODRegister(rod, CAL_L1_ID_0), 8);
02976   Utility::printHex(readRODRegister(rod, CAL_L1_ID_1), 8);
02977   cout << "BCID for ports 0 and 1\n";
02978   Utility::printHex(readRODRegister(rod, CAL_BCID), 8);
02979 
02980   cout << dec;
02981 #endif
02982 }
02983 
02984 unsigned long SctApi::sendTimBurst(unsigned long count, int random, bool external) {
02985   return getCrate()->sendTimBurst(count, random, external);
02986 }
02987 
02988 unsigned long SctApi::sendTriggers(const Trigger* trig, unsigned long count, int scan_point){
02989   int random = trig->getRandom();
02990   double freq = trig->getFrequency();
02991   Trigger::Source source = trig->getSource();
02992   switch (source){
02993   case Trigger::SOURCE_TIM_INTERNAL:
02994   case Trigger::SOURCE_TIM_EXTERNAL:
02995     {
02996       bool use_sequencer = trig->timNeedsSequencer();
02997       bool external = (source==Trigger::SOURCE_TIM_EXTERNAL);
02998 
02999       // std::ios_base& std::internal(std::ios_base&)
03000       if (!external) {
03001     // set up frequencies
03002     timSetFrequency(trig->getFrequency(), timGetResetFrequency());
03003       }
03004 
03005       if (use_sequencer) {
03006     printf("Sending %d triggers using the sequencer, random=%d, external=%d\n",count,random,external);
03007     Trigger::TIMTriggers timTrigs = Trigger::convertToTIMTriggers(trig->getRODTriggers(scan_point));
03008     vector<unsigned> seq(timTrigs.size());
03009     for (unsigned i=0; i<timTrigs.size(); ++i){
03010       seq[i]=timTrigs[i];
03011     }
03012     timLoadSequence(seq);
03013     return timRunSequence(count, random, external);
03014       } else {
03015     printf("Sending %d triggers, random=%d, external=%d\n",count,random,external);
03016     return sendTimBurst(count, random, external);
03017       }
03018       break;
03019     }
03020   case Trigger::SOURCE_ROD:
03021     for(list<RodLabel>::const_iterator rl = rodList.begin();
03022     rl!=rodList.end();
03023     rl++){
03024 #warning "No parallelisation here yet AJB 2005-11-25"
03025       sendRodTrigger(rl->rod, trig, count, scan_point);
03026     }
03027     break;
03028   default:
03029     if (mrs) {
03030       *mrs << "TRIG_SOURCE_UNKNOWN" << MRS_TEXT("Trigger source may not be implimented yet") 
03031        << MRS_PARAM<int>("source",source) 
03032        << MRS_ERROR << ENDM;
03033     }else{
03034       std::cout << "Dont yet know how to send triggers from source : " << source 
03035         << " " << __FILE__ << ":" << __LINE__ << std::endl;
03036     }
03037     throw SctApiException("BadTrigger");
03038     break;
03039   }
03040 }
03041 
03042 void SctApi::sendRodTrigger(unsigned int rod, const Trigger *trig, unsigned long count, int scan_point) {
03043   {
03044     boost::mutex::scoped_lock lock(log().mutex());
03045     log() << "Send Trigger\n";
03046   }
03047 
03048   // Do we want to build and send on both streams?
03049   //  There's only one trigger, so not quite sure what this will do
03050   //  But we already send on both ports and that seems to work... ? (this method not used much)
03051   //  Should probably make the two consistent, so choose "BOTH"
03052 #if USE_DUAL_PORTS
03053   int serialPorts = SP_BOTH;
03054 #else
03055   int serialPorts = SP0;
03056 #endif
03057 
03058   long *data = new long[sizeof(BUILD_STREAM_IN)/4];
03059 
03060   BUILD_STREAM_IN &buildPrim = *(BUILD_STREAM_IN*)data;
03061 
03062 #if (R_BUILD_STREAM == 102)
03063   Trigger::RODTriggers points = trig->getRODTriggers(scan_point);
03064 
03065   for(int i=0; i<N_CMD_LIST_CMDS; i++) {
03066     buildPrim.cmdList.cmd[i] = NO_CMD;
03067     buildPrim.cmdList.data[i] = 0;
03068   }
03069   for(unsigned int i=0; i<points.size(); i++) {
03070     buildPrim.cmdList.cmd[i] = points[i].first;        // Set a trigger sequence
03071     buildPrim.cmdList.data[i] = points[i].second;      // Set a trigger sequence
03072   }
03073 
03074   buildPrim.port = serialPorts;
03075   buildPrim.reset = 1;
03076   buildPrim.chip = 63;
03077   buildPrim.fibre = 3;
03078   buildPrim.dataLen = 0;
03079   buildPrim.data = 0;    // Should be ignored?
03080  
03081   shared_ptr<PrimListWrapper> sendList(new PrimListWrapper(3));
03082 
03083   sendList->addPrimitive(RodPrimitive(4 + sizeof(BUILD_STREAM_IN)/4, 
03084                                       2, BUILD_STREAM, R_BUILD_STREAM, data),
03085                          data);
03086 #elif R_BUILD_STREAM == 101
03087 #error "Build stream not compiled (unsupported old version)" 
03088 #else   // Unknown R_BUILD_STREAM
03089 #error "Build stream not compiled (unknown primitive version, check primParams.h)" 
03090 #endif
03091 
03092 #if USE_DUAL_PORTS
03093   // Send both ports stream
03094   PrimBuilder::instance().sendStream(sendList, serialPorts, 0);
03095 #else
03096   // Confusingly this was already like this, much simpler to use serialPorts and 
03097   //  make it the same as the buildStream above though!
03098   PrimBuilder::instance().sendStream(sendList, SP_BOTH, 0);
03099 #endif
03100 
03101   for (unsigned i=0; i<count; ++i){
03102     sendPrimList(rod, sendList);
03103     
03104     int responseCode = awaitResponse(rod, 2);
03105     
03106     if(responseCode != 0) {
03107       cout << "Send trigger " << i << " failed on rod " << rod << "!\n";
03108       break;
03109     }
03110   }
03111 }
03112 
03113 void SctApi::sendL1A(unsigned int rod, bool capture) {
03114   {
03115     boost::mutex::scoped_lock lock(log().mutex());
03116     log() << "Send L1A\n";
03117   }
03118 
03119   long *data = new long[sizeof(BUILD_STREAM_IN)/4];
03120 
03121   BUILD_STREAM_IN &buildPrim = *(BUILD_STREAM_IN*)data;
03122 
03123 #if (R_BUILD_STREAM == 102)
03124   for(int i=0; i<6; i++) {
03125     buildPrim.cmdList.cmd[i] = 0x64;
03126     buildPrim.cmdList.data[i] = 0;
03127   }
03128 
03129   buildPrim.cmdList.cmd[0] = 0x65;
03130 
03131   buildPrim.port = SP0;
03132   buildPrim.reset = 1;
03133   buildPrim.chip = 63;
03134   buildPrim.fibre = 3;
03135   buildPrim.dataLen = 0;
03136   buildPrim.data = 0;    // Should be ignored?
03137  
03138   shared_ptr<PrimListWrapper> sendList(new PrimListWrapper(3));
03139 
03140   sendList->addPrimitive(RodPrimitive(4 + sizeof(BUILD_STREAM_IN)/4, 
03141                                       2, BUILD_STREAM, R_BUILD_STREAM, data),
03142                          data);
03143 #elif R_BUILD_STREAM == 101
03144 #error "Build stream not compiled (unsupported old version)" 
03145 #else   // Unknown R_BUILD_STREAM
03146 #error "Build stream not compiled (unknown primitive version, check primParams.h)" 
03147 #endif
03148 
03149 #ifdef CMD_BUFFER_BOTH
03150   PrimBuilder::instance().sendStream(sendList, CMD_BUFFER_BOTH, capture);
03151 #else
03152   PrimBuilder::instance().sendStream(sendList, SP_BOTH, capture);
03153 #endif
03154 
03155   sendPrimList(rod, sendList);
03156 
03157   awaitResponse(rod, 2);
03158 }
03159 
03160 void SctApi::bocHistogram(unsigned int rod, 
03161                           unsigned int samples, unsigned int numLoops) {
03162   std::cout << "BOC histogram unsupported\n";
03163   throw SctApiException("BOC histogram unsupported");
03164 }
03165 
03166 void SctApi::printABCDModule(int mid) {
03167   ABCDModule *mConf = lookupConfig(mid);
03168 
03169   if(mConf) {
03170     std::cout << config->printModuleConfig(*mConf);
03171   } else {
03172     cout << "Invalid module id " << mid << endl;
03173   }
03174 }
03175 
03176 void SctApi::printABCDRodModule(int mid, BankType bank) {
03177   getABCDModule(mid, bank);
03178 
03179   ABCDModule *mConf = lookupConfig(mid);
03180   if (mConf) std::cout << config->printModuleConfig(*mConf);
03181 }
03182 
03183 void SctApi::modifyTIMParam(unsigned int type, unsigned int val) {
03184   getCrate()->modifyTIMParam(type, val);
03185 }
03186 
03187 void SctApi::modifyBOCParam(unsigned int type, unsigned int val) {
03188   getCrate()->modifyBOCParam(type, val, true);
03189 }
03190 
03191 void SctApi::modifyBOCParam(unsigned int rod,
03192                             unsigned int channel, unsigned int type, unsigned int val) {
03193   getCrate()->modifyBOCParam(rod, channel, type, val, true);
03194 }
03195 
03196 void SctApi::printBOCSetup(unsigned int rod) {
03197   getCrate()->printBOCSetup(rod);
03198 }
03199 
03200 vector<BOCChannelConfig> SctApi::currentBOCSetup(unsigned int rod) {
03201   return getCrate()->currentBOCSetup(rod);
03202 }
03203 
03204 void SctApi::printBOCRegisters(unsigned int rod) {
03205   getCrate()->printBOCRegisters(rod);
03206 }
03207 
03208 BOCGlobalConfig SctApi::currentBOCRegisters(unsigned int rod) {
03209   return getCrate()->currentBOCRegisters(rod);
03210 }
03211 
03212 void SctApi::saveBOCSetup(unsigned int rod, BankType bank) {
03213   getCrate()->saveBOCSetup(rod, bank);
03214 }
03215 
03216 void SctApi::saveBOCRegisters(unsigned int rod, BankType bank) {
03217   getCrate()->saveBOCRegisters(rod, bank);
03218 }
03219 
03220 void SctApi::restoreBOCSetup(unsigned int rod, BankType bank) {
03221   getCrate()->restoreBOCSetup(rod, bank);
03222 }
03223 
03224 void SctApi::restoreBOCRegisters(unsigned int rod, BankType bank) {
03225   getCrate()->restoreBOCRegisters(rod, bank);
03226 }
03227 
03228 void SctApi::lasersOff() {
03229   {
03230     boost::mutex::scoped_lock lock(log().mutex());
03231     log() << "Lasers off called\n";
03232     log() << "\t TIME " << second_clock::universal_time() << endl;
03233   }
03234 
03235   std::cout << " *** Trying to turn lasers off  ***\n";
03236   getCrate()->lasersOff();
03237 }
03238 
03239 void SctApi::timSetFrequency(double trigFreq, double rstFreq) {
03240   getCrate()->timSetFrequency(trigFreq, rstFreq);
03241 }
03242 
03243 double SctApi::timGetTriggerFrequency() {
03244   return getCrate()->timGetTriggerFrequency();
03245 }
03246 
03247 double SctApi::timGetResetFrequency() {
03248   return getCrate()->timGetResetFrequency();
03249 }
03250 
03251 void SctApi::freeTriggers() {
03252   shared_ptr<PrimListWrapper> timList(new PrimListWrapper(1));
03253 
03254 #ifdef RRIF_CMND_1
03255   PrimBuilder &builder = PrimBuilder::instance();
03256   // Use TIM triggers
03257   builder.writeRegister(timList, RRIF_CMND_1, 1, 1, 1);
03258   // Enable TIM trigger event ID decoding
03259   builder.writeRegister(timList, RRIF_CMND_1, 8, 1, 1);
03260 #else
03261 #error "Unsupported no registers"
03262 #endif
03263 
03264   sendPrimListAll(timList);
03265 
03266   awaitResponseAll(2);
03267 
03268   getCrate()->freeTriggers();
03269 }
03270 
03271 void SctApi::stopTriggers() {
03272   shared_ptr<PrimListWrapper> timList(new PrimListWrapper(1));
03273 
03274 #ifdef RRIF_CMND_1
03275   PrimBuilder &builder = PrimBuilder::instance();
03276   // Use TIM triggers
03277   builder.writeRegister(timList, RRIF_CMND_1, 1, 1, 0);
03278   // Enable TIM trigger event ID decoding
03279   builder.writeRegister(timList, RRIF_CMND_1, 8, 1, 0);
03280 #else
03281 #error "Unsupported no registers"
03282 #endif
03283 
03284   sendPrimListAll(timList);
03285 
03286   awaitResponseAll(2);
03287 
03288   getCrate()->stopTriggers();
03289 }
03290 
03291 void SctApi::timL1A() {
03292   getCrate()->timL1A();
03293 }
03294 
03295 void SctApi::timCalL1A(int delay) {
03296   getCrate()->timCalL1A(delay);
03297 }
03298 
03299 void SctApi::timSoftReset() {
03300   // FER doesn't reset TIM L1 count
03301   getCrate()->timECR();
03302 }
03303 
03304 void SctApi::timBCReset() {
03305   getCrate()->timBCR();
03306 }
03307 
03308 void SctApi::timLoadSequence(const vector<unsigned>& seq){
03309   getCrate()->timLoadSequence(seq);
03310 }
03311 
03312 unsigned long SctApi::timRunSequence(unsigned long trigs, int random, bool external){
03313   return getCrate()->timRunSequence(trigs, random, external);
03314 }
03315 
03316 void SctApi::timVerbose() {
03317   getCrate()->timVerbose();
03318 }
03319 
03320 void SctApi::timWriteRegister(int reg, UINT16 val) {
03321   getCrate()->timRegLoad(reg, val);
03322 }
03323 
03324 UINT16 SctApi::timReadRegister(int reg) {
03325   return getCrate()->timRegRead(reg);
03326 }
03327 
03328 void SctApi::decodeConfig(unsigned int rod, 
03329                           bool skipTrim, bool bypass) {
03330   unsigned long readlength;
03331 #warning "Hard-coded address, this is the serial port output buffer"
03332   unsigned long *config = dspBlockRead(rod, 0x2102000, 270 * 12, -1, readlength);
03333 
03334   unsigned int pos = 0;
03335   while(pos < readlength) {
03336     if((config[pos] & 0x5760000) != 0x5700000) {
03337       cout << "Strange data: ";
03338       cout << hex << " " << pos << " " << config[pos] << dec << endl;
03339       break;
03340     } 
03341 
03342     unsigned int f3 = (config[pos] & 0xff000) >> 12;
03343     unsigned int f4 = (config[pos] & 0x00fc0) >> 6;
03344     unsigned int f5 = (config[pos] & 0x0003f) >> 0;
03345 
03346     pos ++;
03347 
03348     cout << "Chip address " << f4 << ": ";
03349     if(!bypass) {
03350       cout << hex << f3 << "/" << f5 << dec << ": ";
03351     }
03352 
03353     switch(f3) {
03354     case 0x1c:
03355       {
03356         unsigned short data = (0xffff0000 & config[pos]) >> 16;
03357         switch(f5) {
03358         case 0:
03359           // Configuration reg
03360           if(!bypass) {
03361             cout << "Config: " << hex << data << dec;
03362             cout << " comp " << (data & 3) 
03363                  << " cal "  << ((data & 0xc) >> 2)
03364                  << " trim "  << ((data & 0x30) >> 4)
03365                  << " edge "  << ((data & 0x40) >> 6)
03366                  << " mask "  << ((data & 0x80) >> 7)
03367                  << " acc "  << ((data & 0x100) >> 8)
03368                  << " in_b " << ((data & 0x200) >> 9)
03369                  << " out_b " << ((data & 0x400) >> 10)
03370                  << " mast " << ((data & 0x800) >> 11)
03371                  << " end " << ((data & 0x1000) >> 12)
03372                  << " feed " << ((data & 0x2000) >> 13)
03373                  << endl;
03374           } else {
03375             cout << " in_b " << ((data & 0x200) >> 9)
03376                  << " out_b " << ((data & 0x400) >> 10)
03377                  << " mast " << ((data & 0x800) >> 11)
03378                  << " end " << ((data & 0x1000) >> 12)
03379                  << " feed " << ((data & 0x2000) >> 13)
03380                  << endl;
03381           }
03382           break;
03383         case 0x10:
03384           if(!bypass) {
03385             cout << "Strobe delay: " << hex 
03386                  << (data & 0x3f) << dec << endl;
03387           }
03388           break;
03389         case 0x18:
03390           if(!bypass) {
03391             cout << "Threshold/Cal: " << hex
03392                  << ((data & 0xff00) >> 8) << "/" 
03393                  << (data & 0xff) << dec << endl;
03394           }
03395           break;
03396         case 0x38:
03397           if(!bypass) {
03398             cout << "preamp/shaper: " << hex
03399                  << ((data & 0xff00) >> 8) << "/" 
03400                  << (data & 0xff) << dec << endl;
03401           }
03402           break;
03403         case 0x04:
03404           if(skipTrim || bypass) {
03405             cout << "\r                   \r";
03406           } else {
03407             cout << "TRIM DAC: " << hex
03408                  << (data & 0xf) << " " 
03409                  << ((data & 0x7f0) >> 4) << dec << endl;
03410           }
03411           break;
03412         }
03413         pos ++;
03414         break;
03415       }
03416     case 0x8c:
03417       if(!bypass) {
03418         // Mask reg
03419         cout << "Mask ";
03420         cout << hex;
03421         for(int i=0; i<4; i++) {
03422           cout << config[pos++] << " ";
03423         }
03424         cout << dec;
03425         cout << endl;
03426         pos++;
03427       } else {
03428         pos += 5;
03429       }
03430       break;
03431     case 0x0c:
03432       cout << "Something else\n";
03433       break;
03434     }
03435   }
03436 }
03437 
03438 void SctApi::getrpcrc(UINT32 mid, unsigned int &rpartition, unsigned int &rcrate, unsigned int &rrod, unsigned int &rchannel) {
03439   unsigned int partition, crate, rod, channel;
03440 
03441   getpcrc(mid, partition, crate, rod, channel);
03442 
03443   unsigned int mur, module;
03444 
03445   try {
03446     if(checkDebugOption(DEBUG_DIAG))
03447       cout << "Looking for module in partition " << partition << " crate " << crate << " rod " << rod << " channel " << channel << endl;
03448     config->translateFromROD(partition, crate, rod, channel, 
03449                              mur, module);
03450 
03451     if(checkDebugOption(DEBUG_DIAG2))
03452       cout << "Found MUR " << mur << " module number " << module << endl;
03453   } catch(ConfigurationException &c) {
03454     cout << "Can't find module in MUR map: \n";
03455     cout << c.what() << endl;
03456 
03457     {
03458       boost::mutex::scoped_lock lock(log().mutex());
03459       log() << "  (Not found)\n";
03460     }
03461     throw;
03462   }
03463 
03464   try {
03465     config->translateToRROD(mur, module, 
03466                             rpartition, rcrate, rrod, rchannel);
03467   } catch(ConfigurationException &c) {
03468     cout << "Module redundancy not found: \n";
03469     cout << c.what() << endl;
03470 
03471     {
03472       boost::mutex::scoped_lock lock(log().mutex());
03473       log() << "  (Not found)\n";
03474     }
03475     throw;
03476   }
03477 }
03478 
03479 long SctApi::getRodSlot(unsigned int rod) 
03480 {
03481   if(getCrate()) {
03482     return getCrate()->getRodSlot(rod);
03483   } else {
03484     return -1;
03485   }
03486 }
03487 
03488 int SctApi::getRodRevision(unsigned int rod) 
03489 {
03490   if(getCrate()) {
03491     return getCrate()->getRodRevision(rod);
03492   } else {
03493     return -1;
03494   }
03495 }
03496 
03497 int SctApi::getRodRevision(const RodLabel &label) 
03498 {
03499   if(getCrate()) {
03500     return getCrate()->getRodRevision(label.rod);
03501   } else {
03502     return -1;
03503   }
03504 }
03505 
03506 void SctApi::testLinkOutSelect(unsigned int rod,
03507                                unsigned int link) 
03508 {
03509 #ifdef FMT_LINK_DATA_TEST_MUX
03510   int formatter = link/12;
03511   int intLink = link%12;
03512 
03513   if(formatter > 8 || formatter < 0) {
03514     cout << "formatter out of range: " << formatter << endl;
03515     return;
03516   }
03517 
03518   if(intLink > 12 || intLink < 0) {
03519     cout << "link out of range: " << intLink << endl;
03520     return;
03521   }
03522 
03523   shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
03524 
03525   PrimBuilder &builder = PrimBuilder::instance();
03526   builder.writeRegister(primList, FMT_LINK_DATA_TEST_MUX(formatter), 0, 4, intLink);   // 0x070 + formatter
03527   builder.writeRegister(primList, EFB_CMND_0, 4, 4, formatter & 0x7);                  // 0x1a4
03528 
03529   sendPrimList(rod, primList);
03530   awaitResponse(rod, 2);
03531 #else 
03532 #error "Link out select not compiled"
03533 #endif
03534 }
03535 
03536 unsigned int SctApi::testLinkOutRetrieve(unsigned int rod) 
03537 {
03538 #ifdef FMT_LINK_DATA_TEST_MUX
03539   int fReg = readRODRegister(rod, EFB_CMND_0);
03540   int formatter = (fReg >> 4) & 0x7;
03541 
03542   int lReg = readRODRegister(rod, FMT_LINK_DATA_TEST_MUX(formatter));
03543   int intLink = lReg & 0xf;
03544 
03545   return formatter * 12 + intLink;
03546 #else 
03547 #error "Link out select not compiled"
03548 #endif
03549 }
03550 
03551 void SctApi::setDebugOption(std::string opt) {
03552   Debug::getInstance()->setDebugOption(opt);
03553 }
03554 
03555 void SctApi::unsetDebugOption(std::string opt) {
03556   Debug::getInstance()->unsetDebugOption(opt);
03557 }
03558 
03559 std::list<std::string> SctApi::listEnabledDebugOptions() const{
03560   return Debug::getInstance()->listEnabledDebugOptions();
03561 }
03562 
03563 std::vector<std::string> SctApi::listDebugOptions() const{
03564   return Debug::getInstance()->listDebugOptions();
03565 }
03566 
03567 void SctApi::unsetBusy() {
03568   if(m_isDict) {
03569     m_isDict->remove(idiosyncrasy().infoServiceNameOfScanStatusObject());
03570   }
03571 }
03572 
03573 bool SctApi::checkDebugOption(std::string opt) const{
03574   return Debug::getInstance()->checkDebugOption(opt);
03575 }
03576 
03577 bool SctApi::checkDebugOption(int intOpt) const{
03578   return Debug::getInstance()->checkDebugOption((DebugOptions)intOpt);
03579 }
03580 
03581 void SctApi::debugStepHistogram()
03582 {
03583   if(!lastDebugScanEx) {
03584     cout << "No last scan stored\n";
03585     return;
03586   }
03587 
03588   // This can only work as a single ROD method!
03589   RodLabel zeroRod = lastDebugScanEx->rodInfo.begin()->first;
03590 
03591   // Do step
03592 #warning "Hard coded access to diagnostic register with STEP_CTRL and STEP_TRIGGER bits"
03593   dspSingleWrite(zeroRod.rod, 
03594                  0x80000010, lastDebugScanEx->diagnosticReg | (1<<7) | (1<<6), -1); 
03595 
03596 #if USE_THREADS
03597   sleep(1);
03598 #else
03599   // Read the text buffers
03600   awaitResponse(zeroRod.rod, 1);
03601 #endif
03602 
03603   if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
03604     standardRegisterDump(zeroRod.rod);
03605   }
03606 }
03607 
03608 void SctApi::debugContinueHistogram()
03609 {
03610   // This can only work as a single ROD method!
03611   RodLabel zeroRod = lastDebugScanEx->rodInfo.begin()->first;
03612 
03613 #warning "Hard-coded diagnostic register with STEP_TRIGGER bit"
03614   dspSingleWrite(zeroRod.rod, 
03615                  0x80000010, lastDebugScanEx->diagnosticReg | (1<<7), -1); 
03616 
03617 #if USE_THREADS
03618   sleep(1);
03619 #else
03620   // Read the text buffers
03621   awaitResponse(zeroRod.rod, 
03622                 1);
03623 #endif
03624 
03625   if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
03626     standardRegisterDump(zeroRod.rod);
03627   }
03628 }
03629 
03630 void SctApi::debugAbortHistogram()
03631 {
03632 #warning "How to do this... tidyHistogramming? (not when in stalled mode!) AUTO_STALL ends at next bin!"
03633   // killing histogram task then step?
03634   time_t start_time = time(0);
03635 
03636   // This can only work as a single ROD method!
03637   RodLabel zeroRod = lastDebugScanEx->rodInfo.begin()->first;
03638 
03639   while(1) {
03640     cout << "** Loop\n";
03641 
03642 #warning "Hard coded address (Diagnostic register (STEP_TRIGGER))"
03643     dspSingleWrite(zeroRod.rod, 
03644                    0x80000010, (1<<7), -1);
03645     while(dspSingleRead(zeroRod.rod, 
03646                         0x80000010, -1) & (1<<7)) {
03647       if((time(0) - start_time) > 2) {
03648         goto breakOut;
03649       }
03650     }
03651   }
03652 
03653  breakOut:
03654   tidyHistogramming();
03655 }
03656 
03657 void SctApi::standardRegisterDump(RodLabel rl) {
03658   standardRegisterDump(rl.rod);
03659 }
03660 
03661 void SctApi::standardRegisterDump(unsigned int rod) {
03662   static int dumpCount = 0;
03663 
03664   if(!getCrate() 
03665      || !getCrate()->RODPresent(rod)) {
03666     cout << "Invalid crate or ROD in standardRegisterDump\n";
03667     return;
03668   }
03669 
03670   cout << "Making dump number " << dumpCount << endl;
03671 
03672   string baseDir(Sct::SctNames::getTempDir());
03673 
03674   // Awkward to do %05d with strings...
03675   boost::format dirFormat("%s/Dump_%05d_%05d");
03676   dirFormat % baseDir % getpid() % (dumpCount ++);
03677 
03678   string dirName(dirFormat.str());
03679   
03680   cout << " in " << dirName << endl;
03681 
03682   int dirRet = mkdir(dirName.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
03683   if(dirRet != 0) {
03684     // It's OK if it already exists
03685     if(errno != EEXIST) {
03686       perror(("Failed to create Dump directory in '" + baseDir + "', aborting dump").c_str());
03687       return;
03688     }
03689   }
03690 
03691   char *saveDir = getcwd(NULL, 0);
03692   int chRet = chdir(dirName.c_str());
03693   if(chRet != 0) {
03694     perror("Failed to change to Dump directory, aborting dump");
03695     return;
03696   }
03697 
03698   dspBlockDumpFile(rod, 0x02400000, 0x80000, -1, "BigMDSPDump.bin");
03699 
03700   dspBlockDumpFile(rod, 0x00400000, 0x800, -1, "StandardDumpFRM.bin");
03701   dspBlockDumpFile(rod, 0x00402000, 0x100, -1, "StandardDumpEFB.bin");
03702   dspBlockDumpFile(rod, 0x00402400, 0x060, -1, "StandardDumpRTR.bin");
03703   dspBlockDumpFile(rod, 0x00404400, 0x300, -1, "StandardDumpRCF.bin");
03704 
03705   dspBlockDumpFile(rod, 0x02000000, 0x40000, -1, "StandardDumpMDSP_XPROG.bin");
03706   dspBlockDumpFile(rod, 0x80000000, 0x02000, -1, "StandardDumpMDSP_IDRAM.bin");
03707 
03708   ofstream moduleList("StandardModuleList.txt");
03709 
03710   moduleList << "Module configuration for " << moduleMap.size() << " modules:\n";
03711   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
03712       mi!=moduleMap.end();
03713       mi ++) {
03714     UINT32 mid = mi->first;
03715 
03716     string sn = convertToString(mid);
03717     ABCDModule *moduleConf = lookupConfig(mid);
03718     int group = moduleConf->groupId;
03719     int select = moduleConf->select;
03720     int prim = moduleConf->pTTC;
03721     int redun = moduleConf->rTTC;
03722     int link0 = moduleConf->rx[0];
03723     int link1 = moduleConf->rx[1];
03724 
03725     // Reverse translate formatter encoding
03726     if(link0 != DATA_LINK_OFF) 
03727       link0 = (link0/16) * 12 + link0%16;
03728     if(link1 != DATA_LINK_OFF) 
03729       link1 = (link1/16) * 12 + link1%16;
03730 
03731     moduleList.width(8);
03732     moduleList << mid << " " << sn << " Group: " << group << " Select: " << select;
03733     moduleList << "\t Pr: ";
03734     moduleList.width(2);
03735     moduleList << prim << " Red: ";
03736     moduleList.width(3);
03737     moduleList << redun << " Link 0/1: ";
03738     moduleList.width(3);
03739     moduleList << link0 << " ";
03740     moduleList.width(3);
03741     moduleList << link1 << endl;
03742   }
03743 
03744   // Rev E or rev F
03745   if(getCrate()->getRodRevision(rod) >= 0xE) {
03746     for(int s=0; s<4; s++) {
03747       // Event data in slave
03748       string idramFile = "StandardDumpSDSP0_IDRAM.bin";
03749       idramFile[16] = s + '0';
03750       dspBlockDumpFile(rod, 0x00010000, 0x2000, s, idramFile);
03751       string burstFile = "StandardDumpSDSP0_BURST.bin";
03752       burstFile[16] = s + '0';
03753       dspBlockDumpFile(rod, 0x00018000, 0x2000, s, burstFile);
03754       string sdramFile = "StandardDumpSDSP0_SDRAM.bin";
03755       sdramFile[16] = s + '0';
03756       dspBlockDumpFile(rod, 0xa0040000, 0x28800, s, sdramFile);
03757     }
03758   } else {  // Rev C
03759     for(int s=0; s<4; s++) {
03760       // Event data in slave
03761       string idramFile = "StandardDumpSDSP0_IDRAM.bin";
03762       idramFile[16] = s + '0';
03763       dspBlockDumpFile(rod, 0x80000000, 0x2000, s, idramFile);
03764       string burstFile = "StandardDumpSDSP0_BURST.bin";
03765       burstFile[16] = s + '0';
03766       dspBlockDumpFile(rod, 0x80008000, 0x2000, s, burstFile);
03767       string sdramFile = "StandardDumpSDSP0_SDRAM.bin";
03768       sdramFile[16] = s + '0';
03769       dspBlockDumpFile(rod, 0x02040000, 0x28800, s, sdramFile);
03770     }
03771   }
03772 
03773   int chSaveRet = chdir(saveDir);
03774   if(chSaveRet != 0) {
03775     perror("Failed to return to saved directory after Dump");
03776   }
03777 }
03778 
03779 void SctApi::standardRegisterDumpAll() {
03780   for(list<RodLabel>::const_iterator rl = rodList.begin();
03781       rl!=rodList.end();
03782       rl++){
03783     standardRegisterDump(*rl);
03784   }
03785 }
03786 
03787 void SctApi::setupScanMasks(ScanEx &extra, int distSlave, bool dual) {
03788   RodScanEx defaultInfo;
03789 
03790   if(distSlave == 0) {
03791     defaultInfo.slaves = 1;
03792     defaultInfo.bitFieldDSP = 0x1;
03793   } else if(distSlave == 1) {
03794     defaultInfo.slaves = 0;
03795     defaultInfo.bitFieldDSP = 0x0; // Fill in which slaves are used later
03796   } else if(distSlave == 2) {
03797     defaultInfo.slaves = 4;
03798     defaultInfo.bitFieldDSP = 0xf;
03799   }
03800 
03801   ModuleMask zeroMask = {0, 0};
03802 
03803   defaultInfo.channels = zeroMask;
03804 
03805   for(int i=0; i<8; i++) {
03806     defaultInfo.groupChannels[i] = zeroMask;
03807   }
03808   for(int i=0; i<4; i++) {
03809     defaultInfo.slaveChannels[i] = zeroMask;
03810   }
03811 
03812   // Group to DSP mappings
03813   if(distSlave == 0) {               // Which groups for each DSP to use
03814     // All groups to slave 0
03815     extra.groupDspMap[0] = 0xff;
03816     extra.groupDspMap[1] = 0x0;
03817     extra.groupDspMap[2] = 0x0;
03818     extra.groupDspMap[3] = 0x0;
03819   } else if(distSlave == 2) {
03820     // All groups to all slaves
03821     extra.groupDspMap[0] = 0xff;
03822     extra.groupDspMap[1] = 0xff;
03823     extra.groupDspMap[2] = 0xff;
03824     extra.groupDspMap[3] = 0xff;
03825   } else {
03826     if(!dual) {
03827       // Each group to a separate DSP
03828       extra.groupDspMap[0] = 0x11;
03829       extra.groupDspMap[1] = 0x22;
03830       extra.groupDspMap[2] = 0x44;
03831       extra.groupDspMap[3] = 0x88;
03832     } else {
03833       // Each Dsp has to service one trigger
03834       extra.groupDspMap[0] = 0x03;
03835       extra.groupDspMap[1] = 0x0c;
03836       extra.groupDspMap[2] = 0x30;
03837       extra.groupDspMap[3] = 0xc0;
03838     }
03839   }
03840 
03841   if(!dual) {
03842     extra.groupSpMap[0] = 0xff;        // All groups use port 0
03843     extra.groupSpMap[1] = 0x00;
03844   } else {
03845     extra.groupSpMap[0] = 0xf;         // Groups 0-3 use port 0
03846     extra.groupSpMap[1] = 0xf0;        // Groups 4-7 use port 1
03847   }
03848 
03849   if(!dual) {
03850     extra.groupRangeMap[0] = 0xff;         // All groups use range list 0
03851     extra.groupRangeMap[1] = 0x0;
03852   } else {
03853     extra.groupRangeMap[0] = 0x0f;         // Groups 0-3 -> range list 0
03854     extra.groupRangeMap[1] = 0xf0;         // Groups 4-7 -> range list 1
03855   }
03856 
03857   // Set up masks for modules
03858   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
03859       mi!=moduleMap.end();
03860       mi ++) {
03861     UINT32 currMid = mi->first;
03862 
03863     ABCDModule *moduleConfig = lookupConfig(currMid);
03864     unsigned int group = moduleConfig->groupId;
03865 
03866     unsigned int newPartition, newCrate, newRod, newChannel;
03867     getpcrc(currMid, newPartition, newCrate, newRod, newChannel);
03868 
03869     RodLabel thisRod(newPartition, newCrate, newRod);
03870 
03871     RodScanEx &thisInfo = extra.getOrNewRod(thisRod, defaultInfo);
03872 
03873     // Check if redundancy in use
03874     if(moduleConfig->select) {
03875       // does clk/cmd go from same ROD
03876       try {
03877         unsigned int rpartition, rcrate, rrod, rchannel;
03878         getrpcrc(currMid, rpartition, rcrate, rrod, rchannel);
03879 
03880         if(newPartition != rpartition || newCrate != rcrate || newRod != rrod) {
03881           // Nothing to do as mask are rx
03882         }
03883       } catch(ConfigurationException &c) {
03884         // Redundant conversion failed, this should have been picked up in the checks
03885       }
03886     }
03887 
03888     if(newChannel<32) {
03889       if(thisInfo.channels.mask0 & 1<<newChannel) {
03890         cout << "Module already using this channel in this group\n";
03891       }
03892       thisInfo.channels.mask0 |= 1<<newChannel;
03893 
03894       if(distSlave == 1) {
03895         thisInfo.groupChannels[group].mask0 |= 1<<newChannel;
03896       } else if(distSlave == 0) {
03897         thisInfo.groupChannels[0].mask0 |= 1<<newChannel;
03898       } else {
03899         // Same as distSlave == 1...
03900         thisInfo.groupChannels[group].mask0 |= 1<<newChannel;
03901       }
03902     } else {
03903       if(thisInfo.channels.mask1 & 1<<(newChannel-32)) {
03904         cout << "Module already using this channel in this group\n";
03905       }
03906       thisInfo.channels.mask1 |= 1<<(newChannel-32);
03907 
03908       if(distSlave == 1) {
03909         thisInfo.groupChannels[group].mask1 |= 1<<(newChannel-32);
03910       } else if(distSlave == 0) {
03911         thisInfo.groupChannels[0].mask1 |= 1<<(newChannel-32);
03912       } else {
03913         // Same as distSlave == 1...
03914         thisInfo.groupChannels[group].mask1 |= 1<<(newChannel-32);
03915       }
03916     }
03917 
03918     if(group+1 > extra.groupLists.size()) {
03919       extra.groupLists.resize(group + 1);
03920     }
03921     extra.groupLists[group].push_back(convertToString(currMid));
03922   }
03923 
03924   // Fix slave maps
03925   for(list<RodLabel>::const_iterator rl = rodList.begin();
03926       rl!=rodList.end();
03927       rl++){
03928 
03929     RodScanEx &thisInfo = extra.getRodScanInfo(*rl);
03930 
03931     thisInfo.slaves = 0;
03932     thisInfo.firstSlave = numSlaves;
03933 
03934     for(int slave=0; slave<numSlaves; slave++) {
03935       for(int group=0; group<8; group++) {
03936         if(extra.groupDspMap[slave] & (1<<group)) {
03937           if(thisInfo.groupChannels[group].mask0 || thisInfo.groupChannels[group].mask1) {
03938             thisInfo.bitFieldDSP |= 1<<slave;
03939           }
03940 
03941           thisInfo.slaveChannels[slave].mask0 |= thisInfo.groupChannels[group].mask0;
03942           thisInfo.slaveChannels[slave].mask1 |= thisInfo.groupChannels[group].mask1;
03943         }
03944       }
03945 
03946       if(thisInfo.bitFieldDSP & (1<<slave)) {
03947         thisInfo.slaves++; 
03948 
03949         if(thisInfo.firstSlave > 3) {
03950           thisInfo.firstSlave = slave;
03951         }
03952       }
03953     }
03954   }
03955 }
03956 
03957 // Check lists are valid
03958 bool SctApi::checkModuleListsForScan() {
03959   if(moduleMap.begin() == moduleMap.end()) {
03960     cout << "No modules to scan!\n";
03961     if(mrs) {
03962       *mrs << "SCAN_NO_MODULES" << MRS_ERROR 
03963            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
03964            << MRS_TEXT("No modules to scan")
03965            << ENDM;
03966     }
03967     return false;
03968   }
03969 
03970   // Initialise with first module
03971   UINT32 mid = moduleMap.begin()->first;
03972   unsigned int firstPartition, firstCrate, firstRod, firstChannel;
03973   getpcrc(mid, firstPartition, firstCrate, firstRod, firstChannel);
03974 
03975   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
03976       mi!=moduleMap.end();
03977       mi ++) {
03978     UINT32 currMid = mi->first;
03979 
03980     unsigned int newPartition, newCrate, newRod, newChannel;
03981 
03982     getpcrc(currMid, newPartition, newCrate, newRod, newChannel);
03983 
03984     // Check first module against current one
03985     if(newPartition != firstPartition) {
03986       cout << "Can't do scans on modules in different partitions (ever?)\n";
03987       if(mrs) {
03988         *mrs << "SCAN_MISMATCH" << MRS_ERROR 
03989              << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
03990              << MRS_TEXT("Mismatch partitions. Can't do scans on modules in different partitions (ever?)")
03991              << ENDM;
03992       }
03993       return false;
03994     }
03995 
03996     // Check first module against current one
03997     if(newCrate != firstCrate) {
03998       cout << "Can't do scans on modules in different crates (yet)\n";
03999       if(mrs) {
04000         *mrs << "SCAN_MISMATCH" << MRS_ERROR 
04001              << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
04002              << MRS_TEXT("Crate mismatch, can't do scans on modules in different crates (yet)")
04003              << ENDM;
04004       }
04005       return false;
04006     }
04007 
04008     ABCDModule *config = lookupConfig(currMid);
04009 
04010     if(!config) {
04011       cout << "Trying to do a scan on a module with no configuration FAILED!\n";
04012       if(mrs) {
04013         *mrs << "SCAN_NOCONFIG" << MRS_ERROR 
04014              << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
04015              << MRS_TEXT("Trying to do a scan on a module with no configuration FAILED!")
04016              << ENDM;
04017       }
04018       return false;
04019     }
04020 
04021     // Check if redundancy in use
04022     if(config->select) {
04023       // does clk/cmd go from same ROD
04024       try {
04025         unsigned int rpartition, rcrate, rrod, rchannel;
04026         getrpcrc(currMid, rpartition, rcrate, rrod, rchannel);
04027 
04028         if(newPartition != rpartition || newCrate != rcrate || newRod != rrod) {
04029           cout << "Can't do redundant stuff on split RODs at the moment, SCAN CANCELLED\n";
04030           return false;
04031         }
04032       } catch(ConfigurationException &c) {
04033         cout << "No mapping to redundant channel for module with select, SCAN CANCELLED\n";
04034         return false;
04035       }
04036     }
04037   }
04038 
04039   return true;
04040 }
04041 
04042 bool SctApi::preScanHardwareCheck(const Scan& scan, ScanEx& extra) {
04043   std::cout << "preScanHardwareCheck started at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
04044   // Check that the appropriate slaves were initialised 
04045   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
04046       ri != extra.rodInfo.end();
04047       ri++) {
04048     const RodLabel rod = ri->first;
04049     for(int i=0; i<4; i++) {
04050       if(ri->second.bitFieldDSP & (1<<i) 
04051          && getCrate()
04052          && !getCrate()->slavePresent(rod.rod, i)) {
04053         cout << "***** A slave DSP necessary for the requested scan was not initialised\n";
04054         cout << "*****  please check the configuration and the Slave Image files\n";
04055         if(mrs) {
04056           *mrs << MRS_ERROR 
04057                << "SCAN_NODSP" 
04058                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
04059                << MRS_PARAM<int>("slavesNeeded", ri->second.bitFieldDSP)
04060                << MRS_PARAM<int>("slaveNotStarted", i)
04061                << MRS_TEXT("Required DSPs not initialised for the requested scan")
04062                << ENDM;
04063         }
04064         return false;
04065       }
04066     }
04067 
04068     // Don't bother checking if in debug mode
04069     if(!getCrate()->checkBOCLasersOn(rod.rod)) {
04070       if(!scan.getOption(Scan::DEBUG)) {
04071         cout << "Trying to do scan using BOC that has its lasers cut out (aborting)\n";
04072         if(mrs) {
04073           *mrs << "BOC_INTERLOCKED" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
04074                << MRS_PARAM<int>("crate", rod.crate) 
04075                << MRS_PARAM<int>("rod", rod.rod)
04076                << MRS_TEXT("Scan aborting (BOC interlocked)") << ENDM;
04077         }
04078 
04079         return false;
04080       } else {
04081         cout << "Trying to do scan using BOC that has its lasers cut out (continuing for debug)\n";
04082       }
04083     }
04084   }
04085   if(!checkAllModulesProbe("E")) {
04086 #warning "Possibly disable the ones that aren't returning events? (with warnings!)"
04087     if(!scan.getOption(Scan::DEBUG)) {
04088       cout << "Check all modules in scan are returning events! (aborting)\n";
04089       if(mrs) {
04090     *mrs << "SCAN_ABORTED" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
04091          << MRS_TEXT("Scan aborting (Modules not returning events)") 
04092          << MRS_PARAM<const char*>("ucid",static_cast<string>(ucid()).c_str()) << ENDM;
04093       }
04094       return false;
04095     } else {
04096       cout << "All modules in scan are not returning events! (continuing for DEBUG)\n";
04097       if(mrs) {
04098     *mrs << "SCAN_WARNING" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
04099          << MRS_TEXT("Modules not all returning events (Scan continuing anyway (DEBUG))")
04100          << MRS_PARAM<const char*>("ucid",static_cast<string>(ucid()).c_str()) << ENDM;
04101       }
04102     }
04103   }
04104   
04105   return true;
04106 }
04107 
04108 /* This probably should be in ScanControlRODHisto, but 
04109    it has to be done before the main scan and so doesn't 
04110    fit into the current plan...
04111  */
04112 void SctApi::preScanModuleSetup(const Scan &scan) {
04113   std::cout << "preScanModuleSetup started at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
04114   {
04115     std::list<BankType> banks;
04116     banks.push_back(SCTAPI_BANK_SCAN);
04117     setABCDModules(banks);
04118     cout << "Configuration for all modules has been uploaded to SCAN at TIME " << boost::posix_time::second_clock::universal_time() << std::endl;
04119   }
04120 
04121   cout << "Do ROD configuration (masks etc)\n"; 
04122   calib_init();
04123 
04124   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
04125     UINT32 mid = moduleMap.begin()->first;
04126     unsigned int partition, crate, rod, channel;
04127     getpcrc(mid, partition, crate, rod, channel);
04128 
04129     print_calib(rod);
04130   }
04131   // Send configuration to the module (this should be redundant as it the first thing the histogramming does)
04132   std::cout << "send all modules at TIME " << second_clock::universal_time() << std::endl;
04133   sendAllABCDModules(SCTAPI_BANK_SCAN);
04134 
04135   cout << "Module Configurations for scan uploaded to RODs at time " << second_clock::universal_time() << std::endl;
04136 
04137   PrimBuilder &builder = PrimBuilder::instance();
04138   
04139   // For full histograms the formatters need to be told to produce expanded events
04140   shared_ptr<PrimListWrapper> expandFormatList(new PrimListWrapper(1));
04141   for(int i=0; i<8; i++) {
04142     if(scan.getOption(Scan::FULL)) { 
04143       builder.writeRegister(expandFormatList, FMT_EXP_MODE_EN(i), 0, 12, 0xfff);
04144     } else {
04145       builder.writeRegister(expandFormatList, FMT_EXP_MODE_EN(i), 0, 12, 0x0);
04146     }
04147   }
04148 
04149   if(synchSendPrimListAll(expandFormatList) != 0) {
04150     cout << "Expand mode list failed!\n";
04151   }
04152 
04153   if(scan.getOption(Scan::FULL)) {
04154     cout << "Formatters set for expanded mode\n";
04155   } else {
04156     cout << "Formatters set for condensed mode\n";
04157   }
04158 
04159 
04160   if(scan.getScanVariable1() == ST_TOKEN
04161      || scan.getScanVariable1() == ST_BYPASS) {
04162     PrimBuilder &builder = PrimBuilder::instance();
04163 
04164     shared_ptr<PrimListWrapper> chipSeqList(new PrimListWrapper(1));
04165     for(int i=0; i<48; i++) {
04166       builder.writeRegister(chipSeqList, Utility::EfbErrorMask(0, i), 10, 1, 1);
04167       builder.writeRegister(chipSeqList, Utility::EfbErrorMask(1, i), 10, 1, 1);
04168     }
04169     
04170     if(synchSendPrimListAll(chipSeqList) != 0) {
04171       cout << "Chip sequence error list failed!\n";
04172     }
04173 
04174     cout << "EFB chip sequence detection turned off\n";
04175   }
04176 
04177   // Check for double triggers which aren't supported by DSP code
04178   {
04179     Trigger::RODTriggers points = scan.getTrigger1()->getRODTriggers();
04180 
04181     int triggerCount = 0;
04182 
04183     for(unsigned int i=0; i<points.size(); i++) {
04184       // Count triggers
04185       if(points[i].first == L1_TRIGGER) {
04186         triggerCount++;
04187       }
04188     }
04189 
04190     // Double triggers... none of current options will cope...
04191     if(triggerCount > 1 && scan.getOption(Scan::DISTSLAVE) < 3) {
04192       shared_ptr<PrimListWrapper> dblTrigFixList(new PrimListWrapper(1));
04193 
04194       // Mask L1 and BCID checks
04195       for(int f=0; f<48; f++) {
04196     // L1ID
04197     builder.writeRegister(dblTrigFixList, Utility::EfbErrorMask(0, f), 5, 1, 1);
04198         builder.writeRegister(dblTrigFixList, Utility::EfbErrorMask(1, f), 5, 1, 1);
04199 
04200         // BCID
04201         builder.writeRegister(dblTrigFixList, Utility::EfbErrorMask(0, f), 6, 1, 1);
04202         builder.writeRegister(dblTrigFixList, Utility::EfbErrorMask(1, f), 6, 1, 1);
04203       }
04204 
04205       if(synchSendPrimListAll(dblTrigFixList)) {
04206         cout << "Double trigger BC check list failed!\n";
04207       }
04208       cout << "L1 and BCID checks masked for double triggers\n";
04209     }
04210   }
04211 
04212   cout << "Done module set-up at time " << second_clock::universal_time() << std::endl;;
04213 
04214   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
04215     // A bit over the top just to find 0, 0, 0!
04216     UINT32 mid = moduleMap.begin()->first;
04217     unsigned int partition, crate, rod, channel;
04218     getpcrc(mid, partition, crate, rod, channel);
04219 
04220     print_calib(rod);
04221   }
04222 }
04223 
04224 void SctApi::resumePolling() {
04225   getCrate()->resumePolling();
04226 }
04227 
04228 void SctApi::stopPolling() {
04229   getCrate()->stopPolling();
04230 }
04231 
04232 SctApiDDC * SctApi::getSctApiDDC() const {
04233   return m_sctApiDDC.get();
04234 }
04235 
04236 SctApiCounters publishedStats;
04237 SctApiCounters currentStats;
04238 
04239 void SctApi::updateISStats() {
04240   if(!m_isDict) return;
04241   if(publishedStats.primitiveCounter != currentStats.primitiveCounter) {
04242     ISInfoInt isInt(currentStats.primitiveCounter);
04243     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveCounter", isInt);
04244     publishedStats.primitiveCounter = currentStats.primitiveCounter;
04245   }
04246   if(publishedStats.primitiveLengthCounter != currentStats.primitiveLengthCounter) {
04247     ISInfoInt isInt(currentStats.primitiveLengthCounter);
04248     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveLengthCounter", isInt);
04249     publishedStats.primitiveLengthCounter = currentStats.primitiveLengthCounter;
04250   }
04251   if(publishedStats.primitiveOutLengthCounter != currentStats.primitiveOutLengthCounter) {
04252     ISInfoInt isInt(currentStats.primitiveOutLengthCounter);
04253     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveOutLengthCounter", isInt);
04254     publishedStats.primitiveOutLengthCounter = currentStats.primitiveOutLengthCounter;
04255   }
04256   if(publishedStats.mdspMemoryBlockCounter != currentStats.mdspMemoryBlockCounter) {
04257     ISInfoInt isInt(currentStats.mdspMemoryBlockCounter);
04258     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_mdspMemoryBlockCounter", isInt);
04259     publishedStats.mdspMemoryBlockCounter = currentStats.mdspMemoryBlockCounter;
04260   }
04261   if(publishedStats.mdspMemoryBlockLengthCounter != currentStats.mdspMemoryBlockLengthCounter) {
04262     ISInfoInt isInt(currentStats.mdspMemoryBlockLengthCounter);
04263     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_mdspMemoryBlockLengthCounter", isInt);
04264     publishedStats.mdspMemoryBlockLengthCounter = currentStats.mdspMemoryBlockLengthCounter;
04265   }
04266   if(publishedStats.sdspMemoryBlockCounter != currentStats.sdspMemoryBlockCounter) {
04267     ISInfoInt isInt(currentStats.sdspMemoryBlockCounter);
04268     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_sdspMemoryBlockCounter", isInt);
04269     publishedStats.sdspMemoryBlockCounter = currentStats.sdspMemoryBlockCounter;
04270   }
04271   if(publishedStats.sdspMemoryBlockLengthCounter != currentStats.sdspMemoryBlockLengthCounter) {
04272     ISInfoInt isInt(currentStats.sdspMemoryBlockLengthCounter);
04273     m_isDict->update("SCTAPIServer." + idiosyncrasy().uniqueName() + "_sdspMemoryBlockLengthCounter", isInt);
04274     publishedStats.sdspMemoryBlockLengthCounter = currentStats.sdspMemoryBlockLengthCounter;
04275   }
04276 }
04277 
04278 void SctApi::insertISStats() {
04279   if(!m_isDict) return;
04280   ISInfoInt isInt(0);
04281   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveCounter", isInt);
04282   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveLengthCounter", isInt);
04283   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_primitiveOutLengthCounter", isInt);
04284   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_mdspMemoryBlockCounter", isInt);
04285   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_mdspMemoryBlockLengthCounter", isInt);
04286   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_sdspMemoryBlockCounter", isInt);
04287   m_isDict->insert("SCTAPIServer." + idiosyncrasy().uniqueName() + "_sdspMemoryBlockLengthCounter", isInt);
04288 }
04289 }  // End of namespace SctApi
04290 
04291 // Some static exception handlers documented only in this file
04298 static void handle_unexpected(void) {
04299   cerr << "Unexpected exception thrown in unknown place\n";
04300 
04301   try {
04302     throw;
04303   } catch (RodException &r) {
04304     cerr << "Rod Exception\n";
04305     cerr << r.getDescriptor() << ", " << r.getData1() << ", " << r.getData2() << endl;
04306   } catch (NoImageFile &f) {
04307     cerr << "No image file exception " << f.getFileName() << endl;
04308   } catch (VmeException &v) {
04309     SctApi::Utility::decodeVme(v);
04310   } catch (HpiException &h) {
04311     cerr << "HpiException:\n";
04312     hex(cerr);
04313     cerr << h.getDescriptor() << '\n';
04314     cerr << "calcAddr: " << h.getCalcAddr() << ", readAddr: " <<
04315       h.getReadAddr() << '\n';
04316     dec(cerr);
04317   } catch (PrimListException &p) {
04318     cerr << "Primlist Exception:\n";
04319     cerr << p.getDescriptor() << " " << p.getData1() << ", " << p.getData2() << endl;
04320   } catch(std::exception &e) {
04321     cerr << "std::exception with what: " << e.what() << endl;
04322   } catch(...) {
04323     cerr << "Unknown exception type\n";
04324   }
04325 
04326   // New version of VmeInterface should cope and shutdown RCC interface properly
04327   exit(1);
04328 
04329   //  Rethrow exception, function _must_ catch (and therefore method with specification, 
04330   //   if no exceptions specified then no problem in the first place...) std::bad_exception to recover.
04331 // throw;
04332 }
04333 
04334 #if 0
04335 
04336 void buildChannelMasks() {
04337   UINT32 txchannels[2];
04338   UINT32 rxchannels[4];
04339 
04340   txchannels[0] = 0;
04341   txchannels[1] = 0;
04342   rxchannels[0] = 0;
04343   rxchannels[1] = 0;
04344   rxchannels[2] = 0;
04345   rxchannels[3] = 0;
04346 
04347   // Build channel map for modules
04348   for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
04349       mi!=moduleMap.end();
04350       mi ++) {
04351     UINT32 currMid = mi->first;
04352 
04353     cout << "Set up module " << currMid << endl;
04354 
04355     unsigned int newPartition, newCrate, newRod;
04356     // If requires look up redundant channel instead
04357 #warning "How is off-ROD redundancy handled?... (old calib_init)"
04358 
04359     unsigned int rcvChannel, sndChannel;
04360     getpcrc(currMid, newPartition, newCrate, newRod, rcvChannel);
04361 
04362     if(lookupConfig(currMid)->select == 1) {
04363       try {
04364         unsigned int redPartition, redCrate, redRod;
04365         getrpcrc(currMid, redPartition, redCrate, redRod, sndChannel);
04366 #warning "Check same ROD? (old calib_init)"
04367       } catch(ConfigurationException &c) {
04368         sndChannel = rcvChannel;
04369       }
04370     } else {
04371       sndChannel = rcvChannel;
04372     }
04373 
04374     char *mappings = config->getFibreMappings(newPartition, newCrate, newRod);
04375 
04376     int txChannel = mappings[sndChannel * 3 + 0];
04377     int rx0Channel = mappings[rcvChannel * 3 + 1];
04378     int rx1Channel = mappings[rcvChannel * 3 + 2];
04379 
04380     int txi, txval, rx0i, rx0val, rx1i, rx1val;
04381 
04382     if(txChannel<32) { txi = 0; txval = 1<<txChannel; }
04383     else { txi = 1; txval = 1<<(txChannel-32); }
04384 
04385     if(rx0Channel<32) { rx0i = 0; rx0val = 1<<rx0Channel; }
04386     else if(rx0Channel<64) { rx0i = 1; rx0val = 1<<(rx0Channel-32); }
04387     else if(rx0Channel<96) { rx0i = 2; rx0val = 1<<(rx0Channel-64); }
04388     else { rx0i = 3; rx0val = 1<<(rx0Channel-96); }
04389 
04390     if(rx1Channel<16) { rx1i = 0; rx1val = 1<<rx1Channel; }
04391     else if(rx1Channel<32) { rx1i = 1; rx1val = 1<<(rx1Channel-32); }
04392     else if(rx1Channel<64) { rx1i = 2; rx1val = 1<<(rx1Channel-64); }
04393     else { rx1i = 3; rx1val = 1<<(rx1Channel-96); }
04394 
04395     if(txchannels[txi] & txval) {
04396       cout << "Module already using this channel in this group\n";
04397     } else {
04398       txchannels[txi] |= txval;
04399     }
04400 
04401     if(rxchannels[rx0i] & rx0val) {
04402       cout << "Module already using this channel in this group\n";
04403     } else {
04404       rxchannels[rx0i] |= rx0val;
04405     }
04406 
04407     if(rxchannels[rx1i] & rx1val) {
04408       cout << "Module already using this channel in this group\n";
04409     } else {
04410       rxchannels[rx1i] |= rx1val;
04411     }
04412 
04413     delete [] mappings;
04414   }
04415 
04416   cout << "Calculated channel masks:\n";
04417   cout << hex;
04418   cout << "tx: 0x" << txchannels[0] << " 0x" << txchannels[1] << endl;
04419   cout << "rx: 0x" << rxchannels[0] << " 0x" << rxchannels[1] << " 0x" << rxchannels[2] << " 0x" << rxchannels[3] << endl;
04420   cout << dec;
04421 }
04422 
04423 #endif

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