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

Generated on Thu Feb 3 17:37:42 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5