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

Generated on Mon Feb 21 11:43:47 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5