#include "sp605/Message.h" #include const char* sp605_msg_names[sp605::MSG_LASTID] = { "NOP", "HIT", "EPOCH", "OVERFLOW", "INFO" }; const char* sp605_info_names[7] = { "DIS", "NGT", "NRT", "NBE", "MSB", "NOP", "SYN" }; const char* sp605_info_descr[7] = { "channel disabled during readout", "corruption, next grant timeout in switch", "corruption, next request timeout in switch", "corruption, new grant but channel empty in switch", "corruption, unknown metadata type in message builder", "empty word (may appear within other messages)", "out of sync warning" }; size_t sp605::Message::assign(void* buf, unsigned fullsz) { if ((buf==0) || (fullsz<2)) return 0; clear(); //isReadyTracebuffer=false; // we keep this helper pointers locally to avoid large overhead in message data structure uint16_t* pSOM=0; // points to actual start of message word // uint16_t* pTSW=0; // points to actual timestamp word (hit and buffer overflow msgs) uint16_t* pRDA=0; // points to begin of raw data field (hit messages) uint16_t* pEOM=0; // points to end of message word (hit messages) // uint16_t* pBOM=0; // points to buffer overflow word (buffer overflow messages) // uint16_t* pEPM=0; // points to epoch marker (epoch messages) unsigned wordlen = fullsz / sizeof(uint16_t); unsigned wordcnt = 0; uint16_t* cursor = (uint16_t*) buf; // check preamble of start word, may be some or single info word bool israwdata(false); while (wordcnt++ < wordlen) { unsigned kind = (*cursor >>12) & 0xF; // this is raw data, process it later if (israwdata && ((kind & 8) == 0)) { cursor++; continue; } switch (kind) { case 0x8: // start of message if (cursor!=buf) { fprintf(stderr,"SOM inside the message\n"); clear(); } pSOM = cursor; fGroup = evalGroup(pSOM); fChan = evalChNum(pSOM); DPRINT605("sp605::Message::assign: found Start Of Message: 0x%x\n",*cursor); break; case 0x9: // timestamp word fTimeStamp = evalTimeStamp(cursor); DPRINT605("sp605::Message::assign: found Time Stamp Word: 0x%x\n",*cursor); break; case 0xA: // begin of raw data pRDA = cursor; israwdata = true; DPRINT605("sp605::Message::assign: found Begin of Raw DAta: 0x%x\n",*cursor); break; case 0xB: // end of message DPRINT605("sp605::Message::assign: found End Of Message: 0x%x\n",*cursor); pEOM = cursor; fMsgType = MSG_HIT; fHitType = evalHitType(pEOM); fInfoType = evalStopType(pEOM); fTraceSize = evalTraceSize(pEOM); InitTraceBuffer(pRDA); return wordcnt * sizeof(uint16_t); case 0xC: fMsgType = MSG_OVERFLOW; fEpoch = *cursor & 0xFF; // overflow hits DPRINT605("sp605::Message::assign: found Buffer Overflow Message: 0x%x\n",*cursor); return wordcnt * sizeof(uint16_t); case 0xD: // epoch counter fMsgType = MSG_EPOCH; DPRINT605("sp605::Message::assign: found EPoch Marker: 0x%x\n",*cursor); fEpoch = *cursor & 0xFFF; return wordcnt * sizeof(uint16_t); case 0xE: // extracted data //pRDA= cursor; fprintf(stderr,"sp605::Message::assign: data error - extracted data not yet supported!"); break; case 0xF: // info message, single word fMsgType = MSG_INFO; fGroup = 0; fInfoType = (*cursor >>8) & 0xF; switch (fInfoType) { case INFO_DIS: case INFO_NGT: case INFO_NBE: case INFO_MSB: fChan = (*cursor >>4 ) & 0xF; break; case INFO_NRT: case INFO_NOP: break; case INFO_SYN: fEpoch = *cursor & 0xff; break; } DPRINT605("sp605::Message::assign: found INFo Message: 0x%x\n",*cursor); return wordcnt * sizeof(uint16_t); default: fprintf(stderr,"sp605::Message::assign: data error - unknown message header 0x%x\n",*cursor); fMsgType = MSG_NOP; fGroup = 0; return 0; } cursor++; } // check next word: timestamp or epoch counter? // fprintf(stderr,"Cannot decode message completely - not enough bytes"); // indicate that message is not complete and we need more bytes return wordlen + 2; } void sp605::Message::InitTraceBuffer(uint16_t* pRDA) { //isReadyTracebuffer=true; int16_t result(0), rest(0); uint16_t* cursor = pRDA; size_t len = getTraceSize(); fTraces.clear(); fTraces.resize(len, 0); // extract trace words at first call to buffer array // we first write down manually the procedure, then generalize it: // patter repeats every 3 words. There are 45 bit which are 5 samples unsigned bin = 0; while (bin> 3); if(!SetTrace(bin++, result, len)) return; //0 rest = (*cursor & 0x7); cursor++; // cursor to continuation word result = ((*cursor & 0x7FFF) >> 9) | (rest << 6); if(!SetTrace(bin++, result, len)) return; //1 result = (*cursor & 0x1FF); if(!SetTrace(bin++, result, len)) return; //2 cursor++; result = ((*cursor & 0x7FFF) >> 6); if(!SetTrace(bin++, result, len)) return; //3 rest = (*cursor & 0x3F); cursor++; result = ((*cursor & 0x7FFF) >> 12) | (rest << 3); if(!SetTrace(bin++, result, len)) return; //4 } } // ------------------------------------------------------------- uint32_t sp605::Message::getMsgFullTime(uint16_t epoch) const { switch (getMsgType()) { case MSG_HIT: case MSG_OVERFLOW: return FullTimeStamp(epoch, getTimeStamp()); case MSG_EPOCH: return FullTimeStamp(getEpoch(), 0); } return FullTimeStamp(epoch, 0); } //---------------------------------------------------------------------------- //! Returns expanded and adjusted time of message in double (in ns) //! epoch should correspond to the message type double sp605::Message::getMsgFullTimeD(uint16_t epoch) const { return getMsgFullTime(epoch); } void sp605::Message::printData() { printf("MSG:%u %s", (unsigned) getMsgType(), sp605_msg_names[getMsgType()]); if ((getGroup()!=0xff) || (getChNum()!=0xff)) printf(" gr:%x ch:%02x", (unsigned) getGroup(), (unsigned) getChNum()); switch (getMsgType()) { //case MSG_HIT: break; //case MSG_EPOCH: break; //case MSG_OVERFLOW: break; case MSG_INFO: printf(" kind:%u %s", getInfoType(), sp605_info_names[getInfoType()]); switch (getInfoType()) { case INFO_DIS: case INFO_NGT: case INFO_NBE: case INFO_MSB: printf (" c:%u", getInfoChannel()); break; case INFO_NRT: case INFO_NOP: break; case INFO_SYN: printf (" e:%u", getInfoEpoch()); break; } printf(" %s\n", sp605_info_descr[getInfoType()]); break; default: printf("timestamp:%u datasize:%u\n", (unsigned) getTimeStamp(), (unsigned) fTraces.size()); break; } if (fTraces.size()>0) { printf(" ["); for (unsigned n=0;n