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

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

Generated on Fri Dec 16 19:38:18 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5