#ifndef SP605_MESSAGE_H #define SP605_MESSAGE_H #include #include #include #define SP605_SPADIC_MAX_CHANNEL 0xF // 4 bit max channel id #define SP605_SPADIC_MAX_GROUP 0xFF // 8 bit max group id #define SP605_SPADIC_MAX_SAMPLE 0x3F // 6 bit maximum number of samples per message //#define DEBUG605 1 #ifndef DEBUG605 #define DPRINT605( args ...) ; #else #define DPRINT605( args ...) printf( args ) #endif namespace sp605 { /* JAM: start implementing after * spadic specs at http://spadic.uni-hd.de/spadic10/data/spadic10spec.pdf * */ enum MessageFormat { formatSpadic10Direct = 5, // data as they coming from the spadic without any additional CBMnet padding formatSpadic10Optic = 6 // current optical format, including SYNC/AUX messages and }; enum MessageTypes { MSG_NOP = 0, MSG_HIT = 1, MSG_EPOCH = 2, MSG_OVERFLOW = 3, MSG_INFO = 4, MSG_LASTID = 5 }; /* following values reflect bitvalues of hittype data:*/ enum HitTrgTypes { TRIG_GLOBAL = 0, TRIG_SELF = 1, TRIG_NEIGHBOR = 2, TRIG_BOTH = 3 }; /* following values reflect bitvalues of stoptype data:*/ enum MsgStopTypes { STOP_NORMAL = 0, STOP_OUTBUFFULL = 1, STOP_FIFOFULL = 2, STOP_MULTIHIT = 3, STOP_OUTBUFFULLMULTIHIT = 4, STOP_FIFOFULLMULTIHIT = 5 }; /* following values reflect bitvalues of info data:*/ enum InfoTypes { INFO_DIS = 0, // channel disabled during readout, c: channel ID INFO_NGT = 1, // corruption, next grant timeout in switch, c: channel ID INFO_NRT = 2, // corruption, next request timeout in switch INFO_NBE = 3, // corruption, new grant but channel empty in switch, c: channel ID INFO_MSB = 4, // corruption, unknown metadata type in message builder, c: channel ID INFO_NOP = 5, // empty word (may appear within other messages) INFO_SYN = 6 // out of sync warning, e: least significant bits of epoch counter }; class Message { protected: uint8_t fMsgType; // message type as defined in MessageTypes uint16_t fSpadicId; // TODO: id of spadic? uint8_t fGroup; // group id uint8_t fChan; // channel id uint8_t fHitType; // hit type uint8_t fInfoType; // stop type, or info type uint16_t fTimeStamp; // message timestamp uint16_t fEpoch; // field for epoch in different messages uint8_t fTraceSize; std::vector fTraces; // contains unfolded samples. /* will unpack the message bits:*/ void InitTraceBuffer(uint16_t* fRDA); /* helper function to set value to trace buffer. * arguments: sample index bin, sampled value and length of trace len * returns false if we have just set the last sample * otherwise true*/ bool SetTrace(unsigned bin, int16_t value, unsigned len) { if (bin >= fTraces.size()) return false; fTraces[bin] = (value>256) ? value-512 : value; return (bin + 1 == len) ? false : true; } public: Message() { clear(); } ~Message() { } void clear() { fMsgType=MSG_NOP; fSpadicId=0; fGroup=0xff; fChan=0xff; fHitType=0; fEpoch=0; fTimeStamp=0; fTraceSize=0; fTraces.clear(); } /** Method to set pointer on raw buffer which contains message * \param buf is raw buffer, \param fullsz is size of raw buffer - message can be shorter This method will also figure out message types and evaluates pointers to special words inside the message. Return value will indicate shift in buffer until end of current message Note that buf is never owned by the message, but only used as input */ size_t assign(void* buf, unsigned fullsz); uint8_t getMsgType() const { return fMsgType; } // TODO uint16_t getSpadicNumber() const { return fSpadicId; } //TODO! DUMMY Sets the spadic number field in the current message void setSpadicNumber(uint16_t id) { fSpadicId=id;} uint8_t getGroup() const { return fGroup; } // channel number of current trace uint8_t getChNum() const { return fChan; } // return channel num, where group id already included unsigned getFullChNum() const { return getGroup() * 16 + getChNum(); } // ******* HIT message *********** uint8_t getHitType() const { return fHitType; } uint8_t getStopType() const { return fInfoType; } /* length of actual trace in this message. * this is the number of samples*/ uint8_t getTraceSize() const { return fTraceSize; } uint16_t getTimeStamp() const { return fTimeStamp; } // **** OVERFLOW message ******** uint8_t getOverflowHits() const { return fEpoch; } // ***** INFO message ************ uint8_t getInfoType() const { return fInfoType; } uint8_t getInfoChannel() const { return fChan; } uint8_t getInfoEpoch() const { return fEpoch; } /////////////////////////////////////////////////////7 // frontend group at current spadic uint8_t evalGroup(uint16_t* pSOM) const { if(pSOM==0) return 0; return (uint8_t) (( *pSOM >> 4) & 0xFF); } // channel number of current trace uint8_t evalChNum(uint16_t* pSOM) const { if (pSOM == 0) return 0; return (uint8_t)(*pSOM & 0xF); } uint8_t evalHitType(uint16_t* pEOM) const { if (getMsgType() != MSG_HIT || pEOM == 0) return 0; return (uint8_t)((*pEOM >> 4) & 0x3); } uint8_t evalStopType(uint16_t* pEOM) const { if (getMsgType() != MSG_HIT || pEOM == 0) return 0; return (uint8_t)(*pEOM & 0x7); } /* length of actual trace in this message. * this is the number of samples*/ size_t evalTraceSize(uint16_t* pEOM) const { if (getMsgType() != MSG_HIT || pEOM == 0) return 0; return (size_t)((*pEOM >> 6) & 0x3F); } /* access trace sample*/ int16_t getTrace(unsigned bin) { if(getMsgType()!=MSG_HIT) return -1024; if(bin>=getTraceSize()) return -2048; //if(!isReadyTracebuffer) InitTraceBuffer(); return fTraces[bin]; } unsigned getEpoch() const { return fEpoch; } uint16_t evalTimeStamp(uint16_t* fTSW) const { if(fTSW==0) return 0; return (*fTSW & 0xFFF); } uint32_t getMsgFullTime(uint16_t epoch=0) const; double getMsgFullTimeD(uint16_t epoch=0) const; //! Expanded timestamp for 25 MHz and 12 bit epochs // ts unit is 40ns, epoch wraps after 671.1 ms inline static uint32_t FullTimeStamp(uint16_t epoch, uint16_t stamp) { return 40 * (((uint32_t) epoch << 12) | (stamp & 0xfff)); } void printData(); bool isTrace() const { return isHitMsg(); } bool isEpoch() const { return isEpochMsg(); } inline bool isNopMsg() const { return getMsgType() == MSG_NOP; } inline bool isHitMsg() const { return getMsgType() == MSG_HIT; } inline bool isEpochMsg() const { return getMsgType() == MSG_EPOCH;} inline bool isOverflowMsg() const { return getMsgType() == MSG_OVERFLOW; } inline bool isInfoMsg() const { return getMsgType() == MSG_INFO; } }; } #endif