Skip to main content

sky_ili9341/
interface.rs

1/// Hardware interface trait and blocking SPI implementation.
2
3use crate::error::Error;
4
5/// Abstraction over the display communication bus.
6///
7/// Implementations handle the DC pin toggling and byte-level transport.
8pub trait Interface {
9    /// The underlying bus error type.
10    type Error;
11
12    /// Send a command byte followed by optional parameter bytes.
13    fn send_command(&mut self, command: u8, args: &[u8]) -> Result<(), Error<Self::Error>>;
14
15    /// Send pixel data as a contiguous byte slice.
16    ///
17    /// `MemoryWrite` (0x2C) must already have been sent before calling this.
18    fn send_data(&mut self, data: &[u8]) -> Result<(), Error<Self::Error>>;
19}
20
21/// Blanket impl for mutable references.
22impl<T: Interface> Interface for &mut T {
23    type Error = T::Error;
24
25    #[inline]
26    fn send_command(&mut self, command: u8, args: &[u8]) -> Result<(), Error<Self::Error>> {
27        T::send_command(self, command, args)
28    }
29
30    #[inline]
31    fn send_data(&mut self, data: &[u8]) -> Result<(), Error<Self::Error>> {
32        T::send_data(self, data)
33    }
34}
35
36/// Blocking SPI interface using `embedded-hal` 1.0.
37///
38/// `SPI` must implement `embedded_hal::spi::SpiDevice` (manages CS automatically).
39/// `DC` is the data/command selection pin.
40pub struct SpiInterface<SPI, DC> {
41    spi: SPI,
42    dc: DC,
43}
44
45impl<SPI, DC> SpiInterface<SPI, DC> {
46    /// Create a new SPI interface.
47    pub fn new(spi: SPI, dc: DC) -> Self {
48        Self { spi, dc }
49    }
50
51    /// Release the SPI bus and DC pin.
52    pub fn release(self) -> (SPI, DC) {
53        (self.spi, self.dc)
54    }
55}
56
57impl<SPI, DC> Interface for SpiInterface<SPI, DC>
58where
59    SPI: embedded_hal::spi::SpiDevice,
60    DC: embedded_hal::digital::OutputPin,
61{
62    type Error = SPI::Error;
63
64    fn send_command(&mut self, command: u8, args: &[u8]) -> Result<(), Error<Self::Error>> {
65        // DC low = command
66        self.dc.set_low().map_err(|_| Error::DcPin)?;
67        self.spi.write(&[command]).map_err(Error::Bus)?;
68
69        if !args.is_empty() {
70            // DC high = data (parameters)
71            self.dc.set_high().map_err(|_| Error::DcPin)?;
72            self.spi.write(args).map_err(Error::Bus)?;
73        }
74
75        Ok(())
76    }
77
78    fn send_data(&mut self, data: &[u8]) -> Result<(), Error<Self::Error>> {
79        // DC high = data
80        self.dc.set_high().map_err(|_| Error::DcPin)?;
81        self.spi.write(data).map_err(Error::Bus)?;
82        Ok(())
83    }
84}