selection menu works for multiple binaries, and shows selection box

This commit is contained in:
2025-09-18 17:43:49 -06:00
parent 4f93ee4e9d
commit bf359f0513
4 changed files with 45 additions and 44 deletions

View File

@@ -17,6 +17,7 @@ rp235x = ["embassy-rp/rp235xb"]
trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"] trouble = ["dep:bt-hci", "dep:cyw43", "dep:cyw43-pio", "dep:trouble-host"]
defmt = [ defmt = [
"dep:defmt", "dep:defmt",
"shared/defmt",
"panic-probe/print-defmt", "panic-probe/print-defmt",
"embassy-executor/defmt", "embassy-executor/defmt",
"embassy-time/defmt", "embassy-time/defmt",

View File

@@ -18,8 +18,6 @@ mod ui;
mod usb; mod usb;
mod utils; mod utils;
use core::sync::atomic::{AtomicBool, Ordering};
use crate::{ use crate::{
display::{FRAMEBUFFER, display_handler, init_display}, display::{FRAMEBUFFER, display_handler, init_display},
peripherals::{ peripherals::{
@@ -31,6 +29,7 @@ use crate::{
ui::{SELECTIONS, clear_selection, ui_handler}, ui::{SELECTIONS, clear_selection, ui_handler},
}; };
use abi_sys::EntryFn; use abi_sys::EntryFn;
use alloc::string::String;
use embedded_graphics::{ use embedded_graphics::{
pixelcolor::Rgb565, pixelcolor::Rgb565,
prelude::{DrawTarget, RgbColor}, prelude::{DrawTarget, RgbColor},
@@ -38,6 +37,7 @@ use embedded_graphics::{
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
use core::sync::atomic::{AtomicBool, Ordering};
use defmt::unwrap; use defmt::unwrap;
use embassy_executor::{Executor, Spawner}; use embassy_executor::{Executor, Spawner};
use embassy_futures::{join::join, select::select}; use embassy_futures::{join::join, select::select};

View File

@@ -6,7 +6,10 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
use embassy_time::Timer; use embassy_time::Timer;
use embedded_graphics::{ use embedded_graphics::{
Drawable, Drawable,
mono_font::{MonoTextStyle, ascii::FONT_9X15}, mono_font::{
MonoTextStyle,
ascii::{FONT_9X15, FONT_10X20},
},
pixelcolor::Rgb565, pixelcolor::Rgb565,
prelude::{Dimensions, Point, Primitive, RgbColor, Size}, prelude::{Dimensions, Point, Primitive, RgbColor, Size},
primitives::{PrimitiveStyle, Rectangle}, primitives::{PrimitiveStyle, Rectangle},
@@ -14,8 +17,7 @@ use embedded_graphics::{
}; };
use embedded_layout::{ use embedded_layout::{
align::{horizontal, vertical}, align::{horizontal, vertical},
layout::linear::LinearLayout, layout::linear::{FixedMargin, LinearLayout},
object_chain::Chain,
prelude::*, prelude::*,
}; };
use embedded_text::TextBox; use embedded_text::TextBox;
@@ -29,19 +31,18 @@ pub async fn ui_handler() {
if let Some(event) = keyboard::read_keyboard_fifo().await { if let Some(event) = keyboard::read_keyboard_fifo().await {
if let KeyState::Pressed = event.state { if let KeyState::Pressed = event.state {
match event.key { match event.key {
KeyCode::JoyUp => { KeyCode::Up => {
let mut selections = SELECTIONS.lock().await; let mut selections = SELECTIONS.lock().await;
selections.up(); selections.up();
} }
KeyCode::JoyDown => { KeyCode::Down => {
let mut selections = SELECTIONS.lock().await; let mut selections = SELECTIONS.lock().await;
selections.down(); selections.down();
} }
KeyCode::Enter | KeyCode::JoyRight => { KeyCode::Enter | KeyCode::Right => {
let selections = SELECTIONS.lock().await; let selections = SELECTIONS.lock().await;
let selection = selections.selections let selection =
[selections.current_selection as usize - 1] selections.selections[selections.current_selection as usize].clone();
.clone();
let entry = unsafe { load_binary(&selection.short_name).await.unwrap() }; let entry = unsafe { load_binary(&selection.short_name).await.unwrap() };
BINARY_CH.send(entry).await; BINARY_CH.send(entry).await;
@@ -56,8 +57,6 @@ pub async fn ui_handler() {
clear_selection().await; clear_selection().await;
draw_selection().await; draw_selection().await;
} }
Timer::after_millis(50).await;
} }
} }
@@ -73,12 +72,10 @@ pub async fn clear_selection() {
} }
async fn draw_selection() { async fn draw_selection() {
let file_names: Vec<FileName> = { let mut guard = SELECTIONS.lock().await;
let guard = SELECTIONS.lock().await; let file_names = &guard.selections.clone();
guard.selections.clone()
};
let text_style = MonoTextStyle::new(&FONT_9X15, Rgb565::WHITE); let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let display_area = unsafe { FRAMEBUFFER.bounding_box() }; let display_area = unsafe { FRAMEBUFFER.bounding_box() };
const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory"; const NO_BINS: &str = "No Programs found on SD Card. Ensure programs end with '.bin', and are located in the root directory";
@@ -96,37 +93,37 @@ async fn draw_selection() {
.draw(unsafe { &mut FRAMEBUFFER }) .draw(unsafe { &mut FRAMEBUFFER })
.unwrap(); .unwrap();
} else { } else {
let mut file_names = file_names.iter(); let mut views: alloc::vec::Vec<Text<MonoTextStyle<Rgb565>>> = Vec::new();
let Some(first) = file_names.next() else {
Text::new(NO_BINS, Point::zero(), text_style)
.draw(unsafe { &mut FRAMEBUFFER })
.unwrap();
return; for i in file_names {
}; views.push(Text::new(&i.long_name, Point::zero(), text_style));
}
let chain = Chain::new(Text::new(&first.long_name, Point::zero(), text_style)); let views_group = Views::new(views.as_mut_slice());
// for _ in 0..file_names.len() { let layout = LinearLayout::vertical(views_group)
// let chain = chain.append(Text::new(
// file_names.next().unwrap(),
// Point::zero(),
// text_style,
// ));
// }
let layout = LinearLayout::vertical(chain)
.with_alignment(horizontal::Center) .with_alignment(horizontal::Center)
.with_spacing(FixedMargin(5))
.arrange() .arrange()
.align_to(&display_area, horizontal::Center, vertical::Center); .align_to(&display_area, horizontal::Center, vertical::Center);
SELECTIONS.lock().await.last_bounds = Some(layout.bounds()); // draw selected box
let selected_bounds = layout
.inner()
.get(guard.current_selection as usize)
.expect("Selected binary missing")
.bounding_box();
Rectangle::new(selected_bounds.top_left, selected_bounds.size)
.into_styled(PrimitiveStyle::with_stroke(Rgb565::WHITE, 1))
.draw(unsafe { &mut FRAMEBUFFER })
.unwrap();
guard.last_bounds = Some(layout.bounds());
layout.draw(unsafe { &mut FRAMEBUFFER }).unwrap(); layout.draw(unsafe { &mut FRAMEBUFFER }).unwrap();
} }
let mut sel = SELECTIONS.lock().await; guard.changed = false;
sel.changed = false;
} }
#[derive(Clone)] #[derive(Clone)]
@@ -167,15 +164,17 @@ impl SelectionList {
self.changed = true; self.changed = true;
} }
fn down(&mut self) { fn up(&mut self) {
if self.current_selection + 1 < self.selections.len() as u16 { if self.current_selection > 0 {
self.current_selection += 1 self.current_selection -= 1;
self.changed = true;
} }
} }
fn up(&mut self) { fn down(&mut self) {
if self.current_selection > self.selections.len() as u16 { if self.current_selection + 1 < self.selections.len() as u16 {
self.current_selection -= 1 self.current_selection += 1;
self.changed = true;
} }
} }
} }

View File

@@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[features] [features]
default = []
defmt = ["dep:defmt"] defmt = ["dep:defmt"]
[dependencies] [dependencies]