aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Palauqui <[email protected]>2024-10-27 10:23:18 +0100
committerGeorges Palauqui <[email protected]>2024-11-05 18:54:04 +0100
commitfb004fb6e2bd1fe23c50bf0faccd9d4a8061e986 (patch)
treedb51bd25ac775237f43ec59eb2be323b7579269d
parent5b075077090ec1436437c82011554649e909c8ee (diff)
add second example fo SPI display on RP
-rw-r--r--examples/rp/Cargo.toml1
-rw-r--r--examples/rp/src/bin/spi_gc9a01.rs126
2 files changed, 127 insertions, 0 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index b55b20c63..901355aeb 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -45,6 +45,7 @@ byte-slice-cast = { version = "1.2.0", default-features = false }
45smart-leds = "0.4.0" 45smart-leds = "0.4.0"
46heapless = "0.8" 46heapless = "0.8"
47usbd-hid = "0.8.1" 47usbd-hid = "0.8.1"
48rand_core = "0.6.4"
48 49
49embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 50embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
50embedded-hal-async = "1.0" 51embedded-hal-async = "1.0"
diff --git a/examples/rp/src/bin/spi_gc9a01.rs b/examples/rp/src/bin/spi_gc9a01.rs
new file mode 100644
index 000000000..d1cf23e16
--- /dev/null
+++ b/examples/rp/src/bin/spi_gc9a01.rs
@@ -0,0 +1,126 @@
1//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip.
2//!
3//! Example written for a display using the GC9A01 chip. Possibly the Waveshare RP2040-LCD-1.28
4//! (https://www.waveshare.com/wiki/RP2040-LCD-1.28)
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::clocks::RoscRng;
16use embassy_rp::gpio::{Level, Output};
17use embassy_rp::spi;
18use embassy_rp::spi::{Blocking, Spi};
19use embassy_sync::blocking_mutex::raw::NoopRawMutex;
20use embassy_sync::blocking_mutex::Mutex;
21use embassy_time::{Delay, Duration, Timer};
22use embedded_graphics::image::{Image, ImageRawLE};
23use embedded_graphics::pixelcolor::Rgb565;
24use embedded_graphics::prelude::*;
25use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle};
26use mipidsi::models::GC9A01;
27use mipidsi::options::{ColorOrder, ColorInversion};
28use mipidsi::Builder;
29use rand_core::RngCore;
30use {defmt_rtt as _, panic_probe as _};
31
32const DISPLAY_FREQ: u32 = 64_000_000;
33const LCD_X_RES: i32 = 240;
34const LCD_Y_RES: i32 = 240;
35const FERRIS_WIDTH: u32 = 86;
36const FERRIS_HEIGHT: u32 = 64;
37
38#[embassy_executor::main]
39async fn main(_spawner: Spawner) {
40 let p = embassy_rp::init(Default::default());
41 let mut rng = RoscRng;
42
43 info!("Hello World!");
44
45 let bl = p.PIN_25;
46 let rst = p.PIN_12;
47 let display_cs = p.PIN_9;
48 let dcx = p.PIN_8;
49 let mosi = p.PIN_11;
50 let clk = p.PIN_10;
51
52 // create SPI
53 let mut display_config = spi::Config::default();
54 display_config.frequency = DISPLAY_FREQ;
55 display_config.phase = spi::Phase::CaptureOnSecondTransition;
56 display_config.polarity = spi::Polarity::IdleHigh;
57
58 let spi: Spi<'_, _, Blocking> = Spi::new_blocking_txonly(p.SPI1, clk, mosi, display_config.clone());
59 let spi_bus: Mutex<NoopRawMutex, _> = Mutex::new(RefCell::new(spi));
60
61 let display_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(display_cs, Level::High), display_config);
62 let dcx = Output::new(dcx, Level::Low);
63 let rst = Output::new(rst, Level::Low);
64 // dcx: 0 = command, 1 = data
65
66 // Enable LCD backlight
67 let _bl = Output::new(bl, Level::High);
68
69 // display interface abstraction from SPI and DC
70 let di = SPIInterface::new(display_spi, dcx);
71
72 // Define the display from the display interface and initialize it
73 let mut display = Builder::new(GC9A01, di)
74 .display_size(240, 240)
75 .reset_pin(rst)
76 .color_order(ColorOrder::Bgr)
77 .invert_colors(ColorInversion::Inverted)
78 .init(&mut Delay)
79 .unwrap();
80 display.clear(Rgb565::BLACK).unwrap();
81
82 let raw_image_data = ImageRawLE::new(include_bytes!("../../assets/ferris.raw"), FERRIS_WIDTH);
83 let mut ferris = Image::new(&raw_image_data, Point::zero());
84
85 let r = rng.next_u32();
86 let mut delta = Point {
87 x: ((r % 10) + 5) as i32,
88 y: (((r >> 8) % 10) + 5) as i32,
89 };
90 loop {
91 // Move Ferris
92 let bb = ferris.bounding_box();
93 let tl = bb.top_left;
94 let br = bb.bottom_right().unwrap();
95 if tl.x < 0 || br.x > LCD_X_RES {
96 delta.x = -delta.x;
97 }
98 if tl.y < 0 || br.y > LCD_Y_RES {
99 delta.y = -delta.y;
100 }
101
102 // Erase ghosting
103 let style = PrimitiveStyleBuilder::new().fill_color(Rgb565::BLACK).build();
104 let mut off = Point { x: 0, y: 0 };
105 if delta.x < 0 {
106 off.x = FERRIS_WIDTH as i32;
107 }
108 Rectangle::new(tl + off, Size::new(delta.x as u32, FERRIS_HEIGHT))
109 .into_styled(style)
110 .draw(&mut display)
111 .unwrap();
112 off = Point { x: 0, y: 0 };
113 if delta.y < 0 {
114 off.y = FERRIS_HEIGHT as i32;
115 }
116 Rectangle::new(tl + off, Size::new(FERRIS_WIDTH, delta.y as u32))
117 .into_styled(style)
118 .draw(&mut display)
119 .unwrap();
120 // Translate Ferris
121 ferris.translate_mut(delta);
122 // Display the image
123 ferris.draw(&mut display).unwrap();
124 Timer::after(Duration::from_millis(50)).await;
125 }
126}