Index: /trunk/FACT++/src/HeadersFAD.h
===================================================================
--- /trunk/FACT++/src/HeadersFAD.h	(revision 10756)
+++ /trunk/FACT++/src/HeadersFAD.h	(revision 10756)
@@ -0,0 +1,327 @@
+#ifndef FACT_HeadersFAD
+#define FACT_HeadersFAD
+
+#include <ostream>
+
+// For debugging
+#include <iostream>
+
+#include "ByteOrder.h"
+
+// ====================================================================
+
+namespace FAD
+{
+    enum States
+    {
+        // State Machine states
+        kDisconnected = 1,
+        kConnecting,
+        kConnected
+    };
+
+    enum
+    {
+        kMaxBins            = 1024,
+        kNumTemp            = 4,
+        kNumDac             = 8,
+        kNumChips           = 4,
+        kNumChannelsPerChip = 9,
+        kNumChannels        = kNumChips*kNumChannelsPerChip,
+    };
+
+    enum
+    {
+        kMaxRegAddr  = 0xff,    // Highest address in config-ram
+        kMaxRegValue = 0xffff,
+        kMaxDacAddr  = kNumDac-1,
+        kMaxDacValue = 0xffff,
+        kMaxRoiAddr  = kNumChannels-1,
+        kMaxRoiValue = kMaxBins,
+    };
+
+    enum
+    {
+        kDelimiterStart = 0xfb01,
+        kDelimiterEnd   = 0x04fe,
+    };
+
+    // --------------------------------------------------------
+
+    struct EventHeader
+    {
+        enum Bits
+        {
+            kDenable       = 1<<11,
+            kDwrite        = 1<<10,
+            kRefClkTooHigh = 1<< 9,
+            kRefClkTooLow  = 1<< 8,
+            kDcmLocked     = 1<< 7,
+            kDcmReady      = 1<< 6,
+            kSpiSclk       = 1<< 5,
+        };
+
+        // Einmalig:     (new header changes entry in array --> send only if array changed)
+        // ----------------------------------
+        // Event builder stores an array with all available values.
+        // Disconnected boards are removed (replaced by def values)
+        // Any received header information is immediately put in the array.
+        // The array is transmitted whenever it changes.
+        // This will usually happen only very rarely when a new connection
+        // is opened.
+        //
+        // Array[40] of BoardId
+        // Array[40] of Version
+        // Array[40] of DNA
+
+        // Slow changes: (new header changes entry in array --> send only if arra changed)
+        // -------------------------------------------
+        // Event builder stores an array with all available values.
+        // Disconnected boards can be kept in the arrays.
+        // Any received header information is immediately put in the array.
+        // The array is transmitted whenever it changes.
+        //
+        // Connection status (disconnected, connecting, connected) / Array[40]
+        // Consistency of PLLLCK       / Array[  40] of PLLLCK
+        // Consistency of Trigger type / Array[  40] of trigger type
+        // Consistency of ROI          / Array[1440] of ROI
+        // Consistency of RefClock     / Array[  40] of ref clock
+        // Consistency of DAC values   / Array[ 400] of DAC values
+        // Consistency of run number   / Array[  40] of Run numbers
+
+        // Fast changes  (new header changes value --> send only if something changed)
+        // -------------------
+        // Event builder stores an internal array of all boards and
+        //  transmits the min/max values determined from the array
+        //  only if they have changed. Disconnected boards are not considered.
+        //
+        // Maximum/minimum Event counter of all boards in memory + board id
+        // Maximum/minimum time stamp    of all boards in memory + board id
+        // Maximum/minimum temp          of all boards in memory + board id
+
+        // Unknown:
+        // ------------------
+        // Trigger Id ?
+        // TriggerGeneratorPrescaler ?
+        // Number of Triggers to generate ?
+
+
+        // ------------------------------------------------------------
+
+        uint16_t fStartDelimiter;     // 0x04FE
+        uint16_t fPackageLength;
+        uint16_t fVersion;
+        uint16_t fPLLLCK;
+        //
+        uint16_t fTriggerCrc;
+        uint16_t fTriggerType;
+        uint32_t fTriggerId;
+        //
+        uint32_t fEventCounter;
+        uint32_t fFreqRefClock;
+        //
+        uint16_t fBoardId;
+        uint16_t fAdcClockPhaseShift;
+        uint16_t fNumTriggersToGenerate;
+        uint16_t fTriggerGeneratorPrescaler;
+        //
+        uint64_t fDNA; // Xilinx DNA
+        //
+        uint32_t fTimeStamp;
+        uint32_t fRunNumber;
+        //
+        int16_t  fTempDrs[kNumTemp];   // In units of 1/16 deg(?)
+        //
+        uint16_t fDac[kNumDac];
+        //
+
+        EventHeader() { init(*this); }
+
+        void operator=(const std::vector<uint16_t> &vec)
+        {
+            ntohcpy(vec, *this);
+
+            Reverse(((uint16_t*)fEventCounter));
+            Reverse(((uint16_t*)fEventCounter)+1);
+
+            Reverse(&fEventCounter);
+
+            Reverse(((uint16_t*)fFreqRefClock));
+            Reverse(((uint16_t*)fFreqRefClock)+1);
+
+            Reverse(&fFreqRefClock);
+
+            Reverse(((uint16_t*)&fTimeStamp));
+            Reverse(((uint16_t*)&fTimeStamp)+1);
+
+            Reverse(&fTimeStamp);
+
+            Reverse(((uint16_t*)&fRunNumber));
+            Reverse(((uint16_t*)&fRunNumber)+1);
+
+            Reverse(&fRunNumber);
+            Reverse(&fDNA);
+
+/*
+            // Extract temperatures (MSB indicates if temperature
+            // is positive or negative)
+            for (int i=0; i<kNumTemp; i++)
+            {
+                if (fTempDrs[i]&0x8000)
+                    fTempDrs[i] |= 0xE000;
+                fTempDrs[i]>>=3;
+            }
+            */
+        }
+
+        float GetTemp(int i) const
+        {
+            return (((fTempDrs[i]&0x8000)
+                     ?
+                     ((fTempDrs[i]&0x007fff)^0xffffffff)
+                     : (fTempDrs[i]&0x007fff))>>3)/16.; }
+
+        uint8_t PllLock() const        { return  fPLLLCK>>12; }
+
+        bool HasDenable() const        { return fPLLLCK&kDenable; }
+        bool HasDwrite() const         { return fPLLLCK&kDwrite; }
+        bool IsRefClockTooHigh() const { return fPLLLCK&kRefClkTooHigh; }
+        bool IsRefClockTooLow() const  { return fPLLLCK&kRefClkTooLow; }
+        bool IsDcmLocked() const       { return fPLLLCK&kDcmLocked; }
+        bool IsDcmReady() const        { return fPLLLCK&kDcmReady; }
+        bool HasSpiSclk() const        { return fPLLLCK&kSpiSclk; }
+
+        void clear() { reset(*this); }
+        void print(std::ostream &out) const;
+
+    } __attribute__((__packed__));
+
+    struct ChannelHeader
+    {
+        uint16_t fId;
+        uint16_t fStartCell;
+        uint16_t fRegionOfInterest;
+        uint16_t fDummy;
+        // uint16_t fData[];
+
+        ChannelHeader() { init(*this); }
+
+        void operator=(const std::vector<uint16_t> &vec)
+        {
+            ntohcpy(vec, *this);
+        }
+
+        void clear() { reset(*this); }
+        void print(std::ostream &out) const;
+
+    } __attribute__((__packed__));
+
+    // Package ends with:
+    //   0x4242
+    //   0x04fe
+
+    struct DimPassport
+    {
+        uint32_t fTimeStamp;
+
+        uint16_t fVersion;
+        uint16_t fBoardId;
+        uint64_t fDNA; // Xilinx DNA
+
+        DimPassport(const EventHeader &h) :
+            fTimeStamp(h.fTimeStamp),
+            fVersion(h.fVersion),
+            fBoardId(h.fBoardId),
+            fDNA(h.fDNA)
+        {
+        }
+
+    }  __attribute__((__packed__));
+
+    struct DimSetup
+    {
+        uint32_t fTimeStamp;
+
+        uint32_t fFreqRefClock;
+        uint16_t fPLLLCK;
+        uint16_t fAdcClockPhaseShift;
+        uint16_t fNumTriggersToGenerate;
+        uint16_t fTriggerGeneratorPrescaler;
+        uint16_t fDac[kNumDac];
+
+        DimSetup(const EventHeader &h) :
+            fTimeStamp(h.fTimeStamp),
+            fFreqRefClock(h.fFreqRefClock),
+            fPLLLCK(h.fPLLLCK),
+            fAdcClockPhaseShift(h.fAdcClockPhaseShift),
+            fNumTriggersToGenerate(h.fNumTriggersToGenerate),
+            fTriggerGeneratorPrescaler(h.fTriggerGeneratorPrescaler)
+        {
+            memcpy(fDac, h.fDac, sizeof(fDac));
+        }
+
+        uint8_t PllLock() const        { return fPLLLCK>>12; }
+
+        bool HasDenable() const        { return fPLLLCK&EventHeader::kDenable; }
+        bool HasDwrite() const         { return fPLLLCK&EventHeader::kDwrite; }
+        bool IsRefClockTooHigh() const { return fPLLLCK&EventHeader::kRefClkTooHigh; }
+        bool IsRefClockTooLow() const  { return fPLLLCK&EventHeader::kRefClkTooLow; }
+        bool IsDcmLocked() const       { return fPLLLCK&EventHeader::kDcmLocked; }
+        bool IsDcmReady() const        { return fPLLLCK&EventHeader::kDcmReady; }
+        bool HasSpiSclk() const        { return fPLLLCK&EventHeader::kSpiSclk; }
+
+    }  __attribute__((__packed__));
+
+    struct DimTemperatures
+    {
+        uint32_t fTimeStamp;
+
+        float fTempDrs[kNumTemp];
+
+        DimTemperatures(const EventHeader &h) :
+            fTimeStamp(h.fTimeStamp)
+        {
+            for (int i=0; i<kNumTemp; i++)
+                fTempDrs[i] = h.GetTemp(i);
+        }
+
+    } __attribute__((__packed__));;
+
+    struct DimEventHeader
+    {
+        uint32_t fTimeStamp;
+
+        uint32_t fRunNumber;
+        uint32_t fEventCounter;
+        uint16_t fTriggerCrc;
+        uint16_t fTriggerType;
+        uint32_t fTriggerId;
+
+        DimEventHeader(const EventHeader &h) :
+            fTimeStamp(h.fTimeStamp),
+            fRunNumber(h.fRunNumber),
+            fEventCounter(h.fEventCounter),
+            fTriggerCrc(h.fTriggerCrc),
+            fTriggerType(h.fTriggerType),
+            fTriggerId(h.fTriggerId)
+        {
+        }
+
+    }  __attribute__((__packed__));
+
+    // --------------------------------------------------------------------
+
+    inline std::ostream &operator<<(std::ostream &out, const EventHeader &h)
+    {
+        h.print(out);
+        return out;
+    }
+
+    inline std::ostream &operator<<(std::ostream &out, const ChannelHeader &h)
+    {
+        h.print(out);
+        return out;
+    }
+};
+
+#endif
