autd3_driver/firmware/operation/
cpu_gpio_out.rs

1use std::{convert::Infallible, mem::size_of};
2
3use crate::{
4    firmware::operation::{Operation, TypeTag},
5    geometry::Device,
6};
7
8use zerocopy::{Immutable, IntoBytes};
9
10#[repr(C, align(2))]
11#[derive(IntoBytes, Immutable)]
12struct CpuGPIOOut {
13    tag: TypeTag,
14    pa_podr: u8,
15}
16
17pub struct CpuGPIOOutOp {
18    is_done: bool,
19    pa5: bool,
20    pa7: bool,
21}
22
23impl CpuGPIOOutOp {
24    pub(crate) const fn new(pa5: bool, pa7: bool) -> Self {
25        Self {
26            is_done: false,
27            pa5,
28            pa7,
29        }
30    }
31}
32
33impl Operation for CpuGPIOOutOp {
34    type Error = Infallible;
35
36    fn pack(&mut self, _: &Device, tx: &mut [u8]) -> Result<usize, Self::Error> {
37        super::write_to_tx(
38            tx,
39            CpuGPIOOut {
40                tag: TypeTag::CpuGPIOOut,
41                pa_podr: ((self.pa5 as u8) << 5) | ((self.pa7 as u8) << 7),
42            },
43        );
44
45        self.is_done = true;
46        Ok(size_of::<CpuGPIOOut>())
47    }
48
49    fn required_size(&self, _: &Device) -> usize {
50        size_of::<CpuGPIOOut>()
51    }
52
53    fn is_done(&self) -> bool {
54        self.is_done
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use crate::firmware::operation::tests::create_device;
61
62    use super::*;
63
64    const NUM_TRANS_IN_UNIT: u8 = 249;
65
66    #[rstest::rstest]
67    #[test]
68    #[case(0b10100000, true, true)]
69    #[case(0b00100000, true, false)]
70    #[case(0b10000000, false, true)]
71    #[case(0b00000000, false, false)]
72    fn debug_op(#[case] expect: u8, #[case] pa5: bool, #[case] pa7: bool) {
73        const FRAME_SIZE: usize = size_of::<CpuGPIOOut>();
74
75        let device = create_device(NUM_TRANS_IN_UNIT);
76        let mut tx = vec![0x00u8; FRAME_SIZE];
77
78        let mut op = CpuGPIOOutOp::new(pa5, pa7);
79
80        assert_eq!(size_of::<CpuGPIOOut>(), op.required_size(&device));
81        assert_eq!(Ok(size_of::<CpuGPIOOut>()), op.pack(&device, &mut tx));
82        assert!(op.is_done());
83        assert_eq!(TypeTag::CpuGPIOOut as u8, tx[0]);
84        assert_eq!(expect, tx[1]);
85    }
86}