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

SctApi.cxx

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

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