Add single button to async_io

This commit is contained in:
Sofia 2026-05-17 19:12:41 +03:00
parent 756ab08b74
commit a9df3bed8c
4 changed files with 98 additions and 11 deletions

View File

@ -25,10 +25,18 @@ pub enum SMSFormat {
TextMode = 1,
}
#[derive(Clone, Default)]
pub struct Button {
was_pressed: bool,
is_pressed: bool,
presses: u32,
}
#[derive(Clone)]
pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<ATCommand>>>>,
at_response: Rc<Mutex<RefCell<Option<String>>>>,
button: Rc<Mutex<RefCell<Button>>>,
}
impl Default for AsyncIO {
@ -36,6 +44,7 @@ impl Default for AsyncIO {
Self {
at_command: Rc::new(Mutex::new(RefCell::new(None))),
at_response: Rc::new(Mutex::new(RefCell::new(None))),
button: Rc::new(Mutex::new(RefCell::new(Default::default()))),
}
}
}
@ -86,4 +95,29 @@ impl AsyncIO {
None
})
}
pub unsafe fn set_button_pressed(&self, pressed: bool) {
critical_section::with(|cs| {
let mut button = self.button.borrow_ref_mut(cs);
button.was_pressed = button.is_pressed;
button.is_pressed = pressed;
if !button.was_pressed && button.is_pressed {
button.presses += 1;
}
})
}
pub fn get_button_presses(&self) -> u32 {
critical_section::with(|cs| {
let button = self.button.borrow_ref(cs);
button.presses
})
}
pub fn clear_button_presses(&self) {
critical_section::with(|cs| {
let mut button = self.button.borrow_ref_mut(cs);
button.presses = 0;
})
}
}

View File

@ -24,7 +24,7 @@ use critical_section::Mutex;
use esp_hal::{
clock::CpuClock,
delay::Delay,
gpio::{InputConfig, Level, Output, OutputConfig},
gpio::{Input, InputConfig, Level, Output, OutputConfig},
interrupt::software::SoftwareInterruptControl,
main,
spi::master::{Config, Spi},
@ -39,7 +39,8 @@ use esp_backtrace as _;
use crate::{
async_io::AsyncIO,
at_commands::ATCommands,
display::{Display, SetAddressMode},
display::{Display, Position, Rgb565, SetAddressMode},
font::FontRenderer,
state::StateManager,
states::InitATState,
};
@ -142,6 +143,18 @@ fn main() -> ! {
delay: Delay::new(),
};
let font_renderer = FontRenderer::create(30);
display.clear(Rgb565::black().as_color());
font_renderer.render(
&mut display,
"Please wait",
Position::new(120, 120),
font::HorizontalAlignment::Center,
font::VerticalAlignment::Center,
Rgb565::black(),
Rgb565::white(),
);
at_commands.init();
let async_io = AsyncIO::default();
@ -169,6 +182,11 @@ fn main() -> ! {
// let input_6 = Input::new(peripherals.GPIO26, pull_up_cfg);
// let input_7 = Input::new(peripherals.GPIO27, pull_up_cfg);
let button = Input::new(
peripherals.GPIO13,
InputConfig::default().with_pull(esp_hal::gpio::Pull::Up),
);
static mut THREAD_2_STACK: Stack<{ 30 * 1024 }> = esp_hal::system::Stack {
mem: MaybeUninit::new([0u8; 30 * 1024]),
};
@ -185,11 +203,10 @@ fn main() -> ! {
},
{
let io = async_io.clone();
|| thread_2_main(io, at_commands)
|| thread_2_main(io, at_commands, button)
},
);
let mut test_delay = Delay::new();
loop {
state_mgr.update();
state_mgr.draw();
@ -198,7 +215,7 @@ fn main() -> ! {
// for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.1.0/examples
}
fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static>) {
fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static>, button: Input) {
loop {
if let Some(command) = unsafe { async_io.check_at_command() } {
let response = match command {
@ -219,5 +236,7 @@ fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static
};
unsafe { async_io.set_at_response(response) };
}
unsafe { async_io.set_button_pressed(button.is_low()) };
}
}

View File

@ -10,10 +10,10 @@ use crate::{
#[derive(PartialEq, Eq, Clone)]
pub struct TextSettings {
h_align: HorizontalAlignment,
v_align: VerticalAlignment,
fg: Rgb565,
bg: Rgb565,
pub h_align: HorizontalAlignment,
pub v_align: VerticalAlignment,
pub fg: Rgb565,
pub bg: Rgb565,
}
impl Default for TextSettings {
@ -82,6 +82,7 @@ impl<'a> StateManager<'a> {
Some(next_state) => self.curr_state = next_state,
None => {}
}
self.data.io.clear_button_presses();
}
pub fn draw(&mut self) {

View File

@ -11,6 +11,7 @@ use esp_hal::time::{Duration, Instant};
use crate::{
async_io::{ATCommand, SMSFormat},
display::{Position, Rgb565},
font::{HorizontalAlignment, VerticalAlignment},
state::{State, StateData, TextSettings},
};
@ -110,12 +111,44 @@ pub struct TextState {
impl State for TextState {
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
data.delay.delay_millis(100);
None
if data.io.get_button_presses() > 0 {
Some(Box::new(ButtonTestState { presses: 0 }))
} else {
None
}
}
fn draw(&self, data: &mut StateData) {
data.clear_screen(Rgb565::black().as_color());
data.draw_text(&self.text, Position::new(0, 0), TextSettings::default());
data.draw_text(
"OK",
Position::new(120, 240),
TextSettings {
h_align: HorizontalAlignment::Center,
v_align: VerticalAlignment::BottomToTop,
..Default::default()
},
);
}
}
pub struct ButtonTestState {
presses: u32,
}
impl State for ButtonTestState {
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
self.presses += data.io.get_button_presses();
None
}
fn draw(&self, data: &mut StateData) {
data.clear_screen(Rgb565::black().as_color());
data.draw_text(
format!("Presses: {}", self.presses),
Position::new(0, 0),
TextSettings::default(),
);
}
}