diff --git a/boards/pygamer/Cargo.toml b/boards/pygamer/Cargo.toml index cb5bf24643f..1675af9ed46 100644 --- a/boards/pygamer/Cargo.toml +++ b/boards/pygamer/Cargo.toml @@ -16,7 +16,9 @@ version = "0.11.0" [dependencies] cortex-m = {version = "0.7", features = ["critical-section-single-core"]} -st7735-lcd = "0.8.1" +embedded-hal-bus = "0.2.0" +# This version is pinned as recommended by: https://docs.rs/embedded-hal-bus/0.2.0/embedded_hal_bus/spi/struct.ExclusiveDevice.html#method.new_no_delay +st7735-lcd = "=0.10.0" [dependencies.cortex-m-rt] optional = true @@ -29,23 +31,24 @@ version = "0.18.2" [dependencies.usb-device] optional = true -version = "0.3.1" +version = "0.3.2" [dev-dependencies] -embedded-graphics = "0.7.1" -embedded-hal-bus = "0.2.0" +embedded-graphics = "0.8.1" embedded-sdmmc = "0.8.0" lis3dh = "0.4.3" micromath = "2.1" -panic-halt = "0.2" +panic-halt = "1" rtic = {version = "2.1.1", features = ["thumbv7-backend"]} smart-leds = "0.4" -tinybmp = "0.3.1" +tinybmp = "0.6" usbd-serial = "0.2" [features] # ask the HAL to enable atsamd51j support default = ["rt", "atsamd-hal/samd51j"] +dma = ["atsamd-hal/dma"] +max-channels = ["dma", "atsamd-hal/max-channels"] panic_led = [] rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"] usb = ["atsamd-hal/usb", "usb-device"] diff --git a/boards/pygamer/examples/clock_out.rs b/boards/pygamer/examples/clock_out.rs index a6cac263988..9f744a92d9c 100644 --- a/boards/pygamer/examples/clock_out.rs +++ b/boards/pygamer/examples/clock_out.rs @@ -30,5 +30,7 @@ fn main() -> ! { .configure_gclk_divider_and_source(Gclk2, 40, Dpll0, false) .unwrap(); let _clock_out_pin: GclkOut = pins.d5.into(); - loop {} + loop { + cortex_m::asm::wfi(); + } } diff --git a/boards/pygamer/examples/ferris_img.rs b/boards/pygamer/examples/ferris_img.rs index 8852532f73c..2cf9068d492 100644 --- a/boards/pygamer/examples/ferris_img.rs +++ b/boards/pygamer/examples/ferris_img.rs @@ -59,5 +59,7 @@ fn main() -> ! { let ferris = Image::new(&raw_image, Point::new(32, 32)); ferris.draw(&mut display).unwrap(); - loop {} + loop { + cortex_m::asm::wfi(); + } } diff --git a/boards/pygamer/examples/qspi.rs b/boards/pygamer/examples/qspi.rs index 4ac03d9c0d8..212aed377f9 100644 --- a/boards/pygamer/examples/qspi.rs +++ b/boards/pygamer/examples/qspi.rs @@ -99,7 +99,9 @@ fn main() -> ! { flash.read_memory(0, &mut read_buf); assert_eq!(read_buf, write_buf); - loop {} + loop { + cortex_m::asm::wfi(); + } } /// Wait for the write-in-progress and suspended write/erase. diff --git a/boards/pygamer/src/pins.rs b/boards/pygamer/src/pins.rs index 410f3abe38c..d6fa0363b87 100644 --- a/boards/pygamer/src/pins.rs +++ b/boards/pygamer/src/pins.rs @@ -4,6 +4,7 @@ use super::{hal, pac}; use hal::prelude::*; +use embedded_hal_bus::spi as bspi; use hal::clock::GenericClockController; use hal::gpio::PA01; use hal::pwm; @@ -581,11 +582,39 @@ pub struct Display { pub tft_backlight: TftBacklightReset, } +/// Error that can occur when initializing the display. +#[derive(Debug)] +pub enum DisplayError { + /// Could not configure the SERCOM4 clock. + SercomClock, + /// Could not configure the SPI port to drive the display. + Spi, + /// Could not setup the ST7735 display driver. + Driver, + /// Could not configure the TC2/TC3 clock for PWM control of the backlight. + Tc2Tc3Clock, +} +impl From<()> for DisplayError { + #[inline] + fn from(_value: ()) -> Self { + Self::Driver + } +} + pub type TftPads = spi::Pads; -pub type TftSpi = spi::Spi, spi::Tx>; +pub type TftSpi = bspi::ExclusiveDevice< + spi::PanicOnRead, spi::Tx>>, + TftCs, + bspi::NoDelay, +>; + +/// The on-board display driver that is a +/// [`DrawTarget`](https://docs.rs/embedded-graphics/latest/embedded_graphics/draw_target/trait.DrawTarget.html) +/// for embedded graphics. +pub type DisplayDriver = ST7735; impl Display { - /// Convenience for setting up the on board display. + /// Convenience for setting up the on-board display. pub fn init( self, clocks: &mut GenericClockController, @@ -593,18 +622,25 @@ impl Display { mclk: &mut pac::Mclk, timer2: pac::Tc2, delay: &mut hal::delay::Delay, - ) -> Result<(ST7735, Pwm2), ()> { + ) -> Result<(DisplayDriver, Pwm2), DisplayError> { let gclk0 = clocks.gclk0(); - let clock = &clocks.sercom4_core(&gclk0).ok_or(())?; + let clock = &clocks + .sercom4_core(&gclk0) + .ok_or(DisplayError::SercomClock)?; let pads = spi::Pads::default() .sclk(self.tft_sclk) .data_out(self.tft_mosi); - let tft_spi = spi::Config::new(mclk, sercom4, pads, clock.freq()) - .spi_mode(spi::MODE_0) - .baud(16.MHz()) - .enable(); let mut tft_cs: TftCs = self.tft_cs.into(); tft_cs.set_low().ok(); + let tft_spi = bspi::ExclusiveDevice::new_no_delay( + spi::Config::new(mclk, sercom4, pads, clock.freq()) + .spi_mode(spi::MODE_0) + .baud(16.MHz()) + .enable() + .into_panic_on_read(), + tft_cs, + ) + .map_err(|_| DisplayError::Spi)?; let mut display = st7735_lcd::ST7735::new( tft_spi, self.tft_dc.into(),