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

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       {
01124         boost::mutex::scoped_lock lock(log().mutex());
01125         log() << "Stop Event trapping on slave " << slaveNumber << endl;
01126       }
01127       sendPrimList(rod.rod, primList);
01128 
01129       awaitResponse(rod.rod, 5);
01130       primList->clear();
01131 
01132       cout << "Done kill event trapping\n";
01133     }
01134   }
01135 
01136   //  sendPrimList(ex.rod, primList);
01137   //  awaitResponse(ex.rod, 2);
01138   cout << "Done kill histogramming tasks\n";
01139 }
01140 
01141 ScanControl::ScanControl(SctApi &api) : api(api) {}
01142 
01143 #if USE_CONST_SCAN
01144 void  ScanControl::setModuleScanCacheToLastPointInScan(SctApi &api, boost::shared_ptr<const Scan> scan,
01145                                boost::shared_ptr<const ScanEx> scanEx) {
01146 #else
01147 void  ScanControl::setModuleScanCacheToLastPointInScan(SctApi &api, boost::shared_ptr<const Scan> scan) {
01148 #endif
01149   if (api.checkDebugOption(DEBUG_MODULE_CONFIG)) {
01150     std::cout << "setModuleScanCacheToLastPointInScan setting the following values:\n"
01151           << "mid\tsn\tvariable\tvalue\tvar 1/2?" << std::endl;
01152   }
01153 
01154 #if USE_CONST_SCAN
01155   for(unsigned int group = 0; group < scanEx->getNGroups(); group ++) {
01156     const ModuleList &groupList = scanEx->getModuleList(group);
01157 #else
01158   for(unsigned int group = 0; group < scan->getNGroups(); group ++) {
01159     const ModuleList &groupList = scan->getModuleList(group);
01160 #endif
01161     for(ModuleList::const_iterator mi = groupList.begin();
01162     mi!=groupList.end();
01163     mi ++) {
01164       
01165       string sn = *mi;
01166       UINT32 mid = api.findModule(sn);
01167       {
01168     unsigned int partition, crate, rod, channel;
01169     Utility::getpcrc(mid, partition, crate, rod, channel);
01170     if (api.idiosyncrasy().ucid() != Sct::UCID(partition, crate)) {
01171       std::cout << "\nWARNING!!! I didnt think that sn " << sn << " was on this crate!!!\n" 
01172             << __FILE__ << ":" <<  __LINE__ << std::endl;
01173       continue;  // next module
01174     }
01175       }
01176       boost::shared_ptr<SctApiConfigCache::ModuleBanks> banks = api.getModuleConfigCache().getFromMid(mid);
01177       if (!banks.get()){
01178     if (api.mrs) {
01179       *api.mrs << "NO_CACHED_CONFIG" << MRS_ERROR
01180            << MRS_QUALIF("SctApi")
01181            << MRS_PARAM<int>("mid", mid) 
01182            << MRS_TEXT("No cache at all available when setting cache at end of scan") << ENDM;
01183     }else{
01184       std::cout << "ERROR! No cache at all available when setting cache at end of scan, mid" << mid << std::endl; 
01185     }
01186     continue;
01187       }
01188       boost::shared_ptr<ABCDModule> config = banks->get(SCTAPI_BANK_SCAN);
01189       if (!config.get()){
01190     if (api.mrs) {
01191       *api.mrs << "NO_CACHED_CONFIG" << MRS_ERROR
01192            << MRS_QUALIF("SctApi")
01193            << MRS_PARAM<int>("mid", mid) 
01194            << MRS_TEXT("No SCAN cache available when setting cache at end of scan") << ENDM;
01195     }else{
01196       std::cout << "ERROR! No SCAN cache available when setting cache at end of scan, mid" << mid << std::endl; 
01197     }
01198     continue;
01199       }
01200 
01201       if (group<4){
01202     const ::SctApi::Scan::ScanPoints points = scan->getScanPoints1();
01203     if (!points.empty() && scan->getScanVariable1()!=0 ) {
01204       ConfigUtility::modifyVar(config.get(), scan->getScanVariable1(), points[points.size()-1]);
01205       if(api.checkDebugOption(DEBUG_MODULE_CONFIG)){
01206         std::cout << mid << "\t" << sn  << "\t" << scan->getScanVariable1()  << "\t"
01207               << points[points.size()-1]  << "\t" << "\t[1]" << std::endl;
01208       }
01209     }
01210       }else{
01211     const ::SctApi::Scan::ScanPoints points = scan->getScanPoints2();
01212     if (!points.empty() && scan->getScanVariable2()!=0 ) {
01213       ConfigUtility::modifyVar(config.get(), scan->getScanVariable2(), points[points.size()-1]);
01214       if(api.checkDebugOption(DEBUG_MODULE_CONFIG)){
01215         std::cout << mid << "\t" << sn  << "\t" << scan->getScanVariable1()  << "\t"
01216               << points[points.size()-1]  << "\t" << "\t[2]" << std::endl;
01217       }
01218     }
01219       }
01220     }
01221   }
01222   if(api.checkDebugOption(DEBUG_MODULE_CONFIG)) std::cout << std::endl;
01223 }
01224 
01225 void ScanControlRODHisto::readHistograms() {
01226   time_t saveTime;
01227   saveTime = time(NULL);
01228 
01229   /* Loop over RODs and release memory at the end to save space
01230        Makes algorithm slightly inefficient (multiple loops over module list)
01231        but better than crashing due to OOM!
01232   */
01233   list<RodLabel> rodList = api.listRods();
01234 
01235   for(list<RodLabel>::const_iterator rl = rodList.begin();
01236       rl!=rodList.end();
01237       rl++){
01238 
01239     cout << "Reading out modules from ROD " << Sct::URID(rl->partition,
01240                              rl->crate,
01241                              rl->rod) << " of " << rodList.size() << endl;
01242 
01243     // For each module
01244 #if USE_CONST_SCAN
01245     const unsigned int nGrOuPs = scanEx->getNGroups();
01246 #else
01247     const unsigned int nGrOuPs = scan->getNGroups();
01248 #endif
01249     for(unsigned int group = 0; group < nGrOuPs; group ++) {
01250 #if USE_CONST_SCAN
01251       const ModuleList &groupList = scanEx->getModuleList(group);
01252 #else
01253       const ModuleList &groupList = scan->getModuleList(group);
01254 #endif
01255       cout << "Modules in group " << group << " of " << nGrOuPs << ": count= " << groupList.size() << endl;
01256       for(ModuleList::const_iterator mi = groupList.begin();
01257           mi!=groupList.end();
01258           mi ++) {
01259 
01260         string sn = *mi;
01261     cout << "Attempting to find mid for ["<<sn<<"]"<<std::endl;
01262         UINT32 mid = api.findModule(sn);
01263 
01264     cout << "serial number is [" << sn << "] mid = " << mid << std::endl;
01265 
01266         {
01267           unsigned int partition, crate, rod, channel;
01268           Utility::getpcrc(mid, partition, crate, rod, channel);
01269           if(RodLabel(partition, crate, rod) != *rl) {
01270             // Come back later
01271         cout << "Skipping " << sn << " (in ROD " << Sct::URID(partition,crate,rod) << " not " << Sct::URID(rl->partition, rl->crate, rl->rod) << ")\n";
01272             continue;
01273           }
01274         }
01275 
01276         cout << "Module:  " << mid << " = " << sn << endl;
01277 
01278         try {
01279           if(scan->getOption(Scan::FULL)) {
01280         std::cout << "Readout full mode histograms:" << std::endl;
01281             for(int f=0; f<3; f++) {
01282           std::cout << "    (" << f << " of 3)" << std::endl;
01283               scan_result_ptrs result = readHistogramData(mid, f);
01284 
01285               result.header.scanNumber += f;
01286 
01287               // Files need discriminating because they're all the same time
01288               if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
01289                 readHistogramToFile(api.ucid(), *scan, *scanEx, mid, api.convertToString(mid), result, saveTime, f);
01290               }
01291 
01292 #ifdef USE_IS
01293               // IS based on Run/Scan number so nothing more needed
01294               if(api.mrs) readHistogramToIS(api.ucid(), *scan, *scanEx, mid, result);
01295 #endif
01296 
01297               delete [] (char*)result.data;
01298               delete [] result.points;
01299               delete [] result.nEvents;
01300               delete [] result.nErrorEvents;
01301             }
01302           } else {
01303         std::cout << "Readout non-full mode histogram" << std::endl;
01304             scan_result_ptrs result = readHistogramData(mid, 0);
01305 
01306             if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
01307               readHistogramToFile(api.ucid(), *scan, *scanEx, mid, api.convertToString(mid), result, saveTime);
01308             }
01309 #ifdef USE_IS
01310             if(api.mrs)readHistogramToIS(api.ucid(), *scan, *scanEx, mid, result);
01311 #endif
01312             delete [] (char*)result.data;
01313             delete [] result.points;
01314             delete [] result.nEvents;
01315             delete [] result.nErrorEvents;
01316           }
01317         } catch(SctApiException &s) {
01318       std::cout << "Scan readout failed" << std::endl;
01319           if(api.mrs) {
01320             *api.mrs << "SCAN_READOUT_FAIL" << MRS_ERROR
01321                      << MRS_QUALIF("SctApi")
01322                      << MRS_PARAM<int>("run", scan->getRunNumber()) 
01323                      << MRS_PARAM<int>("scan", scan->getScanNumber()) 
01324                      << MRS_PARAM<int>("mid", mid) 
01325                      << MRS_TEXT("Module readout failed") << ENDM;
01326           }
01327         }
01328       } // Histogram for next module
01329     } // Next module group
01330 
01331     // Release memory from ROD
01332     for(std::map<std::pair<RodLabel, int>, 
01333           Utility::MemoryBlock> :: iterator mapIter = scanEx->histoMap.begin();
01334         mapIter != scanEx->histoMap.end();
01335         mapIter++) {
01336 
01337       if(mapIter->first.first == *rl) {
01338         if(api.mrs) {
01339           *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
01340                    << MRS_PARAM<float>("MWords", mapIter->second.size() / 1e6)
01341                    << MRS_PARAM<int>("crate", rl->crate)
01342                    << MRS_PARAM<int>("rod", rl->rod)
01343                    << MRS_TEXT("Releasing memory after histogram readout") << ENDM;
01344         }
01345 
01346         mapIter->second = Utility::MemoryBlock();
01347       }
01348     }
01349   } // End ROD loop
01350 }
01351 
01352 scan_result_ptrs ScanControlRODHisto::readHistogramData(UINT32 mid, int frame) {
01353   scan_result_ptrs scanResult;
01354 
01355   //We do this first deliberately.
01356   //The dummy api will need to mess around with some things
01357   scanResult.data = readHistogramRawData(mid, frame);
01358 
01359   if(scanResult.data == 0) {
01360     cout << "readHistogramRawData returned 0 in readHistogramData";
01361     throw SctApiException("readHistogramRawData returned 0 in readHistogramData");
01362   }
01363 
01364   int nBins = scan->getScanPoints1().size();
01365 
01366   // Read the module configuration from the end of the scan...
01367 
01368   /* Modifyed 2/6/2005 AJB to use the SCAN bank _directly_
01369    * api.getABCDModule(mid, SCTAPI_BANK_SCAN);
01370 
01371   // Save copy of configuration from end of scan
01372    */
01373  
01374   ABCDModule moduleConfig; // no initial value - SHOULD always be set below or there is an error.
01375   boost::shared_ptr<SctApiConfigCache::ModuleBanks> the_banks=api.getModuleConfigCache().getFromMid(mid);
01376   if (!the_banks.get()) {
01377     if(api.mrs) {
01378       *api.mrs << "ROD_BANK_CONFIG_CACHE" << MRS_ERROR << MRS_QUALIF("SCTAPI")
01379            << MRS_PARAM<int>("mid", mid)
01380            << MRS_TEXT("Cant return cache for non-existant MID at end of scan") << ENDM;
01381     }else{
01382       cerr << "Non-existant module mid=" << mid << std::endl;
01383     }
01384   } else {
01385     boost::shared_ptr<ABCDModule> scan_config = the_banks->get(SCTAPI_BANK_SCAN);
01386     if (!scan_config.get()){
01387       if(api.mrs) {
01388     *api.mrs << "ROD_BANK_CONFIG_CACHE" << MRS_ERROR << MRS_QUALIF("SCTAPI")
01389          << MRS_PARAM<int>("mid", mid)
01390          << MRS_TEXT("Cant return cache for non-existant SCAN BANK at end of scan") << ENDM;
01391       }else{
01392     cerr << "Non-existant scan bank at end of scan ! mid=" << mid << std::endl;
01393       }
01394     } else {
01395       moduleConfig = *scan_config;
01396     }
01397   }
01398 
01399   if(checkDebugOption(DEBUG_MODULE_CONFIG)) {
01400     cout << "Configuration after scan temporarily not available \n";
01401     //cout << api.config->printABCDModule(moduleConfig); // private
01402   }
01403 
01404   ScanHeader &header = scanResult.header;
01405 
01406   header.version = CURRENT_SCANHEADER_VERSION;
01407   header.length = sizeof(ScanHeader);
01408   header.runNumber = scan->getRunNumber();
01409   header.scanNumber = scan->getScanNumber();
01410   
01411   strncpy(header.moduleName, api.convertToString(mid).c_str(), 16);
01412 #if USE_CONST_SCAN
01413   strncpy(header.startTime, to_iso_string(scanEx->getStartTime()).c_str(), 16);
01414   strncpy(header.endTime, to_iso_string(scanEx->getEndTime()).c_str(), 16);
01415 #else
01416   strncpy(header.startTime, to_iso_string(scan->getStartTime()).c_str(), 16);
01417   strncpy(header.endTime, to_iso_string(scan->getEndTime()).c_str(), 16);
01418 #endif
01419   header.moduleName[15] = 0;    // Null terminate the string
01420   header.startTime[15] = 0;
01421   header.endTime[15] = 0;
01422   
01423 //   snprintf(header.moduleName, 16, "%s", convertToString(mid).c_str());
01424 //   cout << "Module name in Scan Results (" << header.moduleName << ")\n" ;
01425   header.scanType = scan->getScanVariable1();
01426   header.npoints = nBins;
01427   header.size = nBins * 2 * 1024 * (scan->getOption(Scan::BITS32)?2:1);
01428   header.dataType = SR_DT_SLICE;
01429 
01430   header.width = scan->getOption(Scan::BITS32)?SR_WD_32:SR_WD_16;
01431 
01432   header.config = moduleConfig;
01433 
01434   header.pntPoints = sizeof(ScanHeader);
01435   header.pntEvents = header.pntPoints + nBins * sizeof(FLOAT32);
01436   header.pntErrors = header.pntEvents + nBins * sizeof(UINT32);
01437   header.pntData = header.pntErrors + nBins * sizeof(UINT32);
01438 
01439   // The points
01440   FLOAT32 *points = new FLOAT32[nBins];
01441   for(int i=0; i<nBins; i++) {
01442     points[i] = scan->getScanPoints1()[i];
01443   }
01444   scanResult.points = points;
01445 
01446   // The event counts
01447   UINT32 *events = new UINT32[nBins];
01448 
01449   std::pair<RodLabel, unsigned int> moduleSlave = findModuleSlave(mid);
01450 
01451   // This is the better way of counting (especially when there are errors)
01452   unsigned long *countChunk = getEventCountChunk(moduleSlave.first, moduleSlave.second);
01453 
01454   for(int i=0; i<nBins; i++) {
01455     events[i] = countChunk[i];
01456 
01457     // Unfortunately it counts * 4 for cal line loop
01458     if(scan->getOption(Scan::LOOPCALLINE)) {
01459       events[i] >>= 2; 
01460     }
01461   }
01462 
01463 #if 0
01464   // But this way does get the count right with the callineloop on!
01465   Scan::TrigPoints trigs = scan->getVariableTrigs();
01466  
01467   for(int i=0; i<nBins; i++) {
01468     if(i<lastBin[moduleSlave.first]) {
01469       events[i] = trigs[i];
01470     } else if(i == lastBin[moduleSlave.first]) {
01471       events[i] = lastEvent[moduleSlave.first];
01472     } else {
01473       events[i] = 0;
01474     }
01475   }
01476 #endif
01477 
01478   scanResult.nEvents = events;
01479 
01480   // The error counts
01481   UINT32 *errors = new UINT32[nBins];
01482   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
01483   for(int i=0; i<nBins; i++) {
01484     // An error is when a requested event doesn't get to be histogrammed
01485     errors[i] = trigPoints[i] - events[i];
01486   }
01487   scanResult.nErrorEvents = errors;
01488 
01489   return scanResult;
01490 }
01491 
01492 char* ScanControlRODHisto::readHistogramRawData(UINT32 mid, int frame) {
01493   int nBins = scan->getScanPoints1().size();
01494 
01495   // The number of bins the ROD thinks there are...
01496   int rodBins = nBins;
01497   if(!scan->getOption(Scan::BITS32))
01498     if(rodBins%2 == 1) rodBins++;
01499 
01500   // The data!
01501   int binSize = 0x800*(scan->getOption(Scan::BITS32)?4:2);   // In bytes, so works for 16bit histograms
01502 
01503   char *data = new char[nBins * binSize];
01504 
01505   bool moduleBlock = false;
01506 //    int baseAddress = index*(binSize*nBins);
01507 
01508   unsigned int slaveNumber = 4;
01509 
01510   RodLabel rodLabel;
01511   unsigned int channel;
01512   {
01513     unsigned int partition, crate, rod;
01514     Utility::getpcrc(mid, partition, crate, rod, channel);
01515     RodLabel temp(partition, crate, rod);
01516     rodLabel = temp;
01517   }
01518 
01519   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01520 
01521   for(int slave=0; slave<4; slave++) {
01522     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01523        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01524       if(slaveNumber == 4) {
01525         slaveNumber = slave;
01526       } else {
01527         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01528         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01529 #warning "But maybe I should any way"
01530       }
01531     }
01532   }
01533 
01534   if(slaveNumber == 4) {
01535     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01536 
01537     throw SctApiException("No mapping from module to DSP found");
01538   }
01539 
01540   // Find the module index on this slave
01541   int index = 0;
01542   int nModules = 0; // moduleMap.size();
01543 
01544   for(unsigned int ch=0; ch<48; ch++) {
01545     if(channel == ch) {
01546       index = nModules;
01547     }
01548     if(ch<32) {
01549       if(rodInfo.slaveChannels[slaveNumber].mask0 & 1<<ch) {
01550         nModules ++;
01551       }
01552     } else {
01553       if(rodInfo.slaveChannels[slaveNumber].mask1 & 1<<(ch-32)) {
01554         nModules ++;
01555       }
01556     }
01557   }
01558 
01559   // Get data from place defined by DSP
01560   unsigned long slaveOffset = 0;
01561 
01562   if(moduleBlock) {
01563     slaveOffset += binSize * rodBins;
01564   } else {
01565     slaveOffset += binSize * index;
01566   }
01567 
01568   // For reading expanded data, skip to next block of histograms...
01569   slaveOffset += ((binSize * rodBins * nModules) + binSize) * frame;
01570 
01571   bool error = false;
01572 
01573   for(int i=0; i<nBins; i++) {
01574     unsigned long *chunk = getHistogramChunk(rodLabel, slaveNumber, slaveOffset, binSize/sizeof(UINT32));
01575     unsigned long *buffer = (unsigned long *)&(data[i*binSize]);
01576 
01577     if(chunk) {
01578       for(int b=0; b<binSize/sizeof(UINT32); b++) {
01579         buffer[b] = chunk[b];
01580       }
01581 
01582       // Check End of bin xx Module xx
01583       int bin, module;
01584       int count = sscanf(&((char*)buffer)[binSize-32], "End of bin %d Module %d", &bin, &module);
01585       if(count == 2) {
01586 //          printf("Found End of bin %d module %d\n", bin, module);
01587       } else {
01588         if(!error)
01589           printf("Found bad end of histogram bin (%25s)\n", &((char*)buffer)[binSize-32]);
01590         error = true;
01591       }
01592 
01593 #warning "Memory leak if sendData didn't work"
01594 //       delete [] chunk;
01595     } else {
01596       for(int b=0; b<binSize/sizeof(UINT32); b++) {
01597         buffer[b] = 0;
01598       }
01599     }
01600 
01601     if(moduleBlock) {
01602       slaveOffset += binSize;
01603     } else {
01604       slaveOffset += binSize * nModules;
01605     }
01606   }
01607 
01608   return data;
01609 }
01610 
01611 pair<RodLabel, unsigned int> ScanControlRODHisto::findModuleSlave(unsigned int mid) {
01612   RodLabel rodLabel;
01613   unsigned int channel;
01614   {
01615     unsigned int partition, crate, rod;
01616     Utility::getpcrc(mid, partition, crate, rod, channel);
01617     RodLabel temp(partition, crate, rod);
01618     rodLabel = temp;
01619   }
01620 
01621   unsigned int slaveNumber = 4;
01622 
01623   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01624 
01625   for(int slave=0; slave<4; slave++) {
01626     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01627        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01628       if(slaveNumber == 4) {
01629         slaveNumber = slave;
01630       } else {
01631         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01632         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01633 #warning "But maybe I should any way"
01634       }
01635     }
01636   }
01637 
01638   if(slaveNumber == 4) {
01639     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01640 
01641     throw SctApiException("No mapping from module to DSP found");
01642   }
01643 
01644   return make_pair(rodLabel, slaveNumber);
01645 }
01646 
01647 void readHistogramToFile(const Sct::UCID & ucid, const Scan &scan, const ScanEx &ex, 
01648                          UINT32 mid, std::string sn, scan_result_ptrs scanData, time_t saveTime, int frame) {
01649   const int BUFF_SIZE = 50;
01650 
01651   struct tm broke;
01652   broke = *(gmtime(&saveTime));
01653 
01654   string tempDir = SctNames::getTempDir() + "/";
01655   int bufferLength = BUFF_SIZE + tempDir.length();
01656   char *filename = new char[bufferLength];
01657   strcpy(filename, tempDir.c_str());
01658 
01659   cout << "Module:  " << mid << " = " << sn << endl;
01660 
01661   int written = tempDir.length();
01662   if(scan.getOption(Scan::FULL)) {
01663     written += snprintf(filename + written, bufferLength - written, "Histogram%d_%s", frame, sn.c_str());
01664     //                                                                    20021112143712
01665     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01666   } else {
01667     written += snprintf(filename + written, bufferLength - written, "Histogram_%s", sn.c_str());
01668     //                                                                    20021112143712
01669     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01670   }
01671 
01672   {
01673     Sct::MultiMessageDebugStream m(true,false,true);
01674     m << ucid << " is writing histogram data to " << filename;
01675   };
01676 
01677   saveHistogramToFile(scanData, filename);
01678     
01679   cout << "done.\n";
01680 
01681   delete [] filename;
01682 }
01683 
01684 void saveHistogramToFile(scan_result_ptrs histo, std::string filename) {
01685   ofstream histoout(filename.c_str(), ios::binary);
01686 
01687   //    assert(histo.header.length == sizeof(ScanHeader));
01688   histoout.write((char*)&histo.header, histo.header.length);
01689 
01690   //    assert(histo.header.pntEvents - histo.header.pntPoints == nBins * sizeof(FLOAT32));
01691   histoout.write((char*)histo.points, histo.header.pntEvents-histo.header.pntPoints);
01692 
01693   //    assert(histo.header.pntErrors - histo.header.pntEvents == nBins * sizeof(FLOAT32));
01694   histoout.write((char*)histo.nEvents, histo.header.pntErrors-histo.header.pntEvents);
01695 
01696   //    assert(histo.header.pntData - histo.header.pntErrors == nBins * sizeof(FLOAT32));
01697   histoout.write((char*)histo.nErrorEvents, histo.header.pntData-histo.header.pntErrors);
01698 
01699   //    assert(histo.header.size*2 == (nBins * 0x800 * 4));
01700 
01701   // header.size is a count in 16bit words!
01702   histoout.write((char*)histo.data, histo.header.size*2);
01703 }
01704 
01705 #ifdef USE_IS
01706 
01707 void readHistogramToIS(const Sct::UCID & ucid, const Scan &scan, const ScanEx &ex, UINT32 mid, scan_result_ptrs scanData) {
01708 //   {
01709 //     boost::mutex::scoped_lock lock(log().mutex());
01710 //     log() << "Read Histogram for " << mid << " to IS\n";
01711 //   }
01712 
01713   cout << "Writing histogram data to IS\n";
01714 
01715 //   string sn = convertToString(mid);
01716 
01717   cout << "Module:  " << mid << /* " " << sn << */ endl;
01718   {
01719     Sct::MultiMessageDebugStream m(true,false,true);
01720     m << ucid << " is writing histogram data to IS for mid " << mid;
01721   };
01722 
01723   try {
01724     SctData::ScanResultWriter::publish(scanData);
01725   } catch(Sct::IoException &e) {
01726     cout << "ScanResult publish failed:\n" << e.what() << endl;
01727     e.sendToMrs(MRS_ERROR);
01728   }
01729 }
01730 
01731 #endif
01732 
01733 int SctApi::pollHistogramming(boost::shared_ptr<ScanControl> controller, int timeout) {
01734   int returnVal = 0;
01735 
01736   bool timedout = false;
01737 
01738   time_t start_time = time(0);
01739 
01740   while(!timedout) {
01741     bool progressMade = false;
01742     bool newBin = false;
01743     if(controller->checkScanComplete(progressMade, newBin)) {
01744       // Finished, exit while
01745       break;
01746     }
01747 
01748     if(progressMade) {
01749       start_time = time(0);
01750     }
01751 
01752     if(newBin) {
01753       cout << "Controller going to next bin\n";
01754 
01755       controller->nextBin();
01756     } else {
01757       // Check text buffers (no longer a side effect of polling)
01758 #if USE_THREADS
01759       // Text buffers already checked by primThread
01760       sleep(1);
01761 #else
01762       awaitResponseAll(0);
01763 #endif
01764 
01765       if((time(0) - start_time) > timeout) {
01766         timedout = true;
01767         returnVal = -1;
01768 
01769         controller->reportTimeout();
01770         controller->reportEventErrors();
01771 
01772         break;
01773       }
01774     }
01775   }
01776 
01777 #if USE_IS
01778   if(m_isDict) {
01779     m_isDict->remove("SCTAPIServer.currentBin");
01780     m_isDict->remove("SCTAPIServer.maxBin");
01781   }
01782 #endif
01783 
01784   return returnVal;
01785 }
01786 
01787 void SctApi::doHistogramSetup(const Scan &scan, const ScanEx &extra) {
01788   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01789       ri != extra.rodInfo.end();
01790       ri++) {
01791     //    const RodScanEx &rodInfo = ri->second;
01792     const RodLabel &rod = ri->first;
01793 
01794     // Clear event memory on all slaves
01795     // 8192 words from what was 0x80008000
01796     for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
01797       if(getCrate()->slavePresent(rod.rod, slaveNumber)) {
01798         if(getCrate()->getRodRevision(rod.rod) >= 0xe) {
01799 #warning "Hard-coded address of incoming event buffer"
01800           setSlaveBlock(rod.rod, slaveNumber, 0x18000, 0x2000, 0);
01801         } else {
01802           setSlaveBlock(rod.rod, slaveNumber, 0x80008000, 0x2000, 0);
01803         }
01804       }
01805     }
01806 
01807     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01808 
01809     setupEventTrapping(scan, extra, rod, primList);
01810     startEventTrapping(scan, extra, rod, primList);
01811     setupEventDump(scan, extra, rod, primList);
01812 
01813     if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
01814       standardRegisterDump(rod.rod);
01815 
01816       sendPrimList(rod.rod, primList);
01817       awaitResponse(rod.rod, 5);
01818       primList->clear(); // .reset(new PrimListWrapper(2));
01819     }
01820 
01821     setupHistogramming(scan, extra, rod, scan.getOption(Scan::TIM), primList);
01822 
01823     // Wait for things to settle before starting histogramming
01824     sendPrimList(rod.rod, primList);
01825   }
01826   
01827   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01828       ri != extra.rodInfo.end();
01829       ri++) {
01830     const RodLabel &rod = ri->first;
01831     int responseCode = awaitResponse(rod.rod, 5);
01832     if(responseCode != 0) {
01833       cout << "Histogram setup list failed! (ROD " << rod.rod << ")\n";
01834       throw SctApiException("Histogram setup list failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01835     } else {
01836       unsigned long length;
01837       unsigned long *result = getResponse(rod.rod, length);
01838 
01839       if(result) {
01840     if(result[6] == EVENT_TRAP_SETUP && result[7] == R_EVENT_TRAP_SETUP) {
01841       // First is ETS, so decode as if all are...
01842       int numPrims = result[2];
01843       cout << numPrims << " replies from setup primitive list\n";
01844 
01845       int offset = 4;
01846       for(int prim = 0; prim<numPrims; prim++) {
01847         cout << prim << ": ";
01848         if(result[offset+2] == EVENT_TRAP_SETUP && result[offset+3] == R_EVENT_TRAP_SETUP) {
01849           cout << "ETS Error code " << result[offset+4] << endl;
01850         } else {
01851           cout << "Unexpected (not ETS) reply from setup primitive list\n";
01852         }
01853         offset += result[offset+0];
01854       }
01855     } else {
01856       cout << "Unexpected output list from histogram setup primitive list\n";
01857       ::SctApi::printOutList(result, length, true, 0, cout, 
01858                  checkDebugOption(DEBUG_PRINT_UNKNOWN), checkDebugOption(DEBUG_PRINT_RAW));
01859     }
01860     delete [] result;
01861       } else {
01862     cout << "No response to ETS\n";
01863       }
01864     }
01865   }
01866 }
01867 
01868 void ScanControlRODHisto::startHistogramming() {
01869   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01870       ri != scanEx->rodInfo.end();
01871       ri++) {
01872     const RodLabel &rod = ri->first;
01873 
01874     // Setup debug register
01875     if(scan->getOption(Scan::DEBUG)) {
01876       if(checkDebugOption(DEBUG_SCAN_AUTO_STALL)) {
01877         cout << "** Debug mode setting AUTO_STALL\n"; 
01878         scanEx->diagnosticReg |= (1<<DR_AUTO_STALL);
01879       }
01880 
01881       if(checkDebugOption(DEBUG_SCAN_STEP_MODE)) {
01882         cout << "** Debug mode setting STEP_CTRL\n"; 
01883         scanEx->diagnosticReg |= (1<<DR_STEP_CTRL);
01884       }
01885 
01886       if(checkDebugOption(DEBUG_SCAN_PAUSE_PULSE)) {
01887 #ifdef DR_PULSE_PAUSE
01888         cout << "** Debug mode setting PAUSE_PULSE\n"; 
01889         scanEx->diagnosticReg |= (1<<DR_PULSE_PAUSE);
01890 #else
01891     cout << "ERROR : Debug mode PAUSE_PAUSE no longer available\n";
01892 #endif
01893       }
01894     }
01895 
01896     if(checkDebugOption(DEBUG_SCAN_ROD_MODE_BITS)) {
01897       cout << "Setting up to use ROD mode bits\n"; 
01898 #ifdef DR_USE_ROD_MASK_LUT
01899       scanEx->diagnosticReg |= (1<<DR_USE_ROD_MASK_LUT);
01900 #else
01901       cout << "ERROR : Cannot set up to use ROD mode bits - USE_ROD_MASK_LUT no longer available!\n"; 
01902 #endif
01903     }
01904 
01905     if(scanEx->diagnosticReg != 0x0) {
01906       cout << "Writing master diag reg: 0x" << hex << scanEx->diagnosticReg << dec << endl;
01907       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01908     } else {
01909       cout << "Clearing master diag reg\n";
01910       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01911     }
01912 
01913     if(!useCCode(api, *scan)) {
01914       
01915       unsigned long SDSP_IDRAM_BASE;
01916       if(api.getRodRevision(rod) >= 0xe) {
01917         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
01918       } else {
01919         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
01920       }
01921 
01922       for(int s=0; s<numSlaves; s++) {
01923         if(ri->second.bitFieldDSP & (1<<s)) {
01924           try {
01925             unsigned long val = api.dspSingleBlockRead(rod.rod, 
01926                                                        SDSP_IDRAM_BASE + 0x10, s);
01927             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01928                  << " which should be 0x" << (0) << dec << endl;
01929 
01930             // Toggle cache on
01931             unsigned long newVal = val | (1<<19);
01932             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
01933 
01934             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
01935             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01936                  << " which should be 0x" << (1<<19) << dec << endl;
01937           } catch(VmeException &v) {
01938             Utility::decodeVme(v);
01939             cerr << "VmeException turning on slave " << s << " cache\n";
01940           }
01941         }
01942       }
01943     }
01944 
01945     cout << "Histogram starting...\n";
01946 
01947     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01948     api.startHistogramTask(*scan, *scanEx, rod, 
01949                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
01950                            primList);
01951 
01952 //     {
01953 //       boost::mutex::scoped_lock lock(log().mutex());
01954 //       log() << "Send start histogram task list\n";
01955 //     }
01956     api.sendPrimList(rod.rod, primList);
01957 
01958   }
01959 
01960   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01961       ri != scanEx->rodInfo.end();
01962       ri++) {
01963     const RodLabel &rod = ri->first;
01964     int responseCode = api.awaitResponse(rod.rod, 5);
01965     if(responseCode != 0) {
01966       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
01967       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01968     }
01969   }
01970 }
01971 
01972 void SctApi::eventTrapSetup(int slaveMask, int trapMatch, int trapMod, int trapRemain, bool tim, bool error,
01973                             boost::shared_ptr<PrimListWrapper> primList) {
01974   long *evData = new long[sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32)];
01975 
01976   EVENT_TRAP_SETUP_IN &primData = *(EVENT_TRAP_SETUP_IN*)evData;
01977 
01978 #if R_EVENT_TRAP_SETUP == 103
01979   primData.slvBits = slaveMask;
01980   primData.numberOfEvents = COLLECT_FOREVER;
01981   primData.timeoutInUsec = 0x30000;
01982 
01983   primData.extRouterSetup = 0;
01984 
01985   // This tells the setup code to change the trapRemainder
01986   //  Only matters if setting up more than one slave
01987   primData.distribute = TRAP_DISTRIB_NEITHER;
01988 
01989   primData.releaseFrames = 0;
01990   if(tim) {
01991     primData.permitBackPressure = 0;
01992   } else {
01993     primData.permitBackPressure = 1;
01994   }
01995   primData.dataMode = 0;                        // Data or Event mode
01996   if(tim) {                           // Where to pick events (dsp or router)
01997     primData.sLink = 1;
01998   } else {
01999     primData.sLink = 0;
02000   }
02001 
02002   primData.format = error?TRAP_FMT_ERROR:TRAP_FMT_NORMAL; // Slink format
02003   primData.trapStray = 1;                       // Trap stray events
02004   primData.iterLimit = 2;                       // Don't keep them long
02005 
02006   if(tim) {
02007     // Trap events from the SLINK
02008     primData.trapConfig[0] = TRAP_CFG_SLINK_EVT;
02009   } else {
02010     // Trap events from ROD triggers
02011     primData.trapConfig[0] = TRAP_CFG_ROD_EVT;
02012   }
02013   primData.trapExclusionFlag[0] = 0;            // Don't exclude anything
02014   primData.trapFunction[0] = TRAP_FXN_HISTOGRAM;
02015 
02016   primData.trapMatch[0] = trapMatch;
02017   primData.trapModulus[0] = trapMod;
02018   primData.trapRemainder[0] = trapRemain;
02019 
02020   // Trap one is idle
02021   primData.trapConfig[1] = TRAP_CFG_IDLE;
02022   primData.trapExclusionFlag[1] = 0;
02023   primData.trapFunction[1] = 0;
02024 
02025   primData.trapMatch[1] = 0; 
02026   primData.trapModulus[1] = 0;
02027   primData.trapRemainder[1] = 0;
02028 #else 
02029 #error "Event trapping not compiled (new Primitive definition)!"
02030 #endif
02031   primList->addPrimitive(RodPrimitive(sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32) + 4, 
02032                                       0, EVENT_TRAP_SETUP, R_EVENT_TRAP_SETUP, evData),
02033                          evData);
02034 }
02035 
02036 void SctApi::startEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
02037   shared_ptr<PrimListWrapper> startList(new PrimListWrapper(1));
02038 
02039   PrimBuilder::instance().startEvTrap(startList);
02040 
02041   PrimBuilder::instance().slavePrimList(primList, startList, slaveNumber, true, true);
02042 }
02043 
02044 void SctApi::stopEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
02045   shared_ptr<PrimListWrapper> stopList(new PrimListWrapper(1));
02046 
02047   PrimBuilder::instance().stopEvTrap(stopList);
02048 
02049   PrimBuilder::instance().slavePrimList(primList, stopList, slaveNumber, true, true);
02050 }
02051 
02052 ScanMonitorImpl::ScanMonitorImpl(boost::shared_ptr<ScanControl> control) : controller(control) {
02053 }
02054 
02055 ScanMonitorImpl::~ScanMonitorImpl() {
02056 }
02057 
02058 void ScanMonitorImpl::newBin(int prevTriggers, int newBin) {
02059   controller->nextBin();
02060 }
02061 
02062 void ScanMonitorImpl::finishScan() {
02063   controller->finishHistogram(true);
02064 }
02065 
02066 // If this uses sendData then memory is stored internally so isn't leaked, otherwise it is!
02067 unsigned long *ScanControlRODHisto::getHistogramChunk(RodLabel rodLabel, int slaveNumber,
02068                                                       unsigned long offset, unsigned long size) {
02069   try {
02070     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
02071 
02072     Utility::MemoryBlock chunk;
02073     chunk = scanEx->histoMap[key];
02074     if(!chunk) {
02075       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, HISTOGRAM_DATA, slaveNumber);
02076 
02077       cout << "SendData returned " << chunkPos.first << " " << chunkPos.second << endl;
02078       cout << " need offset " << offset << " length " << size << endl;
02079 
02080       if(api.mrs) {
02081         // Something about getting lots of data
02082         *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
02083                  << MRS_PARAM<float>("MWords", chunkPos.second/4e6)
02084                  << MRS_PARAM<int>("crate", rodLabel.crate)
02085                  << MRS_PARAM<int>("rod", rodLabel.rod)
02086                  << MRS_TEXT("Scan requested histogram readout") << ENDM;
02087       }
02088 
02089       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
02090                           slaveNumber, chunkPos.first, chunkPos.second/sizeof(UINT32));
02091 
02092       if(block == 0) {
02093     throw SctApiException("Read of histogram from slave failed");
02094       }
02095 
02096       chunk = Utility::MemoryBlock(chunkPos.second/sizeof(UINT32), block);
02097 
02098       scanEx->histoMap[key] = chunk;
02099     }
02100 
02101     if((offset + size*4) > (chunk.size() * 4)) {
02102       cout << "Asked for chunk +" << offset << " length " << size << " in " << chunk.size() << "words (continuing)\n";
02103     }
02104 
02105     // Offset is in bytes
02106     return chunk.address() + (offset / 4);
02107   } catch(SctApiException &e) {
02108     cout << "Caught exception in getHistogramChunk: " << e.what() << "\n\ttrying old histogram address\n";
02109     unsigned long slaveAddress;
02110 
02111     if(api.getRodRevision(rodLabel) >= 0xe) {
02112       slaveAddress = 0xa00e2000;
02113     } else {
02114       throw SctApiException("Slave histogram read not possible with old (pre-rev-E) rod");
02115     }
02116     return api.primReadSlaveDsp(rodLabel.rod, 
02117                                 slaveNumber, slaveAddress + offset, size);
02118   }
02119 }
02120 
02121 unsigned long *ScanControlRODHisto::getEventCountChunk(RodLabel rodLabel, int slaveNumber) {
02122   try {
02123     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
02124 
02125     Utility::MemoryBlock chunk = scanEx->evCountMap[key];
02126     if(!chunk) {
02127       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, BIN_DATA, slaveNumber);
02128 
02129       cout << "SendData bin returned " << chunkPos.first << " " << chunkPos.second << endl;
02130 
02131       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
02132                                                   slaveNumber, chunkPos.first, chunkPos.second);
02133       chunk = Utility::MemoryBlock(chunkPos.second, block);
02134 
02135       scanEx->evCountMap[key] = chunk;
02136     }
02137 
02138     return chunk.address();
02139   } catch(SctApiException &e) {
02140     return 0;
02141   }
02142 }
02143 
02144 
02145 ScanControlRODHisto::ScanControlRODHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControl(api), scan(aScan), scanEx(aScanEx), aborting(false) {
02146   int nBins = scan->getScanPoints1().size();
02147 
02148   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
02149 
02150   finalTrigger = trigPoints[nBins-1];
02151 
02152   finalBin = nBins - 1;
02153 
02154   UINT32 initialNTrigs = trigPoints[0];
02155 
02156   unsigned int i = 0;
02157   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs) 
02158     i++;
02159 
02160   // i is now the index of the first different point
02161   sectionStartBin = 0;
02162   sectionEndBin = i - 1;
02163   if(i==trigPoints.size()) {
02164     sectionEndTrigger = trigPoints[i-1];
02165   } else {
02166     sectionEndTrigger = trigPoints[i-1] - trigPoints[i];
02167   }
02168   cout << "Final bin = " << finalBin << " trigger = " << finalTrigger << endl;
02169 
02170   cout << "Initial sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
02171 
02172   // no rods 
02173   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02174       ri != scanEx->rodInfo.end();
02175       ri++) {
02176     const RodLabel &rodLabel = ri->first;
02177     reportedFinished[rodLabel]=false;
02178   }
02179 }
02180 
02181 void ScanControlRODHisto::initialisePolling() { 
02182   scanStart = time(0);
02183 
02184   cout << "Histogram polling started\n";
02185   // Let it get going so the bin counter gets reset
02186   sleep(1);
02187 
02188   cout << "Polling histogramming task\n";
02189   cout << "scan point count " << scan->getScanPoints1().size() << endl;
02190 
02191   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02192       ri != scanEx->rodInfo.end();
02193       ri++) {
02194     const RodLabel &rodLabel = ri->first;
02195 
02196     if(api.mrs) {
02197       const std::string m1 = (Sct::StringStreamer << "POLL_ROD_" << api.ucid());      const std::string m2 = (Sct::StringStreamer << "ROD polling started on " << api.ucid());
02198       
02199       *api.mrs << m1 << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
02200                << MRS_PARAM<int>("partition", rodLabel.partition)
02201                << MRS_PARAM<int>("crate", rodLabel.crate)
02202                << MRS_PARAM<int>("rod", rodLabel.rod)
02203                << MRS_PARAM<int>("run", scan->getRunNumber())
02204                << MRS_PARAM<int>("scan", scan->getScanNumber())
02205                << MRS_PARAM<int>("firstSlave", ri->second.firstSlave)
02206                << MRS_TEXT(m2)
02207                << ENDM;
02208     }
02209   }
02210 
02211 #if USE_IS
02212   if(api.m_isDict) {
02213     ISInfoInt binNumber(0);
02214     api.m_isDict->insert("SCTAPIServer.currentBin", binNumber);
02215 
02216     ISInfoInt maxNumber(finalBin);
02217     api.m_isDict->insert("SCTAPIServer.maxBin", maxNumber);
02218   }
02219 #endif
02220 }
02221 
02222 void ScanControlRODHisto::reportTimeout() {
02223   Sct::MultiMessageDebugStream m(true,false,true);
02224 
02225   m << "You are about to get the 'Scan aborted (histogramming stalled)' "
02226     <<"message.  Histogram polling timeout being reported in ["
02227     <<__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. ";
02228 
02229   RodLabel minROD;
02230   if(scanEx->rodInfo.size() > 0) {
02231     minROD = scanEx->rodInfo.begin()->first;
02232   }
02233 
02234   m << "Was expecting: finalBin=" << finalBin << ", finalTrigger=" << finalTrigger;
02235 
02236   // Find the ROD that stopped everything
02237   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02238       ri != scanEx->rodInfo.end();
02239       ri++) {
02240     const RodLabel &rodLabel = ri->first;
02241     cout << "   ROD (" << rodLabel.partition << ", " << rodLabel.crate << ", " << rodLabel.rod << "): ";
02242     cout << " Event " << lastEvent[rodLabel] << "    Bin " << lastBin[rodLabel] << "\n";
02243 
02244     if(lastEvent[rodLabel] < lastEvent[minROD]) {
02245       minROD = rodLabel;
02246     } else if(lastEvent[rodLabel] == lastEvent[minROD] && lastBin[rodLabel] < lastBin[minROD]) {
02247       minROD = rodLabel;
02248     }
02249   }
02250 
02251 
02252   m << ".  Problem was perhaps localised to"
02253     << " partition " << minROD.partition
02254     << " crate" << minROD.crate
02255     << " rod" << minROD.rod
02256     << " run" << scan->getRunNumber()
02257     << " scan"<< scan->getScanNumber()
02258     << " bin"<< lastBin[minROD]
02259     << " event"<< lastEvent[minROD];
02260 
02261   m.flush();
02262 
02263   if(api.mrs) {
02264     *api.mrs << "SCAN_ABORTED" << MRS_ERROR
02265              << MRS_PARAM<int>("partition", minROD.partition)
02266              << MRS_PARAM<int>("crate", minROD.crate)
02267              << MRS_PARAM<int>("rod", minROD.rod)
02268              << MRS_PARAM<int>("run", scan->getRunNumber())
02269              << MRS_PARAM<int>("scan", scan->getScanNumber())
02270              << MRS_PARAM<int>("bin", lastBin[minROD]) << MRS_PARAM<int>("event", lastEvent[minROD]) 
02271              << MRS_TEXT("Scan aborted (histogramming stalled)") << ENDM;
02272   }
02273 }
02274 
02275 void ScanControlRODHisto::nextBin() {
02276   // Fix ending variables if reached the end
02277   if(findNextSection()) {
02278     finalTrigger = sectionEndTrigger;
02279     finalBin = sectionEndBin;
02280     return;
02281   }
02282 
02283   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02284       ri != scanEx->rodInfo.end();
02285       ri++) {
02286     const RodLabel &rod = ri->first;
02287 
02288     cout << "New histogram control task...\n";
02289 
02290     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
02291     api.startHistogramTask(*scan, *scanEx, rod, 
02292                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
02293                            primList);
02294 
02295     api.sendPrimList(rod.rod, primList);
02296     int responseCode = api.awaitResponse(rod.rod, 5);
02297 
02298     if(responseCode != 0) {
02299       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
02300       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
02301     }
02302   }  
02303 }
02304 
02305 bool ScanControlRODHisto::findNextSection() {
02306   // Find next section to do
02307   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
02308 
02309   unsigned int i = sectionEndBin + 1; // StartBin + 1;
02310 
02311   if(i==trigPoints.size()) {
02312     // Nothing more to do
02313     // If we're done, the previous section was last so don't overwrite the parameters
02314     return true;
02315   }
02316 
02317   UINT32 initialNTrigs = trigPoints[i];
02318 
02319   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs)
02320     i ++; 
02321 
02322   bool done = false;
02323 
02324   sectionStartBin = 0;
02325   sectionEndBin = i - 1;
02326 
02327   if(i == trigPoints.size()) {
02328     sectionEndTrigger = trigPoints[i-1];
02329   } else {
02330     sectionEndTrigger = trigPoints[i-1] - trigPoints[i];
02331 
02332 //     sectionStartBin = i;
02333 //     sectionEndBin = trigPoints.size() - 1;
02334 //     sectionEndTrigger = scan->getVariableTrigs()[i] - completedTriggers[i];
02335   }
02336 
02337 #if 0 
02338   // The old way
02339   unsigned int i = sectionEndBin + 1;
02340   UINT32 initialNTrigs = trigPoints[i];
02341   while(i<trigPoints.size() && trigPoints[i] == initialNTrigs) 
02342     i++;
02343 
02344   sectionStartBin = sectionEndBin + 1;
02345   sectionEndBin = i - 1;
02346   sectionEndTrigger = scan->getVariableTrigs()[i-1];
02347 
02348   done = false;
02349 #endif
02350 
02351   cout << "Next sectionStartBin = " << sectionStartBin << " sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
02352 
02353   return done;
02354 }
02355 
02356 bool ScanControlRODHisto::checkScanComplete(bool &progressMade, bool &newBin) {
02357   if(aborting) {
02358     return true;
02359   }
02360 
02361   progressMade = false;
02362   newBin = false;
02363 
02364   bool result = true;
02365 
02366   int totalBin = 0;
02367 
02368   map<RodLabel, bool> rodNewBinMap;
02369 
02370   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02371       ri != scanEx->rodInfo.end();
02372       ri++) {
02373     const RodLabel &rodLabel = ri->first;
02374 
02375     bool rodNewBin = false;
02376 
02377     if(!checkScanCompleteROD(rodLabel, progressMade, rodNewBin, totalBin)) {
02378       result = false;
02379     }
02380 
02381     rodNewBinMap[rodLabel] = rodNewBin;
02382   }
02383 
02384   // Only do a "newBin" if all RODs agree
02385   newBin = true;  
02386   for(map<RodLabel, bool>::const_iterator mapIter = rodNewBinMap.begin();
02387       mapIter != rodNewBinMap.end();
02388       mapIter++) {
02389     if(mapIter->second == false) {
02390       newBin = false;
02391     } else {
02392       cout << "New bin requested by ROD (" << mapIter->first.partition << ", " << mapIter->first.crate << ", " << mapIter->first.rod << ")\n";
02393     }
02394   }
02395 
02396   if(progressMade) {
02397     int progressBin = totalBin / scanEx->rodInfo.size();
02398 
02399 #if USE_IS
02400     if(api.m_isDict) {
02401       ISInfoInt binNumber(progressBin);
02402       api.m_isDict->update("SCTAPIServer.currentBin", binNumber);
02403     }
02404 #endif
02405   }
02406 
02407   return result;
02408 }
02409 
02410 void ScanControlRODHisto::abort() {
02411   aborting = true;
02412 }
02413 
02414 #warning "32 bit version unreliable!!"
02415 unsigned int ScanControlRODHisto::getEventCounter(const RodLabel &rodLabel, int slave, bool fromMaster) {
02416   if(fromMaster) {
02417     // Use the event count copied from the slave to MDSP this is 16bit though!
02418 #if defined(HSSTAT_REG_0)
02419     unsigned long address=0;
02420     switch (slave){
02421     case 0: address=HSSTAT_REG_0; break;
02422     case 1: address=HSSTAT_REG_1; break;
02423     case 2: address=HSSTAT_REG_2; break;
02424     case 3: address=HSSTAT_REG_3; break;
02425     default: cerr << "get event counter for bad slave number : " << slave << std::endl; return 0;
02426     }
02427     unsigned long reg = api.dspSingleRead(rodLabel.rod, address, -1);
02428     //std::cout << "AJB reading histo status from MDSP address 0x" << hex << address
02429     //        << " previous code was suggesting " << 0x8000002c - (slave & 2) * 2 
02430     //      << " got " << reg << dec << endl;    
02431     unsigned currEvent = (unsigned) (reg & 0xffff);
02432 #else
02433 #warning "AJB Hard-coded memory address for checking SDSP event count"
02434     // Read out event counts formatted as:
02435     //      [SLV2][SLV3]  [SLV0][SLV1]
02436     //   where each [] is 16bits
02437     unsigned long reg = api.dspSingleRead(rodLabel.rod, 
02438                                           0x8000002c - (slave & 2) * 2, -1);
02439     unsigned int currEvent = (unsigned int) ((reg >> (16*(slave&1))) & 0xffff);
02440 #endif
02441     return currEvent;
02442   } else {
02443     // Read 32bit version from slave
02444     //  Use primitive rather than direct read of slave (which is very bad!)
02445     unsigned long reg = api.dspSingleBlockRead(rodLabel.rod, 
02446                                                0x8000002c, slave);
02447     return (unsigned int) reg;
02448   }
02449 }
02450 
02451 bool ScanControlRODHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
02452   int partition = rodLabel.partition;
02453   int crate = rodLabel.crate;
02454   int rod = rodLabel.rod;
02455 
02456   int currBin = 0;
02457   int currEvent = 0;
02458 
02459   // Read bin number from master dsp
02460 #warning "AJB does not like the look of this hard-coded memory address for the bin number - not one little bit!"
02461   // See Sct/comRegDfns_11x.h for placement of regs
02462   long reg = api.dspSingleRead(rod, 0x80000020, -1);
02463   currBin = (reg & 0xff);
02464 
02465   RodScanEx &rodInfo = scanEx->rodInfo[rodLabel];
02466 
02467   // Use the event count copied from the lowest slave with a module, this is 16bit though!
02468   currEvent = getEventCounter(rodLabel, rodInfo.firstSlave, true);
02469 
02470   if(currBin != lastBin[rodLabel]) {
02471     lastBin[rodLabel] = currBin;
02472     lastEvent[rodLabel] = currEvent;
02473     cout << "Next bin " << currBin << "+" << currEvent << " on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02474 
02475     progressMade = true;
02476   } else if(currEvent != lastEvent[rodLabel]) { 
02477     lastEvent[rodLabel] = currEvent;
02478     cout << "Next event " << currEvent << " (bin " << currBin << ") on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02479 
02480     progressMade = true;
02481   }
02482 
02483   totalBin += currBin;
02484 
02485   // End of current section
02486   if(currBin == sectionEndBin && currEvent == sectionEndTrigger) {
02487     // Probably got to the end...
02488     newBin = true;
02489 
02490     // Check all the DSPs involved
02491     for(int s=0; s<4; s++) {
02492       if(rodInfo.bitFieldDSP & (1<<s)) {
02493         int slaveEvent = getEventCounter(rodLabel, s, false);
02494         // Actually this one not finished yet
02495         if(slaveEvent != sectionEndTrigger) {
02496           cout << " Slave " << s << " completed only " << slaveEvent << "/" << sectionEndTrigger << " triggers\n";
02497           newBin = false;
02498         }
02499       }
02500     }
02501   } else if(currBin == sectionEndBin && currEvent == (sectionEndTrigger%65536)) {
02502     // Should check trigger count on slave (not 16bit?)
02503 
02504     // If progress was made we'll wait for the next iteration
02505     if(!progressMade) {
02506       // Otherwise its most likely finished properly...
02507       newBin = true;
02508 
02509       // Check all the DSPs involved
02510       for(int s=0; s<4; s++) {
02511     if(rodInfo.bitFieldDSP & (1<<s)) {
02512           int slaveEvent = getEventCounter(rodLabel, s, false);
02513       // Actually this one not finished yet
02514       if(slaveEvent != sectionEndTrigger) {
02515         cout << " Slave " << s << " completed only " << slaveEvent << "/" << sectionEndTrigger << " triggers\n";
02516         newBin = false;
02517       }
02518     }
02519       }
02520     }
02521   }
02522 
02523   // Could this be if(newBin && currBin == finalBin) ???
02524   if(((currBin == finalBin) && (currEvent == finalTrigger))
02525      || ((currBin == finalBin) && (currEvent == (finalTrigger%65536)) && !progressMade)) {
02526 
02527     // Fix lastEvent in the case it's incorrect due to 16bitness
02528     lastEvent[rodLabel] = finalTrigger;
02529 
02530     if(api.mrs && !reportedFinished[rodLabel]) {
02531       reportedFinished[rodLabel]=true;
02532       *api.mrs << "HISTO_SUCCESS" << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
02533                << MRS_PARAM<int>("partition", rodLabel.partition)
02534                << MRS_PARAM<int>("crate", rodLabel.crate)
02535                << MRS_PARAM<int>("rod", rodLabel.rod)
02536                << MRS_TEXT("Histogramming successfully complete")
02537                << ENDM;
02538     }
02539 
02540     cout << "Histogramming completed successfully on rod " << rod << "\n";
02541 
02542     return true;
02543   }
02544 
02545   return false;
02546 }
02547 
02548 void ScanControlTIMHisto::finishHistogram(bool success) { 
02549   printVetoStatus();
02550   this->ScanControlRODHisto::finishHistogram(success);  
02551 }
02552 
02553 void ScanControlAsyncHisto::finishHistogram(bool success) { 
02554   printVetoStatus();
02555   this->ScanControlRODHisto::finishHistogram(success);  
02556 }
02557 
02558 void ScanControl::printVetoStatus(){
02559   // Total count of clocks spent with FFTVeto on
02560   long long loCount = api.timReadRegister(0x74);
02561   long long hiCount = api.timReadRegister(0x76);
02562   long long extCount = api.timReadRegister(0x78);
02563   long long count = loCount + (hiCount << 16) + ((extCount << 16) << 16);
02564   
02565   // Number Triggers Veto'd
02566   long loVeto = api.timReadRegister(0x7c);
02567   long hiVeto = api.timReadRegister(0x7e);
02568   long veto = loVeto + (hiVeto << 16);
02569   
02570   // Count of number of times the veto is asserted.
02571   long loVetos = api.timReadRegister(0x84);
02572   long hiVetos = api.timReadRegister(0x86);
02573   long vetos = loVetos + (hiVetos << 16);
02574 
02575   std::ostringstream vetostatus;
02576   vetostatus << "TIM FFTV Software disable:" << (bool)(api.timReadRegister(0x9c) & 0x100);
02577   vetostatus << "; Hardware disable:" << (bool)(api.timReadRegister(0x5a) & 0x8000);
02578   vetostatus << "; Veto on:" << (bool)(api.timReadRegister(0x5a) & 0x4000) << std::endl;
02579   
02580   std::ostringstream oss; 
02581   oss << std::hex << count << std::dec;
02582   
02583   std::cout << vetostatus.str();
02584   printf("TIM FFTV: Clocks spent vetoed %lld  Vetoed triggers %ld  Veto applications %ld\n", count, veto, vetos);
02585   
02586   if (api.mrs) {
02587     *api.mrs << MRS_INFORMATION << MRS_QUALIF("SCTAPI") << "TIM_FFTV_STATUS"
02588          << MRS_TEXT("TIM module fixed-frequency veto status")
02589          << MRS_PARAM<const char*>("Number of clocks with veto applied",oss.str().c_str())
02590          << MRS_PARAM<long>("Number of triggers vetoed",veto)
02591          << MRS_PARAM<long>("Number of times veto applied",vetos)
02592          << MRS_PARAM<const char*>("Status",vetostatus.str().c_str())
02593          << ENDM;
02594   }
02595 } 
02596 
02597 void ScanControlRODHisto::finishHistogram(bool success) { 
02598   time_t scanEnd = time(0);
02599 
02600 #if USE_CONST_SCAN
02601   scanEx->setEndTime(second_clock::universal_time());
02602 #else
02603   scan->setEndTime(second_clock::universal_time());
02604 #endif
02605 
02606   std::cout << api.ucid() << " finished histogramming at TIME " << second_clock::universal_time() << std::endl;
02607 
02608   if(!useCCode(api, *scan)) {
02609     for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02610         ri != scanEx->rodInfo.end();
02611         ri++) {
02612       const RodLabel &rod = ri->first;
02613       const RodScanEx &rodInfo = ri->second;
02614 
02615       unsigned long SDSP_IDRAM_BASE;
02616       if(api.getRodRevision(rod) >= 0xe) {
02617         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02618       } else {
02619         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02620       }
02621 
02622       for(int s=0; s<numSlaves; s++) {
02623         if(rodInfo.bitFieldDSP & (1<<s)) {
02624           try {
02625 #warning "Hard coded reads of diagnostic register"
02626             unsigned long val = api.dspSingleBlockRead(rod.rod, 
02627                                                        SDSP_IDRAM_BASE + 0x10, s);
02628             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02629                  << " which should be 0x" << (1<<19) << dec << endl;
02630 
02631             // Flush cache
02632             unsigned long newVal = val | 1<<17;
02633             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02634             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02635             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02636                  << " which should be 0x" << (1<<17) << dec << endl;
02637 
02638             // Turn off flush and cache
02639             newVal = val | 1<<19;
02640             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02641             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02642             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02643                  << " which should be 0x" << (0) << dec << endl;
02644           } catch(VmeException &v) {
02645             Utility::decodeVme(v);
02646             cerr << "VmeException turning off slave " << s << " cache\n";
02647           }
02648         }
02649       }
02650     }
02651   }
02652 
02653 #if USE_CONST_SCAN
02654   setModuleScanCacheToLastPointInScan(api, scan, scanEx);
02655 #else
02656   setModuleScanCacheToLastPointInScan(api, scan);
02657 #endif
02658   
02659   std::cout << api.ucid() << " Done setModuleScanCacheToLastPointInScan at TIME " << second_clock::universal_time() << std::endl;
02660 
02661   // Read out if successful (even in debug mode!)
02662   //  but don't readout in debug mode if polling failed
02663   if(!scan->getOption(Scan::DEBUG) || success == true) {
02664     if(api.mrs) {
02665       *api.mrs << "SCAN_FINISHED" << MRS_INFORMATION 
02666                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02667                << MRS_TEXT("Scan finished") 
02668                << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02669                << MRS_PARAM<int>("ScanType1", scan->getScanVariable1())
02670                << MRS_PARAM<int>("ScanType2", scan->getScanVariable2())
02671                << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02672                << ENDM;
02673     }
02674 
02675     cout << api.ucid() << " Histogramming complete, " << (scanEnd - scanStart) << " seconds, tidying up...\n";
02676 //     {
02677 //       boost::mutex::scoped_lock lock(log().mutex());
02678 //       log() << "Histogramming complete, " << (scanEnd - scanStart) << " seconds\n";
02679 //     }
02680 
02681     cout << api.ucid() << " Starting to read histograms at TIME " << second_clock::universal_time() << std::endl;
02682 
02683     readHistograms();
02684 
02685     cout << api.ucid() << " Histograms read finished at TIME " << second_clock::universal_time() << std::endl;
02686   } else {
02687     if(!scan->getOption(Scan::DEBUG)) {
02688       cout << "Histogram polling failed\n";
02689 
02690       if(api.mrs) {
02691         *api.mrs << "SCAN_FAILED" << MRS_INFORMATION 
02692                  << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02693                  << MRS_TEXT("Scan polling failed") 
02694                  << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02695                  << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02696                  << ENDM;
02697       }
02698     }
02699   }
02700 
02701   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02702     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02703 
02704     api.print_calib(zeroRod.rod);
02705   }
02706   
02707   if(!scan->getOption(Scan::DEBUG)) {
02708     api.stopHistogramming(*scanEx);
02709 
02710     // Only restore module config if not debug mode
02711     postScanModuleSetup();
02712   } else {
02713     if(api.mrs) {
02714       *api.mrs << "SCAN_DEBUG" << MRS_INFORMATION 
02715                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02716                << MRS_TEXT("Scan done in debug mode, probably best to be at the command line to sort it out!") 
02717                << ENDM;
02718     }
02719 
02720     cout << "** In debug mode, you're responsible for terminating histogram and for readout\n";
02721   }
02722 
02723   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02724     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02725 
02726     api.print_calib(zeroRod.rod);
02727   }
02728 
02729   // This should now have been updated with the modules in the scan
02730   std::cout << scan->print();
02731   
02732 #if USE_IS
02733   if(api.m_isDict) 
02734     api.m_isDict->remove(api.idiosyncrasy().infoServiceNameOfScanStatusObject());
02735 #endif
02736 
02737   if(api.mrs)
02738     *api.mrs << "SCAN_COMPLETE" << MRS_INFORMATION << MRS_QUALIF("SctApi") << MRS_TEXT("Scan has completed") << ENDM;
02739 }
02740 
02741 void ScanControlRODHisto::postScanModuleSetup() {
02742   api.setErrorMasks();
02743 }
02744 
02745 bool ScanControlRODHisto::checkDebugOption(int opt) {
02746   return Debug::getInstance()->checkDebugOption((DebugOptions)opt);
02747 }
02748 
02749 void ScanControlRODHisto::reportEventErrors() {
02750   api.reportEventErrors();
02751 }
02752 
02753 unsigned int ScanControlRODHisto::getProcTime(const RodLabel rlabel, int dsp) {
02754   if(dsp == -1) {
02755     throw SctApiException("Can't getProcTime on MDSP");
02756   } else {
02757     int procTime;
02758 
02759     unsigned long SDSP_IDRAM_BASE;
02760     if(api.getRodRevision(rlabel) >= 0xe) {
02761       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02762     } else {
02763       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02764     }
02765 
02766     unsigned long length;
02767 
02768 #warning "Hard-coded address, sdsp histogram status block"
02769     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02770                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02771 
02772     if(regs) {
02773       long reg;
02774 
02775       // H stat reg 0
02776       reg = regs[6];
02777       procTime = ((reg >> 16) & 0xffff);
02778     } else {
02779       throw SctApiException("Failed to read getProcTime from DSP");
02780     }
02781 
02782     return procTime;
02783   }
02784 }
02785 
02786 ScanControlRODHisto::TrapBuffers ScanControlRODHisto::getTrapBuffers(const RodLabel rlabel, int dsp) {
02787   if(dsp == -1) {
02788     throw SctApiException("Invaled dsp passed to getTrapBuffers");
02789   } else {
02790     int ihead, itail, xhead, xtail;
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 #warning "Hard coded address of sdsp trap block"
02801     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02802                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02803 
02804     if(regs) {
02805       long reg;
02806 
02807       // Trap stat 1
02808       reg = regs[1];
02809       itail = ((reg & 0xff0000) >> 16);
02810       xtail = ((reg & 0xff000000) >> 24);
02811 
02812       // Trap stat 1
02813       reg = regs[2];
02814       ihead = ((reg & 0xff0000) >> 16);
02815       xhead = ((reg & 0xff000000) >> 24);
02816     } else {
02817       throw SctApiException("Failed to read DSP for getTrapBuffers");
02818     }
02819 
02820     return make_pair(make_pair(ihead, itail), make_pair(xhead, xtail));
02821   }
02822 }
02823 
02824 void ScanControlRODHisto::dumpHistoStatus(const RodLabel rlabel, int dsp) {
02825   if(dsp == -1) {
02826     const unsigned long MDSP_IDRAM_BASE = 0x80000000;
02827 
02828     // Histogram command stat 0
02829 #ifndef HCMD_STAT_REG_0 
02830 #warning "Reading hard-coded HCMD_STAT_REG_0"
02831     long reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x20, -1);
02832 #else
02833     long reg = api.dspSingleRead(0, HCMD_STAT_REG_0, -1);
02834 #endif
02835     cout << "Bin: " << (reg & 0xff) 
02836          << " Cal: " << ((reg & 0xff00) >> 8) 
02837          << " Errs: " << ((reg & 0xffff0000) >> 16) << endl;
02838 
02839     // Histogram command stat 1
02840 #ifndef HCMD_STAT_REG_1 
02841 #warning "Reading hard-coded HCMD_STAT_REG_1"
02842     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x24, -1);
02843 #else
02844     reg = api.dspSingleRead(0, HCMD_STAT_REG_1, -1);
02845 #endif
02846     cout << "avg. trans " << (reg & 0xff)
02847          << " avg. len " << ((reg & 0xff00) >> 8)
02848          << " avg. proc. " << ((reg & 0xffff0000) >> 16) << endl;
02849 
02850     // Histogram status 1
02851 #ifndef HSSTAT_REG_1 
02852 #warning "Reading hard-coded HSSTAT_REG_1"
02853     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x2c, -1);
02854 #else
02855     reg = api.dspSingleRead(0, HSSTAT_REG_1, -1);
02856 #endif
02857     cout << "Slave 0: " << (reg & 0xffff)
02858          << " Slave 1: " << ((reg & 0xffff0000) >> 16) << endl;
02859 
02860     // Histogram status 0
02861 #ifndef HSSTAT_REG_0 
02862 #warning "Reading hard-coded HSSTAT_REG_0"
02863     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x28, -1);
02864 #else
02865     reg = api.dspSingleRead(0, HSSTAT_REG_0, -1);
02866 #endif
02867     cout << "Slave 2: " << (reg & 0xffff)
02868          << " Slave 3: " << ((reg & 0xffff0000) >> 16) << endl;
02869   } else {
02870     unsigned long SDSP_IDRAM_BASE;
02871     if(api.getRodRevision(rlabel) >= 0xe) {
02872       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02873     } else {
02874       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02875     }
02876 
02877     unsigned long length;
02878 #warning "Hard coded block of trap status registers"
02879     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02880                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02881 
02882     if(regs) {
02883       long reg;
02884 
02885       cout << "TrapStatus: \n";
02886 
02887 
02888       // Trap stat 0
02889       reg = regs[1];
02890       int words = ((reg &0xffff) >> 0);
02891       int itail = ((reg & 0xff0000) >> 16);
02892       int xtail = ((reg & 0xff000000) >> 24);
02893 
02894       cout << "Event word count: " << words;
02895       cout << " IFrame tail: " << itail;
02896       cout << " XFrame tail: " << xtail << endl;
02897 
02898       // Trap stat 1
02899       reg = regs[2];
02900       int ihead = ((reg & 0xff0000) >> 16);
02901       int xhead = ((reg & 0xff000000) >> 24);
02902       cout << " IFrame head: " << ihead;
02903       cout << " XFrame head: " << xhead << endl;
02904 
02905       // Trap cmd stat
02906       reg = regs[17];
02907       cout << "Trap Command/Status: " 
02908            << ((reg & 0x1)?"Trailer ":"")            // TCSR_TRAILER
02909            << ((reg & 0x2)?"Transmit ":"")
02910            << ((reg & 0x4)?"Header ":"")
02911            << ((reg & 0x4)?"ISR active ":"");
02912       cout << ((reg & 0x10)?"\"Data Error\" ":"")
02913            << ((reg & 0x20)?"\"Header Error\" ":"")
02914            << ((reg & 0x40)?"\"Trailer Error\" ":"")
02915            << ((reg & 0x80)?"\"Link Error\" ":"");
02916       cout << ((reg & 0x100)?"\"Error\" ":"")
02917            << ((reg & 0x200)?"\"Overflow(old)\" ":"")
02918            << ((reg & 0x800)?"\"ISR pending\" ":"");
02919       cout << ((reg & 0x4000)?"\"Overflow error\" ":"")
02920            << ((reg & 0x8000)?"\"Overflow\" ":"");
02921       cout << endl;
02922 
02923       int errCount = ((reg >> 16) & 0xff);
02924       cout << "\"Error count\": " << errCount << endl;
02925       int evCount = ((reg >> 24) & 0xff);
02926       cout << "\"Event count\": " << evCount << endl;
02927 
02928       // Hcmd stat reg 0
02929       reg = regs[4];
02930       int currentBin = (reg & 0xff);
02931       cout << "Bin: " << currentBin
02932            << " Cal: " << ((reg & 0x1f00) >> 8) 
02933            << ((reg & 0x800)?" Cal enabled":"")
02934            << ((reg & 0x1000)?" New bin":"")
02935            << ((reg & 0x20000)?" New cal":"") << endl;
02936 
02937       // Hcmd stat reg 1
02938       reg = regs[5];
02939       int numEvents = reg;
02940       cout << "Num events: " << numEvents << endl;
02941 
02942       // H stat reg 0
02943       reg = regs[6];
02944       cout << "Histogram status: 0x" << hex << (reg & 0xffff) << dec << " " << ((reg & 0x1)?"Ready ":"")
02945            << ((reg & 0x2)?"Expecting ":"")
02946            << ((reg & 0x4)?"Processing ":"")
02947            << ((reg & 0x8)?"Done ":"") << endl;
02948 
02949       int procTime = ((reg >> 16) & 0xffff);
02950       cout << "Bin err: " << ((reg >> 8) & 0xff) 
02951            << " proc time: " << ((reg >> 16) & 0xffff) << endl;
02952 
02953       // H stat reg 1
02954       reg = regs[7];
02955       int evRecvd = reg;
02956       cout << "Events recvd: " << evRecvd << endl;
02957 
02958       ofstream statusOut("TIMStatus.txt", ios_base::out | ios_base::app);
02959       statusOut << currentBin << "\t" 
02960                 << ihead  << "\t" << itail << "\t" 
02961                 << xhead << "\t" << xtail << "\t"
02962                 << errCount << "\t" << evCount << "\t" 
02963                 << evRecvd << "\t" << words << "\t" << procTime << endl;
02964     }
02965   }
02966 }
02967 
02968 ScanControlTIMHisto::ScanControlTIMHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControlRODHisto(api, aScan, aScanEx), binCount(0) {
02969 }
02970 
02971 void ScanControlTIMHisto::startHistogramming() {
02972   // Set BCID offset to 3
02973   api.timWriteRegister(0x14, 0x3000);
02974 
02975   // reset TIM FFT veto counters
02976   for (unsigned reg=0x74; reg<=0x86; reg+=2){
02977     api.timWriteRegister(reg,0x0);
02978   }
02979 
02980   shared_ptr<PrimListWrapper> preTimList(new PrimListWrapper(4));
02981   PrimBuilder::instance().rodMode(preTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1); 
02982 
02983   PrimBuilder::instance().writeRegister(preTimList, RTR_CMND_STAT, 7, 1, 1);   // Mask LDown#
02984 
02985   for(int f=0; f<8; f++) {
02986 //     //    PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0xaaaa);   // Decrement L1 for check
02987 //     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x5555);   // Increment L1 for check
02988     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x0);   // Clear L1 inc
02989   }
02990 
02991    //for(int ch=0; ch<48; ch++) {
02992    //  PrimBuilder::instance().writeRegister(preTimList, Utility::EfbErrorMask(0, ch), 5, 1, 1);  // Mask L1ID check
02993    //  PrimBuilder::instance().writeRegister(preTimList, Utility::EfbErrorMask(1, ch), 5, 1, 1);  // Mask L1ID check
02994    //}
02995 
02996   cout << "Sending pre TIM setup list\n";
02997   api.synchSendPrimListAll(preTimList);
02998   cout << " done sending pre TIM setup list\n";
02999 
03000   hex(cout);
03001   cout << "0x" << RTR_CMND_STAT << ": 0x" << api.readRODRegister(0, RTR_CMND_STAT) << endl;
03002   cout << "0x" << Utility::EfbErrorMask(0, 0) << ": 0x" << api.readRODRegister(0, Utility::EfbErrorMask(0, 0)) << endl;
03003   cout << "0x" << Utility::EfbErrorMask(1, 0) << ": 0x" << api.readRODRegister(0, Utility::EfbErrorMask(1, 0)) << endl;
03004   cout << "0x" << DM_DFLT_LUT(0) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(0)) << endl;
03005   cout << "0x" << DM_DFLT_LUT(1) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(1)) << endl;
03006   dec(cout);
03007 
03008   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03009     // This is added to by dumpHistoStatus
03010     ofstream statusOut("TIMStatus.txt");
03011     statusOut << "bin\tihead\titail\txhead\txtail\terrCnt\tevCount\tevRecvd\twords\tprocTime\n";
03012   }
03013 }
03014 
03015 void ScanControlTIMHisto::nextBin() {
03016   cout << "TIM histo, next bin\n";
03017 
03018   unsigned scanvariable1 = scan->getScanVariable1();
03019   if (scanvariable1!=0){
03020     double value = scan->getScanPoints1()[binCount];
03021     
03022     if (ConfigUtility::isModuleRegister(scanvariable1)){
03023       std::list<BankType> banks;
03024       banks.push_back(SCTAPI_BANK_SCAN);
03025       api.modifyABCDVarROD(scanvariable1, value, banks);
03026     } else if (ConfigUtility::isTimRegister(scanvariable1) ) {
03027       api.modifyTIMParam(scanvariable1, (int)(value+0.5));
03028     } else if (ConfigUtility::isBocRegister(scanvariable1) ){
03029       api.modifyBOCParam(scanvariable1, (int)(value+0.5));
03030     } else if (ConfigUtility::variableType(scanvariable1)==ConfigUtility::TRIGGER_VAR) {
03031       ; // done later
03032     } else {
03033       if (api.mrs) {
03034     *api.mrs << "BAD_SCAN_VARIABLE" << MRS_TEXT("Unknown scan variable in TIM scan")
03035          << MRS_PARAM<int>("Variable number",scanvariable1) << MRS_WARNING << ENDM;
03036       } else{
03037     std::cout << "Warning - bad scan variable : " << scanvariable1 
03038           << " type " << ConfigUtility::variableType(scanvariable1) << std::endl;
03039       }
03040     }
03041   }
03042 
03043   // AJB add this?
03044   //if (!ConfigUtility::isBOCRegister(scan->getScanVariable1())) 
03045   api.sendAllABCDModules(SCTAPI_BANK_SCAN);
03046   
03047   // SET_TRIGGER (ie tell histograms about next bin)
03048   shared_ptr<PrimListWrapper> setTriggerList(new PrimListWrapper(4));
03049   PrimBuilder::instance().setTrigger(setTriggerList, binCount, Utility::translateBank(SCTAPI_BANK_SCAN));
03050 
03051   shared_ptr<PrimListWrapper> binTimList(new PrimListWrapper(4));
03052 
03053   // Send to all slaves
03054   for(int s=0; s<4; s++) {
03055     PrimBuilder::instance().slavePrimList(binTimList, setTriggerList, s, 1, 0);
03056   }
03057 
03058   PrimBuilder::instance().rodMode(binTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1);
03059   PrimBuilder::instance().writeRegister(binTimList, RTR_CMND_STAT, 7, 1, 1);   // Mask LDown#
03060 
03061   cout << "Sending TIM setup list\n";
03062   api.synchSendPrimListAll(binTimList);
03063   cout << " done sending TIM setup list\n";
03064 
03065   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03066     cout << "******************* Pre triggers status ********************\n";
03067     dumpHistoStatus(RodLabel(), 0);
03068   }
03069 
03070   cout << "Sending soft/bc resets to crate: " << api.ucid() << endl;
03071   api.timSoftReset();
03072   api.timBCReset();
03073 
03074   Scan::TrigPoints trigs = scan->getVariableTrigs();
03075 
03076   cout << "Want " << trigs[binCount] << " triggers to crate: " << api.ucid() << endl;
03077 
03078   const Trigger& trig1 = *scan->getTrigger1();
03079   
03080   if(1) {
03081     switch(scan->getOption(Scan::TIM)) {
03082     case 1:
03083       // Just send lots of triggers, relies on user to set up frequency/nth appropriately
03084       {
03085     api.sendTriggers(&trig1, trigs[binCount], binCount);
03086       }
03087       break;
03088     case 2:
03089 #warning "Assumes ROD 0!!!"
03090       // Send one trigger at a time, then wait maximum of 1 second for trap buffers to equalize
03091       for(unsigned int i=0; i<trigs[binCount]; i++) {
03092     api.timL1A();
03093     
03094     TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03095     
03096     if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03097       sleep(1);
03098       }
03099       break;
03100     case 3:
03101 #warning "Assumes ROD 0!!!"
03102       // Send in bursts of triggers, wait for them to finish
03103       // Designed to be run at 100kHz
03104       {
03105     unsigned int sentTriggers = 0;
03106     const unsigned int trigsPerBurst = 20;
03107     
03108     while(sentTriggers < trigs[binCount]) {
03109       if(sentTriggers % 1000 < trigsPerBurst) {
03110         cout << "Done " << sentTriggers << " triggers\n";
03111         if(checkDebugOption(DEBUG_TIM_SCAN_STATUS))
03112           dumpHistoStatus(RodLabel(), 0);
03113       }
03114       int ntrigs = min(trigs[binCount]-sentTriggers, trigsPerBurst);
03115       api.sendTimBurst(ntrigs,false);
03116       sentTriggers += ntrigs;
03117       
03118       // Have they been processed yet?
03119       TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03120       
03121       TrapBuffers oldtb;
03122       if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03123         do {
03124           oldtb = tb;
03125           usleep(trigsPerBurst * 10);  // 7 * 10us at 100kHz 
03126           tb = getTrapBuffers(RodLabel(), 0);
03127           
03128           if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
03129           if(tb == oldtb) break;
03130         } while(1); 
03131     }
03132       }
03133       break;
03134     case 4:
03135 #warning "Assumes ROD 0!!!"
03136       // Adjust frequency depending on how long the previous set of triggers 
03137       //  takes to histogram, first 1 then 10 then the rest.
03138       {
03139     unsigned int sentTriggers = 0;
03140     
03141     api.timL1A();
03142     sentTriggers ++;
03143     
03144     //   // Set 100kHz triggers
03145     //   api.timSetFrequency(100, 0);
03146     
03147     unsigned int procTime = getProcTime(RodLabel(), 0);
03148     double timFrequency = 0.25 * 1e6/procTime;
03149     // Don't go faster than 6kHz
03150     api.timSetFrequency(min(6.0, timFrequency/1000), 0);
03151     
03152     cout << "*** Proc Time for 1 trigger was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
03153     
03154     procTime = getProcTime(RodLabel(), 0);
03155     timFrequency = 0.25 * 1e6/procTime;
03156     api.timSetFrequency(min(6.0, timFrequency/1000), 0);
03157     
03158     cout << "*** Proc Time after 10 trigs was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
03159     
03160     if(trigs[binCount] > sentTriggers)
03161       api.sendTimBurst(trigs[binCount]-sentTriggers,false);
03162     
03163     if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03164       cout << "******************* Post triggers status ********************\n";
03165       dumpHistoStatus(RodLabel(), 0);
03166     }
03167     
03168     TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
03169     
03170     TrapBuffers oldtb;
03171     if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
03172       do {
03173         oldtb = tb;
03174         sleep(1);
03175         tb = getTrapBuffers(RodLabel(), 0);
03176         
03177         if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
03178         if(tb == oldtb) break;
03179       } while(1); 
03180     break;
03181       }
03182     default:
03183       {
03184     std::cout << "ERROR - unknown TIM option : " 
03185           << (scan->getOption(Scan::TIM)) << std::endl;
03186     break;
03187       }
03188     } // End switch on TIM histogramming types
03189   }
03190   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03191     cout << "******************* Post triggers status 2 ******************\n";
03192     dumpHistoStatus(RodLabel(), 0);
03193   }
03194 
03195   //  TTrigger soft;
03196   //soft.softL1A(30);
03197 
03198   //  api.timL1A();
03199   binCount ++;
03200 }
03201 
03202 // TIM histos don't run Histo Control so event counters not mirrored to master
03203 // A sort of dummy function at the moment...
03204 bool ScanControlTIMHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
03205 
03206   cout << "Checking TIM scan complete\n";
03207 
03208   progressMade = true;
03209 
03210   // If the triggers are sent synchronously in newBin then they must be done...
03211   newBin = true;
03212 
03213   totalBin += binCount-1;
03214 
03215   //  cout << "Are we at the end: " << (binCount-1) << " " << finalBin << endl;
03216 
03217   if((binCount-1 >= finalBin)) {
03218     return true;
03219   }
03220 
03221   return false;
03222 }
03223 
03224 // bool ScanControlTIMHisto::checkScanComplete(bool &progressMade) {
03225 //   return false;
03226 // }
03227 
03228 ScanControlAsyncHisto::ScanControlAsyncHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControlRODHisto(api, aScan, aScanEx), binCount(0) {
03229 }
03230 
03231 void ScanControlAsyncHisto::startHistogramming() {
03232 #warning "Should we check we're in physics mode?"
03233   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03234     // This is added to by dumpHistoStatus
03235     ofstream statusOut("TIMStatus.txt");
03236     statusOut << "bin\tihead\titail\txhead\txtail\terrCnt\tevCount\tevRecvd\twords\tprocTime\n";
03237   }
03238 }
03239 
03240 void ScanControlAsyncHisto::nextBin() {
03241   cout << "Asynchronous histo, next bin\n";
03242 
03243   if (scan->getScanVariable1()!=0){
03244     std::list<BankType> banks;
03245     banks.push_back(SCTAPI_BANK_SCAN);
03246     
03247     api.modifyABCDVarROD(scan->getScanVariable1(), scan->getScanPoints1()[binCount], banks);
03248   }
03249 
03250   if(0) {
03251     // AJB add this?
03252     //if (!ConfigUtility::isBOCRegister(scan->getScanVariable1())) 
03253     api.sendAllABCDModules(SCTAPI_BANK_SCAN);
03254   }
03255 
03256   // SET_TRIGGER (ie tell histograms about next bin)
03257   shared_ptr<PrimListWrapper> setTriggerList(new PrimListWrapper(4));
03258   PrimBuilder::instance().setTrigger(setTriggerList, binCount, Utility::translateBank(SCTAPI_BANK_SCAN));
03259 
03260   shared_ptr<PrimListWrapper> binTimList(new PrimListWrapper(4));
03261 
03262   // Send to all slaves
03263   for(int s=0; s<4; s++) {
03264     PrimBuilder::instance().slavePrimList(binTimList, setTriggerList, s, 1, 0);
03265   }
03266 
03267   // Do this if configuring modules, otherwise, we're already in physics mode
03268 //   PrimBuilder::instance().rodMode(binTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1);
03269 //   PrimBuilder::instance().writeRegister(binTimList, RTR_CMND_STAT, 7, 1, 1);   // Mask LDown#
03270 
03271   cout << "Sending async TIM set trigger list\n";
03272   api.synchSendPrimListAll(binTimList);
03273   cout << " done sending async TIM set trigger list\n";
03274 
03275   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
03276     cout << "******************* Next bin triggers status ********************\n";
03277     dumpHistoStatus(RodLabel(), 0);
03278   }
03279 
03280 //   cout << "Sending soft/bc resets to crate: " << api.ucid() << endl;
03281 //   api.timSoftReset();
03282 //   api.timBCReset();
03283 
03284   binCount ++;
03285 }
03286 
03287 }

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