pm-kit milestone 2: ST7796 display bring-up
Init the Kit's ST7796 320x480 over SPI0 (SCK=GP2, MOSI=GP3, CS=GP5, DC=GP6, RST=GP7; BGR, colours inverted, 16 MHz) via mipidsi 0.9 + embedded-graphics, and draw a panel + "PM-KIT / RUST OK" so SPI + the graphics stack are verifiable on screen. GP25 LED keeps blinking as a heartbeat. Compiles for thumbv8m; runtime (does it draw? colours/orientation right?) is the on-device check. Next: tune orientation/colour if needed, then inputs + audio + pm-core. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8b4fca2a74
commit
4275187008
2 changed files with 67 additions and 10 deletions
|
|
@ -2,13 +2,16 @@
|
||||||
name = "pm-kit"
|
name = "pm-kit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "PM_K-1 firmware (RP2350 / Pico 2). Stage 3 bring-up: boot-proof blink, then drivers + pm-core."
|
description = "PM_K-1 firmware (RP2350 / Pico 2). Stage 3 bring-up: boot blink → display → drivers + pm-core."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rp235x-hal = { version = "0.3", features = ["binary-info", "critical-section-impl", "rt"] }
|
rp235x-hal = { version = "0.3", features = ["binary-info", "critical-section-impl", "rt"] }
|
||||||
cortex-m-rt = "0.7"
|
cortex-m-rt = "0.7"
|
||||||
panic-halt = "1"
|
panic-halt = "1"
|
||||||
embedded-hal = "1"
|
embedded-hal = "1"
|
||||||
|
embedded-hal-bus = "0.2"
|
||||||
|
mipidsi = "0.9"
|
||||||
|
embedded-graphics = "0.8"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,44 @@
|
||||||
//! PM_K-1 firmware — Stage 3 bring-up milestone 1: prove our Rust boots on the Pico 2 (RP2350).
|
//! PM_K-1 firmware — Stage 3 bring-up.
|
||||||
//!
|
//! Milestone 1 (done): blink GP25 → proved boot/flash.
|
||||||
//! Blinks the onboard LED (GP25). If it blinks, the whole path works: toolchain, RP2350 boot
|
//! Milestone 2 (this): init the ST7796 320×480 display over SPI0 and draw to it.
|
||||||
//! block, memory layout, flash, and the cortex-m-rt entry. Drivers (display / audio / inputs /
|
//! Pins (from the CircuitPython firmware): SCK=GP2, MOSI=GP3, CS=GP5, DC=GP6, RST=GP7;
|
||||||
//! USB-MIDI) and the `pm-core` engine come next, once boot is confirmed on hardware.
|
//! BGR panel, colours inverted. LED on GP25 keeps blinking as a heartbeat.
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
use embedded_graphics::{
|
||||||
|
mono_font::{ascii::FONT_10X20, MonoTextStyle},
|
||||||
|
pixelcolor::Rgb565,
|
||||||
|
prelude::*,
|
||||||
|
primitives::{PrimitiveStyle, Rectangle},
|
||||||
|
text::Text,
|
||||||
|
};
|
||||||
use embedded_hal::delay::DelayNs;
|
use embedded_hal::delay::DelayNs;
|
||||||
use embedded_hal::digital::OutputPin;
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||||
|
use mipidsi::interface::SpiInterface;
|
||||||
|
use mipidsi::models::ST7796;
|
||||||
|
use mipidsi::options::{ColorInversion, ColorOrder, Orientation};
|
||||||
|
use mipidsi::Builder;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use rp235x_hal as hal;
|
use rp235x_hal as hal;
|
||||||
|
use hal::fugit::RateExtU32;
|
||||||
|
use hal::Clock;
|
||||||
|
|
||||||
/// Image definition block — the RP2350 bootrom looks for this to boot the image.
|
/// Image definition block — the RP2350 bootrom looks for this to boot the image.
|
||||||
#[link_section = ".start_block"]
|
#[link_section = ".start_block"]
|
||||||
#[used]
|
#[used]
|
||||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||||
|
|
||||||
const XTAL_FREQ_HZ: u32 = 12_000_000; // Pico 2 crystal
|
const XTAL_FREQ_HZ: u32 = 12_000_000;
|
||||||
|
const WIDTH: u16 = 320;
|
||||||
|
const HEIGHT: u16 = 480;
|
||||||
|
|
||||||
#[hal::entry]
|
#[hal::entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||||
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
|
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
|
||||||
|
|
||||||
let clocks = hal::clocks::init_clocks_and_plls(
|
let clocks = hal::clocks::init_clocks_and_plls(
|
||||||
XTAL_FREQ_HZ,
|
XTAL_FREQ_HZ,
|
||||||
pac.XOSC,
|
pac.XOSC,
|
||||||
|
|
@ -37,11 +52,50 @@ fn main() -> ! {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
let mut timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
||||||
|
|
||||||
let sio = hal::Sio::new(pac.SIO);
|
let sio = hal::Sio::new(pac.SIO);
|
||||||
let pins = hal::gpio::Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
|
let pins = hal::gpio::Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
|
||||||
|
|
||||||
let mut led = pins.gpio25.into_push_pull_output();
|
let mut led = pins.gpio25.into_push_pull_output();
|
||||||
|
|
||||||
|
// --- ST7796 over SPI0 ---
|
||||||
|
let sclk = pins.gpio2.into_function::<hal::gpio::FunctionSpi>();
|
||||||
|
let mosi = pins.gpio3.into_function::<hal::gpio::FunctionSpi>();
|
||||||
|
let dc = pins.gpio6.into_push_pull_output();
|
||||||
|
let rst = pins.gpio7.into_push_pull_output();
|
||||||
|
let cs = pins.gpio5.into_push_pull_output();
|
||||||
|
|
||||||
|
let spi = hal::spi::Spi::<_, _, _, 8>::new(pac.SPI0, (mosi, sclk));
|
||||||
|
let spi = spi.init(
|
||||||
|
&mut pac.RESETS,
|
||||||
|
clocks.peripheral_clock.freq(),
|
||||||
|
16.MHz(),
|
||||||
|
embedded_hal::spi::MODE_0,
|
||||||
|
);
|
||||||
|
let spi_device = ExclusiveDevice::new_no_delay(spi, cs).unwrap();
|
||||||
|
|
||||||
|
let mut buffer = [0u8; 512];
|
||||||
|
let di = SpiInterface::new(spi_device, dc, &mut buffer);
|
||||||
|
|
||||||
|
let mut display = Builder::new(ST7796, di)
|
||||||
|
.reset_pin(rst)
|
||||||
|
.display_size(WIDTH, HEIGHT)
|
||||||
|
.color_order(ColorOrder::Bgr)
|
||||||
|
.invert_colors(ColorInversion::Inverted)
|
||||||
|
.orientation(Orientation::new())
|
||||||
|
.init(&mut timer)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// background
|
||||||
|
display.clear(Rgb565::new(2, 4, 8)).unwrap();
|
||||||
|
// a panel + label so we can see SPI + the graphics stack working
|
||||||
|
Rectangle::new(Point::new(20, 60), Size::new((WIDTH - 40) as u32, 140))
|
||||||
|
.into_styled(PrimitiveStyle::with_fill(Rgb565::new(2, 40, 50)))
|
||||||
|
.draw(&mut display)
|
||||||
|
.unwrap();
|
||||||
|
let title = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
|
||||||
|
Text::new("PM-KIT", Point::new(40, 110), title).draw(&mut display).unwrap();
|
||||||
|
Text::new("RUST OK", Point::new(40, 150), title).draw(&mut display).unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
led.set_high().unwrap();
|
led.set_high().unwrap();
|
||||||
timer.delay_ms(250);
|
timer.delay_ms(250);
|
||||||
|
|
@ -54,4 +108,4 @@ fn main() -> ! {
|
||||||
#[link_section = ".bi_entries"]
|
#[link_section = ".bi_entries"]
|
||||||
#[used]
|
#[used]
|
||||||
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 1] =
|
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 1] =
|
||||||
[hal::binary_info::rp_program_name!(c"pm-kit blink")];
|
[hal::binary_info::rp_program_name!(c"pm-kit display")];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue