use core::{cell::RefCell, char, marker::PhantomData}; use alloc::vec; use alloc::{ boxed::Box, collections::{btree_map::BTreeMap, btree_set::BTreeSet}, rc::Rc, string::{String, ToString}, vec::Vec, }; use critical_section::Mutex; use crate::at_commands::{ATCommand, ATError, 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>>>, is_pressed: Rc>>>, presses: Rc>>>, } 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) { 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(cs).clone(); *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); log::info!("{:?}", *button); num_presses.insert(*button, num + 1); } } *self.presses.borrow_ref_mut(cs) = num_presses; }); } 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 { critical_section::with(|cs| { let is_pressed = self.is_pressed.borrow_ref(cs); is_pressed.clone() }) } pub fn just_pressed_buttons(&self) -> BTreeSet { 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(Clone)] pub struct AsyncIO { at_command: Rc>>>>, handling_at_command: Rc>>, at_response: Rc, ATError>>>>>, 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 { _data: PhantomData, } impl ATPromise { pub fn poll(&self, io: &mut AsyncIO) -> Option> { match io.poll_at_response() { Some(response) => { log::info!("Response: {:?}", response); match response { Ok(response) => { let mut parser = ATResponseParser::from(response); Some(T::parse_response(&mut parser)) } Err(err) => Some(Err(err)), } } None => None, } } } impl AsyncIO { pub fn send_at_command + 'static>( &self, command: T, ) -> Result, ()> { 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> { 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: Result, ATError>) { 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, ATError>> { 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() { return None; } if let Some(resp) = response.take() { return Some(resp); } None }) } } #[derive(Default, Clone)] pub struct NumberInput { written: String, } impl NumberInput { pub fn poll(&mut self, io: &mut AsyncIO) -> bool { let mut wrote = false; for button in io.keypad.just_pressed_buttons() { let character = match button { KeypadButton::Keypad1 => Some('1'), KeypadButton::Keypad2 => Some('2'), KeypadButton::Keypad3 => Some('3'), KeypadButton::Keypad4 => Some('4'), KeypadButton::Keypad5 => Some('5'), KeypadButton::Keypad6 => Some('6'), KeypadButton::Keypad7 => Some('7'), KeypadButton::Keypad8 => Some('8'), KeypadButton::Keypad9 => Some('9'), KeypadButton::Keypad0 => Some('0'), _ => None, }; if let Some(character) = character { self.written += &character.to_string(); wrote = true; } } wrote } pub fn read<'s>(&'s self) -> &'s String { &self.written } } impl KeypadButton { pub fn get_chars(&self) -> Option> { match self { KeypadButton::Keypad1 => Some(vec![' ', '1']), KeypadButton::Keypad2 => Some(vec!['a', 'b', 'c', '2']), KeypadButton::Keypad3 => Some(vec!['d', 'e', 'f', '3']), KeypadButton::Keypad4 => Some(vec!['g', 'h', 'i', '4']), KeypadButton::Keypad5 => Some(vec!['j', 'k', 'l', '5']), KeypadButton::Keypad6 => Some(vec!['m', 'n', 'o', '6']), KeypadButton::Keypad7 => Some(vec!['p', 'q', 'r', 's', '7']), KeypadButton::Keypad8 => Some(vec!['t', 'u', 'v', '8']), KeypadButton::Keypad9 => Some(vec!['w', 'x', 'y', 'z', '9']), KeypadButton::Keypad0 => Some(vec![' ', '0']), KeypadButton::KeypadStar => Some(vec!['*']), KeypadButton::KeypadHash => Some(vec!['#']), _ => None, } } } #[derive(Debug, Clone)] pub struct LastPressed { key: KeypadButton, idx: usize, } impl LastPressed { pub fn increment(&mut self) { let chars = self.key.get_chars(); if let Some(chars) = chars { self.idx = (self.idx + 1) % chars.len() } } pub fn get_char(&self) -> char { self.key.get_chars().unwrap()[self.idx] } } static TEXT_KEYS: [KeypadButton; 13] = [ KeypadButton::Keypad0, KeypadButton::Keypad1, KeypadButton::Keypad2, KeypadButton::Keypad3, KeypadButton::Keypad4, KeypadButton::Keypad5, KeypadButton::Keypad6, KeypadButton::Keypad7, KeypadButton::Keypad8, KeypadButton::Keypad9, KeypadButton::Keypad0, KeypadButton::KeypadStar, KeypadButton::KeypadHash, ]; #[derive(Debug, Default, Clone)] pub struct TextInput { written: String, last_pressed: Option, } impl TextInput { pub fn poll(&mut self, io: &mut AsyncIO) -> bool { let mut wrote = false; for button in io.keypad.just_pressed_buttons() { if let Some(mut last_pressed) = self.last_pressed.take() { if last_pressed.key == button { last_pressed.increment(); self.last_pressed = Some(last_pressed); wrote = true; } else if TEXT_KEYS.contains(&button) { self.written += &last_pressed.get_char().to_string(); self.last_pressed = Some(LastPressed { key: button, idx: 0, }); wrote = true; } else if button == KeypadButton::KeypadA { self.written += &last_pressed.get_char().to_string(); wrote = true; } } else if TEXT_KEYS.contains(&button) { self.last_pressed = Some(LastPressed { key: button, idx: 0, }); wrote = true; } } wrote } pub fn read(&self) -> String { let mut written = self.written.clone(); if let Some(last_pressed) = &self.last_pressed { written += &last_pressed.get_char().to_string(); } written } }