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

Generated on Fri Dec 16 19:38:19 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5