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

Generated on Thu Dec 22 20:17:10 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5