Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:21

0001 //#include "Utilities/Configuration/interface/Architecture.h"
0002 /*  
0003  *  \author A. Campbell - DESY
0004  */
0005 #ifndef HTBDAQ_DATA_STANDALONE
0006 #include "EventFilter/CastorRawToDigi/interface/CastorCORData.h"
0007 #else
0008 #include "CastorCORData.h"
0009 #endif
0010 #include <cstring>
0011 #include <iostream>
0012 #include <algorithm>
0013 #include <iomanip>
0014 
0015 using namespace std;
0016 
0017 const int CastorCORData::CHANNELS_PER_SPIGOT = 36;
0018 const int CastorCORData::MAXIMUM_SAMPLES_PER_CHANNEL = 20;
0019 
0020 CastorCORData::CastorCORData() : m_formatVersion(-2), m_rawLength(0), m_rawConst(nullptr), m_ownData(nullptr) {}
0021 CastorCORData::CastorCORData(const unsigned short* data, int length) {
0022   adoptData(data, length);
0023   m_ownData = nullptr;
0024 }
0025 CastorCORData::CastorCORData(const CastorCORData& hd)
0026     : m_formatVersion(hd.m_formatVersion), m_rawLength(hd.m_rawLength), m_rawConst(hd.m_rawConst), m_ownData(nullptr) {}
0027 
0028 CastorCORData::CastorCORData(int version_to_create) : m_formatVersion(version_to_create) {
0029   allocate(version_to_create);
0030 }
0031 
0032 void CastorCORData::allocate(int version_to_create) {
0033   m_formatVersion = version_to_create;
0034   // the needed space is for the biggest possible event...
0035   const int needed = 0x200;
0036   // create a buffer big enough...
0037   m_ownData = new unsigned short[needed];
0038   m_rawLength = 0;
0039   m_rawConst = m_ownData;
0040 }
0041 
0042 CastorCORData& CastorCORData::operator=(const CastorCORData& hd) {
0043   if (m_ownData == nullptr) {
0044     m_formatVersion = hd.m_formatVersion;
0045     m_rawLength = hd.m_rawLength;
0046     m_rawConst = hd.m_rawConst;
0047   }
0048   return (*this);
0049 }
0050 
0051 void CastorCORData::adoptData(const unsigned short* data, int length) {
0052   m_rawLength = length;
0053   m_rawConst = data;
0054   if (m_rawLength < 5) {
0055     m_formatVersion = -2;  // invalid!
0056   } else {
0057     m_formatVersion = (m_rawConst[4] >> 12) & 0xF;
0058   }
0059 }
0060 
0061 // check :: not EE, length is reasonable, length matches wordcount
0062 //          length required for tp+daq is correct
0063 
0064 bool CastorCORData::check() const {
0065   // length checks
0066   //  minimum length
0067   if (m_rawLength < 6 + 12)
0068     return false;
0069   //  matches wordcount
0070   if (m_rawLength != m_rawConst[m_rawLength - 3])
0071     return false;
0072 
0073   // daq/tp length check
0074   int tp, daq, header, trailer, trigger;
0075   determineSectionLengths(tp, daq, header, trailer, trigger);
0076   if (trigger + daq + header + trailer > m_rawLength)
0077     return false;
0078 
0079   return true;
0080 }
0081 
0082 void CastorCORData::determineSectionLengths(
0083     int& tpWords, int& daqWords, int& headerWords, int& trailerWords, int& triggerLen) const {
0084   tpWords = m_rawConst[5] >> 8;  // should be 8 but could be up to 12
0085   if (m_rawLength > 4)
0086     daqWords = m_rawConst[m_rawLength - 4] & 0x7FF;  // no zero suppression supported
0087                                                      // there are 24 16bit words per time sample
0088                                                      // these contain the data from 36 channels
0089                                                      // daqWords is number of 16 bit words of qie data
0090                                                      // hence #qie data values id daqWords*3/2
0091   headerWords = 8;
0092   triggerLen = 12;    // total space reserved for trigger information
0093   trailerWords = 12;  // minimum, may be more...
0094 }
0095 
0096 void CastorCORData::determineStaticLengths(int& headerWords, int& trailerWords, int& triggerLen) const {
0097   headerWords = 8;
0098   triggerLen = 12;    // total space reserved for trigger information
0099   trailerWords = 12;  // minimum, may be more...
0100 }
0101 
0102 void CastorCORData::unpack(unsigned char* daq_lengths,
0103                            unsigned short* daq_samples,
0104                            unsigned char* tp_lengths,
0105                            unsigned short* tp_samples) const {
0106   if (daq_lengths != nullptr)
0107     memset(daq_lengths, 0, CHANNELS_PER_SPIGOT);
0108   if (tp_lengths != nullptr)
0109     memset(tp_lengths, 0, 1);
0110 
0111   int tp_words_total = 0;
0112   int daq_words_total = 0;
0113   int headerLen = 0;
0114   int trailerLen = 0;
0115   int triggerLen = 0;
0116   determineSectionLengths(tp_words_total, daq_words_total, headerLen, trailerLen, triggerLen);
0117 
0118   int wordPtr;
0119   const unsigned short* tpBase = m_rawConst + headerLen;
0120   // process the trigger primitive words
0121   if (tp_lengths != nullptr) {
0122     for (wordPtr = 0; wordPtr < tp_words_total; wordPtr++) {
0123       tp_samples[tp_lengths[0]] = tpBase[wordPtr];
0124       tp_lengths[0]++;
0125     }
0126   }
0127 
0128   const unsigned short* daqBase = m_rawConst + headerLen + triggerLen;
0129   unsigned long dat;
0130   // process the DAQ words
0131   int lastCapid = 0;
0132   int ts, dv;
0133   int tsamples = daq_words_total / 24;
0134   if (daq_lengths != nullptr) {
0135     for (ts = 0; ts < tsamples; ts++) {
0136       for (int j = 0; j < 12; j++) {
0137         dat = daqBase[(ts * 12 + j) * 2] << 16 | daqBase[(ts * 12 + j) * 2 + 1];
0138         dv = (dat & 0x80000000) >> 31;
0139         daq_samples[(j * 3) * MAXIMUM_SAMPLES_PER_CHANNEL + ts] =
0140             ((dat & 0x40000000) >> 20) | ((dat & 0x3fe00000) >> 21) | (dv << 9);
0141         daq_samples[(j * 3 + 1) * MAXIMUM_SAMPLES_PER_CHANNEL + ts] =
0142             ((dat & 0x00100000) >> 10) | ((dat & 0x000ff800) >> 11) | (dv << 9);
0143         daq_samples[(j * 3 + 2) * MAXIMUM_SAMPLES_PER_CHANNEL + ts] =
0144             ((dat & 0x00000400)) | ((dat & 0x000003fe) >> 1) | (dv << 9);
0145       }
0146     }
0147     // now loop over channels - set daq_lengths with error bits
0148     int ichan;
0149     for (ichan = 0; ichan < CHANNELS_PER_SPIGOT; ichan++) {
0150       daq_lengths[ichan] = tsamples;
0151       for (ts = 0; ts < tsamples; ts++) {
0152         int erdv = (daq_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + ts] & 0x600) >> 9;
0153         int capid = (daq_samples[ichan * MAXIMUM_SAMPLES_PER_CHANNEL + ts] & 0x180) >> 7;
0154         if (erdv != 1 || (ts != 0 && (capid != ((lastCapid + 1) % 4)))) {
0155           daq_lengths[ichan] |= 0x80;
0156         }
0157         lastCapid = capid;
0158       }
0159     }
0160   }
0161 }
0162 
0163 void CastorCORData::pack(unsigned char* daq_lengths,
0164                          unsigned short* daq_samples,
0165                          unsigned char* tp_lengths,
0166                          unsigned short* tp_samples,
0167                          bool do_capid) {
0168   int tp_words_total = 0, daq_words_total = 0, headerLen, trailerLen, triggerLen;
0169   determineStaticLengths(headerLen, trailerLen, triggerLen);
0170 
0171   tp_words_total = 0;
0172   daq_words_total = 0;
0173   int isample;
0174 
0175   // trigger words
0176   unsigned short* ptr = m_ownData + headerLen;
0177   if (tp_samples != nullptr && tp_lengths != nullptr) {
0178     for (isample = 0; isample < tp_lengths[0] && isample < 12; isample++) {
0179       ptr[tp_words_total] = tp_samples[isample];
0180       tp_words_total++;
0181     }
0182   }
0183 
0184   // daq words
0185   ptr = m_ownData + headerLen + triggerLen;
0186   int timesamples = std::min(daq_lengths[0] & 0x3f, MAXIMUM_SAMPLES_PER_CHANNEL);
0187   int ts, capid, j;
0188   unsigned long dat;
0189   unsigned short s1, s2, s3;
0190   bool somevalid;
0191 
0192   for (ts = 0; ts < timesamples; ts++) {
0193     capid = ts % 4;
0194     for (j = 0; j < 12; j++) {
0195       somevalid = false;
0196       if (daq_lengths[j * 3] == 0 || (daq_lengths[j * 3] & 0xc0)) {
0197         s1 = 0x400;  // ER !DV
0198       } else {
0199         s1 = daq_samples[(j * 3) * MAXIMUM_SAMPLES_PER_CHANNEL + ts];
0200         somevalid = true;
0201       }
0202       if (daq_lengths[j * 3 + 1] == 0 || (daq_lengths[j * 3 + 1] & 0xc0)) {
0203         s2 = 0x400;  // ER !DV
0204       } else {
0205         s2 = daq_samples[(j * 3 + 1) * MAXIMUM_SAMPLES_PER_CHANNEL + ts];
0206         somevalid = true;
0207       }
0208       if (daq_lengths[j * 3 + 2] == 0 || (daq_lengths[j * 3 + 2] & 0xc0)) {
0209         s3 = 0x400;  // ER !DV
0210       } else {
0211         s3 = daq_samples[(j * 3 + 2) * MAXIMUM_SAMPLES_PER_CHANNEL + ts];
0212         somevalid = true;
0213       }
0214       //dat = 0x80000001 // msb is dv for the fibre
0215       //// sample data  is ER(1)+CAPID(2)+EXP(2)+Mantissa(5)
0216       //// daq_samples has ER(1)+DV(1)+CAPID(2)+EXP(2)+Mantissa(5)
0217       //// should check daq_lengths for the 3 channels here ??
0218       //|  ( daq_samples[(j*3  )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 21
0219       //|  ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 11
0220       //|  ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) <<  1
0221       //|  ( daq_samples[(j*3  )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 20
0222       //|  ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 10
0223       //|  ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) ;
0224       dat = 0x00000001  // msb is dv for the fibre
0225                         // sample data  is ER(1)+CAPID(2)+EXP(2)+Mantissa(5)
0226             // daq_samples has ER(1)+DV(1)+CAPID(2)+EXP(2)+Mantissa(5)
0227             // should check daq_lengths for the 3 channels here ??
0228             | (s1 & 0x1ff) << 21 | (s2 & 0x1ff) << 11 | (s3 & 0x1ff) << 1 | (s1 & 0x400) << 20 | (s2 & 0x400) << 10 |
0229             (s3 & 0x400);
0230       if (somevalid)
0231         dat |= 0x80000000;
0232       // should we set dv from daq_samples ??
0233       if (do_capid)
0234         dat = (dat & 0xcff3fcff) | capid << 28 | capid << 18 | capid << 8;
0235       ptr[daq_words_total++] = dat >> 16;
0236       ptr[daq_words_total++] = dat & 0xffff;
0237     }
0238   }
0239 
0240   m_ownData[5] = (tp_words_total << 8) | 0x1;
0241   unsigned short totalLen = headerLen + 12 + daq_words_total + trailerLen;
0242 
0243   m_rawLength = totalLen;
0244   m_ownData[totalLen - 2] = totalLen / 2;  // 32-bit words
0245   m_ownData[totalLen - 3] = totalLen;
0246   m_ownData[totalLen - 4] = daq_words_total;
0247 }
0248 
0249 void CastorCORData::packHeaderTrailer(
0250     int L1Anumber, int bcn, int submodule, int orbitn, int pipeline, int ndd, int nps, int firmwareRev) {
0251   m_ownData[0] = L1Anumber & 0xFF;
0252   m_ownData[1] = (L1Anumber & 0xFFFF00) >> 8;
0253 
0254   m_ownData[2] = 0x8000;  // Version is valid, no error bits - status bits need definition
0255   m_ownData[3] = ((orbitn & 0x1F) << 11) | (submodule & 0x7FF);
0256   m_ownData[4] = ((m_formatVersion & 0xF) << 12) | (bcn & 0xFFF);
0257   m_ownData[5] |= ((nps & 0xF) << 4) | 0x1;
0258   m_ownData[6] = ((firmwareRev & 0x70000) >> 3) | (firmwareRev & 0x1FFF);
0259   m_ownData[7] = (pipeline & 0xFF) | ((ndd & 0x1F) << 8);
0260   m_ownData[m_rawLength - 4] &= 0x7FF;
0261   m_ownData[m_rawLength - 4] |= (ndd & 0x1F) << 11;
0262 
0263   m_ownData[m_rawLength - 2] = m_rawLength / 2;  // 32-bit words
0264   m_ownData[m_rawLength - 1] = (L1Anumber & 0xFF) << 8;
0265 }
0266 
0267 unsigned int CastorCORData::getOrbitNumber() const { return (m_rawConst[3] >> 11); }
0268 unsigned int CastorCORData::getSubmodule() const { return (m_rawConst[3] & 0x7FF); }
0269 unsigned int CastorCORData::htrSlot() const {
0270   const unsigned int smid = getSubmodule();
0271   return ((smid >> 1) & 0x1F);
0272 }
0273 unsigned int CastorCORData::htrTopBottom() const {
0274   const unsigned int smid = getSubmodule();
0275   return (smid & 0x01);
0276 }
0277 unsigned int CastorCORData::readoutVMECrateId() const {
0278   const unsigned int smid = getSubmodule();
0279   return ((smid >> 6) & 0x1F);
0280 }
0281 bool CastorCORData::isCalibrationStream() const { return (m_formatVersion == -1) ? (false) : (m_rawConst[2] & 0x4000); }
0282 bool CastorCORData::isUnsuppressed() const { return (m_formatVersion < 4) ? (false) : (m_rawConst[6] & 0x8000); }
0283 bool CastorCORData::wasMarkAndPassZS(int fiber, int fiberchan) const {
0284   if (fiber < 1 || fiber > 8 || fiberchan < 0 || fiberchan > 2)
0285     return false;
0286   if (!isUnsuppressed() || m_formatVersion < 5)
0287     return false;
0288   unsigned short val = (fiber < 5) ? (m_rawConst[m_rawLength - 12]) : (m_rawConst[m_rawLength - 11]);
0289   int shift = (((fiber - 1) % 4) * 3) + fiberchan;
0290   return ((val >> shift) & 0x1) != 0;
0291 }
0292 
0293 bool CastorCORData::isPatternRAMEvent() const { return (m_formatVersion == -1) ? (false) : (m_rawConst[2] & 0x1000); }
0294 bool CastorCORData::isHistogramEvent() const {
0295   return (m_formatVersion == -1) ? (m_rawConst[2] & 0x2) : (m_rawConst[2] & 0x2000);
0296 }
0297 int CastorCORData::getNDD() const {
0298   return (m_formatVersion == -1) ? (m_rawConst[m_rawLength - 4] >> 8) : (m_rawConst[m_rawLength - 4] >> 11);
0299 }
0300 int CastorCORData::getNTP() const {
0301   int retval = -1;
0302   if (m_formatVersion == -1)
0303     retval = m_rawConst[m_rawLength - 4] & 0xFF;
0304   else if (m_formatVersion < 3)
0305     retval = m_rawConst[m_rawLength - 4] >> 11;
0306   return retval;
0307 }
0308 int CastorCORData::getNPrecisionWords() const {
0309   return (m_formatVersion == -1) ? (m_rawConst[m_rawLength - 4] & 0xFF) : (m_rawConst[m_rawLength - 4] & 0x7FF);
0310 }
0311 int CastorCORData::getNPS() const { return (m_formatVersion == -1) ? (0) : ((m_rawConst[5] >> 4) & 0xF); }
0312 unsigned int CastorCORData::getPipelineLength() const { return (m_rawConst[7] & 0xFF); }
0313 unsigned int CastorCORData::getFirmwareRevision() const { return (m_rawConst[6]); }
0314 
0315 void CastorCORData::getHistogramFibers(int& a, int& b) const {
0316   a = -1;
0317   b = -1;
0318   if (m_formatVersion == -1) {
0319     a = ((m_rawConst[2] & 0x0F00) >> 8);
0320     b = ((m_rawConst[2] & 0xF000) >> 12);
0321   } else {
0322     a = ((m_rawConst[5] & 0x0F00) >> 8);
0323     b = ((m_rawConst[5] & 0xF000) >> 12);
0324   }
0325 }
0326 
0327 bool CastorCORData::unpackHistogram(int myfiber, int mysc, int capid, unsigned short* histogram) const {
0328   // check for histogram mode
0329   if (!isHistogramEvent())
0330     return false;
0331 
0332   int fiber1, fiber2;
0333   getHistogramFibers(fiber1, fiber2);
0334   if (fiber1 != myfiber && fiber2 != myfiber)
0335     return false;
0336 
0337   if (m_formatVersion == -1) {
0338     int offset = 6 + mysc * 4 * 32 + capid * 32;
0339     if (myfiber == fiber2)
0340       offset += 3 * 4 * 32;  // skip to the second half...
0341     for (int i = 0; i < 32; i++)
0342       histogram[i] = m_rawConst[offset + i];
0343     return true;
0344   } else {
0345     int offset = 8 + mysc * 4 * 32 + capid * 32;
0346     if (myfiber == fiber2)
0347       offset += 3 * 4 * 32;  // skip to the second half...
0348     for (int i = 0; i < 32; i++)
0349       histogram[i] = m_rawConst[offset + i];
0350     return true;
0351   }
0352 }