Initial commit
This commit is contained in:
commit
639ee2af7f
11 changed files with 1844 additions and 0 deletions
18
.cargo/config.toml
Normal file
18
.cargo/config.toml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[build]
|
||||||
|
|
||||||
|
rustflags = [
|
||||||
|
"-C", "link-arg=-nostartfiles",
|
||||||
|
]
|
||||||
|
|
||||||
|
target = "xtensa-esp32s3-none-elf"
|
||||||
|
|
||||||
|
[target.xtensa-esp32s3-none-elf]
|
||||||
|
|
||||||
|
# linker = "ldproxy"
|
||||||
|
runner = "espflash flash --monitor"
|
||||||
|
|
||||||
|
[unstable]
|
||||||
|
build-std = ["core", "panic_abort"]
|
||||||
|
|
||||||
|
[env]
|
||||||
|
MCU="esp32s3"
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
1494
Cargo.lock
generated
Normal file
1494
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
24
Cargo.toml
Normal file
24
Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "cardputer-bsc-nostd"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "s"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
debug = true # Symbols are nice and they don't increase the size on Flash
|
||||||
|
opt-level = "z"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
embedded-hal-bus = "0.3.0"
|
||||||
|
esp-hal = {version = "=1.0.0-beta.1", features = ["esp32s3", "unstable"]}
|
||||||
|
mipidsi = "0.9.0"
|
||||||
|
thiserror = {version = "2.0.11", default-features = false}
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = ["examples/*"]
|
||||||
25
examples/display_test/Cargo.toml
Normal file
25
examples/display_test/Cargo.toml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
[package]
|
||||||
|
name = "display_test"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "display_test"
|
||||||
|
harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "s"
|
||||||
|
debug = true
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
debug = true # Symbols are nice and they don't increase the size on Flash
|
||||||
|
opt-level = "z"
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cardputer-bsc-nostd = { version = "0.1.0", path = "../.." }
|
||||||
|
embedded-graphics = "0.8.1"
|
||||||
|
esp-hal = {version = "=1.0.0-beta.1", features = ["esp32s3", "unstable"]}
|
||||||
|
esp-println = { version = "0.14.0", features = ["esp32s3"] }
|
||||||
|
esp-bootloader-esp-idf = "0.1.0"
|
||||||
52
examples/display_test/build.rs
Normal file
52
examples/display_test/build.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
fn main() {
|
||||||
|
linker_be_nice();
|
||||||
|
// make sure linkall.x is the last linker script (otherwise might cause problems with flip-link)
|
||||||
|
println!("cargo:rustc-link-arg=-Tlinkall.x");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linker_be_nice() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() > 1 {
|
||||||
|
let kind = &args[1];
|
||||||
|
let what = &args[2];
|
||||||
|
|
||||||
|
match kind.as_str() {
|
||||||
|
"undefined-symbol" => match what.as_str() {
|
||||||
|
"_defmt_timestamp" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`");
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
"_stack_start" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("💡 Is the linker script `linkall.x` missing?");
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
"esp_wifi_preempt_enable"
|
||||||
|
| "esp_wifi_preempt_yield_task"
|
||||||
|
| "esp_wifi_preempt_task_create" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("💡 `esp-wifi` has no scheduler enabled. Make sure you have the `builtin-scheduler` feature enabled, or that you provide an external scheduler.");
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
"embedded_test_linker_file_not_added_to_rustflags" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("💡 `embedded-test` not found - make sure `embedded-test.x` is added as a linker script for tests");
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
// we don't have anything helpful for "missing-lib" yet
|
||||||
|
_ => {
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-link-arg=-Wl,--error-handling-script={}",
|
||||||
|
std::env::current_exe().unwrap().display()
|
||||||
|
);
|
||||||
|
}
|
||||||
89
examples/display_test/src/main.rs
Normal file
89
examples/display_test/src/main.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
|
use cardputer_bsc_nostd::display::{DISPLAY_SIZE_HEIGHT, DISPLAY_SIZE_WIDTH};
|
||||||
|
use embedded_graphics::pixelcolor::Rgb565;
|
||||||
|
use esp_hal::{
|
||||||
|
ledc::{LowSpeed, channel::ChannelIFace, timer::TimerIFace},
|
||||||
|
main,
|
||||||
|
};
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
|
println!("{info}");
|
||||||
|
esp_hal::system::software_reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_bootloader_esp_idf::esp_app_desc!();
|
||||||
|
|
||||||
|
#[main]
|
||||||
|
fn entrypoint() -> ! {
|
||||||
|
_main();
|
||||||
|
println!("main exited, entering infinite loop");
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _main() {
|
||||||
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
let mut display = cardputer_bsc_nostd::display::build(
|
||||||
|
peripherals.SPI2,
|
||||||
|
peripherals.GPIO36,
|
||||||
|
peripherals.GPIO35,
|
||||||
|
peripherals.GPIO37,
|
||||||
|
peripherals.GPIO34,
|
||||||
|
peripherals.GPIO33,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut ledc = esp_hal::ledc::Ledc::new(peripherals.LEDC);
|
||||||
|
ledc.set_global_slow_clock(esp_hal::ledc::LSGlobalClkSource::APBClk);
|
||||||
|
|
||||||
|
let mut timer = ledc.timer::<LowSpeed>(esp_hal::ledc::timer::Number::Timer3);
|
||||||
|
timer.configure(esp_hal::ledc::timer::config::Config {
|
||||||
|
duty: esp_hal::ledc::timer::config::Duty::Duty8Bit,
|
||||||
|
clock_source: esp_hal::ledc::timer::LSClockSource::APBClk,
|
||||||
|
frequency: esp_hal::time::Rate::from_hz(256),
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let mut backlight: esp_hal::ledc::channel::Channel<'_, _> =
|
||||||
|
ledc.channel(esp_hal::ledc::channel::Number::Channel7, peripherals.GPIO38);
|
||||||
|
|
||||||
|
backlight
|
||||||
|
.configure(esp_hal::ledc::channel::config::Config {
|
||||||
|
timer: &timer,
|
||||||
|
duty_pct: 100,
|
||||||
|
pin_config: esp_hal::ledc::channel::config::PinConfig::PushPull,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
display
|
||||||
|
.set_pixels(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DISPLAY_SIZE_WIDTH - 1,
|
||||||
|
DISPLAY_SIZE_HEIGHT - 1,
|
||||||
|
core::iter::repeat_n(
|
||||||
|
Rgb565::new(0, 0, 0),
|
||||||
|
DISPLAY_SIZE_WIDTH as usize * DISPLAY_SIZE_HEIGHT as usize,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
display
|
||||||
|
.set_pixels(
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
DISPLAY_SIZE_WIDTH - 21,
|
||||||
|
DISPLAY_SIZE_HEIGHT - 21,
|
||||||
|
core::iter::repeat_n(
|
||||||
|
Rgb565::new(31, 0, 0),
|
||||||
|
DISPLAY_SIZE_WIDTH as usize * DISPLAY_SIZE_HEIGHT as usize,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "esp"
|
||||||
132
src/display.rs
Normal file
132
src/display.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
//! 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)
|
||||||
|
}
|
||||||
0
src/keyboard.rs
Normal file
0
src/keyboard.rs
Normal file
7
src/lib.rs
Normal file
7
src/lib.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub mod display;
|
||||||
|
pub mod keyboard;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn main() {}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue