cardputer-bsc-nostd/src/display.rs
2025-07-12 14:20:37 +01:00

132 lines
4.1 KiB
Rust

//! Create and initialize ST7789 display driver
// use display_interface_spi::SPIInterface;
use embedded_hal_bus::spi::ExclusiveDevice;
use mipidsi::{
Builder, Display as MipiDisplay,
interface::SpiInterface,
models::ST7789,
options::{ColorInversion, Orientation},
};
use thiserror::Error;
pub struct Display {}
type Drawable<'a> = MipiDisplay<
SpiInterface<
'a,
ExclusiveDevice<
esp_hal::spi::master::Spi<'a, esp_hal::Blocking>,
esp_hal::gpio::Output<'a>,
esp_hal::delay::Delay,
>,
esp_hal::gpio::Output<'a>,
>,
ST7789,
esp_hal::gpio::Output<'a>,
>;
/// Display width
pub const DISPLAY_SIZE_WIDTH: u16 = 240;
/// Display height
pub const DISPLAY_SIZE_HEIGHT: u16 = 135;
pub const DISPLAY_BUFFER_SIZE: usize =
DISPLAY_SIZE_WIDTH as usize * DISPLAY_SIZE_HEIGHT as usize * 2;
#[derive(Debug, Error)]
pub enum BuildError {
#[error("SPI config error: {0}")]
SpiConfigError(#[from] esp_hal::spi::master::ConfigError),
#[error("Some error occurred when initialising the MIPI DSI display")]
MipidsiInitError,
#[error("SPI error: {0:?}")]
SpiError(esp_hal::spi::Error),
}
pub fn build<'a>(
spi: esp_hal::peripherals::SPI2<'a>,
sck: esp_hal::peripherals::GPIO36<'a>,
dc: esp_hal::peripherals::GPIO35<'a>,
cs: esp_hal::peripherals::GPIO37<'a>,
rs: esp_hal::peripherals::GPIO34<'a>,
rst: esp_hal::peripherals::GPIO33<'a>,
) -> Result<Drawable<'a>, BuildError> {
static mut DISPLAY_BUFFER: [u8; 1000] = [0; 1000];
// let spi_config = SpiConfig::new().baudrate(80.MHz().into());
// let device_config = DriverConfig::new();
// let spi = SpiDeviceDriver::new_single(
// spi,
// sck,
// dc,
// Option::<AnyIOPin>::None,
// Some(cs),
// &device_config,
// &spi_config,
// )?;
let spi = esp_hal::spi::master::Spi::new(
spi,
esp_hal::spi::master::Config::default().with_frequency(esp_hal::time::Rate::from_mhz(80)),
)?
.with_sck(sck)
.with_mosi(dc);
let Ok(spi) = ExclusiveDevice::new(
spi,
esp_hal::gpio::Output::new(
cs,
esp_hal::gpio::Level::Low,
esp_hal::gpio::OutputConfig::default(),
),
esp_hal::delay::Delay::new(),
);
let rs = esp_hal::gpio::Output::new(
rs,
esp_hal::gpio::Level::Low,
esp_hal::gpio::OutputConfig::default(),
);
let rst = esp_hal::gpio::Output::new(
rst,
esp_hal::gpio::Level::Low,
esp_hal::gpio::OutputConfig::default(),
);
#[allow(static_mut_refs)]
let mut drawable = Builder::new(
ST7789,
SpiInterface::new(spi, rs, unsafe { DISPLAY_BUFFER.as_mut_slice() }),
) //st7789(SpiInterface::new(spi, rs))
.invert_colors(ColorInversion::Inverted)
.display_size(DISPLAY_SIZE_HEIGHT, DISPLAY_SIZE_WIDTH) // deliberately reversed order
.display_offset(40, 53)
.reset_pin(rst)
.init(&mut esp_hal::delay::Delay::new())
.map_err(|_| BuildError::MipidsiInitError)?;
// Can't capture the error since it's a public type
// in a private module and not re-exported. The master
// branch of the mipidsi repo does have a fix but it's
// not had a crates.io release yet.
drawable
.set_orientation(Orientation::new().rotate(mipidsi::options::Rotation::Deg90))
.map_err(|e| match e {
mipidsi::interface::SpiError::Spi(e) => match e {
embedded_hal_bus::spi::DeviceError::Spi(e) => BuildError::SpiError(e),
embedded_hal_bus::spi::DeviceError::Cs(e) => match e {},
},
mipidsi::interface::SpiError::Dc(e) => match e {},
})?;
drawable
.set_vertical_scroll_offset(0)
.map_err(|e| match e {
mipidsi::interface::SpiError::Spi(e) => match e {
embedded_hal_bus::spi::DeviceError::Spi(e) => BuildError::SpiError(e),
embedded_hal_bus::spi::DeviceError::Cs(e) => match e {},
},
mipidsi::interface::SpiError::Dc(e) => match e {},
})?;
Ok(drawable)
}