-
Notifications
You must be signed in to change notification settings - Fork 494
Expand file tree
/
Copy pathCMV.h
More file actions
130 lines (112 loc) · 4.49 KB
/
CMV.h
File metadata and controls
130 lines (112 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
/// @file CMV.h
/// @author Tuba Gündem, tuba.gundem@cern.ch
/// @brief Common mode values data format definition
/// The data is sent by the CRU as 256+16 bit words. The CMV data layout is as follows:
/// - 256-bit Header: [version:8][packetID:8][errorCode:8][magicWord:8][heartbeatOrbit:32][heartbeatBC:16][padding:176]
/// - 16-bit CMV value: [sign:1][I8F7:15] where bit 15 is the sign (1=positive, 0=negative) and the lower 15 bits are a fixed point I8F7 value (8 integer bits, 7 fractional bits)
/// Float conversion: sign ? (value & 0x7FFF) / 128.0 : -(value & 0x7FFF) / 128.0
#ifndef ALICEO2_DATAFORMATSTPC_CMV_H
#define ALICEO2_DATAFORMATSTPC_CMV_H
#include <cstdint>
#include <cmath>
namespace o2::tpc::cmv
{
static constexpr uint32_t NTimeBinsPerPacket = 3564; ///< number of time bins (covering 8 heartbeats)
static constexpr uint32_t NPacketsPerTFPerCRU = 4; ///< 4 packets per timeframe
static constexpr uint32_t NTimeBinsPerTF = NTimeBinsPerPacket * NPacketsPerTFPerCRU; ///< maximum number of timebins per timeframe (14256)
/// Header definition of the CMVs
struct Header {
static constexpr uint8_t MagicWord = 0xDC;
union {
uint32_t word0 = 0; ///< bits 0 - 31
struct {
uint8_t version : 8; ///< version
uint8_t packetID : 8; ///< packet id
uint8_t errorCode : 8; ///< errors
uint8_t magicWord : 8; ///< magic word
};
};
union {
uint32_t word1 = 0; ///< bits 32 - 63
struct {
uint32_t heartbeatOrbit : 32; ///< first heart beat timing of the package
};
};
union {
uint16_t word2 = 0; ///< bits 64 - 79
struct {
uint16_t heartbeatBC : 16; ///< first BC id of the package
};
};
union {
uint16_t word3 = 0; ///< bits 80 - 95
struct {
uint16_t unused1 : 16; ///< reserved
};
};
union {
uint32_t word4 = 0; ///< bits 96 - 127
struct {
uint32_t unused2 : 32; ///< reserved
};
};
union {
uint64_t word5 = 0; ///< bits 128 - 191
struct {
uint64_t unused3 : 64; ///< reserved
};
};
union {
uint64_t word6 = 0; ///< bits 192 - 255
struct {
uint64_t unused4 : 64; ///< reserved
};
};
};
/// CMV single data container
struct Data {
uint16_t CMV{0}; ///< 16-bit signed fixed point value: bit 15 = sign (1=positive, 0=negative), bits 14-0 = I8F7 magnitude
uint16_t getCMV() const { return CMV; } ///< raw 16-bit integer representation
void setCMV(uint16_t value) { CMV = value; } ///< set raw 16-bit integer representation
// Decode to float: sign-magnitude with 7 fractional bits, range ±255.992
float getCMVFloat() const
{
const bool positive = (CMV >> 15) & 1; // bit 15: sign (1=positive, 0=negative)
const float magnitude = (CMV & 0x7FFF) / 128.f; // lower 15 bits, shift right by 7 (divide by 2^7)
return positive ? magnitude : -magnitude;
}
// Encode from float: clamps magnitude to 15 bits, range ±255.992
void setCMVFloat(float value)
{
const bool positive = (value >= 0.f);
const uint16_t magnitude = static_cast<uint16_t>(std::abs(value) * 128.f + 0.5f) & 0x7FFF;
CMV = (positive ? 0x8000 : 0x0000) | magnitude;
}
};
/// CMV full data container: one packet carries NTimeBinsPerPacket
struct Container {
Header header; ///< CMV data header
Data data[NTimeBinsPerPacket]; ///< data values
// Header and data accessors
const Header& getHeader() const { return header; }
Header& getHeader() { return header; }
const Data* getData() const { return data; }
Data* getData() { return data; }
// Per timebin CMV accessors
uint16_t getCMV(uint32_t timeBin) const { return data[timeBin].getCMV(); }
void setCMV(uint32_t timeBin, uint16_t value) { data[timeBin].setCMV(value); }
float getCMVFloat(uint32_t timeBin) const { return data[timeBin].getCMVFloat(); }
void setCMVFloat(uint32_t timeBin, float value) { data[timeBin].setCMVFloat(value); }
};
} // namespace o2::tpc::cmv
#endif