autd3_driver/firmware/fpga/
gpio_out.rs1use crate::{ethercat::DcSysTime, geometry::Transducer};
2
3use derive_more::Debug;
4use zerocopy::{Immutable, IntoBytes};
5
6use super::ec_time_to_sys_time;
7
8#[non_exhaustive]
12#[derive(Clone, Debug)]
13pub enum GPIOOutputType<'a> {
14 BaseSignal,
16 Thermo,
18 ForceFan,
20 Sync,
22 ModSegment,
24 #[debug("ModIdx({})", _0)]
25 ModIdx(u16),
27 StmSegment,
29 #[debug("StmIdx({})", _0)]
30 StmIdx(u16),
32 IsStmMode,
34 SysTimeEq(DcSysTime),
36 #[debug("PwmOut({})", _0.idx())]
37 PwmOut(&'a Transducer),
39 #[debug("Direct({})", _0)]
40 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}