diff --git a/Cargo.toml b/Cargo.toml index aefbca93..9de0f491 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ libtock_low_level_debug = { path = "apis/low_level_debug" } libtock_platform = { path = "platform" } libtock_runtime = { path = "runtime" } libtock_temperature = { path = "apis/temperature" } +libtock_text_screen = { path = "apis/text_screen" } [profile.dev] panic = "abort" @@ -41,6 +42,7 @@ members = [ "apis/leds", "apis/low_level_debug", "apis/temperature", + "apis/text_screen", "panic_handlers/debug_panic", "panic_handlers/small_panic", "platform", diff --git a/apis/text_screen/Cargo.toml b/apis/text_screen/Cargo.toml new file mode 100644 index 00000000..63590d16 --- /dev/null +++ b/apis/text_screen/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "libtock_text_screen" +version = "0.1.0" +authors = ["Tock Project Developers "] +license = "MIT/Apache-2.0" +edition = "2021" +repository = "https://www.github.com/tock/libtock-rs" +description = "libtock text_screen driver" + +[dependencies] +libtock_platform = { path = "../../platform" } + +[dev-dependencies] +libtock_unittest = { path = "../../unittest" } diff --git a/apis/text_screen/src/lib.rs b/apis/text_screen/src/lib.rs new file mode 100644 index 00000000..1efe3b1a --- /dev/null +++ b/apis/text_screen/src/lib.rs @@ -0,0 +1,100 @@ +#![no_std] + +use core::cell::Cell; +use libtock_platform::{ + share::scope, subscribe::OneId, DefaultConfig, ErrorCode, Syscalls, Upcall, +}; + +pub struct TextScreen(S); + +impl TextScreen { + pub fn exists() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() + } + + pub fn turn_display_on() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, DISPLAY, 0, 0).to_result() + } + + pub fn turn_display_off() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, NO_DISPLAY, 0, 0).to_result() + } + + pub fn blink_display() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, BLINK, 0, 0).to_result() + } + + pub fn no_blink_display() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, NO_BLINK, 0, 0).to_result() + } + + pub fn show_cursor() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, SHOW_CURSOR, 0, 0).to_result() + } + + pub fn hide_cursor() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, NO_CURSOR, 0, 0).to_result() + } + + pub fn set_cursor(x: u32, y: u32) -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, SET_CURSOR, x, y).to_result() + } + + pub fn clear_display() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, CLEAR, 0, 0).to_result() + } + + pub fn home() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, HOME, 0, 0).to_result() + } + + pub fn get_resolution() -> Result<(u32, u32), ErrorCode> { + let res_cell: Cell> = Cell::new(None); + let listener = TextScreenListener(|(width, height)| { + res_cell.set(Some((width, height))); + }); + + scope(|subscribe| { + S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener)?; + + Self::get_resolution()?; + + while res_cell.get() == None { + S::yield_wait(); + } + + match res_cell.get() { + None => Err(ErrorCode::Fail), + Some((width, height)) => Ok((width, height)), + } + }) + } +} + +struct TextScreenListener(pub F); +impl Upcall> for TextScreenListener { + fn upcall(&self, _: u32, width: u32, height: u32) { + self.0((width, height)) + } +} + +// ----------------------------------------------------------------------------- +// Driver number and command IDs +// ----------------------------------------------------------------------------- + +const DRIVER_NUM: u32 = 0x90003; + +// Command IDs + +const EXISTS: u32 = 0; +const GET_RESOLUTION: u32 = 1; +const DISPLAY: u32 = 2; +const NO_DISPLAY: u32 = 3; +const BLINK: u32 = 4; +const NO_BLINK: u32 = 5; +const SHOW_CURSOR: u32 = 6; +const NO_CURSOR: u32 = 7; +const WRITE: u32 = 8; +const CLEAR: u32 = 9; +const HOME: u32 = 10; +const SET_CURSOR: u32 = 11; diff --git a/src/lib.rs b/src/lib.rs index c13b39db..e6e51c3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,3 +44,8 @@ pub mod temperature { pub type Temperature = temperature::Temperature; pub use temperature::TemperatureListener; } + +pub mod text_screen { + use libtock_text_screen as text_screen; + pub type TextScreen = text_screen::TextScreen; +}