avr_tester/
spi.rs

1use crate::*;
2
3/// Provides access to the SPI.
4///
5/// See: [`Spi::read()`] and [`Spi::write()`].
6pub struct Spi<'a> {
7    sim: &'a mut AvrSimulator,
8    id: u8,
9}
10
11impl<'a> Spi<'a> {
12    pub(crate) fn new(sim: &'a mut AvrSimulator, id: u8) -> Self {
13        Self { sim, id }
14    }
15
16    /// Retrieves a value from AVR.
17    ///
18    /// See: [`Readable`].
19    /// See also: [`Self::try_read_byte()`].
20    ///
21    /// # Examples
22    ///
23    /// ```no_run
24    /// # use avr_tester::*;
25    /// # fn avr() -> AvrTester { panic!() }
26    /// #
27    /// let mut avr = avr();
28    ///
29    /// // Retrieves a single byte:
30    /// // (when the input buffer is empty, panics.)
31    /// assert_eq!(72, avr.spi0().read::<u8>());
32    ///
33    /// // Retrieves the entire buffer:
34    /// // (when it's empty, returns an empty vector.)
35    /// assert_eq!(vec![72, 101, 108, 108, 111], avr.spi0().read::<Vec<u8>>());
36    ///
37    /// // Retrieves `n` bytes from the buffer:
38    /// // (when there's not enough bytes, panics.)
39    /// assert_eq!([72, 101, 108, 108, 111], avr.spi0().read::<[u8; 5]>());
40    ///
41    /// // Retrieves the entire input buffer and converts it into string:
42    /// // (when it's empty, returns an empty string.)
43    /// assert_eq!("Hello", avr.spi0().read::<String>());
44    /// ```
45    pub fn read<T>(&mut self) -> T
46    where
47        T: Readable,
48    {
49        T::read(self)
50    }
51
52    /// Transmits a value to AVR.
53    ///
54    /// See: [`Writable`].
55    ///
56    /// # Examples
57    ///
58    /// ```no_run
59    /// # use avr_tester::*;
60    /// # fn avr() -> AvrTester { panic!() }
61    /// #
62    /// let mut avr = avr();
63    ///
64    /// // Transmits a single byte:
65    /// avr.spi0().write(123);
66    ///
67    /// // Transmits many bytes:
68    /// avr.spi0().write([10, 20, 30]);
69    ///
70    /// // Transmits a string:
71    /// avr.spi0().write("Hello!");
72    ///
73    /// // Strings are transmitted as a series of their bytes, so the above is
74    /// // equivalent to:
75    /// avr.spi0().write([72, 101, 108, 108, 111, 33]);
76    /// //                H   e    l    l    o    !
77    /// ```
78    pub fn write<T>(&mut self, value: T)
79    where
80        T: Writable,
81    {
82        value.write(self);
83    }
84}
85
86impl Reader for Spi<'_> {
87    fn read_byte(&mut self) -> u8 {
88        self.try_read_byte().expect(
89            "SPI's buffer is empty - got no more bytes to read; if you're \
90             receiving a large buffer, try running the simulator for a bit \
91             longer so that the simulated AVR has more time to respond",
92        )
93    }
94
95    fn try_read_byte(&mut self) -> Option<u8> {
96        self.sim.read_spi(self.id)
97    }
98}
99
100impl Writer for Spi<'_> {
101    fn write_byte(&mut self, value: u8) {
102        self.sim.write_spi(self.id, value);
103    }
104}
105
106/// Asynchronous equivalent of [`Spi`].
107///
108/// See [`avr_rt()`] for more details.
109pub struct SpiAsync {
110    id: u8,
111}
112
113impl SpiAsync {
114    pub(crate) fn new(id: u8) -> Self {
115        Self { id }
116    }
117
118    /// Asynchronous equivalent of [`Spi::read()`].
119    pub fn read<T>(&self) -> T
120    where
121        T: Readable,
122    {
123        self.with(|spi| spi.read())
124    }
125
126    /// Asynchronous equivalent of [`Spi::write()`].
127    pub fn write<T>(&mut self, value: T)
128    where
129        T: Writable,
130    {
131        self.with(|spi| spi.write(value))
132    }
133
134    fn with<T>(&self, f: impl FnOnce(&mut Spi) -> T) -> T {
135        ComponentRuntime::with(|rt| {
136            let mut spi = Spi::new(rt.sim(), self.id);
137
138            f(&mut spi)
139        })
140    }
141}
142
143impl Reader for SpiAsync {
144    fn read_byte(&mut self) -> u8 {
145        self.with(|spi| spi.read_byte())
146    }
147
148    fn try_read_byte(&mut self) -> Option<u8> {
149        self.with(|spi| spi.try_read_byte())
150    }
151}
152
153impl Writer for SpiAsync {
154    fn write_byte(&mut self, value: u8) {
155        self.with(|spi| spi.write_byte(value))
156    }
157}