#ifndef __ANTARESDAQ__ARS__ #define __ANTARESDAQ__ARS__ #include #include #include #include #include "antares-dataformat/DataTypes.hh" /** * ARS timestamp LSB [ns] */ static const double ARS_TIMESTAMP_NS = 25.0; /** * ARS item interface. */ class ARS_Item { public: /** * Virtual destructor. */ virtual ~ARS_Item() {} ClassDef(ARS_Item,2); }; /** * ARS STATUS */ class Status_Item : public ARS_Item { public: /** ARS status */ unsigned char status; /** ARS timestamp (24 bits) */ unsigned int timestamp; /** * Default constructor. */ Status_Item() : status(0), timestamp(0) {} /** * Print ASCII. * * \param out output stream * \param object Status item * \return output stream */ friend std::ostream& operator<<(std::ostream& out, const Status_Item& object) { using namespace std; return out << setw(2) << setfill('0') << hex << (int) object.status << setw(6) << setfill('0') << hex << object.timestamp << setfill(' ') << dec; } /** ROOT class definition */ ClassDef(Status_Item, 2); }; /** * ARS RTS */ class RTS_Item : public Status_Item { public: /** * Default constructor. */ RTS_Item() : Status_Item() {} /** ROOT class definition */ ClassDef(RTS_Item, 2); }; /** * ARS CRM */ class CRM_Item : public Status_Item { public: /** ARS Count Rate Monitor value */ unsigned char crm; /** * Default constructor. */ CRM_Item() : Status_Item(), crm(0) {} /** * Print ASCII. * * \param out output stream * \param object CRM item * \return output stream */ friend std::ostream& operator<<(std::ostream& out, const CRM_Item& object) { using namespace std; out << static_cast(object); out << setw(2) << hex << object.crm << dec; return out; } /** ROOT class definition */ ClassDef(CRM_Item, 2); }; /** * ARS SPE */ class SPE_Item : public Status_Item { public: /** ARS Analogue to Voltage Convertor */ unsigned char avc; /** ARS Time to Voltage Convertor */ unsigned char tvc; /** * Default constructor. */ SPE_Item() : Status_Item(), avc(0), tvc(0) {} /** * Print ASCII. * * \param out output stream * \param object SPE item * \return output stream */ friend std::ostream& operator<<(std::ostream& out, const SPE_Item& object) { using namespace std; out << static_cast(object); out << setw(2) << setfill('0') << hex << (int) object.avc << setw(2) << setfill('0') << hex << (int) object.tvc << setfill(' ') << dec; return out; } /** ROOT class definition */ ClassDef(SPE_Item, 2); }; /** * Anode waveform sample */ class AWF_Sample { public: /** TVC */ unsigned char time; /** AVC */ unsigned char anode; /** * Default constructor. */ AWF_Sample() : time(0), anode(0) {} /** * Virtual destructor. */ virtual ~AWF_Sample() {}; /** ROOT class definition */ ClassDef(AWF_Sample, 2); }; /** * Dynode waveform sample */ class DWF_Sample : public AWF_Sample { public: /** AVC dynode 1 */ unsigned char dynode1; /** AVC dynode 2 */ unsigned char dynode2; /** * Default constructor. */ DWF_Sample() : AWF_Sample(), dynode1(0), dynode2(0) {} /** ROOT class definition */ ClassDef(DWF_Sample, 2); }; /** * ARS WF header interface * * Note that the waveform header is padded to 4x4 Bytes * due to the minimal bus transfer size of 4 words. */ class WF_Header : public SPE_Item { public: /** Waveform address */ unsigned char waveformAddress; /** * Default constructor. */ WF_Header() : SPE_Item(), waveformAddress(0) {} /** ROOT class definition */ ClassDef(WF_Header, 2); }; /** * ARS waveform */ template class WF_Item : public WF_Header { protected: /** * number of waveform samples */ static const unsigned int NUMBER_OF_SAMPLES = 128; /** data */ T data_[NUMBER_OF_SAMPLES]; public: typedef T* iterator; //!< iterator typedef const T* const_iterator; //!< const iterator /** begin iterator of waveform data */ iterator begin() { return data_; } /** end iterator of waveform data */ iterator end() { return data_ + NUMBER_OF_SAMPLES; } /** access to waveform data */ const T& operator[](const int i) { return data_[i]; } /** * Default constructor. */ WF_Item() : WF_Header() {} /** ROOT class definition */ ClassDef(WF_Item, 2); }; ClassDefT2(WF_Item,T); ClassImpT(WF_Item,T); /** * ARS Anode waveform */ class AWF_Item : public WF_Item { public: /** * Default constructor. */ AWF_Item() : WF_Item() {} /** ROOT class definition */ ClassDef(AWF_Item, 2); }; /** * ARS Dynode waveform */ class DWF_Item : public WF_Item { public: /** * Default constructor. */ DWF_Item() : WF_Item() {} /** ROOT class definition */ ClassDef(DWF_Item, 2); }; /** * Determine the TVC number. * * \param timestamp ARS time stamp * \param tvc ARS TVC value * \return 0/1 */ inline int getTVC(const unsigned int timestamp, const unsigned char tvc) { switch (timestamp & 0x3) { case 0: if (tvc & 0x80) return 1; else return 0; break; case 1: return 0; break; case 2: if (tvc & 0x80) return 0; else return 1; break; case 3: return 1; break; } return 0; } /** * equal operator for Status item * * \param first Status item * \param second Status item * \return true if first equals second; else false */ inline bool operator==(const Status_Item& first, const Status_Item& second) { return (first.timestamp == second.timestamp); } /** * not-equal operator for Status item * * \param first Status item * \param second Status item * \return true if first not equals second; else false */ inline bool operator!=(const Status_Item& first, const Status_Item& second) { return (first.timestamp != second.timestamp); } /** * comparator for Status item; earliest hit first * * \param first Status item * \param second Status item * \return true if first earlier than second; else false */ inline bool operator<(const Status_Item& first, const Status_Item& second) { return (first.timestamp < second.timestamp); } /** * equal operator for SPE item * * \param first SPE item * \param second SPE item * \return true if first equals second; else false */ inline bool operator==(const SPE_Item& first, const SPE_Item& second) { return (first.timestamp == second.timestamp && first.tvc == second.tvc); } /** * not-equal operator for SPE item * * \param first SPE item * \param second SPE item * \return true if first not equals second; else false */ inline bool operator!=(const SPE_Item& first, const SPE_Item& second) { return (first.timestamp != second.timestamp || first.tvc != second.tvc); } /** * comparator for SPE item; earliest hit first * * \param first SPE item * \param second SPE item * \return true if first earlier than second; else false */ inline bool operator<(const SPE_Item& first, const SPE_Item& second) { if (first.timestamp == second.timestamp) { const int firstTvcInUse = getTVC(first.timestamp, first.tvc); const int secondTvcInUse = getTVC(second.timestamp, second.tvc); if (firstTvcInUse == secondTvcInUse) return first.tvc < second.tvc; else return firstTvcInUse < secondTvcInUse; //! } else { return first.timestamp < second.timestamp; } } /** * comparator for SPE item; earliest hit first * * \param first SPE item * \param second timestamp * \return true if first earlier than second; else false */ inline bool operator<(const SPE_Item& first, const unsigned int second) { return first.timestamp < second; } /** * comparator for SPE item; earliest hit first * * \param first timestamp * \param second SPE item * \return true if first earlier than second; else false */ inline bool operator<(const unsigned int first, const SPE_Item& second) { return first < second.timestamp; } #endif