diff --git a/.github/workflows/app.yaml b/.github/workflows/app.yaml index eaa867dc..a7623684 100644 --- a/.github/workflows/app.yaml +++ b/.github/workflows/app.yaml @@ -1,4 +1,4 @@ -name: Check the ui-app crate +name: ui-app on: push: diff --git a/.github/workflows/stm32.yaml b/.github/workflows/stm32.yaml index dad9bea6..b66d1579 100644 --- a/.github/workflows/stm32.yaml +++ b/.github/workflows/stm32.yaml @@ -1,4 +1,4 @@ -name: Check the ui-app crate +name: ui-stm32 on: push: diff --git a/ui-app/src/lib.rs b/ui-app/src/lib.rs index 00efbecc..9bf6bbc8 100644 --- a/ui-app/src/lib.rs +++ b/ui-app/src/lib.rs @@ -55,12 +55,16 @@ pub enum KeyValue { RightShift, } +#[derive(Copy, Clone, Debug, PartialEq, Format)] +pub enum Button { + A, + B, +} + #[derive(Copy, Clone, Debug, PartialEq, Format)] pub enum Event { - PttDown, - PttUp, - AiDown, - AiUp, + ButtonDown(Button), + ButtonUp(Button), KeyDown(Key, KeyValue), KeyUp(Key), } @@ -122,16 +126,16 @@ pub trait Outputs { #[derive(Debug)] pub struct App { - ptt_down: bool, - ai_down: bool, + a_down: bool, + b_down: bool, } impl App { #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { - ptt_down: false, - ai_down: false, + a_down: false, + b_down: false, } } @@ -141,26 +145,33 @@ impl App { pub fn handle(&mut self, event: Event, out: &mut impl Outputs) { match event { - Event::PttDown => { - self.ptt_down = true; - } - Event::PttUp => { - self.ptt_down = false; - } - Event::AiDown => { - self.ai_down = true; - } - Event::AiUp => { - self.ai_down = false; - } + Event::ButtonDown(button) => match button { + Button::A => { + self.a_down = true; + } + Button::B => { + self.b_down = true; + } + }, + + Event::ButtonUp(button) => match button { + Button::A => { + self.a_down = false; + } + Button::B => { + self.b_down = false; + } + }, + Event::KeyDown(_key, _value) => { out.log("key down"); } + Event::KeyUp(_key) => { out.log("key up"); } } - out.status_led().set(false, self.ptt_down, self.ai_down); + out.status_led().set(false, self.a_down, self.b_down); } } diff --git a/ui-app/tests/integration.rs b/ui-app/tests/integration.rs index 7e2b6d8b..623bb421 100644 --- a/ui-app/tests/integration.rs +++ b/ui-app/tests/integration.rs @@ -37,59 +37,36 @@ fn default_black() { } #[test] -fn ptt_button_green() { - let mut outputs = MockOutputs::default(); - let mut app = App::new(); - app.start(&mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); - - // Up should have no effect - app.handle(Event::PttUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); - - // Pushing the button should illuminate the LED - app.handle(Event::PttDown, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Green)); - - // Down should be idempotent - app.handle(Event::PttDown, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Green)); - - // Up should extinguish the LED - app.handle(Event::PttUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); - - // Up should be idempotent - app.handle(Event::PttUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); -} - -#[test] -fn ai_button_blue() { - let mut outputs = MockOutputs::default(); - let mut app = App::new(); - app.start(&mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); - - // Up should have no effect - app.handle(Event::AiUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); - - // Pushing the button should illuminate the LED - app.handle(Event::AiDown, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Blue)); - - // Down should be idempotent - app.handle(Event::AiDown, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Blue)); - - // Up should extinguish the LED - app.handle(Event::AiUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); +fn individual_buttons() { + fn individual_button(button: Button, color: Color) { + let mut outputs = MockOutputs::default(); + let mut app = App::new(); + app.start(&mut outputs); + assert_eq!(outputs.status_led.color, Some(Color::Black)); + + // Up should have no effect + app.handle(Event::ButtonUp(button), &mut outputs); + assert_eq!(outputs.status_led.color, Some(Color::Black)); + + // Pushing the button should illuminate the LED + app.handle(Event::ButtonDown(button), &mut outputs); + assert_eq!(outputs.status_led.color, Some(color)); + + // Down should be idempotent + app.handle(Event::ButtonDown(button), &mut outputs); + assert_eq!(outputs.status_led.color, Some(color)); + + // Up should extinguish the LED + app.handle(Event::ButtonUp(button), &mut outputs); + assert_eq!(outputs.status_led.color, Some(Color::Black)); + + // Up should be idempotent + app.handle(Event::ButtonUp(button), &mut outputs); + assert_eq!(outputs.status_led.color, Some(Color::Black)); + } - // Up should be idempotent - app.handle(Event::AiUp, &mut outputs); - assert_eq!(outputs.status_led.color, Some(Color::Black)); + individual_button(Button::A, Color::Green); + individual_button(Button::B, Color::Blue); } #[test] @@ -99,16 +76,16 @@ fn buttons_compose() { app.start(&mut outputs); assert_eq!(outputs.status_led.color, Some(Color::Black)); - app.handle(Event::AiDown, &mut outputs); + app.handle(Event::ButtonDown(Button::B), &mut outputs); assert_eq!(outputs.status_led.color, Some(Color::Blue)); - app.handle(Event::PttDown, &mut outputs); + app.handle(Event::ButtonDown(Button::A), &mut outputs); assert_eq!(outputs.status_led.color, Some(Color::Cyan)); - app.handle(Event::AiUp, &mut outputs); + app.handle(Event::ButtonUp(Button::B), &mut outputs); assert_eq!(outputs.status_led.color, Some(Color::Green)); - app.handle(Event::PttUp, &mut outputs); + app.handle(Event::ButtonUp(Button::A), &mut outputs); assert_eq!(outputs.status_led.color, Some(Color::Black)); } diff --git a/ui-stm32/src/main.rs b/ui-stm32/src/main.rs index f40e7469..e107889c 100644 --- a/ui-stm32/src/main.rs +++ b/ui-stm32/src/main.rs @@ -4,6 +4,7 @@ mod board; use board::{Board, Button, Keyboard}; +use ui_app::Button as ButtonId; use ui_app::{App, Event}; use defmt::*; @@ -23,12 +24,12 @@ type EventSender = Sender<'static, CriticalSectionRawMutex, Event, EVENT_QUEUE_D static EVENT_QUEUE: EventChannel = Channel::new(); #[embassy_executor::task(pool_size = 2)] -async fn monitor_button(mut button: Button, down: Event, up: Event, events: EventSender) { +async fn monitor_button(mut button: Button, id: ButtonId, events: EventSender) { loop { button.wait_for_rising_edge().await; - events.send(down).await; + events.send(Event::ButtonDown(id)).await; button.wait_for_falling_edge().await; - events.send(up).await; + events.send(Event::ButtonUp(id)).await; } } @@ -51,15 +52,13 @@ async fn main(spawner: Spawner) { // Capture button events unwrap!(spawner.spawn(monitor_button( board.ai_button.take().unwrap(), - Event::AiDown, - Event::AiUp, + ButtonId::A, EVENT_QUEUE.sender() ))); unwrap!(spawner.spawn(monitor_button( board.ptt_button.take().unwrap(), - Event::PttDown, - Event::PttUp, + ButtonId::B, EVENT_QUEUE.sender() ))); diff --git a/ui-tauri/src-tauri/src/lib.rs b/ui-tauri/src-tauri/src/lib.rs index d9cf49f3..34c088bb 100644 --- a/ui-tauri/src-tauri/src/lib.rs +++ b/ui-tauri/src-tauri/src/lib.rs @@ -5,7 +5,7 @@ use core::ops::DerefMut; use once_cell::sync::OnceCell; use std::sync::Mutex; use tauri::Emitter; -use ui_app::{App, Event, Key, KeyValue, Led, Outputs}; +use ui_app::{App, Button, Event, Key, KeyValue, Led, Outputs}; mod hactar_vaporwave; @@ -66,25 +66,31 @@ fn start() { } #[tauri::command] -fn ptt_button_press(name: &str) { - println!("PTT button event: {}", name); +fn button_a_press(name: &str) { + const DOWN: Event = Event::ButtonDown(Button::A); + const UP: Event = Event::ButtonUp(Button::A); + + println!("Button A event: {}", name); let mut board = BOARD.get().unwrap().lock().unwrap(); let mut ui_app = UI_APP.get().unwrap().lock().unwrap(); match name { - "mousedown" => ui_app.handle(Event::PttDown, board.deref_mut()), - "mouseup" => ui_app.handle(Event::PttUp, board.deref_mut()), + "mousedown" => ui_app.handle(DOWN, board.deref_mut()), + "mouseup" => ui_app.handle(UP, board.deref_mut()), _ => {} } } #[tauri::command] -fn ai_button_press(name: &str) { - println!("AI button press"); +fn button_b_press(name: &str) { + const DOWN: Event = Event::ButtonDown(Button::B); + const UP: Event = Event::ButtonUp(Button::B); + + println!("Button B event: {}", name); let mut board = BOARD.get().unwrap().lock().unwrap(); let mut ui_app = UI_APP.get().unwrap().lock().unwrap(); match name { - "mousedown" => ui_app.handle(Event::AiDown, board.deref_mut()), - "mouseup" => ui_app.handle(Event::AiUp, board.deref_mut()), + "mousedown" => ui_app.handle(DOWN, board.deref_mut()), + "mouseup" => ui_app.handle(UP, board.deref_mut()), _ => {} } } @@ -189,8 +195,8 @@ pub fn run() { }) .invoke_handler(tauri::generate_handler![ start, - ai_button_press, - ptt_button_press, + button_a_press, + button_b_press, keydown, keyup ]) diff --git a/ui-tauri/src/index.html b/ui-tauri/src/index.html index a85398fb..973177ed 100644 --- a/ui-tauri/src/index.html +++ b/ui-tauri/src/index.html @@ -18,8 +18,8 @@