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 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 crate::at_commands::{ATCommand, StubATCommand};
#[derive(Clone)]
pub struct Button {
was_pressed: Rc<Mutex<RefCell<bool>>>,
is_pressed: Rc<Mutex<RefCell<bool>>>,
presses: Rc<Mutex<RefCell<u32>>>,
#[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,
}
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 {
Self {
was_pressed: Rc::new(Mutex::new(RefCell::new(Default::default()))),
@ -22,31 +46,49 @@ impl Default for Button {
}
}
impl Button {
pub unsafe fn set_pressed(&self, pressed: bool) {
impl Keypad {
pub fn handle_presses(&self, presses: BTreeSet<KeypadButton>) {
critical_section::with(|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 presses = self.presses.borrow_ref_mut(cs);
*was_pressed = *is_pressed;
*is_pressed = pressed;
if !*was_pressed && *is_pressed {
*presses += 1;
let mut num_presses = self.presses.borrow_ref_mut(cs);
*was_pressed = is_pressed.clone();
*is_pressed = presses;
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| {
let presses = self.presses.borrow_ref(cs);
*presses
let is_pressed = self.is_pressed.borrow_ref(cs);
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) {
critical_section::with(|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 {
at_command: Rc<Mutex<RefCell<Option<ConstructedATCommand>>>>,
at_response: Rc<Mutex<RefCell<Option<String>>>>,
pub button: Button,
pub keypad: Keypad,
}
impl Default for AsyncIO {
@ -74,7 +116,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: Default::default(),
keypad: Keypad::default(),
}
}
}

View File

@ -10,7 +10,7 @@
use core::mem::MaybeUninit;
use alloc::{boxed::Box, vec::Vec};
use alloc::{boxed::Box, collections::btree_set::BTreeSet, vec::Vec};
use esp_hal::{
clock::CpuClock,
delay::Delay,
@ -28,7 +28,7 @@ use esp_hal::{
use esp_backtrace as _;
use crate::{
async_io::AsyncIO,
async_io::{AsyncIO, KeypadButton},
at_commands::ATCommands,
display::{Display, Position, Rgb565, SetAddressMode},
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] = [
[
KeypadButton::Keypad1,
@ -260,7 +241,7 @@ fn thread_2_main(
log::info!("Event: {}", event);
}
let mut buttons_pressed = Vec::new();
let mut buttons_pressed = BTreeSet::new();
loop {
let keypad_data = sx1509.read_keypad();
@ -276,11 +257,11 @@ fn thread_2_main(
if buttons_pressed.contains(&button) {
break;
}
buttons_pressed.push(button);
buttons_pressed.insert(button);
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 => {}
}
self.data.io.button.clear();
self.data.io.keypad.clear();
}
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 crate::{
async_io::ATPromise,
async_io::{ATPromise, KeypadButton},
at_commands::{
ATCommand, ATInformationCommand, CheckPinCommand, EnterPinCommand, SMSFormat,
SelectSMSFormatCommand, SetTECharsetCommand, TECharset,
@ -124,7 +124,7 @@ pub struct TextState {
impl State for TextState {
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 }))
} else {
None
@ -152,7 +152,7 @@ pub struct ButtonTestState {
impl State for ButtonTestState {
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
}