Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/app.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Check the ui-app crate
name: ui-app

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stm32.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Check the ui-app crate
name: ui-stm32

on:
push:
Expand Down
53 changes: 32 additions & 21 deletions ui-app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
Expand Down Expand Up @@ -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,
}
}

Expand All @@ -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);
}
}
89 changes: 33 additions & 56 deletions ui-app/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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));
}

Expand Down
13 changes: 6 additions & 7 deletions ui-stm32/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
mod board;

use board::{Board, Button, Keyboard};
use ui_app::Button as ButtonId;
use ui_app::{App, Event};

use defmt::*;
Expand All @@ -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;
}
}

Expand All @@ -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()
)));

Expand Down
28 changes: 17 additions & 11 deletions ui-tauri/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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()),
_ => {}
}
}
Expand Down Expand Up @@ -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
])
Expand Down
4 changes: 2 additions & 2 deletions ui-tauri/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
</div>
<canvas id="screen" width="320" height="240"></canvas>
<div id="buttons">
<button id="ptt-button">PTT</button>
<button id="ai-button">AI</button>
<button id="button-a">A</button>
<button id="button-b">B</button>
</div>
<div id="keyboard">
<div id="row1" class="row">
Expand Down
Loading