/*! \brief extract channel information from raw data

  ReadBuffData extracts channel information from the raw data arrays
  and places it into a structure called evt.  A pointer to each
  of the evt objects is placed in the eventlist vector for later time
  sorting.
  \param [in] buf : the buffer to process
  \param [in] bufLen : the length of the buffer
  \param [in] eventList : the event list to add the extracted buffer to
  \return An unused integer
*/
int ReadBuffDataDF(word_t *buf, unsigned long *bufLen,
                   vector<ChanEvent*> &eventList) {
    // multiplier for high bits of 48-bit time
    static const double HIGH_MULT = pow(2., 32.);
    word_t modNum;
    unsigned long numEvents = 0;
    word_t *bufStart = buf;
    /* Determine the number of words in the buffer */
    *bufLen = *buf++;
    /* Read the module number */
    modNum = *buf++;
    ChanEvent *lastVirtualChannel = NULL;
    if(*bufLen > 0) {   // check if the buffer has data
        if(*bufLen == 2) {
            // this is an empty channel
            return 0;
        }
        do {
            ChanEvent *currentEvt = new ChanEvent;
            // decoding event data... see pixie16app.c
            // buf points to the start of channel data
            word_t chanNum      = (buf[0] & 0x0000000F);
            word_t slotNum      = (buf[0] & 0x000000F0) >> 4;
            word_t crateNum     = (buf[0] & 0x00000F00) >> 8;
            word_t headerLength = (buf[0] & 0x0001F000) >> 12;
            word_t eventLength  = (buf[0] & 0x1FFE0000) >> 17;
            currentEvt->virtualChannel = ((buf[0] & 0x20000000) != 0);
            currentEvt->saturatedBit   = ((buf[0] & 0x40000000) != 0);
            currentEvt->pileupBit      = ((buf[0] & 0x80000000) != 0);
            // Rev. D header lengths not clearly defined in pixie16app_defs
            //! magic numbers here for now
            // make some sanity checks
            if(headerLength == stats.headerLength) {
                // this is a manual statistics block inserted by the poll program
                stats.DoStatisticsBlock(&buf[1], modNum);
                buf += eventLength;
                numEvents = readbuff::STATS;
                continue;
            }
            if(headerLength != 4  && headerLength != 8 &&
                headerLength != 12 && headerLength != 16) {
                cout << "  Unexpected header length: " << headerLength << endl;
                cout << "    Buffer " << modNum << " of length " << *bufLen << endl;
                cout << "    CHAN:SLOT:CRATE "
                     << chanNum << ":" << slotNum << ":" << crateNum << endl;
                // advance to next event and continue
                // buf += EventLength;
                // continue;
                // skip the rest of this buffer
                return readbuff::ERROR;
                //return numEvents;
            }
            word_t lowTime     = buf[1];
            word_t highTime    = buf[2] & 0x0000FFFF;
            word_t cfdTime     = (buf[2] & 0xFFFF0000) >> 16;
            word_t energy      = buf[3] & 0x0000FFFF;
            word_t traceLength = (buf[3] & 0xFFFF0000) >> 16;
            if(headerLength == 8 || headerLength == 16) {
                // skip the onboard partial sums for now
                //   trailing, leading, gap, baseline
            }
            if(headerLength >= 12) {
                int offset = headerLength - 8;
                for(int i=0; i < currentEvt->numQdcs; i++) {
                        currentEvt->qdcValue[i] = buf[offset + i];
                }
            }
            // one last sanity check
            if(traceLength / 2 + headerLength != eventLength) {
                cout << "  Bad event length (" << eventLength
                    << ") does not correspond with length of header (" << headerLength
                    << ") and length of trace (" << traceLength << ")" << endl;
                buf += eventLength;
                continue;
            }
            // handle multiple crates
            modNum += 100 * crateNum;
            currentEvt->chanNum = chanNum;
            currentEvt->modNum = modNum;
            if(currentEvt->virtualChannel) {
                DetectorLibrary* modChan = DetectorLibrary::get();
                currentEvt->modNum += modChan->GetPhysicalModules();
                if(modChan->at(modNum, chanNum).HasTag("construct_trace")) {
                        lastVirtualChannel = currentEvt;
                }
            }
            currentEvt->energy = energy;
            //KM 2012-10-24 reinstating removal of saturated
            if(currentEvt->saturatedBit)
                currentEvt->energy = 16383;
            currentEvt->trigTime = lowTime;
            currentEvt->cfdTime  = cfdTime;
            currentEvt->eventTimeHi = highTime;
            currentEvt->eventTimeLo = lowTime;
            currentEvt->time = highTime * HIGH_MULT + lowTime;
            buf += headerLength;
            /* Check if trace data follows the channel header */
            if(traceLength > 0) {
                // sbuf points to the beginning of trace data
                halfword_t *sbuf = (halfword_t *)buf;
                currentEvt->trace.reserve(traceLength);
                if(currentEvt->saturatedBit)
                    currentEvt->trace.SetValue("saturation", 1);
                if(lastVirtualChannel != NULL && lastVirtualChannel->trace.empty()) {
                    lastVirtualChannel->trace.assign(traceLength, 0);
                }
                // Read the trace data (2-bytes per sample, i.e. 2 samples per word)
                for(unsigned int k = 0; k < traceLength; k ++) {
                    currentEvt->trace.push_back(sbuf[k]);
                    if(lastVirtualChannel != NULL) {
                        lastVirtualChannel->trace[k] += sbuf[k];
                    }
                }
                buf += traceLength / 2;
            }
            eventList.push_back(currentEvt);
            numEvents++;
        } while(buf < bufStart + *bufLen);
    } else {  // if buffer has data
Exemple #2
0
/*! \brief extract channel information from raw data

  ReadBuffData extracts channel information from the raw data arrays
  and places it into a structure called evt.  A pointer to each
  of the evt objects is placed in the eventlist vector for later time
  sorting.
  \param [in] buf : the buffer to process
  \param [in] bufLen : the length of the buffer
  \param [in] eventList : the event list to add the extracted buffer to
  \return An unused integer */
int ReadBuffDataF(word_t *buf, unsigned long *bufLen,
                  vector<ChanEvent*> &eventList) {
    // multiplier for high bits of 48-bit time
    static const double HIGH_MULT = pow(2., 32.);
    word_t modNum;
    unsigned long numEvents = 0;
    word_t *bufStart = buf;
    /* Determine the number of words in the buffer */
    *bufLen = *buf++;
    /* Read the module number */
    modNum = *buf++;
    ChanEvent *lastVirtualChannel = NULL;
    if(*bufLen > 0) {   // check if the buffer has data
        if(*bufLen == 2) {
            // this is an empty channel
            return 0;
        }
        do {
            ChanEvent *currentEvt = new ChanEvent;
            // decoding event data... see pixie16app.c
            // buf points to the start of channel data

	    //Decode the first header word
            word_t chanNum        = (buf[0] & 0x0000000F);
            word_t slotNum        = (buf[0] & 0x000000F0) >> 4;
            word_t crateNum       = (buf[0] & 0x00000F00) >> 8;
            word_t headerLength   = (buf[0] & 0x0001F000) >> 12;
            word_t eventLength    = (buf[0] & 0x7FFE0000) >> 17;
            currentEvt->pileupBit = (buf[0] & 0x80000000) != 0;

	    // Sanity check
            if(headerLength == stats.headerLength) {
                // this is a manual statistics block inserted poll
                stats.DoStatisticsBlock(&buf[1], modNum);
                buf += eventLength;
                numEvents = readbuff::STATS;
                continue;
            }

	    //Decode the second header word
            word_t lowTime     = buf[1];

	    //Decode the third header word
        word_t highTime            = buf[2] & 0x0000FFFF;
        word_t cfdTime             = (buf[2] & 0x3FFF0000) >> 16;
	    currentEvt->cfdTrigSource  = ((buf[2] & 0x40000000) != 0);
	    currentEvt->cfdForceTrig   = ((buf[2] & 0x80000000) != 0);

	    //Decode the foruth header word
        word_t energy            = buf[3] & 0x0000FFFF;
        word_t traceLength       = (buf[3] & 0x7FFF0000) >> 16;
	    currentEvt->saturatedBit = ((buf[3] & 0x80000000) != 0);

	    int offset = headerLength - 8;
	    switch(headerLength) {
	    case 4:
	    case 6:
	    case 8:
	    case 10:
		break;
	    case 12:
	    case 14:
	    case 16:
	    case 18:
                for(int i=0; i < currentEvt->numQdcs; i++)
                        currentEvt->qdcValue[i] = buf[offset + i];
		break;
	    default:
		cerr << "  Unexpected header length: " << headerLength << endl;
                cerr << "    Buffer " << modNum << " of length " << *bufLen << endl;
                cerr << "    CHAN:SLOT:CRATE "
                     << chanNum << ":" << slotNum << ":" << crateNum << endl;
                return readbuff::ERROR;
		break;
	    }

            // one last sanity check
            if(traceLength / 2 + headerLength != eventLength) {
                cerr << "  Bad event length (" << eventLength
		     << ") does not correspond with length of header ("
		     << headerLength << ") and length of trace ("
		     << traceLength << ")" << endl;
                buf += eventLength;
                continue;
            }

            // handle multiple crates
            modNum += 100 * crateNum;
            currentEvt->chanNum = chanNum;
            currentEvt->modNum = modNum;
            if(currentEvt->virtualChannel) {
                DetectorLibrary* modChan = DetectorLibrary::get();
                currentEvt->modNum += modChan->GetPhysicalModules();
                if(modChan->at(modNum, chanNum).HasTag("construct_trace")) {
                        lastVirtualChannel = currentEvt;
                }
            }
            currentEvt->energy = energy;
            if(currentEvt->saturatedBit)
                currentEvt->energy = 16383;
            currentEvt->trigTime = lowTime;
            currentEvt->cfdTime  = cfdTime;
            currentEvt->eventTimeHi = highTime;
            currentEvt->eventTimeLo = lowTime;
            currentEvt->time = highTime * HIGH_MULT + lowTime;
            buf += headerLength;

            /* Check if trace data follows the channel header */
            if(traceLength > 0) {
                // sbuf points to the beginning of trace data
                halfword_t *sbuf = (halfword_t *)buf;
                currentEvt->trace.reserve(traceLength);
                if(currentEvt->saturatedBit)
                    currentEvt->trace.SetValue("saturation", 1);
                if(lastVirtualChannel != NULL && lastVirtualChannel->trace.empty()) {
                    lastVirtualChannel->trace.assign(traceLength, 0);
                }
                // Read the trace data (2-bytes per sample, i.e. 2 samples per word)
                for(unsigned int k = 0; k < traceLength; k ++) {
                    currentEvt->trace.push_back(sbuf[k]);
                    if(lastVirtualChannel != NULL) {
                        lastVirtualChannel->trace[k] += sbuf[k];
                    }
                }
                buf += traceLength / 2;
            }
            eventList.push_back(currentEvt);
            numEvents++;
        } while(buf < bufStart + *bufLen);
    } else {  // if buffer has data