From 45dc19c32943be553b30badcc8f3c2518f769627 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 27 Feb 2025 08:57:16 -0500 Subject: [PATCH] Move board control into a self-contained object --- pico-st7789/src/main.rs | 145 +++------------------------- pico-st7789/src/st7789.rs | 196 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 131 deletions(-) create mode 100644 pico-st7789/src/st7789.rs diff --git a/pico-st7789/src/main.rs b/pico-st7789/src/main.rs index 61534c4..532810c 100644 --- a/pico-st7789/src/main.rs +++ b/pico-st7789/src/main.rs @@ -15,6 +15,10 @@ use rp_pico::{ pac, Pins, }; +mod st7789; +use st7789::{ST7789Display, SETUP_PROGRAM}; +pub use st7789::Step; + const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764 const ROWS: usize = 320; @@ -28,125 +32,6 @@ struct Frame { } */ -struct Step { - param_cnt: usize, - command: u8, - params: [u8; 4], - delay: Option, -} - -impl Step { - fn send_command( - &self, - spi: &mut Spi, - data_command: &mut Pin, PullDown>, - ) where - D: SpiDevice, - Pinout: ValidSpiPinout, - P: PinId, - { - let _ = data_command.set_low(); - let _ = spi.write(&[self.command]); - if self.param_cnt > 0 { - let _ = data_command.set_high(); - let _ = spi.write(&self.params[0..self.param_cnt]); - } - } -} - -const NOP: u8 = 0x00; - -const SWRESET: Step = Step { - param_cnt: 0, - command: 0x01, - params: [0, 0, 0, 0], - delay: Some(150), -}; -const SLPOUT: Step = Step { - param_cnt: 0, - command: 0x11, - params: [0, 0, 0, 0], - delay: Some(10), -}; -const COLMOD: u8 = 0x3a; -const MADCTL: Step = Step { - param_cnt: 1, - command: 0x36, - params: [0x00, 0, 0, 0], - delay: None, -}; -const CASET: u8 = 0x2a; -const RASET: u8 = 0x2b; -const INVON: Step = Step { - param_cnt: 0, - command: 0x21, - params: [0, 0, 0, 0], - delay: Some(10), -}; -const NORON: Step = Step { - param_cnt: 0, - command: 0x13, - params: [0, 0, 0, 0], - delay: Some(10), -}; -const DISPON: Step = Step { - param_cnt: 0, - command: 0x29, - params: [0, 0, 0, 0], - delay: Some(10), -}; -const RAMWR: u8 = 0x2c; - -// Adafruit setup instructions -// SWRESET (0x01), 150ms delay -// SLPOUT (0x11), 10ms delay -// COLMOD (0x3a) 0x55 (65K RGB, 16bit/pixel), 10ms delay -// MADCTL (0x36) 0x00, -// memory data access control, RGB -// CASET 0x00, 0, 0, 170, -// column address set, 4 parameters -// 0x00, 0x00 indicates xstart is 0 -// 0x00, 170 indicates xend is 170 -// RASET 0x00, 0, 320 >> 8, 320 & 0xFF, -// row address set, 4 parameters -// 0x00, 0x00 indicates ystart is 0 -// 3230 >> 8, 320 & 0xff indicates that 320 is the last y address -// INVON, 10ms delay -// invert the display -// NORON, 10ms delay -// normal display mode -// DISPON, 10ms delay -// turn the display on - -const SETUP_PROGRAM: [Step; 8] = [ - SWRESET, - SLPOUT, - Step { - param_cnt: 1, - command: COLMOD, - params: [0x66, 0, 0, 0], - delay: Some(10), - }, - MADCTL, - Step { - param_cnt: 4, - command: CASET, - params: [0, 35, 0, 204], - delay: None, - }, - /* - Step { - param_cnt: 4, - command: RASET, - params: [0, 0, (320 >> 8) as u8, (320 & 0xff) as u8], - delay: None, - }, - */ - INVON, - NORON, - DISPON, -]; - #[entry] unsafe fn main() -> ! { // rp_pico::pac::Peripherals is a reference to physical hardware defined on the Pico. @@ -214,36 +99,34 @@ unsafe fn main() -> ! { embedded_hal::spi::MODE_3, ); + let mut display = ST7789Display::new(board_select, data_command, spi); + let _ = reset.set_high(); timer.delay_ms(10); - let _ = board_select.set_low(); - timer.delay_ms(10); for step in SETUP_PROGRAM { - step.send_command(&mut spi, &mut data_command); - if let Some(delay) = step.delay { - timer.delay_ms(delay); - } + let mut display = display.acquire(); + display.send_command(&step, &mut timer); } timer.delay_ms(1000); let mut frame: [u8; FRAMEBUF] = [0; FRAMEBUF]; - /* - let mut frame = Frame { - columns: COLUMNS, - buf: [0; FRAMEBUF], - }; - */ let mut strength = 0; loop { led.set_high(); + /* let _ = board_select.set_low(); let _ = data_command.set_low(); let _ = spi.write(&[RAMWR]); let _ = data_command.set_high(); let _ = spi.write(&frame); let _ = board_select.set_high(); + */ + { + let display = display.acquire(); + display.send_buf(&frame); + } for x in 80..90 { for y in 155..165 { diff --git a/pico-st7789/src/st7789.rs b/pico-st7789/src/st7789.rs new file mode 100644 index 0000000..4e19441 --- /dev/null +++ b/pico-st7789/src/st7789.rs @@ -0,0 +1,196 @@ +use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiBus}; +use rp_pico::hal::{ + gpio::{FunctionSio, Pin, PinId, PullDown, SioOutput}, + spi::{Enabled, SpiDevice, ValidSpiPinout}, + Spi, Timer, +}; + +pub struct Step { + param_cnt: usize, + command: u8, + params: [u8; 4], + delay: Option, +} + +impl Step { + pub fn send_command( + &self, + spi: &mut Spi, + data_command: &mut Pin, PullDown>, + ) where + D: SpiDevice, + Pinout: ValidSpiPinout, + P: PinId, + { + let _ = data_command.set_low(); + let _ = spi.write(&[self.command]); + if self.param_cnt > 0 { + let _ = data_command.set_high(); + let _ = spi.write(&self.params[0..self.param_cnt]); + } + } +} + +const NOP: u8 = 0x00; + +const SWRESET: Step = Step { + param_cnt: 0, + command: 0x01, + params: [0, 0, 0, 0], + delay: Some(150), +}; +const SLPOUT: Step = Step { + param_cnt: 0, + command: 0x11, + params: [0, 0, 0, 0], + delay: Some(10), +}; +const COLMOD: u8 = 0x3a; +const MADCTL: Step = Step { + param_cnt: 1, + command: 0x36, + params: [0x00, 0, 0, 0], + delay: None, +}; +const CASET: u8 = 0x2a; +const RASET: u8 = 0x2b; +const INVON: Step = Step { + param_cnt: 0, + command: 0x21, + params: [0, 0, 0, 0], + delay: Some(10), +}; +const NORON: Step = Step { + param_cnt: 0, + command: 0x13, + params: [0, 0, 0, 0], + delay: Some(10), +}; +const DISPON: Step = Step { + param_cnt: 0, + command: 0x29, + params: [0, 0, 0, 0], + delay: Some(10), +}; +const RAMWR: u8 = 0x2c; + +// Adafruit setup instructions +// SWRESET (0x01), 150ms delay +// SLPOUT (0x11), 10ms delay +// COLMOD (0x3a) 0x55 (65K RGB, 16bit/pixel), 10ms delay +// MADCTL (0x36) 0x00, +// memory data access control, RGB +// CASET 0x00, 0, 0, 170, +// column address set, 4 parameters +// 0x00, 0x00 indicates xstart is 0 +// 0x00, 170 indicates xend is 170 +// RASET 0x00, 0, 320 >> 8, 320 & 0xFF, +// row address set, 4 parameters +// 0x00, 0x00 indicates ystart is 0 +// 3230 >> 8, 320 & 0xff indicates that 320 is the last y address +// INVON, 10ms delay +// invert the display +// NORON, 10ms delay +// normal display mode +// DISPON, 10ms delay +// turn the display on + +pub const SETUP_PROGRAM: [Step; 8] = [ + SWRESET, + SLPOUT, + Step { + param_cnt: 1, + command: COLMOD, + params: [0x66, 0, 0, 0], + delay: Some(10), + }, + MADCTL, + Step { + param_cnt: 4, + command: CASET, + params: [0, 35, 0, 204], + delay: None, + }, + /* + Step { + param_cnt: 4, + command: RASET, + params: [0, 0, (320 >> 8) as u8, (320 & 0xff) as u8], + delay: None, + }, + */ + INVON, + NORON, + DISPON, +]; + +pub struct ST7789Display< + BoardSelectId: PinId, + DataCommandId: PinId, + D: SpiDevice, + Pinout: ValidSpiPinout, +> { + inner: ST7789DisplayEnabled, +} + +impl> + ST7789Display +{ + pub fn new( + board_select: Pin, PullDown>, + data_command: Pin, PullDown>, + spi: Spi, + ) -> Self { + Self { + inner: ST7789DisplayEnabled { + board_select, + data_command, + spi, + }, + } + } + + pub fn acquire( + &mut self, + ) -> &mut ST7789DisplayEnabled { + self.inner.board_select.set_low(); + &mut self.inner + } +} + +pub struct ST7789DisplayEnabled< + BoardSelectId: PinId, + DataCommandId: PinId, + D: SpiDevice, + Pinout: ValidSpiPinout, +> { + board_select: Pin, PullDown>, + data_command: Pin, PullDown>, + spi: Spi, +} + +impl> + ST7789DisplayEnabled +{ + pub fn send_command(&mut self, step: &Step, timer: &mut Timer) { + step.send_command(&mut self.spi, &mut self.data_command); + if let Some(delay) = step.delay { + timer.delay_ms(delay); + } + } + + pub fn send_buf(&mut self, frame: &[u8]) { + let _ = self.data_command.set_low(); + let _ = self.spi.write(&[RAMWR]); + let _ = self.data_command.set_high(); + let _ = self.spi.write(&frame); + } +} + +impl> Drop + for ST7789DisplayEnabled +{ + fn drop(&mut self) { + self.board_select.set_high(); + } +}