Last active
September 12, 2022 10:25
-
-
Save 9names/1a1227c7365b100123bcedea74e2aa4c to your computer and use it in GitHub Desktop.
A quick test of the pico display pack with the mipidsi crate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! # Pimoroni Display Pack Example | |
#![no_std] | |
#![no_main] | |
use embedded_hal::digital::v2::InputPin; | |
// The macro for our start-up function | |
use rp_pico::entry; | |
// Time handling traits | |
use embedded_time::rate::*; | |
// Ensure we halt the program on panic (if we don't mention this crate it won't | |
// be linked) | |
use panic_halt as _; | |
// Pull in any important traits | |
use rp_pico::hal::prelude::*; | |
// A shorter alias for the Peripheral Access Crate, which provides low-level | |
// register access | |
use rp_pico::hal::pac; | |
// A shorter alias for the Hardware Abstraction Layer, which provides | |
// higher-level drivers. | |
use rp_pico::hal; | |
// ST7789 driver | |
// use st7789::{Orientation, ST7789}; | |
// SPI display interface | |
use display_interface_spi::SPIInterface; | |
// Graphics drawing utilities | |
use embedded_graphics::pixelcolor::Rgb565; | |
use embedded_graphics::prelude::*; | |
use embedded_graphics::primitives::*; | |
// GPIO traits | |
use embedded_hal::digital::v2::OutputPin; | |
use embedded_hal::PwmPin; | |
use mipidsi; | |
/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust | |
/// if your board has a different frequency | |
const XTAL_FREQ_HZ: u32 = 12_000_000u32; | |
#[entry] | |
fn main() -> ! { | |
// Grab our singleton objects | |
let mut pac = pac::Peripherals::take().unwrap(); | |
let core = pac::CorePeripherals::take().unwrap(); | |
// Set up the watchdog driver - needed by the clock setup code | |
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); | |
// Configure the clocks | |
let clocks = hal::clocks::init_clocks_and_plls( | |
XTAL_FREQ_HZ, | |
pac.XOSC, | |
pac.CLOCKS, | |
pac.PLL_SYS, | |
pac.PLL_USB, | |
&mut pac.RESETS, | |
&mut watchdog, | |
) | |
.ok() | |
.unwrap(); | |
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); | |
// The single-cycle I/O block controls our GPIO pins | |
let sio = hal::Sio::new(pac.SIO); | |
// Set the pins up according to their function on this particular board | |
let pins = rp_pico::Pins::new( | |
pac.IO_BANK0, | |
pac.PADS_BANK0, | |
sio.gpio_bank0, | |
&mut pac.RESETS, | |
); | |
// Init PWMs | |
let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS); | |
// Configure and enable PWMs | |
let pwm3 = &mut pwm_slices.pwm3; | |
pwm3.set_ph_correct(); | |
pwm3.enable(); | |
let pwm4 = &mut pwm_slices.pwm4; | |
pwm4.set_ph_correct(); | |
pwm4.enable(); | |
// Configure button inputs | |
// 12 - A button | |
let _a_pin = pins.gpio12.into_pull_up_input(); | |
// 13 - B button | |
let _b_pin = pins.gpio13.into_pull_up_input(); | |
// 14 - X button | |
let _x_pin = pins.gpio14.into_pull_up_input(); | |
// 15 - Y button | |
let _y_pin = pins.gpio15.into_pull_up_input(); | |
// 6 (PWM 3A) - LED red | |
let r_channel = &mut pwm3.channel_a; | |
r_channel.output_to(pins.gpio6); | |
r_channel.set_inverted(); | |
r_channel.set_duty(0); | |
// 7 (PWM 3B) - LED green | |
let g_channel = &mut pwm3.channel_b; | |
g_channel.output_to(pins.gpio7); | |
g_channel.set_inverted(); | |
g_channel.set_duty(0); | |
// 8 (PWM 4A) - LED blue | |
let b_channel = &mut pwm4.channel_a; | |
b_channel.output_to(pins.gpio8); | |
b_channel.set_inverted(); | |
b_channel.set_duty(0); | |
// 20 - LCD backlight | |
pins.gpio20.into_push_pull_output().set_high().unwrap(); | |
// 22 - LCD hard reset | |
let mut rst_pin = pins.gpio22.into_push_pull_output(); | |
rst_pin.set_low().unwrap(); | |
// Setup SPI | |
let spi_cs = pins.gpio17.into_push_pull_output(); | |
let spi_miso = pins.gpio16.into_push_pull_output(); | |
let _spi_sclk = pins.gpio18.into_mode::<hal::gpio::FunctionSpi>(); | |
let _spi_mosi = pins.gpio19.into_mode::<hal::gpio::FunctionSpi>(); | |
let spi = hal::Spi::<_, _, 8>::new(pac.SPI0); | |
// Exchange the uninitialised SPI driver for an initialised one | |
let spi = spi.init( | |
&mut pac.RESETS, | |
clocks.peripheral_clock.freq(), | |
125_000_000u32.Hz(), | |
&embedded_hal::spi::MODE_3, | |
); | |
// display interface abstraction from SPI and DC | |
let di = SPIInterface::new(spi, spi_miso, spi_cs); | |
// create driver | |
let mut display = mipidsi::Display::st7789( | |
di, | |
rst_pin, | |
mipidsi::DisplayOptions { | |
orientation: mipidsi::Orientation::PortraitInverted(true), | |
invert_vertical_refresh: false, | |
color_order: Default::default(), | |
invert_horizontal_refresh: false, | |
display_size: (135, 240), | |
framebuffer_size: (240, 320), | |
window_offset: (52, 40), | |
}, | |
); | |
// initialize | |
display.init(&mut delay).unwrap(); | |
let Y_MAX = 240; | |
let X_MAX = 135; | |
let CIRCLE_WIDTH = 60; | |
let CIRCLE_RADIUS = 30; | |
let circle_origin_red = Circle::new( | |
Point::new(0 - CIRCLE_RADIUS, 0 - CIRCLE_RADIUS), | |
CIRCLE_WIDTH, | |
) | |
.into_styled(PrimitiveStyle::with_fill(Rgb565::RED)); | |
let circle_xmax_blue = Circle::new( | |
Point::new(X_MAX - CIRCLE_RADIUS, 0 - CIRCLE_RADIUS), | |
CIRCLE_WIDTH, | |
) | |
.into_styled(PrimitiveStyle::with_fill(Rgb565::BLUE)); | |
let circle_ymax_green = Circle::new( | |
Point::new(0 - CIRCLE_RADIUS, Y_MAX - CIRCLE_RADIUS), | |
CIRCLE_WIDTH, | |
) | |
.into_styled(PrimitiveStyle::with_fill(Rgb565::GREEN)); | |
let circle_xmax_ymax_yellow = Circle::new( | |
Point::new(X_MAX - CIRCLE_RADIUS, Y_MAX - CIRCLE_RADIUS), | |
CIRCLE_WIDTH, | |
) | |
.into_styled(PrimitiveStyle::with_fill(Rgb565::YELLOW)); | |
let line_origin_to_xmax_ymax_purple = Line::new(Point::new(0, 0), Point::new(X_MAX, Y_MAX)) | |
.into_styled(PrimitiveStyle::with_stroke(Rgb565::CSS_PURPLE, 1)); | |
let line_xmax_0_to_0_ymax_white = Line::new(Point::new(X_MAX, 0), Point::new(0, Y_MAX)) | |
.into_styled(PrimitiveStyle::with_stroke(Rgb565::WHITE, 1)); | |
display.clear(Rgb565::WHITE).unwrap(); | |
display.clear(Rgb565::BLACK).unwrap(); | |
circle_origin_red.draw(&mut display).unwrap(); | |
circle_xmax_blue.draw(&mut display).unwrap(); | |
circle_ymax_green.draw(&mut display).unwrap(); | |
circle_xmax_ymax_yellow.draw(&mut display).unwrap(); | |
line_origin_to_xmax_ymax_purple.draw(&mut display).unwrap(); | |
line_xmax_0_to_0_ymax_white.draw(&mut display).unwrap(); | |
loop { | |
if _a_pin.is_high().unwrap() { | |
r_channel.set_duty(32000); | |
} else { | |
r_channel.set_duty(0); | |
} | |
if _b_pin.is_low().unwrap() { | |
display.clear(Rgb565::BLACK).unwrap(); | |
circle_origin_red.draw(&mut display).unwrap(); | |
circle_xmax_blue.draw(&mut display).unwrap(); | |
circle_ymax_green.draw(&mut display).unwrap(); | |
circle_xmax_ymax_yellow.draw(&mut display).unwrap(); | |
line_origin_to_xmax_ymax_purple.draw(&mut display).unwrap(); | |
line_xmax_0_to_0_ymax_white.draw(&mut display).unwrap(); | |
} | |
} | |
} | |
// use display_interface_spu::WriteOnlyDataCommand; | |
pub fn lcd_test_pattern<DI, RST, M, C: RgbColor, PinE>( | |
lcd: &mut mipidsi::Display<DI, RST, M>, | |
c1: C, | |
c2: C, | |
) -> Result<(), mipidsi::Error<PinE>> | |
where | |
DI: display_interface::WriteOnlyDataCommand, | |
RST: OutputPin<Error = PinE>, | |
M: mipidsi::models::Model<ColorFormat = C>, | |
{ | |
let Size { width, height } = lcd.size(); | |
let pattern = (0..height as i32).flat_map(|y| { | |
(0..width as i32).map(move |x| { | |
let dx = x - width as i32 / 2; | |
let dy = y - height as i32 / 2; | |
if dx * dx * 2 + dy * dy < 40 * 40 { | |
c1 | |
} else { | |
c2 | |
} | |
}) | |
}); | |
lcd.set_pixels(0, 0, width as u16, height as u16, pattern) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment