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, TextMode = 1,
} }
#[derive(Clone, Default)]
pub struct Button {
was_pressed: bool,
is_pressed: bool,
presses: u32,
}
#[derive(Clone)] #[derive(Clone)]
pub struct AsyncIO { pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<ATCommand>>>>, at_command: Rc<Mutex<RefCell<Option<ATCommand>>>>,
at_response: Rc<Mutex<RefCell<Option<String>>>>, at_response: Rc<Mutex<RefCell<Option<String>>>>,
button: Rc<Mutex<RefCell<Button>>>,
} }
impl Default for AsyncIO { impl Default for AsyncIO {
@ -36,6 +44,7 @@ impl Default for AsyncIO {
Self { Self {
at_command: Rc::new(Mutex::new(RefCell::new(None))), at_command: Rc::new(Mutex::new(RefCell::new(None))),
at_response: 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 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::{ use esp_hal::{
clock::CpuClock, clock::CpuClock,
delay::Delay, delay::Delay,
gpio::{InputConfig, Level, Output, OutputConfig}, gpio::{Input, InputConfig, Level, Output, OutputConfig},
interrupt::software::SoftwareInterruptControl, interrupt::software::SoftwareInterruptControl,
main, main,
spi::master::{Config, Spi}, spi::master::{Config, Spi},
@ -39,7 +39,8 @@ use esp_backtrace as _;
use crate::{ use crate::{
async_io::AsyncIO, async_io::AsyncIO,
at_commands::ATCommands, at_commands::ATCommands,
display::{Display, SetAddressMode}, display::{Display, Position, Rgb565, SetAddressMode},
font::FontRenderer,
state::StateManager, state::StateManager,
states::InitATState, states::InitATState,
}; };
@ -142,6 +143,18 @@ fn main() -> ! {
delay: Delay::new(), 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(); at_commands.init();
let async_io = AsyncIO::default(); let async_io = AsyncIO::default();
@ -169,6 +182,11 @@ fn main() -> ! {
// let input_6 = Input::new(peripherals.GPIO26, pull_up_cfg); // let input_6 = Input::new(peripherals.GPIO26, pull_up_cfg);
// let input_7 = Input::new(peripherals.GPIO27, 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 { static mut THREAD_2_STACK: Stack<{ 30 * 1024 }> = esp_hal::system::Stack {
mem: MaybeUninit::new([0u8; 30 * 1024]), mem: MaybeUninit::new([0u8; 30 * 1024]),
}; };
@ -185,11 +203,10 @@ fn main() -> ! {
}, },
{ {
let io = async_io.clone(); 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 { loop {
state_mgr.update(); state_mgr.update();
state_mgr.draw(); 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 // 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 { loop {
if let Some(command) = unsafe { async_io.check_at_command() } { if let Some(command) = unsafe { async_io.check_at_command() } {
let response = match 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_at_response(response) };
} }
unsafe { async_io.set_button_pressed(button.is_low()) };
} }
} }

View File

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

View File

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