display_interface_spi/
lib.rs

1//! Generic SPI interface for display drivers
2
3#![no_std]
4
5mod asynch;
6
7use byte_slice_cast::*;
8use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
9use embedded_hal::{digital::OutputPin, spi::SpiDevice};
10
11type Result = core::result::Result<(), DisplayError>;
12
13pub(crate) const BUFFER_SIZE: usize = 64;
14
15fn send_u8<SPI>(spi: &mut SPI, words: DataFormat<'_>) -> Result
16where
17    SPI: SpiDevice,
18{
19    match words {
20        DataFormat::U8(slice) => spi.write(slice).map_err(|_| DisplayError::BusWriteError),
21        DataFormat::U16(slice) => spi
22            .write(slice.as_byte_slice())
23            .map_err(|_| DisplayError::BusWriteError),
24        DataFormat::U16LE(slice) => {
25            for v in slice.as_mut() {
26                *v = v.to_le();
27            }
28            spi.write(slice.as_byte_slice())
29                .map_err(|_| DisplayError::BusWriteError)
30        }
31        DataFormat::U16BE(slice) => {
32            for v in slice.as_mut() {
33                *v = v.to_be();
34            }
35            spi.write(slice.as_byte_slice())
36                .map_err(|_| DisplayError::BusWriteError)
37        }
38        DataFormat::U8Iter(iter) => {
39            let mut buf = [0; BUFFER_SIZE];
40            let mut i = 0;
41
42            for v in iter.into_iter() {
43                buf[i] = v;
44                i += 1;
45
46                if i == buf.len() {
47                    spi.write(&buf).map_err(|_| DisplayError::BusWriteError)?;
48                    i = 0;
49                }
50            }
51
52            if i > 0 {
53                spi.write(&buf[..i])
54                    .map_err(|_| DisplayError::BusWriteError)?;
55            }
56
57            Ok(())
58        }
59        DataFormat::U16LEIter(iter) => {
60            let mut buf = [0; BUFFER_SIZE];
61            let mut i = 0;
62
63            for v in iter.map(u16::to_le) {
64                buf[i] = v;
65                i += 1;
66
67                if i == buf.len() {
68                    spi.write(buf.as_byte_slice())
69                        .map_err(|_| DisplayError::BusWriteError)?;
70                    i = 0;
71                }
72            }
73
74            if i > 0 {
75                spi.write(buf[..i].as_byte_slice())
76                    .map_err(|_| DisplayError::BusWriteError)?;
77            }
78
79            Ok(())
80        }
81        DataFormat::U16BEIter(iter) => {
82            let mut buf = [0; BUFFER_SIZE];
83            let mut i = 0;
84            let len = buf.len();
85
86            for v in iter.map(u16::to_be) {
87                buf[i] = v;
88                i += 1;
89
90                if i == len {
91                    spi.write(buf.as_byte_slice())
92                        .map_err(|_| DisplayError::BusWriteError)?;
93                    i = 0;
94                }
95            }
96
97            if i > 0 {
98                spi.write(buf[..i].as_byte_slice())
99                    .map_err(|_| DisplayError::BusWriteError)?;
100            }
101
102            Ok(())
103        }
104        _ => Err(DisplayError::DataFormatNotImplemented),
105    }
106}
107
108/// SPI display interface.
109///
110/// This combines the SPI peripheral and a data/command pin
111pub struct SPIInterface<SPI, DC> {
112    spi: SPI,
113    dc: DC,
114}
115
116impl<SPI, DC> SPIInterface<SPI, DC> {
117    /// Create new SPI interface for communication with a display driver
118    pub fn new(spi: SPI, dc: DC) -> Self {
119        Self { spi, dc }
120    }
121
122    /// Consume the display interface and return
123    /// the underlying peripheral driver and GPIO pins used by it
124    pub fn release(self) -> (SPI, DC) {
125        (self.spi, self.dc)
126    }
127}
128
129impl<SPI, DC> WriteOnlyDataCommand for SPIInterface<SPI, DC>
130where
131    SPI: SpiDevice,
132    DC: OutputPin,
133{
134    fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result {
135        // 1 = data, 0 = command
136        self.dc.set_low().map_err(|_| DisplayError::DCError)?;
137
138        // Send words over SPI
139        send_u8(&mut self.spi, cmds)
140    }
141
142    fn send_data(&mut self, buf: DataFormat<'_>) -> Result {
143        // 1 = data, 0 = command
144        self.dc.set_high().map_err(|_| DisplayError::DCError)?;
145
146        // Send words over SPI
147        send_u8(&mut self.spi, buf)
148    }
149}