#![no_std] #![no_main] use core::cell::RefCell; use defmt::info; use display_interface_spi::SPIInterface; use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice; use embassy_executor::Spawner; use embassy_nrf::{ bind_interrupts, gpio::{AnyPin, Level, Output, OutputDrive, Pin}, peripherals, spim::{self, Spim}, }; use embassy_sync::blocking_mutex::Mutex; use embassy_time::{Delay, Duration, Timer}; use embedded_hal::digital::OutputPin; use ili9341::Ili9341; use {defmt_rtt as _, panic_probe as _}; use embedded_graphics::{ mono_font::{ascii::FONT_10X20, MonoTextStyle}, pixelcolor::{BinaryColor, Rgb565}, prelude::*, primitives::{ Circle, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, StrokeAlignment, Triangle, }, text::{Alignment, Text}, }; // Setup interrupts bind_interrupts!(struct Irqs { // Setup interrupts for SPI (SERIAL3) UARTE3_SPIM3_SPIS3_TWIM3_TWIS3 => embassy_nrf::spim::InterruptHandler; }); #[embassy_executor::task] async fn blink(pin: AnyPin, blink_delay: Duration) -> ! { let mut led = Output::new(pin, Level::Low, OutputDrive::Standard); loop { led.set_high(); Timer::after(blink_delay).await; led.set_low(); Timer::after(blink_delay).await; } } fn display_demo(display: &mut D) -> Result<(), D::Error> where D: DrawTarget, { display.clear(Rgb565::CSS_DARK_OLIVE_GREEN)?; // Create styles used by the drawing operations. let thin_stroke = PrimitiveStyle::with_stroke(Rgb565::WHITE, 1); let thick_stroke = PrimitiveStyle::with_stroke(Rgb565::WHITE, 3); let border_stroke = PrimitiveStyleBuilder::new() .stroke_color(Rgb565::WHITE) .stroke_width(3) .stroke_alignment(StrokeAlignment::Inside) .build(); let fill = PrimitiveStyle::with_fill(Rgb565::WHITE); let character_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let yoffset = 10; // Draw a 3px wide outline around the display. display .bounding_box() .into_styled(border_stroke) .draw(display)?; // Draw a triangle. Triangle::new( Point::new(16, 16 + yoffset), Point::new(16 + 16, 16 + yoffset), Point::new(16 + 8, yoffset), ) .into_styled(thin_stroke) .draw(display)?; // Draw a filled square Rectangle::new(Point::new(52, yoffset), Size::new(16, 16)) .into_styled(fill) .draw(display)?; // Draw a circle with a 3px wide stroke. Circle::new(Point::new(88, yoffset), 17) .into_styled(thick_stroke) .draw(display)?; // Draw centered text. let text = "embedded-graphics"; Text::with_alignment( text, display.bounding_box().center() + Point::new(0, 15), character_style, Alignment::Center, ) .draw(display)?; Ok(()) } #[embassy_executor::main] async fn main(spawner: Spawner) { // Initialize the nRF let p = embassy_nrf::init(Default::default()); // Spawn the blink task spawner .spawn(blink(p.P0_02.degrade(), Duration::from_millis(250))) .expect("Failed to start blink task"); //////////////// // Setup pins // //////////////// let mosi = p.P0_13; let miso = p.P0_12; let sck = p.P0_30; let cs_pin = p.P0_31; let dc_pin = p.P0_20; // Data / Command pin for the display let disp_rst_pin = p.P0_11; // Initialize the CS, DC, and display reset pins as outputs let chip_select = Output::new(cs_pin, Level::High, OutputDrive::Standard); let direction_control = Output::new(dc_pin, Level::High, OutputDrive::Standard); let display_reset = Output::new(disp_rst_pin, Level::High, OutputDrive::Standard); /////////////// // Setup SPI // /////////////// // Create an SPI config with the SPI frequency at 8MHz let mut spim_config = spim::Config::default(); spim_config.frequency = spim::Frequency::M8; // Grab the SPI Master peripheral form the nRF60 let spim = embassy_nrf::spim::Spim::new(p.SERIAL3, Irqs, sck, miso, mosi, spim_config); // Use the SPI peripheral to create a shared SPI bus let spi_bus: Mutex = Mutex::new(RefCell::new(spim)); // Use the shared bus to create a SPI Device to use for the display let spi_display = SpiDevice::new(&spi_bus, chip_select); // Create a new SPI display interface let iface = SPIInterface::new(spi_display, direction_control); //////////////////////// // Create the display // //////////////////////// // Some options for the display let display_orientation = ili9341::Orientation::Landscape; let display_size = ili9341::DisplaySize240x320; // Create the display let mut display = Ili9341::new( iface, display_reset, &mut embassy_time::Delay, display_orientation, display_size, ) .unwrap(); // Now loop, re-running the demo every second loop { display_demo(&mut display).expect("Failed to run display demo"); Timer::after_secs(1).await; } }