diff --git a/src/at_commands.rs b/src/at_commands.rs index ec4ca18..32c2f08 100644 --- a/src/at_commands.rs +++ b/src/at_commands.rs @@ -1,19 +1,38 @@ -use alloc::format; -use alloc::string::String; +use alloc::string::{String, ToString}; use alloc::vec::Vec; +use alloc::{borrow::ToOwned, format}; use core::fmt::Write; use esp_hal::{Blocking, delay::Delay, gpio::Output, uart::Uart}; static RESPONSES: [&'static str; 3] = ["OK", "ERROR", "DOWNLOAD"]; pub struct ATCommands<'a, 'd> { - pub rst: Output<'a>, - pub pwr_key: Output<'a>, - pub uart: Uart<'d, Blocking>, - pub delay: Delay, + rst: Output<'a>, + pwr_key: Output<'a>, + uart: Uart<'d, Blocking>, + delay: Delay, + + buffer: String, + lines: Vec, } impl<'a, 'd> ATCommands<'a, 'd> { + pub fn new( + rst: Output<'a>, + pwr_key: Output<'a>, + uart: Uart<'d, Blocking>, + ) -> ATCommands<'a, 'd> { + ATCommands { + rst, + pwr_key, + uart, + delay: Delay::new(), + + buffer: String::new(), + lines: Vec::new(), + } + } + pub fn init(&mut self) { self.pwr_key.set_low(); self.delay.delay_millis(1_000); @@ -38,11 +57,12 @@ impl<'a, 'd> ATCommands<'a, 'd> { pub fn raw_command(&mut self, command: String) -> String { self.uart.flush().unwrap(); self.flush_rx(); - self.uart.write_str(&(command.clone() + "\r")).unwrap(); + let command = command.clone() + "\r"; + self.uart.write_str(&command).unwrap(); self.uart.flush().unwrap(); self.delay.delay_millis(500); log::info!("Wrote command {}", command); - self.read_response() + self.read_response(command) } pub fn raw_two_part_command(&mut self, command: String, additional: String) -> String { @@ -52,55 +72,86 @@ impl<'a, 'd> ATCommands<'a, 'd> { self.uart.flush().unwrap(); self.delay.delay_millis(500); log::info!("Wrote command {}", command); - log::info!("{}", self.flush_rx()); + self.flush_rx(); - self.uart.write_str(&(additional.clone() + "\x1A")).unwrap(); + let text = additional.clone() + "\x1A"; + self.uart.write_str(&text).unwrap(); self.uart.flush().unwrap(); - self.read_response() + self.read_response(text) } - fn read_response(&mut self) -> String { - let mut buffer = [0u8; 1024]; + pub fn readline(&mut self) -> Option { + self.flush_rx(); + if self.lines.len() > 0 { + Some(self.lines.remove(0)) + } else { + None + } + } - let mut contents = String::new(); - - while { - let parts: Vec<&str> = contents.split("\r\n").collect(); - !RESPONSES - .iter() - .any(|r| parts.iter().any(|p| p.contains(r))) - } { - let length = self.uart.read(&mut buffer).unwrap(); - contents += str::from_utf8(&buffer[..length]).unwrap(); - log::info!("Contents so far: {}", contents); + fn read_response(&mut self, start: String) -> String { + let mut response = None; + while response.is_none() { + self.flush_rx(); + response = self.parse_response(&start); } - let parts: Vec<&str> = contents.split("\r\n").collect(); - let (idx, _) = parts - .iter() - .enumerate() - .find(|(_, part)| RESPONSES.iter().any(|r| part.contains(r))) - .unwrap(); - parts - .into_iter() - .take(idx + 1) - .collect::>() - .join("\n") + response.unwrap() } - pub fn flush_rx(&mut self) -> String { + fn parse_response(&mut self, start: &String) -> Option { + let start_idx = self + .lines + .iter() + .enumerate() + .find(|(_, l)| l.starts_with(start)) + .map(|(i, _)| i); + + if let Some(start_idx) = start_idx { + let mut response = String::new(); + + for (i, line) in self.lines.iter().cloned().skip(start_idx).enumerate() { + if i == 0 { + continue; + } + if response.len() > 0 { + response += "\n"; + } + response += &line; + if RESPONSES.iter().any(|r| line.starts_with(r)) { + for _ in 0..=i { + self.lines.remove(start_idx); + } + return Some(response); + } + } + } + + None + } + + pub fn flush_rx(&mut self) { let mut buffer = [0u8; 1024]; - let mut contents = String::new(); while { self.delay.delay_millis(10); self.uart.read_ready() } { let length = self.uart.read(&mut buffer).unwrap(); - contents += str::from_utf8(&buffer[..length]).unwrap(); + self.buffer += str::from_utf8(&buffer[..length]).unwrap(); } - contents + let lines = self + .buffer + .split("\n") + .map(|s| s.to_string()) + .collect::>(); + self.buffer = lines.last().unwrap().to_string(); + + let full_lines_len = lines.len() - 1; + for line in lines.into_iter().take(full_lines_len) { + self.lines.push(line); + } } } diff --git a/src/main.rs b/src/main.rs index 17bd781..3574f43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,12 +126,7 @@ fn main() -> ! { .with_rx(peripherals.GPIO7) .with_tx(peripherals.GPIO8); - let mut at_commands = ATCommands { - rst: sim_rst, - pwr_key: sim_pwr_key, - uart, - delay: Delay::new(), - }; + let mut at_commands = ATCommands::new(sim_rst, sim_pwr_key, uart); let font_renderer = FontRenderer::create(30); display.clear(Rgb565::black().as_color()); @@ -290,5 +285,9 @@ fn thread_2_main(async_io: AsyncIO, mut at_commands: ATCommands<'static, 'static }; unsafe { async_io.set_at_response(response) }; } + + if let Some(event) = at_commands.readline() { + log::info!("Event: {}", event); + } } } diff --git a/src/states.rs b/src/states.rs index 1562a36..eb72b24 100644 --- a/src/states.rs +++ b/src/states.rs @@ -44,7 +44,9 @@ impl State for InitATState { // Wait for previous AT command to finish if let Some(response) = data.io.poll_at_response() { match response { - Some(_) => {} + Some(response) => { + log::info!("Response: {}", response) + } None => {} } return None;