diff options
| author | Georges Palauqui <[email protected]> | 2024-10-27 10:23:18 +0100 |
|---|---|---|
| committer | Georges Palauqui <[email protected]> | 2024-11-05 18:54:04 +0100 |
| commit | fb004fb6e2bd1fe23c50bf0faccd9d4a8061e986 (patch) | |
| tree | db51bd25ac775237f43ec59eb2be323b7579269d /examples | |
| parent | 5b075077090ec1436437c82011554649e909c8ee (diff) | |
add second example fo SPI display on RP
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/rp/src/bin/spi_gc9a01.rs | 126 |
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 } | |||
| 45 | smart-leds = "0.4.0" | 45 | smart-leds = "0.4.0" |
| 46 | heapless = "0.8" | 46 | heapless = "0.8" |
| 47 | usbd-hid = "0.8.1" | 47 | usbd-hid = "0.8.1" |
| 48 | rand_core = "0.6.4" | ||
| 48 | 49 | ||
| 49 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } | 50 | embedded-hal-1 = { package = "embedded-hal", version = "1.0" } |
| 50 | embedded-hal-async = "1.0" | 51 | embedded-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 | |||
| 9 | use core::cell::RefCell; | ||
| 10 | |||
| 11 | use defmt::*; | ||
| 12 | use display_interface_spi::SPIInterface; | ||
| 13 | use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig; | ||
| 14 | use embassy_executor::Spawner; | ||
| 15 | use embassy_rp::clocks::RoscRng; | ||
| 16 | use embassy_rp::gpio::{Level, Output}; | ||
| 17 | use embassy_rp::spi; | ||
| 18 | use embassy_rp::spi::{Blocking, Spi}; | ||
| 19 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 20 | use embassy_sync::blocking_mutex::Mutex; | ||
| 21 | use embassy_time::{Delay, Duration, Timer}; | ||
| 22 | use embedded_graphics::image::{Image, ImageRawLE}; | ||
| 23 | use embedded_graphics::pixelcolor::Rgb565; | ||
| 24 | use embedded_graphics::prelude::*; | ||
| 25 | use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; | ||
| 26 | use mipidsi::models::GC9A01; | ||
| 27 | use mipidsi::options::{ColorOrder, ColorInversion}; | ||
| 28 | use mipidsi::Builder; | ||
| 29 | use rand_core::RngCore; | ||
| 30 | use {defmt_rtt as _, panic_probe as _}; | ||
| 31 | |||
| 32 | const DISPLAY_FREQ: u32 = 64_000_000; | ||
| 33 | const LCD_X_RES: i32 = 240; | ||
| 34 | const LCD_Y_RES: i32 = 240; | ||
| 35 | const FERRIS_WIDTH: u32 = 86; | ||
| 36 | const FERRIS_HEIGHT: u32 = 64; | ||
| 37 | |||
| 38 | #[embassy_executor::main] | ||
| 39 | async 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 | } | ||
