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

Last change on this file since 10576 was 10574, checked in by tbretz, 14 years ago
Renamed LP1/LP2 to Lpint/LPext
File size: 20.1 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 uint16_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 return htoncpy(*this);
322 }
323
324 void operator=(const std::vector<uint16_t> &vec)
325 {
326 ntohcpy(vec, *this);
327 }
328
329 void clear() { reset(*this); }
330 void print(std::ostream &out) const;
331
332 StaticDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
333 const StaticDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
334
335 void EnableFTU(int i) { fActiveFTU[i/10] |= (1<<(i%10)); }
336 void DisableFTU(int i) { fActiveFTU[i/10] &= ~(1<<(i%10)); }
337
338 void EnableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0x3ff; }
339 void DisableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0; }
340
341 void ToggleFTU(int i) { fActiveFTU[i/10] ^= (1<<(i%10)); }
342
343 } __attribute__((__packed__));
344
345 // DimStructures must be a multiple of two... I don't know why
346 struct DimStaticData
347 {
348 uint64_t fTimeStamp;
349 //8
350 uint16_t fGeneralSettings; // only 8 bit used
351 uint16_t fStatusLEDs; // only 8 bit used
352 uint64_t fActiveFTU; // 40 bits in row
353 //20
354 uint16_t fTriggerInterval; // only 10 bit used
355 //22
356 uint16_t fTriggerSeqLPint; // only 5bits used
357 uint16_t fTriggerSeqLPext; // only 5bits used
358 uint16_t fTriggerSeqPed; // only 5bits used
359 //28
360 uint16_t fCoincidencePhysics; // 0-40
361 uint16_t fCoincidenceCalib; // 0-40
362 //32
363 uint16_t fWindowPhysics;
364 uint16_t fWindowCalib;
365 //36
366 uint16_t fDelayTrigger;
367 uint16_t fDelayTimeMarker;
368 uint32_t fDeadTime;
369 //44
370 uint16_t fClockConditioner[8];
371 //60
372 uint16_t fEnable[80]; // 160*9bit = 180byte
373 uint16_t fThreshold[160];
374 uint16_t fMultiplicity[40]; // N out of 4
375 uint16_t fPrescaling[40];
376 // 640+60 = 700
377
378 bool HasTrigger() const { return fGeneralSettings & StaticData::kTrigger; }
379 bool HasPedestal() const { return fGeneralSettings & StaticData::kPedestal; }
380 bool HasLPext() const { return fGeneralSettings & StaticData::kLPext; }
381 bool HasLPint() const { return fGeneralSettings & StaticData::kLPint; }
382 bool HasExt2() const { return fGeneralSettings & StaticData::kExt2; }
383 bool HasExt1() const { return fGeneralSettings & StaticData::kExt1; }
384 bool HasVeto() const { return fGeneralSettings & StaticData::kVeto; }
385 bool HasTimeMarker() const { return fGeneralSettings & StaticData::kTimeMarker; }
386
387 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
388 bool IsEnabled(int i) const { return fEnable[i/16]&(1<<(i%16)); }
389
390 DimStaticData() { memset(this, 0, sizeof(DimStaticData)); }
391
392 DimStaticData(const Header &h, const StaticData &d) :
393 fTimeStamp(h.fTimeStamp),
394 fGeneralSettings(d.fGeneralSettings),
395 fStatusLEDs(d.fStatusLEDs),
396 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
397 (uint64_t(d.fActiveFTU[1])<<10) |
398 (uint64_t(d.fActiveFTU[2])<<20) |
399 (uint64_t(d.fActiveFTU[3])<<30)),
400 fTriggerInterval(d.fTriggerInterval*4+8),
401 fTriggerSeqLPint((d.fTriggerSequence)&0x1f),
402 fTriggerSeqLPext((d.fTriggerSequence>>5)&0x1f),
403 fTriggerSeqPed((d.fTriggerSequence>>10)&0x1f),
404 fCoincidencePhysics(d.fCoincidencePhysics),
405 fCoincidenceCalib(d.fCoincidenceCalib),
406 fWindowPhysics(d.fWindowPhysics*4+8),
407 fWindowCalib(d.fWindowCalib*4+8),
408 fDelayTrigger(d.fDelayTrigger*4+8),
409 fDelayTimeMarker(d.fDelayTimeMarker*4+8),
410 fDeadTime(uint32_t(d.fDeadTime)*4+8)
411 {
412 memcpy(fClockConditioner, d.fClockConditioner, sizeof(uint16_t)*8);
413
414 uint16_t src[160];
415 for (int i=0; i<40; i++)
416 {
417 for (int j=0; j<4; j++)
418 {
419 src[i*4+j] = d[i].fEnable[j];
420 fThreshold[i*4+j] = d[i].fDAC[j];
421 }
422
423 fMultiplicity[i] = d[i].fDAC[4];
424 fPrescaling[i] = d[i].fPrescaling;
425 }
426 bitcpy(fEnable, 80, src, 160, 9);
427 }
428
429 } __attribute__((__packed__));
430
431
432 struct DynamicDataBoard
433 {
434 uint32_t fRatePatch[4]; // Patch 0,1,2,3
435 uint32_t fRateTotal; // Sum
436
437 uint16_t fOverflow; // Patches: bits 0-3, total 4
438 uint16_t fCrcError;
439
440 void print(std::ostream &out) const;
441
442 void reverse()
443 {
444 for (int i=0; i<4; i++)
445 Reverse(fRatePatch+i);
446
447 Reverse(&fRateTotal);
448 }
449
450 uint32_t &operator[](int i) { return fRatePatch[i]; }
451
452 } __attribute__((__packed__));
453
454
455 struct DynamicData
456 {
457 uint64_t fOnTimeCounter;
458 uint16_t fTempSensor[4]; // U45, U46, U48, U49
459
460 DynamicDataBoard fBoard[4][10]; // 4 crates * 10 boards
461
462 DynamicData() { init(*this); }
463
464 std::vector<uint16_t> HtoN() const
465 {
466 DynamicData d(*this);
467
468 Reverse(&d.fOnTimeCounter);
469
470 for (int c=0; c<4; c++)
471 for (int b=0; b<10; b++)
472 d.fBoard[c][b].reverse();
473
474 return htoncpy(d);
475 }
476
477 void operator=(const std::vector<uint16_t> &vec)
478 {
479 ntohcpy(vec, *this);
480
481 Reverse(&fOnTimeCounter);
482
483 for (int c=0; c<4; c++)
484 for (int b=0; b<10; b++)
485 fBoard[c][b].reverse();
486 }
487
488 void clear() { reset(*this); }
489 void print(std::ostream &out) const;
490
491 DynamicDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
492 const DynamicDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
493
494 } __attribute__((__packed__));
495
496
497 struct DimDynamicData
498 {
499 uint64_t fTimeStamp;
500
501 uint64_t fOnTimeCounter;
502 float fTempSensor[4];
503
504 uint32_t fRatePatch[160];
505
506 uint32_t fRateBoard[40];
507 uint16_t fRateOverflow[40];
508
509 uint16_t fCrcError[40];
510
511 DimDynamicData(const Header &h, const DynamicData &d) :
512 fTimeStamp(h.fTimeStamp),
513 fOnTimeCounter(d.fOnTimeCounter)
514 {
515 for (int i=0; i<4; i++)
516 fTempSensor[i] = d.fTempSensor[i];
517
518 for (int i=0; i<40; i++)
519 {
520 fRateBoard[i] = d[i].fRateTotal;
521 fRateOverflow[i] = d[i].fOverflow;
522 fCrcError[i] = d[i].fCrcError;
523 for (int j=0; j<4; j++)
524 fRatePatch[i*4+j] = d[i].fRatePatch[j];
525 }
526 }
527
528 } __attribute__((__packed__));
529
530
531 struct FtuResponse
532 {
533 uint16_t fPingAddr; // Number of Pings and addr (pings= see error)
534 uint64_t fDNA;
535 uint16_t fErrorCounter; //
536
537 void reverse() { Reverse(&fDNA); }
538
539 void print(std::ostream &out) const;
540
541 } __attribute__((__packed__));
542
543 struct FtuList
544 {
545 uint16_t fNumBoards; /// Total number of boards responded
546 uint16_t fNumBoardsCrate[4]; /// Num of board responded in crate 0-3
547 uint16_t fActiveFTU[4]; /// List of active FTU boards in crate 0-3
548
549 FtuResponse fFTU[4][10];
550
551 FtuList() { init(*this); }
552
553 std::vector<uint16_t> HtoN() const
554 {
555 FtuList d(*this);
556
557 for (int c=0; c<4; c++)
558 for (int b=0; b<10; b++)
559 d.fFTU[c][b].reverse();
560
561 return htoncpy(d);
562 }
563
564 void operator=(const std::vector<uint16_t> &vec)
565 {
566 ntohcpy(vec, *this);
567
568 for (int c=0; c<4; c++)
569 for (int b=0; b<10; b++)
570 fFTU[c][b].reverse();
571 }
572
573 void clear() { reset(*this); }
574 void print(std::ostream &out) const;
575
576 FtuResponse &operator[](int i) { return fFTU[i/10][i%10]; }
577 const FtuResponse &operator[](int i) const { return fFTU[i/10][i%10]; }
578
579 } __attribute__((__packed__));
580
581 struct DimFtuList
582 {
583 uint64_t fTimeStamp;
584 uint64_t fActiveFTU;
585
586 uint16_t fNumBoards; /// Number of boards answered in total
587 uint8_t fNumBoardsCrate[4]; /// Number of boards answered per crate
588
589 uint64_t fDNA[40]; /// DNA of FTU board
590 uint8_t fAddr[40]; /// Address of FTU board
591 uint8_t fPing[40]; /// Number of pings until response (same as in Error)
592
593 DimFtuList(const Header &h, const FtuList &d) :
594 fTimeStamp(h.fTimeStamp),
595 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
596 (uint64_t(d.fActiveFTU[1])<<10) |
597 (uint64_t(d.fActiveFTU[2])<<20) |
598 (uint64_t(d.fActiveFTU[3])<<30)),
599 fNumBoards(d.fNumBoards)
600 {
601 for (int i=0; i<4; i++)
602 fNumBoardsCrate[i] = d.fNumBoardsCrate[i];
603
604 for (int i=0; i<40; i++)
605 {
606 fDNA[i] = d[i].fDNA;
607 fAddr[i] = d[i].fPingAddr&0x3f;
608 fPing[i] = (d[i].fPingAddr>>8)&0x3;
609 }
610 }
611
612 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
613
614 } __attribute__((__packed__));
615
616
617 struct Error
618 {
619 uint16_t fNumCalls; // 0=error, >1 needed repetition but successfull
620
621 uint16_t fDelimiter;
622 uint16_t fDestAddress;
623 uint16_t fSrcAddress;
624 uint16_t fFirmwareId;
625 uint16_t fCommand;
626 uint16_t fData[21];
627 uint16_t fCrcErrorCounter;
628 uint16_t fCrcCheckSum;
629
630 Error() { init(*this); }
631
632 std::vector<uint16_t> HtoN() const
633 {
634 return htoncpy(*this);
635 }
636
637 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
638
639 void clear() { reset(*this); }
640
641 uint16_t &operator[](int idx) { return fData[idx]; }
642 const uint16_t &operator[](int idx) const { return fData[idx]; }
643
644 void print(std::ostream &out) const;
645
646 } __attribute__((__packed__));
647
648 struct DimError
649 {
650 uint64_t fTimeStamp;
651 Error fError;
652
653 DimError(const Header &h, const Error &e) :
654 fTimeStamp(h.fTimeStamp),
655 fError(e)
656 {
657 fError.fDestAddress = (e.fDestAddress&0x3)*10 + ((e.fDestAddress>>2)&0xf);
658 fError.fSrcAddress = (e.fSrcAddress &0x3)*10 + ((e.fSrcAddress >>2)&0xf);
659 }
660
661 } __attribute__((__packed__));
662
663 /*
664 struct Command
665 {
666 uint16_t fStartDelimiter;
667 uint16_t fCommand;
668 uint16_t fParam[3];
669
670 Command() { init(*this); }
671
672 void HtoN() { hton(*this); }
673 void NtoH() { ntoh(*this); }
674
675 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
676
677 void clear() { reset(*this); }
678
679
680 } __attribute__((__packed__));
681 */
682
683 // --------------------------------------------------------------------
684
685 inline std::ostream &operator<<(std::ostream &out, const FtuResponse &h)
686 {
687 h.print(out);
688 return out;
689 }
690
691 inline std::ostream &operator<<(std::ostream &out, const Header &h)
692 {
693 h.print(out);
694 return out;
695 }
696
697
698 inline std::ostream &operator<<(std::ostream &out, const FtuList &h)
699 {
700 h.print(out);
701 return out;
702 }
703
704 inline std::ostream &operator<<(std::ostream &out, const DynamicDataBoard &h)
705 {
706 h.print(out);
707 return out;
708 }
709
710 inline std::ostream &operator<<(std::ostream &out, const DynamicData &h)
711 {
712 h.print(out);
713 return out;
714 }
715
716 inline std::ostream &operator<<(std::ostream &out, const StaticDataBoard &h)
717 {
718 h.print(out);
719 return out;
720 }
721
722 inline std::ostream &operator<<(std::ostream &out, const StaticData &h)
723 {
724 h.print(out);
725 return out;
726 }
727
728 inline std::ostream &operator<<(std::ostream &out, const Error &h)
729 {
730 h.print(out);
731 return out;
732 }
733};
Note: See TracBrowser for help on using the repository browser.