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

Last change on this file since 10597 was 10593, checked in by tbretz, 14 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.