aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Palauqui <[email protected]>2024-10-27 09:53:00 +0100
committerGeorges Palauqui <[email protected]>2024-10-27 09:53:00 +0100
commit7733b99e0960d41d7b7d88f4d94adb6b21eb17b4 (patch)
tree60dae4dfed04902f1565669250ffb103eda23b50
parent66205fdd859b4c8607d0b6be9e4fcb27e8096493 (diff)
update spi_display example for rp23
-rw-r--r--examples/rp23/Cargo.toml8
-rw-r--r--examples/rp23/src/bin/spi_display.rs163
2 files changed, 18 insertions, 153 deletions
diff --git a/examples/rp23/Cargo.toml b/examples/rp23/Cargo.toml
index 5527a1e0a..eec12a9ab 100644
--- a/examples/rp23/Cargo.toml
+++ b/examples/rp23/Cargo.toml
@@ -38,10 +38,10 @@ cortex-m = { version = "0.7.6", features = ["inline-asm"] }
38cortex-m-rt = "0.7.0" 38cortex-m-rt = "0.7.0"
39critical-section = "1.1" 39critical-section = "1.1"
40panic-probe = { version = "0.3", features = ["print-defmt"] } 40panic-probe = { version = "0.3", features = ["print-defmt"] }
41display-interface-spi = "0.4.1" 41display-interface-spi = "0.5.0"
42embedded-graphics = "0.7.1" 42embedded-graphics = "0.8.1"
43st7789 = "0.6.1" 43mipidsi = "0.8.0"
44display-interface = "0.4.1" 44display-interface = "0.5.0"
45byte-slice-cast = { version = "1.2.0", default-features = false } 45byte-slice-cast = { version = "1.2.0", default-features = false }
46smart-leds = "0.3.0" 46smart-leds = "0.3.0"
47heapless = "0.8" 47heapless = "0.8"
diff --git a/examples/rp23/src/bin/spi_display.rs b/examples/rp23/src/bin/spi_display.rs
index 195db5a97..6b7c0781f 100644
--- a/examples/rp23/src/bin/spi_display.rs
+++ b/examples/rp23/src/bin/spi_display.rs
@@ -1,4 +1,4 @@
1//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. 1//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2350 chip.
2//! 2//!
3//! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch 3//! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch
4//! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8) 4//! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8)
@@ -9,6 +9,7 @@
9use core::cell::RefCell; 9use core::cell::RefCell;
10 10
11use defmt::*; 11use defmt::*;
12use display_interface_spi::SPIInterface;
12use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig; 13use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig;
13use embassy_executor::Spawner; 14use embassy_executor::Spawner;
14use embassy_rp::block::ImageDef; 15use embassy_rp::block::ImageDef;
@@ -25,14 +26,15 @@ use embedded_graphics::pixelcolor::Rgb565;
25use embedded_graphics::prelude::*; 26use embedded_graphics::prelude::*;
26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; 27use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
27use embedded_graphics::text::Text; 28use embedded_graphics::text::Text;
28use st7789::{Orientation, ST7789}; 29use mipidsi::models::ST7789;
30use mipidsi::options::{Orientation, Rotation};
31use mipidsi::Builder;
29use {defmt_rtt as _, panic_probe as _}; 32use {defmt_rtt as _, panic_probe as _};
30 33
31#[link_section = ".start_block"] 34#[link_section = ".start_block"]
32#[used] 35#[used]
33pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); 36pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe();
34 37
35use crate::my_display_interface::SPIDeviceInterface;
36use crate::touch::Touch; 38use crate::touch::Touch;
37 39
38const DISPLAY_FREQ: u32 = 64_000_000; 40const DISPLAY_FREQ: u32 = 64_000_000;
@@ -79,17 +81,15 @@ async fn main(_spawner: Spawner) {
79 let _bl = Output::new(bl, Level::High); 81 let _bl = Output::new(bl, Level::High);
80 82
81 // display interface abstraction from SPI and DC 83 // display interface abstraction from SPI and DC
82 let di = SPIDeviceInterface::new(display_spi, dcx); 84 let di = SPIInterface::new(display_spi, dcx);
83 85
84 // create driver 86 // Define the display from the display interface and initialize it
85 let mut display = ST7789::new(di, rst, 240, 320); 87 let mut display = Builder::new(ST7789, di)
86 88 .display_size(240, 320)
87 // initialize 89 .reset_pin(rst)
88 display.init(&mut Delay).unwrap(); 90 .orientation(Orientation::new().rotate(Rotation::Deg90))
89 91 .init(&mut Delay)
90 // set default orientation 92 .unwrap();
91 display.set_orientation(Orientation::Landscape).unwrap();
92
93 display.clear(Rgb565::BLACK).unwrap(); 93 display.clear(Rgb565::BLACK).unwrap();
94 94
95 let raw_image_data = ImageRawLE::new(include_bytes!("../../assets/ferris.raw"), 86); 95 let raw_image_data = ImageRawLE::new(include_bytes!("../../assets/ferris.raw"), 86);
@@ -180,138 +180,3 @@ mod touch {
180 } 180 }
181 } 181 }
182} 182}
183
184mod my_display_interface {
185 use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
186 use embedded_hal_1::digital::OutputPin;
187 use embedded_hal_1::spi::SpiDevice;
188
189 /// SPI display interface.
190 ///
191 /// This combines the SPI peripheral and a data/command pin
192 pub struct SPIDeviceInterface<SPI, DC> {
193 spi: SPI,
194 dc: DC,
195 }
196
197 impl<SPI, DC> SPIDeviceInterface<SPI, DC>
198 where
199 SPI: SpiDevice,
200 DC: OutputPin,
201 {
202 /// Create new SPI interface for communciation with a display driver
203 pub fn new(spi: SPI, dc: DC) -> Self {
204 Self { spi, dc }
205 }
206 }
207
208 impl<SPI, DC> WriteOnlyDataCommand for SPIDeviceInterface<SPI, DC>
209 where
210 SPI: SpiDevice,
211 DC: OutputPin,
212 {
213 fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> {
214 // 1 = data, 0 = command
215 self.dc.set_low().map_err(|_| DisplayError::DCError)?;
216
217 send_u8(&mut self.spi, cmds).map_err(|_| DisplayError::BusWriteError)?;
218 Ok(())
219 }
220
221 fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
222 // 1 = data, 0 = command
223 self.dc.set_high().map_err(|_| DisplayError::DCError)?;
224
225 send_u8(&mut self.spi, buf).map_err(|_| DisplayError::BusWriteError)?;
226 Ok(())
227 }
228 }
229
230 fn send_u8<T: SpiDevice>(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> {
231 match words {
232 DataFormat::U8(slice) => spi.write(slice),
233 DataFormat::U16(slice) => {
234 use byte_slice_cast::*;
235 spi.write(slice.as_byte_slice())
236 }
237 DataFormat::U16LE(slice) => {
238 use byte_slice_cast::*;
239 for v in slice.as_mut() {
240 *v = v.to_le();
241 }
242 spi.write(slice.as_byte_slice())
243 }
244 DataFormat::U16BE(slice) => {
245 use byte_slice_cast::*;
246 for v in slice.as_mut() {
247 *v = v.to_be();
248 }
249 spi.write(slice.as_byte_slice())
250 }
251 DataFormat::U8Iter(iter) => {
252 let mut buf = [0; 32];
253 let mut i = 0;
254
255 for v in iter.into_iter() {
256 buf[i] = v;
257 i += 1;
258
259 if i == buf.len() {
260 spi.write(&buf)?;
261 i = 0;
262 }
263 }
264
265 if i > 0 {
266 spi.write(&buf[..i])?;
267 }
268
269 Ok(())
270 }
271 DataFormat::U16LEIter(iter) => {
272 use byte_slice_cast::*;
273 let mut buf = [0; 32];
274 let mut i = 0;
275
276 for v in iter.map(u16::to_le) {
277 buf[i] = v;
278 i += 1;
279
280 if i == buf.len() {
281 spi.write(&buf.as_byte_slice())?;
282 i = 0;
283 }
284 }
285
286 if i > 0 {
287 spi.write(&buf[..i].as_byte_slice())?;
288 }
289
290 Ok(())
291 }
292 DataFormat::U16BEIter(iter) => {
293 use byte_slice_cast::*;
294 let mut buf = [0; 64];
295 let mut i = 0;
296 let len = buf.len();
297
298 for v in iter.map(u16::to_be) {
299 buf[i] = v;
300 i += 1;
301
302 if i == len {
303 spi.write(&buf.as_byte_slice())?;
304 i = 0;
305 }
306 }
307
308 if i > 0 {
309 spi.write(&buf[..i].as_byte_slice())?;
310 }
311
312 Ok(())
313 }
314 _ => unimplemented!(),
315 }
316 }
317}