source: trunk/FACT++/src/HeadersFTM.h @ 10593

Last change on this file since 10593 was 10593, checked in by tbretz, 9 years ago
Fixed type of fClockConditioner; added proper byte swapping for fClockConditioner; some improvements to output; fixed printing of error message.
File size: 20.3 KB
Line 
1#include <string.h>
2#include <algorithm>
3#include <arpa/inet.h>
4#include <stdexcept>
5#include <typeinfo>
6#include <vector>
7
8// For debugging
9#include <iostream>
10
11namespace Header
12{
13    template<typename S>
14        void hton(S &s)
15    {
16        std::transform(reinterpret_cast<uint16_t*>(&s),
17                       reinterpret_cast<uint16_t*>(&s)+sizeof(S)/2,
18                       reinterpret_cast<uint16_t*>(&s),
19                       htons);
20    }
21
22    template<typename S>
23        void ntoh(S &s)
24    {
25        std::transform(reinterpret_cast<uint16_t*>(&s),
26                       reinterpret_cast<uint16_t*>(&s)+sizeof(S)/2,
27                       reinterpret_cast<uint16_t*>(&s),
28                       ntohs);
29    }
30
31    template<typename S>
32        S NtoH(const S &s)
33    {
34        S ret(s);
35        ntoh(ret);
36        return ret;
37    }
38
39    template<typename S>
40        S HtoN(const S &s)
41    {
42        S ret(s);
43        hton(ret);
44        return ret;
45    }
46
47    template<typename S>
48        void reset(S &s)
49    {
50        memset(&s, 0, sizeof(S));
51    }
52
53    template<typename S>
54        void init(S &s)
55    {
56        if (sizeof(S)%2!=0)
57            throw std::logic_error("size of "+std::string(typeid(S).name())+" not a multiple of 2.");
58
59        reset(s);
60    }
61
62    template<typename S>
63        void ntohcpy(const std::vector<uint16_t> &vec, S &s)
64    {
65        if (sizeof(S)!=vec.size()*2)
66            throw std::logic_error("size of vector mismatch "+std::string(typeid(S).name()));
67
68        std::transform(vec.begin(), vec.end(),
69                       reinterpret_cast<uint16_t*>(&s), ntohs);
70    }
71
72    template<typename S>
73        std::vector<uint16_t> htoncpy(const S &s)
74    {
75        if (sizeof(S)%2)
76            throw std::logic_error("size of "+std::string(typeid(S).name())+" not a multiple of 2");
77
78        std::vector<uint16_t> v(sizeof(S)/2);
79
80        std::transform(reinterpret_cast<const uint16_t*>(&s),
81                       reinterpret_cast<const uint16_t*>(&s)+sizeof(S)/2,
82                       v.begin(), htons);
83
84        return v;
85    }
86
87    template<typename T, typename S>
88    void bitcpy(T *target, size_t ntarget, const S *source, size_t nsource, size_t ss=0, size_t ts=0)
89    {
90        const size_t targetsize = ss==0 ? sizeof(T) : std::min(ss, sizeof(T));
91        const size_t sourcesize = ts==0 ? sizeof(S) : std::min(ts, sizeof(S));
92
93        const S *const ends = source + nsource;
94        const T *const endt = target + ntarget;
95
96        const S *s = source;
97              T *t = target;
98
99        memset(t, 0, sizeof(T)*ntarget);
100
101        size_t targetpos = 0;
102        size_t sourcepos = 0;
103
104        while (s<ends && t<endt)
105        {
106            // Start filling with "source size" - "position" bits
107            *t |= (*s>>sourcepos)<<targetpos;
108
109            // If not all bits fitted into targetsize the number
110            // of copied bits is the number of bits which fitted
111            const int n = std::min(sourcesize-sourcepos, targetsize-targetpos);
112
113            targetpos += n;
114            sourcepos += n;
115
116            if (sourcepos>=sourcesize)
117                s++;
118
119            if (targetpos>=targetsize)
120                t++;
121
122            sourcepos %= sourcesize;
123            targetpos %= targetsize;
124        }
125    }
126
127}
128
129// ====================================================================
130
131#include <ostream>
132
133namespace FTM
134{
135    using namespace Header;
136
137    enum States
138    {
139        kDisconnected = 1,
140        kConnected,
141        kIdle,
142        kTakingData,
143
144        // FTM internal states
145        kFtmIdle    = 1,
146        kFtmConfig  = 2,
147        kFtmRunning = 3,
148        kFtmCalib   = 4,
149    };
150
151    enum Commands
152    {
153        kCmdRead           = 0x0001,
154        kCmdWrite          = 0x0002,
155        kCmdStartRun       = 0x0004,
156        kCmdStopRun        = 0x0008,
157        kCmdPing           = 0x0010,
158        kCmdCrateReset     = 0x0020,
159        kCmdDisableReports = 0x0040,
160        kCmdToggleLed      = 0xc000,
161
162        kWriteStaticData   = 0x0001,
163        kWriteRegister     = 0x0004,
164
165        kReadStaticData    = 0x0001,
166        kReadDynamicData   = 0x0002,
167        kReadRegister      = 0x0004,
168
169        kStartRun          = 0x0001,
170        kTakeNevents       = 0x0002,
171    };
172
173    enum Types
174    {
175        kHeader      = 0,   // Local extension to identify a header in fCounter
176        kStaticData  = 1,
177        kDynamicData = 2,
178        kFtuList     = 3,
179        kErrorList   = 4,
180        kRegister    = 5,
181    };
182
183    // --------------------------------------------------------------------
184
185    template<typename T>
186        void Reverse(T *t)
187    {
188        std::reverse((uint16_t*)t, ((uint16_t*)t)+sizeof(T)/2);
189    }
190
191    enum
192    {
193        kDelimiterStart = 0xfb01,
194        kDelimiterEnd   = 0x04fe
195    };
196
197    struct Header
198    {
199        uint16_t fDelimiter;        /// Start delimiter
200        uint16_t fType;             /// Type of the data to be received after the header
201        uint16_t fDataSize;         /// Size in words to be received after the header
202        uint16_t fState;            /// State of the FTM state machine
203        uint64_t fBoardId;
204        uint16_t fFirmwareId;
205        uint32_t fTriggerCounter;
206        uint64_t fTimeStamp;
207
208        Header() { init(*this); }
209
210        std::vector<uint16_t> HtoN() const
211        {
212            Header h(*this);
213
214            Reverse(&h.fBoardId);
215            Reverse(&h.fTriggerCounter);
216            Reverse(&h.fTimeStamp);
217
218            return htoncpy(h);
219        }
220        void operator=(const std::vector<uint16_t> &vec)
221        {
222            ntohcpy(vec, *this);
223
224            Reverse(&fBoardId);
225            Reverse(&fTriggerCounter);
226            Reverse(&fTimeStamp);
227        }
228
229        void clear() { reset(*this); }
230        void print(std::ostream &out) const;
231
232    } __attribute__((__packed__));
233
234    struct DimPassport
235    {
236        uint64_t fBoardId;
237        uint16_t fFirmwareId;
238
239        DimPassport(const Header &h) :
240            fBoardId(h.fBoardId),
241            fFirmwareId(h.fFirmwareId)
242        {
243        }
244    } __attribute__((__packed__));
245
246    struct DimTriggerCounter
247    {
248        uint64_t fTimeStamp;
249        uint32_t fTriggerCounter;
250
251        DimTriggerCounter(const Header &h) :
252            fTimeStamp(h.fTimeStamp),
253            fTriggerCounter(h.fTriggerCounter)
254        {
255        }
256    } __attribute__((__packed__));
257
258
259    struct StaticDataBoard
260    {
261        uint16_t fEnable[4];   // 4x9bits
262        uint16_t fDAC[5];      // 4x12bit + 1xN/40
263        uint16_t fPrescaling;
264
265        StaticDataBoard() { init(*this); }
266
267        void print(std::ostream &out) const;
268
269    } __attribute__((__packed__));
270
271    struct StaticData
272    {
273        enum
274        {
275            kMaxCoincidence     = 40,
276            kMaxWindow          = 0xf,
277            kMaxDeadTime        = 0xffff,
278            kMaxDelayTimeMarker = 0x3ff,
279            kMaxDelayTrigger    = 0x3ff,
280            kMaxTriggerInterval = 0x3ff,
281            kMaskSequence       = 0x7ff,
282            kMaskSettings       = 0xf,
283            kMaskLEDs           = 0xf,
284        };
285
286        enum GeneralSettings
287        {
288            kTrigger    = 0x80,
289            kPedestal   = 0x40,
290            kLPext      = 0x20,
291            kLPint      = 0x10,
292            kExt2       = 0x08,
293            kExt1       = 0x04,
294            kVeto       = 0x02,
295            kTimeMarker = 0x01,
296        };
297
298        uint16_t fGeneralSettings;         // only 8 bit used
299        uint16_t fStatusLEDs;              // only 8 bit used
300        uint16_t fTriggerInterval;         // only 10 bit used
301        uint16_t fTriggerSequence;         // 3x5bit
302        uint64_t fDummy0;
303        uint16_t fCoincidencePhysics;
304        uint16_t fCoincidenceCalib;
305        uint16_t fDelayTrigger;
306        uint16_t fDelayTimeMarker;
307        uint16_t fDeadTime;
308        uint32_t fClockConditioner[8];  // R0, R1, R8, R9, R11, R13, R14, R15
309        uint16_t fWindowPhysics;
310        uint16_t fWindowCalib;
311        uint16_t fDummy1;
312
313        StaticDataBoard fBoard[4][10];      // 4 crates * 10 boards
314
315        uint16_t fActiveFTU[4];             // 4 crates * 10 bits
316
317        StaticData() { init(*this); }
318
319        std::vector<uint16_t> HtoN() const
320        {
321            StaticData d(*this);
322            for (int i=0; i<8; i++)
323                Reverse(d.fClockConditioner+i);
324
325            return htoncpy(d);
326        }
327
328        void operator=(const std::vector<uint16_t> &vec)
329        {
330            ntohcpy(vec, *this);
331
332            for (int i=0; i<8; i++)
333                Reverse(fClockConditioner+i);
334        }
335
336        void clear() { reset(*this); }
337        void print(std::ostream &out) const;
338
339        StaticDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
340        const StaticDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
341
342        void EnableFTU(int i)  { fActiveFTU[i/10] |=  (1<<(i%10)); }
343        void DisableFTU(int i) { fActiveFTU[i/10] &= ~(1<<(i%10)); }
344
345        void EnableAllFTU()    { for (int i=0; i<4; i++) fActiveFTU[i] = 0x3ff; }
346        void DisableAllFTU()   { for (int i=0; i<4; i++) fActiveFTU[i] = 0;     }
347
348        void ToggleFTU(int i)  { fActiveFTU[i/10] ^= (1<<(i%10)); }
349
350    } __attribute__((__packed__));
351
352    // DimStructures must be a multiple of two... I don't know why
353    struct DimStaticData
354    {
355        uint64_t fTimeStamp;
356        //8
357        uint16_t fGeneralSettings;         // only 8 bit used
358        uint16_t fStatusLEDs;              // only 8 bit used
359        uint64_t fActiveFTU;               // 40 bits in row
360        //20
361        uint16_t fTriggerInterval;         // only 10 bit used
362        //22
363        uint16_t fTriggerSeqLPint;         // only 5bits used
364        uint16_t fTriggerSeqLPext;         // only 5bits used
365        uint16_t fTriggerSeqPed;           // only 5bits used
366        //28
367        uint16_t fCoincidencePhysics;      // 0-40
368        uint16_t fCoincidenceCalib;        // 0-40
369        //32
370        uint16_t fWindowPhysics;
371        uint16_t fWindowCalib;
372        //36
373        uint16_t fDelayTrigger;
374        uint16_t fDelayTimeMarker;
375        uint32_t fDeadTime;
376        //44
377        uint16_t fClockConditioner[8];
378        //60
379        uint16_t fEnable[80];  // 160*9bit = 180byte
380        uint16_t fThreshold[160];
381        uint16_t fMultiplicity[40];     // N out of 4
382        uint16_t fPrescaling[40];
383        // 640+60 = 700
384
385        bool HasTrigger() const     { return fGeneralSettings & StaticData::kTrigger; }
386        bool HasPedestal() const    { return fGeneralSettings & StaticData::kPedestal; }
387        bool HasLPext() const       { return fGeneralSettings & StaticData::kLPext; }
388        bool HasLPint() const       { return fGeneralSettings & StaticData::kLPint; }
389        bool HasExt2() const        { return fGeneralSettings & StaticData::kExt2; }
390        bool HasExt1() const        { return fGeneralSettings & StaticData::kExt1; }
391        bool HasVeto() const        { return fGeneralSettings & StaticData::kVeto; }
392        bool HasTimeMarker() const  { return fGeneralSettings & StaticData::kTimeMarker; }
393
394        bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
395        bool IsEnabled(int i) const { return fEnable[i/16]&(1<<(i%16)); }
396
397        DimStaticData() { memset(this, 0, sizeof(DimStaticData)); }
398
399        DimStaticData(const Header &h, const StaticData &d) :
400            fTimeStamp(h.fTimeStamp),
401            fGeneralSettings(d.fGeneralSettings),
402            fStatusLEDs(d.fStatusLEDs),
403            fActiveFTU( uint64_t(d.fActiveFTU[0])      |
404                       (uint64_t(d.fActiveFTU[1])<<10) |
405                       (uint64_t(d.fActiveFTU[2])<<20) |
406                       (uint64_t(d.fActiveFTU[3])<<30)),
407            fTriggerInterval(d.fTriggerInterval),
408            fTriggerSeqLPint((d.fTriggerSequence)&0x1f),
409            fTriggerSeqLPext((d.fTriggerSequence>>5)&0x1f),
410            fTriggerSeqPed((d.fTriggerSequence>>10)&0x1f),
411            fCoincidencePhysics(d.fCoincidencePhysics),
412            fCoincidenceCalib(d.fCoincidenceCalib),
413            fWindowPhysics(d.fWindowPhysics*4+8),
414            fWindowCalib(d.fWindowCalib*4+8),
415            fDelayTrigger(d.fDelayTrigger*4+8),
416            fDelayTimeMarker(d.fDelayTimeMarker*4+8),
417            fDeadTime(uint32_t(d.fDeadTime)*4+8)
418        {
419            memcpy(fClockConditioner, d.fClockConditioner, sizeof(uint16_t)*8);
420
421            uint16_t src[160];
422            for (int i=0; i<40; i++)
423            {
424                for (int j=0; j<4; j++)
425                {
426                    src[i*4+j] = d[i].fEnable[j];
427                    fThreshold[i*4+j] = d[i].fDAC[j];
428                }
429
430                fMultiplicity[i] = d[i].fDAC[4];
431                fPrescaling[i] = d[i].fPrescaling;
432            }
433            bitcpy(fEnable, 80, src, 160, 9);
434        }
435
436    } __attribute__((__packed__));
437
438
439    struct DynamicDataBoard
440    {
441        uint32_t fRatePatch[4];   // Patch 0,1,2,3
442        uint32_t fRateTotal;      // Sum
443
444        uint16_t fOverflow;       // Patches: bits 0-3, total 4
445        uint16_t fCrcError;
446
447        void print(std::ostream &out) const;
448
449        void reverse()
450        {
451            for (int i=0; i<4; i++)
452                Reverse(fRatePatch+i);
453
454            Reverse(&fRateTotal);
455        }
456
457        uint32_t &operator[](int i) { return fRatePatch[i]; }
458
459    }  __attribute__((__packed__));
460
461
462    struct DynamicData
463    {
464        uint64_t fOnTimeCounter;
465        uint16_t fTempSensor[4];  // U45, U46, U48, U49
466
467        DynamicDataBoard fBoard[4][10];      // 4 crates * 10 boards
468
469        DynamicData() { init(*this); }
470
471        std::vector<uint16_t> HtoN() const
472        {
473            DynamicData d(*this);
474
475            Reverse(&d.fOnTimeCounter);
476
477            for (int c=0; c<4; c++)
478                for (int b=0; b<10; b++)
479                    d.fBoard[c][b].reverse();
480
481            return htoncpy(d);
482        }
483
484        void operator=(const std::vector<uint16_t> &vec)
485        {
486            ntohcpy(vec, *this);
487
488            Reverse(&fOnTimeCounter);
489
490            for (int c=0; c<4; c++)
491                for (int b=0; b<10; b++)
492                    fBoard[c][b].reverse();
493        }
494
495        void clear() { reset(*this); }
496        void print(std::ostream &out) const;
497
498        DynamicDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
499        const DynamicDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
500
501    } __attribute__((__packed__));
502
503
504    struct DimDynamicData
505    {
506        uint64_t fTimeStamp;
507
508        uint64_t fOnTimeCounter;
509        float    fTempSensor[4];
510
511        uint32_t fRatePatch[160];
512
513        uint32_t fRateBoard[40];
514        uint16_t fRateOverflow[40];
515
516        uint16_t fCrcError[40];
517
518        DimDynamicData(const Header &h, const DynamicData &d) :
519            fTimeStamp(h.fTimeStamp),
520            fOnTimeCounter(d.fOnTimeCounter)
521        {
522            for (int i=0; i<4; i++)
523                fTempSensor[i] = d.fTempSensor[i];
524
525            for (int i=0; i<40; i++)
526            {
527                fRateBoard[i]    = d[i].fRateTotal;
528                fRateOverflow[i] = d[i].fOverflow;
529                fCrcError[i]     = d[i].fCrcError;
530                for (int j=0; j<4; j++)
531                    fRatePatch[i*4+j] = d[i].fRatePatch[j];
532            }
533        }
534
535    } __attribute__((__packed__));
536
537
538    struct FtuResponse
539    {
540        uint16_t fPingAddr;       // Number of Pings and addr (pings= see error)
541        uint64_t fDNA;
542        uint16_t fErrorCounter;   //
543
544        void reverse() { Reverse(&fDNA); }
545
546        void print(std::ostream &out) const;
547
548    } __attribute__((__packed__));
549
550    struct FtuList
551    {
552        uint16_t fNumBoards;         /// Total number of boards responded
553        uint16_t fNumBoardsCrate[4]; /// Num of board responded in crate 0-3
554        uint16_t fActiveFTU[4];      /// List of active FTU boards in crate 0-3
555
556        FtuResponse fFTU[4][10];
557
558        FtuList() { init(*this); }
559
560        std::vector<uint16_t> HtoN() const
561        {
562            FtuList d(*this);
563
564            for (int c=0; c<4; c++)
565                for (int b=0; b<10; b++)
566                    d.fFTU[c][b].reverse();
567
568            return htoncpy(d);
569        }
570
571        void operator=(const std::vector<uint16_t> &vec)
572        {
573            ntohcpy(vec, *this);
574
575            for (int c=0; c<4; c++)
576                for (int b=0; b<10; b++)
577                    fFTU[c][b].reverse();
578        }
579
580        void clear() { reset(*this); }
581        void print(std::ostream &out) const;
582
583        FtuResponse &operator[](int i) { return fFTU[i/10][i%10]; }
584        const FtuResponse &operator[](int i) const { return fFTU[i/10][i%10]; }
585
586    } __attribute__((__packed__));
587
588    struct DimFtuList
589    {
590        uint64_t fTimeStamp;
591        uint64_t fActiveFTU;
592
593        uint16_t fNumBoards;          /// Number of boards answered in total
594        uint8_t  fNumBoardsCrate[4];  /// Number of boards answered per crate
595
596        uint64_t fDNA[40];            /// DNA of FTU board
597        uint8_t  fAddr[40];           /// Address of FTU board
598        uint8_t  fPing[40];           /// Number of pings until response (same as in Error)
599
600        DimFtuList(const Header &h, const FtuList &d) :
601            fTimeStamp(h.fTimeStamp),
602            fActiveFTU( uint64_t(d.fActiveFTU[0])      |
603                       (uint64_t(d.fActiveFTU[1])<<10) |
604                       (uint64_t(d.fActiveFTU[2])<<20) |
605                       (uint64_t(d.fActiveFTU[3])<<30)),
606            fNumBoards(d.fNumBoards)
607        {
608            for (int i=0; i<4; i++)
609                fNumBoardsCrate[i] = d.fNumBoardsCrate[i];
610
611            for (int i=0; i<40; i++)
612            {
613                fDNA[i]  =  d[i].fDNA;
614                fAddr[i] =  d[i].fPingAddr&0x3f;
615                fPing[i] = (d[i].fPingAddr>>8)&0x3;
616            }
617        }
618
619        bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
620
621    } __attribute__((__packed__));
622
623
624    struct Error
625    {
626        uint16_t fNumCalls;   // 0=error, >1 needed repetition but successfull
627
628        uint16_t fDelimiter;
629        uint16_t fDestAddress;
630        uint16_t fSrcAddress;
631        uint16_t fFirmwareId;
632        uint16_t fCommand;
633        uint16_t fData[21];
634        uint16_t fCrcErrorCounter;
635        uint16_t fCrcCheckSum;
636
637        Error() { init(*this); }
638
639        std::vector<uint16_t> HtoN() const
640        {
641            return htoncpy(*this);
642        }
643
644        void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
645
646        void clear() { reset(*this); }
647
648        uint16_t &operator[](int idx) { return fData[idx]; }
649        const uint16_t &operator[](int idx) const { return fData[idx]; }
650
651        void print(std::ostream &out) const;
652
653    } __attribute__((__packed__));
654
655    struct DimError
656    {
657        uint64_t fTimeStamp;
658        Error    fError;
659
660        DimError(const Header &h, const Error &e) :
661            fTimeStamp(h.fTimeStamp),
662            fError(e)
663        {
664            fError.fDestAddress = (e.fDestAddress&0x3)*10 + ((e.fDestAddress>>2)&0xf);
665            fError.fSrcAddress  = (e.fSrcAddress &0x3)*10 + ((e.fSrcAddress >>2)&0xf);
666        }
667
668    }  __attribute__((__packed__));
669
670    /*
671    struct Command
672    {
673        uint16_t fStartDelimiter;
674        uint16_t fCommand;
675        uint16_t fParam[3];
676
677        Command() { init(*this); }
678
679        void HtoN() { hton(*this); }
680        void NtoH() { ntoh(*this); }
681
682        void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
683
684        void clear() { reset(*this); }
685
686
687     } __attribute__((__packed__));
688    */
689
690    // --------------------------------------------------------------------
691
692    inline std::ostream &operator<<(std::ostream &out, const FtuResponse &h)
693    {
694        h.print(out);
695        return out;
696    }
697
698    inline std::ostream &operator<<(std::ostream &out, const Header &h)
699    {
700        h.print(out);
701        return out;
702    }
703
704
705    inline std::ostream &operator<<(std::ostream &out, const FtuList &h)
706    {
707        h.print(out);
708        return out;
709    }
710
711    inline std::ostream &operator<<(std::ostream &out, const DynamicDataBoard &h)
712    {
713        h.print(out);
714        return out;
715    }
716
717    inline std::ostream &operator<<(std::ostream &out, const DynamicData &h)
718    {
719        h.print(out);
720        return out;
721    }
722
723    inline std::ostream &operator<<(std::ostream &out, const StaticDataBoard &h)
724    {
725        h.print(out);
726        return out;
727    }
728
729    inline std::ostream &operator<<(std::ostream &out, const StaticData &h)
730    {
731        h.print(out);
732        return out;
733    }
734
735    inline std::ostream &operator<<(std::ostream &out, const Error &h)
736    {
737        h.print(out);
738        return out;
739    }
740};
Note: See TracBrowser for help on using the repository browser.