aboutsummaryrefslogtreecommitdiff
path: root/examples/rp235x/src/bin/spi_display.rs
diff options
context:
space:
mode:
authorCurly <[email protected]>2025-02-23 07:33:58 -0800
committerCurly <[email protected]>2025-02-23 07:33:58 -0800
commit3932835998802fc3abf7cce4f736e072858ebfd1 (patch)
tree5dd714b99bc74a03556c58809237c88691c293bb /examples/rp235x/src/bin/spi_display.rs
parentc3c67db93e627a4fafe5e1a1123e5cbb4abafe47 (diff)
rename `rp23` (?) folder to `rp235x`; fix `ci.sh` to use `rp235x` folder
Diffstat (limited to 'examples/rp235x/src/bin/spi_display.rs')
-rw-r--r--examples/rp235x/src/bin/spi_display.rs177
1 files changed, 177 insertions, 0 deletions
diff --git a/examples/rp235x/src/bin/spi_display.rs b/examples/rp235x/src/bin/spi_display.rs
new file mode 100644
index 000000000..9c524ab25
--- /dev/null
+++ b/examples/rp235x/src/bin/spi_display.rs
@@ -0,0 +1,177 @@
1//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2350 chip.
2//!
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)
5
6#![no_std]
7#![no_main]
8
9use core::cell::RefCell;
10
11use defmt::*;
12use display_interface_spi::SPIInterface;
13use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig;
14use embassy_executor::Spawner;
15use embassy_rp::gpio::{Level, Output};
16use embassy_rp::spi;
17use embassy_rp::spi::{Blocking, Spi};
18use embassy_sync::blocking_mutex::raw::NoopRawMutex;
19use embassy_sync::blocking_mutex::Mutex;
20use embassy_time::Delay;
21use embedded_graphics::image::{Image, ImageRawLE};
22use embedded_graphics::mono_font::ascii::FONT_10X20;
23use embedded_graphics::mono_font::MonoTextStyle;
24use embedded_graphics::pixelcolor::Rgb565;
25use embedded_graphics::prelude::*;
26use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
27use embedded_graphics::text::Text;
28use mipidsi::models::ST7789;
29use mipidsi::options::{Orientation, Rotation};
30use mipidsi::Builder;
31use {defmt_rtt as _, panic_probe as _};
32
33use crate::touch::Touch;
34
35const DISPLAY_FREQ: u32 = 64_000_000;
36const TOUCH_FREQ: u32 = 200_000;
37
38#[embassy_executor::main]
39async fn main(_spawner: Spawner) {
40 let p = embassy_rp::init(Default::default());
41 info!("Hello World!");
42
43 let bl = p.PIN_13;
44 let rst = p.PIN_15;
45 let display_cs = p.PIN_9;
46 let dcx = p.PIN_8;
47 let miso = p.PIN_12;
48 let mosi = p.PIN_11;
49 let clk = p.PIN_10;
50 let touch_cs = p.PIN_16;
51 //let touch_irq = p.PIN_17;
52
53 // create SPI
54 let mut display_config = spi::Config::default();
55 display_config.frequency = DISPLAY_FREQ;
56 display_config.phase = spi::Phase::CaptureOnSecondTransition;
57 display_config.polarity = spi::Polarity::IdleHigh;
58 let mut touch_config = spi::Config::default();
59 touch_config.frequency = TOUCH_FREQ;
60 touch_config.phase = spi::Phase::CaptureOnSecondTransition;
61 touch_config.polarity = spi::Polarity::IdleHigh;
62
63 let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, touch_config.clone());
64 let spi_bus: Mutex<NoopRawMutex, _> = Mutex::new(RefCell::new(spi));
65
66 let display_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(display_cs, Level::High), display_config);
67 let touch_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(touch_cs, Level::High), touch_config);
68
69 let mut touch = Touch::new(touch_spi);
70
71 let dcx = Output::new(dcx, Level::Low);
72 let rst = Output::new(rst, Level::Low);
73 // dcx: 0 = command, 1 = data
74
75 // Enable LCD backlight
76 let _bl = Output::new(bl, Level::High);
77
78 // display interface abstraction from SPI and DC
79 let di = SPIInterface::new(display_spi, dcx);
80
81 // Define the display from the display interface and initialize it
82 let mut display = Builder::new(ST7789, di)
83 .display_size(240, 320)
84 .reset_pin(rst)
85 .orientation(Orientation::new().rotate(Rotation::Deg90))
86 .init(&mut Delay)
87 .unwrap();
88 display.clear(Rgb565::BLACK).unwrap();
89
90 let raw_image_data = ImageRawLE::new(include_bytes!("../../assets/ferris.raw"), 86);
91 let ferris = Image::new(&raw_image_data, Point::new(34, 68));
92
93 // Display the image
94 ferris.draw(&mut display).unwrap();
95
96 let style = MonoTextStyle::new(&FONT_10X20, Rgb565::GREEN);
97 Text::new(
98 "Hello embedded_graphics \n + embassy + RP2040!",
99 Point::new(20, 200),
100 style,
101 )
102 .draw(&mut display)
103 .unwrap();
104
105 loop {
106 if let Some((x, y)) = touch.read() {
107 let style = PrimitiveStyleBuilder::new().fill_color(Rgb565::BLUE).build();
108
109 Rectangle::new(Point::new(x - 1, y - 1), Size::new(3, 3))
110 .into_styled(style)
111 .draw(&mut display)
112 .unwrap();
113 }
114 }
115}
116
117/// Driver for the XPT2046 resistive touchscreen sensor
118mod touch {
119 use embedded_hal_1::spi::{Operation, SpiDevice};
120
121 struct Calibration {
122 x1: i32,
123 x2: i32,
124 y1: i32,
125 y2: i32,
126 sx: i32,
127 sy: i32,
128 }
129
130 const CALIBRATION: Calibration = Calibration {
131 x1: 3880,
132 x2: 340,
133 y1: 262,
134 y2: 3850,
135 sx: 320,
136 sy: 240,
137 };
138
139 pub struct Touch<SPI: SpiDevice> {
140 spi: SPI,
141 }
142
143 impl<SPI> Touch<SPI>
144 where
145 SPI: SpiDevice,
146 {
147 pub fn new(spi: SPI) -> Self {
148 Self { spi }
149 }
150
151 pub fn read(&mut self) -> Option<(i32, i32)> {
152 let mut x = [0; 2];
153 let mut y = [0; 2];
154 self.spi
155 .transaction(&mut [
156 Operation::Write(&[0x90]),
157 Operation::Read(&mut x),
158 Operation::Write(&[0xd0]),
159 Operation::Read(&mut y),
160 ])
161 .unwrap();
162
163 let x = (u16::from_be_bytes(x) >> 3) as i32;
164 let y = (u16::from_be_bytes(y) >> 3) as i32;
165
166 let cal = &CALIBRATION;
167
168 let x = ((x - cal.x1) * cal.sx / (cal.x2 - cal.x1)).clamp(0, cal.sx);
169 let y = ((y - cal.y1) * cal.sy / (cal.y2 - cal.y1)).clamp(0, cal.sy);
170 if x == 0 && y == 0 {
171 None
172 } else {
173 Some((x, y))
174 }
175 }
176 }
177}