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 None,
16 BaseSignal,
18 Thermo,
20 ForceFan,
22 Sync,
24 ModSegment,
26 #[debug("ModIdx({})", _0)]
27 ModIdx(u16),
29 StmSegment,
31 #[debug("StmIdx({})", _0)]
32 StmIdx(u16),
34 IsStmMode,
36 SysTimeEq(DcSysTime),
38 #[debug("PwmOut({})", _0.idx())]
39 PwmOut(&'a Transducer),
41 #[debug("Direct({})", _0)]
42 Direct(bool),
44}
45
46#[bitfield_struct::bitfield(u64)]
47#[derive(IntoBytes, Immutable)]
48pub(crate) struct DebugValue {
49 #[bits(56)]
50 pub(crate) value: u64,
51 #[bits(8)]
52 pub(crate) tag: u8,
53}
54
55impl From<GPIOOutputType<'_>> for DebugValue {
56 fn from(ty: GPIOOutputType<'_>) -> Self {
57 Self::new()
58 .with_value(match &ty {
59 GPIOOutputType::None
60 | GPIOOutputType::BaseSignal
61 | GPIOOutputType::Thermo
62 | GPIOOutputType::ForceFan
63 | GPIOOutputType::Sync
64 | GPIOOutputType::ModSegment
65 | GPIOOutputType::StmSegment
66 | GPIOOutputType::IsStmMode => 0,
67 GPIOOutputType::PwmOut(tr) => tr.idx() as _,
68 GPIOOutputType::ModIdx(idx) => *idx as _,
69 GPIOOutputType::StmIdx(idx) => *idx as _,
70 GPIOOutputType::SysTimeEq(time) => ec_time_to_sys_time(time) >> 9,
71 GPIOOutputType::Direct(v) => *v as _,
72 })
73 .with_tag(match &ty {
74 GPIOOutputType::None => 0x00,
75 GPIOOutputType::BaseSignal => 0x01,
76 GPIOOutputType::Thermo => 0x02,
77 GPIOOutputType::ForceFan => 0x03,
78 GPIOOutputType::Sync => 0x10,
79 GPIOOutputType::ModSegment => 0x20,
80 GPIOOutputType::ModIdx(_) => 0x21,
81 GPIOOutputType::StmSegment => 0x50,
82 GPIOOutputType::StmIdx(_) => 0x51,
83 GPIOOutputType::IsStmMode => 0x52,
84 GPIOOutputType::SysTimeEq(_) => 0x60,
85 GPIOOutputType::PwmOut(_) => 0xE0,
86 GPIOOutputType::Direct(_) => 0xF0,
87 })
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use crate::geometry::Point3;
94
95 use super::*;
96
97 #[test]
98 fn display() {
99 assert_eq!("None", format!("{:?}", GPIOOutputType::None));
100 assert_eq!("BaseSignal", format!("{:?}", GPIOOutputType::BaseSignal));
101 assert_eq!("Thermo", format!("{:?}", GPIOOutputType::Thermo));
102 assert_eq!("ForceFan", format!("{:?}", GPIOOutputType::ForceFan));
103 assert_eq!("Sync", format!("{:?}", GPIOOutputType::Sync));
104 assert_eq!("ModSegment", format!("{:?}", GPIOOutputType::ModSegment));
105 assert_eq!("ModIdx(1)", format!("{:?}", GPIOOutputType::ModIdx(1)));
106 assert_eq!("StmSegment", format!("{:?}", GPIOOutputType::StmSegment));
107 assert_eq!("StmIdx(1)", format!("{:?}", GPIOOutputType::StmIdx(1)));
108 assert_eq!("IsStmMode", format!("{:?}", GPIOOutputType::IsStmMode));
109 assert_eq!(
110 "PwmOut(0)",
111 format!(
112 "{:?}",
113 GPIOOutputType::PwmOut(&Transducer::new(Point3::origin()))
114 )
115 );
116 assert_eq!(
117 "Direct(true)",
118 format!("{:?}", GPIOOutputType::Direct(true))
119 );
120 }
121}