From 65ad7bab489db0223f58ed85e4990498388edaea Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Wed, 2 Jul 2025 20:15:21 -0600 Subject: [PATCH] WIP --- Cargo.lock | 22 +++++++- Cargo.toml | 5 +- src/display.rs | 140 ++++++++++++++++++------------------------------- src/main.rs | 29 +++++----- 4 files changed, 91 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe98260..0b6773f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1357,8 +1357,10 @@ dependencies = [ "embedded-sdmmc", "panic-probe", "portable-atomic", + "spin", "st7365p-lcd", "static_cell", + "talc", "trouble-host", ] @@ -1727,13 +1729,22 @@ dependencies = [ "rgb", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + [[package]] name = "st7365p-lcd" version = "0.10.0" -source = "git+https://github.com/legitcamper/st7365p-lcd-rs#d751e8d30f1a3f964ffe05e4bb16f82112fbefce" dependencies = [ "embedded-graphics-core", "embedded-hal 1.0.0", + "embedded-hal-async", "nb 1.1.0", ] @@ -1792,6 +1803,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "talc" +version = "4.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ae828aa394de34c7de08f522d1b86bd1c182c668d27da69caadda00590f26d" +dependencies = [ + "lock_api", +] + [[package]] name = "term" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index 5a9425d..7595054 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,10 @@ defmt-rtt = "0.4.2" embedded-graphics = { version = "0.8.1" } embedded-sdmmc = { git = "https://github.com/Be-ing/embedded-sdmmc-rs", branch = "bisync", default-features = false } -st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs" } +# st7365p-lcd = { git = "https://github.com/legitcamper/st7365p-lcd-rs" } +st7365p-lcd = { path = "../ST7365P-lcd-rs" } static_cell = "2.1.1" bitflags = "2.9.1" +talc = "4.4.3" +spin = "0.10.0" diff --git a/src/display.rs b/src/display.rs index fe3f2b0..4a3ec11 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,113 +1,73 @@ +use defmt::info; use embassy_rp::{ gpio::{Level, Output}, peripherals::{PIN_13, PIN_14, PIN_15, SPI1}, - spi::{Blocking, Spi}, + spi::{Async, Spi}, }; use embassy_time::{Delay, Timer}; use embedded_graphics::{ - Drawable, Pixel, - pixelcolor::{Rgb565, raw::RawU16}, - prelude::{DrawTarget, OriginDimensions, Point, Primitive, RawData, RgbColor, Size}, - primitives::{PrimitiveStyle, Rectangle}, + Drawable, + mono_font::{ + MonoFont, MonoTextStyle, + ascii::{FONT_6X9, FONT_10X20}, + }, + pixelcolor::Rgb565, + prelude::{Point, RgbColor, WebColors}, + text::{Baseline, Text, TextStyle}, }; use embedded_hal_bus::spi::ExclusiveDevice; -use st7365p_lcd::{Orientation, ST7365P}; +use st7365p_lcd::{FrameBuffer, ST7365P}; + +type SPI = Spi<'static, SPI1, Async>; + +type FRAMEBUFFER = FrameBuffer< + SCREEN_WIDTH, + SCREEN_HEIGHT, + ExclusiveDevice, Output<'static>, Delay>, + Output<'static>, + Output<'static>, +>; + +const SCREEN_WIDTH: usize = 320; +const SCREEN_HEIGHT: usize = 320; +const SCREEN_ROWS: usize = 15; +const SCREEN_COLS: usize = 31; +const FONT: MonoFont = FONT_10X20; +const COLOR: Rgb565 = Rgb565::CSS_LAWN_GREEN; #[embassy_executor::task] -pub async fn display_task( - spi: Spi<'static, SPI1, Blocking>, - cs: PIN_13, - data: PIN_14, - reset: PIN_15, -) { +pub async fn display_task(spi: SPI, cs: PIN_13, data: PIN_14, reset: PIN_15) { let spi_device = ExclusiveDevice::new(spi, Output::new(cs, Level::Low), Delay).unwrap(); - let mut display = ST7365P::new( + let display = ST7365P::new( spi_device, Output::new(data, Level::Low), Some(Output::new(reset, Level::High)), - true, false, - 320, - 320, + true, + SCREEN_WIDTH as u32, + SCREEN_HEIGHT as u32, ); - display.init(&mut Delay).unwrap(); - display.set_orientation(&Orientation::Landscape).unwrap(); - let mut virtual_display = VirtualDisplay::new(display, 320 / 2, 320 / 2); + let mut framebuffer: FRAMEBUFFER = FrameBuffer::new(display); - let thin_stroke = PrimitiveStyle::with_stroke(Rgb565::RED, 20); - - Rectangle::new(Point::new(10, 10), Size::new(100, 100)) - .into_styled(thin_stroke) - .draw(&mut virtual_display) + framebuffer.init(&mut Delay).await.unwrap(); + framebuffer.display.set_offset(0, 0); + framebuffer + .display + .set_custom_orientation(0x60) + .await .unwrap(); + Text::with_alignment( + "Hello!", + Point::new(160, 160), + MonoTextStyle::new(&FONT_10X20, Rgb565::RED), + embedded_graphics::text::Alignment::Center, + ) + .draw(&mut framebuffer) + .unwrap(); + loop { + framebuffer.draw().await.unwrap(); Timer::after_millis(500).await; } } - -/// simple abstraction over real display & resolution to reduce frame buffer size -/// by cutting the resolution by 1/4 -struct VirtualDisplay { - display: ST7365P< - ExclusiveDevice, Output<'static>, Delay>, - Output<'static>, - Output<'static>, - >, - width: u32, - height: u32, -} - -impl VirtualDisplay { - pub fn new( - display: ST7365P< - ExclusiveDevice, Output<'static>, Delay>, - Output<'static>, - Output<'static>, - >, - new_width: u32, - new_height: u32, - ) -> Self { - Self { - display, - width: new_width, - height: new_height, - } - } -} - -impl DrawTarget for VirtualDisplay { - type Color = Rgb565; - type Error = (); - - fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> - where - I: IntoIterator>, - { - for Pixel(coord, color) in pixels.into_iter() { - // Check bounds on the *virtual* (already reduced) resolution - if coord.x >= 0 - && coord.y >= 0 - && coord.x < self.width as i32 - && coord.y < self.height as i32 - { - let px = coord.x as u16 * 2; - let py = coord.y as u16 * 2; - let raw_color = RawU16::from(color).into_inner(); - - // Draw the 2x2 block on the underlying hardware - self.display.set_pixel(px, py, raw_color)?; - self.display.set_pixel(px + 1, py, raw_color)?; - self.display.set_pixel(px, py + 1, raw_color)?; - self.display.set_pixel(px + 1, py + 1, raw_color)?; - } - } - Ok(()) - } -} - -impl OriginDimensions for VirtualDisplay { - fn size(&self) -> Size { - Size::new(self.width, self.height) - } -} diff --git a/src/main.rs b/src/main.rs index 56b63f8..ddc8d29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #![feature(impl_trait_in_assoc_type)] +#![feature(ascii_char)] #![no_std] #![no_main] @@ -39,19 +40,21 @@ async fn main(spawner: Spawner) { static KEYBOARD_EVENTS: StaticCell> = StaticCell::new(); let keyboard_events = KEYBOARD_EVENTS.init(Channel::new()); - // configure keyboard event handler - let mut config = i2c::Config::default(); - config.frequency = 100_000; - let i2c1 = I2c::new_async(p.I2C1, p.PIN_7, p.PIN_6, Irqs, config); - spawner - .spawn(peripherals_task(i2c1, keyboard_events.sender())) - .unwrap(); - - // // configure display handler - // let mut config = spi::Config::default(); - // config.frequency = 16_000_000; - // let spi1 = spi::Spi::new_blocking(p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, config); + // // configure keyboard event handler + // let mut config = i2c::Config::default(); + // config.frequency = 100_000; + // let i2c1 = I2c::new_async(p.I2C1, p.PIN_7, p.PIN_6, Irqs, config); // spawner - // .spawn(display_task(spi1, p.PIN_13, p.PIN_14, p.PIN_15)) + // .spawn(peripherals_task(i2c1, keyboard_events.sender())) // .unwrap(); + + // configure display handler + let mut config = spi::Config::default(); + config.frequency = 16_000_000; + let spi1 = spi::Spi::new( + p.SPI1, p.PIN_10, p.PIN_11, p.PIN_12, p.DMA_CH0, p.DMA_CH1, config, + ); + spawner + .spawn(display_task(spi1, p.PIN_13, p.PIN_14, p.PIN_15)) + .unwrap(); }