CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/EventFilter/CastorRawToDigi/src/CastorCORData.cc

Go to the documentation of this file.
00001 //#include "Utilities/Configuration/interface/Architecture.h"
00002 /*  
00003  *  $Date: 2009/12/28 23:16:05 $
00004  *  $Revision: 1.2 $
00005  *  \author A. Campbell - DESY
00006  */
00007 #ifndef HTBDAQ_DATA_STANDALONE
00008 #include "EventFilter/CastorRawToDigi/interface/CastorCORData.h"
00009 #else
00010 #include "CastorCORData.h"
00011 #endif
00012 #include <string.h>
00013 #include <iostream>
00014 #include <algorithm>
00015 #include <iomanip>
00016 
00017 using namespace std;
00018 
00019 const int CastorCORData::CHANNELS_PER_SPIGOT         = 36;
00020 const int CastorCORData::MAXIMUM_SAMPLES_PER_CHANNEL = 20;
00021 
00022 CastorCORData::CastorCORData() : m_formatVersion(-2), m_rawLength(0), m_rawConst(0), m_ownData(0) { }
00023 CastorCORData::CastorCORData(const unsigned short* data, int length) {
00024   adoptData(data,length);
00025   m_ownData=0;
00026 }
00027 CastorCORData::CastorCORData(const CastorCORData& hd) : m_formatVersion(hd.m_formatVersion), m_rawLength(hd.m_rawLength), m_rawConst(hd.m_rawConst), m_ownData(0) { }
00028 
00029 CastorCORData::CastorCORData(int version_to_create) : m_formatVersion(version_to_create) {
00030   allocate(version_to_create);
00031 }
00032 
00033 void CastorCORData::allocate(int version_to_create) {
00034   m_formatVersion=version_to_create;
00035   // the needed space is for the biggest possible event...
00036   const int needed=0x200;
00037   // create a buffer big enough...
00038   m_ownData=new unsigned short[needed];
00039   m_rawLength=0;
00040   m_rawConst=m_ownData;
00041 }
00042 
00043 CastorCORData& CastorCORData::operator=(const CastorCORData& hd) {
00044   if (m_ownData==0) {
00045     m_formatVersion=hd.m_formatVersion;
00046     m_rawLength=hd.m_rawLength;
00047     m_rawConst=hd.m_rawConst;
00048   }
00049   return (*this);
00050 }
00051 
00052 void CastorCORData::adoptData(const unsigned short* data, int length) {
00053   m_rawLength=length;
00054   m_rawConst=data;
00055   if (m_rawLength<5) {
00056     m_formatVersion=-2; // invalid!
00057   } else {
00058     m_formatVersion=(m_rawConst[4]>>12)&0xF;
00059   }
00060 }
00061 
00062 // check :: not EE, length is reasonable, length matches wordcount
00063 //          length required for tp+daq is correct
00064 
00065 bool CastorCORData::check() const {
00066      // length checks
00067     //  minimum length
00068     if (m_rawLength<6+12) return false;
00069     //  matches wordcount
00070     if (m_rawLength!=m_rawConst[m_rawLength-3]) return false;
00071  
00072     // daq/tp length check
00073     int tp, daq, header, trailer, trigger;
00074     determineSectionLengths(tp,daq,header,trailer,trigger);
00075     if (trigger+daq+header+trailer>m_rawLength) return false;
00076 
00077   return true;
00078 }
00079 
00080 void CastorCORData::determineSectionLengths(int& tpWords, int& daqWords, int& headerWords, int& trailerWords, int& triggerLen) const {
00081  
00082     tpWords=m_rawConst[5]>>8; // should be 8 but could be up to 12
00083     if (m_rawLength>4) 
00084       daqWords=m_rawConst[m_rawLength-4]&0x7FF; // no zero suppression supported
00085           // there are 24 16bit words per time sample
00086           // these contain the data from 36 channels
00087           // daqWords is number of 16 bit words of qie data 
00088           // hence #qie data values id daqWords*3/2
00089     headerWords=8;
00090         triggerLen=12;   // total space reserved for trigger information
00091     trailerWords=12; // minimum, may be more...
00092 }
00093 
00094 void CastorCORData::determineStaticLengths(int& headerWords, int& trailerWords, int& triggerLen) const {
00095    headerWords=8;
00096    triggerLen=12;   // total space reserved for trigger information
00097    trailerWords=12; // minimum, may be more...
00098 
00099 }
00100 
00101 
00102 void CastorCORData::unpack(unsigned char* daq_lengths, unsigned short* daq_samples,
00103                          unsigned char* tp_lengths, unsigned short* tp_samples) const {
00104 
00105   if (daq_lengths!=0) memset(daq_lengths,0,CHANNELS_PER_SPIGOT);
00106   if (tp_lengths!=0) memset(tp_lengths,0,1);
00107 
00108   int tp_words_total, daq_words_total, headerLen, trailerLen, triggerLen;
00109   determineSectionLengths(tp_words_total,daq_words_total,headerLen,trailerLen,triggerLen);
00110 
00111   int wordPtr;
00112   const unsigned short* tpBase=m_rawConst+headerLen;
00113   // process the trigger primitive words
00114   if (tp_lengths!=0) {
00115     for (wordPtr=0; wordPtr<tp_words_total; wordPtr++) {
00116        tp_samples[tp_lengths[0]]=tpBase[wordPtr];
00117        tp_lengths[0]++;
00118     }
00119   }
00120  
00121   const unsigned short* daqBase=m_rawConst+headerLen+triggerLen;
00122   unsigned long dat;
00123   // process the DAQ words
00124   int lastCapid=0;
00125   int ts,dv;
00126   int tsamples = daq_words_total/24;
00127   if (daq_lengths!=0) {
00128         for ( ts = 0; ts < tsamples; ts++ ) {
00129                 for (int j=0; j<12 ; j++) {
00130                         dat = daqBase[(ts*12+j)*2]<<16 | daqBase[(ts*12+j)*2+1];
00131                         dv  = ( dat & 0x80000000 ) >> 31;
00132                         daq_samples[(j*3)  *MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x40000000 ) >> 20 ) | (( dat & 0x3fe00000 ) >> 21 ) | ( dv << 9 );
00133                         daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x00100000 ) >> 10 ) | (( dat & 0x000ff800 ) >> 11 ) | ( dv << 9 );
00134                         daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x00000400 )       ) | (( dat & 0x000003fe ) >>  1 ) | ( dv << 9 );
00135                 }
00136     }
00137    // now loop over channels - set daq_lengths with error bits
00138    int ichan;
00139    for ( ichan = 0; ichan<CHANNELS_PER_SPIGOT; ichan++) {
00140            daq_lengths[ichan]=tsamples;
00141            for ( ts = 0; ts < tsamples; ts++ ) {
00142               int erdv =(daq_samples[ichan*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x600 ) >> 9;
00143                   int capid=(daq_samples[ichan*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x180 ) >> 7;
00144                   if ( erdv!=1 || ( ts!=0 && (capid!=((lastCapid+1)%4)))) {
00145                          daq_lengths[ichan]|=0x80; 
00146               }
00147                   lastCapid=capid;
00148        }
00149    }
00150  }
00151 }
00152 
00153 void CastorCORData::pack(unsigned char* daq_lengths, unsigned short* daq_samples,
00154                        unsigned char* tp_lengths, unsigned short* tp_samples, bool do_capid) {
00155   
00156   int tp_words_total=0, daq_words_total=0, headerLen, trailerLen, triggerLen;
00157   determineStaticLengths(headerLen,trailerLen,triggerLen);
00158 
00159   tp_words_total=0;
00160   daq_words_total=0;
00161   int isample;
00162 
00163   // trigger words
00164   unsigned short* ptr=m_ownData+headerLen;
00165   if (tp_samples!=0 && tp_lengths!=0) {
00166       for (isample=0; isample<tp_lengths[0] && isample<12; isample++) {
00167         ptr[tp_words_total]=tp_samples[isample];
00168         tp_words_total++;
00169       }
00170   }
00171 
00172   // daq words
00173   ptr=m_ownData+headerLen+triggerLen;
00174   int timesamples = std::min (daq_lengths[0]&0x3f,MAXIMUM_SAMPLES_PER_CHANNEL) ;
00175   int ts, capid, j;
00176   unsigned long dat;
00177   unsigned short s1,s2,s3;
00178   bool somevalid;
00179 
00180   for (ts=0; ts<timesamples; ts++){
00181         capid = ts%4;
00182     for (j=0; j<12 ; j++) {
00183                 somevalid = false;
00184                 if ( daq_lengths[j*3] == 0 || ( daq_lengths[j*3] & 0xc0 ) ) {
00185                         s1 = 0x400; // ER !DV
00186             } else {
00187                         s1 = daq_samples[(j*3  )*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
00188                         somevalid = true;
00189             }
00190                 if ( daq_lengths[j*3+1] == 0 || ( daq_lengths[j*3+1] & 0xc0 ) ) {
00191                         s2 = 0x400; // ER !DV
00192             } else {
00193                         s2 = daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
00194                         somevalid = true;
00195             }
00196                 if ( daq_lengths[j*3+2] == 0 || ( daq_lengths[j*3+2] & 0xc0 ) ) {
00197                         s3 = 0x400; // ER !DV
00198             } else {
00199                         s3 = daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
00200                         somevalid = true;
00201             }
00202                 //dat = 0x80000001 // msb is dv for the fibre
00206                      //|  ( daq_samples[(j*3  )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 21
00207                          //|  ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 11
00208                          //|  ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) <<  1
00209                      //|  ( daq_samples[(j*3  )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 20
00210                          //|  ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 10
00211                          //|  ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) ;
00212                 dat = 0x00000001 // msb is dv for the fibre
00213                              // sample data  is ER(1)+CAPID(2)+EXP(2)+Mantissa(5)
00214                                                  // daq_samples has ER(1)+DV(1)+CAPID(2)+EXP(2)+Mantissa(5)
00215                                                  // should check daq_lengths for the 3 channels here ??
00216                      |  ( s1 & 0x1ff ) << 21
00217                          |  ( s2 & 0x1ff ) << 11
00218                          |  ( s3 & 0x1ff ) <<  1
00219                      |  ( s1 & 0x400 ) << 20
00220                          |  ( s2 & 0x400 ) << 10
00221                          |  ( s3 & 0x400 ) ;
00222             if ( somevalid ) dat |= 0x80000000;
00223                 // should we set dv from daq_samples ??
00224                 if (do_capid) dat = ( dat & 0xcff3fcff ) | capid << 28 | capid << 18 | capid << 8;
00225                 ptr[daq_words_total++] = dat >> 16;
00226                 ptr[daq_words_total++] = dat & 0xffff;
00227 
00228     } 
00229   }
00230 
00231    m_ownData[5]=(tp_words_total<<8)|0x1;
00232    unsigned short totalLen=headerLen+12+daq_words_total+trailerLen;
00233 
00234    m_rawLength=totalLen;
00235    m_ownData[totalLen-2]=totalLen/2; // 32-bit words
00236    m_ownData[totalLen-3]=totalLen;
00237    m_ownData[totalLen-4]=daq_words_total;
00238  
00239 }
00240 
00241 void CastorCORData::packHeaderTrailer(int L1Anumber, int bcn, int submodule, int orbitn, int pipeline, int ndd, int nps, int firmwareRev) {
00242   m_ownData[0]=L1Anumber&0xFF;
00243   m_ownData[1]=(L1Anumber&0xFFFF00)>>8;
00244 
00245   m_ownData[2]=0x8000; // Version is valid, no error bits - status bits need definition
00246   m_ownData[3]=((orbitn&0x1F)<<11)|(submodule&0x7FF);
00247   m_ownData[4]=((m_formatVersion&0xF)<<12)|(bcn&0xFFF);
00248   m_ownData[5]|=((nps&0xF)<<4)|0x1;
00249   m_ownData[6]=((firmwareRev&0x70000)>>3)|(firmwareRev&0x1FFF);
00250   m_ownData[7]=(pipeline&0xFF) | ((ndd&0x1F)<<8);
00251   m_ownData[m_rawLength-4]&=0x7FF;
00252   m_ownData[m_rawLength-4]|=(ndd&0x1F)<<11;
00253   
00254   m_ownData[m_rawLength-2]=m_rawLength/2; // 32-bit words
00255   m_ownData[m_rawLength-1]=(L1Anumber&0xFF)<<8;
00256 }
00257 
00258 unsigned int CastorCORData::getOrbitNumber() const { 
00259   return (m_rawConst[3]>>11);
00260 }
00261 unsigned int CastorCORData::getSubmodule() const {
00262   return (m_rawConst[3]&0x7FF);
00263 }
00264 unsigned int CastorCORData::htrSlot() const{
00265   const unsigned int smid = getSubmodule();
00266   return ((smid>>1)&0x1F);
00267 } 
00268 unsigned int CastorCORData::htrTopBottom() const{
00269   const unsigned int smid = getSubmodule();
00270   return (smid&0x01);
00271 } 
00272 unsigned int CastorCORData::readoutVMECrateId() const{
00273   const unsigned int smid = getSubmodule();
00274   return ((smid>>6)&0x1F);
00275 } 
00276 bool CastorCORData::isCalibrationStream() const {
00277   return (m_formatVersion==-1)?(false):(m_rawConst[2]&0x4000);
00278 }
00279 bool CastorCORData::isUnsuppressed() const {
00280   return (m_formatVersion<4)?(false):(m_rawConst[6]&0x8000);
00281 }
00282 bool CastorCORData::wasMarkAndPassZS(int fiber, int fiberchan) const {
00283   if (fiber<1 || fiber>8 || fiberchan<0 || fiberchan>2) return false;
00284   if (!isUnsuppressed() || m_formatVersion<5) return false;
00285   unsigned short val=(fiber<5)?(m_rawConst[m_rawLength-12]):(m_rawConst[m_rawLength-11]);
00286   int shift=(((fiber-1)%4)*3)+fiberchan;
00287   return ((val>>shift)&0x1)!=0;
00288 } 
00289 
00290 bool CastorCORData::isPatternRAMEvent() const {
00291   return (m_formatVersion==-1)?(false):(m_rawConst[2]&0x1000);
00292 }
00293 bool CastorCORData::isHistogramEvent() const {
00294   return (m_formatVersion==-1)?(m_rawConst[2]&0x2):(m_rawConst[2]&0x2000);
00295 }
00296 int CastorCORData::getNDD() const {
00297   return (m_formatVersion==-1)?(m_rawConst[m_rawLength-4]>>8):(m_rawConst[m_rawLength-4]>>11);
00298 }
00299 int CastorCORData::getNTP() const {
00300   int retval=-1;
00301   if (m_formatVersion==-1) retval=m_rawConst[m_rawLength-4]&0xFF;
00302   else if (m_formatVersion<3) retval=m_rawConst[m_rawLength-4]>>11;
00303   return retval;
00304 }
00305 int CastorCORData::getNPrecisionWords() const {
00306   return (m_formatVersion==-1)?(m_rawConst[m_rawLength-4]&0xFF):(m_rawConst[m_rawLength-4]&0x7FF);
00307 }
00308 int CastorCORData::getNPS() const {
00309   return (m_formatVersion==-1)?(0):((m_rawConst[5]>>4)&0xF);
00310 }
00311 unsigned int CastorCORData::getPipelineLength() const {
00312   return (m_rawConst[7]&0xFF);
00313 }
00314 unsigned int CastorCORData::getFirmwareRevision() const {
00315   return (m_rawConst[6]);
00316 }
00317 
00318 void CastorCORData::getHistogramFibers(int& a, int& b) const {
00319   a=-1;
00320   b=-1;
00321   if (m_formatVersion==-1) {
00322     a=((m_rawConst[2]&0x0F00)>>8);
00323     b=((m_rawConst[2]&0xF000)>>12);
00324   } else {
00325     a=((m_rawConst[5]&0x0F00)>>8);
00326     b=((m_rawConst[5]&0xF000)>>12);
00327   }
00328 }
00329 
00330 bool CastorCORData::unpackHistogram(int myfiber, int mysc, int capid, unsigned short* histogram) const {
00331   // check for histogram mode
00332   if (!isHistogramEvent()) return false;
00333 
00334   int fiber1, fiber2;
00335   getHistogramFibers(fiber1,fiber2);
00336   if (fiber1!=myfiber && fiber2!=myfiber) return false;
00337 
00338   if (m_formatVersion==-1) {
00339     int offset=6+mysc*4*32+capid*32;
00340     if (myfiber==fiber2) offset+=3*4*32; // skip to the second half...
00341     for (int i=0; i<32; i++)
00342       histogram[i]=m_rawConst[offset+i];
00343     return true;
00344   } else {
00345     int offset=8+mysc*4*32+capid*32;
00346     if (myfiber==fiber2) offset+=3*4*32; // skip to the second half...
00347     for (int i=0; i<32; i++)
00348       histogram[i]=m_rawConst[offset+i];
00349     return true;
00350   }
00351 }
00352