diff --git a/Cargo.lock b/Cargo.lock index 454ca00..2166dcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "arrform" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7cf566ecc5c9d82b973e81d30babf6583c9b497f86295c952d538c3254ef4e6" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -805,6 +811,27 @@ dependencies = [ "embedded-io", ] +[[package]] +name = "embedded-layout" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a90553247f2b05c59ac7894ea13d830636c2b1203fa03bff400eddbd1fa9f52" +dependencies = [ + "embedded-graphics", + "embedded-layout-macros", +] + +[[package]] +name = "embedded-layout-macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f6e621fe4c7e05b695274b722dc0a60bacd1c8696b58191baa0154713d52400" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "embedded-sdmmc" version = "0.8.0" @@ -1871,7 +1898,10 @@ dependencies = [ name = "shared" version = "0.1.0" dependencies = [ + "arrform", "embedded-graphics", + "embedded-graphics-core", + "embedded-layout", ] [[package]] @@ -1886,6 +1916,7 @@ version = "0.1.0" dependencies = [ "embedded-graphics", "embedded-graphics-simulator", + "embedded-layout", "shared", ] diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 24e73ca..54d9cac 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -4,4 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] +arrform = "0.1.1" embedded-graphics = "0.8.1" +embedded-graphics-core = "0.4.0" +embedded-layout = "0.4.2" diff --git a/shared/src/lib.rs b/shared/src/lib.rs index da31938..ba4f420 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -1,106 +1,74 @@ -#![feature(ascii_char)] +pub mod screen { + use arrform::{ArrForm, arrform}; + use embedded_graphics::{ + Drawable, + draw_target::DrawTarget, + mono_font::{MonoTextStyle, ascii::FONT_10X20}, + pixelcolor::Rgb565, + prelude::{Point, RgbColor, Size}, + primitives::Rectangle, + text::Text, + }; + use embedded_layout::{ + align::{horizontal, vertical}, + layout::linear::LinearLayout, + prelude::*, + }; -use embedded_graphics::{ - mono_font::{ - MonoFont, MonoTextStyle, - ascii::{FONT_6X9, FONT_10X20}, - }, - pixelcolor::{BinaryColor, Rgb565}, - prelude::{Point, WebColors, *}, - primitives::{Circle, Line, PrimitiveStyle, Rectangle}, - text::{Alignment, Baseline, Text, TextStyle}, -}; + pub const SCREEN_WIDTH: usize = 320; + pub const SCREEN_HEIGHT: usize = 320; -pub const SCREEN_WIDTH: usize = 320; -pub const SCREEN_HEIGHT: usize = 320; -const SCREEN_ROWS: usize = 15; -const SCREEN_COLS: usize = 31; -const FONT: MonoFont = FONT_10X20; -const COLOR: Rgb565 = Rgb565::CSS_LAWN_GREEN; + pub const STATUS_BAR_WIDTH: usize = 320; + pub const STATUS_BAR_HEIGHT: usize = 40; -pub struct Cursor { - x: u16, - y: u16, -} - -impl Cursor { - fn new(x: u16, y: u16) -> Self { - Self { x, y } - } -} - -pub struct TextBuffer { - grid: [[Option; SCREEN_COLS]; SCREEN_ROWS], - cursor: Cursor, -} - -impl TextBuffer { - pub fn new() -> Self { - Self { - grid: [[None; SCREEN_COLS]; SCREEN_ROWS], - cursor: Cursor { x: 0, y: 0 }, - } + pub struct UI { + pub status_bar: StatusBar, } - /// writes char at cursor - pub fn write_char(&mut self, ch: char) { - for (i, row) in self.grid.iter_mut().enumerate() { - for (j, col) in row.iter_mut().enumerate() { - if i as u16 == self.cursor.x && j as u16 == self.cursor.y { - *col = Some(ch) - } + impl UI { + pub fn new() -> Self { + Self { + status_bar: StatusBar { + battery: 100, + backlight: 100, + volume: 100, + }, } } - } - /// fills text buffer with char - pub fn fill(&mut self, ch: char) { - for i in 0..SCREEN_ROWS { - for j in 0..SCREEN_COLS { - self.cursor = Cursor::new(i as u16, j as u16); - self.write_char(ch); - } + pub fn draw_status_bar>(&mut self, target: &mut D) { + let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); + + let status_bar = Rectangle::new( + Point::new(0, 0), + Size::new(STATUS_BAR_WIDTH as u32, STATUS_BAR_HEIGHT as u32), + ); + let _ = LinearLayout::horizontal( + Chain::new(Text::new( + arrform!(20, "Bat: {}", self.status_bar.battery).as_str(), + Point::zero(), + text_style, + )) + .append(Text::new( + arrform!(20, "Lght: {}", self.status_bar.backlight).as_str(), + Point::zero(), + text_style, + )) + .append(Text::new( + arrform!(20, "Vol: {}", self.status_bar.volume).as_str(), + Point::zero(), + text_style, + )), + ) + .arrange() + .align_to(&status_bar, horizontal::Center, vertical::Center) + .draw(target); } } - pub fn scroll_up(&mut self) { - let (top, bottom) = self.grid.split_at_mut(SCREEN_ROWS - 1); - for (dest, src) in top.iter_mut().zip(&bottom[1..]) { - dest.copy_from_slice(src); - } - - self.grid[SCREEN_ROWS - 1].fill(None); - } - - pub fn draw>(&mut self, target: &mut D) { - let style = MonoTextStyle::new(&FONT, COLOR); - - let char_width = FONT.character_size.width as i32; - let char_height = FONT.character_size.height as i32; - - let matrix_width = SCREEN_COLS as i32 * char_width; - let matrix_height = SCREEN_ROWS as i32 * char_height; - - let offset_x = (SCREEN_WIDTH as i32 - matrix_width) / 2; - let offset_y = (SCREEN_HEIGHT as i32 - matrix_height) / 2; - - for (i, row) in self.grid.iter().enumerate() { - for (j, col) in row[1..].iter().enumerate() { - if let Some(ch) = col { - let pos = Point::new( - offset_x + (j as i32) * char_width, - offset_y + (i as i32) * char_height, - ); - - let _ = Text::with_baseline( - ch.as_ascii().unwrap().as_str(), - pos, - style, - Baseline::Top, - ) - .draw(target); - } - } - } + pub struct StatusBar { + pub battery: u8, + pub backlight: u8, + pub volume: u8, } } diff --git a/simulator/Cargo.toml b/simulator/Cargo.toml index 1743861..8818868 100644 --- a/simulator/Cargo.toml +++ b/simulator/Cargo.toml @@ -6,4 +6,5 @@ edition = "2024" [dependencies] embedded-graphics = "0.8.1" embedded-graphics-simulator = "0.7.0" +embedded-layout = "0.4.2" shared = { path = "../shared" } diff --git a/simulator/src/main.rs b/simulator/src/main.rs index 9ef62c9..e98399d 100644 --- a/simulator/src/main.rs +++ b/simulator/src/main.rs @@ -1,29 +1,17 @@ -#![feature(ascii_char)] - -use embedded_graphics::{ - geometry::Size, - mono_font::{ - MonoFont, MonoTextStyle, - ascii::{FONT_6X9, FONT_10X20}, - }, - pixelcolor::{BinaryColor, Rgb565}, - prelude::{Point, WebColors, *}, - primitives::{Circle, Line, PrimitiveStyle, Rectangle}, - text::{Alignment, Baseline, Text, TextStyle}, -}; +use embedded_graphics::{pixelcolor::Rgb565, prelude::Size}; use embedded_graphics_simulator::{ BinaryColorTheme, OutputSettingsBuilder, SimulatorDisplay, Window, }; -use shared::{SCREEN_HEIGHT, SCREEN_WIDTH, TextBuffer}; +use shared::screen::{SCREEN_HEIGHT, SCREEN_WIDTH, UI}; fn main() -> Result<(), core::convert::Infallible> { let mut display = SimulatorDisplay::::new(Size::new(SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32)); - let mut textbuffer = TextBuffer::new(); - textbuffer.fill('A'); - textbuffer.draw(&mut display); + let mut ui = UI::new(); + + ui.draw_status_bar(&mut display); let output_settings = OutputSettingsBuilder::new().build(); Window::new("Hello World", &output_settings).show_static(&display);