esp32-phone/src/async_io.rs
2026-06-01 20:25:20 +03:00

208 lines
5.9 KiB
Rust

use core::{cell::RefCell, marker::PhantomData};
use alloc::{
boxed::Box,
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
rc::Rc,
string::String,
vec::Vec,
};
use critical_section::Mutex;
use esp_hal::delay::Delay;
use crate::at_commands::{ATCommand, ATParseError, ATResponseParser, SimpleATCommand};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum KeypadButton {
Keypad1,
Keypad2,
Keypad3,
Keypad4,
Keypad5,
Keypad6,
Keypad7,
Keypad8,
Keypad9,
Keypad0,
KeypadStar,
KeypadHash,
KeypadA,
KeypadB,
KeypadC,
KeypadD,
}
#[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()))),
is_pressed: Rc::new(Mutex::new(RefCell::new(Default::default()))),
presses: Rc::new(Mutex::new(RefCell::new(Default::default()))),
}
}
}
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 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 is_pressed(&self, button: KeypadButton) -> bool {
critical_section::with(|cs| {
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 just_pressed_buttons(&self) -> BTreeSet<KeypadButton> {
critical_section::with(|cs| {
let presses = self.presses.borrow_ref(cs);
presses.keys().copied().collect()
})
}
pub fn clear(&self) {
critical_section::with(|cs| {
let mut presses = self.presses.borrow_ref_mut(cs);
presses.clear();
})
}
}
#[derive(Debug, Clone)]
pub enum ConstructedATCommand {
/// Single-part command
Single(String),
/// Two-part AT-command
AddInfo(String, String),
}
unsafe impl Send for ConstructedATCommand {}
unsafe impl Sync for ConstructedATCommand {}
#[derive(Clone)]
pub struct AsyncIO {
at_command: Rc<Mutex<RefCell<Option<Box<dyn SimpleATCommand>>>>>,
handling_at_command: Rc<Mutex<RefCell<bool>>>,
at_response: Rc<Mutex<RefCell<Option<Vec<String>>>>>,
pub keypad: Keypad,
}
impl Default for AsyncIO {
fn default() -> Self {
Self {
at_command: Rc::new(Mutex::new(RefCell::new(None))),
handling_at_command: Rc::new(Mutex::new(RefCell::new(false))),
at_response: Rc::new(Mutex::new(RefCell::new(None))),
keypad: Keypad::default(),
}
}
}
unsafe impl Send for AsyncIO {}
unsafe impl Sync for AsyncIO {}
#[derive(Default, Clone, Debug)]
pub struct ATPromise<T: ATCommand> {
_data: PhantomData<T>,
}
impl<T: ATCommand> ATPromise<T> {
pub fn poll(&self, io: &mut AsyncIO) -> Option<Option<Result<T::Response, ATParseError>>> {
match io.poll_at_response() {
Some(response) => match response {
Some(response) => {
let mut parser = ATResponseParser::from(response);
Some(Some(T::parse_response(&mut parser)))
}
None => Some(None),
},
None => Some(None),
}
}
}
impl AsyncIO {
pub fn send_at_command<Resp, T: ATCommand<Response = Resp> + 'static>(
&self,
command: T,
) -> Result<ATPromise<T>, ()> {
critical_section::with(|cs| {
let mut borrow = self.at_command.borrow_ref_mut(cs);
if borrow.is_some() {
return Err(());
}
*borrow = Some(Box::new(command));
Ok(ATPromise { _data: PhantomData })
})
}
pub unsafe fn check_at_command(self) -> Option<Box<dyn SimpleATCommand>> {
critical_section::with(|cs| {
let mut borrow = self.at_command.borrow_ref_mut(cs);
*self.handling_at_command.borrow_ref_mut(cs) = true;
borrow.take()
})
}
pub unsafe fn set_at_response(&self, response_str: Vec<String>) {
critical_section::with(|cs| {
*self.handling_at_command.borrow_ref_mut(cs) = false;
let mut command = self.at_command.borrow_ref_mut(cs);
let mut response = self.at_response.borrow_ref_mut(cs);
command.take();
*response = Some(response_str);
})
}
fn poll_at_response(&self) -> Option<Option<Vec<String>>> {
critical_section::with(|cs| {
let command = self.at_command.borrow_ref(cs);
let mut response = self.at_response.borrow_ref_mut(cs);
if command.is_some() || *self.handling_at_command.borrow_ref(cs) {
return Some(None);
}
if let Some(resp) = response.take() {
return Some(Some(resp));
}
None
})
}
}