display_interface_spi/
asynch.rs

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