Add Keypad to AsyncIO

This commit is contained in:
Sofia 2026-05-29 21:55:18 +03:00
parent f3e0080f8e
commit 2380fbee6d
4 changed files with 71 additions and 48 deletions

View File

@ -1,18 +1,42 @@
use core::{cell::RefCell, marker::PhantomData}; use core::{cell::RefCell, marker::PhantomData};
use alloc::{rc::Rc, string::String}; use alloc::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
rc::Rc,
string::String,
vec::Vec,
};
use critical_section::Mutex; use critical_section::Mutex;
use crate::at_commands::{ATCommand, StubATCommand}; use crate::at_commands::{ATCommand, StubATCommand};
#[derive(Clone)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Button { pub enum KeypadButton {
was_pressed: Rc<Mutex<RefCell<bool>>>, Keypad1,
is_pressed: Rc<Mutex<RefCell<bool>>>, Keypad2,
presses: Rc<Mutex<RefCell<u32>>>, Keypad3,
Keypad4,
Keypad5,
Keypad6,
Keypad7,
Keypad8,
Keypad9,
KeypadStar,
KeypadHash,
KeypadA,
KeypadB,
KeypadC,
KeypadD,
} }
impl Default for Button { #[derive(Clone)]
pub struct Keypad {
was_pressed: Rc<Mutex<RefCell<BTreeSet<KeypadButton>>>>,
is_pressed: Rc<Mutex<RefCell<BTreeSet<KeypadButton>>>>,
presses: Rc<Mutex<RefCell<BTreeMap<KeypadButton, u32>>>>,
}
impl Default for Keypad {
fn default() -> Self { fn default() -> Self {
Self { Self {
was_pressed: Rc::new(Mutex::new(RefCell::new(Default::default()))), was_pressed: Rc::new(Mutex::new(RefCell::new(Default::default()))),
@ -22,31 +46,49 @@ impl Default for Button {
} }
} }
impl Button { impl Keypad {
pub unsafe fn set_pressed(&self, pressed: bool) { pub fn handle_presses(&self, presses: BTreeSet<KeypadButton>) {
critical_section::with(|cs| { critical_section::with(|cs| {
let mut was_pressed = self.was_pressed.borrow_ref_mut(cs); let mut was_pressed = self.was_pressed.borrow_ref_mut(cs);
let mut is_pressed = self.is_pressed.borrow_ref_mut(cs); let mut is_pressed = self.is_pressed.borrow_ref_mut(cs);
let mut presses = self.presses.borrow_ref_mut(cs); let mut num_presses = self.presses.borrow_ref_mut(cs);
*was_pressed = *is_pressed;
*is_pressed = pressed; *was_pressed = is_pressed.clone();
if !*was_pressed && *is_pressed { *is_pressed = presses;
*presses += 1; for button in is_pressed.iter() {
if !was_pressed.contains(button) {
let num = num_presses.get(button).copied().unwrap_or(0);
num_presses.insert(*button, num + 1);
} }
}
});
}
pub fn get_presses(&self, button: KeypadButton) -> u32 {
critical_section::with(|cs| {
let presses = self.presses.borrow_ref(cs);
presses.get(&button).copied().unwrap_or(0)
}) })
} }
pub fn get_presses(&self) -> u32 { pub fn is_pressed(&self, button: KeypadButton) -> bool {
critical_section::with(|cs| { critical_section::with(|cs| {
let presses = self.presses.borrow_ref(cs); let is_pressed = self.is_pressed.borrow_ref(cs);
*presses is_pressed.contains(&button)
})
}
pub fn pressed_buttons(&self) -> BTreeSet<KeypadButton> {
critical_section::with(|cs| {
let is_pressed = self.is_pressed.borrow_ref(cs);
is_pressed.clone()
}) })
} }
pub fn clear(&self) { pub fn clear(&self) {
critical_section::with(|cs| { critical_section::with(|cs| {
let mut presses = self.presses.borrow_ref_mut(cs); let mut presses = self.presses.borrow_ref_mut(cs);
*presses = 0; presses.clear();
}) })
} }
} }
@ -66,7 +108,7 @@ unsafe impl Sync for ConstructedATCommand {}
pub struct AsyncIO { pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<ConstructedATCommand>>>>, at_command: Rc<Mutex<RefCell<Option<ConstructedATCommand>>>>,
at_response: Rc<Mutex<RefCell<Option<String>>>>, at_response: Rc<Mutex<RefCell<Option<String>>>>,
pub button: Button, pub keypad: Keypad,
} }
impl Default for AsyncIO { impl Default for AsyncIO {
@ -74,7 +116,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: Default::default(), keypad: Keypad::default(),
} }
} }
} }

View File

@ -10,7 +10,7 @@
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use alloc::{boxed::Box, vec::Vec}; use alloc::{boxed::Box, collections::btree_set::BTreeSet, vec::Vec};
use esp_hal::{ use esp_hal::{
clock::CpuClock, clock::CpuClock,
delay::Delay, delay::Delay,
@ -28,7 +28,7 @@ use esp_hal::{
use esp_backtrace as _; use esp_backtrace as _;
use crate::{ use crate::{
async_io::AsyncIO, async_io::{AsyncIO, KeypadButton},
at_commands::ATCommands, at_commands::ATCommands,
display::{Display, Position, Rgb565, SetAddressMode}, display::{Display, Position, Rgb565, SetAddressMode},
font::FontRenderer, font::FontRenderer,
@ -192,25 +192,6 @@ fn main() -> ! {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum KeypadButton {
Keypad1,
Keypad2,
Keypad3,
Keypad4,
Keypad5,
Keypad6,
Keypad7,
Keypad8,
Keypad9,
KeypadStar,
KeypadHash,
KeypadA,
KeypadB,
KeypadC,
KeypadD,
}
static KEYPAD_BUTTONS: [[KeypadButton; 4]; 4] = [ static KEYPAD_BUTTONS: [[KeypadButton; 4]; 4] = [
[ [
KeypadButton::Keypad1, KeypadButton::Keypad1,
@ -260,7 +241,7 @@ fn thread_2_main(
log::info!("Event: {}", event); log::info!("Event: {}", event);
} }
let mut buttons_pressed = Vec::new(); let mut buttons_pressed = BTreeSet::new();
loop { loop {
let keypad_data = sx1509.read_keypad(); let keypad_data = sx1509.read_keypad();
@ -276,11 +257,11 @@ fn thread_2_main(
if buttons_pressed.contains(&button) { if buttons_pressed.contains(&button) {
break; break;
} }
buttons_pressed.push(button); buttons_pressed.insert(button);
delay.delay_millis(5); delay.delay_millis(5);
} }
log::info!("Pressed: {:?}", buttons_pressed); async_io.keypad.handle_presses(buttons_pressed);
} }
} }

View File

@ -85,7 +85,7 @@ impl<'a> StateManager<'a> {
} }
None => {} None => {}
} }
self.data.io.button.clear(); self.data.io.keypad.clear();
} }
pub fn draw(&mut self) { pub fn draw(&mut self) {

View File

@ -4,7 +4,7 @@ use alloc::{borrow::ToOwned, boxed::Box, format, string::String};
use esp_hal::time::{Duration, Instant}; use esp_hal::time::{Duration, Instant};
use crate::{ use crate::{
async_io::ATPromise, async_io::{ATPromise, KeypadButton},
at_commands::{ at_commands::{
ATCommand, ATInformationCommand, CheckPinCommand, EnterPinCommand, SMSFormat, ATCommand, ATInformationCommand, CheckPinCommand, EnterPinCommand, SMSFormat,
SelectSMSFormatCommand, SetTECharsetCommand, TECharset, SelectSMSFormatCommand, SetTECharsetCommand, TECharset,
@ -124,7 +124,7 @@ 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>> {
if data.io.button.get_presses() > 0 { if data.io.keypad.get_presses(KeypadButton::KeypadA) > 0 {
Some(Box::new(ButtonTestState { presses: 0 })) Some(Box::new(ButtonTestState { presses: 0 }))
} else { } else {
None None
@ -152,7 +152,7 @@ pub struct ButtonTestState {
impl State for ButtonTestState { impl State for ButtonTestState {
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> { fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
self.presses += data.io.button.get_presses(); self.presses += data.io.keypad.get_presses(KeypadButton::KeypadA);
None None
} }