Add text input
This commit is contained in:
parent
da2eb1baad
commit
b6517d2ee6
119
src/async_io.rs
119
src/async_io.rs
@ -1,5 +1,6 @@
|
||||
use core::{cell::RefCell, char, marker::PhantomData};
|
||||
|
||||
use alloc::vec;
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
|
||||
@ -8,7 +9,6 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
use critical_section::Mutex;
|
||||
use esp_hal::delay::Delay;
|
||||
|
||||
use crate::at_commands::{ATCommand, ATParseError, ATResponseParser, SimpleATCommand};
|
||||
|
||||
@ -54,16 +54,19 @@ impl Keypad {
|
||||
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);
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
@ -103,17 +106,6 @@ impl Keypad {
|
||||
}
|
||||
}
|
||||
|
||||
#[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>>>>>,
|
||||
@ -240,3 +232,104 @@ impl NumberInput {
|
||||
&self.written
|
||||
}
|
||||
}
|
||||
|
||||
impl KeypadButton {
|
||||
pub fn get_chars(&self) -> Option<Vec<char>> {
|
||||
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<LastPressed>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ use alloc::{borrow::ToOwned, format};
|
||||
use core::fmt::Write;
|
||||
use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart};
|
||||
|
||||
use crate::async_io::ConstructedATCommand;
|
||||
|
||||
static RESPONSES: [&'static str; 3] = ["OK", "ERROR", "DOWNLOAD"];
|
||||
|
||||
pub struct ATCommands<'a, 'd> {
|
||||
|
||||
@ -256,10 +256,6 @@ fn thread_2_main(
|
||||
delay.delay_millis(5);
|
||||
}
|
||||
|
||||
if buttons_pressed.len() > 0 {
|
||||
log::info!("{:?}", buttons_pressed)
|
||||
}
|
||||
|
||||
async_io.keypad.handle_presses(buttons_pressed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use alloc::{
|
||||
use esp_hal::time::{Duration, Instant};
|
||||
|
||||
use crate::{
|
||||
async_io::{ATPromise, KeypadButton, NumberInput},
|
||||
async_io::{ATPromise, KeypadButton, NumberInput, TextInput},
|
||||
at_commands::{
|
||||
ATCommand, ATInformationCommand, ATParseError, CheckPinCommand, CheckPinResult,
|
||||
EnterPinCommand, EnterPinResult, SMSFormat, SelectSMSFormatCommand, SendSMSCommand,
|
||||
@ -307,13 +307,12 @@ impl State for PhoneNumberState {
|
||||
|
||||
pub struct MessageState {
|
||||
number: String,
|
||||
input: NumberInput,
|
||||
input: TextInput,
|
||||
}
|
||||
|
||||
impl State for MessageState {
|
||||
fn update(&mut self, data: &mut StateData) -> Option<Box<dyn State>> {
|
||||
self.input.poll(&mut data.io);
|
||||
|
||||
if !self.input.poll(&mut data.io) {
|
||||
if data.io.keypad.get_presses(KeypadButton::KeypadA) > 0 {
|
||||
Some(Box::new(ATCommandState::with(
|
||||
"Sending SMS..".to_owned(),
|
||||
@ -339,6 +338,9 @@ impl State for MessageState {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, data: &mut StateData) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user