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

SctApiHisto.cxx

00001 
00009 #include "SctApi.h"
00010 #include "SctApiConsts.h"
00011 #include "SctApiDebug.h"
00012 #include "SctApiHisto.h"
00013 #include "crate.h"
00014 #include "primListWrapper.h"
00015 #include "PrimBuilder.h"
00016 #include "ConfigurationUtility.h"
00017 
00018 #include "RodCrate/RodModule.h"
00019 
00020 #include "CommonWithDsp/primParams.h"
00021 #include "CommonWithDsp/registerIndices.h"
00022 
00023 #include "ABCD/ABCDscans.h"
00024 #include "ABCD/ABCDchip.h"
00025 
00026 #include "ScanResultWriter/scan.h"
00027 #include "utility.h"
00028 
00029 #include "VmeDecode.h"
00030 
00031 #ifdef USE_IS
00032 #include "Sct/IoExceptions.h"
00033 #include "ScanResultWriter/ScanResultWriter.h"
00034 #endif
00035 #include "Sct/SctNames.h"
00036 
00037 #include "Scan.h"
00038 #include "Trigger.h"
00039 #include "SctApiException.h"
00040 
00041 #include <boost/date_time/posix_time/posix_time.hpp>
00042 #include <boost/lexical_cast.hpp>
00043 #include <boost/timer.hpp>
00044 
00045 #include <algorithm>
00046 
00047 #include "Sct/MultiMessageDebugStream.h"
00048 #include "Idiosyncrasy.h"
00049 
00050 using namespace std;
00051 using namespace Sct;
00052 using namespace SctPixelRod;
00053 using namespace boost::posix_time;
00054 using boost::shared_ptr;
00055 
00056 namespace SctApi {
00057 void SctApi::doScan(boost::shared_ptr<Scan> scan) {
00058   boost::timer timer;
00059   {
00060     boost::mutex::scoped_lock lock(log().mutex());
00061     log() << "doScan - timer started\n";
00062   }
00063 
00064   scan->setStartTime(second_clock::universal_time());
00065   
00066   // Set up parameters
00067   boost::shared_ptr<ScanEx> extra(new ScanEx);
00068   extra->diagnosticReg = 0;
00069 
00070   extra->trimScan = 0;
00071   if(scan->getScanVariable1() == ST_TRIM) {
00072     // We need to download the trim configuration
00073     extra->trimScan = 1;
00074   }
00075 
00076   cout << "Do scan " << scanNumber << ":\n";
00077   scan->setRunNumber(runNumber);
00078   scan->setScanNumber(scanNumber);
00079 
00080   // Increment the scan number before doing anything else
00081   if(scan->getOption(Scan::FULL)) {
00082     // A full scan is three consecutive histograms
00083     scanNumber += 3;
00084   } else {
00085     scanNumber += 1;
00086   }
00087 
00088   if(mrs) {
00089     *mrs << "SCAN_REQUESTED" << MRS_INFORMATION
00090          << MRS_PARAM<int>("run", runNumber) << MRS_PARAM<int>("scan", scan->getScanNumber()) << MRS_TEXT("Scan requested") << ENDM;
00091   }
00092   std::cout << "about to print scan " << std::endl;
00093   scan->print();
00094   std::cout << "finished printing scan " << std::endl;
00095 
00096   // Do checks on scan
00097   if(scan->getScanPoints2().size() != 0 && scan->getScanPoints2().size() != scan->getScanPoints1().size()) {
00098     cout << "Can't have two different sized scan points lists!\n";
00099     if(mrs) {
00100       *mrs << "SCAN_MISMATCH" << MRS_ERROR 
00101            << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00102            << MRS_TEXT("doScan supplied with two different sized scan points lists!")
00103            << ENDM;
00104     }
00105     throw SctApiException("Invalid scan. Scan points mismatch");
00106   }
00107 
00108   if(!checkModuleListsForScan()) {
00109     throw SctApiException("Invalid scan. Module lists check failed");
00110   }
00111 
00112   std::cout << "setting up scan masks" << std::endl;
00113   setupScanMasks(*extra, scan->getOption(Scan::DISTSLAVE), scan->getScanPoints2().size() != 0);
00114    std::cout << "Done" << std::endl;
00115 
00116   RodLabel zeroRod = extra->rodInfo.begin()->first;
00117 
00118   // Tell the scan which modules are in which groups
00119   for(unsigned int i = 0;
00120       i<extra->groupLists.size();
00121       i++) {
00122     scan->setModuleList(i, extra->groupLists[i]);
00123   }
00124   scan->setNGroups(extra->groupLists.size());
00125 
00126   // Report module masks
00127   if(checkDebugOption(DEBUG_DIAG)) {
00128     RodScanEx &rodInfo = extra->rodInfo.find(zeroRod)->second;
00129     cout << hex << "Channels in use: 0x" << rodInfo.channels.mask0 << " 0x" << rodInfo.channels.mask1 << dec << endl;
00130 
00131     for(int i=0; i<numSlaves * 2; i++) {
00132       cout << hex << "Group channels: 0x" << rodInfo.groupChannels[i].mask0 << " 0x" << rodInfo.groupChannels[i].mask1 << dec << endl;
00133     }
00134 
00135     for(int i=0; i<numSlaves; i++) {
00136       cout << hex << "Slave channels: 0x" << rodInfo.slaveChannels[i].mask0 << " 0x" << rodInfo.slaveChannels[i].mask1 << dec << endl;
00137     }
00138 
00139     cout << "Slave DSP bit-field: " << hex << (int)rodInfo.bitFieldDSP << dec << " nSlaves: " << rodInfo.slaves << endl;
00140 
00141     hex(cout);
00142     for(int i=0; i<numSlaves; i++) {
00143       cout << "Groups on DSP " << i << ": 0x" << (int)extra->groupDspMap[i] << endl;
00144     }
00145 
00146     for(int i=0; i<2; i++) {
00147       cout << "Groups to serial port " << i << ": 0x" << (int)extra->groupSpMap[i] << endl;
00148     }
00149 
00150     for(int i=0; i<2; i++) {
00151       cout << "Groups using range list " << i << ": 0x" << (int)extra->groupRangeMap[i] << endl;
00152     }
00153     dec(cout);
00154   }
00155 
00156   for(ScanEx::RodInfoMap::const_iterator ri = extra->rodInfo.begin();
00157       ri != extra->rodInfo.end();
00158       ri++) {
00159     if(ri->second.bitFieldDSP & 0xf == 0) {
00160 #warning "Should only abort if no slaves on all RODs?"
00161       cout << "No slaves have been deemed involved in histogramming aborting\n";
00162       if(mrs) {
00163         *mrs << MRS_ERROR 
00164              << "SCAN_NODSP" 
00165              << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00166              << MRS_TEXT("No DSP matched to modules for scan")
00167              << MRS_PARAM<int>("partition", ri->first.partition)
00168              << MRS_PARAM<int>("crate", ri->first.crate)
00169              << MRS_PARAM<int>("rod", ri->first.rod)
00170              << ENDM;
00171       }
00172       // Harshly abort if one ROD doesn't have modules in a scan...
00173       throw SctApiException("Invalid scan. A ROD doesn't have any modules attached");
00174     }
00175   }
00176   std::cout << "pre scan hardware check, time = " << timer.elapsed() << std::endl;
00177   if (!preScanHardwareCheck(*scan.get(), *extra)) throw SctApiException("Pre scan hardware check failed");
00178   std::cout << "done" << std::endl;
00179   
00180   std::cout << "pre scan module setup, time = " << timer.elapsed() << std::endl;
00181   preScanModuleSetup(*scan.get());
00182   std::cout << "done" << std::endl;
00183   
00184   { 
00185     // Check for soft reset and update diagnostic reg accordingly.
00186     Trigger::RODTriggers points = scan->getTrigger1()->getRODTriggers();
00187 
00188     for(unsigned int i=0; i<points.size(); i++) {
00189       if(points[i].first == SOFT_RESET) {
00190         cout << "Do extra soft reset before trigger to mask soft reset in trigger\n";
00191         extra->diagnosticReg |= 1 << DR_SOFT_BC_RESET;
00192       }
00193     }
00194   }
00195 
00196   bool setupGood = true;
00197 
00198   try {
00199     cout << "Setup histogramming tasks ..., time = " << timer.elapsed() << std::endl;
00200     doHistogramSetup(*scan.get(), *extra);
00201     cout << " ... done setup histogramming tasks, time = " << timer.elapsed() << std::endl;
00202   } catch(SctApiException &s) {
00203     setupGood = false;
00204   }
00205 
00206   // Send MRS message first so timing not involved
00207   if(mrs) {
00208     *mrs << "SCAN_STARTED" << MRS_INFORMATION 
00209          << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
00210          << MRS_TEXT("Scan started") 
00211          << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
00212          << MRS_PARAM<int>("ScanType1", scan->getScanVariable1())
00213          << MRS_PARAM<int>("ScanType2", scan->getScanVariable2())
00214          << ENDM;
00215   }
00216 
00217   try {
00218     if(setupGood) {
00219       // Do polling in separate thread, first decide which controller to use
00220       if(scan->getOption(Scan::TIM)) {
00221         scanController.reset(new ScanControlTIMHisto(*this, scan, extra));
00222       } else {
00223         scanController.reset(new ScanControlRODHisto(*this, scan, extra));
00224       }
00225 
00226       cout << "Starting histogramming ...\n";
00227       scanController->startHistogramming();
00228       cout << " ... histogramming started\n";
00229     }
00230   } catch(SctApiException &s) {
00231     setupGood = false;
00232   }
00233   std::cout << "Start polling thread time = " << timer.elapsed() << std::endl; 
00234 #ifndef USE_SCAN_THREAD
00235   if(setupGood) {
00236     // But not for now
00237     scanLoop();
00238   }
00239 #endif
00240 }
00241 
00242 void SctApi::awaitScan() {
00243   while((scanController || m_inScanLoop) || m_inRawScanLoop) {
00244     sleep(1);
00245   }
00246 }
00247 
00248 /* Called by scanPollingThread */
00249 void SctApi::scanLoop() {
00250   // Do this before getting the scan out
00251   m_inScanLoop = true;
00252 
00253   boost::shared_ptr<ScanControl> control;
00254 
00255   swap(control, scanController);
00256 
00257   // For the debug methods to talk to
00258   lastScanController = control;
00259 
00260   if(!control) {
00261     cout << "Given null scan aborting!\n";
00262     return;
00263   }
00264 
00265   control->initialisePolling();
00266 
00267   int pollReturn = pollHistogramming(control, 3);
00268 
00269   cout << "pollHistogramming complete (" << pollReturn << ")\n";
00270 
00271   control->finishHistogram(pollReturn == 0);
00272 
00273   // Do this before getting the scan out
00274   m_inScanLoop = false;
00275 }
00276 
00277 void SctApi::scanPollingThread() {
00278   cout << "SCAN: Start polling thread\n";
00279 
00280   while(!m_stopPolling) {
00281     sleep(1);
00282     if(scanController) {
00283       scanLoop();
00284     }
00285   }
00286 }
00287 
00288 void SctApi::setupEventTrapping(const Scan &scan, const ScanEx &ex, const RodLabel rod, boost::shared_ptr<PrimListWrapper> primList) {
00289   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00290 
00291   // Set up each slave individually
00292   for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
00293     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00294       int match;
00295       int modulus;            // Trap if (count % mod) == rem
00296       int remainder;
00297 
00298       switch(scan.getOption(Scan::DISTSLAVE)) {
00299       case 0:
00300         // Single slave
00301         match = 0;
00302         modulus = 1;
00303         remainder = 0;
00304 
00305         if(scan.getOption(Scan::NTH) > 1) {
00306           // Only trap every nth trigger
00307           modulus = scan.getOption(Scan::NTH);
00308           remainder = scan.getOption(Scan::NTH_REM);
00309         }
00310         break;
00311       case 1:
00312         // Group distribution
00313         match = slaveNumber;  // Match number set by histo control to distribute to slaves
00314         modulus = 1;
00315         remainder = 0;
00316         break;
00317       case 2:
00318         // Router distribution, between 4 DSPs
00319         match = 0;
00320         modulus = rodInfo.slaves;
00321         remainder = slaveNumber;
00322 
00323         if(scan.getOption(Scan::NTH) > 1) {
00324           modulus = rodInfo.slaves * scan.getOption(Scan::NTH);
00325           remainder = slaveNumber * scan.getOption(Scan::NTH) + scan.getOption(Scan::NTH_REM);
00326         }
00327         break;
00328       default:
00329         match = 0;
00330         modulus = 1;
00331         remainder = 0;
00332         break;
00333       }
00334 
00335       eventTrapSetup(0x1 << slaveNumber, 
00336                      match, modulus, remainder,
00337                      scan.getOption(Scan::TIM), checkDebugOption(DEBUG_SCAN_ERROR_TRAP_ALL), primList);
00338     }
00339   }
00340 }
00341 
00342 void SctApi::setupEventDump(const Scan &scan, const ScanEx &ex, const RodLabel rod, boost::shared_ptr<PrimListWrapper> primList) {
00343   if(!(checkDebugOption(DEBUG_SCAN_ERROR_TRAP) && scan.getOption(Scan::DEBUG))) return;
00344 
00345   int slaveNumber = 2;
00346 
00347   // No difference depending where its run...
00348   {
00349     // Trap all events as errors
00350     long *evData = new long[sizeof(EVENT_TRAP_SETUP_IN)/4];
00351 
00352     EVENT_TRAP_SETUP_IN &primData = *(EVENT_TRAP_SETUP_IN*)evData;
00353 
00354 #if R_EVENT_TRAP_SETUP == 103
00355     primData.slvBits = 0x1 << slaveNumber;
00356     primData.numberOfEvents = COLLECT_FOREVER;
00357     primData.timeoutInUsec = 0x30000;
00358 
00359     primData.extRouterSetup = 0;
00360 
00361     // This tells the setup code to change the trapRemainder
00362     //  Only matters if setting up more than one slave
00363     primData.distribute = TRAP_DISTRIB_NEITHER;
00364 
00365     primData.releaseFrames = 0;
00366     primData.permitBackPressure = 1;
00367     primData.dataMode = 0;                        // Data or Event mode
00368     primData.sLink = 0;                           // Where to pick events (dsp or router)
00369 
00370     primData.format = TRAP_FMT_ERROR;             // Slink format
00371     primData.trapStray = 1;                       // Trap stray events
00372     primData.iterLimit = 2;                       // Don't keep them long
00373 
00374     // Trap events from ROD triggers
00375     primData.trapConfig[0] = TRAP_CFG_ROD_EVT;
00376     primData.trapExclusionFlag[0] = 0;            // Don't exclude anything
00377     primData.trapFunction[0] = TRAP_FXN_RESYNCH;
00378 
00379     primData.trapMatch[0] = 0;                    // = slave number??
00380     primData.trapModulus[0] = 1;                  // Trap if (count % mod) == rem
00381     primData.trapRemainder[0] = 0;
00382 
00383     // Trap one is idle
00384     primData.trapConfig[1] = TRAP_CFG_IDLE;
00385     primData.trapExclusionFlag[1] = 0;
00386     primData.trapFunction[1] = 0;
00387 
00388     primData.trapMatch[1] = 0; 
00389     primData.trapModulus[1] = 0;
00390     primData.trapRemainder[1] = 0;
00391 #else 
00392 #error "Event trapping not compiled (new Primitive definition)!"
00393 #endif
00394     primList->addPrimitive(RodPrimitive(sizeof(EVENT_TRAP_SETUP_IN)/sizeof(UINT32) + 4, 
00395                                         0, EVENT_TRAP_SETUP, R_EVENT_TRAP_SETUP, evData),
00396                            evData);
00397   }
00398 
00399   // Start event trapping on slave 2
00400   startEventTrap(slaveNumber, primList);
00401 
00402   // Start a dump to remove the events...
00403   {
00404     long *taskData = new long[sizeof(START_TASK_IN)/4];
00405 
00406     for(unsigned int i=0; i<sizeof(START_TASK_IN)/4; i++) {
00407       taskData[i] = 0;
00408     }
00409 
00410     START_TASK_IN &taskPrim = *(START_TASK_IN *)taskData;
00411 
00412     taskPrim.taskType = RESYNCH_TASK;
00413     taskPrim.taskRevision = R_RESYNCH_TASK;
00414     taskPrim.priority = 1; // Top???
00415     taskPrim.completionFlag = 1; 
00416 
00417     RESYNCH_TASK_IN &resynch = taskPrim.taskStruct.resynchTaskIn;
00418 
00419     resynch.errorType = 0;
00420 
00421     shared_ptr<PrimListWrapper> myList(new PrimListWrapper(4));
00422 
00423     myList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/4,
00424                                       3, START_TASK, R_START_TASK, taskData),
00425                          taskData);
00426 
00427     PrimBuilder::instance().slavePrimList(primList, myList, slaveNumber, true, true);
00428   }
00429 }
00430 
00431 void SctApi::startEventTrapping(const Scan &scan, const ScanEx &ex, const RodLabel rod, shared_ptr<PrimListWrapper> primList) {
00432   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00433 
00434   for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
00435     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00436       startEventTrap(slaveNumber, primList);
00437     }
00438   }
00439 }
00440 
00441 void  SctApi::setupHistogramming(const Scan &scan, const ScanEx &ex, const RodLabel rod, bool tim, 
00442                                  boost::shared_ptr<PrimListWrapper> primList) {
00443   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00444 
00445   int nBins = scan.getScanPoints1().size();
00446   if(!scan.getOption(Scan::BITS32)) {
00447     if(nBins%2 == 1) {
00448       nBins += 1;
00449     }
00450   }
00451 
00452   for(int slaveNumber = 0; slaveNumber < 4; slaveNumber ++) {
00453     if((rodInfo.bitFieldDSP & (1<<slaveNumber)) && getCrate()->slavePresent(rod.rod, slaveNumber)) {
00454       // Primitive
00455       long *histoData = new long[sizeof(HISTOGRAM_SETUP_IN)/4];
00456 
00457       HISTOGRAM_SETUP_IN &primData = *(HISTOGRAM_SETUP_IN*)histoData;
00458 
00459 #if (R_HISTOGRAM_SETUP == 108)
00460       primData.base = (UINT32 *)0xffffffff;//  HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00461       primData.nBins = nBins; 
00462 
00463       primData.dataType[0] = scan.getScanVariable1();
00464       primData.dataType[1] = scan.getScanVariable2();
00465 
00466       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00467 
00468       if(checkDebugOption(DEBUG_SCAN_USE_ASSEMBLER)) {
00469         primData.routineType = HISTO_ROUTINE_ASM;
00470       } else {
00471         primData.routineType = HISTO_ROUTINE_C;
00472       }
00473 
00474       // arrangement
00475       primData.opt[0] = 0; // HISTOGRAM_SLICE; // scan.getOption(Scan::FORMAT)?HISTOGRAM_SLICE:HISTOGRAM_BLOCK;
00476       // dataFormat
00477       primData.opt[1] = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00478       // unused
00479       primData.opt[2] = 0;
00480       primData.opt[3] = 0;
00481 
00482       UINT8 groupMap = ex.groupDspMap[slaveNumber];
00483 
00484       primData.validModules[0] = 0;
00485       primData.validModules[1] = 0;
00486 
00487       primData.moduleRangeMap[0][0] = 0;
00488       primData.moduleRangeMap[0][1] = 0;
00489       primData.moduleRangeMap[1][0] = 0;
00490       primData.moduleRangeMap[1][1] = 0;
00491 
00492       for(int i=0; i<8; i++) {
00493         if(groupMap & (1<<i)) {
00494           primData.validModules[0] |= rodInfo.groupChannels[i].mask0;          // Modules to this slave
00495           primData.validModules[1] |= rodInfo.groupChannels[i].mask1;          //    32-47 in low 16 bits
00496 
00497           if(ex.groupSpMap[0] & (1<<i)) {
00498             primData.moduleRangeMap[0][0] |= rodInfo.groupChannels[i].mask0;
00499             primData.moduleRangeMap[0][1] |= rodInfo.groupChannels[i].mask1;
00500           }
00501           if(ex.groupSpMap[1] & (1<<i)) {
00502             primData.moduleRangeMap[1][0] |= rodInfo.groupChannels[i].mask0;
00503             primData.moduleRangeMap[1][1] |= rodInfo.groupChannels[i].mask1;
00504           }
00505         }
00506       }
00507 
00508       primData.xPtr[0] = (FLOAT32 *)0xffffffff; // 0x3f00000;                    // Where the fit data will be stored
00509       primData.xPtr[1] = (FLOAT32 *)0xffffffff; // 0x3f01000; 
00510 #elif (R_HISTOGRAM_SETUP == 105) || (R_HISTOGRAM_SETUP == 107)
00511       primData.base = (UINT32 *)0xffffffff;//  HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00512       primData.nBins = nBins; 
00513 
00514       primData.padding[0] = 0;
00515       primData.padding[1] = 0;
00516 
00517       primData.dataType[0] = scan.getScanVariable1();
00518       primData.dataType[1] = scan.getScanVariable2();
00519 
00520       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00521 
00522       // arrangement
00523       primData.opt[0] = HISTOGRAM_SLICE; // scan.getOption(Scan::FORMAT)?HISTOGRAM_SLICE:HISTOGRAM_BLOCK;
00524       // dataFormat
00525       primData.opt[1] = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00526       // unused
00527       primData.opt[2] = 0;
00528 #if(R_HISTOGRAM_SETUP == 107)
00529       primData.opt[3] = 0;
00530 #endif
00531 
00532       UINT8 groupMap = ex.groupDspMap[slaveNumber];
00533 
00534       primData.validModules[0] = 0;
00535       primData.validModules[1] = 0;
00536 
00537       primData.moduleRangeMap[0][0] = 0;
00538       primData.moduleRangeMap[0][1] = 0;
00539       primData.moduleRangeMap[1][0] = 0;
00540       primData.moduleRangeMap[1][1] = 0;
00541 
00542       for(int i=0; i<8; i++) {
00543         if(groupMap & (1<<i)) {
00544           primData.validModules[0] |= rodInfo.groupChannels[i].mask0;          // Modules to this slave
00545           primData.validModules[1] |= rodInfo.groupChannels[i].mask1;          //    32-47 in low 16 bits
00546 
00547           if(ex.groupSpMap[0] & (1<<i)) {
00548             primData.moduleRangeMap[0][0] |= rodInfo.groupChannels[i].mask0;
00549             primData.moduleRangeMap[0][1] |= rodInfo.groupChannels[i].mask1;
00550           }
00551           if(ex.groupSpMap[1] & (1<<i)) {
00552             primData.moduleRangeMap[1][0] |= rodInfo.groupChannels[i].mask0;
00553             primData.moduleRangeMap[1][1] |= rodInfo.groupChannels[i].mask1;
00554           }
00555         }
00556       }
00557 
00558       primData.xPtr[0] = (FLOAT32 *)0xffffffff; // 0x3f00000;                    // Where the fit data will be stored
00559       primData.xPtr[1] = (FLOAT32 *)0xffffffff; // 0x3f01000; 
00560 #elif R_HISTOGRAM_SETUP == 104
00561       primData.base = (UINT32 *)0xffffffff; // HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00562       primData.rodType = ROD_TYPE_SCT;
00563       primData.nBins = nBins;
00564 
00565       primData.padding[0] = 0;
00566       primData.padding[1] = 0;
00567 
00568       primData.dataType[0] = scan.getScanVariable1();
00569       primData.dataType[1] = scan.getScanVariable2();
00570 
00576       primData.arrangement = HISTOGRAM_SLICE;
00577       primData.dataFormat = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;          // Get all three data sets
00578       primData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00579       primData.unused = 0;
00580 
00581       if(scan.getOption(Scan::DISTSLAVE) == 1) {
00582         primData.validModules[0] = rodInfo.groupChannels[slaveNumber][0];          // Modules to this slave
00583         primData.validModules[1] = rodInfo.groupChannels[slaveNumber][1];          //    32-47 in low 16 bits
00584         primData.moduleRangeMap[0][0] = rodInfo.groupChannels[slaveNumber][0];     // All modules use rangemap 0
00585         primData.moduleRangeMap[0][1] = rodInfo.groupChannels[slaveNumber][1];
00586       } else {
00587         primData.validModules[0] = rodInfo.channels[0];                          // Modules to this slave
00588         primData.validModules[1] = rodInfo.channels[1];                          //    32-47 in low 16 bits
00589         primData.moduleRangeMap[0][0] = rodInfo.channels[0];                     // All modules use rangemap 0
00590         primData.moduleRangeMap[0][1] = rodInfo.channels[1];
00591       }
00592       primData.moduleRangeMap[1][0] = 0;                                    // No modules for rangemap 1
00593       primData.moduleRangeMap[1][1] = 0;
00594 
00595       primData.xPtr[0] = (FLOAT32 *)0x3f00000;                              // Where the fit data will be stored
00596       primData.xPtr[1] = (FLOAT32 *)0x3f01000; 
00597 #else 
00598 #error "Histogram setup not compiled (new Primitive definition)!"
00599 #endif
00600 
00601       long *taskData = new long[sizeof(START_TASK_IN)/4];
00602 
00603       for(unsigned int i=0; i<sizeof(START_TASK_IN)/4; i++) {
00604         taskData[i] = 0;
00605       }
00606 
00607       START_TASK_IN &taskPrim = *(START_TASK_IN *)taskData;
00608 
00609       taskPrim.taskType = HISTOGRAM_TASK;
00610       taskPrim.taskRevision = R_HISTOGRAM_TASK;
00611       taskPrim.priority = 1; // Top???
00612       taskPrim.completionFlag = 1; 
00613 
00614       HISTOGRAM_TASK_IN &histoTaskData = taskPrim.taskStruct.histogramTaskIn;
00615 
00616       histoTaskData.nEvents = COLLECT_FOREVER;
00617       if(tim) {
00618         histoTaskData.controlFlag = LOCAL_SET_TRIG;
00619       } else {
00620         histoTaskData.controlFlag = MASTER_HREG;
00621       }
00622 
00623       boost::shared_ptr<PrimListWrapper> myList(new PrimListWrapper(4));
00624 
00625       myList->addPrimitive(RodPrimitive(4 + sizeof(HISTOGRAM_SETUP_IN)/sizeof(UINT32), 
00626                                         2, HISTOGRAM_SETUP, R_HISTOGRAM_SETUP, histoData),
00627                            histoData);
00628       myList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/4,
00629                                         3, START_TASK, R_START_TASK, taskData),
00630                            taskData);
00631 
00632       PrimBuilder::instance().slavePrimList(primList, myList, slaveNumber, true, true);
00633     }
00634   }
00635 }
00636 
00637 void SctApi::startHistogramTask(const Scan &scan, const ScanEx &ex, const RodLabel rod, 
00638                                 unsigned int startBin, unsigned int nBins, unsigned int nTrigs,
00639                                 boost::shared_ptr<PrimListWrapper> primList) {
00640   const RodScanEx &rodInfo = ex.getRodScanInfo(rod);
00641 
00642   // The number of bins in the variable list has to be nBins...
00643   unsigned int allBins = nBins;
00644 
00645   long *ctrlData = new long[sizeof(START_TASK_IN)/4 + allBins * 2];
00646 
00647   for(unsigned int i=0; i<sizeof(START_TASK_IN)/4 + allBins * 2; i++) {
00648     ctrlData[i] = 0;
00649   }
00650 
00651   struct START_TASK_IN &primData = *(START_TASK_IN*)ctrlData;
00652   struct HISTOGRAM_CTRL_TASK_IN &taskData = primData.taskStruct.histoCtrlTaskIn; 
00653 
00654 #if (R_HISTOGRAM_CTRL_TASK == 107)
00655   primData.taskType = HISTOGRAM_CTRL_TASK;
00656   primData.taskRevision = R_HISTOGRAM_CTRL_TASK;
00657   primData.priority = 1;
00658   primData.completionFlag = 1; 
00659 
00660   taskData.slvBits = rodInfo.bitFieldDSP;   // Which DSPs to use
00661 
00662   if(scan.getScanPoints2().size() > 0) {
00663     taskData.port = SP_BOTH;
00664   } else {
00665     //@todo Should this be SP_BOTH??? 
00666     // The histogramming itself can only use one port...
00667     // But this may tell the engine to configure modules using both ports?
00668     // Which would be good to do anyway
00669     //taskData.port = SP_BOTH;
00670     taskData.port = SP0;
00671   }
00672 
00673   taskData.configRegister[0] = scan.getScanVariable1(); // ST_VTHR;
00674   taskData.configRegister[1] = scan.getScanVariable2(); // ST_VTHR;
00675 
00676   taskData.configSctSet = Utility::translateBank(SCTAPI_BANK_SCAN);
00677 
00678 #warning "Alan Barr (AJB) suspects that this will need to change when Dougs new configuration code arrives."
00679   // Which bit of configuration to send, unless this is a trim scan then basic should be enough
00680   if(!ex.trimScan) 
00681     taskData.dataSet = MODULE_BASIC; 
00682   else 
00683     taskData.dataSet = MODULE_TRIM;               // Which bit of configuration to send
00684 
00685   taskData.groupRangeMap[0] = ex.groupRangeMap[0];
00686   taskData.groupRangeMap[1] = ex.groupRangeMap[1];
00687 
00688   taskData.groupDSPMap[0] = ex.groupDspMap[0];
00689   taskData.groupDSPMap[1] = ex.groupDspMap[1];
00690   taskData.groupDSPMap[2] = ex.groupDspMap[2];
00691   taskData.groupDSPMap[3] = ex.groupDspMap[3];
00692 
00693   taskData.groupSPMap[0] = ex.groupSpMap[0];
00694   taskData.groupSPMap[1] = ex.groupSpMap[1];
00695 
00696   taskData.globalCtrl = 0;              // Don't want to take control for internal triggers
00697   taskData.syncLevel = 0;               //  So don't need synchronisation 
00698 
00699   taskData.histoBase = (UINT32*)0xffffffff; // HISTOGRAM_DEFAULT_BASE;    // 0x20d2000
00700 
00701   taskData.doChipOcc = 1;
00702   taskData.dataFormat = scan.getOption(Scan::FULL)?HISTOGRAM_FULL:HISTOGRAM_CONDENSED;
00703   taskData.binSize = scan.getOption(Scan::BITS32)?HISTOGRAM_32BIT:HISTOGRAM_16BIT;
00704   taskData.unused1 = 0;
00705 
00706   taskData.extSetup = 0xff;                    // This is specifies which setup tasks are done externally (to the control task)
00707   taskData.dataPath = DATA_PATH_NORMAL;        // Other option is INMEM (presumably TestBench based)
00708   taskData.capture = 0;
00709   taskData.useRangeList = 0;                   // Major difference from Doug's example!
00710 
00711   taskData.repetitions = nTrigs;
00712   taskData.nBins = nBins;
00713   taskData.bin0 = startBin;
00714 
00715   // Ignore range list data 
00716   for(int i=0; i<5; i++) {
00717     taskData.rangeList[0].xPair[i].x0 = 0.0;
00718     taskData.rangeList[1].xPair[i].x0 = 0.0;
00719     taskData.rangeList[0].xPair[i].delta_x = 0.0;
00720     taskData.rangeList[1].xPair[i].delta_x = 0.0;
00721   }
00722 
00723   // X data lists
00724   taskData.dataPtr[0] = (FLOAT32 *)0xffffffff;   // Data for group 1               Append to end of primitive
00725   taskData.dataPtr[1] = (FLOAT32 *)0xffffffff;   // Data for group 2
00726 
00727   // Clear trigger sequences
00728   for(int i=0; i<N_CMD_LIST_CMDS; i++) {            // from primParams.h
00729     taskData.triggerSequence[0].cmd[i] = NO_CMD;    // Set a trigger sequence
00730     taskData.triggerSequence[1].cmd[i] = NO_CMD;    // Set a trigger sequence
00731     taskData.triggerSequence[0].data[i] = 0;        // Set a trigger sequence
00732     taskData.triggerSequence[1].data[i] = 0;        // Set a trigger sequence
00733   }
00734 
00735 
00736 //    // Two L1As (illegal without delay?!)
00737 //    taskData.triggerSequence[0].cmd[0] = L1_TRIGGER;
00738 //    taskData.triggerSequence[1].cmd[0] = L1_TRIGGER;
00739 //    taskData.triggerSequence[0].cmd[1] = L1_TRIGGER;
00740 //    taskData.triggerSequence[1].cmd[1] = L1_TRIGGER;
00741 
00742   Trigger::RODTriggers points = scan.getTrigger1()->getRODTriggers();
00743 
00744   for(unsigned int i=0; i<points.size(); i++) {
00745     taskData.triggerSequence[0].cmd[i] = points[i].first;        // Set a trigger sequence
00746     taskData.triggerSequence[0].data[i] = points[i].second;      // Set a trigger sequence
00747   }
00748 
00749   if(scan.getScanPoints2().size() > 0) {
00750     points = scan.getTrigger2()->getRODTriggers();
00751 
00752     for(unsigned int i=0; i<points.size(); i++) {
00753       taskData.triggerSequence[1].cmd[i] = points[i].first;      // Set a trigger sequence 2
00754       taskData.triggerSequence[1].data[i] = points[i].second;    // Set a trigger sequence 2
00755     }
00756   } else {
00757     // Leave as default
00758   }
00759 
00760 //    taskData.triggerSequence[0].cmd[0] = CALIBRATION_PULSE;
00761 //    taskData.triggerSequence[0].cmd[1] = DELAY;
00762 //    taskData.triggerSequence[0].cmd[2] = L1_TRIGGER;
00763 
00764 //    taskData.triggerSequence[0].data[1] = 0x81;
00765 
00766   unsigned short cmd, data;
00767 
00768   scan.getTrigger1()->getCommIncr(cmd, data);
00769   taskData.incCmd[0] = cmd;
00770   taskData.incData[0] = data;
00771   scan.getTrigger2()->getCommIncr(cmd, data);
00772   taskData.incCmd[1] = cmd;
00773   taskData.incData[1] = data;
00774 
00775   taskData.calLineLoop = scan.getOption(Scan::LOOPCALLINE);
00776   if(scan.getOption(Scan::DISTSLAVE) == 2) {
00777     taskData.distributionToggle = ROUTER_DISTRIB;
00778   } else {
00779     taskData.distributionToggle = MODULE_GROUP;
00780   }
00781 
00782   for(int i=0; i<10; i++) {
00783     taskData.genData[i] = 0;
00784   }
00785 
00786   // Defined groups
00787   taskData.genData[0] = 0xff;
00788 
00789   if(scan.getScanPoints2().size() > 0) {
00790     taskData.genData[1] = 1;
00791     taskData.genData[2] = 0x0200; // 0301;
00792   }
00793 
00794 #elif (R_HISTOGRAM_CTRL_TASK == 105)
00795   primData.taskType = HISTOGRAM_CTRL_TASK;
00796   primData.taskRevision = R_HISTOGRAM_CTRL_TASK;
00797   primData.priority = 0; // Top???
00798   primData.completionFlag = 1; 
00799 
00800   taskData.slvBits = 0xf;             // Use all slaves
00801   taskData.configSctSet = translateBank(SCTAPI_BANK_PHYSICS);
00802   // Not an array yet
00803 //    taskData.configRegister[0] = 0;     // V_THR ??
00804 //    taskData.configRegister[1] = 0;     // V_THR ??
00805   taskData.dataSet = 0;               // ??
00806   taskData.useRangeList = 0;          // ??
00807   taskData.groupRangeMap[0] = 0;      // No range map
00808   taskData.groupRangeMap[1] = 0;      //  ditto
00809   taskData.cmdBuff = CMD_BUFFER_BOTH;     // Which serial port to use
00810   taskData.dataPtr[0] = group1Data;   // Data for group 1
00811   taskData.dataPtr[1] = group2Data;   // Data for group 2
00812   taskData.repetitions = 10;          // Make it stop quickly 10 events
00813   taskData.nBins = 10;                // 10 bins
00814   taskData.bin0 = 0;                  // Start at 0
00815 
00816   taskData.triggerSequence[0];        // Set a trigger sequence
00817   taskData.triggerSequence[1];        // Set a trigger sequence
00818 
00819   taskData.incCmd[0] = 0;
00820   taskData.incCmd[1] = 0;
00821   taskData.calLineLoop = 0;  // Doesn't work yet??
00822 
00823   taskData.distributionToggle = 0;  // ??
00824   taskData.incData[0] = 1;
00825   taskData.incData[1] = 1;
00826 
00827   taskData.groupSPMap[0] = 0;
00828   taskData.groupSPMap[1] = 0;
00829 #else  // Unknown R_HISTOGRAM_CTRL_TASK
00830 #error "Histogram Task not compiled (new Primitive definition)!" 
00831 #endif
00832 
00833   int offset = sizeof(START_TASK_IN)/4;
00834 
00835   // Copy real bins
00836   for(unsigned int i=0; i<allBins; i++) {
00837     ctrlData[offset + i] = *(UINT32 *)&(scan.getScanPoints1()[i]);
00838     if(scan.getScanPoints2().size() == 0) {
00839       ctrlData[offset + allBins + i] = *(UINT32*)&(scan.getScanPoints1()[i]);
00840     } else {
00841       ctrlData[offset + allBins + i] = *(UINT32*)&(scan.getScanPoints2()[i]);
00842     }
00843   }
00844 
00845   primList->addPrimitive(RodPrimitive(4 + sizeof(START_TASK_IN)/sizeof(UINT32) + allBins * 2, 
00846                                       0, START_TASK, R_START_TASK, ctrlData),
00847                          ctrlData);
00848 }
00849 
00850 /*
00851   Stop histogram control in master
00852   Histogram and event trapping in slaves
00853 
00854   *********** XXX Send them individually as it doesn't seem to work otherwise ***************
00855 */
00856 void SctApi::stopHistogramming(const ScanEx &ex) {
00857   for(ScanEx::RodInfoMap::const_iterator ri = ex.rodInfo.begin();
00858       ri != ex.rodInfo.end();
00859       ri++) {
00860     const RodLabel &rod = ri->first;
00861 
00862     {
00863       boost::mutex::scoped_lock lock(log().mutex());
00864       log() << "Stop histogramming (controlled)\n";
00865     }
00866 //  stopEvTrap(0);
00867 
00868 //  taskOp(16, 0, 0, -1);   // Stop histogram control task
00869 
00870 //  taskOp(32, 0, 0, 0);     // Stop histogram task
00871 
00872     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(2));
00873 
00874     PrimBuilder &builder = PrimBuilder::instance();
00875     builder.taskOp(primList, HISTOGRAM_CTRL_TASK, TASK_STOP, 0);
00876 
00877     {
00878       boost::mutex::scoped_lock lock(log().mutex());
00879       log() << "Stop histo control task\n";
00880     }
00881     sendPrimList(rod.rod, primList);
00882 
00883     awaitResponse(rod.rod, 5);
00884     primList->clear();
00885 
00886     cout << "Done kill control task\n";
00887 
00888     for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
00889       // Kill all tasks!!!!
00890       boost::shared_ptr<PrimListWrapper> slList(new PrimListWrapper(1));
00891 
00892       // Stop Slave histogramming task
00893 
00894       builder.taskOp(slList, HISTOGRAM_TASK, TASK_STOP, 0);
00895 
00896       PrimBuilder::instance().slavePrimList(primList, slList, slaveNumber, true, true);
00897       {
00898         boost::mutex::scoped_lock lock(log().mutex());
00899         log() << "Stop slave histogram task " << slaveNumber << endl;
00900       }
00901       sendPrimList(rod.rod, primList);
00902       awaitResponse(rod.rod, 5);
00903       slList->clear();
00904       primList->clear();
00905 
00906       cout << "Done kill histogram task\n";
00907 
00908       stopEventTrap(slaveNumber, primList);
00909 
00910       {
00911         boost::mutex::scoped_lock lock(log().mutex());
00912         log() << "Stop Event trapping on slave " << slaveNumber << endl;
00913       }
00914       sendPrimList(rod.rod, primList);
00915 
00916       awaitResponse(rod.rod, 5);
00917       primList->clear();
00918 
00919       cout << "Done kill event trapping\n";
00920     }
00921   }
00922 
00923   //  sendPrimList(ex.rod, primList);
00924   //  awaitResponse(ex.rod, 2);
00925   cout << "Done kill histogramming tasks\n";
00926 }
00927 
00928 ScanControl::ScanControl(SctApi &api) : api(api) {}
00929 
00930 void ScanControlRODHisto::readHistograms() {
00931   time_t saveTime;
00932   saveTime = time(NULL);
00933 
00934   /* Loop over RODs and release memory at the end to save space
00935        Makes algorithm slightly inefficient (multiple loops over module list)
00936        but better than crashing due to OOM!
00937   */
00938   list<RodLabel> rodList = api.listRods();
00939 
00940   for(list<RodLabel>::const_iterator rl = rodList.begin();
00941       rl!=rodList.end();
00942       rl++){
00943 
00944     cout << "Reading out modules from ROD " << rl->rod << endl;
00945 
00946     // For each module
00947     for(unsigned int group = 0; group < scan->getNGroups(); group ++) {
00948       const ModuleList &groupList = scan->getModuleList(group);
00949       cout << "Modules in group " << group << " count: " << groupList.size() << endl;
00950       for(ModuleList::const_iterator mi = groupList.begin();
00951           mi!=groupList.end();
00952           mi ++) {
00953 
00954         string sn = *mi;
00955         UINT32 mid = api.findModule(sn);
00956 
00957         {
00958           unsigned int partition, crate, rod, channel;
00959           Utility::getpcrc(mid, partition, crate, rod, channel);
00960           if(RodLabel(partition, crate, rod) != *rl) {
00961             // Come back later
00962 //      cout << "Skipping " << sn << " (in ROD " << rod << " not " << rl->rod << ")\n";
00963             continue;
00964           }
00965         }
00966 
00967         cout << "Module:  " << mid << " " << sn << endl;
00968 
00969         try {
00970           if(scan->getOption(Scan::FULL)) {
00971             for(int f=0; f<3; f++) {
00972               scan_result_ptrs result = readHistogramData(mid, f);
00973 
00974               result.header.scanNumber += f;
00975 
00976               // Files need discriminating because they're all the same time
00977               if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
00978                 readHistogramToFile(*scan, *scanEx, mid, api.convertToString(mid), result, saveTime, f);
00979               }
00980 
00981 #ifdef USE_IS
00982               // IS based on Run/Scan number so nothing more needed
00983               if(api.mrs)readHistogramToIS(*scan, *scanEx, mid, result);
00984 #endif
00985 
00986               delete [] (char*)result.data;
00987               delete [] result.points;
00988               delete [] result.nEvents;
00989               delete [] result.nErrorEvents;
00990             }
00991           } else {
00992             scan_result_ptrs result = readHistogramData(mid, 0);
00993 
00994             if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
00995               readHistogramToFile(*scan, *scanEx, mid, api.convertToString(mid), result, saveTime);
00996             }
00997 #ifdef USE_IS
00998             if(api.mrs)readHistogramToIS(*scan, *scanEx, mid, result);
00999 #endif
01000             delete [] (char*)result.data;
01001             delete [] result.points;
01002             delete [] result.nEvents;
01003             delete [] result.nErrorEvents;
01004           }
01005         } catch(SctApiException &s) {
01006           if(api.mrs) {
01007             *api.mrs << "SCAN_READOUT_FAIL" << MRS_ERROR
01008                      << MRS_QUALIF("SctApi")
01009                      << MRS_PARAM<int>("run", scan->getRunNumber()) 
01010                      << MRS_PARAM<int>("scan", scan->getScanNumber()) 
01011                      << MRS_PARAM<int>("mid", mid) 
01012                      << MRS_TEXT("Module readout failed") << ENDM;
01013           }
01014         }
01015       } // Histogram for next module
01016     } // Next module group
01017 
01018     // Release memory from ROD
01019     for(std::map<std::pair<RodLabel, int>, 
01020           Utility::MemoryBlock> :: iterator mapIter = scanEx->histoMap.begin();
01021         mapIter != scanEx->histoMap.end();
01022         mapIter++) {
01023 
01024       if(mapIter->first.first == *rl) {
01025         if(api.mrs) {
01026           *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
01027                    << MRS_PARAM<float>("MWords", mapIter->second.size() / 1e6)
01028                    << MRS_PARAM<int>("crate", rl->crate)
01029                    << MRS_PARAM<int>("rod", rl->rod)
01030                    << MRS_TEXT("Releasing memory after histogram readout") << ENDM;
01031         }
01032 
01033         mapIter->second = Utility::MemoryBlock();
01034       }
01035     }
01036   } // End ROD loop
01037 }
01038 
01039 scan_result_ptrs ScanControlRODHisto::readHistogramData(UINT32 mid, int frame) {
01040   scan_result_ptrs scanResult;
01041 
01042   //We do this first deliberately.
01043   //The dummy api will need to mess around with some things
01044   scanResult.data = readHistogramRawData(mid, frame);
01045 
01046   int nBins = scan->getScanPoints1().size();
01047 
01048   // Read the module configuration from the end of the scan...
01049   api.getABCDModule(mid, SCTAPI_BANK_SCAN);
01050 
01051   // Save copy of configuration from end of scan
01052   ABCDModule moduleConfig = *api.retrieveModule(mid);
01053 
01054   if(checkDebugOption(DEBUG_MODULE_CONFIG)) {
01055     cout << "Configuration after scan:\n";
01056     api.printABCDModule(mid);
01057   }
01058 
01059   ScanHeader &header = scanResult.header;
01060 
01061   header.version = CURRENT_SCANHEADER_VERSION;
01062   header.length = sizeof(ScanHeader);
01063   header.runNumber = scan->getRunNumber();
01064   header.scanNumber = scan->getScanNumber();
01065   
01066   strncpy(header.moduleName, api.convertToString(mid).c_str(), 16);
01067   strncpy(header.startTime, to_iso_string(scan->getStartTime()).c_str(), 16);
01068   strncpy(header.endTime, to_iso_string(scan->getEndTime()).c_str(), 16);
01069   header.moduleName[15] = 0;    // Null terminate the string
01070   header.startTime[15] = 0;
01071   header.endTime[15] = 0;
01072   
01073 //   snprintf(header.moduleName, 16, "%s", convertToString(mid).c_str());
01074 //   cout << "Module name in Scan Results (" << header.moduleName << ")\n" ;
01075   header.scanType = scan->getScanVariable1();
01076   header.npoints = nBins;
01077   header.size = nBins * 2 * 1024 * (scan->getOption(Scan::BITS32)?2:1);
01078   header.dataType = SR_DT_SLICE;
01079 
01080   header.width = scan->getOption(Scan::BITS32)?SR_WD_32:SR_WD_16;
01081 
01082   header.config = moduleConfig;
01083 
01084   header.pntPoints = sizeof(ScanHeader);
01085   header.pntEvents = header.pntPoints + nBins * sizeof(FLOAT32);
01086   header.pntErrors = header.pntEvents + nBins * sizeof(UINT32);
01087   header.pntData = header.pntErrors + nBins * sizeof(UINT32);
01088 
01089   // The points
01090   FLOAT32 *points = new FLOAT32[nBins];
01091   for(int i=0; i<nBins; i++) {
01092     points[i] = scan->getScanPoints1()[i];
01093   }
01094   scanResult.points = points;
01095 
01096   // The event counts
01097   UINT32 *events = new UINT32[nBins];
01098 
01099   std::pair<RodLabel, unsigned int> moduleSlave = findModuleSlave(mid);
01100 
01101   // This is the better way of counting (especially when there are errors)
01102   unsigned long *countChunk = getEventCountChunk(moduleSlave.first, moduleSlave.second);
01103 
01104   for(int i=0; i<nBins; i++) {
01105     events[i] = countChunk[i];
01106 
01107     // Unfortunately it counts * 4 for cal line loop
01108     if(scan->getOption(Scan::LOOPCALLINE)) {
01109       events[i] >>= 2; 
01110     }
01111   }
01112 
01113 #if 0
01114   // But this way does get the count right with the callineloop on!
01115   Scan::TrigPoints trigs = scan->getVariableTrigs();
01116  
01117   for(int i=0; i<nBins; i++) {
01118     if(i<lastBin[moduleSlave.first]) {
01119       events[i] = trigs[i];
01120     } else if(i == lastBin[moduleSlave.first]) {
01121       events[i] = lastEvent[moduleSlave.first];
01122     } else {
01123       events[i] = 0;
01124     }
01125   }
01126 #endif
01127 
01128   scanResult.nEvents = events;
01129 
01130   // The error counts
01131   UINT32 *errors = new UINT32[nBins];
01132   for(int i=0; i<nBins; i++) {
01133 #warning "Get real error count (if possible!)"
01134     errors[i] = 0;
01135   }
01136   scanResult.nErrorEvents = errors;
01137 
01138   return scanResult;
01139 }
01140 
01141 char* ScanControlRODHisto::readHistogramRawData(UINT32 mid, int frame) {
01142   int nBins = scan->getScanPoints1().size();
01143 
01144   // The number of bins the ROD thinks there are...
01145   int rodBins = nBins;
01146   if(!scan->getOption(Scan::BITS32))
01147     if(rodBins%2 == 1) rodBins++;
01148 
01149   // The data!
01150   int binSize = 0x800*(scan->getOption(Scan::BITS32)?4:2);   // In bytes, so works for 16bit histograms
01151 
01152   char *data = new char[nBins * binSize];
01153 
01154   bool moduleBlock = false;
01155 //    int baseAddress = index*(binSize*nBins);
01156 
01157   unsigned int slaveNumber = 4;
01158 
01159   RodLabel rodLabel;
01160   unsigned int channel;
01161   {
01162     unsigned int partition, crate, rod;
01163     Utility::getpcrc(mid, partition, crate, rod, channel);
01164     RodLabel temp(partition, crate, rod);
01165     rodLabel = temp;
01166   }
01167 
01168   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01169 
01170   for(int slave=0; slave<4; slave++) {
01171     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01172        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01173       if(slaveNumber == 4) {
01174         slaveNumber = slave;
01175       } else {
01176         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01177         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01178 #warning "But maybe I should any way"
01179       }
01180     }
01181   }
01182 
01183   if(slaveNumber == 4) {
01184     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01185 
01186     throw SctApiException("No mapping from module to DSP found");
01187   }
01188 
01189   // Find the module index on this slave
01190   int index = 0;
01191   int nModules = 0; // moduleMap.size();
01192 
01193   for(unsigned int ch=0; ch<48; ch++) {
01194     if(channel == ch) {
01195       index = nModules;
01196     }
01197     if(ch<32) {
01198       if(rodInfo.slaveChannels[slaveNumber].mask0 & 1<<ch) {
01199         nModules ++;
01200       }
01201     } else {
01202       if(rodInfo.slaveChannels[slaveNumber].mask1 & 1<<(ch-32)) {
01203         nModules ++;
01204       }
01205     }
01206   }
01207 
01208   // Get data from place defined by DSP
01209   unsigned long slaveOffset = 0;
01210 
01211   if(moduleBlock) {
01212     slaveOffset += binSize * rodBins;
01213   } else {
01214     slaveOffset += binSize * index;
01215   }
01216 
01217   // For reading expanded data, skip to next block of histograms...
01218   slaveOffset += ((binSize * rodBins * nModules) + binSize) * frame;
01219 
01220   bool error = false;
01221 
01222   for(int i=0; i<nBins; i++) {
01223     unsigned long *chunk = getHistogramChunk(rodLabel, slaveNumber, slaveOffset, binSize/4);
01224     unsigned long *buffer = (unsigned long *)&(data[i*binSize]);
01225 
01226     if(chunk) {
01227       for(int b=0; b<binSize/4; b++) {
01228         buffer[b] = chunk[b];
01229       }
01230 
01231       // Check End of bin xx Module xx
01232       int bin, module;
01233       int count = sscanf(&((char*)buffer)[binSize-32], "End of bin %d Module %d", &bin, &module);
01234       if(count == 2) {
01235 //          printf("Found End of bin %d module %d\n", bin, module);
01236       } else {
01237         if(!error)
01238           printf("Found bad end of histogram bin (%25s)\n", &((char*)buffer)[binSize-32]);
01239         error = true;
01240       }
01241 
01242 #warning "Memory leak if sendData didn't work"
01243 //       delete [] chunk;
01244     } else {
01245       for(int b=0; b<binSize/4; b++) {
01246         buffer[b] = 0;
01247       }
01248     }
01249 
01250     if(moduleBlock) {
01251       slaveOffset += binSize;
01252     } else {
01253       slaveOffset += binSize * nModules;
01254     }
01255   }
01256 
01257   return data;
01258 }
01259 
01260 pair<RodLabel, unsigned int> ScanControlRODHisto::findModuleSlave(unsigned int mid) {
01261   RodLabel rodLabel;
01262   unsigned int channel;
01263   {
01264     unsigned int partition, crate, rod;
01265     Utility::getpcrc(mid, partition, crate, rod, channel);
01266     RodLabel temp(partition, crate, rod);
01267     rodLabel = temp;
01268   }
01269 
01270   unsigned int slaveNumber = 4;
01271 
01272   const RodScanEx &rodInfo = scanEx->getRodScanInfo(rodLabel);
01273 
01274   for(int slave=0; slave<4; slave++) {
01275     if((channel<32 && (rodInfo.slaveChannels[slave].mask0 & 1<<channel))
01276        || (channel >= 32 && (rodInfo.slaveChannels[slave].mask1 & 1<<(channel-32)))) {
01277       if(slaveNumber == 4) {
01278         slaveNumber = slave;
01279       } else {
01280         cerr << " ****** Module found on multiple slaves this is an unsupported configuration, the first one will be downloaded??? *****\n";
01281         cerr << " ****** Well you don't expect me to add them all together do you??? *****\n";
01282 #warning "But maybe I should any way"
01283       }
01284     }
01285   }
01286 
01287   if(slaveNumber == 4) {
01288     cerr << " ****** Current module not found on any slave, skipping histogram read out *****\n";
01289 
01290     throw SctApiException("No mapping from module to DSP found");
01291   }
01292 
01293   return make_pair(rodLabel, slaveNumber);
01294 }
01295 
01296 void readHistogramToFile(const Scan &scan, const ScanEx &ex, 
01297                          UINT32 mid, std::string sn, scan_result_ptrs scanData, time_t saveTime, int frame) {
01298   const int BUFF_SIZE = 50;
01299 
01300   struct tm broke;
01301   broke = *(gmtime(&saveTime));
01302 
01303   string tempDir = SctNames::getTempDir() + "/";
01304   int bufferLength = BUFF_SIZE + tempDir.length();
01305   char *filename = new char[bufferLength];
01306   strcpy(filename, tempDir.c_str());
01307 
01308   cout << "Module:  " << mid << " " << sn << endl;
01309 
01310   int written = tempDir.length();
01311   if(scan.getOption(Scan::FULL)) {
01312     written += snprintf(filename + written, bufferLength - written, "Histogram%d_%s", frame, sn.c_str());
01313     //                                                                    20021112143712
01314     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01315   } else {
01316     written += snprintf(filename + written, bufferLength - written, "Histogram_%s", sn.c_str());
01317     //                                                                    20021112143712
01318     strftime(filename + written, bufferLength - written, "_%Y%m%d%H%M%S.bin", &broke);
01319   }
01320 
01321   cout << "Writing histogram data to " << filename << endl;
01322 
01323   saveHistogramToFile(scanData, filename);
01324     
01325   cout << "done.\n";
01326 
01327   delete [] filename;
01328 }
01329 
01330 void saveHistogramToFile(scan_result_ptrs histo, std::string filename) {
01331   ofstream histoout(filename.c_str(), ios::binary);
01332 
01333   //    assert(histo.header.length == sizeof(ScanHeader));
01334   histoout.write((char*)&histo.header, histo.header.length);
01335 
01336   //    assert(histo.header.pntEvents - histo.header.pntPoints == nBins * sizeof(FLOAT32));
01337   histoout.write((char*)histo.points, histo.header.pntEvents-histo.header.pntPoints);
01338 
01339   //    assert(histo.header.pntErrors - histo.header.pntEvents == nBins * sizeof(FLOAT32));
01340   histoout.write((char*)histo.nEvents, histo.header.pntErrors-histo.header.pntEvents);
01341 
01342   //    assert(histo.header.pntData - histo.header.pntErrors == nBins * sizeof(FLOAT32));
01343   histoout.write((char*)histo.nErrorEvents, histo.header.pntData-histo.header.pntErrors);
01344 
01345   //    assert(histo.header.size*2 == (nBins * 0x800 * 4));
01346 
01347   // header.size is a count in 16bit words!
01348   histoout.write((char*)histo.data, histo.header.size*2);
01349 }
01350 
01351 #ifdef USE_IS
01352 
01353 void readHistogramToIS(const Scan &scan, const ScanEx &ex, UINT32 mid, scan_result_ptrs scanData) {
01354 //   {
01355 //     boost::mutex::scoped_lock lock(log().mutex());
01356 //     log() << "Read Histogram for " << mid << " to IS\n";
01357 //   }
01358 
01359   cout << "Writing histogram data to IS\n";
01360 
01361 //   string sn = convertToString(mid);
01362 
01363   cout << "Module:  " << mid << /* " " << sn << */ endl;
01364 
01365   try {
01366     SctData::ScanResultWriter::publish(scanData);
01367   } catch(Sct::IoException &e) {
01368     cout << "ScanResult publish failed:\n" << e.what() << endl;
01369     e.sendToMrs(MRS_ERROR);
01370   }
01371 }
01372 
01373 #endif
01374 
01375 int SctApi::pollHistogramming(boost::shared_ptr<ScanControl> controller, int timeout) {
01376   int returnVal = 0;
01377 
01378   bool timedout = false;
01379 
01380   time_t start_time = time(0);
01381 
01382   while(!timedout) {
01383     bool progressMade = false;
01384     bool newBin = false;
01385     if(controller->checkScanComplete(progressMade, newBin)) {
01386       // Finished, exit while
01387       break;
01388     }
01389 
01390     if(progressMade) {
01391       start_time = time(0);
01392     }
01393 
01394     if(newBin) {
01395       cout << "Controller going to next bin\n";
01396 
01397       controller->nextBin();
01398     } else {
01399       // Check text buffers (no longer a side effect of polling)
01400 #if USE_THREADS
01401       // Text buffers already checked by primThread
01402       sleep(1);
01403 #else
01404       awaitResponse(rod, 0);
01405 #endif
01406 
01407       if((time(0) - start_time) > timeout) {
01408         timedout = true;
01409         returnVal = -1;
01410 
01411         controller->reportTimeout();
01412         controller->reportEventErrors();
01413 
01414         break;
01415       }
01416     }
01417   }
01418 
01419 #if USE_IS
01420   if(m_isDict) {
01421     m_isDict->remove("SCTAPIServer.currentBin");
01422     m_isDict->remove("SCTAPIServer.maxBin");
01423   }
01424 #endif
01425 
01426   return returnVal;
01427 }
01428 
01429 void SctApi::doHistogramSetup(const Scan &scan, const ScanEx &extra) {
01430   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01431       ri != extra.rodInfo.end();
01432       ri++) {
01433     //    const RodScanEx &rodInfo = ri->second;
01434     const RodLabel &rod = ri->first;
01435 
01436     // Clear event memory on all slaves
01437     // 8192 words from what was 0x80008000
01438     for(int slaveNumber=0; slaveNumber<numSlaves; slaveNumber++) {
01439       if(getCrate()->slavePresent(rod.rod, slaveNumber)) {
01440         if(getCrate()->getRodRevision(rod.rod) >= 0xe) {
01441           setSlaveBlock(rod.rod, slaveNumber, 0x18000, 0x2000, 0);
01442         } else {
01443           setSlaveBlock(rod.rod, slaveNumber, 0x80008000, 0x2000, 0);
01444         }
01445       }
01446     }
01447 
01448     cout << "Setup event trapping...\n";
01449 
01450     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01451 
01452     setupEventTrapping(scan, extra, rod, primList);
01453     startEventTrapping(scan, extra, rod, primList);
01454 
01455     setupEventDump(scan, extra, rod, primList);
01456 
01457     if(checkDebugOption(DEBUG_EXTRA_DUMPS)) {
01458       standardRegisterDump(rod.rod);
01459 
01460       sendPrimList(rod.rod, primList);
01461       awaitResponse(rod.rod, 5);
01462 
01463       primList->clear(); // .reset(new PrimListWrapper(2));
01464     }
01465 
01466     cout << "Histogramming setup...\n";
01467 
01468     setupHistogramming(scan, extra, rod, scan.getOption(Scan::TIM), primList);
01469 
01470     // Wait for things to settle before starting histogramming
01471     sendPrimList(rod.rod, primList);
01472   }
01473 
01474   for(ScanEx::RodInfoMap::const_iterator ri = extra.rodInfo.begin();
01475       ri != extra.rodInfo.end();
01476       ri++) {
01477     //    const RodScanEx &rodInfo = ri->second;
01478     const RodLabel &rod = ri->first;
01479     int responseCode = awaitResponse(rod.rod, 5);
01480     if(responseCode != 0) {
01481       cout << "Histogram setup list failed! (ROD " << rod.rod << ")\n";
01482       throw SctApiException("Histogram setup list failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01483     }
01484   }
01485 }
01486 
01487 void ScanControlRODHisto::startHistogramming() {
01488   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01489       ri != scanEx->rodInfo.end();
01490       ri++) {
01491     const RodLabel &rod = ri->first;
01492 
01493     // Setup debug register
01494     if(scan->getOption(Scan::DEBUG)) {
01495       if(checkDebugOption(DEBUG_SCAN_AUTO_STALL)) {
01496         cout << "** Debug mode setting AUTO_STALL\n"; 
01497         scanEx->diagnosticReg |= (1<<DR_AUTO_STALL);
01498       }
01499 
01500       if(checkDebugOption(DEBUG_SCAN_STEP_MODE)) {
01501         cout << "** Debug mode setting STEP_CTRL\n"; 
01502         scanEx->diagnosticReg |= (1<<DR_STEP_CTRL);
01503       }
01504 
01505       if(checkDebugOption(DEBUG_SCAN_PAUSE_PULSE)) {
01506         cout << "** Debug mode setting PAUSE_PULSE\n"; 
01507         scanEx->diagnosticReg |= (1<<DR_PULSE_PAUSE);
01508       }
01509     }
01510 
01511     if(checkDebugOption(DEBUG_SCAN_ROD_MODE_BITS)) {
01512       cout << "Setting up to use ROD mode bits\n"; 
01513       scanEx->diagnosticReg |= (1<<DR_USE_ROD_MASK_LUT);
01514     }
01515 
01516     if(scanEx->diagnosticReg != 0x0) {
01517       cout << "Writing master diag reg: 0x" << hex << scanEx->diagnosticReg << dec << endl;
01518       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01519     } else {
01520       cout << "Clearing master diag reg\n";
01521       api.dspSingleWrite(rod.rod, 0x80000010, scanEx->diagnosticReg, -1);
01522     }
01523 
01524     if(checkDebugOption(DEBUG_SCAN_USE_ASSEMBLER)) {
01525       unsigned long SDSP_IDRAM_BASE;
01526       if(api.getRodRevision(rod) >= 0xe) {
01527         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
01528       } else {
01529         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
01530       }
01531 
01532       for(int s=0; s<numSlaves; s++) {
01533         if(ri->second.bitFieldDSP & (1<<s)) {
01534           try {
01535             unsigned long val = api.dspSingleBlockRead(rod.rod, 
01536                                                        SDSP_IDRAM_BASE + 0x10, s);
01537             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01538                  << " which should be 0x" << (0) << dec << endl;
01539 
01540             // Toggle cache on
01541             unsigned long newVal = val | (1<<19);
01542             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
01543 
01544             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
01545             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
01546                  << " which should be 0x" << (1<<19) << dec << endl;
01547           } catch(VmeException &v) {
01548             Utility::decodeVme(v);
01549             cerr << "VmeException turning on slave " << s << " cache\n";
01550           }
01551         }
01552       }
01553     }
01554 
01555     cout << "Histogram starting...\n";
01556 
01557     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01558     api.startHistogramTask(*scan, *scanEx, rod, 
01559                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
01560                            primList);
01561 
01562 //     {
01563 //       boost::mutex::scoped_lock lock(log().mutex());
01564 //       log() << "Send start histogram task list\n";
01565 //     }
01566     api.sendPrimList(rod.rod, primList);
01567     int responseCode = api.awaitResponse(rod.rod, 5);
01568 
01569     if(responseCode != 0) {
01570       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
01571       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01572     }
01573   }
01574 }
01575 
01576 void SctApi::eventTrapSetup(int slaveMask, int trapMatch, int trapMod, int trapRemain, bool tim, bool error,
01577                             boost::shared_ptr<PrimListWrapper> primList) {
01578   long *evData = new long[sizeof(EVENT_TRAP_SETUP_IN)/4];
01579 
01580   EVENT_TRAP_SETUP_IN &primData = *(EVENT_TRAP_SETUP_IN*)evData;
01581 
01582 #if R_EVENT_TRAP_SETUP == 103
01583   primData.slvBits = slaveMask;
01584   primData.numberOfEvents = COLLECT_FOREVER;
01585   primData.timeoutInUsec = 0x30000;
01586 
01587   primData.extRouterSetup = 0;
01588 
01589   // This tells the setup code to change the trapRemainder
01590   //  Only matters if setting up more than one slave
01591   primData.distribute = TRAP_DISTRIB_NEITHER;
01592 
01593   primData.releaseFrames = 0;
01594   if(tim) {
01595     primData.permitBackPressure = 0;
01596   } else {
01597     primData.permitBackPressure = 1;
01598   }
01599   primData.dataMode = 0;                        // Data or Event mode
01600   if(tim) {                           // Where to pick events (dsp or router)
01601     primData.sLink = 1;
01602   } else {
01603     primData.sLink = 0;
01604   }
01605 
01606   primData.format = error?TRAP_FMT_ERROR:TRAP_FMT_NORMAL; // Slink format
01607   primData.trapStray = 1;                       // Trap stray events
01608   primData.iterLimit = 2;                       // Don't keep them long
01609 
01610   if(tim) {
01611     // Trap events from the SLINK
01612     primData.trapConfig[0] = TRAP_CFG_SLINK_EVT;
01613   } else {
01614     // Trap events from ROD triggers
01615     primData.trapConfig[0] = TRAP_CFG_ROD_EVT;
01616   }
01617   primData.trapExclusionFlag[0] = 0;            // Don't exclude anything
01618   primData.trapFunction[0] = TRAP_FXN_HISTOGRAM;
01619 
01620   primData.trapMatch[0] = trapMatch;
01621   primData.trapModulus[0] = trapMod;
01622   primData.trapRemainder[0] = trapRemain;
01623 
01624   // Trap one is idle
01625   primData.trapConfig[1] = TRAP_CFG_IDLE;
01626   primData.trapExclusionFlag[1] = 0;
01627   primData.trapFunction[1] = 0;
01628 
01629   primData.trapMatch[1] = 0; 
01630   primData.trapModulus[1] = 0;
01631   primData.trapRemainder[1] = 0;
01632 #else 
01633 #error "Event trapping not compiled (new Primitive definition)!"
01634 #endif
01635   primList->addPrimitive(RodPrimitive(sizeof(EVENT_TRAP_SETUP_IN)/4 + 4, 
01636                                       0, EVENT_TRAP_SETUP, R_EVENT_TRAP_SETUP, evData),
01637                          evData);
01638 }
01639 
01640 void SctApi::startEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
01641   shared_ptr<PrimListWrapper> startList(new PrimListWrapper(1));
01642 
01643   PrimBuilder::instance().startEvTrap(startList);
01644 
01645   PrimBuilder::instance().slavePrimList(primList, startList, slaveNumber, true, true);
01646 }
01647 
01648 void SctApi::stopEventTrap(int slaveNumber, boost::shared_ptr<PrimListWrapper> primList) {
01649   shared_ptr<PrimListWrapper> stopList(new PrimListWrapper(1));
01650 
01651   PrimBuilder::instance().stopEvTrap(stopList);
01652 
01653   PrimBuilder::instance().slavePrimList(primList, stopList, slaveNumber, true, true);
01654 }
01655 
01656 // If this uses sendData then memory is stored internally so isn't leaked, otherwise it is!
01657 unsigned long *ScanControlRODHisto::getHistogramChunk(RodLabel rodLabel, int slaveNumber,
01658                                                       unsigned long offset, unsigned long size) {
01659   try {
01660     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
01661 
01662     Utility::MemoryBlock chunk;
01663     chunk = scanEx->histoMap[key];
01664     if(!chunk) {
01665       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, HISTOGRAM_DATA, slaveNumber);
01666 
01667       cout << "SendData returned " << chunkPos.first << " " << chunkPos.second << endl;
01668       cout << " need offset " << offset << " length " << size << endl;
01669 
01670       if(api.mrs) {
01671         // Something about getting lots of data
01672         *api.mrs << "SCAN_READOUT" << MRS_DIAGNOSTIC
01673                  << MRS_PARAM<float>("MWords", chunkPos.second/4e6)
01674                  << MRS_PARAM<int>("crate", rodLabel.crate)
01675                  << MRS_PARAM<int>("rod", rodLabel.rod)
01676                  << MRS_TEXT("Scan requested histogram readout") << ENDM;
01677       }
01678 
01679       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
01680                           slaveNumber, chunkPos.first, chunkPos.second/4);
01681       chunk = Utility::MemoryBlock(chunkPos.second/4, block);
01682 
01683       scanEx->histoMap[key] = chunk;
01684     }
01685 
01686     if((offset + size*4) > (chunk.size() * 4)) {
01687       cout << "Asked for chunk +" << offset << " length " << size << " in " << chunk.size() << "words (continuing)\n";
01688     }
01689 
01690     // Offset is in bytes
01691     return chunk.address() + (offset / 4);
01692   } catch(SctApiException &e) {
01693     unsigned long slaveAddress;
01694 
01695     if(api.getRodRevision(rodLabel) >= 0xe) {
01696       slaveAddress = 0xa00e2000;
01697     } else {
01698       slaveAddress = HISTOGRAM_DEFAULT_BASE;     // 0x20d2000;
01699     }
01700 
01701     return api.primReadSlaveDsp(rodLabel.rod, 
01702                                 slaveNumber, slaveAddress + offset, size);
01703   }
01704 }
01705 
01706 unsigned long *ScanControlRODHisto::getEventCountChunk(RodLabel rodLabel, int slaveNumber) {
01707   try {
01708     pair<RodLabel, int> key = make_pair(rodLabel, slaveNumber);
01709 
01710     Utility::MemoryBlock chunk = scanEx->evCountMap[key];
01711     if(!chunk) {
01712       pair<UINT32, UINT32> chunkPos = api.sendData(rodLabel.rod, BIN_DATA, slaveNumber);
01713 
01714       cout << "SendData bin returned " << chunkPos.first << " " << chunkPos.second << endl;
01715 
01716       unsigned long *block = api.primReadSlaveDsp(rodLabel.rod, 
01717                                                   slaveNumber, chunkPos.first, chunkPos.second);
01718       chunk = Utility::MemoryBlock(chunkPos.second, block);
01719 
01720       scanEx->evCountMap[key] = chunk;
01721     }
01722 
01723     return chunk.address();
01724   } catch(SctApiException &e) {
01725     return 0;
01726   }
01727 }
01728 
01729 
01730 ScanControlRODHisto::ScanControlRODHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControl(api), scan(aScan), scanEx(aScanEx), aborting(false) {
01731   int nBins = scan->getScanPoints1().size();
01732 
01733   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
01734 
01735   finalTrigger = trigPoints[nBins-1];
01736 
01737   finalBin = nBins - 1;
01738 
01739   UINT32 initialNTrigs = trigPoints[0];
01740 
01741   unsigned int i = 0;
01742   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs) 
01743     i++;
01744 
01745   // i is now the index of the first different point
01746   sectionStartBin = 0;
01747   sectionEndBin = i - 1;
01748   if(i==trigPoints.size()) {
01749     sectionEndTrigger = scan->getVariableTrigs()[i-1];
01750   } else {
01751     sectionEndTrigger = scan->getVariableTrigs()[i-1] - scan->getVariableTrigs()[i];
01752   }
01753   cout << "Final bin = " << finalBin << " trigger = " << finalTrigger << endl;
01754 
01755   cout << "Initial sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
01756 }
01757 
01758 void ScanControlRODHisto::initialisePolling() { 
01759   scanStart = time(0);
01760 
01761   cout << "Histogram polling started\n";
01762   // Let it get going so the bin counter gets reset
01763   sleep(1);
01764 
01765   cout << "Polling histogramming task\n";
01766   cout << "scan point count " << scan->getScanPoints1().size() << endl;
01767 
01768   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01769       ri != scanEx->rodInfo.end();
01770       ri++) {
01771     const RodLabel &rodLabel = ri->first;
01772 
01773     if(api.mrs) {
01774       *api.mrs << "POLL_ROD" << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
01775                << MRS_PARAM<int>("partition", rodLabel.partition)
01776                << MRS_PARAM<int>("crate", rodLabel.crate)
01777                << MRS_PARAM<int>("rod", rodLabel.rod)
01778                << MRS_PARAM<int>("run", scan->getRunNumber())
01779                << MRS_PARAM<int>("scan", scan->getScanNumber())
01780                << MRS_PARAM<int>("firstSlave", ri->second.firstSlave)
01781                << MRS_TEXT("ROD polling started")
01782                << ENDM;
01783     }
01784   }
01785 
01786 #if USE_IS
01787   if(api.m_isDict) {
01788     ISInfoInt binNumber(0);
01789     api.m_isDict->insert("SCTAPIServer.currentBin", binNumber);
01790 
01791     ISInfoInt maxNumber(finalBin);
01792     api.m_isDict->insert("SCTAPIServer.maxBin", maxNumber);
01793   }
01794 #endif
01795 }
01796 
01797 void ScanControlRODHisto::reportTimeout() {
01798   Sct::MultiMessageDebugStream m(true,false,true);
01799 
01800   m << "You are about to get the 'Scan aborted (histogramming stalled)' "
01801     <<"message.  Histogram polling timeout being reported in ["
01802     <<__FILE__<<"] at line ["<<__LINE__<<". This means that SctApi got bored waiting more than a few (search for the second argument of pollHistogramming in SctApiHisto.cxx) seconds for the results of the next bin to be sent back from the rod." ;
01803 
01804   RodLabel minROD;
01805   if(scanEx->rodInfo.size() > 0) {
01806     minROD = scanEx->rodInfo.begin()->first;
01807   }
01808 
01809   m << "Was expecting: finalBin=" << finalBin << ", finalTrigger=" << finalTrigger;
01810 
01811   // Find the ROD that stopped everything
01812   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01813       ri != scanEx->rodInfo.end();
01814       ri++) {
01815     const RodLabel &rodLabel = ri->first;
01816     cout << "   ROD (" << rodLabel.partition << ", " << rodLabel.crate << ", " << rodLabel.rod << "): ";
01817     cout << " Event " << lastEvent[rodLabel] << "    Bin " << lastBin[rodLabel] << "\n";
01818 
01819     if(lastEvent[rodLabel] < lastEvent[minROD]) {
01820       minROD = rodLabel;
01821     } else if(lastEvent[rodLabel] == lastEvent[minROD] && lastBin[rodLabel] < lastBin[minROD]) {
01822       minROD = rodLabel;
01823     }
01824   }
01825 
01826 
01827   m << ".  Problem was perhaps localised to "
01828     << "partition " << minROD.partition
01829     << "crate" << minROD.crate
01830     << "rod" << minROD.rod
01831     << "run" << scan->getRunNumber()
01832     << "scan"<< scan->getScanNumber()
01833     << "bin"<< lastBin[minROD]
01834     << "event"<< lastEvent[minROD];
01835 
01836   m.flush();
01837 
01838   if(api.mrs) {
01839     *api.mrs << "SCAN_ABORTED" << MRS_ERROR
01840              << MRS_PARAM<int>("partition", minROD.partition)
01841              << MRS_PARAM<int>("crate", minROD.crate)
01842              << MRS_PARAM<int>("rod", minROD.rod)
01843              << MRS_PARAM<int>("run", scan->getRunNumber())
01844              << MRS_PARAM<int>("scan", scan->getScanNumber())
01845              << MRS_PARAM<int>("bin", lastBin[minROD]) << MRS_PARAM<int>("event", lastEvent[minROD]) 
01846              << MRS_TEXT("Scan aborted (histogramming stalled)") << ENDM;
01847   }
01848 }
01849 
01850 void ScanControlRODHisto::nextBin() {
01851   // Fix ending variables if reached the end
01852   if(findNextSection()) {
01853     finalTrigger = sectionEndTrigger;
01854     finalBin = sectionEndBin;
01855     return;
01856   }
01857 
01858   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01859       ri != scanEx->rodInfo.end();
01860       ri++) {
01861     const RodLabel &rod = ri->first;
01862 
01863     cout << "New histogram control task...\n";
01864 
01865     boost::shared_ptr<PrimListWrapper> primList(new PrimListWrapper(1));
01866     api.startHistogramTask(*scan, *scanEx, rod, 
01867                            sectionStartBin, 1 + sectionEndBin - sectionStartBin, sectionEndTrigger, 
01868                            primList);
01869 
01870     api.sendPrimList(rod.rod, primList);
01871     int responseCode = api.awaitResponse(rod.rod, 5);
01872 
01873     if(responseCode != 0) {
01874       cout << "Histogram primitive failed! (ROD " << rod.rod << ")\n";
01875       throw SctApiException("Histogram primitive failed! (ROD " + boost::lexical_cast<string>(rod.rod) + ")");
01876     }
01877   }  
01878 }
01879 
01880 bool ScanControlRODHisto::findNextSection() {
01881   // Find next section to do
01882   Scan::TrigPoints trigPoints = scan->getVariableTrigs();
01883 
01884   unsigned int i = sectionEndBin + 1; // StartBin + 1;
01885 
01886   if(i==trigPoints.size()) {
01887     // Nothing more to do
01888     // If we're done, the previous section was last so don't overwrite the parameters
01889     return true;
01890   }
01891 
01892   UINT32 initialNTrigs = trigPoints[i];
01893 
01894   while(i<trigPoints.size() && trigPoints[i] >= initialNTrigs)
01895     i ++; 
01896 
01897   bool done = false;
01898 
01899   sectionStartBin = 0;
01900   sectionEndBin = i - 1;
01901 
01902   if(i == trigPoints.size()) {
01903     sectionEndTrigger = scan->getVariableTrigs()[i-1];
01904   } else {
01905     sectionEndTrigger = scan->getVariableTrigs()[i-1] - scan->getVariableTrigs()[i];
01906 
01907 //     sectionStartBin = i;
01908 //     sectionEndBin = trigPoints.size() - 1;
01909 //     sectionEndTrigger = scan->getVariableTrigs()[i] - completedTriggers[i];
01910   }
01911 
01912 #if 0 
01913   // The old way
01914   unsigned int i = sectionEndBin + 1;
01915   UINT32 initialNTrigs = trigPoints[i];
01916   while(i<trigPoints.size() && trigPoints[i] == initialNTrigs) 
01917     i++;
01918 
01919   sectionStartBin = sectionEndBin + 1;
01920   sectionEndBin = i - 1;
01921   sectionEndTrigger = scan->getVariableTrigs()[i-1];
01922 
01923   done = false;
01924 #endif
01925 
01926   cout << "Next sectionStartBin = " << sectionStartBin << " sectionEndBin = " << sectionEndBin << " sectionEndTrigger = " << sectionEndTrigger << endl;
01927 
01928   return done;
01929 }
01930 
01931 bool ScanControlRODHisto::checkScanComplete(bool &progressMade, bool &newBin) {
01932   if(aborting) {
01933     return true;
01934   }
01935 
01936   progressMade = false;
01937   newBin = false;
01938 
01939   bool result = true;
01940 
01941   int totalBin = 0;
01942 
01943   map<RodLabel, bool> rodNewBinMap;
01944 
01945   for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
01946       ri != scanEx->rodInfo.end();
01947       ri++) {
01948     const RodLabel &rodLabel = ri->first;
01949 
01950     bool rodNewBin = false;
01951 
01952     if(!checkScanCompleteROD(rodLabel, progressMade, rodNewBin, totalBin)) {
01953       result = false;
01954     }
01955 
01956     rodNewBinMap[rodLabel] = rodNewBin;
01957   }
01958 
01959   // Only do a "newBin" if all RODs agree
01960   newBin = true;  
01961   for(map<RodLabel, bool>::const_iterator mapIter = rodNewBinMap.begin();
01962       mapIter != rodNewBinMap.end();
01963       mapIter++) {
01964     if(mapIter->second == false) {
01965       newBin = false;
01966     } else {
01967       cout << "New bin requested by ROD (" << mapIter->first.partition << ", " << mapIter->first.crate << ", " << mapIter->first.rod << ")\n";
01968     }
01969   }
01970 
01971   if(progressMade) {
01972     int progressBin = totalBin / scanEx->rodInfo.size();
01973 
01974 #if USE_IS
01975     if(api.m_isDict) {
01976       ISInfoInt binNumber(progressBin);
01977       api.m_isDict->update("SCTAPIServer.currentBin", binNumber);
01978     }
01979 #endif
01980   }
01981 
01982   return result;
01983 }
01984 
01985 void ScanControlRODHisto::abort() {
01986   aborting = true;
01987 }
01988 
01989 #warning "32 bit version unreliable!!"
01990 unsigned int ScanControlRODHisto::getEventCounter(const RodLabel &rodLabel, int slave, bool fromMaster) {
01991   if(fromMaster) {
01992     // Use the event count copied from the slave to MDSP this is 16bit though!
01993     unsigned long reg = api.dspSingleRead(rodLabel.rod, 
01994                                           0x8000002c - (slave & 2) * 2, -1);
01995     unsigned int currEvent = (unsigned int) ((reg >> (16*(slave&1))) & 0xffff);
01996 
01997     return currEvent;
01998   } else {
01999     // Read 32bit version from slave (this is direct read of slave which is very bad!)
02000     unsigned long reg = api.dspSingleRead(rodLabel.rod, 
02001                                           0x8000002c, slave);
02002     return (unsigned int) reg;
02003   }
02004 }
02005 
02006 bool ScanControlRODHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
02007   int partition = rodLabel.partition;
02008   int crate = rodLabel.crate;
02009   int rod = rodLabel.rod;
02010 
02011   int currBin = 0;
02012   int currEvent = 0;
02013 
02014   // Read bin number from master dsp
02015   long reg = api.dspSingleRead(rod, 0x80000020, -1);
02016   currBin = (reg & 0xff);
02017 
02018   RodScanEx &rodInfo = scanEx->rodInfo[rodLabel];
02019 
02020   // Use the event count copied from the lowest slave with a module, this is 16bit though!
02021   currEvent = getEventCounter(rodLabel, rodInfo.firstSlave, true);
02022 
02023   if(currBin != lastBin[rodLabel]) {
02024     lastBin[rodLabel] = currBin;
02025     lastEvent[rodLabel] = currEvent;
02026     cout << "Next bin " << currBin << "+" << currEvent << " on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02027 
02028     progressMade = true;
02029   } else if(currEvent != lastEvent[rodLabel]) { 
02030     lastEvent[rodLabel] = currEvent;
02031     cout << "Next event " << currEvent << " (bin " << currBin << ") on ROD (" << partition << ", " << crate << ", " << rod << ")\n";
02032 
02033     progressMade = true;
02034   }
02035 
02036   totalBin += currBin;
02037 
02038   // End of current section
02039   if(currBin == sectionEndBin && currEvent == sectionEndTrigger) {
02040     // Probably got to the end...
02041     newBin = true;
02042 
02043     // Check all the DSPs involved
02044     for(int s=0; s<4; s++) {
02045       if(rodInfo.bitFieldDSP & (1<<s)) {
02046         int slaveEvent = getEventCounter(rodLabel, s, true);
02047         // Actually this one not finished yet
02048         if(slaveEvent != sectionEndTrigger) {
02049           cout << " Slave " << s << " completed only " << slaveEvent << "/" << sectionEndTrigger << " triggers\n";
02050           newBin = false;
02051         }
02052       }
02053     }
02054   } else if(currBin == sectionEndBin && currEvent == (sectionEndTrigger%65536)) {
02055     // Should check trigger count on slave (not 16bit?)
02056 
02057     // If progress was made we'll wait for the next iteration
02058     if(!progressMade) {
02059       // Otherwise its most likely finished properly...
02060       newBin = true;
02061     }
02062   }
02063 
02064   if(((currBin == finalBin) && (currEvent == finalTrigger))
02065      || ((currBin == finalBin) && (currEvent == (finalTrigger%65536)) && !progressMade)) {
02066 
02067     // Fix lastEvent in the case it's incorrect due to 16bitness
02068     lastEvent[rodLabel] = finalTrigger;
02069 
02070     // Should only print this out once (may get called multiple times if multiple RODs take different amounts of time to complete
02071     if(api.mrs) {
02072       *api.mrs << "HISTO_SUCCESS" << MRS_DIAGNOSTIC << MRS_QUALIF("SCTAPI") 
02073                << MRS_PARAM<int>("partition", rodLabel.partition)
02074                << MRS_PARAM<int>("crate", rodLabel.crate)
02075                << MRS_PARAM<int>("rod", rodLabel.rod)
02076                << MRS_TEXT("Histogramming successfully complete")
02077                << ENDM;
02078     }
02079 
02080     cout << "Histogramming completed successfully\n";
02081 
02082     return true;
02083   }
02084 
02085   return false;
02086 }
02087 
02088 void ScanControlRODHisto::finishHistogram(bool success) { 
02089   time_t scanEnd = time(0);
02090 
02091   scan->setEndTime(second_clock::universal_time());
02092 
02093   if(checkDebugOption(DEBUG_SCAN_USE_ASSEMBLER)) {
02094     for(ScanEx::RodInfoMap::const_iterator ri = scanEx->rodInfo.begin();
02095         ri != scanEx->rodInfo.end();
02096         ri++) {
02097       const RodLabel &rod = ri->first;
02098       const RodScanEx &rodInfo = ri->second;
02099 
02100       unsigned long SDSP_IDRAM_BASE;
02101       if(api.getRodRevision(rod) >= 0xe) {
02102         SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02103       } else {
02104         SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02105       }
02106 
02107       for(int s=0; s<numSlaves; s++) {
02108         if(rodInfo.bitFieldDSP & (1<<s)) {
02109           try {
02110             unsigned long val = api.dspSingleBlockRead(rod.rod, 
02111                                                        SDSP_IDRAM_BASE + 0x10, s);
02112             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02113                  << " which should be 0x" << (1<<19) << dec << endl;
02114 
02115             // Flush cache
02116             unsigned long newVal = val | 1<<17;
02117             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02118             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02119             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02120                  << " which should be 0x" << (1<<17) << endl;
02121 
02122             // Turn off flush and cache
02123             newVal = val | 1<<19;
02124             api.dspSingleBlockWrite(rod.rod, SDSP_IDRAM_BASE + 0x10, newVal, s);
02125             val = api.dspSingleBlockRead(rod.rod, SDSP_IDRAM_BASE + 0x10, s);
02126             cout << "Read from slave " << s << " diag register: 0x" << hex << val 
02127                  << " which should be 0x" << (0) << endl;
02128           } catch(VmeException &v) {
02129             Utility::decodeVme(v);
02130             cerr << "VmeException turning off slave " << s << " cache\n";
02131           }
02132         }
02133       }
02134     }
02135   }
02136 
02137   // Read out if successful (even in debug mode!)
02138   //  but don't readout in debug mode if polling failed
02139   if(!scan->getOption(Scan::DEBUG) || success == true) {
02140     if(api.mrs) {
02141       *api.mrs << "SCAN_FINISHED" << MRS_INFORMATION 
02142                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02143                << MRS_TEXT("Scan finished") 
02144                << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02145                << MRS_PARAM<int>("ScanType1", scan->getScanVariable1())
02146                << MRS_PARAM<int>("ScanType2", scan->getScanVariable2())
02147                << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02148                << ENDM;
02149     }
02150 
02151     cout << "Histogramming complete, " << (scanEnd - scanStart) << " seconds, tidying up...\n";
02152 //     {
02153 //       boost::mutex::scoped_lock lock(log().mutex());
02154 //       log() << "Histogramming complete, " << (scanEnd - scanStart) << " seconds\n";
02155 //     }
02156 
02157     cout << "Reading histograms...\n";
02158 
02159     readHistograms();
02160 
02161     cout << "... histograms read\n";
02162   } else {
02163     if(!scan->getOption(Scan::DEBUG)) {
02164       cout << "Histogram polling failed\n";
02165 
02166       if(api.mrs) {
02167         *api.mrs << "SCAN_FAILED" << MRS_INFORMATION 
02168                  << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02169                  << MRS_TEXT("Scan polling failed") 
02170                  << MRS_PARAM<int>("ScanNumber", scan->getScanNumber())
02171                  << MRS_PARAM<int>("ScanTime", scanEnd - scanStart)
02172                  << ENDM;
02173       }
02174     }
02175   }
02176 
02177   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02178     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02179 
02180     api.print_calib(zeroRod.rod);
02181   }
02182 
02183   if(!scan->getOption(Scan::DEBUG)) {
02184     api.stopHistogramming(*scanEx);
02185 
02186     // Only restore module config if not debug mode
02187     postScanModuleSetup();
02188   } else {
02189     if(api.mrs) {
02190       *api.mrs << "SCAN_DEBUG" << MRS_INFORMATION 
02191                << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doScan") 
02192                << MRS_TEXT("Scan done in debug mode, probably best to be at the command line to sort it out!") 
02193                << ENDM;
02194     }
02195 
02196     cout << "** In debug mode, you're responsible for terminating histogram and for readout\n";
02197   }
02198 
02199   if(checkDebugOption(DEBUG_PRINT_CALIB)) {
02200     RodLabel zeroRod = scanEx->rodInfo.begin()->first;
02201 
02202     api.print_calib(zeroRod.rod);
02203   }
02204 
02205   // This should now have been updated with the modules in the scan
02206   scan->print();
02207   
02208 #if USE_IS
02209   if(api.m_isDict) 
02210     api.m_isDict->remove(api.idiosyncrasy().infoServiceNameOfScanStatusObject());
02211 #endif
02212 
02213   if(api.mrs)
02214     *api.mrs << "SCAN_COMPLETE" << MRS_INFORMATION << MRS_QUALIF("SctApi") << MRS_TEXT("Scan has completed") << ENDM;
02215 }
02216 
02217 void ScanControlRODHisto::postScanModuleSetup() {
02218   PrimBuilder &builder = PrimBuilder::instance();
02219 
02220   if(scan->getScanVariable1() == ST_TOKEN
02221      || scan->getScanVariable1() == ST_BYPASS) {
02222     // Restore chip sequence check in EFB
02223     shared_ptr<PrimListWrapper> chipSeqList(new PrimListWrapper(1));
02224     for(int i=0; i<48; i++) {
02225       builder.writeRegister(chipSeqList, ERROR_MASK(0, i), 10, 1, 0);
02226       builder.writeRegister(chipSeqList, ERROR_MASK(1, i), 10, 1, 0);
02227     }
02228 
02229     if(api.synchSendPrimListAllCrates(chipSeqList)) {
02230       cout << "Chip sequence error list failed!\n";
02231     }
02232 
02233     cout << "EFB chip sequence detection turned back on\n";
02234   }
02235 
02236   // Restore checks cancelled for double triggers which aren't supported by DSP code
02237   {
02238     Trigger::RODTriggers points = scan->getTrigger1()->getRODTriggers();
02239 
02240     int triggerCount = 0;
02241 
02242     for(unsigned int i=0; i<points.size(); i++) {
02243       // Count triggers
02244       if(points[i].first == L1_TRIGGER) {
02245         triggerCount++;
02246       }
02247     }
02248 
02249     // Double triggers... none of current options will cope...
02250     if(triggerCount > 1 && scan->getOption(Scan::DISTSLAVE) < 3) {
02251       shared_ptr<PrimListWrapper> dblIdCheckList(new PrimListWrapper(1));
02252 
02253       // Restore L1 and BCID checks
02254       for(int f=0; f<48; f++) {
02255         // L1ID
02256         //builder.writeRegister(dblIdCheckList, ERROR_MASK(0, f), 5, 1, 0);
02257         //builder.writeRegister(dblIdCheckList, ERROR_MASK(1, f), 5, 1, 0);
02258 
02259         // BCID
02260         //builder.writeRegister(dblIdCheckList, ERROR_MASK(0, f), 6, 1, 0);
02261         //builder.writeRegister(dblIdCheckList, ERROR_MASK(1, f), 6, 1, 0);
02262       }
02263 
02264       if(api.synchSendPrimListAllCrates(dblIdCheckList)) {
02265         cout << "Double trigger BC check list failed!\n";
02266       }
02267 
02268       cout << "L1 and BCID checks restored after double triggers\n";
02269     }
02270   }
02271 
02272   //    getABCDModules(SCTAPI_BANK_PHYSICS);
02273   //    sendAllABCDModules(SCTAPI_BANK_PHYSICS);
02274 }
02275 
02276 bool ScanControlRODHisto::checkDebugOption(int opt) {
02277   return Debug::getInstance()->checkDebugOption((DebugOptions)opt);
02278 }
02279 
02280 void ScanControlRODHisto::reportEventErrors() {
02281   api.reportEventErrors();
02282 }
02283 
02284 unsigned int ScanControlRODHisto::getProcTime(const RodLabel rlabel, int dsp) {
02285   if(dsp == -1) {
02286     throw SctApiException("Can't getProcTime on MDSP");
02287   } else {
02288     int procTime;
02289 
02290     unsigned long SDSP_IDRAM_BASE;
02291     if(api.getRodRevision(rlabel) >= 0xe) {
02292       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02293     } else {
02294       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02295     }
02296 
02297     unsigned long length;
02298     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02299                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02300 
02301     if(regs) {
02302       long reg;
02303 
02304       // H stat reg 0
02305       reg = regs[6];
02306       procTime = ((reg >> 16) & 0xffff);
02307     } else {
02308       throw SctApiException("Failed to read getProcTime from DSP");
02309     }
02310 
02311     return procTime;
02312   }
02313 }
02314 
02315 ScanControlRODHisto::TrapBuffers ScanControlRODHisto::getTrapBuffers(const RodLabel rlabel, int dsp) {
02316   if(dsp == -1) {
02317     throw SctApiException("Invaled dsp passed to getTrapBuffers");
02318   } else {
02319     int ihead, itail, xhead, xtail;
02320 
02321     unsigned long SDSP_IDRAM_BASE;
02322     if(api.getRodRevision(rlabel) >= 0xe) {
02323       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02324     } else {
02325       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02326     }
02327 
02328     unsigned long length;
02329     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02330                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02331 
02332     if(regs) {
02333       long reg;
02334 
02335       // Trap stat 1
02336       reg = regs[1];
02337       itail = ((reg & 0xff0000) >> 16);
02338       xtail = ((reg & 0xff000000) >> 24);
02339 
02340       // Trap stat 1
02341       reg = regs[2];
02342       ihead = ((reg & 0xff0000) >> 16);
02343       xhead = ((reg & 0xff000000) >> 24);
02344     } else {
02345       throw SctApiException("Failed to read DSP for getTrapBuffers");
02346     }
02347 
02348     return make_pair(make_pair(ihead, itail), make_pair(xhead, xtail));
02349   }
02350 }
02351 
02352 void ScanControlRODHisto::dumpHistoStatus(const RodLabel rlabel, int dsp) {
02353   if(dsp == -1) {
02354     const unsigned long MDSP_IDRAM_BASE = 0x80000000;
02355 
02356     // Histogram command stat 0
02357     long reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x20, -1);
02358     cout << "Bin: " << (reg & 0xff) 
02359          << " Cal: " << ((reg & 0xff00) >> 8) 
02360          << " Errs: " << ((reg & 0xffff0000) >> 16) << endl;
02361 
02362     // Histogram command stat 1
02363     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x24, -1);
02364     cout << "avg. trans " << (reg & 0xff)
02365          << " avg. len " << ((reg & 0xff00) >> 8)
02366          << " avg. proc. " << ((reg & 0xffff0000) >> 16) << endl;
02367 
02368     // Histogram status 1
02369     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x2c, -1);
02370     cout << "Slave 0: " << (reg & 0xffff)
02371          << " Slave 1: " << ((reg & 0xffff0000) >> 16) << endl;
02372 
02373     // Histogram status 0
02374     reg = api.dspSingleRead(0, MDSP_IDRAM_BASE + 0x28, -1);
02375     cout << "Slave 2: " << (reg & 0xffff)
02376          << " Slave 3: " << ((reg & 0xffff0000) >> 16) << endl;
02377   } else {
02378     unsigned long SDSP_IDRAM_BASE;
02379     if(api.getRodRevision(rlabel) >= 0xe) {
02380       SDSP_IDRAM_BASE = 0x10000;        // Rev E or F
02381     } else {
02382       SDSP_IDRAM_BASE = 0x80000000;     // Rev C
02383     }
02384 
02385     unsigned long length;
02386     unsigned long *regs = api.dspBlockRead(rlabel.rod, 
02387                                            SDSP_IDRAM_BASE + 0x10, 20, dsp, length);
02388 
02389     if(regs) {
02390       long reg;
02391 
02392       cout << "TrapStatus: \n";
02393 
02394 
02395       // Trap stat 0
02396       reg = regs[1];
02397       int words = ((reg &0xffff) >> 0);
02398       int itail = ((reg & 0xff0000) >> 16);
02399       int xtail = ((reg & 0xff000000) >> 24);
02400 
02401       cout << "Event word count: " << words;
02402       cout << " IFrame tail: " << itail;
02403       cout << " XFrame tail: " << xtail << endl;
02404 
02405       // Trap stat 1
02406       reg = regs[2];
02407       int ihead = ((reg & 0xff0000) >> 16);
02408       int xhead = ((reg & 0xff000000) >> 24);
02409       cout << " IFrame head: " << ihead;
02410       cout << " XFrame head: " << xhead << endl;
02411 
02412       // Trap cmd stat
02413       reg = regs[17];
02414       cout << "Trap Command/Status: " 
02415            << ((reg & 0x1)?"Trailer ":"")            // TCSR_TRAILER
02416            << ((reg & 0x2)?"Transmit ":"")
02417            << ((reg & 0x4)?"Header ":"")
02418            << ((reg & 0x4)?"ISR active ":"");
02419       cout << ((reg & 0x10)?"\"Data Error\" ":"")
02420            << ((reg & 0x20)?"\"Header Error\" ":"")
02421            << ((reg & 0x40)?"\"Trailer Error\" ":"")
02422            << ((reg & 0x80)?"\"Link Error\" ":"");
02423       cout << ((reg & 0x100)?"\"Error\" ":"")
02424            << ((reg & 0x200)?"\"Overflow(old)\" ":"")
02425            << ((reg & 0x800)?"\"ISR pending\" ":"");
02426       cout << ((reg & 0x4000)?"\"Overflow error\" ":"")
02427            << ((reg & 0x8000)?"\"Overflow\" ":"");
02428       cout << endl;
02429 
02430       int errCount = ((reg >> 16) & 0xff);
02431       cout << "\"Error count\": " << errCount << endl;
02432       int evCount = ((reg >> 24) & 0xff);
02433       cout << "\"Event count\": " << evCount << endl;
02434 
02435       // Hcmd stat reg 0
02436       reg = regs[4];
02437       int currentBin = (reg & 0xff);
02438       cout << "Bin: " << currentBin
02439            << " Cal: " << ((reg & 0x1f00) >> 8) 
02440            << ((reg & 0x800)?" Cal enabled":"")
02441            << ((reg & 0x1000)?" New bin":"")
02442            << ((reg & 0x20000)?" New cal":"") << endl;
02443 
02444       // Hcmd stat reg 1
02445       reg = regs[5];
02446       int numEvents = reg;
02447       cout << "Num events: " << numEvents << endl;
02448 
02449       // H stat reg 0
02450       reg = regs[6];
02451       cout << "Histogram status: 0x" << hex << (reg & 0xffff) << dec << " " << ((reg & 0x1)?"Ready ":"")
02452            << ((reg & 0x2)?"Expecting ":"")
02453            << ((reg & 0x4)?"Processing ":"")
02454            << ((reg & 0x8)?"Done ":"") << endl;
02455 
02456       int procTime = ((reg >> 16) & 0xffff);
02457       cout << "Bin err: " << ((reg >> 8) & 0xff) 
02458            << " proc time: " << ((reg >> 16) & 0xffff) << endl;
02459 
02460       // H stat reg 1
02461       reg = regs[7];
02462       int evRecvd = reg;
02463       cout << "Events recvd: " << evRecvd << endl;
02464 
02465       ofstream statusOut("TIMStatus.txt", ios_base::out | ios_base::app);
02466       statusOut << currentBin << "\t" 
02467                 << ihead  << "\t" << itail << "\t" 
02468                 << xhead << "\t" << xtail << "\t"
02469                 << errCount << "\t" << evCount << "\t" 
02470                 << evRecvd << "\t" << words << "\t" << procTime << endl;
02471     }
02472   }
02473 }
02474 
02475 ScanControlTIMHisto::ScanControlTIMHisto(SctApi &api, boost::shared_ptr<Scan> aScan, boost::shared_ptr<ScanEx> aScanEx) : ScanControlRODHisto(api, aScan, aScanEx), binCount(0) {
02476 }
02477 
02478 void ScanControlTIMHisto::startHistogramming() {
02479   // Set BCID offset to 3
02480   api.timWriteRegister(0x14, 0x3000);
02481 
02482   shared_ptr<PrimListWrapper> preTimList(new PrimListWrapper(4));
02483   PrimBuilder::instance().rodMode(preTimList, DATA_TAKING_MODE, 0, 1, 0, 0, 1); 
02484 
02485   PrimBuilder::instance().writeRegister(preTimList, RTR_CMND_STAT, 7, 1, 1);   // Mask LDown#
02486 
02487   for(int f=0; f<8; f++) {
02488 //     //    PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0xaaaa);   // Decrement L1 for check
02489 //     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x5555);   // Increment L1 for check
02490     PrimBuilder::instance().writeRegister(preTimList, DM_DFLT_LUT(f), 0, 16, 0x0);   // Clear L1 inc
02491   }
02492 
02493 //   for(int ch=0; ch<48; ch++) {
02494 //     PrimBuilder::instance().writeRegister(preTimList, ERROR_MASK(0, ch), 5, 1, 1);  // Mask L1ID check
02495 //     PrimBuilder::instance().writeRegister(preTimList, ERROR_MASK(1, ch), 5, 1, 1);  // Mask L1ID check
02496 
02497 //     PrimBuilder::instance().writeRegister(preTimList, ERROR_MASK(0, ch), 6, 1, 1);  // Mask BCID check
02498 //     PrimBuilder::instance().writeRegister(preTimList, ERROR_MASK(1, ch), 6, 1, 1);  // Mask BCID check
02499 //   }
02500 
02501   cout << "Sending pre TIM setup list\n";
02502   api.synchSendPrimListAllCrates(preTimList);
02503   cout << " done sending pre TIM setup list\n";
02504 
02505   hex(cout);
02506   cout << "0x" << RTR_CMND_STAT << ": 0x" << api.readRODRegister(0, RTR_CMND_STAT) << endl;
02507   cout << "0x" << ERROR_MASK(0, 0) << ": 0x" << api.readRODRegister(0, ERROR_MASK(0, 0)) << endl;
02508   cout << "0x" << ERROR_MASK(1, 0) << ": 0x" << api.readRODRegister(0, ERROR_MASK(1, 0)) << endl;
02509   cout << "0x" << DM_DFLT_LUT(0) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(0)) << endl;
02510   cout << "0x" << DM_DFLT_LUT(1) << ": 0x" << api.readRODRegister(0, DM_DFLT_LUT(1)) << endl;
02511   dec(cout);
02512 
02513   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
02514     // This is added to by dumpHistoStatus
02515     ofstream statusOut("TIMStatus.txt");
02516     statusOut << "bin\tihead\titail\txhead\txtail\terrCnt\tevCount\tevRecvd\twords\tprocTime\n";
02517   }
02518 }
02519 
02520 void ScanControlTIMHisto::nextBin() {
02521   cout << "TIM histo, next bin\n";
02522 
02523   std::list<BankType> banks;
02524   banks.push_back(SCTAPI_BANK_SCAN);
02525   
02526   api.modifyABCDVarROD(scan->getScanVariable1(), scan->getScanPoints1()[binCount], banks);
02527 
02528   // AJB add this?
02529   //if (!ConfigUtility::isBOCRegister(scan->getScanVariable1())) 
02530   api.sendAllABCDModules(SCTAPI_BANK_SCAN);
02531   
02532   // SET_TRIGGER (ie tell histograms about next bin)
02533   shared_ptr<PrimListWrapper> setTriggerList(new PrimListWrapper(4));
02534   PrimBuilder::instance().setTrigger(setTriggerList, binCount, Utility::translateBank(SCTAPI_BANK_SCAN));
02535 
02536   shared_ptr<PrimListWrapper> binTimList(new PrimListWrapper(4));
02537 
02538   // Send to all slaves
02539   for(int s=0; s<4; s++) {
02540     PrimBuilder::instance().slavePrimList(binTimList, setTriggerList, 
02541                                           s, 1, 0);
02542   }
02543 
02544   // 0x20000 should be DATA_TAKING_MODE
02545   PrimBuilder::instance().rodMode(binTimList, 0x20000, 0, 1, 0, 0, 1); 
02546   PrimBuilder::instance().writeRegister(binTimList, RTR_CMND_STAT, 7, 1, 1);   // Mask LDown#
02547 
02548   cout << "Sending TIM setup list\n";
02549   api.synchSendPrimListAllCrates(binTimList);
02550   cout << " done sending TIM setup list\n";
02551 
02552   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
02553     cout << "******************* Pre triggers status ********************\n";
02554     dumpHistoStatus(RodLabel(), 0);
02555   }
02556 
02557   api.timSoftReset();
02558   api.timBCReset();
02559 
02560   Scan::TrigPoints trigs = scan->getVariableTrigs();
02561 
02562   cout << "Sending " << trigs[binCount] << " triggers to one crate " << endl;
02563 
02564   switch(scan->getOption(Scan::TIM)) {
02565   case 1:
02566     // Just send lots of triggers, relies on user to set up frequency/nth appropriately
02567     api.sendTimBurst(trigs[binCount]);
02568     break;
02569   case 2:
02570 #warning "Assumes ROD 0!!!"
02571     // Send one trigger at a time, then wait maximum of 1 second for trap buffers to equalize
02572     for(unsigned int i=0; i<trigs[binCount]; i++) {
02573       api.timL1A();
02574 
02575       TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
02576 
02577       if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
02578         sleep(1);
02579     }
02580     break;
02581   case 3:
02582 #warning "Assumes ROD 0!!!"
02583     // Send in bursts of triggers, wait for them to finish
02584     // Designed to be run at 100kHz
02585     {
02586       unsigned int sentTriggers = 0;
02587       const unsigned int trigsPerBurst = 20;
02588 
02589       while(sentTriggers < trigs[binCount]) {
02590         if(sentTriggers % 1000 < trigsPerBurst) {
02591           cout << "Done " << sentTriggers << " triggers\n";
02592           if(checkDebugOption(DEBUG_TIM_SCAN_STATUS))
02593              dumpHistoStatus(RodLabel(), 0);
02594         }
02595         int ntrigs = min(trigs[binCount]-sentTriggers, trigsPerBurst);
02596         api.sendTimBurst(ntrigs);
02597         sentTriggers += ntrigs;
02598 
02599         // Have they been processed yet?
02600         TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
02601 
02602         TrapBuffers oldtb;
02603         if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
02604           do {
02605             oldtb = tb;
02606             usleep(trigsPerBurst * 10);  // 7 * 10us at 100kHz 
02607             tb = getTrapBuffers(RodLabel(), 0);
02608 
02609             if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
02610             if(tb == oldtb) break;
02611           } while(1); 
02612       }
02613     }
02614     break;
02615   case 4:
02616 #warning "Assumes ROD 0!!!"
02617     // Adjust frequency depending on how long the previous set of triggers 
02618     //  takes to histogram, first 1 then 10 then the rest.
02619     {
02620       unsigned int sentTriggers = 0;
02621 
02622       api.timL1A();
02623       sentTriggers ++;
02624 
02625 //   // Set 100kHz triggers
02626 //   api.timSetFrequency(100, 0);
02627 
02628       unsigned int procTime = getProcTime(RodLabel(), 0);
02629       double timFrequency = 0.25 * 1e6/procTime;
02630       // Don't go faster than 6kHz
02631       api.timSetFrequency(min(6.0, timFrequency/1000), 0);
02632 
02633       cout << "*** Proc Time for 1 trigger was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
02634 
02635       procTime = getProcTime(RodLabel(), 0);
02636       timFrequency = 0.25 * 1e6/procTime;
02637       api.timSetFrequency(min(6.0, timFrequency/1000), 0);
02638 
02639       cout << "*** Proc Time after 10 trigs was " << procTime << " setting frequency to " << timFrequency << "Hz\n";
02640 
02641       if(trigs[binCount] > sentTriggers)
02642         api.sendTimBurst(trigs[binCount]-sentTriggers);
02643 
02644       if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
02645         cout << "******************* Post triggers status ********************\n";
02646         dumpHistoStatus(RodLabel(), 0);
02647       }
02648 
02649       TrapBuffers tb = getTrapBuffers(RodLabel(), 0);
02650 
02651       TrapBuffers oldtb;
02652       if (!(tb.first.first == tb.first.second && tb.second.first == tb.second.second))
02653         do {
02654           oldtb = tb;
02655           sleep(1);
02656           tb = getTrapBuffers(RodLabel(), 0);
02657 
02658           if(tb.first.first == tb.first.second && tb.second.first == tb.second.second) break;
02659           if(tb == oldtb) break;
02660         } while(1); 
02661       break;
02662     }
02663   } // End switch on TIM histogramming types
02664 
02665   if(checkDebugOption(DEBUG_TIM_SCAN_STATUS)) {
02666     cout << "******************* Post triggers status 2 ******************\n";
02667     dumpHistoStatus(RodLabel(), 0);
02668   }
02669 
02670   //  TTrigger soft;
02671   //soft.softL1A(30);
02672 
02673   //  api.timL1A();
02674 
02675   binCount ++;
02676 }
02677 
02678 // TIM histos don't run Histo Control so event counters not mirrored to master
02679 // A sort of dummy function at the moment...
02680 bool ScanControlTIMHisto::checkScanCompleteROD(const RodLabel &rodLabel, bool &progressMade, bool &newBin, int &totalBin) {
02681 
02682   cout << "Checking TIM scan complete\n";
02683 
02684   progressMade = true;
02685 
02686   // If the triggers are sent synchronously in newBin then they must be done...
02687   newBin = true;
02688 
02689   totalBin += binCount-1;
02690 
02691   //  cout << "Are we at the end: " << (binCount-1) << " " << finalBin << endl;
02692 
02693   if((binCount-1 >= finalBin)) {
02694     return true;
02695   }
02696 
02697   return false;
02698 }
02699 
02700 // bool ScanControlTIMHisto::checkScanComplete(bool &progressMade) {
02701 //   return false;
02702 // }
02703 
02704 }

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