alpha_g_detector/alpha16.rs
1use std::fmt;
2use thiserror::Error;
3
4// Only imported for documentation. If you notice that this is no longer the
5// case, please open an issue/PR.
6#[allow(unused_imports)]
7use crate::alpha16::aw_map::TpcWirePosition;
8
9/// Anode wire map.
10pub mod aw_map;
11
12/// Sampling rate (samples per second) of the ADC channels that receive the
13/// Barrel Veto SiPM signals.
14pub const ADC16_RATE: f64 = 100e6;
15/// Sampling rate (samples per second) of the ADC channels that receive the
16/// radial Time Projection Chamber anode wire signals.
17pub const ADC32_RATE: f64 = 62.5e6;
18/// Maximum value at which the ADC waveforms saturate.
19pub const ADC_MAX: i16 = 32764;
20/// Minimum value at which the ADC waveforms saturate.
21pub const ADC_MIN: i16 = -32768;
22
23/// The error type returned when conversion from unsigned integer to
24/// [`ChannelId`] fails.
25#[derive(Error, Debug)]
26#[error("unknown conversion from unsigned `{input}` to ChannelId")]
27pub struct TryChannelIdFromUnsignedError {
28 input: u8,
29}
30
31/// Channel ID that corresponds to SiPMs of the Barrel Veto.
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub struct Adc16ChannelId(u8);
34impl TryFrom<u8> for Adc16ChannelId {
35 type Error = TryChannelIdFromUnsignedError;
36
37 /// There are 16 valid channel ids. Perform the conversion from an integer
38 /// in range `0..=15`.
39 fn try_from(num: u8) -> Result<Self, Self::Error> {
40 if num > 15 {
41 Err(TryChannelIdFromUnsignedError { input: num })
42 } else {
43 Ok(Adc16ChannelId(num))
44 }
45 }
46}
47
48/// Channel ID that corresponds to anode wires in the radial Time Projection
49/// Chamber.
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51pub struct Adc32ChannelId(u8);
52impl TryFrom<u8> for Adc32ChannelId {
53 type Error = TryChannelIdFromUnsignedError;
54
55 /// There are 32 valid channel ids. Perform the conversion from an integer
56 /// in range `0..=31`.
57 fn try_from(num: u8) -> Result<Self, Self::Error> {
58 if num > 31 {
59 Err(TryChannelIdFromUnsignedError { input: num })
60 } else {
61 Ok(Adc32ChannelId(num))
62 }
63 }
64}
65
66/// ADC channel ID in an Alpha16 board.
67#[derive(Clone, Copy, Debug)]
68pub enum ChannelId {
69 /// Barrel Veto SiPM channel.
70 A16(Adc16ChannelId),
71 /// Radial Time Projection Chamber anode wire channel.
72 A32(Adc32ChannelId),
73}
74// There is not TryFrom implementation because there is not an unambiguous
75// integer representation for both channels at the same time.
76// Agana uses some times [0-47] with [0-15] BV and [16-47] TPC. In other places
77// it uses [0-15] BV and [128-159] TPC. Avoid that mess here.
78
79/// The error type returned when conversion from unsigned integer to
80/// [`ModuleId`] fails.
81#[derive(Error, Debug)]
82#[error("unknown conversion from unsigned `{input}` to ModuleId")]
83pub struct TryModuleIdFromUnsignedError {
84 input: u8,
85}
86
87/// Module ID of an Alpha16 board.
88///
89/// I don't know how this is useful, the mapping to anode wires is independent
90/// from the module ID (see [`TpcWirePosition`]). This is included for
91/// completeness.
92#[derive(Clone, Copy, Debug, PartialEq, Eq)]
93pub struct ModuleId(u8);
94impl TryFrom<u8> for ModuleId {
95 type Error = TryModuleIdFromUnsignedError;
96
97 /// There are 8 valid module ids. Perform the conversion from an integer
98 /// in range `0..=7`.
99 fn try_from(num: u8) -> Result<Self, Self::Error> {
100 if num > 7 {
101 Err(TryModuleIdFromUnsignedError { input: num })
102 } else {
103 Ok(ModuleId(num))
104 }
105 }
106}
107
108/// The error type returned when conversion from mac address to [`BoardId`]
109/// fails.
110#[derive(Error, Debug)]
111#[error("unknown conversion from mac address `{input:?}` to BoardId")]
112pub struct TryBoardIdFromMacAddressError {
113 input: [u8; 6],
114}
115
116/// The error type returned when parsing a [`BoardId`] fails.
117#[derive(Error, Debug)]
118#[error("unknown parsing from board name `{input}` to BoardId")]
119pub struct ParseBoardIdError {
120 input: String,
121}
122
123// Known Alpha16 board names and mac addresses
124// Just add new boards to this list
125// ("name", [mac address])
126// "name" is 2 ASCII characters that also appear in the data bank name
127const ALPHA16BOARDS: [(&str, [u8; 6]); 8] = [
128 ("09", [216, 128, 57, 104, 55, 76]),
129 ("10", [216, 128, 57, 104, 170, 37]),
130 ("11", [216, 128, 57, 104, 172, 127]),
131 ("12", [216, 128, 57, 104, 79, 167]),
132 ("13", [216, 128, 57, 104, 202, 166]),
133 ("14", [216, 128, 57, 104, 142, 130]),
134 ("16", [216, 128, 57, 104, 111, 162]),
135 ("18", [216, 128, 57, 104, 142, 82]),
136];
137
138/// Identity of a physical Alpha16 board.
139///
140/// It is important to notice that a [`BoardId`] is different to a
141/// [`TpcWirePosition`]. The former identifies a physical Alpha16 board, while
142/// the latter is a fixed position that maps a location in the rTPC. The mapping
143/// between [`BoardId`] and [`TpcWirePosition`] depends on the run number e.g.
144/// we switch an old board for a new board.
145#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
146pub struct BoardId {
147 name: &'static str,
148 mac_address: [u8; 6],
149}
150impl TryFrom<&str> for BoardId {
151 type Error = ParseBoardIdError;
152
153 fn try_from(name: &str) -> Result<Self, Self::Error> {
154 for pair in ALPHA16BOARDS {
155 if name == pair.0 {
156 return Ok(BoardId {
157 name: pair.0,
158 mac_address: pair.1,
159 });
160 }
161 }
162 Err(ParseBoardIdError {
163 input: name.to_string(),
164 })
165 }
166}
167impl TryFrom<[u8; 6]> for BoardId {
168 type Error = TryBoardIdFromMacAddressError;
169
170 fn try_from(mac: [u8; 6]) -> Result<Self, Self::Error> {
171 for pair in ALPHA16BOARDS {
172 if mac == pair.1 {
173 return Ok(BoardId {
174 name: pair.0,
175 mac_address: pair.1,
176 });
177 }
178 }
179 Err(TryBoardIdFromMacAddressError { input: mac })
180 }
181}
182impl BoardId {
183 /// Return the name of a physical Alpha16 board. This is a human readable
184 /// name used to identify a board instead of the mac address.
185 ///
186 /// # Examples
187 ///
188 /// ```
189 /// # use alpha_g_detector::alpha16::TryBoardIdFromMacAddressError;
190 /// # fn main() -> Result<(), TryBoardIdFromMacAddressError> {
191 /// use alpha_g_detector::alpha16::BoardId;
192 ///
193 /// let board_id = BoardId::try_from([216, 128, 57, 104, 142, 82])?;
194 /// assert_eq!(board_id.name(), "18");
195 /// # Ok(())
196 /// # }
197 /// ```
198 pub fn name(&self) -> &str {
199 self.name
200 }
201 /// Return the mac address of a physical Alpha16 board.
202 ///
203 /// # Examples
204 ///
205 /// ```
206 /// # use alpha_g_detector::alpha16::TryBoardIdFromMacAddressError;
207 /// # fn main() -> Result<(), TryBoardIdFromMacAddressError> {
208 /// use alpha_g_detector::alpha16::BoardId;
209 ///
210 /// let board_id = BoardId::try_from([216, 128, 57, 104, 142, 82])?;
211 /// assert_eq!(board_id.mac_address(), [216, 128, 57, 104, 142, 82]);
212 /// # Ok(())
213 /// # }
214 /// ```
215 pub fn mac_address(&self) -> [u8; 6] {
216 self.mac_address
217 }
218}
219
220/// The error type returned when conversion from
221/// [`&[u8]`](https://doc.rust-lang.org/std/primitive.slice.html) to
222/// [`AdcPacket`] fails.
223#[derive(Error, Debug)]
224pub enum TryAdcPacketFromSliceError {
225 /// The input slice is not long enough to contain a complete packet.
226 #[error("incomplete slice (expected at least `{min_expected}` bytes, found `{found}`)")]
227 IncompleteSlice { found: usize, min_expected: usize },
228 /// Unknown packet type.
229 #[error("unknown packet type `{found}`")]
230 UnknownType { found: u8 },
231 /// Unknown packet version.
232 #[error("unknown packet version `{found}`")]
233 UnknownVersion { found: u8 },
234 /// Integer representation of Module ID doesn't match any known
235 /// [`ModuleId`].
236 #[error("unknown module id")]
237 UnknownModuleId(#[from] TryModuleIdFromUnsignedError),
238 /// Integer representation of channel ID doesn't match any known
239 /// [`ChannelId`].
240 #[error("unknown channel number")]
241 UnknownChannelId(#[from] TryChannelIdFromUnsignedError),
242 /// Non-zero value found in bytes meant to be fixed to `0`.
243 #[error("zero-bytes mismatch (found `{found:?}`)")]
244 ZeroMismatch { found: [u8; 2] },
245 /// MAC address doesn't map to any known [`BoardId`].
246 #[error("unknown mac address")]
247 UnknownMac(#[from] TryBoardIdFromMacAddressError),
248 /// Suppression baseline in the footer doesn't match waveform samples.
249 #[error("suppression baseline mismatch (expected `{expected}`, found `{found}`)")]
250 BaselineMismatch { found: i16, expected: i16 },
251 /// The value of `keep_last` is inconsistent with the `keep_bit`, or its
252 /// value is less than the minimum required by the suppression baseline.
253 // The `keep_more` and `threshold` values are not known here, so a more
254 // specific error than this is not possible.
255 // If limit == 0, then it is an inconsistency with the `keep_bit`
256 // If limit != 0, then value is less than the limit imposed by the
257 // suppression baseline.
258 #[error("bad keep_last `{found}` (limit was `{limit}`)")]
259 BadKeepLast { found: usize, limit: usize },
260 /// The `keep_bit` in the footer is inconsistent with the packet size and
261 /// data suppression status.
262 // The `threshold` is not known here, so a more specific error than this is
263 // not possible.
264 #[error("keep_bit mismatch (found `{found}`)")]
265 KeepBitMismatch { found: bool },
266 /// The number of waveform samples is less/more than the minimum/maximum
267 /// required by the suppression baseline, `keep_last`, or requested number
268 /// of samples.
269 #[error("bad number of samples `{found}` (expected at least `{min}` and at most `{max}`)")]
270 BadNumberOfSamples {
271 found: usize,
272 min: usize,
273 max: usize,
274 },
275}
276
277/// Version 3 of an ADC data packet.
278///
279/// An ADC packet represents the data collected from an individual channel in an
280/// Alpha16 board. The binary representation of an [`AdcV3Packet`] in a data
281/// bank is shown below. All multi-byte fields are big-endian:
282///
283/// <center>
284///
285/// |Byte(s)|Description|
286/// |:-:|:-:|
287/// |0|Fixed to 1|
288/// |1|Fixed to 3|
289/// |2-3|Accepted trigger|
290/// |4|Module ID|
291/// |5|Channel ID|
292/// |6-7|Requested samples|
293/// |8-11|Event timestamp (LSW)|
294/// |12-13|Fixed to 0|
295/// |14-19|MAC address|
296/// |20-23|Event timestamp (MSW)|
297/// |24-27|Trigger offset|
298/// |28-31|Build timestamp|
299/// |32-33|First waveform sample|
300/// |...|Waveform samples|
301/// |Last 4 bytes|Data suppression info|
302///
303/// </center>
304///
305/// Bytes `[12..size - 4]` are only included in the packet if the `keep_bit` is
306/// set after data suppression.
307#[derive(Clone, Debug)]
308pub struct AdcV3Packet {
309 accepted_trigger: u16,
310 module_id: ModuleId,
311 channel_id: ChannelId,
312 requested_samples: usize,
313 event_timestamp: u64,
314 board_id: Option<BoardId>,
315 trigger_offset: Option<i32>,
316 build_timestamp: Option<u32>,
317 waveform: Vec<i16>,
318 suppression_baseline: i16,
319 keep_last: usize,
320 keep_bit: bool,
321 suppression_enabled: bool,
322}
323
324impl fmt::Display for AdcV3Packet {
325 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 writeln!(f, "Packet type: {}", self.packet_type())?;
327 writeln!(f, "Packet version: {}", self.packet_version())?;
328 writeln!(f, "Accepted trigger: {}", self.accepted_trigger)?;
329 writeln!(f, "Module ID: {:?}", self.module_id)?;
330 let channel_id = match self.channel_id {
331 ChannelId::A16(channel) => format!("{channel:?}"),
332 ChannelId::A32(channel) => format!("{channel:?}"),
333 };
334 writeln!(f, "Channel ID: {channel_id}")?;
335 writeln!(f, "Requested samples: {}", self.requested_samples)?;
336 writeln!(f, "Event timestamp: {}", self.event_timestamp)?;
337 let mac_address = self
338 .board_id
339 .map_or("None".to_string(), |b| format!("{:?}", b.mac_address()));
340 writeln!(f, "MAC address: {mac_address}")?;
341 let trigger_offset = self
342 .trigger_offset
343 .map_or("None".to_string(), |v| v.to_string());
344 writeln!(f, "Trigger offset: {trigger_offset}",)?;
345 let build_timestamp = self
346 .build_timestamp
347 .map_or("None".to_string(), |v| v.to_string());
348 writeln!(f, "Build timestamp: {build_timestamp}",)?;
349 writeln!(f, "Waveform samples: {}", self.waveform.len())?;
350 writeln!(f, "Suppression baseline: {}", self.suppression_baseline)?;
351 writeln!(f, "Keep last: {}", self.keep_last)?;
352 writeln!(f, "Keep bit: {}", self.keep_bit)?;
353 write!(f, "Suppression enabled: {}", self.suppression_enabled)?;
354
355 Ok(())
356 }
357}
358
359impl AdcV3Packet {
360 /// Return the packet type.
361 ///
362 /// # Examples
363 ///
364 /// ```
365 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
366 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
367 /// use alpha_g_detector::alpha16::AdcV3Packet;
368 ///
369 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
370 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
371 ///
372 /// assert_eq!(packet.packet_type(), 1);
373 /// # Ok(())
374 /// # }
375 /// ```
376 pub fn packet_type(&self) -> u8 {
377 1
378 }
379 /// Return the packet version. For [`AdcV3Packet`] it is fixed to `3`.
380 ///
381 /// # Examples
382 ///
383 /// ```
384 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
385 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
386 /// use alpha_g_detector::alpha16::AdcV3Packet;
387 ///
388 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
389 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
390 ///
391 /// assert_eq!(packet.packet_version(), 3);
392 /// # Ok(())
393 /// # }
394 /// ```
395 pub fn packet_version(&self) -> u8 {
396 3
397 }
398 /// In the firmware logic, `accepted_trigger` is a 32-bits unsigned integer.
399 /// Return the 16 LSB as [`u16`].
400 ///
401 /// This is a counter that indicates the number of trigger signals received
402 /// from the TRG board. All packets from the same event must have the same
403 /// `accepted_trigger` counter.
404 ///
405 /// # Examples
406 ///
407 /// ```
408 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
409 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
410 /// use alpha_g_detector::alpha16::AdcV3Packet;
411 ///
412 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
413 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
414 ///
415 /// assert_eq!(packet.accepted_trigger(), 4);
416 /// # Ok(())
417 /// # }
418 /// ```
419 pub fn accepted_trigger(&self) -> u16 {
420 self.accepted_trigger
421 }
422 /// Return the [`ModuleId`] of the Alpha16 board from which the packet was
423 /// generated.
424 ///
425 /// # Examples
426 ///
427 /// ```
428 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
429 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
430 /// use alpha_g_detector::alpha16::{AdcV3Packet, ModuleId};
431 ///
432 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
433 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
434 ///
435 /// assert_eq!(packet.module_id(), ModuleId::try_from(5)?);
436 /// # Ok(())
437 /// # }
438 /// ```
439 pub fn module_id(&self) -> ModuleId {
440 self.module_id
441 }
442 /// Return the [`ChannelId`] in an Alpha16 board from which the packet was
443 /// generated.
444 ///
445 /// # Examples
446 ///
447 /// ```
448 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
449 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
450 /// use alpha_g_detector::alpha16::{AdcV3Packet, ChannelId};
451 ///
452 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
453 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
454 ///
455 /// assert!(matches!(packet.channel_id(), ChannelId::A16(_)));
456 /// # Ok(())
457 /// # }
458 /// ```
459 pub fn channel_id(&self) -> ChannelId {
460 self.channel_id
461 }
462 /// Return the number of requested waveform samples. The actual number of
463 /// samples in the packet should be obtained from [`waveform`]; due to data
464 /// suppression these two are most likely not equal.
465 ///
466 /// [`waveform`]: AdcV3Packet::waveform.
467 ///
468 /// # Examples
469 ///
470 /// ```
471 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
472 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
473 /// use alpha_g_detector::alpha16::AdcV3Packet;
474 ///
475 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
476 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
477 ///
478 /// assert_eq!(packet.requested_samples(), 699);
479 /// # Ok(())
480 /// # }
481 /// ```
482 pub fn requested_samples(&self) -> usize {
483 self.requested_samples
484 }
485 /// I do not know what this field means. It never matches the event
486 /// timestamp in the MIDAS event.
487 ///
488 /// # Examples
489 ///
490 /// ```
491 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
492 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
493 /// use alpha_g_detector::alpha16::AdcV3Packet;
494 ///
495 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
496 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
497 ///
498 /// assert_eq!(packet.event_timestamp(), 7);
499 /// # Ok(())
500 /// # }
501 /// ```
502 pub fn event_timestamp(&self) -> u64 {
503 self.event_timestamp
504 }
505 /// Return the [`BoardId`] of the Alpha16 board from which the packet was
506 /// generated. Return [`None`] if data suppression is enabled and the
507 /// `keep_bit` is not set.
508 ///
509 /// # Examples
510 ///
511 /// ```
512 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
513 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
514 /// use alpha_g_detector::alpha16::AdcV3Packet;
515 ///
516 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
517 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
518 ///
519 /// assert!(packet.board_id().is_none());
520 /// # Ok(())
521 /// # }
522 /// ```
523 pub fn board_id(&self) -> Option<BoardId> {
524 self.board_id
525 }
526 /// I do not understand what this field means exactly. I know that it
527 /// matches `adcXX_trig_delay - adcXX_trig_start` in the ODB (with `XX`
528 /// equal to `16` or `32`). Return [`None`] if data suppression is enabled
529 /// and the `keep_bit` is not set.
530 ///
531 /// # Examples
532 ///
533 /// ```
534 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
535 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
536 /// use alpha_g_detector::alpha16::AdcV3Packet;
537 ///
538 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
539 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
540 ///
541 /// assert!(packet.trigger_offset().is_none());
542 /// # Ok(())
543 /// # }
544 /// ```
545 pub fn trigger_offset(&self) -> Option<i32> {
546 self.trigger_offset
547 }
548 /// Return the SOF file build timestamp; this acts as firmware version.
549 /// Return [`None`] if data suppression is enabled and the `keep_bit` is not
550 /// set.
551 ///
552 /// # Examples
553 ///
554 /// ```
555 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
556 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
557 /// use alpha_g_detector::alpha16::AdcV3Packet;
558 ///
559 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
560 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
561 ///
562 /// assert!(packet.build_timestamp().is_none());
563 /// # Ok(())
564 /// # }
565 /// ```
566 pub fn build_timestamp(&self) -> Option<u32> {
567 self.build_timestamp
568 }
569 /// Return the digitized waveform samples received by an ADC channel in an
570 /// Alpha16 board. Return an empty slice if data suppression is enabled and
571 /// the `keep_bit` is not set.
572 ///
573 /// # Examples
574 ///
575 /// ```
576 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
577 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
578 /// use alpha_g_detector::alpha16::AdcV3Packet;
579 ///
580 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
581 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
582 ///
583 /// assert!(packet.waveform().is_empty());
584 /// # Ok(())
585 /// # }
586 /// ```
587 pub fn waveform(&self) -> &[i16] {
588 &self.waveform
589 }
590 /// Return the data suppression waveform baseline.
591 ///
592 /// # Examples
593 ///
594 /// ```
595 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
596 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
597 /// use alpha_g_detector::alpha16::AdcV3Packet;
598 ///
599 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
600 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
601 ///
602 /// assert_eq!(packet.suppression_baseline(), 0);
603 /// # Ok(())
604 /// # }
605 /// ```
606 pub fn suppression_baseline(&self) -> i16 {
607 self.suppression_baseline
608 }
609 /// This is a counter in the firmware side on how many data words are being
610 /// kept due to data suppression. If the `keep_bit` is not set, then
611 /// `keep_last` is equal to 0. This counter increases by the index of the
612 /// last waveform sample over threshold as `keep_last = (index + 2) / 2 + 1`.
613 ///
614 /// Recall that data suppression doesn't "see" the last 6(?) samples, hence
615 /// `keep_last` is not a reliable way to obtain the last waveform sample
616 /// over the data suppression threshold. This `keep_last` value is only
617 /// really useful in validating/checking the data suppression on the
618 /// firmware side. If you are using this for anything else, you are most
619 /// likely making a mistake.
620 ///
621 /// # Examples
622 ///
623 /// ```
624 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
625 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
626 /// use alpha_g_detector::alpha16::AdcV3Packet;
627 ///
628 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
629 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
630 ///
631 /// assert_eq!(packet.keep_last(), 0);
632 /// # Ok(())
633 /// # }
634 /// ```
635 pub fn keep_last(&self) -> usize {
636 self.keep_last
637 }
638 /// Return [`true`] if at least one [`waveform`] sample is over the data
639 /// suppression threshold.
640 ///
641 /// [`waveform`]: AdcV3Packet::waveform.
642 ///
643 /// # Examples
644 ///
645 /// ```
646 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
647 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
648 /// use alpha_g_detector::alpha16::AdcV3Packet;
649 ///
650 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
651 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
652 ///
653 /// assert!(!packet.keep_bit());
654 /// # Ok(())
655 /// # }
656 /// ```
657 pub fn keep_bit(&self) -> bool {
658 self.keep_bit
659 }
660 /// Return [`true`] if data suppression is enabled.
661 ///
662 /// # Examples
663 ///
664 /// ```
665 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
666 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
667 /// use alpha_g_detector::alpha16::AdcV3Packet;
668 ///
669 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
670 /// let packet = AdcV3Packet::try_from(&buffer[..])?;
671 ///
672 /// assert!(packet.is_suppression_enabled());
673 /// # Ok(())
674 /// # }
675 /// ```
676 pub fn is_suppression_enabled(&self) -> bool {
677 self.suppression_enabled
678 }
679}
680
681// The minimum number of samples required to reconstruct the data suppression
682// baseline.
683const BASELINE_SAMPLES: usize = 64;
684// Minimum valid value of keep_last different to 0.
685// keep_last = (index + 2) / 2 + 1
686// And the minimum index is one after the baseline.
687const MIN_KEEP_LAST: usize = (BASELINE_SAMPLES + 2) / 2 + 1;
688
689impl TryFrom<&[u8]> for AdcV3Packet {
690 type Error = TryAdcPacketFromSliceError;
691
692 // All fields are big endian
693 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
694 if slice.len() < 16 {
695 return Err(Self::Error::IncompleteSlice {
696 found: slice.len(),
697 min_expected: 16,
698 });
699 }
700
701 if slice[0] != 1 {
702 return Err(Self::Error::UnknownType { found: slice[0] });
703 }
704 if slice[1] != 3 {
705 return Err(Self::Error::UnknownVersion { found: slice[1] });
706 }
707 let accepted_trigger = slice[2..4].try_into().unwrap();
708 let accepted_trigger = u16::from_be_bytes(accepted_trigger);
709 let module_id = ModuleId::try_from(slice[4])?;
710 // A value of [0-15] is BV, and a value of [128-159] is rTPC
711 let channel_id = slice[5];
712 let channel_id = if channel_id < 128 {
713 ChannelId::A16(channel_id.try_into()?)
714 } else {
715 ChannelId::A32((channel_id - 128).try_into()?)
716 };
717 let requested_samples = slice[6..8].try_into().unwrap();
718 let requested_samples = u16::from_be_bytes(requested_samples).into();
719 let lsw_event_timestamp = slice[8..12].try_into().unwrap();
720
721 let suppression_baseline = slice[slice.len() - 2..].try_into().unwrap();
722 let suppression_baseline = i16::from_be_bytes(suppression_baseline);
723 let footer = slice[slice.len() - 4..][..2].try_into().unwrap();
724 let footer = u16::from_be_bytes(footer);
725 let keep_last = usize::from(footer & 0xFFF);
726 let keep_bit = (footer >> 12) & 1 == 1;
727 let suppression_enabled = (footer >> 13) & 1 == 1;
728
729 if slice.len() == 16 {
730 if !suppression_enabled {
731 return Err(Self::Error::IncompleteSlice {
732 found: 16,
733 min_expected: 36,
734 });
735 }
736 if keep_bit {
737 return Err(Self::Error::KeepBitMismatch { found: keep_bit });
738 }
739 if keep_last != 0 {
740 return Err(Self::Error::BadKeepLast {
741 found: keep_last,
742 limit: 0,
743 });
744 }
745 return Ok(AdcV3Packet {
746 accepted_trigger,
747 module_id,
748 channel_id,
749 requested_samples,
750 event_timestamp: u32::from_be_bytes(lsw_event_timestamp).into(),
751 board_id: None,
752 trigger_offset: None,
753 build_timestamp: None,
754 waveform: Vec::new(),
755 keep_last,
756 suppression_baseline,
757 keep_bit,
758 suppression_enabled,
759 });
760 }
761
762 if slice.len() < 36 {
763 return Err(Self::Error::IncompleteSlice {
764 found: slice.len(),
765 min_expected: 36,
766 });
767 }
768
769 if slice[12..14] != [0, 0] {
770 return Err(Self::Error::ZeroMismatch {
771 found: slice[12..14].try_into().unwrap(),
772 });
773 }
774 let board_id: [u8; 6] = slice[14..20].try_into().unwrap();
775 let board_id = BoardId::try_from(board_id)?;
776 let msw_event_timestamp = slice[20..24].try_into().unwrap();
777 let event_timestamp = [msw_event_timestamp, lsw_event_timestamp].concat();
778 let event_timestamp = event_timestamp.try_into().unwrap();
779 let event_timestamp = u64::from_be_bytes(event_timestamp);
780 let trigger_offset = slice[24..28].try_into().unwrap();
781 let trigger_offset = i32::from_be_bytes(trigger_offset);
782 let build_timestamp = slice[28..32].try_into().unwrap();
783 let build_timestamp = u32::from_be_bytes(build_timestamp);
784 let waveform_bytes = slice.len() - 36;
785 if waveform_bytes % 2 != 0 {
786 return Err(Self::Error::IncompleteSlice {
787 // waveform bytes + header + footer
788 found: waveform_bytes + 36,
789 min_expected: waveform_bytes + 37,
790 });
791 }
792 let waveform: Vec<i16> = slice[32..][..waveform_bytes]
793 .chunks_exact(2)
794 .map(|b| i16::from_be_bytes(b.try_into().unwrap()))
795 .collect();
796
797 if waveform.len() < BASELINE_SAMPLES {
798 return Err(Self::Error::BadNumberOfSamples {
799 found: waveform.len(),
800 min: BASELINE_SAMPLES,
801 max: requested_samples - 2,
802 });
803 }
804 let data_baseline = {
805 // Add over i32 to avoid overflow
806 let num = waveform[..BASELINE_SAMPLES]
807 .iter()
808 .map(|n| i32::from(*n))
809 .sum::<i32>();
810 let d = num / 64;
811 if num % 64 < 0 {
812 d - 1
813 } else {
814 d
815 }
816 };
817 if data_baseline != suppression_baseline.into() {
818 return Err(Self::Error::BaselineMismatch {
819 found: suppression_baseline,
820 expected: data_baseline.try_into().unwrap(),
821 });
822 }
823
824 if suppression_enabled {
825 if !keep_bit {
826 return Err(Self::Error::KeepBitMismatch { found: keep_bit });
827 }
828 if keep_last < MIN_KEEP_LAST {
829 return Err(Self::Error::BadKeepLast {
830 found: keep_last,
831 limit: MIN_KEEP_LAST,
832 });
833 }
834 let last_index = (keep_last - 1) * 2 - 2;
835 if waveform.len() <= last_index {
836 return Err(Self::Error::BadNumberOfSamples {
837 found: waveform.len(),
838 min: last_index + 1,
839 max: requested_samples - 2,
840 });
841 }
842 if waveform.len() > requested_samples - 2 {
843 return Err(Self::Error::BadNumberOfSamples {
844 found: waveform.len(),
845 min: last_index + 1,
846 max: requested_samples - 2,
847 });
848 }
849 } else {
850 if keep_bit {
851 if keep_last < MIN_KEEP_LAST {
852 return Err(Self::Error::BadKeepLast {
853 found: keep_last,
854 limit: MIN_KEEP_LAST,
855 });
856 }
857 let last_index = (keep_last - 1) * 2 - 2;
858 if waveform.len() <= last_index {
859 return Err(Self::Error::BadNumberOfSamples {
860 found: waveform.len(),
861 min: last_index + 1,
862 max: requested_samples - 2,
863 });
864 }
865 } else if keep_last != 0 {
866 return Err(Self::Error::BadKeepLast {
867 found: keep_last,
868 limit: 0,
869 });
870 }
871 if waveform.len() != requested_samples - 2 {
872 return Err(Self::Error::BadNumberOfSamples {
873 found: waveform.len(),
874 min: requested_samples - 2,
875 max: requested_samples - 2,
876 });
877 }
878 }
879
880 Ok(AdcV3Packet {
881 accepted_trigger,
882 module_id,
883 channel_id,
884 requested_samples,
885 event_timestamp,
886 board_id: Some(board_id),
887 trigger_offset: Some(trigger_offset),
888 build_timestamp: Some(build_timestamp),
889 waveform,
890 keep_last,
891 suppression_baseline,
892 keep_bit,
893 suppression_enabled,
894 })
895 }
896}
897
898/// ADC data packet.
899///
900/// This enum can currently contain only an [`AdcV3Packet`]. See its
901/// documentation for more details.
902#[derive(Clone, Debug)]
903pub enum AdcPacket {
904 /// Version 3 of an ADC packet.
905 V3(AdcV3Packet),
906}
907
908impl fmt::Display for AdcPacket {
909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 match self {
911 Self::V3(packet) => write!(f, "{packet}"),
912 }
913 }
914}
915
916impl AdcPacket {
917 /// Return the packet type.
918 ///
919 /// # Examples
920 ///
921 /// ```
922 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
923 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
924 /// use alpha_g_detector::alpha16::AdcPacket;
925 ///
926 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
927 /// let packet = AdcPacket::try_from(&buffer[..])?;
928 ///
929 /// assert_eq!(packet.packet_type(), 1);
930 /// # Ok(())
931 /// # }
932 /// ```
933 pub fn packet_type(&self) -> u8 {
934 match self {
935 Self::V3(packet) => packet.packet_type(),
936 }
937 }
938 /// Return the packet version.
939 ///
940 /// # Examples
941 ///
942 /// ```
943 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
944 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
945 /// use alpha_g_detector::alpha16::AdcPacket;
946 ///
947 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
948 /// let packet = AdcPacket::try_from(&buffer[..])?;
949 ///
950 /// assert_eq!(packet.packet_version(), 3);
951 /// # Ok(())
952 /// # }
953 /// ```
954 pub fn packet_version(&self) -> u8 {
955 match self {
956 Self::V3(packet) => packet.packet_version(),
957 }
958 }
959 /// In the firmware logic, `accepted_trigger` is a 32-bits unsigned integer.
960 /// Return the 16 LSB as [`u16`].
961 ///
962 /// This is a counter that indicates the number of trigger signals received
963 /// from the TRG board. All packets from the same event must have the same
964 /// `accepted_trigger` counter.
965 ///
966 /// # Examples
967 ///
968 /// ```
969 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
970 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
971 /// use alpha_g_detector::alpha16::AdcPacket;
972 ///
973 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
974 /// let packet = AdcPacket::try_from(&buffer[..])?;
975 ///
976 /// assert_eq!(packet.accepted_trigger(), 4);
977 /// # Ok(())
978 /// # }
979 /// ```
980 pub fn accepted_trigger(&self) -> u16 {
981 match self {
982 Self::V3(packet) => packet.accepted_trigger(),
983 }
984 }
985 /// Return the [`ModuleId`] of the Alpha16 board from which the packet was
986 /// generated.
987 ///
988 /// # Examples
989 ///
990 /// ```
991 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
992 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
993 /// use alpha_g_detector::alpha16::{AdcPacket, ModuleId};
994 ///
995 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
996 /// let packet = AdcPacket::try_from(&buffer[..])?;
997 ///
998 /// assert_eq!(packet.module_id(), ModuleId::try_from(5)?);
999 /// # Ok(())
1000 /// # }
1001 /// ```
1002 pub fn module_id(&self) -> ModuleId {
1003 match self {
1004 Self::V3(packet) => packet.module_id(),
1005 }
1006 }
1007 /// Return the [`ChannelId`] in an Alpha16 board from which the packet was
1008 /// generated.
1009 ///
1010 /// # Examples
1011 ///
1012 /// ```
1013 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1014 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1015 /// use alpha_g_detector::alpha16::{AdcPacket, ChannelId};
1016 ///
1017 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1018 /// let packet = AdcPacket::try_from(&buffer[..])?;
1019 ///
1020 /// assert!(matches!(packet.channel_id(), ChannelId::A16(_)));
1021 /// # Ok(())
1022 /// # }
1023 /// ```
1024 pub fn channel_id(&self) -> ChannelId {
1025 match self {
1026 Self::V3(packet) => packet.channel_id(),
1027 }
1028 }
1029 /// Return the number of requested waveform samples. The actual number of
1030 /// samples in the packet should be obtained from [`waveform`]; due to data
1031 /// suppression these two are most likely not equal.
1032 ///
1033 /// [`waveform`]: AdcV3Packet::waveform.
1034 ///
1035 /// # Examples
1036 ///
1037 /// ```
1038 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1039 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1040 /// use alpha_g_detector::alpha16::AdcPacket;
1041 ///
1042 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1043 /// let packet = AdcPacket::try_from(&buffer[..])?;
1044 ///
1045 /// assert_eq!(packet.requested_samples(), 699);
1046 /// # Ok(())
1047 /// # }
1048 /// ```
1049 pub fn requested_samples(&self) -> usize {
1050 match self {
1051 Self::V3(packet) => packet.requested_samples(),
1052 }
1053 }
1054 /// I do not know what this field means. It never matches the event
1055 /// timestamp in the MIDAS event.
1056 ///
1057 /// # Examples
1058 ///
1059 /// ```
1060 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1061 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1062 /// use alpha_g_detector::alpha16::AdcPacket;
1063 ///
1064 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1065 /// let packet = AdcPacket::try_from(&buffer[..])?;
1066 ///
1067 /// assert_eq!(packet.event_timestamp(), 7);
1068 /// # Ok(())
1069 /// # }
1070 /// ```
1071 pub fn event_timestamp(&self) -> u64 {
1072 match self {
1073 Self::V3(packet) => packet.event_timestamp(),
1074 }
1075 }
1076 /// Return the [`BoardId`] of the Alpha16 board from which the packet was
1077 /// generated. Return [`None`] if data suppression is enabled and the
1078 /// `keep_bit` is not set in a version 3 packet.
1079 ///
1080 /// # Examples
1081 ///
1082 /// ```
1083 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1084 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1085 /// use alpha_g_detector::alpha16::{AdcPacket, BoardId};
1086 ///
1087 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1088 /// let packet = AdcPacket::try_from(&buffer[..])?;
1089 ///
1090 /// assert!(packet.board_id().is_none());
1091 /// # Ok(())
1092 /// # }
1093 /// ```
1094 pub fn board_id(&self) -> Option<BoardId> {
1095 match self {
1096 Self::V3(packet) => packet.board_id(),
1097 }
1098 }
1099 /// I do not understand what this field means exactly. I know that it
1100 /// matches `adcXX_trig_delay - adcXX_trig_start` in the ODB (with `XX`
1101 /// equal to `16` or `32`). Return [`None`] if data suppression is enabled
1102 /// and the `keep_bit` is not set in a version 3 packet.
1103 ///
1104 /// # Examples
1105 ///
1106 /// ```
1107 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1108 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1109 /// use alpha_g_detector::alpha16::AdcPacket;
1110 ///
1111 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1112 /// let packet = AdcPacket::try_from(&buffer[..])?;
1113 ///
1114 /// assert!(packet.trigger_offset().is_none());
1115 /// # Ok(())
1116 /// # }
1117 /// ```
1118 pub fn trigger_offset(&self) -> Option<i32> {
1119 match self {
1120 Self::V3(packet) => packet.trigger_offset(),
1121 }
1122 }
1123 /// Return the SOF file build timestamp; this acts as firmware version.
1124 /// Return [`None`] if data suppression is enabled and the `keep_bit` is not
1125 /// set in a version 3 packet.
1126 ///
1127 /// # Examples
1128 ///
1129 /// ```
1130 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1131 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1132 /// use alpha_g_detector::alpha16::AdcPacket;
1133 ///
1134 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1135 /// let packet = AdcPacket::try_from(&buffer[..])?;
1136 ///
1137 /// assert!(packet.build_timestamp().is_none());
1138 /// # Ok(())
1139 /// # }
1140 /// ```
1141 pub fn build_timestamp(&self) -> Option<u32> {
1142 match self {
1143 Self::V3(packet) => packet.build_timestamp(),
1144 }
1145 }
1146 /// Return the digitized waveform samples received by an ADC channel in an
1147 /// Alpha16 board. Return an empty slice if data suppression is enabled and
1148 /// the `keep_bit` is not set in a version 3 packet.
1149 ///
1150 /// # Examples
1151 ///
1152 /// ```
1153 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1154 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1155 /// use alpha_g_detector::alpha16::AdcPacket;
1156 ///
1157 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1158 /// let packet = AdcPacket::try_from(&buffer[..])?;
1159 ///
1160 /// assert!(packet.waveform().is_empty());
1161 /// # Ok(())
1162 /// # }
1163 /// ```
1164 pub fn waveform(&self) -> &[i16] {
1165 match self {
1166 Self::V3(packet) => packet.waveform(),
1167 }
1168 }
1169 /// Return the data suppression waveform baseline. Return [`None`] if this
1170 /// is a version 1 packet (these don't have any data suppression
1171 /// implemented).
1172 ///
1173 /// # Examples
1174 ///
1175 /// ```
1176 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1177 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1178 /// use alpha_g_detector::alpha16::AdcPacket;
1179 ///
1180 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1181 /// let packet = AdcPacket::try_from(&buffer[..])?;
1182 ///
1183 /// assert_eq!(packet.suppression_baseline(), Some(0));
1184 /// # Ok(())
1185 /// # }
1186 /// ```
1187 pub fn suppression_baseline(&self) -> Option<i16> {
1188 match self {
1189 Self::V3(packet) => Some(packet.suppression_baseline()),
1190 }
1191 }
1192 /// This is a counter in the firmware side on how many data words are being
1193 /// kept due to data suppression. If the `keep_bit` is not set, then
1194 /// `keep_last` is equal to 0. This counter increases by the index of the
1195 /// last waveform sample over threshold as `keep_last = (index + 2) / 2 + 1`.
1196 ///
1197 /// Recall that data suppression doesn't "see" the last 6(?) samples, hence
1198 /// `keep_last` is not a reliable way to obtain the last waveform sample
1199 /// over the data suppression threshold. This `keep_last` value is only
1200 /// really useful in validating/checking the data suppression on the
1201 /// firmware side. If you are using this for anything else, you are most
1202 /// likely making a mistake.
1203 ///
1204 /// Return [`None`] if this is a version 1 packet (these don't have any
1205 /// data suppression implemented).
1206 ///
1207 /// # Examples
1208 ///
1209 /// ```
1210 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1211 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1212 /// use alpha_g_detector::alpha16::AdcPacket;
1213 ///
1214 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1215 /// let packet = AdcPacket::try_from(&buffer[..])?;
1216 ///
1217 /// assert_eq!(packet.keep_last(), Some(0));
1218 /// # Ok(())
1219 /// # }
1220 /// ```
1221 pub fn keep_last(&self) -> Option<usize> {
1222 match self {
1223 Self::V3(packet) => Some(packet.keep_last()),
1224 }
1225 }
1226 /// Return [`true`] if at least one [`waveform`] sample is over the data
1227 /// suppression threshold. Return [`None`] if this is a version 1 packet
1228 /// (these don't have any data suppression implemented).
1229 ///
1230 /// [`waveform`]: AdcV3Packet::waveform.
1231 ///
1232 /// # Examples
1233 ///
1234 /// ```
1235 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1236 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1237 /// use alpha_g_detector::alpha16::AdcPacket;
1238 ///
1239 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1240 /// let packet = AdcPacket::try_from(&buffer[..])?;
1241 ///
1242 /// assert_eq!(packet.keep_bit(), Some(false));
1243 /// # Ok(())
1244 /// # }
1245 /// ```
1246 pub fn keep_bit(&self) -> Option<bool> {
1247 match self {
1248 Self::V3(packet) => Some(packet.keep_bit()),
1249 }
1250 }
1251 /// Return [`true`] if data suppression is enabled. Return [`None`] if this
1252 /// is a version 1 packet (these don't have any data suppression
1253 /// implemented).
1254 ///
1255 /// # Examples
1256 ///
1257 /// ```
1258 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1259 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1260 /// use alpha_g_detector::alpha16::AdcPacket;
1261 ///
1262 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1263 /// let packet = AdcPacket::try_from(&buffer[..])?;
1264 ///
1265 /// assert_eq!(packet.is_suppression_enabled(), Some(true));
1266 /// # Ok(())
1267 /// # }
1268 /// ```
1269 pub fn is_suppression_enabled(&self) -> Option<bool> {
1270 match self {
1271 Self::V3(packet) => Some(packet.is_suppression_enabled()),
1272 }
1273 }
1274 /// Return [`true`] if this adc packet is an [`AdcV3Packet`], and [`false`]
1275 /// otherwise.
1276 ///
1277 /// # Examples
1278 ///
1279 /// ```
1280 /// # use alpha_g_detector::alpha16::TryAdcPacketFromSliceError;
1281 /// # fn main() -> Result<(), TryAdcPacketFromSliceError> {
1282 /// use alpha_g_detector::alpha16::AdcPacket;
1283 ///
1284 /// let buffer = [1, 3, 0, 4, 5, 6, 2, 187, 0, 0, 0, 7, 224, 0, 0, 0];
1285 /// let packet = AdcPacket::try_from(&buffer[..])?;
1286 ///
1287 /// assert!(packet.is_v3());
1288 /// # Ok(())
1289 /// # }
1290 /// ```
1291 pub fn is_v3(&self) -> bool {
1292 matches!(self, Self::V3(_))
1293 }
1294}
1295
1296impl TryFrom<&[u8]> for AdcPacket {
1297 type Error = TryAdcPacketFromSliceError;
1298
1299 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
1300 Ok(AdcPacket::V3(AdcV3Packet::try_from(slice)?))
1301 }
1302}
1303
1304#[cfg(test)]
1305mod tests;