Skip to main content

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;