autd3_driver/firmware/operation/
cpu_gpio_out.rs1use 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}