Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
c6c13aa
Refactor button creation
issy Apr 18, 2026
760de75
Fix document access
issy Apr 18, 2026
3d522c7
Refactor display element creation
issy Apr 18, 2026
12e1d84
Comment explaining layout
issy Apr 18, 2026
6a4e5b0
Use enum to identify targeted display
issy Apr 19, 2026
faf4807
Update display layout in task
issy Apr 19, 2026
96aaafd
Add ButtonIdentifier enum
issy Apr 19, 2026
c73568d
Inject external button event channel
issy Apr 19, 2026
553daa2
Restrict drawable type
issy Apr 19, 2026
d6de978
Initialise button event channel externally
issy Apr 19, 2026
88544d7
derive Copy, Clone for enums
issy Apr 19, 2026
d52aefa
Trying to implement click event handlers
issy Apr 19, 2026
9c209b1
This still doesn't work
issy Apr 19, 2026
1ae8481
Start again
issy Apr 19, 2026
fb680cc
Working closure
issy Apr 19, 2026
f2a5e13
Nope
issy Apr 19, 2026
b59335d
Tidying
issy Apr 19, 2026
f9ea3a5
Event listener working
issy Apr 20, 2026
b4c1fc1
Working
issy Apr 20, 2026
8186ec9
Spawn async task
issy Apr 20, 2026
e617e6f
Add task content
issy Apr 20, 2026
55a520a
Take shared reference
issy Apr 20, 2026
d4bfe44
Do not drop
issy Apr 20, 2026
4b1e949
Fix lifetime
issy Apr 20, 2026
9e695e3
Accept mutable reference
issy Apr 20, 2026
f304fe7
Does this work?
issy Apr 20, 2026
2b7af8f
Logging inside task
issy Apr 20, 2026
de43cda
Cover default branch
issy Apr 20, 2026
c9d9505
Rename
issy Apr 20, 2026
2bc8dec
Share `async-channel` in workspace
issy Apr 20, 2026
c802275
Use separate button event receiver
issy Apr 20, 2026
3d03be7
Ugh
issy Apr 20, 2026
1cb1393
Fix
issy Apr 20, 2026
d98e068
Fix
issy Apr 20, 2026
e50ba54
Fix
issy Apr 20, 2026
5bf902d
Remove log lines
issy Apr 20, 2026
403c48e
Remove dummy function
issy Apr 20, 2026
c8850fd
Add util to create event listeners
issy Apr 20, 2026
1efa156
Add button event listeners
issy Apr 20, 2026
5e5a96f
Fix lifetimes
issy Apr 20, 2026
9fd2236
init logger for foundation logging
issy Apr 22, 2026
5419aa7
Revert "init logger for foundation logging"
issy Apr 22, 2026
73fd4ab
Try again with a different crate
issy Apr 22, 2026
ff4a84a
Remove unused crate
issy Apr 22, 2026
329b354
Add extra debug messages
issy Apr 22, 2026
7611fd7
Another log line
issy Apr 22, 2026
31fa7a1
Fix this
issy Apr 22, 2026
78bb2fb
Logging...
issy Apr 22, 2026
508fe91
Start to refactor button events
issy Apr 23, 2026
4b6dde9
Remove unnecessary stuff
issy Apr 23, 2026
fb28bd5
Remove log lines, add test task
issy Apr 23, 2026
a5a9e3b
Solved by moving
issy Apr 23, 2026
1db61b0
Add time source dependency for application
issy Apr 28, 2026
69c1793
Fix types
issy Apr 28, 2026
7f9a9d4
Fix time source lifetimes
issy Apr 28, 2026
94154e2
Formatting
issy Apr 28, 2026
21a3994
Add some logic for the button task
issy Apr 28, 2026
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
61 changes: 47 additions & 14 deletions firmware/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions firmware/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ heapless = { version = "0.9.2" }
static_cell = { version = "2.1.1" }
serde = { version = "1.0.228", default-features = false }
embassy-sync = { version = "0.7.2" }
async-channel = { version = "2.5.0" }
21 changes: 21 additions & 0 deletions firmware/firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
extern crate alloc;
mod midi;
mod storage;
mod time;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

Expand All @@ -26,11 +27,14 @@ use esp_backtrace as _;

use crate::storage::FakeStorageManager;

use crate::time::EmbassyTimeSource;
use core::cell::RefCell;
use display_interface_spi::SPIInterface;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_executor::Spawner;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::{Mutex, raw::NoopRawMutex};
use embassy_sync::channel::{Channel, Sender};
use embassy_time::Delay;
use embedded_graphics::draw_target::DrawTarget;
use embedded_graphics::pixelcolor::Rgb565;
Expand All @@ -42,6 +46,7 @@ use esp_hal::time::Rate;
use esp_hal::timer::timg::TimerGroup;
use esp_hal::uart::{Config as UartConfig, DataBits, Parity, StopBits, Uart, UartRx, UartTx};
use esp_hal::{Async, Blocking};
use foundation::application::channels::{ButtonEvent, ButtonEventReceiver};
use foundation::application::state::{Application, ApplicationBuilder, Displays};
use log::info;
use midi::{UartMidiReader, UartMidiWriter};
Expand All @@ -64,8 +69,11 @@ type FirmwareApplication = Application<
UartMidiReader<'static, 'static>,
UartMidiWriter<'static, 'static>,
FakeStorageManager,
EmbassyTimeSource,
>;

type ButtonEventChannel = Channel<CriticalSectionRawMutex, ButtonEvent, 64>;

static RX: StaticCell<UartRx<Async>> = StaticCell::new();
static TX: StaticCell<UartTx<Async>> = StaticCell::new();
static DISPLAY_1: StaticCell<FirmwareDisplay> = StaticCell::new();
Expand All @@ -76,7 +84,12 @@ static DISPLAYS: StaticCell<Displays<FirmwareDisplay>> = StaticCell::new();
static UART_MIDI_READER: StaticCell<UartMidiReader> = StaticCell::new();
static UART_MIDI_WRITER: StaticCell<UartMidiWriter> = StaticCell::new();
static STORAGE_MANAGER: StaticCell<FakeStorageManager> = StaticCell::new();
static BUTTON_EVENT_CHANNEL: StaticCell<ButtonEventChannel> = StaticCell::new();
static BUTTON_EVENT_SENDER: StaticCell<Sender<CriticalSectionRawMutex, ButtonEvent, 64>> =
StaticCell::new();
static BUTTON_EVENT_RECEIVER: StaticCell<ButtonEventReceiver> = StaticCell::new();
static SPI_BUS: StaticCell<Mutex<NoopRawMutex, RefCell<Spi<Blocking>>>> = StaticCell::new();
static TIME_SOURCE: StaticCell<EmbassyTimeSource> = StaticCell::new();
static APP: StaticCell<FirmwareApplication> = StaticCell::new();

#[embassy_executor::task]
Expand Down Expand Up @@ -217,12 +230,20 @@ async fn main(spawner: Spawner) -> ! {
let midi_reader = UART_MIDI_READER.init(UartMidiReader::new(rx));
let midi_writer = UART_MIDI_WRITER.init(UartMidiWriter::new(tx));
let storage_manager = STORAGE_MANAGER.init(FakeStorageManager::default());
let button_event_channel =
BUTTON_EVENT_CHANNEL.init(Channel::<CriticalSectionRawMutex, ButtonEvent, 64>::new());
// TODO: Use this in tasks later
let _button_event_sender = BUTTON_EVENT_SENDER.init(button_event_channel.sender());
let button_event_receiver = BUTTON_EVENT_RECEIVER.init(button_event_channel.receiver());
let time_source = TIME_SOURCE.init(EmbassyTimeSource::default());

let app = APP.init(
ApplicationBuilder::new()
.with_midi_reader(midi_reader)
.with_midi_writer(midi_writer)
.with_storage_manager(storage_manager)
.with_button_event_receiver(button_event_receiver)
.with_time_source(time_source)
.build(),
);

Expand Down
10 changes: 10 additions & 0 deletions firmware/firmware/src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use foundation::application::time::TimeSource;

#[derive(Default)]
pub struct EmbassyTimeSource;

impl TimeSource for EmbassyTimeSource {
fn now(&self) -> u64 {
embassy_time::Instant::now().as_millis()
}
}
3 changes: 2 additions & 1 deletion firmware/foundation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ prost = { version = "0.14.3", default-features = false, features = ["derive"] }
heapless = { workspace = true, features = ["serde"] }
serde = { workspace = true, features = ["derive"] }
log = { workspace = true }
hashbrown = { version = "0.17.0", features = ["alloc"] }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
embassy-sync = { workspace = true, features = ["log"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
async-channel = { version = "2.5.0" }
async-channel = { workspace = true }
38 changes: 34 additions & 4 deletions firmware/foundation/src/application/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ impl<T, const N: usize> AppChannel<T, N> {

pub type MidiOutChannel = AppChannel<MidiPacket, 128>;

pub enum DisplayIdentifier {
Display1,
Display2,
Display3,
Display4,
}

pub struct DisplayStateUpdateMessage {
pub(crate) display_index: i8,
pub(crate) display_identifier: DisplayIdentifier,
pub(crate) top_row_text: DisplayText,
pub(crate) top_row_color: Colour,
pub(crate) bottom_row_text: DisplayText,
Expand All @@ -62,12 +69,35 @@ pub struct DisplayStateUpdateMessage {

pub type DisplayStateUpdateChannel = AppChannel<DisplayStateUpdateMessage, 16>;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ButtonIdentifier {
Button1,
Button2,
Button3,
Button4,
Button5,
Button6,
Button7,
Button8,
}

#[derive(Debug, Copy, Clone)]
pub enum ButtonEvent {
Pressed { button_index: i8 },
Released { button_index: i8 },
Pressed { button_identifier: ButtonIdentifier },
Released { button_identifier: ButtonIdentifier },
}

pub type ButtonEventChannel = AppChannel<ButtonEvent, 16>;
#[cfg(target_arch = "wasm32")]
type Receiver<'a, T, const N: usize> = async_channel::Receiver<T>;
#[cfg(not(target_arch = "wasm32"))]
type Receiver<'a, T, const N: usize> = embassy_sync::channel::Receiver<
'a,
embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex,
T,
N,
>;

pub type ButtonEventReceiver<'a> = Receiver<'a, ButtonEvent, 64>;

// TODO: Add channel for state updates
pub enum StorageStateEvent {
Expand Down
1 change: 1 addition & 0 deletions firmware/foundation/src/application/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod channels;
pub mod state;
pub mod time;
Loading
Loading