SctApiHisto.cxx

00001 
00009 #include "SctApi.h"
00010 #include "SctApiConsts.h"
00011 #include "SctApiDebug.h"
00012 #include "SctApiHisto.h"
00013 #include "ScanMonitorImpl.h"
00014 #include "crate.h"
00015 #include "primListWrapper.h"
00016 #include "PrimBuilder.h"
00017 #include "ConfigurationUtility.h"
00018 
00019 #include "RodCrate/RodModule.h"
00020 #include "RodCrate/TimDefine.h"
00021 #include "CommonWithDsp/primParams.h"
00022 #include "CommonWithDsp/registerIndices.h"
00023 
00024 #include "Sct/AbcdScans.h"
00025 #include "Sct/AbcdChip.h"
00026 #include "Sct/StringStreamer.h"
00027 
00028 #include "ScanResultWriter/scan.h"
00029 #include "utility.h"
00030 
00031 #include "primUtils.h"
00032 
00033 #include "VmeDecode.h"
00034 
00035 #ifdef USE_IS
00036 #include <is/infoT.h>
00037 #include "Sct/IoExceptions.h"
00038 #include "ScanResultWriter/ScanResultWriter.h"
00039 #endif
00040 #include "Sct/SctNames.h"
00041 
00042 #include "Scan.h"
00043 #include "Trigger.h"
00044 #include "SctApiException.h"
00045 
00046 #include <boost/date_time/posix_time/posix_time.hpp>
00047 #include <boost/lexical_cast.hpp>
00048 
00049 #include <algorithm>
00050 
00051 #include "Sct/MultiMessageDebugStream.h"
00052 #include "Idiosyncrasy.h"
00053 #include "ScanDefImpl.h"
00054 
00055 using namespace std;
00056 using namespace Sct;
00057 using namespace SctPixelRod;
00058 using namespace boost::posix_time;
00059 using boost::shared_ptr;
00060 
00061 namespace SctApi {
00062 
00072 int useCCode(const SctApi& api, const Scan& scan){
00073   if (api.checkDebugOption(DEBUG_SCAN_USE_CCODE)) return 1;
00074   if (scan.getOption(Scan::USE_CCODE)) return 2;
00075   if (scan.getOption(Scan::FULL)) return 3;
00076 //  if (scan.getOption(Scan::TIM)) return 3;
00077   if (scan.getOption(Scan::OPE)) return 4;
00078   return 0;
00079 }
00080 
00081 void SctApi::validateScan(boost::shared_ptr<const Scan> scan) {
00082   // Do checks on scan
00083   if(scan->getScanPoints2().size() != 0 && 
00084      scan->getScanPoints2().size() != scan->getScanPoints1().size()) {
00085     string message("Can't have two different sized scan points! (unless points(2) is empty)");
00086     cout << message << endl;
00087     if(mrs) {
00088       *mrs << "INVALID_SCAN" << MRS_ERROR 
00089            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00090        << MRS_PARAM<int>("ScanPoints(1) size",scan->getScanPoints1().size()) 
00091        << MRS_PARAM<int>("ScanPoints(2) size",scan->getScanPoints2().size())
00092            << MRS_TEXT(message)
00093            << ENDM;
00094     }
00095     throw SctApiException(message);
00096   }
00097   
00098   if(scan->getScanPoints1().empty() && scan->getScanPoints1().empty()){
00099     string message("Scan points are empty!");
00100     cout << message << endl;
00101     if(mrs) {
00102       *mrs << "INVALID_SCAN" << MRS_ERROR 
00103            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00104            << MRS_TEXT(message)
00105            << ENDM;
00106     }
00107     throw SctApiException(message);
00108   }
00109   
00110   if (scan->getTrigger1()->getRODTriggers().empty() 
00111       && scan->getTrigger2()->getRODTriggers().empty()){
00112     string message("Both triggers are empty!");
00113     cout << message << endl;
00114     if(mrs) {
00115       *mrs << "INVALID_TRIGGER" << MRS_ERROR 
00116            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00117            << MRS_TEXT(message)
00118            << ENDM;
00119     }
00120     throw SctApiException(message);
00121   }
00122   
00123   if (scan->getOption(Scan::TIM) && 
00124       !scan->getTrigger2()->getRODTriggers().empty()){
00125     string message("Can't have second trigger for TIM histogramming");
00126     cout << message << endl;
00127     if(mrs) {
00128       *mrs << "INVALID_TRIGGER" << MRS_ERROR 
00129            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00130        << MRS_PARAM<const char*>("Trigger(2)",scan->getTrigger1()->print().c_str())
00131        << MRS_TEXT(message)
00132        << ENDM;
00133     }
00134     throw SctApiException(message);
00135   }
00136   
00137   if (scan->getOption(Scan::TIM) && 
00138       !scan->getTrigger1()->isValidTIMTrigger()){
00139     string message("Trigger(1) is not a valid TIM trigger");
00140     if(mrs) {
00141       *mrs << "INVALID_TRIGGER" << MRS_ERROR 
00142            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00143            << MRS_TEXT(message)
00144        << MRS_PARAM<const char*>("Trigger(1)",scan->getTrigger1()->print().c_str())
00145        << ENDM;
00146     }
00147     throw SctApiException(message);
00148   }
00149   
00150   if(scan->getOption(Scan::TIM)==0 && 
00151      !scan->getTrigger1()->isValidRODTrigger()){
00152     string message("Trigger(1) is not a valid ROD trigger");
00153     cout << message << endl;
00154     if(mrs) {
00155       *mrs << "INVALID_TRIGGER" << MRS_ERROR 
00156            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00157            << MRS_TEXT("Trigger(1) is not a valid ROD trigger")
00158        << MRS_PARAM<const char*>("Trigger(1)",scan->getTrigger1()->print().c_str())
00159        << ENDM;
00160     }
00161     throw SctApiException(message);
00162   }
00163 
00164   if(scan->getOption(Scan::TIM)==0 &&
00165      !scan->getTrigger2()->getRODTriggers().empty() && 
00166      scan->getTrigger2()->isValidRODTrigger()){
00167     string message("Trigger(2) is not a valid ROD trigger");
00168     cout << message << endl;
00169     if(mrs) {
00170       *mrs << "INVALID_TRIGGER" << MRS_ERROR 
00171            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00172            << MRS_TEXT("Trigger(2) is not a valid ROD trigger")
00173        << MRS_PARAM<const char*>("Trigger(2)",scan->getTrigger1()->print().c_str())
00174        << ENDM;
00175     }
00176     throw SctApiException(message);
00177   }  
00178 }
00179 
00180 boost::shared_ptr<ScanMonitor> SctApi::startAsyncScan(boost::shared_ptr<const Scan> scan) {
00181   return boost::shared_ptr<ScanMonitor> ( new ScanMonitorImpl(startScan(scan, false)));
00182 }
00183 
00184 boost::shared_ptr<ScanControl> SctApi::startScan(boost::shared_ptr<const Scan> constScan, bool pollTriggers) {
00185   {
00186     boost::mutex::scoped_lock lock(log().mutex());
00187     log() << "startScan\n";
00188   }
00189   
00190 #if USE_CONST_SCAN
00191   boost::shared_ptr<const Scan> scan = constScan;
00192 #else
00193 #warning "Shouldn't do this!!!!"
00194   // Problem is multiple crates"
00195   // Move nonconst stuff to ScanEx which isn't broadcast over IPC
00196   std::cout << "Copying the constScan to a private version we can modify" << std::endl;
00197   boost::shared_ptr<Scan> scan = ScanDefImpl::clone(constScan);
00198   std::cout << "Finished copying the constScan to a private version we can modify" << std::endl;
00199 #endif
00200 
00201   // Set up parameters
00202   boost::shared_ptr<ScanEx> extra(new ScanEx);
00203 
00204 #if USE_CONST_SCAN
00205   extra->setStartTime(second_clock::universal_time());
00206 #else
00207   scan->setStartTime(second_clock::universal_time());
00208 #endif
00209 
00210   extra->diagnosticReg = 0;
00211 
00212   extra->trimScan = 0;
00213   if(scan->getScanVariable1() == ST_TRIM) {
00214     // We need to download the trim configuration
00215     extra->trimScan = 1;
00216   }
00217 
00218   cout << "Do scan " << scanNumber << ":\n";
00219   // Scan extra->
00220   scan->setRunNumber(runNumber);
00221   scan->setScanNumber(scanNumber);
00222 
00223   // Increment the scan number before doing anything else
00224   if(scan->getOption(Scan::FULL)) {
00225     // A full scan is three consecutive histograms (different time bins)
00226     scanNumber += 3;
00227   } else {
00228     scanNumber += 1;
00229   }
00230 
00231   if(mrs) {
00232     const std::string s1 = (Sct::StringStreamer << "SCAN_REQSD_" << ucid());
00233     const std::string s2 = (Sct::StringStreamer << "Scan requested on " << ucid());
00234     
00235     *mrs << s1 << MRS_INFORMATION
00236          << MRS_PARAM<int>("run", runNumber) << MRS_PARAM<int>("scan", scan->getScanNumber()) << MRS_TEXT(s2) << ENDM;
00237   }
00238 
00239   std::cout << scan->print() << std::endl;
00240 
00241   validateScan(scan);
00242 
00243   if(!checkModuleListsForScan()) {
00244     throw SctApiException("Invalid scan. Module lists check failed");
00245   }
00246 
00247   setupScanMasks(*extra, scan->getOption(Scan::DISTSLAVE), scan->getScanPoints2().size() != 0);
00248 
00249   RodLabel zeroRod = extra->rodInfo.begin()->first;
00250 
00251 #if !USE_CONST_SCAN
00252   // Tell the scan which modules are in which groups (extra already knows)
00253   for(unsigned int i = 0;
00254       i<extra->groupLists.size();
00255       i++) {
00256     scan->setModuleList(i, extra->groupLists[i]);
00257   }
00258   scan->setNGroups(extra->groupLists.size());
00259 #endif
00260 
00261   // Report module masks
00262   if(checkDebugOption(DEBUG_DIAG)) {
00263     RodScanEx &rodInfo = extra->rodInfo.find(zeroRod)->second;
00264     cout << hex << "Channels in use: 0x" << rodInfo.channels.mask0 << " 0x" << rodInfo.channels.mask1 << dec << endl;
00265 
00266     for(int i=0; i<numSlaves * 2; i++) {
00267       cout << hex << "Group channels: 0x" << rodInfo.groupChannels[i].mask0 << " 0x" << rodInfo.groupChannels[i].mask1 << dec << endl;
00268     }
00269 
00270     for(int i=0; i<numSlaves; i++) {
00271       cout << hex << "Slave channels: 0x" << rodInfo.slaveChannels[i].mask0 << " 0x" << rodInfo.slaveChannels[i].mask1 << dec << endl;
00272     }
00273 
00274     cout << "Slave DSP bit-field: " << hex << (int)rodInfo.bitFieldDSP << dec << " nSlaves: " << rodInfo.slaves << endl;
00275 
00276     hex(cout);
00277     for(int i=0; i<numSlaves; i++) {
00278       cout << "Groups on DSP " << i << ": 0x" << (int)extra->groupDspMap[i] << endl;
00279     }
00280 
00281     for(int i=0; i<2; i++) {
00282       cout << "Groups to serial port " << i << ": 0x" << (int)extra->groupSpMap[i] << endl;
00283     }
00284 
00285     for(int i=0; i<2; i++) {
00286       cout << "Groups using range list " << i << ": 0x" << (int)extra->groupRangeMap[i] << endl;
00287     }
00288     dec(cout);
00289   }
00290 
00291   for(ScanEx::RodInfoMap::const_iterator ri = extra->rodInfo.begin();
00292       ri != extra->rodInfo.end();
00293       ri++) {
00294     if(ri->second.bitFieldDSP & 0xf == 0) {
00295 #warning "Should only abort if no slaves on all RODs?"
00296       cout << "No slaves have been deemed involved in histogramming aborting\n";
00297       if(mrs) {
00298         *mrs << MRS_ERROR 
00299              << "SCAN_NODSP" 
00300              << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00301              << MRS_TEXT("No DSP matched to modules for scan")
00302              << MRS_PARAM<int>("partition", ri->first.partition)
00303              << MRS_PARAM<int>("crate", ri->first.crate)
00304              << MRS_PARAM<int>("rod", ri->first.rod)
00305              << ENDM;
00306       }
00307       // Harshly abort if one ROD doesn't have modules in a scan...
00308       throw SctApiException("Invalid scan. A ROD doesn't have any modules attached");
00309     }
00310   }
00311 
00312   if (mrs){
00313     ostringstream oss;
00314     oss << ucid() << " Starting pre scan hardware check";
00315     *mrs << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << "HARDWARE_CHECK" 
00316      << MRS_TEXT(oss.str()) << ENDM;
00317   };  
00318 
00319   if (!preScanHardwareCheck(*scan.get(), *extra)) throw SctApiException("Pre scan hardware check failed");
00320 
00321   std::cout << ucid() << " Starting pre-scan module setup at TIME " << second_clock::universal_time() << std::endl;
00322 
00323   if (mrs){
00324     ostringstream oss;
00325     oss << ucid() << " Starting pre scan module setup";
00326     *mrs << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << "MODULE_SETUP" 
00327      << MRS_TEXT(oss.str()) << ENDM;
00328   };  
00329 
00330   preScanModuleSetup(*scan.get());
00331   
00332   { 
00333     // Check for soft reset and update diagnostic reg accordingly.
00334     Trigger::RODTriggers points = scan->getTrigger1()->getRODTriggers();
00335 
00336     for(unsigned int i=0; i<points.size(); i++) {
00337       if(points[i].first == SOFT_RESET) {
00338         cout << "Do extra soft reset before trigger to mask soft reset in trigger\n";
00339         extra->diagnosticReg |= 1 << DR_SOFT_BC_RESET;
00340       }
00341     }
00342   }
00343 
00344   bool setupGood = true;
00345 
00346 
00347   if (mrs){
00348     ostringstream oss;
00349     oss << ucid() << " Setting up DSP histogramming tasks";
00350     *mrs << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << "HISTO_SETUP" 
00351      << MRS_TEXT(oss.str()) << ENDM;
00352   };  
00353 
00354 
00355   std::cout << ucid() << " Setting up histogramming tasks started at TIME " 
00356         << second_clock::universal_time()  << std::endl;
00357   
00358   try {
00359     cout << "Setup histogramming tasks ...\n";
00360     doHistogramSetup(*scan.get(), *extra);
00361     cout << " ... done setup histogramming tasks\n";
00362   } catch(SctApiException &s) {
00363     setupGood = false;
00364   }
00365 
00366   // Send MRS message first so timing not involved
00367   if(mrs) {
00368     const std::string s1 = (Sct::StringStreamer << "SCAN_STARTED_" << ucid());
00369 #if USE_CONST_SCAN
00370     const std::string s2 = (Sct::StringStreamer << "Scan started on " << ucid() << " with nGroups " << extra->getNGroups() );
00371 #else
00372     const std::string s2 = (Sct::StringStreamer << "Scan started on " << ucid() << " with nGroups " << scan->getNGroups() );
00373 #endif
00374     *mrs << s1 << MRS_INFORMATION 
00375          << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00376          << MRS_TEXT(s2) 
00377          << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
00378          << MRS_PARAM<int>("ScanType1", scan->getScanVariable1())
00379          << MRS_PARAM<int>("ScanType2", scan->getScanVariable2())
00380          << ENDM;
00381   }
00382 
00383   boost::shared_ptr<ScanControl> newScanController;
00384 
00385   try {
00386     if(setupGood) {
00387       // Decide which controller to use
00388       if(!pollTriggers) {
00389         newScanController.reset(new ScanControlAsyncHisto(*this, scan, extra));
00390       } else if(scan->getOption(Scan::TIM)) {
00391         newScanController.reset(new ScanControlTIMHisto(*this, scan, extra));
00392       } else {
00393         newScanController.reset(new ScanControlRODHisto(*this, scan, extra));
00394       }
00395 
00396       std::cout << ucid() << " Starting histogramming ...  at TIME " << second_clock::universal_time() << std::endl;
00397       newScanController->startHistogramming();
00398       std::cout << ucid() << " Histogramming started at TIME " << second_clock::universal_time() << std::endl;
00399     }
00400   } catch(SctApiException &s) {
00401     setupGood = false;
00402   }
00403 
00404   if(setupGood) {
00405     // Do polling in separate thread, first 
00406     // If external triggers then don't do polling loop
00407     if(pollTriggers) {
00408       scanController = newScanController;
00409     }
00410   }
00411 
00412   std::cout << ucid() << " finished histo setup at TIME " 
00413         << second_clock::universal_time() << std::endl;
00414 
00415   return newScanController;
00416 }
00417 
00418 void SctApi::doScan(boost::shared_ptr<const Scan> scan) {
00419   {
00420     boost::mutex::scoped_lock lock(log().mutex());
00421     log() << "doScan\n";
00422   }
00423 
00424   boost::shared_ptr<ScanControl> monitor = startScan(scan, true);
00425 
00426 // if not using a scan thread, need to do the scan loop polling here.
00427 #if ( (USE_SCAN_THREAD) ==0 )
00428   if(monitor) {
00429     std::cout << "No scan thread - doing the scan loop polling in same thread!" << std::endl;
00430     // But not for now
00431     scanLoop();
00432   }
00433 #endif
00434 }
00435 
00436 void SctApi::awaitScan() {
00437   while((scanController || m_inScanLoop) || m_inRawScanLoop) {
00438     sleep(1);
00439   }
00440 }
00441 
00442 /* Called by scanPollingThread */
00443 void SctApi::scanLoop() {
00444   // Do this before getting the scan out
00445   m_inScanLoop = true;
00446 
00447   boost::shared_ptr<ScanControl> control;
00448 
00449   // Effectively kills scanController... ie should have a different name
00450   swap(control, scanController);
00451 
00452   // For the debug methods to talk to
00453   lastScanController = control;
00454 
00455   if(!control) {
00456     cout << "Given null scan aborting!\n";
00457     return;
00458   }
00459 
00460   control->initialisePolling();
00461 
00462   int pollReturn = pollHistogramming(control, 3);
00463 
00464   cout << "pollHistogramming complete (" << pollReturn << ")\n";
00465 
00466   control->finishHistogram(pollReturn == 0);
00467 
00468   // Do this before getting the scan out
00469   m_inScanLoop = false;
00470 }
00471 
00472 void SctApi::scanPollingThread() {
00473   cout << "SCAN: Start polling thread\n";
00474   while(!m_stopPolling) {
00475     usleep(500000);
00476     if(scanController) {
00477       scanLoop();
00478     }
00479   }
00480 }
00481 
00482 void SctApi::setupEventTrapping(const Scan &scan, const ScanEx &ex, const RodLabel rod, boost::shared_ptr<PrimListWrapper> primList) {
00483   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00484 
00485   // Set up each slave individually
00486   for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
00487     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00488       int match;
00489       int modulus;            // Trap if (count % mod) == rem
00490       int remainder;
00491 
00492       switch(scan.getOption(Scan::DISTSLAVE)) {
00493       case 0:
00494         // Single slave
00495         match = 0;
00496         modulus = 1;
00497         remainder = 0;
00498 
00499         if(scan.getOption(Scan::NTH) > 1) {
00500           // Only trap every nth trigger
00501           modulus = scan.getOption(Scan::NTH);
00502           remainder = scan.getOption(Scan::NTH_REM);
00503         }
00504         break;
00505       case 1:
00506         // Group distribution
00507         match = slaveNumber;  // Match number set by histo control to distribute to slaves
00508         modulus = 1;
00509         remainder = 0;
00510         break;
00511       case 2:
00512         // Router distribution, between 4 DSPs
00513         match = 0;
00514         modulus = rodInfo.slaves;
00515         remainder = slaveNumber;
00516 
00517         if(scan.getOption(Scan::NTH) > 1) {
00518           modulus = rodInfo.slaves * scan.getOption(Scan::NTH);
00519           remainder = slaveNumber * scan.getOption(Scan::NTH) + scan.getOption(Scan::NTH_REM);
00520         }
00521         break;
00522       default:
00523         match = 0;
00524         modulus = 1;
00525         remainder = 0;
00526         break;
00527       }
00528 
00529       eventTrapSetup(0x1 << slaveNumber, 
00530                      match, modulus, remainder,
00531                      scan.getOption(Scan::TIM), checkDebugOption(DEBUG_SCAN_ERROR_TRAP_ALL), primList);
00532     }
00533   }
00534 }
00535 
00536 void SctApi::setupEventDump(const Scan &scan, const ScanEx &ex, const RodLabel rod, boost::shared_ptr<PrimListWrapper> primList) {
00537   if(!(checkDebugOption(DEBUG_SCAN_ERROR_TRAP) && scan.getOption(Scan::DEBUG))) return;
00538 
00539   int slaveNumber = 2;
00540 
00541   // No difference depending where its run...
00542   {
00543     // Trap all events as errors
00544     long *evData = new long[sizeof(EVENT_TRAP_SETUP_IN)/sizeof(long)];
00545 
00546     EVENT_TRAP_SETUP_IN &primData = *(EVENT_TRAP_SETUP_IN*)evData;
00547 
00548 #if R_EVENT_TRAP_SETUP == 103
00549     primData.slvBits = 0x1 << slaveNumber;
00550     primData.numberOfEvents = COLLECT_FOREVER;
00551     primData.timeoutInUsec = 0x30000;
00552 
00553     primData.extRouterSetup = 0;
00554 
00555     // This tells the setup code to change the trapRemainder
00556     //  Only matters if setting up more than one slave
00557     primData.distribute = TRAP_DISTRIB_NEITHER;
00558 
00559     primData.releaseFrames = 0;
00560     primData.permitBackPressure = 1;
00561     primData.dataMode = 0;                        // Data or Event mode
00562     primData.sLink = 0;                           // Where to pick events (dsp or router)
00563 
00564     primData.format = TRAP_FMT_ERROR;             // Slink format
00565     primData.trapStray = 1;                       // Trap stray events
00566     primData.iterLimit = 2;                       // Don't keep them long
00567 
00568     // Trap events from ROD triggers
00569     primData.trapConfig[0] = TRAP_CFG_ROD_EVT;
00570     primData.trapExclusionFlag[0] = 0;            // Don't exclude anything
00571     primData.trapFunction[0] = TRAP_FXN_RESYNCH;
00572 
00573     primData.trapMatch[0] = 0;                    // = slave number??
00574     primData.trapModulus[0] = 1;                  // Trap if (count % mod) == rem
00575     primData.trapRemainder[0] = 0;
00576 
00577     // Trap one is idle
00578     primData.trapConfig[1] = TRAP_CFG_IDLE;
00579     primData.trapExclusionFlag[1] = 0;
00580     primData.trapFunction[1] = 0;
00581 
00582     primData.trapMatch[1] = 0; 
00583     primData.trapModulus[1] = 0;
00584     primData.trapRemainder[1] = 0;
00585 #else 
00586 #error "Event trapping not compiled (new Primitive definition)!"
00587 #endif
00588     primList->addPrimitive(RodPrimitive(sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32) + 4, 
00589                                         0, EVENT_TRAP_SETUP, R_EVENT_TRAP_SETUP, evData),
00590                            evData);
00591   }
00592 
00593   // Start event trapping on slave 2
00594   startEventTrap(slaveNumber, primList);
00595 
00596   // Start a dump to remove the events...
00597   {
00598     long *taskData = new long[sizeof(START_TASK_IN)/sizeof(long)];
00599 
00600     for(unsigned int i=0; i<sizeof(START_TASK_IN)/sizeof(long); i++) {
00601       taskData[i] = 0;
00602     }
00603 
00604     START_TASK_IN &taskPrim = *(START_TASK_IN *)taskData;
00605 
00606     taskPrim.taskType = RESYNCH_TASK;
00607     taskPrim.taskRevision = R_RESYNCH_TASK;
00608     taskPrim.priority = 1; // Top???
00609     taskPrim.completionFlag = 1; 
00610 
00611     RESYNCH_TASK_IN &resynch = taskPrim.taskStruct.resynchTaskIn;
00612 
00613     resynch.errorType = 0;
00614 
00615     shared_ptr<PrimListWrapper> myList(new PrimListWrapper(4));
00616 
00617     myList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/sizeof(UINT32),
00618                                       3, START_TASK, R_START_TASK, taskData),
00619                          taskData);
00620 
00621     PrimBuilder::instance().slavePrimList(primList, myList, slaveNumber, true, true);
00622   }
00623 }
00624 
00625 void SctApi::startEventTrapping(const Scan &scan, const ScanEx &ex, const RodLabel rod, shared_ptr<PrimListWrapper> primList) {
00626   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00627 
00628   for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
00629     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00630       startEventTrap(slaveNumber, primList);
00631     }
00632   }
00633 }
00634 
00635 void SctApi::setupHistogramming(const Scan &scan, const ScanEx &ex, const RodLabel rod, bool tim, 
00636                                  boost::shared_ptr<PrimListWrapper> primList) {
00637   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00638 
00639   int nBins = scan.getScanPoints1().size();
00640   if(!scan.getOption(Scan::BITS32)) {
00641     if(nBins%2 == 1) {
00642       nBins += 1;
00643     }
00644   }
00645 
00646   for(int slaveNumber = 0; slaveNumber < 4; slaveNumber ++) {
00647     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00648       // Primitive
00649       long *histoData = new long[sizeof(HISTOGRAM_SETUP_IN)/sizeof(UINT32)];
00650 
00651       HISTOGRAM_SETUP_IN &primData = *(HISTOGRAM_SETUP_IN*)histoData;
00652 
00653 #if (R_HISTOGRAM_SETUP == 108)
00654       primData.base = (UINT32 *)0xffffffff;//  HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00655       primData.nBins = nBins; 
00656 
00657       primData.dataType[0] = scan.getScanVariable1();
00658       primData.dataType[1] = scan.getScanVariable2();
00659 
00660       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00661 
00662       if(useCCode(*this, scan)) {
00663         primData.routineType = HISTO_ROUTINE_C;
00664     {
00665       Sct::MultiMessageDebugStream m(true,false,true);
00666       m << ucid() << " is using CCODE rather than ASM for histogramming (reason="
00667         << useCCode(*this,scan) << ")";
00668     };
00669       } else {
00670         primData.routineType = HISTO_ROUTINE_ASM;
00671       }
00672 
00673       // The meanings of the histogramming options have been unilaterally redefined by Douglas...
00674       // doChipOcc
00675       //   supported with both ASM and C histogramming
00676       primData.opt[0] = scan.getOption(Scan::OPE)?1:0;
00677       // dataFormat
00678       //   not supported by either ASM or C histogramming
00679       primData.opt[1] = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00680       // verbose
00681       //   only supported by C histogramming
00682       primData.opt[2] = 0;
00683       // unused
00684       primData.opt[3] = 0;
00685 
00686       UINT8 groupMap = ex.groupDspMap[slaveNumber];
00687 
00688       primData.validModules[0] = 0;
00689       primData.validModules[1] = 0;
00690 
00691       primData.moduleRangeMap[0][0] = 0;
00692       primData.moduleRangeMap[0][1] = 0;
00693       primData.moduleRangeMap[1][0] = 0;
00694       primData.moduleRangeMap[1][1] = 0;
00695 
00696       for(int i=0; i<8; i++) {
00697         if(groupMap & (1<<i)) {
00698           primData.validModules[0] |= rodInfo.groupChannels[i].mask0;          // Modules to this slave
00699           primData.validModules[1] |= rodInfo.groupChannels[i].mask1;          //    32-47 in low 16 bits
00700 
00701           if(ex.groupSpMap[0] & (1<<i)) {
00702             primData.moduleRangeMap[0][0] |= rodInfo.groupChannels[i].mask0;
00703             primData.moduleRangeMap[0][1] |= rodInfo.groupChannels[i].mask1;
00704           }
00705           if(ex.groupSpMap[1] & (1<<i)) {
00706             primData.moduleRangeMap[1][0] |= rodInfo.groupChannels[i].mask0;
00707             primData.moduleRangeMap[1][1] |= rodInfo.groupChannels[i].mask1;
00708           }
00709         }
00710       }
00711 
00712       primData.xPtr[0] = (FLOAT32 *)0xffffffff; // 0x3f00000;                    // Where the fit data will be stored
00713       primData.xPtr[1] = (FLOAT32 *)0xffffffff; // 0x3f01000; 
00714 #elif (R_HISTOGRAM_SETUP == 105) || (R_HISTOGRAM_SETUP == 107)
00715       primData.base = (UINT32 *)0xffffffff;//  HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00716       primData.nBins = nBins; 
00717 
00718       primData.padding[0] = 0;
00719       primData.padding[1] = 0;
00720 
00721       primData.dataType[0] = scan.getScanVariable1();
00722       primData.dataType[1] = scan.getScanVariable2();
00723 
00724       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00725 
00726       // arrangement
00727       primData.opt[0] = HISTOGRAM_SLICE; // scan.getOption(Scan::FORMAT)?HISTOGRAM_SLICE:HISTOGRAM_BLOCK;
00728       // dataFormat
00729       primData.opt[1] = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00730       // unused
00731       primData.opt[2] = 0;
00732 #if(R_HISTOGRAM_SETUP == 107)
00733       primData.opt[3] = 0;
00734 #endif
00735 
00736       UINT8 groupMap = ex.groupDspMap[slaveNumber];
00737 
00738       primData.validModules[0] = 0;
00739       primData.validModules[1] = 0;
00740 
00741       primData.moduleRangeMap[0][0] = 0;
00742       primData.moduleRangeMap[0][1] = 0;
00743       primData.moduleRangeMap[1][0] = 0;
00744       primData.moduleRangeMap[1][1] = 0;
00745 
00746       for(int i=0; i<8; i++) {
00747         if(groupMap & (1<<i)) {
00748           primData.validModules[0] |= rodInfo.groupChannels[i].mask0;          // Modules to this slave
00749           primData.validModules[1] |= rodInfo.groupChannels[i].mask1;          //    32-47 in low 16 bits
00750 
00751           if(ex.groupSpMap[0] & (1<<i)) {
00752             primData.moduleRangeMap[0][0] |= rodInfo.groupChannels[i].mask0;
00753             primData.moduleRangeMap[0][1] |= rodInfo.groupChannels[i].mask1;
00754           }
00755           if(ex.groupSpMap[1] & (1<<i)) {
00756             primData.moduleRangeMap[1][0] |= rodInfo.groupChannels[i].mask0;
00757             primData.moduleRangeMap[1][1] |= rodInfo.groupChannels[i].mask1;
00758           }
00759         }
00760       }
00761 
00762       primData.xPtr[0] = (FLOAT32 *)0xffffffff; // 0x3f00000;                    // Where the fit data will be stored
00763       primData.xPtr[1] = (FLOAT32 *)0xffffffff; // 0x3f01000; 
00764 #elif R_HISTOGRAM_SETUP == 104
00765       primData.base = (UINT32 *)0xffffffff; // HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00766       primData.rodType = ROD_TYPE_SCT;
00767       primData.nBins = nBins;
00768 
00769       primData.padding[0] = 0;
00770       primData.padding[1] = 0;
00771 
00772       primData.dataType[0] = scan.getScanVariable1();
00773       primData.dataType[1] = scan.getScanVariable2();
00774 
00780       primData.arrangement = HISTOGRAM_SLICE;
00781       primData.dataFormat = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00782       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00783       primData.unused = 0;
00784 
00785       if(scan.getOption(Scan::DISTSLAVE) == 1) {
00786         primData.validModules[0] = rodInfo.groupChannels[slaveNumber][0];          // Modules to this slave
00787         primData.validModules[1] = rodInfo.groupChannels[slaveNumber][1];          //    32-47 in low 16 bits
00788         primData.moduleRangeMap[0][0] = rodInfo.groupChannels[slaveNumber][0];     // All modules use rangemap 0
00789         primData.moduleRangeMap[0][1] = rodInfo.groupChannels[slaveNumber][1];
00790       } else {
00791         primData.validModules[0] = rodInfo.channels[0];                          // Modules to this slave
00792         primData.validModules[1] = rodInfo.channels[1];                          //    32-47 in low 16 bits
00793         primData.moduleRangeMap[0][0] = rodInfo.channels[0];                     // All modules use rangemap 0
00794         primData.moduleRangeMap[0][1] = rodInfo.channels[1];
00795       }
00796       primData.moduleRangeMap[1][0] = 0;                                    // No modules for rangemap 1
00797       primData.moduleRangeMap[1][1] = 0;
00798 
00799       primData.xPtr[0] = (FLOAT32 *)0x3f00000;                              // Where the fit data will be stored
00800       primData.xPtr[1] = (FLOAT32 *)0x3f01000; 
00801 #else 
00802 #error "Histogram setup not compiled (new Primitive definition)!"
00803 #endif
00804 
00805       long *taskData = new long[sizeof(START_TASK_IN)/sizeof(UINT32)];
00806 
00807       for(unsigned int i=0; i<sizeof(START_TASK_IN)/sizeof(UINT32); i++) {
00808         taskData[i] = 0;
00809       }
00810 
00811       START_TASK_IN &taskPrim = *(START_TASK_IN *)taskData;
00812 
00813       taskPrim.taskType = HISTOGRAM_TASK;
00814       taskPrim.taskRevision = R_HISTOGRAM_TASK;
00815       taskPrim.priority = 1; // Top???
00816       taskPrim.completionFlag = 1; 
00817 
00818       HISTOGRAM_TASK_IN &histoTaskData = taskPrim.taskStruct.histogramTaskIn;
00819 
00820       histoTaskData.nEvents = COLLECT_FOREVER;
00821       if(tim) {
00822         histoTaskData.controlFlag = LOCAL_SET_TRIG;
00823       } else {
00824         histoTaskData.controlFlag = MASTER_HREG;
00825       }
00826 
00827       boost::shared_ptr<PrimListWrapper> myList(new PrimListWrapper(4));
00828 
00829       myList->addPrimitive(RodPrimitive(4 + sizeof(HISTOGRAM_SETUP_IN)/sizeof(UINT32), 
00830                                         2, HISTOGRAM_SETUP, R_HISTOGRAM_SETUP, histoData),
00831                            histoData);
00832       myList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/sizeof(UINT32),
00833                                         3, START_TASK, R_START_TASK, taskData),
00834                            taskData);
00835 
00836       PrimBuilder::instance().slavePrimList(primList, myList, slaveNumber, true, true);
00837     }
00838   }
00839 }
00840 
00841 void SctApi::startHistogramTask(const Scan &scan, const ScanEx &ex, const RodLabel rod, 
00842                                 unsigned int startBin, unsigned int nBins, unsigned int nTrigs,
00843                                 boost::shared_ptr<PrimListWrapper> primList) {
00844   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00845 
00846   // The number of bins in the variable list has to be nBins...
00847   unsigned int allBins = nBins;
00848 
00849   long *ctrlData = new long[sizeof(START_TASK_IN)/sizeof(UINT32) + allBins * 2];
00850 
00851   for(unsigned int i=0; i<sizeof(START_TASK_IN)/sizeof(UINT32) + allBins * 2; i++) {
00852     ctrlData[i] = 0;
00853   }
00854 
00855   struct START_TASK_IN &primData = *(START_TASK_IN*)ctrlData;
00856   struct HISTOGRAM_CTRL_TASK_IN &taskData = primData.taskStruct.histoCtrlTaskIn; 
00857 
00858 #if (R_HISTOGRAM_CTRL_TASK == 107)
00859   primData.taskType = HISTOGRAM_CTRL_TASK;
00860   primData.taskRevision = R_HISTOGRAM_CTRL_TASK;
00861   primData.priority = 1;
00862   primData.completionFlag = 1; 
00863 
00864   taskData.slvBits = rodInfo.bitFieldDSP;   // Which DSPs to use
00865 
00866   if(scan.getScanPoints2().size() > 0) {
00867     taskData.port = SP_BOTH;
00868   } else {
00869     //@todo Should this be SP_BOTH??? 
00870     // The histogramming itself can only use one port...
00871     // But this may tell the engine to configure modules using both ports?
00872     // Which would be good to do anyway
00873     //taskData.port = SP_BOTH;
00874     taskData.port = SP0;
00875   }
00876 
00877   taskData.configRegister[0] = scan.getScanVariable1(); // ST_VTHR;
00878   taskData.configRegister[1] = scan.getScanVariable2(); // ST_VTHR;
00879 
00880   taskData.configSctSet = Utility::translateBank(SCTAPI_BANK_SCAN);
00881 
00882   // Which bit of configuration to send, unless this is a trim scan then basic should be enough
00883 #if (R_RW_MODULE_DATA>=103)
00884   if(!ex.trimScan) {
00885     taskData.dataSet = CONFIG_MODULE_BASIC; 
00886   }else{ 
00887     taskData.dataSet = CONFIG_MODULE_TRIM;               // Which bit of configuration to send
00888   }
00889 #else
00890 #warning "Using old dataSet values (pre 11 April 2005 dsp code) AJB wonders if this is actually #defined or typedefed to the same values..."
00891   if(!ex.trimScan) {
00892     taskData.dataSet = MODULE_BASIC; 
00893   }else{ 
00894     taskData.dataSet = MODULE_TRIM;               // Which bit of configuration to send
00895   }
00896 #endif
00897 
00898   taskData.groupRangeMap[0] = ex.groupRangeMap[0];
00899   taskData.groupRangeMap[1] = ex.groupRangeMap[1];
00900 
00901   taskData.groupDSPMap[0] = ex.groupDspMap[0];
00902   taskData.groupDSPMap[1] = ex.groupDspMap[1];
00903   taskData.groupDSPMap[2] = ex.groupDspMap[2];
00904   taskData.groupDSPMap[3] = ex.groupDspMap[3];
00905 
00906   taskData.groupSPMap[0] = ex.groupSpMap[0];
00907   taskData.groupSPMap[1] = ex.groupSpMap[1];
00908 
00909   taskData.globalCtrl = 0;              // Don't want to take control for internal triggers
00910   taskData.syncLevel = 0;               //  So don't need synchronisation 
00911 
00912   taskData.histoBase = (UINT32*)0xffffffff; // HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00913 
00914   taskData.doChipOcc = scan.getOption(Scan::OPE)?1:0;
00915   taskData.dataFormat = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;
00916   taskData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00917   taskData.unused1 = 0;
00918 
00919   taskData.extSetup = 0xff;                    // This is specifies which setup tasks are done externally (to the control task)
00920   taskData.dataPath = DATA_PATH_NORMAL;        // Other option is INMEM (presumably TestBench based)
00921   taskData.capture = 0;
00922   taskData.useRangeList = 0;                   // Major difference from Doug's example!
00923 
00924   taskData.repetitions = nTrigs;
00925   taskData.nBins = nBins;
00926   taskData.bin0 = startBin;
00927 
00928   // Ignore range list data 
00929   for(int i=0; i<5; i++) {
00930     taskData.rangeList[0].xPair[i].x0 = 0.0;
00931     taskData.rangeList[1].xPair[i].x0 = 0.0;
00932     taskData.rangeList[0].xPair[i].delta_x = 0.0;
00933     taskData.rangeList[1].xPair[i].delta_x = 0.0;
00934   }
00935 
00936   // X data lists
00937   taskData.dataPtr[0] = (FLOAT32 *)0xffffffff;   // Data for group 1               Append to end of primitive
00938   taskData.dataPtr[1] = (FLOAT32 *)0xffffffff;   // Data for group 2
00939 
00940   // Clear trigger sequences
00941   for(int i=0; i<N_CMD_LIST_CMDS; i++) {            // from primParams.h
00942     taskData.triggerSequence[0].cmd[i] = NO_CMD;    // Set a trigger sequence
00943     taskData.triggerSequence[1].cmd[i] = NO_CMD;    // Set a trigger sequence
00944     taskData.triggerSequence[0].data[i] = 0;        // Set a trigger sequence
00945     taskData.triggerSequence[1].data[i] = 0;        // Set a trigger sequence
00946   }
00947 
00948 
00949 //    // Two L1As (illegal without delay?!)
00950 //    taskData.triggerSequence[0].cmd[0] = L1_TRIGGER;
00951 //    taskData.triggerSequence[1].cmd[0] = L1_TRIGGER;
00952 //    taskData.triggerSequence[0].cmd[1] = L1_TRIGGER;
00953 //    taskData.triggerSequence[1].cmd[1] = L1_TRIGGER;
00954 
00955   Trigger::RODTriggers points = scan.getTrigger1()->getRODTriggers();
00956 
00957   for(unsigned int i=0; i<points.size(); i++) {
00958     taskData.triggerSequence[0].cmd[i] = points[i].first;        // Set a trigger sequence
00959     taskData.triggerSequence[0].data[i] = points[i].second;      // Set a trigger sequence
00960   }
00961 
00962   if(scan.getScanPoints2().size() > 0) {
00963     points = scan.getTrigger2()->getRODTriggers();
00964 
00965     for(unsigned int i=0; i<points.size(); i++) {
00966       taskData.triggerSequence[1].cmd[i] = points[i].first;      // Set a trigger sequence 2
00967       taskData.triggerSequence[1].data[i] = points[i].second;    // Set a trigger sequence 2
00968     }
00969   } else {
00970     // Leave as default
00971   }
00972 
00973 //    taskData.triggerSequence[0].cmd[0] = CALIBRATION_PULSE;
00974 //    taskData.triggerSequence[0].cmd[1] = DELAY;
00975 //    taskData.triggerSequence[0].cmd[2] = L1_TRIGGER;
00976 
00977 //    taskData.triggerSequence[0].data[1] = 0x81;
00978 
00979   unsigned short cmd, data;
00980 
00981   scan.getTrigger1()->getCommIncr(cmd, data);
00982   taskData.incCmd[0] = cmd;
00983   taskData.incData[0] = data;
00984   scan.getTrigger2()->getCommIncr(cmd, data);
00985   taskData.incCmd[1] = cmd;
00986   taskData.incData[1] = data;
00987 
00988   taskData.calLineLoop = scan.getOption(Scan::LOOPCALLINE);
00989   if(scan.getOption(Scan::DISTSLAVE) == 2) {
00990     taskData.distributionToggle = ROUTER_DISTRIB;
00991   } else {
00992     taskData.distributionToggle = MODULE_GROUP;
00993   }
00994 
00995   for(int i=0; i<10; i++) {
00996     taskData.genData[i] = 0;
00997   }
00998 
00999   // Defined groups
01000   taskData.genData[0] = 0xff;
01001 
01002   if(scan.getScanPoints2().size() > 0) {
01003     taskData.genData[1] = 1;
01004     taskData.genData[2] = 0x0200; // 0301;
01005   }
01006 
01007 #elif (R_HISTOGRAM_CTRL_TASK == 105)
01008   primData.taskType = HISTOGRAM_CTRL_TASK;
01009   primData.taskRevision = R_HISTOGRAM_CTRL_TASK;
01010   primData.priority = 0; // Top???
01011   primData.completionFlag = 1; 
01012 
01013   taskData.slvBits = 0xf;             // Use all slaves
01014   taskData.configSctSet = translateBank(SCTAPI_BANK_PHYSICS);
01015   // Not an array yet
01016 //    taskData.configRegister[0] = 0;     // V_THR ??
01017 //    taskData.configRegister[1] = 0;     // V_THR ??
01018   taskData.dataSet = 0;               // ??
01019   taskData.useRangeList = 0;          // ??
01020   taskData.groupRangeMap[0] = 0;      // No range map
01021   taskData.groupRangeMap[1] = 0;      //  ditto
01022   taskData.cmdBuff = CMD_BUFFER_BOTH;     // Which serial port to use
01023   taskData.dataPtr[0] = group1Data;   // Data for group 1
01024   taskData.dataPtr[1] = group2Data;   // Data for group 2
01025   taskData.repetitions = 10;          // Make it stop quickly 10 events
01026   taskData.nBins = 10;                // 10 bins
01027   taskData.bin0 = 0;                  // Start at 0
01028 
01029   taskData.triggerSequence[0];        // Set a trigger sequence
01030   taskData.triggerSequence[1];        // Set a trigger sequence
01031 
01032   taskData.incCmd[0] = 0;
01033   taskData.incCmd[1] = 0;
01034   taskData.calLineLoop = 0;  // Doesn't work yet??
01035 
01036   taskData.distributionToggle = 0;  // ??
01037   taskData.incData[0] = 1;
01038   taskData.incData[1] = 1;
01039 
01040   taskData.groupSPMap[0] = 0;
01041   taskData.groupSPMap[1] = 0;
01042 #else  // Unknown R_HISTOGRAM_CTRL_TASK
01043 #error "Histogram Task not compiled (new Primitive definition)!" 
01044 #endif
01045 
01046   int offset = sizeof(START_TASK_IN)/sizeof(UINT32);
01047 
01048   // Copy real bins
01049   for(unsigned int i=0; i<allBins; i++) {
01050     ctrlData[offset + i] = *(UINT32 *)&(scan.getScanPoints1()[i]);
01051     if(scan.getScanPoints2().size() == 0) {
01052       ctrlData[offset + allBins + i] = *(UINT32*)&(scan.getScanPoints1()[i]);
01053     } else {
01054       ctrlData[offset + allBins + i] = *(UINT32*)&(scan.getScanPoints2()[i]);
01055     }
01056   }
01057 
01058   primList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/sizeof(UINT32) + allBins * 2, 
01059                                       0, START_TASK, R_START_TASK, ctrlData),
01060                          ctrlData);
01061 }
01062 
01063 /*
01064   Stop histogram control in master
01065   Histogram and event trapping in slaves
01066 
01067   *********** XXX Send them individually as it doesn't seem to work otherwise ***************
01068 */
01069 void SctApi::stopHistogramming(const ScanEx &ex) {
01070   for(ScanEx::RodInfoMap::const_iterator ri = ex.rodInfo.begin();
01071       ri != ex.rodInfo.end();
01072       ri++) {
01073     const RodLabel &rod = ri->first;
01074 
01075     {
01076       boost::mutex::scoped_lock lock(log().mutex());
01077       log() << "Stop histogramming (controlled)\n";
01078     }
01079 //  stopEvTrap(0);
01080 
01081 //  taskOp(16, 0, 0, -1);   // Stop histogram control task
01082 
01083 //  taskOp(32, 0, 0, 0);     // Stop histogram task
01084 
01085     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(2));
01086 
01087     PrimBuilder &builder = PrimBuilder::instance();
01088     builder.taskOp(primList, HISTOGRAM_CTRL_TASK, TASK_STOP, 0);
01089 
01090     {
01091       boost::mutex::scoped_lock lock(log().mutex());
01092       log() << "Stop histo control task\n";
01093     }
01094     sendPrimList(rod.rod, primList);
01095 
01096     awaitResponse(rod.rod, 5);
01097     primList->clear();
01098 
01099     cout << "Done kill control task\n";
01100 
01101     for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
01102       // Kill all tasks!!!!
01103       boost::shared_ptr<PrimListWrapper> slList(new PrimListWrapper(1));
01104 
01105       // Stop Slave histogramming task
01106 
01107       builder.taskOp(slList, HISTOGRAM_TASK, TASK_STOP, 0);
01108 
01109       PrimBuilder::instance().slavePrimList(primList, slList, slaveNumber, true, true);
01110       {
01111         boost::mutex::scoped_lock lock(log().mutex());
01112         log() << "Stop slave histogram task " << slaveNumber << endl;
01113       }
01114       sendPrimList(rod.rod, primList);
01115       awaitResponse(rod.rod, 5);
01116       slList->clear();
01117       primList->clear();
01118 
01119       cout << "Done kill histogram task\n";
01120 
01121       stopEventTrap(slaveNumber, primList);
01122 
01123       // Reset router trapping
01124       PrimBuilder::instance().writeRegister(primList, RTR_TRAP_RESET(slaveNumber), RTR_TRAP_RESET_O, 1, 1);
01125 
01126       {
01127         boost::mutex::scoped_lock lock(log().mutex());
01128         log() << "Stop Event trapping on slave " << slaveNumber << endl;
01129       }
01130       sendPrimList(rod.rod, primList);
01131 
01132       awaitResponse(rod.rod, 5);
01133       primList->clear();
01134 
01135       cout << "Done kill event trapping\n";
01136     }
01137   }
01138 
01139   //  sendPrimList(ex.rod, primList);
01140   //  awaitResponse(ex.rod, 2);
01141   cout << "Done kill histogramming tasks\n";
01142 }
01143 
01144 ScanControl::ScanControl(SctApi &api) : api(api) {}
01145 
01146 #if USE_CONST_SCAN
01147 void  ScanControl::setModuleScanCacheToLastPointInScan(SctApi &api, boost::shared_ptr<const Scan> scan,
01148                                boost::shared_ptr<const ScanEx> scanEx) {
01149 #else
01150 void  ScanControl::setModuleScanCacheToLastPointInScan(SctApi &api, boost::shared_ptr<const Scan> scan) {
01151 #endif
01152   if (api.checkDebugOption(DEBUG_MODULE_CONFIG)) {
01153     std::cout << "setModuleScanCacheToLastPointInScan setting the following values:\n"
01154           << "mid\tsn\tvariable\tvalue\tvar 1/2?" << std::endl;
01155   }
01156 
01157 #if USE_CONST_SCAN
01158   for(unsigned int group = 0; group < scanEx->getNGroups(); group ++) {
01159     const ModuleList &groupList = scanEx->getModuleList(group);
01160 #else
01161   for(unsigned int group = 0; group < scan->getNGroups(); group ++) {
01162     const ModuleList &groupList = scan->getModuleList(group);
01163 #endif
01164     for(ModuleList::const_iterator mi = groupList.begin();
01165     mi!=groupList.end();
01166     mi ++) {
01167       
01168       string sn = *mi;
01169       UINT32 mid = api.findModule(sn);
01170       {
01171     unsigned int partition, crate, rod, channel;
01172     Utility::getpcrc(mid, partition, crate, rod, channel);
01173     if (api.idiosyncrasy().ucid() != Sct::UCID(partition, crate)) {
01174       std::cout << "\nWARNING!!! I didnt think that sn " << sn << " was on this crate!!!\n" 
01175             << __FILE__ << ":" <<  __LINE__ << std::endl;
01176       continue;  // next module
01177     }
01178       }
01179       boost::shared_ptr<SctApiConfigCache::ModuleBanks> banks = api.getModuleConfigCache().getFromMid(mid);
01180       if (!banks.get()){
01181     if (api.mrs) {
01182       *api.mrs << "NO_CACHED_CONFIG" << MRS_ERROR
01183            << MRS_QUALIF("SctApi")
01184            << MRS_PARAM<int>("mid", mid) 
01185            << MRS_TEXT("No cache at all available when setting cache at end of scan") << ENDM;
01186     }else{
01187       std::cout << "ERROR! No cache at all available when setting cache at end of scan, mid" << mid << std::endl; 
01188     }
01189     continue;
01190       }
01191       boost::shared_ptr<ABCDModule> config = banks->get(SCTAPI_BANK_SCAN);
01192       if (!config.get()){
01193     if (api.mrs) {
01194       *api.mrs << "NO_CACHED_CONFIG" << MRS_ERROR
01195            << MRS_QUALIF("SctApi")
01196            << MRS_PARAM<int>("mid", mid) 
01197            << MRS_TEXT("No SCAN cache available when setting cache at end of scan") << ENDM;
01198     }else{
01199       std::cout << "ERROR! No SCAN cache available when setting cache at end of scan, mid" << mid << std::endl; 
01200     }
01201     continue;
01202       }
01203 
01204       if (group<4){
01205     const ::SctApi::Scan::ScanPoints points = scan->getScanPoints1();
01206     if (!points.empty() && scan->getScanVariable1()!=0 ) {
01207       ConfigUtility::modifyVar(config.get(), scan->getScanVariable1(), points[points.size()-1]);
01208       if(api.checkDebugOption(DEBUG_MODULE_CONFIG)){
01209         std::cout << mid << "\t" << sn  << "\t" << scan->getScanVariable1()  << "\t"
01210               << points[points.size()-1]  << "\t" << "\t[1]" << std::endl;
01211       }
01212     }
01213       }else{
01214     const ::SctApi::Scan::ScanPoints points = scan->getScanPoints2();
01215     if (!points.empty() && scan->getScanVariable2()!=0 ) {
01216       ConfigUtility::modifyVar(config.get(), scan->getScanVariable2(), points[points.size()-1]);
01217       if(api.checkDebugOption(DEBUG_MODULE_CONFIG)){
01218         std::cout << mid << "\t" << sn  << "\t" << scan->getScanVariable1()  << "\t"
01219               << points[points.size()-1]  << "\t" << "\t[2]" << std::endl;
01220       }
01221     }
01222       }
01223     }
01224   }
01225   if(api.checkDebugOption(DEBUG_MODULE_CONFIG)) std::cout << std::endl;
01226 }
01227 
01228 void ScanControlRODHisto::readHistograms() {
01229   time_t saveTime;
01230   saveTime = time(NULL);
01231 
01232   /* Loop over RODs and release memory at the end to save space
01233        Makes algorithm slightly inefficient (multiple loops over module list)
01234        but better than crashing due to OOM!
01235   */
01236   list<RodLabel> rodList = api.listRods();
01237 
01238   for(list<RodLabel>::const_iterator rl = rodList.begin();
01239       rl!=rodList.end();
01240       rl++){
01241 
01242     cout << "Reading out modules from ROD " << Sct::URID(rl->partition,
01243                              rl->crate,
01244                              rl->rod) << " of " << rodList.size() << endl;
01245 
01246     // For each module
01247 #if USE_CONST_SCAN
01248     const unsigned int nGrOuPs = scanEx->getNGroups();
01249 #else
01250     const unsigned int nGrOuPs = scan->getNGroups();
01251 #endif
01252     for(unsigned int group = 0; group < nGrOuPs; group ++) {
01253 #if USE_CONST_SCAN
01254       const ModuleList &groupList = scanEx->getModuleList(group);
01255 #else
01256       const ModuleList &groupList = scan->getModuleList(group);
01257 #endif
01258       cout << "Modules in group " << group << " of " << nGrOuPs << ": count= " << groupList.size() << endl;
01259       for(ModuleList::const_iterator mi = groupList.begin();
01260           mi!=groupList.end();
01261           mi ++) {
01262 
01263         string sn = *mi;
01264     cout << "Attempting to find mid for ["<<sn<<"]"<<std::endl;
01265         UINT32 mid = api.findModule(sn);
01266 
01267     cout << "serial number is [" << sn << "] mid = " << mid << std::endl;
01268 
01269         {
01270           unsigned int partition, crate, rod, channel;
01271           Utility::getpcrc(mid, partition, crate, rod, channel);
01272           if(RodLabel(partition, crate, rod) != *rl) {
01273             // Come back later
01274         cout << "Skipping " << sn << " (in ROD " << Sct::URID(partition,crate,rod) << " not " << Sct::URID(rl->partition, rl->crate, rl->rod) << ")\n";
01275             continue;
01276           }
01277         }
01278 
01279         cout << "Module:  " << mid << " = " << sn << endl;
01280 
01281         try {
01282           if(scan->getOption(Scan::FULL)) {
01283         std::cout << "Readout full mode histograms:" << std::endl;
01284             for(int f=0; f<3; f++) {
01285           std::cout << "    (" << f << " of 3)" << std::endl;
01286               scan_result_ptrs result = readHistogramData(mid, f);
01287 
01288               result.header.scanNumber += f;
01289 
01290               // Files need discriminating because they're all the same time
01291               if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
01292                 readHistogramToFile(api.ucid(), *scan, *scanEx, mid, api.convertToString(mid), result, saveTime, f);
01293               }
01294 
01295 #ifdef USE_IS
01296               // IS based on Run/Scan number so nothing more needed
01297               if(api.mrs) readHistogramToIS(api.ucid(), *scan, *scanEx, mid, result);
01298 #endif
01299 
01300               delete [] (char*)result.data;
01301               delete [] result.points;
01302               delete [] result.nEvents;
01303               delete [] result.nErrorEvents;
01304             }
01305           } else {
01306         std::cout << "Readout non-full mode histogram" << std::endl;
01307             scan_result_ptrs result = readHistogramData(mid, 0);
01308 
01309             if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
01310               readHistogramToFile(api.ucid(), *scan, *scanEx, mid, api.convertToString(mid), result, saveTime);
01311             }
01312 #ifdef USE_IS
01313             if(api.mrs)readHistogramToIS(api.ucid(), *scan, *scanEx, mid, result);
01314 #endif
01315             delete [] (char*)result.data;
01316             delete [] result.points;
01317             delete [] result.nEvents;
01318             delete [] result.nErrorEvents;
01319           }
01320         } catch(SctApiException &s) {
01321       std::cout << "Scan readout failed" << std::endl;
01322           if(api.mrs) {
01323             *api.mrs << "SCAN_READOUT_FAIL" << MRS_ERROR
01324                      << MRS_QUALIF("SctApi")
01325                      << MRS_PARAM<int>("run", scan->getRunNumber()) 
01326                      << MRS_PARAM<int>("scan", scan->getScanNumber()) 
01327                      << MRS_PARAM<int>("mid", mid) 
01328                      << MRS_TEXT("Module readout failed") << ENDM;
01329           }
01330         }
01331       } // Histogram for next module
01332     } // Next module group
01333 
01334     // Release memory from ROD
01335     for(std::map<std::pair<RodLabel, int>, 
01336           Utility::MemoryBlock> :: iterator mapIter = scanEx->histoMap.begin();
01337         mapIter != scanEx->histoMap.end();
01338         mapIter++) {
01339 
01340       if(mapIter->first.first == *rl) {
01341         if(api.mrs) {
01342           *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
01343                    << MRS_PARAM<float>("MWords", mapIter->second.size() / 1e6)
01344                    << MRS_PARAM<int>("crate", rl->crate)
01345                    << MRS_PARAM<int>("rod", rl->rod)
01346                    << MRS_TEXT("Releasing memory after histogram readout") << ENDM;
01347         }
01348 
01349         mapIter->second = Utility::MemoryBlock();
01350       }
01351     }
01352   } // End ROD loop
01353 }
01354 
01355 scan_result_ptrs ScanControlRODHisto::readHistogramData(UINT32 mid, int frame) {
01356   scan_result_ptrs scanResult;
01357 
01358   //We do this first deliberately.
01359   //The dummy api will need to mess around with some things
01360   scanResult.data = readHistogramRawData(mid, frame);
01361 
01362   if(scanResult.data == 0) {
01363     cout << "readHistogramRawData returned 0 in readHistogramData";
01364     throw SctApiException("readHistogramRawData returned 0 in readHistogramData");
01365   }
01366 
01367   int nBins = scan->getScanPoints1().size();
01368 
01369   // Read the module configuration from the end of the scan...
01370 
01371   /* Modifyed 2/6/2005 AJB to use the SCAN bank _directly_
01372    * api.getABCDModule(mid, SCTAPI_BANK_SCAN);
01373 
01374   // Save copy of configuration from end of scan
01375    */
01376  
01377   ABCDModule moduleConfig; // no initial value - SHOULD always be set below or there is an error.
01378   boost::shared_ptr<SctApiConfigCache::ModuleBanks> the_banks=api.getModuleConfigCache().getFromMid(mid);
01379   if (!the_banks.get()) {
01380     if(api.mrs) {
01381       *api.mrs << "ROD_BANK_CONFIG_CACHE" << MRS_ERROR << MRS_QUALIF("SCTAPI")
01382            << MRS_PARAM<int>("mid", mid)
01383            << MRS_TEXT("Cant return cache for non-existant MID at end of scan") << ENDM;
01384     }else{
01385       cerr << "Non-existant module mid=" << mid << std::endl;
01386     }
01387   } else {
01388     boost::shared_ptr<ABCDModule> scan_config = the_banks->get(SCTAPI_BANK_SCAN);
01389     if (!scan_config.get()){
01390       if(api.mrs) {
01391     *api.mrs << "ROD_BANK_CONFIG_CACHE" << MRS_ERROR << MRS_QUALIF("SCTAPI")
01392          << MRS_PARAM<int>("mid", mid)
01393          << MRS_TEXT("Cant return cache for non-existant SCAN BANK at end of scan") << ENDM;
01394       }else{
01395     cerr << "Non-existant scan bank at end of scan ! mid=" << mid << std::endl;
01396       }
01397     } else {
01398       moduleConfig = *scan_config;
01399     }
01400   }
01401 
01402   if(checkDebugOption(DEBUG_MODULE_CONFIG)) {
01403     cout << "Configuration after scan temporarily not available \n";
01404     //cout << api.config->printABCDModule(moduleConfig); // private
01405   }
01406 
01407   ScanHeader &header = scanResult.header;
01408 
01409   header.version = CURRENT_SCANHEADER_VERSION;
01410   header.length = sizeof(ScanHeader);
01411   header.runNumber = scan->getRunNumber();
01412   header.scanNumber = scan->getScanNumber();
01413   
01414   strncpy(header.moduleName, api.convertToString(mid).c_str(), 16);
01415 #if USE_CONST_SCAN
01416   strncpy(header.startTime, to_iso_string(scanEx->getStartTime()).c_str(), 16);
01417   strncpy(header.endTime, to_iso_string(scanEx->getEndTime()).c_str(), 16);
01418 #else
01419   strncpy(header.startTime, to_iso_string(scan->getStartTime()).c_str(), 16);
01420   strncpy(header.endTime, to_iso_string(scan->getEndTime()).c_str(), 16);
01421 #endif
01422   header.moduleName[15] = 0;    // Null terminate the string
01423   header.startTime[15] = 0;
01424   header.endTime[15] = 0;
01425   
01426 //   snprintf(header.moduleName, 16, "%s", convertToString(mid).c_str());
01427 //   cout << "Module name in Scan Results (" << header.moduleName << ")\n" ;
01428   header.scanType = scan->getScanVariable1();
01429   header.npoints = nBins;
01430   header.size = nBins * 2 * 1024 * (scan->getOption(Scan::BITS32)?2:1);
01431   header.dataType = SR_DT_SLICE;
01432 
01433   header.width = scan->getOption(Scan::BITS32)?SR_WD_32:SR_WD_16;
01434 
01435   header.config = moduleConfig;
01436 
01437   header.pntPoints = sizeof(ScanHeader);
01438   header.pntEvents = header.pntPoints + nBins * sizeof(FLOAT32);
01439   header.pntErrors = header.pntEvents + nBins * sizeof(UINT32);
01440   header.pntData = header.pntErrors + nBins * sizeof(UINT32);
01441 
01442   // The points
01443   FLOAT32 *points = new FLOAT32[nBins];
01444   for(int i=0; i<nBins; i++) {
01445     points[i] = scan->getScanPoints1()[i];
01446   }
01447   scanResult.points = points;
01448 
01449   // The event counts
01450   UINT32 *events = new UINT32[nBins];
01451 
01452   std::pair<RodLabel, unsigned int> moduleSlave = findModuleSlave(mid);
01453 
01454   // This is the better way of counting (especially when there are errors)
01455   unsigned long *countChunk = getEventCountChunk(moduleSlave.first, moduleSlave.second);
01456 
01457   for(int i=0; i<nBins; i++) {
01458     events[i] = countChunk[i];
01459 
01460     // Unfortunately it counts * 4 for cal line loop
01461     if(scan->getOption(Scan::LOOPCALLINE)) {
01462       events[i] >>= 2; 
01463     }
01464   }
01465 
01466 #if 0
01467   // But this way does get the count right with the callineloop on!
01468   Scan::TrigPoints trigs = scan->getVariableTrigs();
01469  
01470   for(int i=0; i<nBins; i++) {
01471     if(i<lastBin[moduleSlave.first]) {
01472       events[i] = trigs[i];
01473     } else if(i == lastBin[moduleSlave.first]) {
01474       events[i] = lastEvent[moduleSlave.first];
01475     } else {
01476       events[i] = 0;
01477     }
01478   }
01479 #endif
01480 
01481   scanResult.nEvents = events;
01482 
01483   // The error counts
01484   UINT32 *errors = new UINT32[nBins];
01485   UINT32 correctedTrigPoint;
01486   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
01487   for(int i=0; i<nBins; i++) {
01488     // An error is when a requested event doesn't get to be histogrammed
01489     // The requested number of triggers is first corrected for cases
01490     // where the trap modulus is > 1.
01491     if(scan->getOption(Scan::NTH) > 1) {
01492       correctedTrigPoint = ((UINT32) trigPoints[i] / (UINT32)scan->getOption(Scan::NTH));
01493     }else{
01494       correctedTrigPoint = trigPoints[i];
01495     }
01496     if (correctedTrigPoint >= events[i]){
01497        errors[i] = correctedTrigPoint - events[i];
01498     }else{
01499        errors[i] = 0;
01500     }
01501   }
01502   scanResult.nErrorEvents = errors;
01503 
01504   return scanResult;
01505 }
01506 
01507 char* ScanControlRODHisto::readHistogramRawData(UINT32 mid, int frame) {
01508   int nBins = scan->getScanPoints1().size();
01509 
01510   // The number of bins the ROD thinks there are...
01511   int rodBins = nBins;
01512   if(!scan->getOption(Scan::BITS32))
01513     if(rodBins%2 == 1) rodBins++;
01514 
01515   // The data!
01516   int binSize = 0x800*(scan->getOption(Scan::BITS32)?4:2);   // In bytes, so works for 16bit histograms
01517 
01518   char *data = new char[nBins * binSize];
01519 
01520   bool moduleBlock = false;
01521 //    int baseAddress = index*(binSize*nBins);
01522 
01523   unsigned int slaveNumber = 4;
01524 
01525   RodLabel rodLabel;
01526   unsigned int channel;
01527   {
01528     unsigned int partition, crate, rod;
01529     Utility::getpcrc(mid, partition, crate, rod, channel);
01530     RodLabel temp(partition, crate, rod);
01531     rodLabel = temp;
01532   }
01533 
01534   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01535 
01536   for(int slave=0; slave<4; slave++) {
01537     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01538        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01539       if(slaveNumber == 4) {
01540         slaveNumber = slave;
01541       } else {
01542         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01543         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01544 #warning "But maybe I should any way"
01545       }
01546     }
01547   }
01548 
01549   if(slaveNumber == 4) {
01550     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01551 
01552     throw SctApiException("No mapping from module to DSP found");
01553   }
01554 
01555   // Find the module index on this slave
01556   int index = 0;
01557   int nModules = 0; // moduleMap.size();
01558 
01559   for(unsigned int ch=0; ch<48; ch++) {
01560     if(channel == ch) {
01561       index = nModules;
01562     }
01563     if(ch<32) {
01564       if(rodInfo.slaveChannels[slaveNumber].mask0 & 1<<ch) {
01565         nModules ++;
01566       }
01567     } else {
01568       if(rodInfo.slaveChannels[slaveNumber].mask1 & 1<<(ch-32)) {
01569         nModules ++;
01570       }
01571     }
01572   }
01573 
01574   // Get data from place defined by DSP
01575   unsigned long slaveOffset = 0;
01576 
01577   if(moduleBlock) {
01578     slaveOffset += binSize * rodBins;
01579   } else {
01580     slaveOffset += binSize * index;
01581   }
01582 
01583   // For reading expanded data, skip to next block of histograms...
01584   slaveOffset += ((binSize * rodBins * nModules) + binSize) * frame;
01585 
01586   bool error = false;
01587 
01588   for(int i=0; i<nBins; i++) {
01589     unsigned long *chunk = getHistogramChunk(rodLabel, slaveNumber, slaveOffset, binSize/sizeof(UINT32));
01590     unsigned long *buffer = (unsigned long *)&(data[i*binSize]);
01591 
01592     if(chunk) {
01593       for(int b=0; b<binSize/sizeof(UINT32); b++) {
01594         buffer[b] = chunk[b];
01595       }
01596 
01597       // Check End of bin xx Module xx
01598       int bin, module;
01599       int count = sscanf(&((char*)buffer)[binSize-32], "End of bin %d Module %d", &bin, &module);
01600       if(count == 2) {
01601 //          printf("Found End of bin %d module %d\n", bin, module);
01602       } else {
01603         if(!error)
01604           printf("Found bad end of histogram bin (%25s)\n", &((char*)buffer)[binSize-32]);
01605         error = true;
01606       }
01607 
01608 #warning "Memory leak if sendData didn't work"
01609 //       delete [] chunk;
01610     } else {
01611       for(int b=0; b<binSize/sizeof(UINT32); b++) {
01612         buffer[b] = 0;
01613       }
01614     }
01615 
01616     if(moduleBlock) {
01617       slaveOffset += binSize;
01618     } else {
01619       slaveOffset += binSize * nModules;
01620     }
01621   }
01622 
01623   return data;
01624 }
01625 
01626 pair<RodLabel, unsigned int> ScanControlRODHisto::findModuleSlave(unsigned int mid) {
01627   RodLabel rodLabel;
01628   unsigned int channel;
01629   {
01630     unsigned int partition, crate, rod;
01631     Utility::getpcrc(mid, partition, crate, rod, channel);
01632     RodLabel temp(partition, crate, rod);
01633     rodLabel = temp;
01634   }
01635 
01636   unsigned int slaveNumber = 4;
01637 
01638   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01639 
01640   for(int slave=0; slave<4; slave++) {
01641     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01642        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01643       if(slaveNumber == 4) {
01644         slaveNumber = slave;
01645       } else {
01646         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01647         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01648 #warning "But maybe I should any way"
01649       }
01650     }
01651   }
01652 
01653   if(slaveNumber == 4) {
01654     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01655 
01656     throw SctApiException("No mapping from module to DSP found");
01657   }
01658 
01659   return make_pair(rodLabel, slaveNumber);
01660 }
01661 
01662 void readHistogramToFile(const Sct::UCID & ucid, const Scan &scan, const ScanEx &ex, 
01663                          UINT32 mid, std::string sn, scan_result_ptrs scanData, time_t saveTime, int frame) {
01664   const int BUFF_SIZE = 50;
01665 
01666   struct tm broke;
01667   broke = *(gmtime(&saveTime));
01668 
01669   string tempDir = SctNames::getTempDir() + "/";
01670   int bufferLength = BUFF_SIZE + tempDir.length();
01671   char *filename = new char[bufferLength];
01672   strcpy(filename, tempDir.c_str());
01673 
01674   cout << "Module:  " << mid << " = " << sn << endl;
01675 
01676   int written = tempDir.length();
01677   if(scan.getOption(Scan::FULL)) {
01678     written += snprintf(filename + written, bufferLength - written, "Histogram%d_%s", frame, sn.c_str());
01679     //                                                                    20021112143712
01680     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01681   } else {
01682     written += snprintf(filename + written, bufferLength - written, "Histogram_%s", sn.c_str());
01683     //                                                                    20021112143712
01684     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01685   }
01686 
01687   {
01688     Sct::MultiMessageDebugStream m(true,false,true);
01689     m << ucid << " is writing histogram data to " << filename;
01690   };
01691 
01692   saveHistogramToFile(scanData, filename);
01693     
01694   cout << "done.\n";
01695 
01696   delete [] filename;
01697 }
01698 
01699 void saveHistogramToFile(scan_result_ptrs histo, std::string filename) {
01700   ofstream histoout(filename.c_str(), ios::binary);
01701 
01702   //    assert(histo.header.length == sizeof(ScanHeader));
01703   histoout.write((char*)&histo.header, histo.header.length);
01704 
01705   //    assert(histo.header.pntEvents - histo.header.pntPoints == nBins * sizeof(FLOAT32));
01706   histoout.write((char*)histo.points, histo.header.pntEvents-histo.header.pntPoints);
01707 
01708   //    assert(histo.header.pntErrors - histo.header.pntEvents == nBins * sizeof(FLOAT32));
01709   histoout.write((char*)histo.nEvents, histo.header.pntErrors-histo.header.pntEvents);
01710 
01711   //    assert(histo.header.pntData - histo.header.pntErrors == nBins * sizeof(FLOAT32));
01712   histoout.write((char*)histo.nErrorEvents, histo.header.pntData-histo.header.pntErrors);
01713 
01714   //    assert(histo.header.size*2 == (nBins * 0x800 * 4));
01715 
01716   // header.size is a count in 16bit words!
01717   histoout.write((char*)histo.data, histo.header.size*2);
01718 }
01719 
01720 #ifdef USE_IS
01721 
01722 void readHistogramToIS(const Sct::UCID & ucid, const Scan &scan, const ScanEx &ex, UINT32 mid, scan_result_ptrs scanData) {
01723 //   {
01724 //     boost::mutex::scoped_lock lock(log().mutex());
01725 //     log() << "Read Histogram for " << mid << " to IS\n";
01726 //   }
01727 
01728   cout << "Writing histogram data to IS\n";
01729 
01730 //   string sn = convertToString(mid);
01731 
01732   cout << "Module:  " << mid << /* " " << sn << */ endl;
01733   {
01734     Sct::MultiMessageDebugStream m(true,false,true);
01735     m << ucid << " is writing histogram data to IS for mid " << mid;
01736   };
01737 
01738   try {
01739     SctData::ScanResultWriter::publish(scanData);
01740   } catch(Sct::IoException &e) {
01741     cout << "ScanResult publish failed:\n" << e.what() << endl;
01742     e.sendToMrs(MRS_ERROR);
01743   }
01744 }
01745 
01746 #endif
01747 
01748 int SctApi::pollHistogramming(boost::shared_ptr<ScanControl> controller, int timeout) {
01749   int returnVal = 0;
01750 
01751   bool timedout = false;
01752 
01753   time_t start_time = time(0);
01754 
01755   while(!timedout) {
01756     bool progressMade = false;
01757     bool newBin = false;
01758     if(controller->checkScanComplete(progressMade, newBin)) {
01759       // Finished, exit while
01760       break;
01761     }
01762 
01763     if(progressMade) {
01764       start_time = time(0);
01765     }
01766 
01767     if(newBin) {
01768       cout << "Controller going to next bin\n";
01769 
01770       controller->nextBin();
01771     } else {
01772       // Check text buffers (no longer a side effect of polling)
01773 #if USE_THREADS
01774       // Text buffers already checked by primThread
01775       sleep(1);
01776 #else
01777       awaitResponseAll(0);
01778 #endif
01779 
01780       if((time(0) - start_time) > timeout) {
01781         timedout = true;
01782         returnVal = -1;
01783 
01784         controller->reportTimeout();
01785 
01786         if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
01787           standardRegisterDumpAll();
01788         }
01789 
01790         controller->reportEventErrors();
01791 
01792         break;
01793       }
01794     }
01795   }
01796 
01797 #if USE_IS
01798   if(m_isDict) {
01799     m_isDict->remove("SCTAPIServer.currentBin");
01800     m_isDict->remove("SCTAPIServer.maxBin");
01801   }
01802 #endif
01803 
01804   return returnVal;
01805 }
01806 
01807 void SctApi::doHistogramSetup(const Scan &scan, const ScanEx &extra) {
01808   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01809       ri != extra.rodInfo.end();
01810       ri++) {
01811     //    const RodScanEx &rodInfo = ri->second;
01812     const RodLabel &rod = ri->first;
01813 
01814     // Clear event memory on all slaves
01815     // 8192 words from what was 0x80008000
01816     for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
01817       if(getCrate()->slavePresent(rod.rod, slaveNumber)) {
01818         if(getCrate()->getRodRevision(rod.rod) >= 0xe) {
01819 #warning "Hard-coded address of incoming event buffer"
01820           setSlaveBlock(rod.rod, slaveNumber, 0x18000, 0x2000, 0);
01821         } else {
01822           setSlaveBlock(rod.rod, slaveNumber, 0x80008000, 0x2000, 0);
01823         }
01824       }
01825     }
01826 
01827     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01828 
01829     setupEventTrapping(scan, extra, rod, primList);
01830     startEventTrapping(scan, extra, rod, primList);
01831     setupEventDump(scan, extra, rod, primList);
01832 
01833     /*    if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
01834       sendPrimList(rod.rod, primList);
01835       awaitResponse(rod.rod, 5);
01836       primList->clear(); // .reset(new PrimListWrapper(2));
01837 
01838       // Do the dump after setting up trapping
01839       standardRegisterDump(rod.rod);
01840       }*/
01841 
01842     setupHistogramming(scan, extra, rod, scan.getOption(Scan::TIM), primList);
01843 
01844     // Wait for things to settle before starting histogramming
01845     sendPrimList(rod.rod, primList);
01846   }
01847   
01848   
01849   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01850       ri != extra.rodInfo.end();
01851       ri++) {
01852     const RodLabel &rod = ri->first;
01853     int responseCode = awaitResponse(rod.rod, 5);
01854     if(responseCode != 0) {
01855       cout << "Histogram setup list failed! (ROD " << rod.rod << ")\n";
01856       throw SctApiException("Histogram setup list failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01857     } else {
01858       unsigned long length;
01859       unsigned long *result = getResponse(rod.rod, length);
01860 
01861       if(result) {
01862     if(result[6] == EVENT_TRAP_SETUP && result[7] == R_EVENT_TRAP_SETUP) {
01863       // First is ETS, so decode as if all are...
01864       int numPrims = result[2];
01865       cout << numPrims << " replies from setup primitive list\n";
01866 
01867       int offset = 4;
01868       for(int prim = 0; prim<numPrims; prim++) {
01869         cout << prim << ": ";
01870         if(result[offset+2] == EVENT_TRAP_SETUP && result[offset+3] == R_EVENT_TRAP_SETUP) {
01871           cout << "ETS Error code " << result[offset+4] << endl;
01872         } else {
01873           cout << "Unexpected (not ETS) reply from setup primitive list\n";
01874         }
01875         offset += result[offset+0];
01876       }
01877     } else {
01878       cout << "Unexpected output list from histogram setup primitive list\n";
01879       ::SctApi::printOutList(result, length, true, 0, cout, 
01880                  checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01881     }
01882     delete [] result;
01883       } else {
01884     cout << "No response to ETS\n";
01885       }
01886     }
01887   }
01888 }
01889 
01890 void ScanControlRODHisto::startHistogramming() {
01891   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01892       ri != scanEx->rodInfo.end();
01893       ri++) {
01894     const RodLabel &rod = ri->first;
01895 
01896     // Setup debug register
01897     if(scan->getOption(Scan::DEBUG)) {
01898       if(checkDebugOption(DEBUG_SCAN_AUTO_STALL)) {
01899         cout << "** Debug mode setting AUTO_STALL\n"; 
01900         scanEx->diagnosticReg |= (1<<DR_AUTO_STALL);
01901       }
01902 
01903       if(checkDebugOption(DEBUG_SCAN_STEP_MODE)) {
01904         cout << "** Debug mode setting STEP_CTRL\n"; 
01905         scanEx->diagnosticReg |= (1<<DR_STEP_CTRL);
01906       }
01907 
01908       if(checkDebugOption(DEBUG_SCAN_PAUSE_PULSE)) {
01909 #ifdef DR_PULSE_PAUSE
01910         cout << "** Debug mode setting PAUSE_PULSE\n"; 
01911         scanEx->diagnosticReg |= (1<<DR_PULSE_PAUSE);
01912 #else
01913     cout << "ERROR : Debug mode PAUSE_PAUSE no longer available\n";
01914 #endif
01915       }
01916     }
01917 
01918     if(checkDebugOption(DEBUG_SCAN_ROD_MODE_BITS)) {
01919       cout << "Setting up to use ROD mode bits\n"; 
01920 #ifdef DR_USE_ROD_MASK_LUT
01921       scanEx->diagnosticReg |= (1<<DR_USE_ROD_MASK_LUT);
01922 #else
01923       cout << "ERROR : Cannot set up to use ROD mode bits - USE_ROD_MASK_LUT no longer available!\n"; 
01924 #endif
01925     }
01926 
01927     if(scanEx->diagnosticReg != 0x0) {
01928       cout << "Writing master diag reg: 0x" << hex << scanEx->diagnosticReg << dec << endl;
01929       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01930     } else {
01931       cout << "Clearing master diag reg\n";
01932       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01933     }
01934 
01935     if(!useCCode(api, *scan)) {
01936       
01937       unsigned long SDSP_IDRAM_BASE;
01938       if(api.getRodRevision(rod) >= 0xe) {
01939         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
01940       } else {
01941         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
01942       }
01943 
01944       for(int s=0; s<numSlaves; s++) {
01945         if(ri->second.bitFieldDSP & (1<<s)) {
01946           try {
01947             unsigned long val = api.dspSingleBlockRead(rod.rod, 
01948                                                        SDSP_IDRAM_BASE + 0x10, s);
01949             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01950                  << " which should be 0x" << (0) << dec << endl;
01951 
01952             // Toggle cache on
01953             unsigned long newVal = val | (1<<19);
01954             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
01955 
01956             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
01957             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01958                  << " which should be 0x" << (1<<19) << dec << endl;
01959           } catch(VmeException &v) {
01960             Utility::decodeVme(v);
01961             cerr << "VmeException turning on slave " << s << " cache\n";
01962           }
01963         }
01964       }
01965     }
01966 
01967     cout << "Histogram starting...\n";
01968 
01969     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01970     api.startHistogramTask(*scan, *scanEx, rod, 
01971                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
01972                            primList);
01973 
01974 //     {
01975 //       boost::mutex::scoped_lock lock(log().mutex());
01976 //       log() << "Send start histogram task list\n";
01977 //     }
01978     api.sendPrimList(rod.rod, primList);
01979 
01980   }
01981 
01982   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01983       ri != scanEx->rodInfo.end();
01984       ri++) {
01985     const RodLabel &rod = ri->first;
01986     int responseCode = api.awaitResponse(rod.rod, 5);
01987     if(responseCode != 0) {
01988       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
01989       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01990     }
01991   }
01992 }
01993 
01994 void SctApi::eventTrapSetup(int slaveMask, int trapMatch, int trapMod, int trapRemain, bool tim, bool error,
01995                             boost::shared_ptr<PrimListWrapper> primList) {
01996   long *evData = new long[sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32)];
01997 
01998   EVENT_TRAP_SETUP_IN &primData = *(EVENT_TRAP_SETUP_IN*)evData;
01999 
02000 #if R_EVENT_TRAP_SETUP == 103
02001   primData.slvBits = slaveMask;
02002   primData.numberOfEvents = COLLECT_FOREVER;
02003   primData.timeoutInUsec = 0x30000;
02004 
02005   primData.extRouterSetup = 0;
02006 
02007   // This tells the setup code to change the trapRemainder
02008   //  Only matters if setting up more than one slave
02009   primData.distribute = TRAP_DISTRIB_NEITHER;
02010 
02011   primData.releaseFrames = 0;
02012   if(tim) {
02013     primData.permitBackPressure = 0;
02014   } else {
02015     primData.permitBackPressure = 1;
02016   }
02017   primData.dataMode = 0;                        // Data or Event mode
02018   if(tim) {                           // Where to pick events (dsp or router)
02019     primData.sLink = 1;
02020   } else {
02021     primData.sLink = 0;
02022   }
02023 
02024   primData.format = error?TRAP_FMT_ERROR:TRAP_FMT_NORMAL; // Slink format
02025   primData.trapStray = 1;                       // Trap stray events
02026   primData.iterLimit = 2;                       // Don't keep them long
02027 
02028   if(tim) {
02029     // Trap events from the SLINK
02030     primData.trapConfig[0] = TRAP_CFG_SLINK_EVT;
02031   } else {
02032     // Trap events from ROD triggers
02033     primData.trapConfig[0] = TRAP_CFG_ROD_EVT;
02034   }
02035   primData.trapExclusionFlag[0] = 0;            // Don't exclude anything
02036   primData.trapFunction[0] = TRAP_FXN_HISTOGRAM;
02037 
02038   primData.trapMatch[0] = trapMatch;
02039   primData.trapModulus[0] = trapMod;
02040   primData.trapRemainder[0] = trapRemain;
02041 
02042   // Trap one is idle
02043   primData.trapConfig[1] = TRAP_CFG_IDLE;
02044   primData.trapExclusionFlag[1] = 0;
02045   primData.trapFunction[1] = 0;
02046 
02047   primData.trapMatch[1] = 0; 
02048   primData.trapModulus[1] = 0;
02049   primData.trapRemainder[1] = 0;
02050 #else 
02051 #error "Event trapping not compiled (new Primitive definition)!"
02052 #endif
02053   primList->addPrimitive(RodPrimitive(sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32) + 4, 
02054                                       0, EVENT_TRAP_SETUP, R_EVENT_TRAP_SETUP, evData),
02055                          evData);
02056 }
02057 
02058 void SctApi::startEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
02059   shared_ptr<PrimListWrapper> startList(new PrimListWrapper(1));
02060 
02061   PrimBuilder::instance().startEvTrap(startList);
02062 
02063   PrimBuilder::instance().slavePrimList(primList, startList, slaveNumber, true, true);
02064 }
02065 
02066 void SctApi::stopEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
02067   shared_ptr<PrimListWrapper> stopList(new PrimListWrapper(1));
02068 
02069   PrimBuilder::instance().stopEvTrap(stopList);
02070 
02071   PrimBuilder::instance().slavePrimList(primList, stopList, slaveNumber, true, true);
02072 }
02073 
02074 ScanMonitorImpl::ScanMonitorImpl(boost::shared_ptr<ScanControl> control) : controller(control) {
02075 }
02076 
02077 ScanMonitorImpl::~ScanMonitorImpl() {
02078 }
02079 
02080 void ScanMonitorImpl::newBin(int prevTriggers, int newBin) {
02081   controller->nextBin();
02082 }
02083 
02084 void ScanMonitorImpl::finishScan() {
02085   controller->finishHistogram(true);
02086 }
02087 
02088 // If this uses sendData then memory is stored internally so isn't leaked, otherwise it is!
02089 unsigned long *ScanControlRODHisto::getHistogramChunk(RodLabel rodLabel, int slaveNumber,
02090                                                       unsigned long offset, unsigned long size) {
02091   try {
02092     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
02093 
02094     Utility::MemoryBlock chunk;
02095     chunk = scanEx->histoMap[key];
02096     if(!chunk) {
02097       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, HISTOGRAM_DATA, slaveNumber);
02098 
02099       cout << "SendData returned " << chunkPos.first << " " << chunkPos.second << endl;
02100       cout << " need offset " << offset << " length " << size << endl;
02101 
02102       if(api.mrs) {
02103         // Something about getting lots of data
02104         *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
02105                  << MRS_PARAM<float>("MWords", chunkPos.second/4e6)
02106                  << MRS_PARAM<int>("crate", rodLabel.crate)
02107                  << MRS_PARAM<int>("rod", rodLabel.rod)
02108                  << MRS_TEXT("Scan requested histogram readout") << ENDM;
02109       }
02110 
02111       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
02112                           slaveNumber, chunkPos.first, chunkPos.second/sizeof(UINT32));
02113 
02114       if(block == 0) {
02115     throw SctApiException("Read of histogram from slave failed");
02116       }
02117 
02118       chunk = Utility::MemoryBlock(chunkPos.second/sizeof(UINT32), block);
02119 
02120       scanEx->histoMap[key] = chunk;
02121     }
02122 
02123     if((offset + size*4) > (chunk.size() * 4)) {
02124       cout << "Asked for chunk +" << offset << " length " << size << " in " << chunk.size() << "words (continuing)\n";
02125     }
02126 
02127     // Offset is in bytes
02128     return chunk.address() + (offset / 4);
02129   } catch(SctApiException &e) {
02130     cout << "Caught exception in getHistogramChunk: " << e.what() << "\n\ttrying old histogram address\n";
02131     unsigned long slaveAddress;
02132 
02133     if(api.getRodRevision(rodLabel) >= 0xe) {
02134       slaveAddress = 0xa00e2000;
02135     } else {
02136       throw SctApiException("Slave histogram read not possible with old (pre-rev-E) rod");
02137     }
02138     return api.primReadSlaveDsp(rodLabel.rod, 
02139                                 slaveNumber, slaveAddress + offset, size);
02140   }
02141 }
02142 
02143 unsigned long *ScanControlRODHisto::getEventCountChunk(RodLabel rodLabel, int slaveNumber) {
02144   try {
02145     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
02146 
02147     Utility::MemoryBlock chunk = scanEx->evCountMap[key];
02148     if(!chunk) {
02149       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, BIN_DATA, slaveNumber);
02150 
02151       cout << "SendData bin returned " << chunkPos.first << " " << chunkPos.second << endl;
02152 
02153       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
02154                                                   slaveNumber, chunkPos.first, chunkPos.second);
02155       chunk = Utility::MemoryBlock(chunkPos.second, block);
02156 
02157       scanEx->evCountMap[key] = chunk;
02158     }
02159 
02160     return chunk.address();
02161   } catch(SctApiException &e) {
02162     return 0;
02163   }
02164 }
02165 
02166 
02167 ScanControlRODHisto::ScanControlRODHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControl(api), scan(aScan), scanEx(aScanEx), aborting(false) {
02168   int nBins = scan->getScanPoints1().size();
02169 
02170   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
02171 
02172   finalTrigger = trigPoints[nBins-1];
02173 
02174   finalBin = nBins - 1;
02175 
02176   UINT32 initialNTrigs = trigPoints[0];
02177 
02178   unsigned int i = 0;
02179   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs) 
02180     i++;
02181 
02182   // i is now the index of the first different point
02183   sectionStartBin = 0;
02184   sectionEndBin = i - 1;
02185   if(i==trigPoints.size()) {
02186     sectionEndTrigger = trigPoints[i-1];
02187   } else {
02188     sectionEndTrigger = trigPoints[i-1] - trigPoints[i];
02189   }
02190   cout << "Final bin = " << finalBin << " trigger = " << finalTrigger << endl;
02191 
02192   cout << "Initial sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
02193 
02194   // no rods 
02195   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02196       ri != scanEx->rodInfo.end();
02197       ri++) {
02198     const RodLabel &rodLabel = ri->first;
02199     reportedFinished[rodLabel]=false;
02200   }
02201 }
02202 
02203 void ScanControlRODHisto::initialisePolling() { 
02204   scanStart = time(0);
02205 
02206   cout << "Histogram polling started\n";
02207   // Let it get going so the bin counter gets reset
02208   sleep(1);
02209 
02210   cout << "Polling histogramming task\n";
02211   cout << "scan point count " << scan->getScanPoints1().size() << endl;
02212 
02213   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02214       ri != scanEx->rodInfo.end();
02215       ri++) {
02216     const RodLabel &rodLabel = ri->first;
02217 
02218     if(api.mrs) {
02219       const std::string m1 = (Sct::StringStreamer << "POLL_ROD_" << api.ucid());      const std::string m2 = (Sct::StringStreamer << "ROD polling started on " << api.ucid());
02220       
02221       *api.mrs << m1 << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
02222                << MRS_PARAM<int>("partition", rodLabel.partition)
02223                << MRS_PARAM<int>("crate", rodLabel.crate)
02224                << MRS_PARAM<int>("rod", rodLabel.rod)
02225                << MRS_PARAM<int>("run", scan->getRunNumber())
02226                << MRS_PARAM<int>("scan", scan->getScanNumber())
02227                << MRS_PARAM<int>("firstSlave", ri->second.firstSlave)
02228                << MRS_TEXT(m2)
02229                << ENDM;
02230     }
02231   }
02232 
02233 #if USE_IS
02234   if(api.m_isDict) {
02235     ISInfoInt binNumber(0);
02236     api.m_isDict->insert("SCTAPIServer.currentBin", binNumber);
02237 
02238     ISInfoInt maxNumber(finalBin);
02239     api.m_isDict->insert("SCTAPIServer.maxBin", maxNumber);
02240   }
02241 #endif
02242 }
02243 
02244 void ScanControlRODHisto::reportTimeout() {
02245   Sct::MultiMessageDebugStream m(true,false,true);
02246 
02247   m << "You are about to get the 'Scan aborted (histogramming stalled)' "
02248     <<"message.  Histogram polling timeout being reported in ["
02249     <<__FILE__<<"] at line ["<<__LINE__<<"]. This means that SctApi got bored waiting more than about 5 (search for the second argument of pollHistogramming in SctApiHisto.cxx) seconds for the event counter to be incremented in the rod. ";
02250 
02251   RodLabel minROD;
02252   if(scanEx->rodInfo.size() > 0) {
02253     minROD = scanEx->rodInfo.begin()->first;
02254   }
02255 
02256   m << "Was expecting: finalBin=" << finalBin << ", finalTrigger=" << finalTrigger;
02257 
02258   // Find the ROD that stopped everything
02259   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02260       ri != scanEx->rodInfo.end();
02261       ri++) {
02262     const RodLabel &rodLabel = ri->first;
02263     cout << "   ROD (" << rodLabel.partition << ", " << rodLabel.crate << ", " << rodLabel.rod << "): ";
02264     cout << " Event " << lastEvent[rodLabel] << "    Bin " << lastBin[rodLabel] << "\n";
02265 
02266     if(lastEvent[rodLabel] < lastEvent[minROD]) {
02267       minROD = rodLabel;
02268     } else if(lastEvent[rodLabel] == lastEvent[minROD] && lastBin[rodLabel] < lastBin[minROD]) {
02269       minROD = rodLabel;
02270     }
02271   }
02272 
02273 
02274   m << ".  Problem was perhaps localised to"
02275     << " partition " << minROD.partition
02276     << " crate" << minROD.crate
02277     << " rod" << minROD.rod
02278     << " run" << scan->getRunNumber()
02279     << " scan"<< scan->getScanNumber()
02280     << " bin"<< lastBin[minROD]
02281     << " event"<< lastEvent[minROD];
02282 
02283   m.flush();
02284 
02285   if(api.mrs) {
02286     *api.mrs << "SCAN_ABORTED" << MRS_ERROR
02287              << MRS_PARAM<int>("partition", minROD.partition)
02288              << MRS_PARAM<int>("crate", minROD.crate)
02289              << MRS_PARAM<int>("rod", minROD.rod)
02290              << MRS_PARAM<int>("run", scan->getRunNumber())
02291              << MRS_PARAM<int>("scan", scan->getScanNumber())
02292              << MRS_PARAM<int>("bin", lastBin[minROD]) << MRS_PARAM<int>("event", lastEvent[minROD]) 
02293              << MRS_TEXT("Scan aborted (histogramming stalled)") << ENDM;
02294   }
02295 }
02296 
02297 void ScanControlRODHisto::nextBin() {
02298   // Fix ending variables if reached the end
02299   if(findNextSection()) {
02300     finalTrigger = sectionEndTrigger;
02301     finalBin = sectionEndBin;
02302     return;
02303   }
02304 
02305   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02306       ri != scanEx->rodInfo.end();
02307       ri++) {
02308     const RodLabel &rod = ri->first;
02309 
02310     cout << "New histogram control task...\n";
02311 
02312     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
02313     api.startHistogramTask(*scan, *scanEx, rod, 
02314                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
02315                            primList);
02316 
02317     api.sendPrimList(rod.rod, primList);
02318     int responseCode = api.awaitResponse(rod.rod, 5);
02319 
02320     if(responseCode != 0) {
02321       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
02322       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
02323     }
02324   }  
02325 }
02326 
02327 bool ScanControlRODHisto::findNextSection() {
02328   // Find next section to do
02329   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
02330 
02331   unsigned int i = sectionEndBin + 1; // StartBin + 1;
02332 
02333   if(i==trigPoints.size()) {
02334     // Nothing more to do
02335     // If we're done, the previous section was last so don't overwrite the parameters
02336     return true;
02337   }
02338 
02339   UINT32 initialNTrigs = trigPoints[i];
02340 
02341   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs)
02342     i ++; 
02343 
02344   bool done = false;
02345 
02346   sectionStartBin = 0;
02347   sectionEndBin = i - 1;
02348 
02349   if(i == trigPoints.size()) {
02350     sectionEndTrigger = trigPoints[i-1];
02351   } else {
02352     sectionEndTrigger = trigPoints[i-1] - trigPoints[i];
02353 
02354 //     sectionStartBin = i;
02355 //     sectionEndBin = trigPoints.size() - 1;
02356 //     sectionEndTrigger = scan->getVariableTrigs()[i] - completedTriggers[i];
02357   }
02358 
02359 #if 0 
02360   // The old way
02361   unsigned int i = sectionEndBin + 1;
02362   UINT32 initialNTrigs = trigPoints[i];
02363   while(i<trigPoints.size() && trigPoints[i] == initialNTrigs) 
02364     i++;
02365 
02366   sectionStartBin = sectionEndBin + 1;
02367   sectionEndBin = i - 1;
02368   sectionEndTrigger = scan->getVariableTrigs()[i-1];
02369 
02370   done = false;
02371 #endif
02372 
02373   cout << "Next sectionStartBin = " << sectionStartBin << " sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
02374 
02375   return done;
02376 }
02377 
02378 bool ScanControlRODHisto::checkScanComplete(bool &progressMade, bool &newBin) {
02379   if(aborting) {
02380     return true;
02381   }
02382 
02383   progressMade = false;
02384   newBin = false;
02385 
02386   bool result = true;
02387 
02388   int totalBin = 0;
02389 
02390   map<RodLabel, bool> rodNewBinMap;
02391 
02392   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02393       ri != scanEx->rodInfo.end();
02394       ri++) {
02395     const RodLabel &rodLabel = ri->first;
02396 
02397     bool rodNewBin = false;
02398 
02399     if(!checkScanCompleteROD(rodLabel, progressMade, rodNewBin, totalBin)) {
02400       result = false;
02401     }
02402 
02403     rodNewBinMap[rodLabel] = rodNewBin;
02404   }
02405 
02406   // Only do a "newBin" if all RODs agree
02407   newBin = true;  
02408   for(map<RodLabel, bool>::const_iterator mapIter = rodNewBinMap.begin();
02409       mapIter != rodNewBinMap.end();
02410       mapIter++) {
02411     if(mapIter->second == false) {
02412       newBin = false;
02413     } else {
02414       cout << "New bin requested by ROD (" << mapIter->first.partition << ", " << mapIter->first.crate << ", " << mapIter->first.rod << ")\n";
02415     }
02416   }
02417 
02418   if(progressMade) {
02419     int progressBin = totalBin / scanEx->rodInfo.size();
02420 
02421 #if USE_IS
02422     if(api.m_isDict) {
02423       ISInfoInt binNumber(progressBin);
02424       api.m_isDict->update("SCTAPIServer.currentBin", binNumber);
02425     }
02426 #endif
02427   }
02428 
02429   return result;
02430 }
02431 
02432 void ScanControlRODHisto::abort() {
02433   aborting = true;
02434 }
02435 
02436 unsigned int ScanControlRODHisto::getEventCounter(const RodLabel &rodLabel, int slave, bool fromMaster) {
02437   // Now then, now then, now then!
02438   // With dsp code version 1.20 and above, things have changed as follows:
02439   // o mdsp maintains one 32 bit event count for each module group (slave)
02440   // o sdsp maintains one 32 bit event count
02441 
02442   if(fromMaster) {
02443   // Read 32 bit counter from mdsp
02444     unsigned long address=0;
02445 #if defined(HSSTAT_REG_0)
02446     switch (slave){
02447     case 0: address=HSSTAT_REG_0; break;
02448     case 1: address=HSSTAT_REG_1; break;
02449     case 2: address=HSSTAT_REG_2; break;
02450     case 3: address=HSSTAT_REG_3; break;
02451     default: cerr << "get event counter for bad slave number : " << slave << std::endl; return 0;
02452     }
02453 #else
02454 #warning "PWP Hard-coded memory address for checking MDSP event counters"
02455     switch (slave){
02456     case 0: address=0x80000028; break;
02457     case 1: address=0x8000002c; break;
02458     case 2: address=0x80000030; break;
02459     case 3: address=0x80000034; break;
02460     default: cerr << "get event counter for bad slave number : " << slave << std::endl; return 0;
02461     }
02462 #endif
02463 
02464     unsigned long reg = api.dspSingleRead(rodLabel.rod, address, -1);
02465     return (unsigned int) reg;
02466   } else {
02467     // Read 32 bit counter from sdsp
02468     // Uses RW_SLAVE_MEMORY primitive rather than direct read of slave (which would be unpredictable!)
02469     unsigned long SDSP_IDRAM_BASE;
02470     if(api.getRodRevision(rodLabel) >= 0xe) {
02471       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02472     } else {
02473       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02474     }
02475     unsigned long reg = api.dspSingleBlockRead(rodLabel.rod, SDSP_IDRAM_BASE+0x2c, slave);
02476     return (unsigned int) reg;
02477   }
02478 }
02479 
02480 bool ScanControlRODHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
02481   int partition = rodLabel.partition;
02482   int crate = rodLabel.crate;
02483   int rod = rodLabel.rod;
02484 
02485   int currBin = 0;
02486   int currEvent = 0;
02487 
02488   // Read bin number from master dsp
02489 #warning "AJB does not like the look of this hard-coded memory address for the bin number - not one little bit!"
02490   // See Sct/comRegDfns_11x.h for placement of regs
02491   long reg = api.dspSingleRead(rod, 0x80000020, -1);
02492   currBin = (reg & 0xff);
02493 
02494   RodScanEx &rodInfo = scanEx->rodInfo[rodLabel];
02495 
02496   // Use the event count copied from the master for the lowest slave with a module
02497   // This counter should now be 32 bit
02498   currEvent = getEventCounter(rodLabel, rodInfo.firstSlave, true);
02499 
02500   if(currBin != lastBin[rodLabel]) {
02501     lastBin[rodLabel] = currBin;
02502     lastEvent[rodLabel] = currEvent;
02503     cout << "Next bin " << currBin << "+" << currEvent << " on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02504 
02505     progressMade = true;
02506   } else if(currEvent != lastEvent[rodLabel]) { 
02507     lastEvent[rodLabel] = currEvent;
02508     cout << "Next event " << currEvent << " (bin " << currBin << ") on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02509 
02510     progressMade = true;
02511   }
02512 
02513   totalBin += currBin;
02514 
02515   // End of current section
02516   if(currBin == sectionEndBin && currEvent == sectionEndTrigger) {
02517     // Probably got to the end...
02518     newBin = true;
02519 
02520     // Check all the DSPs involved
02521     for(int s=0; s<4; s++) {
02522       if(rodInfo.bitFieldDSP & (1<<s)) {
02523         int slaveEvent = getEventCounter(rodLabel, s, true);
02524         // Actually this one not finished yet
02525         if(slaveEvent != sectionEndTrigger) {
02526           cout << " Slave " << s << " completed only " << slaveEvent << "/" << sectionEndTrigger << " triggers\n";
02527           newBin = false;
02528         }
02529       }
02530     }
02531   } else if(currBin == sectionEndBin && currEvent == (sectionEndTrigger%65536)) {
02532     // Should check trigger count on slave (not 16bit?)
02533 
02534     // If progress was made we'll wait for the next iteration
02535     if(!progressMade) {
02536       // Otherwise its most likely finished properly...
02537       newBin = true;
02538 
02539       // Check all the DSPs involved
02540       for(int s=0; s<4; s++) {
02541     if(rodInfo.bitFieldDSP & (1<<s)) {
02542           int slaveEvent = getEventCounter(rodLabel, s, true);
02543       // Actually this one not finished yet
02544       if(slaveEvent != sectionEndTrigger) {
02545         cout << " Slave " << s << " completed only " << slaveEvent << "/" << sectionEndTrigger << " triggers\n";
02546         newBin = false;
02547       }
02548     }
02549       }
02550     }
02551   }
02552 
02553   // Could this be if(newBin && currBin == finalBin) ???
02554 #warning "Actually, this is wrong if the last section is one bin"
02555   //  (finalTrigger is the complete count, which may not be the 
02556   //   same as the number of triggers sent in last section)
02557   if(((currBin == finalBin) && (currEvent == finalTrigger))
02558      || ((currBin == finalBin) && (currEvent == (finalTrigger%65536)) && !progressMade)) {
02559 
02560     // Fix lastEvent in the case it's incorrect due to 16bitness
02561     lastEvent[rodLabel] = finalTrigger;
02562 
02563     if(api.mrs && !reportedFinished[rodLabel]) {
02564       reportedFinished[rodLabel]=true;
02565       *api.mrs << "HISTO_SUCCESS" << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
02566                << MRS_PARAM<int>("partition", rodLabel.partition)
02567                << MRS_PARAM<int>("crate", rodLabel.crate)
02568                << MRS_PARAM<int>("rod", rodLabel.rod)
02569                << MRS_TEXT("Histogramming successfully complete")
02570                << ENDM;
02571     }
02572 
02573     cout << "Histogramming completed successfully on rod " << rod << "\n";
02574 
02575     return true;
02576   }
02577 
02578   return false;
02579 }
02580 
02581 void ScanControlTIMHisto::finishHistogram(bool success) { 
02582   printVetoStatus();
02583   this->ScanControlRODHisto::finishHistogram(success);  
02584 }
02585 
02586 void ScanControlAsyncHisto::finishHistogram(bool success) { 
02587   printVetoStatus();
02588   this->ScanControlRODHisto::finishHistogram(success);  
02589 }
02590 
02591 void ScanControl::printVetoStatus(){
02592   // Total count of clocks spent with FFTVeto on
02593   long long loCount = api.timReadRegister(0x74);
02594   long long hiCount = api.timReadRegister(0x76);
02595   long long extCount = api.timReadRegister(0x78);
02596   long long count = loCount + (hiCount << 16) + ((extCount << 16) << 16);
02597   
02598   // Number Triggers Veto'd
02599   long loVeto = api.timReadRegister(0x7c);
02600   long hiVeto = api.timReadRegister(0x7e);
02601   long veto = loVeto + (hiVeto << 16);
02602   
02603   // Count of number of times the veto is asserted.
02604   long loVetos = api.timReadRegister(0x84);
02605   long hiVetos = api.timReadRegister(0x86);
02606   long vetos = loVetos + (hiVetos << 16);
02607 
02608   std::ostringstream vetostatus;
02609   vetostatus << "TIM FFTV Software disable:" << (bool)(api.timReadRegister(0x9c) & 0x100);
02610   vetostatus << "; Hardware disable:" << (bool)(api.timReadRegister(0x5a) & 0x8000);
02611   vetostatus << "; Veto on:" << (bool)(api.timReadRegister(0x5a) & 0x4000) << std::endl;
02612   
02613   std::ostringstream oss; 
02614   oss << std::hex << count << std::dec;
02615   
02616   std::cout << vetostatus.str();
02617   printf("TIM FFTV: Clocks spent vetoed %lld  Vetoed triggers %ld  Veto applications %ld\n", count, veto, vetos);
02618   
02619   if (api.mrs) {
02620     *api.mrs << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << "TIM_FFTV_STATUS"
02621          << MRS_TEXT("TIM module fixed-frequency veto status")
02622          << MRS_PARAM<const char*>("Number of clocks with veto applied",oss.str().c_str())
02623          << MRS_PARAM<long>("Number of triggers vetoed",veto)
02624          << MRS_PARAM<long>("Number of times veto applied",vetos)
02625          << MRS_PARAM<const char*>("Status",vetostatus.str().c_str())
02626          << ENDM;
02627   }
02628 } 
02629 
02630 void ScanControlRODHisto::finishHistogram(bool success) { 
02631   time_t scanEnd = time(0);
02632 
02633 #if USE_CONST_SCAN
02634   scanEx->setEndTime(second_clock::universal_time());
02635 #else
02636   scan->setEndTime(second_clock::universal_time());
02637 #endif
02638 
02639   std::cout << api.ucid() << " finished histogramming at TIME " << second_clock::universal_time() << std::endl;
02640 
02641   if(!useCCode(api, *scan)) {
02642     for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02643         ri != scanEx->rodInfo.end();
02644         ri++) {
02645       const RodLabel &rod = ri->first;
02646       const RodScanEx &rodInfo = ri->second;
02647 
02648       unsigned long SDSP_IDRAM_BASE;
02649       if(api.getRodRevision(rod) >= 0xe) {
02650         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02651       } else {
02652         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02653       }
02654 
02655       for(int s=0; s<numSlaves; s++) {
02656         if(rodInfo.bitFieldDSP & (1<<s)) {
02657           try {
02658 #warning "Hard coded reads of diagnostic register"
02659             unsigned long val = api.dspSingleBlockRead(rod.rod, 
02660                                                        SDSP_IDRAM_BASE + 0x10, s);
02661             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02662                  << " which should be 0x" << (1<<19) << dec << endl;
02663 
02664             // Flush cache
02665             unsigned long newVal = val | 1<<17;
02666             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02667             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02668             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02669                  << " which should be 0x" << (1<<17) << dec << endl;
02670 
02671             // Turn off flush and cache
02672             newVal = val | 1<<19;
02673             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02674             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02675             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02676                  << " which should be 0x" << (0) << dec << endl;
02677           } catch(VmeException &v) {
02678             Utility::decodeVme(v);
02679             cerr << "VmeException turning off slave " << s << " cache\n";
02680           }
02681         }
02682       }
02683     }
02684   }
02685 
02686 #if USE_CONST_SCAN
02687   setModuleScanCacheToLastPointInScan(api, scan, scanEx);
02688 #else
02689   setModuleScanCacheToLastPointInScan(api, scan);
02690 #endif
02691   
02692   std::cout << api.ucid() << " Done setModuleScanCacheToLastPointInScan at TIME " << second_clock::universal_time() << std::endl;
02693 
02694   // Read out if successful (even in debug mode!)
02695   //  but don't readout in debug mode if polling failed
02696   if(!scan->getOption(Scan::DEBUG) || success == true) {
02697     if(api.mrs) {
02698       *api.mrs << "SCAN_FINISHED" << MRS_INFORMATION 
02699                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02700                << MRS_TEXT("Scan finished") 
02701                << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02702                << MRS_PARAM<int>("ScanType1", scan->getScanVariable1())
02703                << MRS_PARAM<int>("ScanType2", scan->getScanVariable2())
02704                << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02705                << ENDM;
02706     }
02707 
02708     cout << api.ucid() << " Histogramming complete, " << (scanEnd - scanStart) << " seconds, tidying up...\n";
02709 //     {
02710 //       boost::mutex::scoped_lock lock(log().mutex());
02711 //       log() << "Histogramming complete, " << (scanEnd - scanStart) << " seconds\n";
02712 //     }
02713 
02714     cout << api.ucid() << " Starting to read histograms at TIME " << second_clock::universal_time() << std::endl;
02715 
02716     readHistograms();
02717 
02718     cout << api.ucid() << " Histograms read finished at TIME " << second_clock::universal_time() << std::endl;
02719   } else {
02720     if(!scan->getOption(Scan::DEBUG)) {
02721       cout << "Histogram polling failed\n";
02722 
02723       if(api.mrs) {
02724         *api.mrs << "SCAN_FAILED" << MRS_INFORMATION 
02725                  << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02726                  << MRS_TEXT("Scan polling failed") 
02727                  << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02728                  << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02729                  << ENDM;
02730       }
02731     }
02732   }
02733 
02734   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02735     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02736 
02737     api.print_calib(zeroRod.rod);
02738   }
02739   
02740   if(!scan->getOption(Scan::DEBUG)) {
02741     api.stopHistogramming(*scanEx);
02742 
02743     // Only restore module config if not debug mode
02744     postScanModuleSetup();
02745   } else {
02746     if(api.mrs) {
02747       *api.mrs << "SCAN_DEBUG" << MRS_INFORMATION 
02748                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02749                << MRS_TEXT("Scan done in debug mode, probably best to be at the command line to sort it out!") 
02750                << ENDM;
02751     }
02752 
02753     cout << "** In debug mode, you're responsible for terminating histogram and for readout\n";
02754   }
02755 
02756   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02757     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02758 
02759     api.print_calib(zeroRod.rod);
02760   }
02761 
02762   // This should now have been updated with the modules in the scan
02763   std::cout << scan->print();
02764   
02765 #if USE_IS
02766   if(api.m_isDict) 
02767     api.m_isDict->remove(api.idiosyncrasy().infoServiceNameOfScanStatusObject());
02768 #endif
02769 
02770   if(api.mrs)
02771     *api.mrs << "SCAN_COMPLETE" << MRS_INFORMATION << MRS_QUALIF("SctApi") << MRS_TEXT("Scan has completed") << ENDM;
02772 }
02773 
02774 void ScanControlRODHisto::postScanModuleSetup() {
02775   api.setErrorMasks();
02776 }
02777 
02778 bool ScanControlRODHisto::checkDebugOption(int opt) {
02779   return Debug::getInstance()->checkDebugOption((DebugOptions)opt);
02780 }
02781 
02782 void ScanControlRODHisto::reportEventErrors() {
02783   api.reportEventErrors();
02784 }
02785 
02786 unsigned int ScanControlRODHisto::getProcTime(const RodLabel rlabel, int dsp) {
02787   if(dsp == -1) {
02788     throw SctApiException("Can't getProcTime on MDSP");
02789   } else {
02790     int procTime;
02791 
02792     unsigned long SDSP_IDRAM_BASE;
02793     if(api.getRodRevision(rlabel) >= 0xe) {
02794       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02795     } else {
02796       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02797     }
02798 
02799     unsigned long length;
02800 
02801 #warning "Hard-coded address, sdsp histogram status block"
02802     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02803                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02804 
02805     if(regs) {
02806       long reg;
02807 
02808       // H stat reg 0
02809       reg = regs[6];
02810       procTime = ((reg >> 16) & 0xffff);
02811     } else {
02812       throw SctApiException("Failed to read getProcTime from DSP");
02813     }
02814 
02815     return procTime;
02816   }
02817 }
02818 
02819 ScanControlRODHisto::TrapBuffers ScanControlRODHisto::getTrapBuffers(const RodLabel rlabel, int dsp) {
02820   if(dsp == -1) {
02821     throw SctApiException("Invaled dsp passed to getTrapBuffers");
02822   } else {
02823     int ihead, itail, xhead, xtail;
02824 
02825     unsigned long SDSP_IDRAM_BASE;
02826     if(api.getRodRevision(rlabel) >= 0xe) {
02827       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02828     } else {
02829       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02830     }
02831 
02832     unsigned long length;
02833 #warning "Hard coded address of sdsp trap block"
02834     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02835                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02836 
02837     if(regs) {
02838       long reg;
02839 
02840       // Trap stat 1
02841       reg = regs[1];
02842       itail = ((reg & 0xff0000) >> 16);
02843       xtail = ((reg & 0xff000000) >> 24);
02844 
02845       // Trap stat 1
02846       reg = regs[2];
02847       ihead = ((reg & 0xff0000) >> 16);
02848       xhead = ((reg & 0xff000000) >> 24);
02849     } else {
02850       throw SctApiException("Failed to read DSP for getTrapBuffers");
02851     }
02852 
02853     return make_pair(make_pair(ihead, itail), make_pair(xhead, xtail));
02854   }
02855 }
02856 
02857 void ScanControlRODHisto::dumpHistoStatus(const RodLabel rlabel, int dsp) {
02858   if(dsp == -1) {
02859     const unsigned long MDSP_IDRAM_BASE = 0x80000000;
02860 
02861     // Histogram command stat 0
02862 #ifndef HCMD_STAT_REG_0 
02863 #warning "Reading hard-coded HCMD_STAT_REG_0"
02864     long reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x20, -1);
02865 #else
02866     long reg = api.dspSingleRead(0, HCMD_STAT_REG_0, -1);
02867 #endif
02868     cout << "Bin: " << (reg & 0xff) 
02869          << " Cal: " << ((reg & 0xff00) >> 8) 
02870          << " Errs: " << ((reg & 0xffff0000) >> 16) << endl;
02871 
02872     // Histogram command stat 1
02873 #ifndef HCMD_STAT_REG_1 
02874 #warning "Reading hard-coded HCMD_STAT_REG_1"
02875     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x24, -1);
02876 #else
02877     reg = api.dspSingleRead(0, HCMD_STAT_REG_1, -1);
02878 #endif
02879     cout << "avg. trans " << (reg & 0xff)
02880          << " avg. len " << ((reg & 0xff00) >> 8)
02881          << " avg. proc. " << ((reg & 0xffff0000) >> 16) << endl;
02882 
02883     // Histogram status 1
02884 #ifndef HSSTAT_REG_1 
02885 #warning "Reading hard-coded HSSTAT_REG_1"
02886     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x2c, -1);
02887 #else
02888     reg = api.dspSingleRead(0, HSSTAT_REG_1, -1);
02889 #endif
02890     cout << "Slave 0: " << (reg & 0xffff)
02891          << " Slave 1: " << ((reg & 0xffff0000) >> 16) << endl;
02892 
02893     // Histogram status 0
02894 #ifndef HSSTAT_REG_0 
02895 #warning "Reading hard-coded HSSTAT_REG_0"
02896     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x28, -1);
02897 #else
02898     reg = api.dspSingleRead(0, HSSTAT_REG_0, -1);
02899 #endif
02900     cout << "Slave 2: " << (reg & 0xffff)
02901          << " Slave 3: " << ((reg & 0xffff0000) >> 16) << endl;
02902   } else {
02903     unsigned long SDSP_IDRAM_BASE;
02904     if(api.getRodRevision(rlabel) >= 0xe) {
02905       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02906     } else {
02907       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02908     }
02909 
02910     unsigned long length;
02911 #warning "Hard coded block of trap status registers"
02912     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02913                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02914 
02915     if(regs) {
02916       long reg;
02917 
02918       cout << "TrapStatus: \n";
02919 
02920 
02921       // Trap stat 0
02922       reg = regs[1];
02923       int words = ((reg &0xffff) >> 0);
02924       int itail = ((reg & 0xff0000) >> 16);
02925       int xtail = ((reg & 0xff000000) >> 24);
02926 
02927       cout << "Event word count: " << words;
02928       cout << " IFrame tail: " << itail;
02929       cout << " XFrame tail: " << xtail << endl;
02930 
02931       // Trap stat 1
02932       reg = regs[2];
02933       int ihead = ((reg & 0xff0000) >> 16);
02934       int xhead = ((reg & 0xff000000) >> 24);
02935       cout << " IFrame head: " << ihead;
02936       cout << " XFrame head: " << xhead << endl;
02937 
02938       // Trap cmd stat
02939       reg = regs[17];
02940       cout << "Trap Command/Status: " 
02941            << ((reg & 0x1)?"Trailer ":"")            // TCSR_TRAILER
02942            << ((reg & 0x2)?"Transmit ":"")
02943            << ((reg & 0x4)?"Header ":"")
02944            << ((reg & 0x4)?"ISR active ":"");
02945       cout << ((reg & 0x10)?"\"Data Error\" ":"")
02946            << ((reg & 0x20)?"\"Header Error\" ":"")
02947            << ((reg & 0x40)?"\"Trailer Error\" ":"")
02948            << ((reg & 0x80)?"\"Link Error\" ":"");
02949       cout << ((reg & 0x100)?"\"Error\" ":"")
02950            << ((reg & 0x200)?"\"Overflow(old)\" ":"")
02951            << ((reg & 0x800)?"\"ISR pending\" ":"");
02952       cout << ((reg & 0x4000)?"\"Overflow error\" ":"")
02953            << ((reg & 0x8000)?"\"Overflow\" ":"");
02954       cout << endl;
02955 
02956       int errCount = ((reg >> 16) & 0xff);
02957       cout << "\"Error count\": " << errCount << endl;
02958       int evCount = ((reg >> 24) & 0xff);
02959       cout << "\"Event count\": " << evCount << endl;
02960 
02961       // Hcmd stat reg 0
02962       reg = regs[4];
02963       int currentBin = (reg & 0xff);
02964       cout << "Bin: " << currentBin
02965            << " Cal: " << ((reg & 0x1f00) >> 8) 
02966            << ((reg & 0x800)?" Cal enabled":"")
02967            << ((reg & 0x1000)?" New bin":"")
02968            << ((reg & 0x20000)?" New cal":"") << endl;
02969 
02970       // Hcmd stat reg 1
02971       reg = regs[5];
02972       int numEvents = reg;
02973       cout << "Num events: " << numEvents << endl;
02974 
02975       // H stat reg 0
02976       reg = regs[6];
02977       cout << "Histogram status: 0x" << hex << (reg & 0xffff) << dec << " " << ((reg & 0x1)?"Ready ":"")
02978            << ((reg & 0x2)?"Expecting ":"")
02979            << ((reg & 0x4)?"Processing ":"")
02980            << ((reg & 0x8)?"Done ":"") << endl;
02981 
02982       int procTime = ((reg >> 16) & 0xffff);
02983       cout << "Bin err: " << ((reg >> 8) & 0xff) 
02984            << " proc time: " << ((reg >> 16) & 0xffff) << endl;
02985 
02986       // H stat reg 1
02987       reg = regs[7];
02988       int evRecvd = reg;
02989       cout << "Events recvd: " << evRecvd << endl;
02990 
02991       ofstream statusOut("TIMStatus.txt", ios_base::out | ios_base::app);
02992       statusOut << currentBin << "\t" 
02993                 << ihead  << "\t" << itail << "\t" 
02994                 << xhead << "\t" << xtail << "\t"
02995                 << errCount << "\t" << evCount << "\t" 
02996                 << evRecvd << "\t" << words << "\t" << procTime << endl;
02997     }
02998   }
02999 }
03000 
03001 ScanControlTIMHisto::ScanControlTIMHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControlRODHisto(api, aScan, aScanEx), binCount(0) {
03002 }
03003 
03004 void ScanControlTIMHisto::startHistogramming() {
03005   // Set BCID offset to 3
03006   api.timWriteRegister(0x14, 0x3000);
03007 
03008   // reset TIM FFT veto counters
03009   for (unsigned reg=0x74; reg<=0x86; reg+=2){
03010     api.timWriteRegister(reg,0x0);
03011   }
03012 
03013   shared_ptr<PrimListWrapper> preTimList(new PrimListWrapper(4));
03014 // next two lines unnecessary - done at newBin PWP
03015 //  PrimBuilder::instance().rodMode(preTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1); 
03016 //  PrimBuilder::instance().writeRegister(preTimList, RTR_CMND_STAT, RTR_SLINK_DOWN_OVERRIDE_O, 1, 1);   // Mask LDown#
03017 
03018   for(int f=0; f<8; f++) {
03019 //     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0xaaaa);   // Decrement L1 for check
03020 //     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x5555);   // Increment L1 for check
03021     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x0);   // Clear L1 inc
03022   }
03023 
03024    //for(int ch=0; ch<48; ch++) {
03025    //  PrimBuilder::instance().writeRegister(preTimList, Utility::EfbErrorMask(0, ch), 5, 1, 1);  // Mask L1ID check
03026    //  PrimBuilder::instance().writeRegister(preTimList, Utility::EfbErrorMask(1, ch), 5, 1, 1);  // Mask L1ID check
03027    //}
03028 
03029   cout << "Sending pre TIM setup list\n";
03030   api.synchSendPrimListAll(preTimList);
03031   cout << " done sending pre TIM setup list\n";
03032 
03033   hex(cout);
03034   cout << "0x" << RTR_CMND_STAT << ": 0x" << api.readRODRegister(0, RTR_CMND_STAT) << endl;
03035   cout << "0x" << Utility::EfbErrorMask(0, 0) << ": 0x" << api.readRODRegister(0, Utility::EfbErrorMask(0, 0)) << endl;
03036   cout << "0x" << Utility::EfbErrorMask(1, 0) << ": 0x" << api.readRODRegister(0, Utility::EfbErrorMask(1, 0)) << endl;
03037   cout << "0x" << DM_DFLT_LUT(0) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(0)) << endl;
03038   cout << "0x" << DM_DFLT_LUT(1) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(1)) << endl;
03039   dec(cout);
03040 
03041   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03042     // This is added to by dumpHistoStatus
03043     ofstream statusOut("TIMStatus.txt");
03044     statusOut << "bin\tihead\titail\txhead\txtail\terrCnt\tevCount\tevRecvd\twords\tprocTime\n";
03045   }
03046 
03047   std::cout << "Wait for slave 0 of all RODs to be ready\n";
03048 
03049 /*
03050   bool ready;
03051   unsigned long loop = 0;
03052   do{
03053     ready = true;
03054     for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
03055         ri != scanEx->rodInfo.end();
03056         ri++) {
03057       const RodLabel &rodLabel = ri->first;
03058 
03059       unsigned long SDSP_IDRAM_BASE;
03060       if(api.getRodRevision(rodLabel) >= 0xe) {
03061         SDSP_IDRAM_BASE = 0x10000;
03062       } else {
03063         SDSP_IDRAM_BASE = 0x80000000;
03064       }
03065       unsigned long reg = api.dspSingleBlockRead(rodLabel.rod, SDSP_IDRAM_BASE+0x28, 0);
03066       if((reg & 0x01) == 0) ready = false;
03067     }
03068     loop ++;
03069     usleep(1000); //1mS
03070   }while((ready == false) && (loop < 1000));
03071 
03072   if(loop > 999){
03073     std::cout << "timeout waiting for slaves to be ready\n";
03074   }else{
03075     std::cout << "Slaves ready in " << loop << " loops\n";
03076   }
03077 */
03078 }
03079 
03080 void ScanControlTIMHisto::nextBin() {
03081   cout << "TIM histo, next bin\n";
03082 
03083   unsigned scanvariable1 = scan->getScanVariable1();
03084   if (scanvariable1!=0){
03085     double value = scan->getScanPoints1()[binCount];
03086     
03087     if (ConfigUtility::isModuleRegister(scanvariable1)){
03088       std::list<BankType> banks;
03089       banks.push_back(SCTAPI_BANK_SCAN);
03090       api.modifyABCDVarROD(scanvariable1, value, banks);
03091     } else if (ConfigUtility::isTimRegister(scanvariable1) ) {
03092       api.modifyTIMParam(scanvariable1, (int)(value+0.5));
03093     } else if (ConfigUtility::isBocRegister(scanvariable1) ){
03094       api.modifyBOCParam(scanvariable1, (int)(value+0.5));
03095     } else if (ConfigUtility::variableType(scanvariable1)==ConfigUtility::TRIGGER_VAR) {
03096       ; // done later
03097     } else {
03098       if (api.mrs) {
03099     *api.mrs << "BAD_SCAN_VARIABLE" << MRS_TEXT("Unknown scan variable in TIM scan")
03100          << MRS_PARAM<int>("Variable number",scanvariable1) << MRS_WARNING << ENDM;
03101       } else{
03102     std::cout << "Warning - bad scan variable : " << scanvariable1 
03103           << " type " << ConfigUtility::variableType(scanvariable1) << std::endl;
03104       }
03105     }
03106   }
03107 
03108   // AJB add this?
03109   //if (!ConfigUtility::isBOCRegister(scan->getScanVariable1())) 
03110   api.sendAllABCDModules(SCTAPI_BANK_SCAN);
03111   
03112   // SET_TRIGGER (ie tell histograms about next bin)
03113   shared_ptr<PrimListWrapper> setTriggerList(new PrimListWrapper(4));
03114   PrimBuilder::instance().setTrigger(setTriggerList, binCount, Utility::translateBank(SCTAPI_BANK_SCAN));
03115 
03116   shared_ptr<PrimListWrapper> binTimList(new PrimListWrapper(4));
03117 
03118   // Send to all slaves
03119   for(int s=0; s<4; s++) {
03120     PrimBuilder::instance().slavePrimList(binTimList, setTriggerList, s, 1, 0);
03121   }
03122 
03123   PrimBuilder::instance().rodMode(binTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1);
03124   PrimBuilder::instance().writeRegister(binTimList, RTR_CMND_STAT, RTR_SLINK_DOWN_OVERRIDE_O, 1, 1);   // Mask LDown#
03125 
03126   cout << "Sending TIM setup list\n";
03127   api.synchSendPrimListAll(binTimList);
03128   cout << " done sending TIM setup list\n";
03129 
03130   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03131     cout << "******************* Pre triggers status ********************\n";
03132     dumpHistoStatus(RodLabel(), 0);
03133   }
03134 
03135   cout << "Sending soft/bc resets to crate: " << api.ucid() << endl;
03136   api.timSoftReset();
03137   api.timBCReset();
03138 
03139   Scan::TrigPoints trigs = scan->getVariableTrigs();
03140 
03141   cout << "Want " << trigs[binCount] << " triggers to crate: " << api.ucid() << endl;
03142 
03143   const Trigger& trig1 = *scan->getTrigger1();
03144   
03145   if(1) {
03146     switch(scan->getOption(Scan::TIM)) {
03147     case 1:
03148       // Just send lots of triggers, relies on user to set up frequency/nth appropriately
03149       {
03150     api.sendTriggers(&trig1, trigs[binCount], binCount);
03151       }
03152       break;
03153     case 2:
03154 #warning "Assumes ROD 0!!!"
03155       // Send one trigger at a time, then wait maximum of 1 second for trap buffers to equalize
03156       for(unsigned int i=0; i<trigs[binCount]; i++) {
03157     api.timL1A();
03158     
03159     TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03160     
03161     if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03162       sleep(1);
03163       }
03164       break;
03165     case 3:
03166 #warning "Assumes ROD 0!!!"
03167       // Send in bursts of triggers, wait for them to finish
03168       // Designed to be run at 100kHz
03169       {
03170     unsigned int sentTriggers = 0;
03171     const unsigned int trigsPerBurst = 20;
03172     
03173     while(sentTriggers < trigs[binCount]) {
03174       if(sentTriggers % 1000 < trigsPerBurst) {
03175         cout << "Done " << sentTriggers << " triggers\n";
03176         if(checkDebugOption(DEBUG_TIM_SCAN_STATUS))
03177           dumpHistoStatus(RodLabel(), 0);
03178       }
03179       int ntrigs = min(trigs[binCount]-sentTriggers, trigsPerBurst);
03180       api.sendTimBurst(ntrigs,false);
03181       sentTriggers += ntrigs;
03182       
03183       // Have they been processed yet?
03184       TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03185       
03186       TrapBuffers oldtb;
03187       if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03188         do {
03189           oldtb = tb;
03190           usleep(trigsPerBurst * 10);  // 7 * 10us at 100kHz 
03191           tb = getTrapBuffers(RodLabel(), 0);
03192           
03193           if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
03194           if(tb == oldtb) break;
03195         } while(1); 
03196     }
03197       }
03198       break;
03199     case 4:
03200 #warning "Assumes ROD 0!!!"
03201       // Adjust frequency depending on how long the previous set of triggers 
03202       //  takes to histogram, first 1 then 10 then the rest.
03203       {
03204     unsigned int sentTriggers = 0;
03205     
03206     api.timL1A();
03207     sentTriggers ++;
03208     
03209     //   // Set 100kHz triggers
03210     //   api.timSetFrequency(100, 0);
03211     
03212     unsigned int procTime = getProcTime(RodLabel(), 0);
03213     double timFrequency = 0.25 * 1e6/procTime;
03214     // Don't go faster than 6kHz
03215     api.timSetFrequency(min(6.0, timFrequency/1000), 0);
03216     
03217     cout << "*** Proc Time for 1 trigger was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
03218     
03219     procTime = getProcTime(RodLabel(), 0);
03220     timFrequency = 0.25 * 1e6/procTime;
03221     api.timSetFrequency(min(6.0, timFrequency/1000), 0);
03222     
03223     cout << "*** Proc Time after 10 trigs was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
03224     
03225     if(trigs[binCount] > sentTriggers)
03226       api.sendTimBurst(trigs[binCount]-sentTriggers,false);
03227     
03228     if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03229       cout << "******************* Post triggers status ********************\n";
03230       dumpHistoStatus(RodLabel(), 0);
03231     }
03232     
03233     TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03234     
03235     TrapBuffers oldtb;
03236     if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03237       do {
03238         oldtb = tb;
03239         sleep(1);
03240         tb = getTrapBuffers(RodLabel(), 0);
03241         
03242         if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
03243         if(tb == oldtb) break;
03244       } while(1); 
03245     break;
03246       }
03247     default:
03248       {
03249     std::cout << "ERROR - unknown TIM option : " 
03250           << (scan->getOption(Scan::TIM)) << std::endl;
03251     break;
03252       }
03253     } // End switch on TIM histogramming types
03254   }
03255   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03256     cout << "******************* Post triggers status 2 ******************\n";
03257     dumpHistoStatus(RodLabel(), 0);
03258   }
03259 
03260   //  TTrigger soft;
03261   //soft.softL1A(30);
03262 
03263   //  api.timL1A();
03264   binCount ++;
03265 }
03266 
03267 // TIM histos don't run Histo Control so event counters not mirrored to master
03268 // A sort of dummy function at the moment...
03269 bool ScanControlTIMHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
03270 
03271   unsigned long slvEvtCnt1 = getEventCounter(rodLabel, 0, false);
03272   usleep(10000); // 10mS??
03273   unsigned long slvEvtCnt2 = getEventCounter(rodLabel, 0, false);
03274   
03275   if(slvEvtCnt1 != slvEvtCnt2){
03276     // progress was made if this changed
03277     progressMade = true;
03278     newBin = false;
03279   }else if((binCount>0) && (slvEvtCnt2 == 0)){
03280     // Not the first bin, but no events were seen: nothing happened!
03281     // (Necessary because polling starts before first TIM trigger is issued)
03282     progressMade == false;
03283     newBin = false;
03284   }else{
03285     // neither count changed and at least one of them is not zero:
03286     // assume this bin has been completed
03287     progressMade = true;
03288     newBin = true;
03289   }
03290 
03291   std::cout << "Checking TIM scan complete: slvCount1 " <<  slvEvtCnt1 << " slvCount2 " << slvEvtCnt2 << endl;
03292 
03293   totalBin += binCount-1;
03294 
03295   //  cout << "Are we at the end: " << (binCount-1) << " " << finalBin << endl;
03296 
03297   if((binCount-1 >= finalBin)) {
03298     return true;
03299   }
03300 
03301   return false;
03302 }
03303 
03304 // bool ScanControlTIMHisto::checkScanComplete(bool &progressMade) {
03305 //   return false;
03306 // }
03307 
03308 ScanControlAsyncHisto::ScanControlAsyncHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControlRODHisto(api, aScan, aScanEx), binCount(0) {
03309 }
03310 
03311 void ScanControlAsyncHisto::startHistogramming() {
03312 #warning "Should we check we're in physics mode?"
03313   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03314     // This is added to by dumpHistoStatus
03315     ofstream statusOut("TIMStatus.txt");
03316     statusOut << "bin\tihead\titail\txhead\txtail\terrCnt\tevCount\tevRecvd\twords\tprocTime\n";
03317   }
03318 }
03319 
03320 void ScanControlAsyncHisto::nextBin() {
03321   cout << "Asynchronous histo, next bin\n";
03322 
03323   if (scan->getScanVariable1()!=0){
03324     std::list<BankType> banks;
03325     banks.push_back(SCTAPI_BANK_SCAN);
03326     
03327     api.modifyABCDVarROD(scan->getScanVariable1(), scan->getScanPoints1()[binCount], banks);
03328   }
03329 
03330   if(0) {
03331     // AJB add this?
03332     //if (!ConfigUtility::isBOCRegister(scan->getScanVariable1())) 
03333     api.sendAllABCDModules(SCTAPI_BANK_SCAN);
03334   }
03335 
03336   // SET_TRIGGER (ie tell histograms about next bin)
03337   shared_ptr<PrimListWrapper> setTriggerList(new PrimListWrapper(4));
03338   PrimBuilder::instance().setTrigger(setTriggerList, binCount, Utility::translateBank(SCTAPI_BANK_SCAN));
03339 
03340   shared_ptr<PrimListWrapper> binTimList(new PrimListWrapper(4));
03341 
03342   // Send to all slaves
03343   for(int s=0; s<4; s++) {
03344     PrimBuilder::instance().slavePrimList(binTimList, setTriggerList, s, 1, 0);
03345   }
03346 
03347   // Do this if configuring modules, otherwise, we're already in physics mode
03348 //   PrimBuilder::instance().rodMode(binTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1);
03349 //   PrimBuilder::instance().writeRegister(binTimList, RTR_CMND_STAT, RTR_SLINK_DOWN_OVERRIDE_O, 1, 1);   // Mask LDown#
03350 
03351   cout << "Sending async TIM set trigger list\n";
03352   api.synchSendPrimListAll(binTimList);
03353   cout << " done sending async TIM set trigger list\n";
03354 
03355   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03356     cout << "******************* Next bin triggers status ********************\n";
03357     dumpHistoStatus(RodLabel(), 0);
03358   }
03359 
03360 //   cout << "Sending soft/bc resets to crate: " << api.ucid() << endl;
03361 //   api.timSoftReset();
03362 //   api.timBCReset();
03363 
03364   binCount ++;
03365 }
03366 
03367 }

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