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

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

Generated on Thu Feb 10 02:40:16 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5