gondola_core/monitoring/
mtb_moni_data.rs1use crate::prelude::*;
5
6#[derive(Debug, Copy, Clone, PartialEq)]
8#[cfg_attr(feature="pybindings", pyclass)]
9pub struct MtbMoniData {
10 pub tiu_busy_len : u32,
11 pub tiu_status : u8,
17 pub daq_queue_len: u16,
22 pub temp : u16,
25 pub rb_lost_rate : u8,
28 pub rate : u16,
29 pub lost_rate : u16,
30 pub vccint : u16,
31 pub vccbram : u16,
32 pub vccaux : u16,
33 pub timestamp : u64,
35}
36
37impl MtbMoniData {
38
39 pub fn new() -> Self {
40 Self {
41 tiu_busy_len : u32::MAX,
42 tiu_status : u8::MAX,
43 daq_queue_len : u16::MAX,
46 temp : u16::MAX,
47 vccint : u16::MAX,
48 vccaux : u16::MAX,
49 vccbram : u16::MAX,
50 rate : u16::MAX,
51 lost_rate : u16::MAX,
52 rb_lost_rate : u8::MAX,
53 timestamp : 0,
54 }
55 }
56
57 pub fn get_tiu_emulation_mode(&self) -> bool {
58 self.tiu_status & 0x1 > 0
59 }
60
61 pub fn get_tiu_use_aux_link(&self) -> bool {
62 self.tiu_status & 0x2 > 0
63 }
64
65 pub fn get_tiu_bad(&self) -> bool {
66 self.tiu_status & 0x4 > 0
67 }
68
69 pub fn get_tiu_busy_stuck(&self) -> bool {
70 self.tiu_status & 0x8 > 0
71 }
72
73 pub fn get_tiu_ignore_busy(&self) -> bool {
74 self.tiu_status & 0x10 > 0
75 }
76
77
78 pub fn get_fpga_temp(&self) -> f32 {
80 self.temp as f32 * 503.975 / 4096.0 - 273.15
81 }
82
83 pub fn adc_vcc_conversion(data : u16) -> f32 {
85 3.0 * data as f32 / (2_u32.pow(12-1)) as f32
86 }
87
88 }
96
97impl Default for MtbMoniData {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103impl fmt::Display for MtbMoniData {
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 write!(f, "<MtbMoniData:
106 MTB EVT RATE [Hz] {}
107 LOST EVT RATE [Hz] {}
108 LOST RB EVT R [Hz] {}
109 TIU BUSY CNT [CLK] {}
110 DAQ QUEUE LEN {}
111 --- TIU STATUS ---
112 EMU MODE {}
113 USE AUX LINK {}
114 TIU BAD {}
115 BUSY STUCK {}
116 IGNORE BUSY {}
117 --- --- --- --- --
118 FPGA TEMP [\u{00B0}C] {:.2}
119 VCCINT [V] {:.3}
120 VCCAUX [V] {:.3},
121 VCCBRAM [V] {:.3}>",
122 self.rate,
123 self.lost_rate,
124 self.rb_lost_rate,
125 self.tiu_busy_len,
126 self.daq_queue_len,
127 self.get_tiu_emulation_mode(),
129 self.get_tiu_use_aux_link(),
130 self.get_tiu_bad(),
131 self.get_tiu_busy_stuck(),
132 self.get_tiu_ignore_busy(),
133 self.get_fpga_temp(),
134 Self::adc_vcc_conversion(self.vccint ),
135 Self::adc_vcc_conversion(self.vccaux ),
136 Self::adc_vcc_conversion(self.vccbram ),
137 )
138 }
139}
140
141impl TofPackable for MtbMoniData {
142 const TOF_PACKET_TYPE : TofPacketType = TofPacketType::MtbMoniData;
143}
144
145impl Serialization for MtbMoniData {
146
147 const SIZE : usize = 24;
148 const HEAD : u16 = 0xAAAA;
149 const TAIL : u16 = 0x5555;
150
151 fn to_bytestream(&self) -> Vec<u8> {
152 let mut stream = Vec::<u8>::with_capacity(Self::SIZE);
153 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
154 stream.extend_from_slice(&self.tiu_busy_len.to_le_bytes());
155 stream.extend_from_slice(&self.tiu_status .to_le_bytes());
156 stream.extend_from_slice(&self.rb_lost_rate.to_le_bytes());
158 stream.extend_from_slice(&self.daq_queue_len.to_le_bytes());
159 stream.extend_from_slice(&self.temp .to_le_bytes());
160 stream.extend_from_slice(&self.vccint .to_le_bytes());
161 stream.extend_from_slice(&self.vccaux .to_le_bytes());
162 stream.extend_from_slice(&self.vccbram .to_le_bytes());
163 stream.extend_from_slice(&self.rate .to_le_bytes());
166 stream.extend_from_slice(&self.lost_rate .to_le_bytes());
167 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
168 stream
169 }
170
171 fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
172 -> Result<Self, SerializationError> {
173 let mut moni_data = Self::new();
174 Self::verify_fixed(stream, pos)?;
175 moni_data.tiu_busy_len = parse_u32(&stream, pos);
176 moni_data.tiu_status = parse_u8(&stream, pos);
177 moni_data.rb_lost_rate = parse_u8(&stream, pos);
179 moni_data.daq_queue_len = parse_u16(&stream, pos);
180 moni_data.temp = parse_u16(&stream, pos);
181 moni_data.vccint = parse_u16(&stream, pos);
182 moni_data.vccaux = parse_u16(&stream, pos);
184 moni_data.vccbram = parse_u16(&stream, pos);
185 moni_data.rate = parse_u16(&stream, pos);
187 moni_data.lost_rate = parse_u16(&stream, pos);
188 *pos += 2; Ok(moni_data)
191 }
192}
193
194impl MoniData for MtbMoniData {
195
196 fn get_timestamp(&self) -> u64 {
197 self.timestamp
198 }
199
200 fn set_timestamp(&mut self, ts : u64) {
201 self.timestamp = ts;
202 }
203
204 fn get_board_id(&self) -> u8 {
205 return 0;
206 }
207
208 fn get(&self, varname : &str) -> Option<f32> {
209 match varname {
210 "board_id" => Some(0.0f32),
211 "tiu_busy_len" => Some(self.tiu_busy_len as f32),
212 "tiu_status" => Some(self.tiu_status as f32),
213 "daq_queue_len" => Some(self.daq_queue_len as f32),
214 "temp" => Some(self.get_fpga_temp()),
216 "vccint" => Some(Self::adc_vcc_conversion(self.vccint)),
217 "vccaux" => Some(Self::adc_vcc_conversion(self.vccaux)),
218 "vccbram" => Some(Self::adc_vcc_conversion(self.vccbram)),
219 "rate" => Some(self.rate as f32),
220 "lost_rate" => Some(self.lost_rate as f32),
221 "rb_lost_rate" => Some(self.rb_lost_rate as f32),
222 "timestamp" => Some(self.timestamp as f32),
223 _ => None
224 }
225 }
226
227 fn keys() -> Vec<&'static str> {
228 vec![
229 "board_id" ,
230 "tiu_busy_len" ,
231 "tiu_status" ,
232 "daq_queue_len" ,
233 "temp" ,
234 "vccint" ,
235 "vccaux" ,
236 "vccbram" ,
237 "rb_lost_rate" ,
238 "rate" ,
239 "lost_rate",
240 "timestamp"]
241 }
242}
243
244#[cfg(feature = "random")]
245impl FromRandom for MtbMoniData {
246 fn from_random() -> Self {
247 let mut moni = Self::new();
248 let mut rng = rand::rng();
249 moni.tiu_busy_len = rng.random::<u32>();
250 moni.tiu_status = rng.random::<u8>();
251 moni.daq_queue_len= rng.random::<u16>();
253 moni.temp = rng.random::<u16>();
254 moni.vccint = rng.random::<u16>();
255 moni.vccaux = rng.random::<u16>();
256 moni.vccbram = rng.random::<u16>();
257 moni.rb_lost_rate = rng.random::<u8>();
258 moni.rate = rng.random::<u16>();
259 moni.lost_rate = rng.random::<u16>();
260 moni.timestamp = 0;
261 moni
262 }
263}
264
265#[cfg(feature="pybindings")]
266#[pymethods]
267impl MtbMoniData {
268
269 #[getter]
270 fn get_vccint(&self) -> f32 {
271 Self::adc_vcc_conversion(self.vccint)
272 }
273
274 #[getter]
275 fn get_vccbram(&self) -> f32 {
276 Self::adc_vcc_conversion(self.vccbram)
277 }
278
279 #[getter]
280 fn get_vccaux(&self) -> f32 {
281 Self::adc_vcc_conversion(self.vccaux)
282 }
283
284 #[getter]
285 pub fn get_rate(&self) -> u16 {
286 self.rate
287 }
288
289 #[getter]
290 pub fn get_lost_rate(&self) -> u16 {
291 self.lost_rate
292 }
293
294 #[getter]
295 pub fn get_tiu_busy_len(&self) -> u32 {
298 self.tiu_busy_len * 10
299 }
300
301 #[getter]
302 pub fn get_daq_queue_len(&self) -> u16 {
303 self.daq_queue_len
304 }
305
306 #[getter]
307 #[pyo3(name="tiu_emulation_mode")]
308 pub fn get_tiu_emulation_mode_py(&self) -> bool {
309 self.get_tiu_emulation_mode()
310 }
311
312 #[getter]
313 #[pyo3(name="tiu_use_aux_link")]
314 pub fn get_tiu_use_aux_link_py(&self) -> bool {
315 self.get_tiu_use_aux_link()
316 }
317
318 #[getter]
319 #[pyo3(name="tiu_bad")]
320 pub fn get_tiu_bad_py(&self) -> bool {
321 self.get_tiu_bad()
322 }
323
324 #[getter]
325 #[pyo3(name="tiu_busy_stuck")]
326 pub fn get_tiu_busy_stuck_py(&self) -> bool {
327 self.get_tiu_busy_stuck()
328 }
329
330 #[getter]
331 #[pyo3(name="tiu_ignore_busy")]
332 pub fn get_tiu_ignore_busy_py(&self) -> bool {
333 self.get_tiu_ignore_busy()
334 }
335
336
337 #[getter]
338 #[pyo3(name="fpga_temp")]
339 pub fn get_fpga_temp_py(&self) -> f32 {
340 self.get_fpga_temp()
341 }
342
343 #[getter]
344 pub fn get_timestamp(&self) -> u64 {
345 self.timestamp
346 }
347}
348
349moniseries!(MtbMoniDataSeries, MtbMoniData);
353
354#[cfg(feature="pybindings")]
355pythonize_packable!(MtbMoniData);
356
357#[cfg(feature="pybindings")]
358pythonize_monidata!(MtbMoniData);
359
360#[test]
363#[cfg(feature = "random")]
364fn pack_mtbmonidata() {
365 for _ in 0..100 {
366 let data = MtbMoniData::from_random();
367 let test : MtbMoniData = data.pack().unpack().unwrap();
368 assert_eq!(data, test);
369 }
370}
371