autd3_driver/firmware/fpga/
gpio_out.rs

1use crate::{ethercat::DcSysTime, geometry::Transducer};
2
3use derive_more::Debug;
4use zerocopy::{Immutable, IntoBytes};
5
6use super::ec_time_to_sys_time;
7
8/// Output of the GPIO pin. See also [`GPIOOutputs`].
9///
10/// [`GPIOOutputs`]: crate::datagram::GPIOOutputs
11#[non_exhaustive]
12#[derive(Clone, Debug)]
13pub enum GPIOOutputType<'a> {
14    /// Base signal (50% duty cycle square wave with the same frequency as ultrasound).
15    BaseSignal,
16    /// High if the temperature sensor is asserted.
17    Thermo,
18    /// High if the ForceFan flag is asserted.
19    ForceFan,
20    /// EtherCAT synchronization signal.
21    Sync,
22    /// Modulation segment (High if the segment is 1, Low if the segment is 0).
23    ModSegment,
24    #[debug("ModIdx({})", _0)]
25    /// High when the Modulation index is the specified value.
26    ModIdx(u16),
27    /// STM and Gain segment (High if the segment is 1, Low if the segment is 0).
28    StmSegment,
29    #[debug("StmIdx({})", _0)]
30    /// High when the STM index is the specified value.
31    StmIdx(u16),
32    /// High if FociSTM/GainSTM is used.
33    IsStmMode,
34    /// High during the specified system time.
35    SysTimeEq(DcSysTime),
36    #[debug("PwmOut({})", _0.idx())]
37    /// PWM output of the specified transducer.
38    PwmOut(&'a Transducer),
39    #[debug("Direct({})", _0)]
40    /// High if `true`.
41    Direct(bool),
42}
43
44#[bitfield_struct::bitfield(u64)]
45#[derive(IntoBytes, Immutable)]
46pub(crate) struct DebugValue {
47    #[bits(56)]
48    pub(crate) value: u64,
49    #[bits(8)]
50    pub(crate) tag: u8,
51}
52
53impl From<Option<GPIOOutputType<'_>>> for DebugValue {
54    fn from(ty: Option<GPIOOutputType<'_>>) -> Self {
55        Self::new()
56            .with_value(match &ty {
57                None
58                | Some(GPIOOutputType::BaseSignal)
59                | Some(GPIOOutputType::Thermo)
60                | Some(GPIOOutputType::ForceFan)
61                | Some(GPIOOutputType::Sync)
62                | Some(GPIOOutputType::ModSegment)
63                | Some(GPIOOutputType::StmSegment)
64                | Some(GPIOOutputType::IsStmMode) => 0,
65                Some(GPIOOutputType::PwmOut(tr)) => tr.idx() as _,
66                Some(GPIOOutputType::ModIdx(idx)) => *idx as _,
67                Some(GPIOOutputType::StmIdx(idx)) => *idx as _,
68                Some(GPIOOutputType::SysTimeEq(time)) => ec_time_to_sys_time(time) >> 9,
69                Some(GPIOOutputType::Direct(v)) => *v as _,
70            })
71            .with_tag(match &ty {
72                None => 0x00,
73                Some(GPIOOutputType::BaseSignal) => 0x01,
74                Some(GPIOOutputType::Thermo) => 0x02,
75                Some(GPIOOutputType::ForceFan) => 0x03,
76                Some(GPIOOutputType::Sync) => 0x10,
77                Some(GPIOOutputType::ModSegment) => 0x20,
78                Some(GPIOOutputType::ModIdx(_)) => 0x21,
79                Some(GPIOOutputType::StmSegment) => 0x50,
80                Some(GPIOOutputType::StmIdx(_)) => 0x51,
81                Some(GPIOOutputType::IsStmMode) => 0x52,
82                Some(GPIOOutputType::SysTimeEq(_)) => 0x60,
83                Some(GPIOOutputType::PwmOut(_)) => 0xE0,
84                Some(GPIOOutputType::Direct(_)) => 0xF0,
85            })
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use crate::geometry::Point3;
92
93    use super::*;
94
95    #[test]
96    fn display() {
97        assert_eq!("BaseSignal", format!("{:?}", GPIOOutputType::BaseSignal));
98        assert_eq!("Thermo", format!("{:?}", GPIOOutputType::Thermo));
99        assert_eq!("ForceFan", format!("{:?}", GPIOOutputType::ForceFan));
100        assert_eq!("Sync", format!("{:?}", GPIOOutputType::Sync));
101        assert_eq!("ModSegment", format!("{:?}", GPIOOutputType::ModSegment));
102        assert_eq!("ModIdx(1)", format!("{:?}", GPIOOutputType::ModIdx(1)));
103        assert_eq!("StmSegment", format!("{:?}", GPIOOutputType::StmSegment));
104        assert_eq!("StmIdx(1)", format!("{:?}", GPIOOutputType::StmIdx(1)));
105        assert_eq!("IsStmMode", format!("{:?}", GPIOOutputType::IsStmMode));
106        assert_eq!(
107            "PwmOut(0)",
108            format!(
109                "{:?}",
110                GPIOOutputType::PwmOut(&Transducer::new(Point3::origin()))
111            )
112        );
113        assert_eq!(
114            "Direct(true)",
115            format!("{:?}", GPIOOutputType::Direct(true))
116        );
117    }
118}