screen: Move setup to module
This commit is contained in:
parent
3ae65edcbe
commit
d7eeb67538
2 changed files with 134 additions and 65 deletions
79
src/main.rs
79
src/main.rs
|
|
@ -18,8 +18,6 @@ use embassy_gps::gps::l76k;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
#[cfg(feature = "screen")]
|
|
||||||
use esp_hal::{delay, gpio, spi, time};
|
|
||||||
#[cfg(all(target_arch = "riscv32", feature = "spat"))]
|
#[cfg(all(target_arch = "riscv32", feature = "spat"))]
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_radio::wifi;
|
use esp_radio::wifi;
|
||||||
|
|
@ -36,10 +34,6 @@ mod radio;
|
||||||
mod screen;
|
mod screen;
|
||||||
|
|
||||||
const WIFI_CHANNEL: radio::Channel = 180;
|
const WIFI_CHANNEL: radio::Channel = 180;
|
||||||
#[cfg(feature = "screen")]
|
|
||||||
pub const DISPLAY_WIDTH: u16 = 320;
|
|
||||||
#[cfg(feature = "screen")]
|
|
||||||
pub const DISPLAY_HEIGHT: u16 = 172;
|
|
||||||
|
|
||||||
// This creates a default app-descriptor required by the esp-idf bootloader.
|
// This creates a default app-descriptor required by the esp-idf bootloader.
|
||||||
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
||||||
|
|
@ -84,7 +78,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
|
|
||||||
info!("Embassy initialized!");
|
info!("Embassy initialized!");
|
||||||
|
|
||||||
// ST7789 172*320px screen
|
// Setup ST7789 screen
|
||||||
// SCL: D8/ GPIO8 (SPI_SCK)
|
// SCL: D8/ GPIO8 (SPI_SCK)
|
||||||
// SDA: D10/ GPIO10 (SPI_MOSI)
|
// SDA: D10/ GPIO10 (SPI_MOSI)
|
||||||
// RES: D3/ GPIO7
|
// RES: D3/ GPIO7
|
||||||
|
|
@ -95,43 +89,28 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
let mut spi_buffer = [0_u8; 512];
|
let mut spi_buffer = [0_u8; 512];
|
||||||
#[cfg(feature = "screen")]
|
#[cfg(feature = "screen")]
|
||||||
let mut screen = {
|
let mut screen = {
|
||||||
let (spi, cs) = setup_st7789_spi(
|
// 172*320px in landscape orientation
|
||||||
|
let (display, width, height) = screen::make_small_display(
|
||||||
peripherals.GPIO8,
|
peripherals.GPIO8,
|
||||||
peripherals.GPIO10,
|
peripherals.GPIO10,
|
||||||
|
peripherals.GPIO7,
|
||||||
|
peripherals.GPIO23,
|
||||||
peripherals.GPIO24,
|
peripherals.GPIO24,
|
||||||
peripherals.GPIO9,
|
peripherals.GPIO0,
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
|
&mut spi_buffer,
|
||||||
)
|
)
|
||||||
.expect("Failed to build SPI config");
|
.expect("Fatal error building screen");
|
||||||
let output_config = gpio::OutputConfig::default();
|
|
||||||
let dc_output = gpio::Output::new(peripherals.GPIO23, gpio::Level::Low, output_config);
|
|
||||||
let rst_output = gpio::Output::new(peripherals.GPIO7, gpio::Level::High, output_config);
|
|
||||||
let _ = gpio::Output::new(peripherals.GPIO0, gpio::Level::High, output_config); // backlight
|
|
||||||
|
|
||||||
let mut display_delay = delay::Delay::new();
|
let mut screen = screen::Handler::new(display, width, height);
|
||||||
|
|
||||||
let spi_device = embedded_hal_bus::spi::ExclusiveDevice::new_no_delay(spi, cs)
|
let _ = screen
|
||||||
.expect("Failed to initialize SPI device");
|
.update(screen::ScreenState::Initial)
|
||||||
|
.inspect_err(log_screen_error);
|
||||||
|
|
||||||
let display = mipidsi::Builder::new(
|
screen
|
||||||
mipidsi::models::ST7789,
|
|
||||||
mipidsi::interface::SpiInterface::new(spi_device, dc_output, &mut spi_buffer),
|
|
||||||
)
|
|
||||||
.display_size(DISPLAY_HEIGHT + 34, DISPLAY_WIDTH) // somehow this display has 34 px of invisible space on the left (in native orientation)
|
|
||||||
.reset_pin(rst_output)
|
|
||||||
.invert_colors(mipidsi::options::ColorInversion::Inverted)
|
|
||||||
.orientation(mipidsi::options::Orientation::new().rotate(mipidsi::options::Rotation::Deg90))
|
|
||||||
.init(&mut display_delay)
|
|
||||||
.expect("Failed to initialize display");
|
|
||||||
|
|
||||||
screen::Handler::new(display, DISPLAY_WIDTH, DISPLAY_HEIGHT)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "screen")]
|
|
||||||
let _ = screen
|
|
||||||
.update(screen::ScreenState::Initial)
|
|
||||||
.inspect_err(log_screen_error);
|
|
||||||
|
|
||||||
// Setup WiFi
|
// Setup WiFi
|
||||||
let (mut wifi_controller, interfaces) = esp_radio::wifi::new(
|
let (mut wifi_controller, interfaces) = esp_radio::wifi::new(
|
||||||
peripherals.WIFI,
|
peripherals.WIFI,
|
||||||
|
|
@ -155,7 +134,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
let mac = esp_hal::efuse::base_mac_address();
|
let mac = esp_hal::efuse::base_mac_address();
|
||||||
info!("WiFi MAC: {mac}");
|
info!("WiFi MAC: {mac}");
|
||||||
|
|
||||||
// Seeed XIAO L67K:
|
// Setup GNSS: Seeed XIAO L67K:
|
||||||
// RX: D7/ GPIO12
|
// RX: D7/ GPIO12
|
||||||
// TX: D6/ GPIO11
|
// TX: D6/ GPIO11
|
||||||
// WAKEUP: D0/ GPIO1 -> HIGH for active, LOW for Sleep
|
// WAKEUP: D0/ GPIO1 -> HIGH for active, LOW for Sleep
|
||||||
|
|
@ -376,36 +355,6 @@ async fn gnss_task(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the SPI interface for the ST7789 display
|
|
||||||
///
|
|
||||||
/// Returns (spi master, chip-select) tuple or SPI config error
|
|
||||||
#[cfg(feature = "screen")]
|
|
||||||
fn setup_st7789_spi(
|
|
||||||
scl: esp_hal::peripherals::GPIO8<'static>,
|
|
||||||
sda: esp_hal::peripherals::GPIO10<'static>,
|
|
||||||
cs: esp_hal::peripherals::GPIO24<'static>,
|
|
||||||
miso: esp_hal::peripherals::GPIO9<'static>,
|
|
||||||
spi: esp_hal::peripherals::SPI2<'static>,
|
|
||||||
) -> Result<
|
|
||||||
(
|
|
||||||
spi::master::Spi<'static, esp_hal::Blocking>,
|
|
||||||
gpio::Output<'static>,
|
|
||||||
),
|
|
||||||
spi::master::ConfigError,
|
|
||||||
> {
|
|
||||||
let spi_config = spi::master::Config::default()
|
|
||||||
.with_frequency(time::Rate::from_mhz(40))
|
|
||||||
.with_mode(spi::Mode::_0);
|
|
||||||
let spi: spi::master::Spi<'_, esp_hal::Blocking> = spi::master::Spi::new(spi, spi_config)?
|
|
||||||
.with_sck(scl)
|
|
||||||
.with_mosi(sda)
|
|
||||||
.with_miso(miso);
|
|
||||||
|
|
||||||
let cs_output = gpio::Output::new(cs, gpio::Level::High, gpio::OutputConfig::default());
|
|
||||||
|
|
||||||
Ok((spi, cs_output))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "screen")]
|
#[cfg(feature = "screen")]
|
||||||
fn log_screen_error<E>(error: &E)
|
fn log_screen_error<E>(error: &E)
|
||||||
where
|
where
|
||||||
|
|
|
||||||
120
src/screen.rs
120
src/screen.rs
|
|
@ -348,3 +348,123 @@ fn maneuver_to_str(value: applogic::v2x::map::Maneuvers) -> alloc::string::Strin
|
||||||
if value.right_allowed { ">" } else { " " },
|
if value.right_allowed { ">" } else { " " },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an [`mipidsi::Display`], width, height tuple for an ST7789 172*320px screen in landscape orientation
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Human-readable fatal errors
|
||||||
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
|
pub fn make_small_display<IoScl, IoSda, IoRes, IoDc, IoCs, IoBl, Spi>(
|
||||||
|
scl: IoScl,
|
||||||
|
sda: IoSda,
|
||||||
|
res: IoRes,
|
||||||
|
dc: IoDc,
|
||||||
|
cs: IoCs,
|
||||||
|
bl: IoBl,
|
||||||
|
spi: Spi,
|
||||||
|
spi_buffer: &mut [u8],
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
mipidsi::Display<
|
||||||
|
mipidsi::interface::SpiInterface<
|
||||||
|
'_,
|
||||||
|
embedded_hal_bus::spi::ExclusiveDevice<
|
||||||
|
esp_hal::spi::master::Spi<'_, esp_hal::Blocking>,
|
||||||
|
esp_hal::gpio::Output<'_>,
|
||||||
|
embedded_hal_bus::spi::NoDelay,
|
||||||
|
>,
|
||||||
|
esp_hal::gpio::Output<'_>,
|
||||||
|
>,
|
||||||
|
mipidsi::models::ST7789,
|
||||||
|
esp_hal::gpio::Output<'_>,
|
||||||
|
>,
|
||||||
|
u16,
|
||||||
|
u16,
|
||||||
|
),
|
||||||
|
alloc::string::String,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
IoScl: esp_hal::gpio::interconnect::PeripheralOutput<'static>,
|
||||||
|
IoSda: esp_hal::gpio::interconnect::PeripheralOutput<'static>,
|
||||||
|
IoRes:
|
||||||
|
esp_hal::gpio::interconnect::PeripheralOutput<'static> + esp_hal::gpio::OutputPin + 'static,
|
||||||
|
IoDc:
|
||||||
|
esp_hal::gpio::interconnect::PeripheralOutput<'static> + esp_hal::gpio::OutputPin + 'static,
|
||||||
|
IoCs:
|
||||||
|
esp_hal::gpio::interconnect::PeripheralOutput<'static> + esp_hal::gpio::OutputPin + 'static,
|
||||||
|
IoBl:
|
||||||
|
esp_hal::gpio::interconnect::PeripheralOutput<'static> + esp_hal::gpio::OutputPin + 'static,
|
||||||
|
Spi: esp_hal::spi::master::Instance + 'static,
|
||||||
|
{
|
||||||
|
const DISPLAY_WIDTH: u16 = 320;
|
||||||
|
const DISPLAY_HEIGHT: u16 = 172;
|
||||||
|
const DISPLAY_HIDDEN_X: u16 = 34; // somehow this display has 34 px of invisible space on the left (in native orientation)
|
||||||
|
|
||||||
|
let (spi, cs) = setup_st7789_spi(scl, sda, cs, spi)
|
||||||
|
.map_err(|err| alloc::format!("Failed to build SPI config: {err}"))?;
|
||||||
|
|
||||||
|
let output_config = esp_hal::gpio::OutputConfig::default();
|
||||||
|
let dc_output = esp_hal::gpio::Output::new(dc, esp_hal::gpio::Level::Low, output_config);
|
||||||
|
let rst_output = esp_hal::gpio::Output::new(res, esp_hal::gpio::Level::High, output_config);
|
||||||
|
let _ = esp_hal::gpio::Output::new(bl, esp_hal::gpio::Level::High, output_config); // enable backlight
|
||||||
|
|
||||||
|
let mut display_delay = esp_hal::delay::Delay::new();
|
||||||
|
|
||||||
|
let spi_device = embedded_hal_bus::spi::ExclusiveDevice::new_no_delay(spi, cs)
|
||||||
|
.map_err(|err| alloc::format!("Failed to initialize SPI device: {err}"))?;
|
||||||
|
|
||||||
|
let display = mipidsi::Builder::new(
|
||||||
|
mipidsi::models::ST7789,
|
||||||
|
mipidsi::interface::SpiInterface::new(spi_device, dc_output, spi_buffer),
|
||||||
|
)
|
||||||
|
.display_size(DISPLAY_HEIGHT + DISPLAY_HIDDEN_X, DISPLAY_WIDTH)
|
||||||
|
.reset_pin(rst_output)
|
||||||
|
.invert_colors(mipidsi::options::ColorInversion::Inverted)
|
||||||
|
.orientation(mipidsi::options::Orientation::new().rotate(mipidsi::options::Rotation::Deg90))
|
||||||
|
.init(&mut display_delay)
|
||||||
|
.map_err(|err| alloc::format!("Failed to initialize display: {err:?}"))?;
|
||||||
|
|
||||||
|
Ok((display, DISPLAY_WIDTH, DISPLAY_HEIGHT))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds the SPI interface for the ST7789 display
|
||||||
|
///
|
||||||
|
/// Returns (spi master, chip-select) tuple
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns SPI config error when SPI setup failed
|
||||||
|
fn setup_st7789_spi<IoScl, IoSda, IoCs, Spi>(
|
||||||
|
scl: IoScl,
|
||||||
|
sda: IoSda,
|
||||||
|
cs: IoCs,
|
||||||
|
spi: Spi,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
esp_hal::spi::master::Spi<'static, esp_hal::Blocking>,
|
||||||
|
esp_hal::gpio::Output<'static>,
|
||||||
|
),
|
||||||
|
esp_hal::spi::master::ConfigError,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
IoScl: esp_hal::gpio::interconnect::PeripheralOutput<'static>,
|
||||||
|
IoSda: esp_hal::gpio::interconnect::PeripheralOutput<'static>,
|
||||||
|
IoCs:
|
||||||
|
esp_hal::gpio::interconnect::PeripheralOutput<'static> + esp_hal::gpio::OutputPin + 'static,
|
||||||
|
Spi: esp_hal::spi::master::Instance + 'static,
|
||||||
|
{
|
||||||
|
let spi_config = esp_hal::spi::master::Config::default()
|
||||||
|
.with_frequency(esp_hal::time::Rate::from_mhz(40))
|
||||||
|
.with_mode(esp_hal::spi::Mode::_0);
|
||||||
|
let spi: esp_hal::spi::master::Spi<'_, esp_hal::Blocking> =
|
||||||
|
esp_hal::spi::master::Spi::new(spi, spi_config)?
|
||||||
|
.with_sck(scl)
|
||||||
|
.with_mosi(sda);
|
||||||
|
|
||||||
|
let cs_output = esp_hal::gpio::Output::new(
|
||||||
|
cs,
|
||||||
|
esp_hal::gpio::Level::High,
|
||||||
|
esp_hal::gpio::OutputConfig::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((spi, cs_output))
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue