diff --git a/src/async_io.rs b/src/async_io.rs index 3f3c8ec..e209703 100644 --- a/src/async_io.rs +++ b/src/async_io.rs @@ -3,7 +3,7 @@ use core::{cell::RefCell, marker::PhantomData}; use alloc::{rc::Rc, string::String}; use critical_section::Mutex; -use crate::at_commands::ATCommand; +use crate::at_commands::{ATCommand, StubATCommand}; #[derive(Clone)] pub struct Button { @@ -97,13 +97,17 @@ impl ATPromise { None => Some(None), } } + + pub fn downgrade(self) -> ATPromise { + ATPromise { _data: PhantomData } + } } impl AsyncIO { pub fn send_at_command>( &self, command: T, - ) -> Result<(), ()> { + ) -> Result, ()> { critical_section::with(|cs| { let mut borrow = self.at_command.borrow_ref_mut(cs); if borrow.is_some() { @@ -112,7 +116,7 @@ impl AsyncIO { *borrow = Some(command.execute()); - Ok(()) + Ok(ATPromise { _data: PhantomData }) }) } @@ -132,7 +136,7 @@ impl AsyncIO { }) } - pub fn poll_at_response(&self) -> Option> { + fn poll_at_response(&self) -> Option> { critical_section::with(|cs| { let command = self.at_command.borrow_ref(cs); let mut response = self.at_response.borrow_ref_mut(cs); diff --git a/src/at_commands.rs b/src/at_commands.rs index e12416b..a37c124 100644 --- a/src/at_commands.rs +++ b/src/at_commands.rs @@ -2,6 +2,7 @@ use alloc::string::{String, ToString}; use alloc::vec::Vec; use alloc::{borrow::ToOwned, format}; use core::fmt::Write; +use core::marker::PhantomData; use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart}; use crate::async_io::ConstructedATCommand; @@ -164,6 +165,19 @@ pub trait ATCommand: Send + Sync { fn parse_response(text: String) -> Self::Response; } +pub struct StubATCommand(()); +impl ATCommand for StubATCommand { + type Response = String; + + fn execute(&self) -> ConstructedATCommand { + panic!("Should never be called") + } + + fn parse_response(text: String) -> Self::Response { + text + } +} + pub struct ATInformationCommand; impl ATCommand for ATInformationCommand { type Response = String; diff --git a/src/states.rs b/src/states.rs index 55a1b88..12e4e71 100644 --- a/src/states.rs +++ b/src/states.rs @@ -9,9 +9,11 @@ use alloc::{ use esp_hal::time::{Duration, Instant}; use crate::{ + async_io::ATPromise, at_commands::{ ATInformationCommand, CheckPinCommand, EnterPinCommand, ListTECharacterSetsCommand, - SMSFormat, SelectSMSFormatCommand, SendSMSCommand, SetTECharsetCommand, TECharset, + SMSFormat, SelectSMSFormatCommand, SendSMSCommand, SetTECharsetCommand, StubATCommand, + TECharset, }, display::{Position, Rgb565}, font::{HorizontalAlignment, VerticalAlignment}, @@ -23,6 +25,7 @@ pub struct InitATState { message: String, dots: u8, prev_dots: Instant, + promise: Option>, } impl Default for InitATState { @@ -32,6 +35,7 @@ impl Default for InitATState { message: "Initializing AT..".to_string(), dots: 0, prev_dots: Instant::now(), + promise: None, } } } @@ -44,13 +48,16 @@ impl State for InitATState { self.prev_dots = Instant::now(); } - // Wait for previous AT command to finish - if let Some(response) = data.io.poll_at_response() { - match response { - Some(response) => { - log::info!("Response: {}", response) - } - None => {} + if let Some(promise) = &self.promise { + match promise.poll(&mut data.io) { + Some(response) => match response { + Some(response) => { + log::info!("Response: {}", response); + self.promise = None; + } + None => {} + }, + None => self.promise = None, } return None; } @@ -58,37 +65,61 @@ impl State for InitATState { // Send next AT command let res: Option> = match self.inner_state { 0 => { - data.io.send_at_command(ATInformationCommand).unwrap(); + self.promise = Some( + data.io + .send_at_command(ATInformationCommand) + .unwrap() + .downgrade(), + ); self.message = "Checking info".to_owned(); None } 1 => { - data.io - .send_at_command(EnterPinCommand("1234".to_owned())) - .unwrap(); + self.promise = Some( + data.io + .send_at_command(EnterPinCommand("1234".to_owned())) + .unwrap() + .downgrade(), + ); self.message = "Entering PIN".to_owned(); None } 2 => { - data.io.send_at_command(CheckPinCommand).unwrap(); + self.promise = Some( + data.io + .send_at_command(CheckPinCommand) + .unwrap() + .downgrade(), + ); None } 3 => { - data.io.send_at_command(ListTECharacterSetsCommand).unwrap(); + self.promise = Some( + data.io + .send_at_command(ListTECharacterSetsCommand) + .unwrap() + .downgrade(), + ); self.message = "Checking\ncharsets".to_owned(); None } 4 => { - data.io - .send_at_command(SelectSMSFormatCommand(SMSFormat::TextMode)) - .unwrap(); + self.promise = Some( + data.io + .send_at_command(SelectSMSFormatCommand(SMSFormat::TextMode)) + .unwrap() + .downgrade(), + ); self.message = "Selecting SMS\nformat".to_owned(); None } 5 => { - data.io - .send_at_command(SetTECharsetCommand(TECharset::IRA)) - .unwrap(); + self.promise = Some( + data.io + .send_at_command(SetTECharsetCommand(TECharset::IRA)) + .unwrap() + .downgrade(), + ); self.message = "Selecting SMS\nformat".to_owned(); None }