Skip to content

Instantly share code, notes, and snippets.

@9names
Last active September 12, 2022 10:25
Show Gist options
  • Save 9names/1a1227c7365b100123bcedea74e2aa4c to your computer and use it in GitHub Desktop.
Save 9names/1a1227c7365b100123bcedea74e2aa4c to your computer and use it in GitHub Desktop.
A quick test of the pico display pack with the mipidsi crate
//! # 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