SctApiRaw.cxx

00001 
00009 #include <algorithm>
00010 
00011 #include <unistd.h>
00012 #include <sys/stat.h>   // mkdir etc
00013 #include <sys/types.h>
00014 
00015 #include "primListWrapper.h"
00016 #include "PrimBuilder.h"
00017 #include "sctConf/configuration.h"
00018 #include "SctApi.h"
00019 #include "SctApiDebug.h"
00020 #include "crate.h"
00021 #include "ScanResultWriter/scan.h"
00022 #include "utility.h"
00023 #include "Trigger.h"
00024 
00025 #include "SctApiHisto.h" // For histogramming helper functions 
00026 
00027 #ifdef USE_IS
00028 #include <is/infoT.h>
00029 #include "Sct/IoExceptions.h"
00030 #include "ScanResultWriter/ScanResultWriter.h"
00031 #endif
00032 
00033 #include "Sct/SctNames.h"
00034 
00035 #include "CommonWithDsp/primParams.h"
00036 #include "CommonWithDsp/registerIndices.h"
00037 
00038 #include "Scan.h"
00039 #include "SctApiException.h"
00040 #include "Idiosyncrasy.h"
00041 
00042 #include <boost/date_time/posix_time/posix_time.hpp>
00043 #include <boost/bind.hpp>
00044 
00045 using namespace std;
00046 using namespace SctConfiguration;
00047 using namespace boost::posix_time;
00048 
00049 namespace SctApi {
00050 
00051 int SctApi::setupRawData(unsigned int rod, 
00052                          int delay, int units, bool setMask, const Trigger *trig) {
00053   int success = 1;
00054 
00055   PrimBuilder &builder = PrimBuilder::instance();
00056 
00057 #if (R_SET_ROD_MODE < 101)
00058 #error "Old form (update primParams.h)"
00059 #else
00060 
00061   boost::shared_ptr<PrimListWrapper> setupList(new PrimListWrapper(2));
00062 
00063   // Configuration readback requires bit 19 of RRIF_CMND to be set to "trigger" the capture
00064   rodMode(rod, CALIBRATION_MODE + INMEM_EVT_CAPTURE_MODE, 0, 1, units+1, delay, 0);
00065 
00066   // Disable formatters (after ROD mode, which would reenable them...)
00067   for(int i=0; i<8; i++) {
00068     builder.writeRegister(setupList, FMT_LINK_EN(i), 0, 12, 0x0);
00069   }
00070 
00071 //   // Enable FE Command Outputs with SP0
00072 //   builder.writeRegister(0x1c7, 0, 2, 0x1, setupList);
00073 
00074 #ifdef funny 
00075   if(setMask) {
00076     // Set masks
00077     builder.writeRegister(setupList, FE_CMND_MASK_0_LO, 0, 32, 0xffffffff);
00078     builder.writeRegister(setupList, FE_CMND_MASK_0_HI, 0, 16, 0xffff);
00079     builder.writeRegister(setupList, FE_CMND_MASK_1_LO, 0, 32, 0xffffffff);
00080     builder.writeRegister(setupList, FE_CMND_MASK_1_HI, 0, 16, 0xffff);
00081 
00082     // Load enable?
00083 //   builder.writeRegister(setupList, RRIF_CMND_1, 20, 1, 0x1);
00084     // Load masks
00085     builder.writeRegister(setupList, RRIF_CMND_1, 2, 1, 0x1);
00086   }
00087 #endif
00088 
00089   sendPrimList(rod, setupList);
00090   int responseCode = awaitResponse(rod, 10);
00091   if(responseCode == 0) {
00092     // Do something that might trigger a response
00093     if(trig) {
00094       sendRodTrigger(rod, trig, 1);
00095     } else {
00096       sendL1A(rod);
00097     }
00098 
00099 //   // Set MUX to read out
00100 //   writeRODRegister(rod, 0x1c7, 25, 3, 0x1);
00101 
00102   // Leave formatters disabled, will be enabled by next scan
00103 
00104 //   // Enable formatters
00105 //   for(int i=0; i<12; i++) {
00106 //     builder.writeRegister(0x0 + i, 0, 12, 0x1, setupList);
00107 //   }
00108   } else {
00109     success = 0;
00110   }
00111 #endif
00112 
00113   return success;
00114 }
00115 
00116 void SctApi::dumpRawEvent(unsigned int rod, int units, 
00117                           unsigned long *bufferA, unsigned long *bufferB) {
00118   static int captureCount = 0;
00119 
00120   cout << "Dumping RAW FIFOs to file, count " << captureCount << endl;
00121 
00122   string dirName = Sct::SctNames::getTempDir() + "/Captures";
00123 
00124   // Ignore success (0) or failure
00125   mkdir(dirName.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
00126   
00127   char *saveDir = getcwd(NULL, 0);
00128   chdir(dirName.c_str());
00129 
00130   char fileName[100];
00131   sprintf(fileName, "RawCaptureA_%05d.bin", captureCount);
00132 
00133   ofstream foutA(fileName, ios::binary | ios::trunc);
00134   foutA.write((char*)&bufferA[0], units*4);
00135 
00136   // Only increment second time
00137   sprintf(fileName, "RawCaptureB_%05d.bin", captureCount++);
00138 
00139   ofstream foutB(fileName, ios::binary | ios::trunc);
00140   foutB.write((char*)&bufferB[0], units*4);
00141 
00142   chdir(saveDir);
00143 
00144   free(saveDir);
00145 }
00146 
00148 static int lookupFifoHit(UINT16 *bufA, UINT16 *bufB,
00149                          int channel, int pos) {
00150   int word = (channel / 16) % 3;
00151   int bit = channel % 16;
00152 
00153   int val = 0;
00154   if(channel<48) {
00155     if(bufA)
00156       val = ((bufA[pos*3 + word] >> bit) & 0x1);
00157   } else if(channel<96) {
00158     if(bufB)
00159       val = ((bufB[pos*3 + word] >> bit) & 0x1);
00160   }
00161 
00162   return val;
00163 }
00164 
00165 void SctApi::rawData(unsigned int rod, 
00166                      int delay, int units, bool setMask, const Trigger *trig) {
00167   setupRawData(rod, delay, units, setMask, trig);
00168   
00169   unsigned long *bufferA = readFifo(rod, 0, 0, units);
00170   unsigned long *bufferB = readFifo(rod, 0, 1, units);
00171 
00172   for(int ch=0; ch<96; ch++) {
00173     cout << "Ch ";
00174     cout.width(2);
00175     cout << ch << ": ";
00176     for(int i=0; i<units; i++) {
00177       // Data is in sets of three 16bit words 
00178       cout.width(1);
00179       cout << lookupFifoHit((UINT16*)bufferA, (UINT16*)bufferB, ch, i);
00180     }
00181     cout << endl;
00182   }
00183 
00184   delete [] bufferA;
00185   delete [] bufferB;
00186 
00187   if(setMask) {
00188     // Restore to how it was
00189     calib_init();
00190   }
00191 }
00192 
00193 // Could add do all modules option but then where would the data go?!
00194 void SctApi::doRawScan(boost::shared_ptr<Scan> scan, int delay, int width, bool configure, bool clkBy2) {
00195 
00196   m_inRawScanLoop = true;  // unset by the termination of theActualThread below:
00197 
00198   {
00199     boost::mutex::scoped_lock lock(log().mutex());
00200     log() << "doRawScan\n";
00201   }
00202   
00203   boost::thread theActualThread(boost::bind(&SctApi::doRawScanThread, this, scan, delay, width, configure, clkBy2));
00204 }
00205 
00206 void SctApi::doRawScanThread(boost::shared_ptr<Scan> scan, int delay, int width, bool configure, bool clkBy2) {
00207 
00208   // A thread must handle any exception thrown by that thread!
00209 
00210   try {
00211 
00212     doRawScanThreadInnards(scan, delay, width, configure, clkBy2);
00213 
00214   } catch (const SctApiException & s) {
00215 
00216     std::ostringstream os;
00217     os << "WARNING: doRawScan failed: SctApiException with message ["<<s.what()<<"] caught in doRawScanThread in file " << __FILE__ << " at line " << __LINE__<< ".";
00218     if (mrs) {
00219       *mrs << MRS_WARNING << MRS_QUALIF("doRawScan") << MRS_TEXT(os.str()) << ENDM;
00220     };
00221     cout << os.str() << std::endl;
00222 
00223   } catch (const ConfigurationException & c) {
00224 
00225     std::ostringstream os;
00226     os << "WARNING: doRawScan failed: ConfigurationException with message ["<<c.what()<<"] caught in doRawScanThread in file " << __FILE__ << " at line " << __LINE__<< ".";
00227     if (mrs) {
00228       *mrs << MRS_WARNING << MRS_QUALIF("doRawScan") << MRS_TEXT(os.str()) << ENDM;
00229     };
00230     cout << os.str() << std::endl;
00231 
00232   } catch (const std::exception & e) {
00233 
00234     std::ostringstream os;
00235     os << "WARNING: doRawScan failed: std::exception with message ["<<e.what()<<"] caught in doRawScanThread in file " << __FILE__ << " at line " << __LINE__<< ".";
00236     if (mrs) {
00237       *mrs << MRS_WARNING << MRS_QUALIF("doRawScan") << MRS_TEXT(os.str()) << ENDM;
00238     };
00239     cout << os.str() << std::endl;
00240 
00241   } catch (...) {
00242 
00243     // We MUST make sure we catch all exceptions within this thread or else C++
00244     // says that undefined behaviour will occur.
00245     std::ostringstream os;
00246     os << "WARNING: doRawScan failed: unknon exception caught in doRawScanThread in file " << __FILE__ << " at line " << __LINE__<< ".";
00247     if (mrs) {
00248       *mrs << MRS_WARNING << MRS_QUALIF("doRawScan") << MRS_TEXT(os.str()) << ENDM;
00249     };
00250     cout << os.str() << std::endl;
00251 
00252   };
00253 
00254   if(m_isDict) {
00255     m_isDict->remove(m_id->infoServiceNameOfScanStatusObject());
00256   }
00257   m_inRawScanLoop = false;
00258 }
00259 
00260 void SctApi::doRawScanThreadInnards(boost::shared_ptr<Scan> scan, int delay, int width, bool configure, bool clkBy2) {
00261   {
00262     boost::mutex::scoped_lock lock(log().mutex());
00263     log() << "doRawScanThread\n";
00264   }
00265 
00266   boost::posix_time::ptime startTime(second_clock::universal_time());
00267 
00268   scan->setRunNumber(runNumber);
00269   scan->setScanNumber(scanNumber);
00270 
00271   scanNumber ++;
00272 
00273   std::cout << scan->print();
00274 
00275   const int realUnits = width;
00276   int units;
00277 
00278   if(checkDebugOption(DEBUG_SAVE_RAW_CAPTURE)) {
00279     units = 0x8000;
00280   } else {
00281     units = realUnits;
00282   }
00283 
00284   int nBins = scan->getScanPoints1().size();
00285 
00286   map<UINT32, UINT32 *> dataMap;
00287 
00288   for(map<UINT32, ABCDModule> ::const_iterator iter = moduleMap.begin();
00289       iter != moduleMap.end();
00290       iter ++) {
00291     UINT32 *rawData = new UINT32[nBins * realUnits * 2];
00292 
00293     for(int i=0; i<nBins*realUnits*2; i++) {
00294       rawData[i] = 0;
00295     }
00296 
00297     dataMap.insert(make_pair(iter->first, rawData));
00298   }
00299 
00300   map<RodLabel, unsigned char *> fibreMappings;
00301 
00302   // Do pre scan setup
00303   for(list<RodLabel>::const_iterator rl = rodList.begin();
00304       rl!=rodList.end();
00305       rl++){
00306     int crate = rl->crate;
00307     int rod = rl->rod;
00308 
00309     if(!getCrate()->checkBOCLasersOn(rod)) {
00310       cout << "Continuing raw scan using BOC that has its lasers cut out\n";
00311       if(mrs) {
00312     *mrs << "BOC_INTERLOCKED" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
00313          << MRS_PARAM<int>("crate", crate) 
00314          << MRS_PARAM<int>("rod", rod)
00315          << MRS_TEXT("Continuing raw scan (BOC may be interlocked)") << ENDM;
00316       }
00317     }
00318 
00319     try { 
00320       fibreMappings[*rl] = config->getFibreMappings(rl->partition, rl->crate, rl->rod);
00321     } catch(ConfigurationException &c) {
00322       cout << "No fibre mappings for appropriate module: \n";
00323       cout << c.what() << endl;
00324 
00325       {
00326     boost::mutex::scoped_lock lock(log().mutex());
00327     log() << "  (Not found)\n";
00328       }
00329 
00330       if(mrs) {
00331     *mrs << "SCAN_ABORT" << MRS_ERROR 
00332          << MRS_QUALIF("SCTAPI") << MRS_QUALIF("doRawScan") 
00333          << MRS_TEXT("Aborting scan due to missing fibre mappings") 
00334          << ENDM;
00335       }
00336       
00337       std::ostringstream os;
00338       os << "Aborting raw scan due to missing fibre mappings in " << __FILE__ << " at line " << __LINE__ << "."; 
00339 
00340       throw SctApiException(os.str());
00341     }
00342 
00343     if(clkBy2)
00344       getCrate()->enterBOCClockBy2Mode(rod);
00345   }
00346 
00347   if(configure) {
00348     cout << "Configure modules for scan\n";
00349   } else {
00350     cout << "Don't configure module\n";
00351   }
00352 
00353   /**** Start scan ****/
00354 
00355   Scan::TrigPoints trigs = scan->getVariableTrigs();
00356 
00357   int bin = 0;
00358   vector<FLOAT32> scanPoints = scan->getScanPoints1();
00359 
00360   const boost::shared_ptr<Trigger> trigger = scan->getTrigger1();
00361 
00362 #if USE_IS
00363   if(m_isDict) {
00364     ISInfoInt binNumber(0);
00365     m_isDict->insert("SCTAPIServer.currentBin", binNumber);
00366 
00367     ISInfoInt maxNumber(scanPoints.size()-1);
00368     m_isDict->insert("SCTAPIServer.maxBin", maxNumber);
00369   }
00370 #endif
00371 
00372   for(vector<FLOAT32>::const_iterator point_iter = scanPoints.begin();
00373       point_iter != scanPoints.end();
00374       point_iter++, bin++) {
00375 
00376     cout << "Bin: " << bin << endl;
00377 
00378 #if USE_IS
00379     if(m_isDict) {
00380       ISInfoInt binNumber(bin);
00381       m_isDict->update("SCTAPIServer.currentBin", binNumber);
00382     }
00383 #endif
00384 
00385     modifyABCDVar(scan->getScanVariable1(), *point_iter);
00386     if(configure) {
00387       std::cout << "Sending SCAN bank to all modules" << std::endl;
00388       setABCDModules(std::list<BankType>(1,SCTAPI_BANK_SCAN));
00389       const bool enableDataMode = scan->getOption(Scan::ENABLE_DATA_MODE);
00390       sendAllABCDModules(SCTAPI_BANK_SCAN, SCTAPI_CONFIG_ALL, enableDataMode);
00391     }
00392 
00393     if(checkDebugOption(DEBUG_USE_RAW_PRIMITIVE)) {
00394       boost::shared_ptr<PrimListWrapper> rawBinList(new PrimListWrapper(2));
00395 
00396       Trigger::RODTriggers points = trigger->getRODTriggers();
00397       struct ::CmdList rodTrigger;
00398 
00399       for(int i=0; i<N_CMD_LIST_CMDS; i++) {
00400     rodTrigger.cmd[i] = NO_CMD;
00401     rodTrigger.data[i] = 0;
00402       }
00403 
00404       for(unsigned int i=0; i<points.size(); i++) {
00405     rodTrigger.cmd[i] = points[i].first;        // Set a trigger sequence
00406     rodTrigger.data[i] = points[i].second;      // Set a trigger sequence
00407       }
00408 
00409       PrimBuilder::instance().bocHistogram(rawBinList, delay, units, trigs[bin], rodTrigger, SP0);
00410 
00411       for(list<RodLabel>::const_iterator rl = rodList.begin();
00412       rl!=rodList.end();
00413       rl++){
00414     unsigned int partition = rl->partition;
00415     unsigned int crate = rl->crate;
00416     unsigned int rod = rl->rod;
00417 
00418     sendPrimList(rod, rawBinList);
00419     int responseCode = awaitResponse(rod, 200); // Vary timeout based on number of triggers (and width)?
00420     if(responseCode == 0) {
00421       unsigned long length;
00422       unsigned long *result = getResponse(rod, length);
00423       // count = result[8];
00424 
00425       for(map<UINT32, ABCDModule> ::const_iterator iter = moduleMap.begin();
00426           iter != moduleMap.end();
00427           iter ++) {
00428 
00429         UINT32 mid = iter->first;
00430 
00431         unsigned int thisPartition, thisCrate, thisRod, channel;
00432         Utility::getpcrc(mid, thisPartition, thisCrate, thisRod, channel);
00433 
00434         // Ignore this module because it's on a different ROD
00435         if(!(thisRod == rod && thisCrate == crate && thisPartition == partition)) {
00436           continue;
00437         }
00438 
00439         UINT32 *rawData = dataMap.find(mid)->second;
00440 
00441         if(!rawData) {
00442           cout << "Can't find preallocated memory!\n";
00443 
00444           std::ostringstream os;
00445           os << "Aborting raw scan due to failure to find preallocated memory in " << __FILE__ << " at line " << __LINE__ << "."; 
00446 
00447           throw SctApiException(os.str());
00448         }
00449 
00450         for(int link=0; link<2; link++) {
00451           int fibre = fibreMappings[*rl][channel * 3 + link + 1];  // Looking for offsets 1 and 2
00452 
00453           for(int i=0; i<realUnits; i++) {
00454         // 
00455         rawData[bin * (realUnits*2) + (realUnits * link) + i] = result[9 + (fibre*units) + i];
00456           }
00457         }
00458       }
00459     }
00460       }
00461     } else {
00462 
00463     for(unsigned int t=0; t<trigs[bin]; t++) {
00464       for(list<RodLabel>::const_iterator rl = rodList.begin();
00465       rl!=rodList.end();
00466       rl++){
00467     unsigned int partition = rl->partition;
00468     unsigned int crate = rl->crate;
00469     unsigned int rod = rl->rod;
00470 
00471     const RodLabel &rodLabel = *rl;
00472 
00473     if(checkDebugOption(DEBUG_DIAG)) {
00474       cout << "doRawScan bin: " << bin << " trigger: " << t << " on (" << partition << ", " << crate << ", " << rod << ")\n";
00475     }
00476 
00477     setupRawData(rod, delay, units, false, trigger.get());
00478 
00479     unsigned long* bufferA = readFifo(rod, 0, 0, units);
00480     unsigned long* bufferB = readFifo(rod, 0, 1, units);
00481 
00482     if(!bufferA || !bufferB) {
00483           cout << "Failed to read FIFO\n";
00484           
00485           std::ostringstream os;
00486           os << "Aborting raw scan due to FIFO read failure in " << __FILE__ << " at line " << __LINE__ << "."; 
00487           
00488           throw SctApiException(os.str());
00489     }
00490 
00491     if(checkDebugOption(DEBUG_SAVE_RAW_CAPTURE)) {
00492       dumpRawEvent(rod, units, bufferA, bufferB);
00493     }
00494 
00495     for(map<UINT32, ABCDModule> ::const_iterator iter = moduleMap.begin();
00496         iter != moduleMap.end();
00497         iter ++) {
00498 
00499       UINT32 mid = iter->first;
00500 
00501       unsigned int thisPartition, thisCrate, thisRod, channel;
00502       Utility::getpcrc(mid, thisPartition, thisCrate, thisRod, channel);
00503 
00504           // Ignore this module because its on a different ROD
00505       if(!(thisRod == rod && thisCrate == crate && thisPartition == partition)) {
00506         continue;
00507       }
00508 
00509       UINT32 *rawData = dataMap.find(mid)->second;
00510 
00511       if(!rawData) {
00512             cout << "Can't find preallocated memory!\n";
00513 
00514             std::ostringstream os;
00515             os << "Aborting raw scan due failure to find preallocated memory in " << __FILE__ << " at line " << __LINE__ << "."; 
00516             
00517             throw SctApiException(os.str());
00518       }
00519 
00520       for(int link=0; link<2; link++) {
00521         int fibre = fibreMappings[rodLabel][channel * 3 + link + 1];  // Looking for offsets 1 and 2
00522 
00523         for(int i=0; i<realUnits; i++) {
00524           int val = lookupFifoHit((UINT16*)bufferA, (UINT16*)bufferB, fibre, i);
00525           rawData[bin * (realUnits*2) + (realUnits * link) + i] += val?1:0;
00526         }
00527       }
00528         }
00529         delete [] bufferA;
00530         delete [] bufferB;
00531       }
00532     } 
00533     }
00534   }
00535 
00536   /**** Finished scan ****/
00537 
00538   boost::posix_time::ptime endTime(second_clock::universal_time());
00539 
00540   /*** Tidy up ***/
00541 
00542 #warning "Hmmm.... this never did anything because raw scans never set up the module list..."
00543 //   ScanControl::setModuleScanCacheToLastPointInScan(*this, scan);
00544 
00545 #if USE_IS
00546   if(m_isDict) {
00547     m_isDict->remove("SCTAPIServer.currentBin");  // CGL: 2004/01/21: I wonder if this line should go to the bottom of this method with the SCTAPIServer.scanning line ...
00548     m_isDict->remove("SCTAPIServer.maxBin");  // CGL: 2004/01/21: I wonder if this line should go to the bottom of this method with the SCTAPIServer.scanning line ...
00549   }
00550 #endif
00551 
00552   for(list<RodLabel>::const_iterator rl = rodList.begin();
00553       rl!=rodList.end();
00554       rl++){
00555     delete [] fibreMappings[*rl];
00556 
00557     if(clkBy2)
00558       getCrate()->leaveBOCClockBy2Mode(rl->rod);
00559 
00560     if(checkDebugOption(DEBUG_BOC_SETUP))
00561       printBOCSetup(rl->rod);
00562 
00563     getCrate()->configureBOC(rl->rod);
00564   }
00565 
00566 
00567   /*** Write module data ***/
00568 
00569 #if !(USE_CONST_SCAN)
00570   // Save time taken
00571   scan->setStartTime(startTime);
00572   scan->setEndTime(endTime);
00573 #endif
00574 
00575   // Mostly the same data, just copy in the FIFOs for each module
00576   scan_result_ptrs scanResult;
00577 
00578   ScanHeader &header = scanResult.header;
00579 
00580   // Fill in common data
00581   header.version = CURRENT_SCANHEADER_VERSION;
00582   header.length = sizeof(ScanHeader);
00583   header.runNumber = scan->getRunNumber();
00584   header.scanNumber = scan->getScanNumber();
00585 
00586   strncpy(header.startTime, to_iso_string(startTime).c_str(), 16);
00587   strncpy(header.endTime, to_iso_string(endTime).c_str(), 16);
00588   header.startTime[15] = 0;    // Null terminate the string
00589   header.endTime[15] = 0;
00590 
00591   header.scanType = scan->getScanVariable1(); 
00592   header.npoints = nBins;
00593   header.size = nBins * 2 * realUnits * 2;
00594   header.dataType = SR_DT_RAWHIST; // Was SLICE_COMPRESSED
00595   // Gratuitous memory hog (could be 16bit?) (do raw scan)
00596   header.width = SR_WD_32;
00597   header.pntPoints = sizeof(ScanHeader);
00598   header.pntEvents = header.pntPoints + nBins * sizeof(FLOAT32);
00599   header.pntErrors = header.pntEvents + nBins * sizeof(UINT32);
00600   header.pntData = header.pntErrors + nBins * sizeof(UINT32);
00601 
00602   // The points
00603   FLOAT32 *points = new FLOAT32[nBins];
00604   for(int i=0; i<nBins; i++) {
00605     points[i] = scan->getScanPoints1()[i];
00606   }
00607   scanResult.points = points;
00608 
00609   // The event counts (trigs already copied)
00610   UINT32 *events = new UINT32[nBins];
00611   for(int i=0; i<nBins; i++) {
00612     events[i] = trigs[i];
00613   }
00614 #warning "Could be counted (raw scan)?"
00615   scanResult.nEvents = events;
00616 
00617   // The error counts     
00618 #warning "What errors should be recorded in raw scan?"
00619   //  (If complete failure then no histogram generated)
00620   UINT32 *errors = new UINT32[nBins];
00621   for(int i=0; i<nBins; i++) {
00622     errors[i] = 0;           // Of course! 
00623   }
00624   scanResult.nErrorEvents = errors;
00625 
00626   // Use the same time for all modules
00627   time_t secs;
00628   secs = time(NULL);
00629   struct tm broke;
00630   broke = *(gmtime(&secs));
00631 
00632   //  for each module
00633   for(map<UINT32, ABCDModule> ::const_iterator iter = moduleMap.begin();
00634       iter != moduleMap.end();
00635       iter ++) {
00636 
00637     // Fill in module specific information
00638 
00639     strncpy(header.moduleName, convertToString(iter->first).c_str(), 16);
00640     header.moduleName[15] = 0;                        // Null terminate the string
00641     header.config = iter->second;
00642 
00643     scanResult.data = dataMap.find(iter->first)->second;
00644 
00645     // What to do with it now!
00646 
00647     if(checkDebugOption(DEBUG_SAVE_HISTOGRAM)) {
00648       const int BUFF_SIZE = 50;
00649       char filename[BUFF_SIZE];
00650 
00651       int written = snprintf(filename, BUFF_SIZE, "RawHistogram_%s", convertToString(iter->first).c_str());
00652       //                                                  20021112143712
00653       strftime(filename + written, BUFF_SIZE - written, "_%Y%m%d%H%M%S.bin", &broke);
00654 
00655       cout << "Saving raw histogram: " << filename << endl;
00656       saveHistogramToFile(scanResult, filename);
00657     }
00658 
00659 #if USE_IS
00660     cout << "Writing raw data to IS\n";
00661 
00662     try {
00663       if (mrs) SctData::ScanResultWriter::publish(scanResult);
00664     } catch(Sct::IoException &e) {
00665       cout << "ScanResult publish failed:\n" << e.what() << endl;
00666       e.sendToMrs(MRS_ERROR);
00667     }
00668 #endif
00669 
00670     delete [] dataMap.find(iter->first)->second;
00671     // Make sure its not used again (duplicate module in moduleMap!)
00672     dataMap.find(iter->first)->second = 0;
00673   }
00674 
00675   delete [] scanResult.points; 
00676   delete [] scanResult.nEvents;
00677   delete [] scanResult.nErrorEvents;
00678 
00679   // Delete any unused memory
00680   for(map<UINT32, UINT32 *> ::const_iterator iter = dataMap.begin();
00681       iter != dataMap.end();
00682       iter ++) {
00683     if(iter->second) {
00684       delete [] iter->second;
00685     }
00686   }
00687 }
00688 
00689 #warning "Should this stay, or become something better..."
00690 // This needs trigger added, read all channels into one histogram...
00691 void SctApi::readRawData(unsigned int rod, 
00692                          int delay, bool setMask) {
00693   {
00694     boost::mutex::scoped_lock lock(log().mutex());
00695     log() << "Raw histogram of all ROD data\n";
00696   }
00697 
00698   int units = 768 * 2;
00699 
00700   scan_result_ptrs scanResult;
00701 
00702   // When the scan started
00703   time_t secs;
00704   secs = time(NULL);
00705   struct tm broke;
00706   broke = *(gmtime(&secs));
00707 
00708   int nBins = 96; // scan->getScanPoints1().size();
00709 
00710   ScanHeader &header = scanResult.header;
00711 
00712   header.version = 0;
00713   header.length = sizeof(ScanHeader);
00714   header.runNumber = runNumber;
00715   header.scanNumber = scanNumber;
00716   strncpy(header.moduleName, "raw link data", 16);
00717   header.moduleName[15] = 0;                        // Null terminate the string
00718   header.scanType = 0; 
00719   header.npoints = nBins;
00720   header.size = nBins * 2 * 1024 * 2;
00721 #warning "Need new type for this (readRawData)"
00722   header.dataType = SR_DT_SLICE;
00723 
00724   // Gratuitous memory (or at least file system) hog! (readRawData)
00725   header.width = SR_WD_32;
00726 
00727   // No module config for all modules!
00728   unsigned long *startAddress = (unsigned long*)&header.config;
00729   fill(startAddress, startAddress + sizeof(ABCDModule)/sizeof(unsigned long), 0);
00730 
00731   header.pntPoints = sizeof(ScanHeader);
00732   header.pntEvents = header.pntPoints + nBins * sizeof(FLOAT32);
00733   header.pntErrors = header.pntEvents + nBins * sizeof(UINT32);
00734   header.pntData = header.pntErrors + nBins * sizeof(UINT32);
00735 
00736   // The points
00737   FLOAT32 *points = new FLOAT32[nBins];
00738   for(int i=0; i<nBins; i++) {
00739     points[i] = i;
00740   }
00741   scanResult.points = points;
00742 
00743   // The event counts
00744   UINT32 *events = new UINT32[nBins];
00745   for(int i=0; i<nBins; i++) {
00746     events[i] = 1;
00747   }
00748   scanResult.nEvents = events;
00749 
00750   // The error counts
00751   UINT32 *errors = new UINT32[nBins];
00752   for(int i=0; i<nBins; i++) {
00753 #warning "More 0 error counts (readRawData)"
00754     errors[i] = 0;
00755   }
00756   scanResult.nErrorEvents = errors;
00757 
00758   // The data!
00759   int binSize = 0x800*4;   // In bytes, so works for 16bit histograms
00760 
00761   setupRawData(rod, delay, units, setMask);
00762 
00763   unsigned long *bufferA = readFifo(rod, 0, 0, units);
00764   unsigned long *bufferB = readFifo(rod, 0, 1, units);
00765 
00766   char *data = new char[nBins * binSize];
00767 
00768   unsigned long *longData = (unsigned long *)data;
00769 
00770   for(int ch=0; ch<96; ch++) {
00771     for(int i=0; i<units; i++) {
00772       int val = lookupFifoHit((UINT16*)bufferA, (UINT16*)bufferB, ch, i);
00773       longData[ch * (units) + i] = val;
00774     }
00775     cout << endl;
00776   }
00777 
00778   delete [] bufferA;
00779   delete [] bufferB;
00780 
00781   scanResult.data = data;
00782 
00783   // Save histogram to file
00784   const int BUFF_SIZE = 50;
00785   char filename[BUFF_SIZE];
00786 
00787   int written = snprintf(filename, BUFF_SIZE, "RawHistogramFull");
00788   //                                                  20021112143712
00789   strftime(filename + written, BUFF_SIZE - written, "_%Y%m%d%H%M%S.bin", &broke);
00790 
00791   cout << "Saving raw histogram: " << filename << endl;
00792 
00793   saveHistogramToFile(scanResult, filename);
00794 }
00795 
00796 vector<char> SctApi::probeWithTrigger(unsigned int rod, 
00797                                       const Trigger *trigger, signed int harness) {
00798   int delay = 5;
00799   const int realUnits = 100;
00800   int units;
00801 
00802   if(checkDebugOption(DEBUG_SAVE_RAW_CAPTURE)) {
00803     units = 0x8000;
00804   } else {
00805     units = realUnits;
00806   }
00807 
00808   int startCh = 0;
00809   int endCh = 47;
00810 
00811   if(harness != -1) {
00812     startCh = harness*6;
00813     endCh = harness*6 + 5;
00814   }
00815 
00816   // Each channel has two links!
00817   int numLinks = ((endCh+1) - startCh) * 2;
00818   vector<char> result(numLinks);
00819 
00820   if(!getCrate()) {
00821     cout << "Aborting probe on nonexistant crate!\n";
00822     if(mrs) {
00823       *mrs << "CRATE_NOTEXIST" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
00824            << MRS_PARAM<int>("crate", crt()) 
00825            << MRS_TEXT("Aborting probe (Crate does not exist)") << ENDM;
00826     }
00827     return result;
00828   }
00829 
00830   if(!getCrate()->RODPresent(rod)) {
00831     cout << "No configured ROD ! Aborting probe\n";
00832     if(mrs) {
00833       *mrs << "ROD_NONEXIST" << MRS_ERROR << MRS_QUALIF("SCTAPI") 
00834            << MRS_PARAM<int>("crate", crt()) 
00835            << MRS_PARAM<int>("rod", rod)
00836            << MRS_TEXT("Aborting probe (ROD not configured)") << ENDM;
00837     }
00838 
00839     return result;
00840   }
00841 
00842   if(!getCrate()->checkBOCLasersOn(rod)) {
00843     cout << "Continuing probe using BOC that has its lasers cut out\n";
00844     if(mrs) {
00845       *mrs << "BOC_INTERLOCKED" << MRS_WARNING << MRS_QUALIF("SCTAPI") 
00846            << MRS_PARAM<int>("crate", crt()) 
00847            << MRS_PARAM<int>("rod", rod)
00848            << MRS_TEXT("Continuing probe (BOC interlocked)") << ENDM;
00849     }
00850   }
00851 
00852   // Always set up masks first
00853   int setupSuccess = setupRawData(rod, delay, units, true, trigger);
00854 
00855   if(!setupSuccess) {
00856     cout << "Probe failed!";
00857     for(int i = 0; i<numLinks; i++) {
00858       result[i] = 'X';
00859     }
00860     return result;
00861   }
00862 
00863   unsigned long *bufferA = readFifo(rod, 0, 0, units);
00864   unsigned long *bufferB = readFifo(rod, 0, 1, units);
00865 
00866   if(!bufferA && !bufferB) {
00867     cout << "No data refusing to analyse probe!\n";
00868     return vector<char>();
00869   }
00870 
00871   if(checkDebugOption(DEBUG_SAVE_RAW_CAPTURE)) {
00872     dumpRawEvent(rod, units, bufferA, bufferB);
00873   }
00874 
00875   // Now we've saved the data we can pretend it always was 100
00876   units = realUnits;
00877 
00878   char *data = new char[units];
00879 
00880   for(int index=0; index<numLinks; index++) {
00881     int link = index + startCh*2;
00882     bool same = true;
00883     bool clock2 = true;
00884     bool clock4 = true;
00885     signed char lastValue2 = -1;
00886     signed char lastValue = -1;
00887 
00888     int headerState = 0;
00889 
00890     // Which BC an event started if there was one
00891     int eventStart = -1;
00892 
00893     for(int i=0; i<units; i++) {
00894       int val = lookupFifoHit((UINT16*)bufferA, (UINT16*)bufferB, link, i);
00895 
00896       if(i > 0) {   // not first pass
00897         if(same && lastValue != val) {
00898           same = false;
00899         }
00900     if(clock2 && lastValue == val) {
00901           clock2 = false;
00902         }
00903     if(clock4 && lastValue2 == val) {
00904           clock4 = false;
00905         }
00906         lastValue2 = lastValue;
00907       }
00908 
00909       lastValue = val;
00910       data[i] = val;
00911 
00912       switch(headerState) {
00913       case 0:
00914         if(val == 1) headerState = 1;
00915         break;
00916       case 1:  // 1xxxxxx
00917         if(val == 0) headerState = 10; // 10 
00918         else headerState = 2;          // 11
00919         break;
00920       case 2:  // 11xxxxx
00921         if(val == 0) headerState = 20; // 110 
00922         else headerState = 3;          // 111
00923         break;
00924       case 3:  // 111xxxx
00925         if(val == 0) headerState = 4;  // 1110 
00926         else headerState = 99;         // junk
00927         break;
00928       case 4:  // 1110xxx
00929         if(val == 1) {
00930           headerState = 21; // 11101 - event header
00931           eventStart = i-4;
00932         } else headerState = 99;         // junk
00933         break;
00934       case 10: // 10xxxxx
00935         if(val == 1) headerState = 11; // 101 
00936         else headerState = 99;         // junk
00937         break;
00938       case 11: // 101xxxx
00939         if(val == 0) headerState = 12; // 1010 
00940         else headerState = 99;         // junk
00941         break;
00942       case 12: // 1010xxx
00943         if(val == 1) headerState = 13; // 10101 
00944         else headerState = 15;         // 10100
00945         break;
00946       case 13: // 10101xx
00947         if(val == 0) headerState = 14; // 101010 
00948         else headerState = 99;         // junk
00949         break;
00950       case 14: // 10101xx
00951         if(val == 0) headerState = 22; // 1010100 - soft reset 
00952         else headerState = 99;         // junk
00953         break;
00954       case 15: // 10100xx
00955         if(val == 1) headerState = 16; // 101001 
00956         else headerState = 99;         // junk
00957         break;
00958       case 16: // 10100xx
00959         if(val == 0) headerState = 23; // 1010010 - BC reset 
00960         else headerState = 99;         // junk
00961         break;
00962       case 20: // L1A 110
00963         // Any more "1"  - could be another L1A?
00964         if(val == 1) headerState = 31;
00965         break;
00966       case 22: // SR  1010100
00967       case 23: // BCR 1010010
00968         // Any more "1" and we assume junk
00969         if(val == 1) headerState = 99;
00970         break;
00971       case 31:  // 1xxxxxx
00972         if(val == 0) headerState = 99; // 10 
00973         else headerState = 32;         // 11
00974         break;
00975       case 32:  // 11xxxxx
00976         if(val == 0) headerState = 33; // 110 
00977         else headerState = 99;         // 111
00978         break;
00979       case 33: // second L1A 110
00980         // Any more "1" and we assume junk
00981         if(val == 1) headerState = 99;
00982         break;
00983       default:
00984         // including valid event header or junk
00985         // - do nothing 
00986         break;
00987       }
00988     }
00989 
00990     bool verbose = checkDebugOption(DEBUG_VERBOSE_PROBE);
00991 
00992     if(verbose) {
00993       cout.width(2);
00994       cout << (link/2) << " (" << link%2 << ") ";
00995     }
00996 
00997     if(same) {
00998       result[index] = int(lastValue) + '0';
00999       if(verbose) cout << "All " << int(lastValue) << "'s\n";
01000     } else if(clock2) {
01001       result[index] = '2';
01002       if(verbose) cout << "Clock by 2\n";
01003     } else if(clock4) {
01004       result[index] = '4';
01005       if(verbose) cout << "Clock by 4\n";
01006     } else {
01007       switch(headerState) {
01008       case 20:
01009         result[index] = 'L';
01010         if(verbose) cout << "L1A\n";
01011         break;
01012       case 21:
01013         result[index] = 'E';
01014         if(verbose) {
01015           cout << "Event Header ";
01016           // Bits 6-9 are L1ID
01017           int l1 = 0;
01018           for (int i=6; i<=9; i++) {
01019             l1 = (l1 << 1) + data[i+eventStart];
01020           }
01021           cout << "L1 = " << l1;
01022 
01023           // Bits 10-17 are BCID
01024           int bc = 0;
01025           for (int i=10; i<=17; i++) {
01026             bc = (bc << 1) + data[i+eventStart];
01027           }
01028           cout << " BC = " << bc << endl;
01029         }
01030         break;
01031       case 22:
01032         result[index] = 'S';
01033         if(verbose) cout << "Soft Reset\n";
01034         break;
01035       case 23:
01036         result[index] = 'B';
01037         if(verbose) cout << "BC Reset\n";
01038         break;
01039       case 33:
01040         result[index] = 'l';
01041         if(verbose) cout << "2 * L1A\n";
01042         break;
01043       default:
01044         result[index] = 'J';
01045         if(verbose) cout << "Junk\n";
01046         break;
01047       }
01048       if(verbose) {
01049         cout << "       ";
01050         for(int i=0; i<min(units, 60); i++) {
01051           cout << int(data[i]);
01052         }
01053         cout << endl;
01054       }
01055     }
01056   }
01057 
01058   delete [] bufferA;
01059   delete [] bufferB;
01060 
01061   delete [] data;
01062 
01063   return result;
01064 }
01065 
01066 vector<char> SctApi::probe(unsigned int rod, 
01067                            signed int harness) {
01068   return probeWithTrigger(rod, 0, harness);
01069 }
01070 
01071 vector<vector<char> > SctApi::probeScan(unsigned int rod, 
01072                                         boost::shared_ptr<Scan> scan, signed int harness) {
01073   {
01074     boost::mutex::scoped_lock lock(log().mutex());
01075     log() << "probeScan\n";
01076   }
01077 
01078   scan->setRunNumber(runNumber);
01079   scan->setScanNumber(scanNumber);
01080 
01081   scan->print();
01082 
01083   vector<FLOAT32> scanPoints = scan->getScanPoints1();
01084 
01085   const boost::shared_ptr<Trigger> trigger = scan->getTrigger1();
01086 
01087   vector<vector<char> > result(scanPoints.size());
01088 
01089   if(scanPoints.size() == 0) {
01090     cout << "Asked for probeScan with 0 scan points\n";
01091   }
01092 
01093   for(unsigned int point = 0; point < scanPoints.size(); point ++) {
01094     FLOAT32 val = scanPoints[point];
01095 
01096     try {
01097       modifyABCDVar(scan->getScanVariable1(), val);
01098     } catch(SctApiException &s) {
01099       std::cout << "SctApi Exception thrown by modifyABCDVar in probeScan:\n";
01100       std::cout << s.what() << std::endl;
01101     }
01102 
01103     result[point] = probeWithTrigger(rod, trigger.get(), harness);
01104   }
01105 
01106   if(checkDebugOption(DEBUG_BOC_SETUP))
01107     printBOCSetup(rod);
01108 
01109   getCrate()->configureBOC(rod);
01110 
01111   return result;
01112 }
01113 
01114 bool SctApi::checkAllModulesProbe(string value) {
01115   bool result = true;
01116 
01117   for(list<RodLabel>::const_iterator rl = rodList.begin();
01118       rl!=rodList.end();
01119       rl++){
01120     vector<char> values = probe(rl->rod);
01121 
01122     // For each module on ROD
01123 #warning "Slightly inefficient (all modules for each ROD)"
01124     for(map<UINT32, ABCDModule>::const_iterator mi = moduleMap.begin();
01125         mi!=moduleMap.end();
01126         mi ++) {
01127       UINT32 currMid = mi->first;
01128 
01129 #warning "Only checks non redundant links"
01130       // To do "off ROD" modules need to trigger probe off a TIM trigger and read all RODs at the same time
01131       // Except for clock/2 
01132 
01133       unsigned int partition, crate, rod, channel;
01134       ::SctApi::Utility::getpcrc(currMid, partition, crate, rod, channel);
01135 
01136       if(partition == rl->partition && crate == rl->crate && rod == rl->rod) {
01137         unsigned char *mappings = config->getFibreMappings(partition, crate, rod);
01138 
01139         if(mappings[channel * 3 + 1] != (unsigned char)DATA_LINK_OFF) {
01140           char link0 = values[mappings[channel * 3 + 1]];
01141           if(find(value.begin(), value.end(), link0) == value.end()) {
01142             result = false;
01143             cout << "Failed on link 0 of " << currMid << " (" << link0 << ")\n";
01144 
01145             if(mrs) {
01146               // Make it into a string
01147               char link0str[2];
01148               link0str[0] = link0;
01149               link0str[1] = 0;
01150               *mrs << "MODULE_STATE" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01151                    << MRS_PARAM<int>("moduleID", currMid) 
01152                    << MRS_PARAM<const char *>("sn", convertToString(currMid).c_str())
01153                    << MRS_PARAM<const char *>("required", value.c_str())
01154                    << MRS_PARAM<const char *>("found", link0str)
01155                    << MRS_TEXT("Link0 of module not in required state") << ENDM;
01156             }
01157 
01158             break;
01159           }
01160         }
01161 
01162         if(mappings[channel * 3 + 2] != (unsigned char)DATA_LINK_OFF) {
01163           char link1 = values[mappings[channel * 3 + 2]];
01164           if(find(value.begin(), value.end(), link1) == value.end()) {
01165             result = false;
01166             cout << "Failed on link 1 of " << currMid << " (" << link1 << ")\n";
01167             if(mrs) {
01168               // Make it into a string
01169               char link1str[2];
01170               link1str[0] = link1;
01171               link1str[1] = 0;
01172               *mrs << "MODULE_STATE" << MRS_INFORMATION << MRS_QUALIF("SCTAPI") 
01173                    << MRS_PARAM<int>("moduleID", currMid) 
01174                    << MRS_PARAM<const char *>("sn", convertToString(currMid).c_str())
01175                    << MRS_PARAM<const char *>("required", value.c_str())
01176                    << MRS_PARAM<const char *>("found", link1str)
01177                    << MRS_TEXT("Link1 of module not in required state") << ENDM;
01178             }
01179 
01180             break;
01181           }
01182         }
01183       }
01184     }
01185   }
01186 
01187   return result;
01188 }
01189 
01190 }

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