//! The following wiring is setup: //! - TX => GPIO15 //! - RX => GPIO14 #![no_std] #![no_main] #![feature(type_alias_impl_trait)] #![feature(utf8_chunks)] mod modem; mod serial; extern crate alloc; use core::mem::MaybeUninit; use esp_backtrace as _; use esp_println::println; // use hal::embassy::executor::Executor; use esp_wifi::{initialize, EspWifiInitFor}; use embassy_time::{Instant, Duration}; use hal::{timer::TimerGroup, Rng}; use embassy_executor::Spawner; use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal}; use hal::{ clock::ClockControl, embassy, gpio::IO, interrupt, uart::{ config::{Config, DataBits, Parity, StopBits}, TxRxPins, }, Delay, peripherals::{Interrupt, Peripherals, UART1}, prelude::*, Uart, gpio::GpioPin, }; use hal::clock::{CpuClock, Clocks}; use esp_hal_common::uart::{config::AtCmdConfig, UartRx, UartTx}; use static_cell::make_static; use atat::{ asynch::{ AtatClient, Client, }, AtatIngress, Buffers, DefaultDigester, Ingress, AtDigester, }; #[global_allocator] static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty(); fn init_heap() { const HEAP_SIZE: usize = 32 * 1024; static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit(); unsafe { ALLOCATOR.init(HEAP.as_mut_ptr() as *mut u8, HEAP_SIZE); } } const AT_CMD: u8 = 0x04; const READ_BUF_SIZE: usize = 64; const INGRESS_BUF_SIZE: usize = 1024; const URC_CAPACITY: usize = 128; const URC_SUBSCRIBERS: usize = 3; #[embassy_executor::task] async fn ingress_task( mut ingress: Ingress< 'static, DefaultDigester, modem::Urc, INGRESS_BUF_SIZE, URC_CAPACITY, URC_SUBSCRIBERS, >, mut rx: UartRx<'static, UART1>) { log::info!("reading in ingress_task..."); ingress.read_from(&mut rx).await; } #[embassy_executor::task] async fn test_send(mut client: Client<'static, UartTx<'static, UART1>, INGRESS_BUF_SIZE>) { let mut state: u8 = 0; loop { match state { 0 => { match client.send(&modem::GetModelId).await { Ok(d) => log::info!("GetModelId Sent: {:?}", d), Err(e) => { match e { atat::Error::Timeout => log::error!("[GetModelId] - Timeout Error: {:?}", e), atat::Error::Parse => log::error!("[GetModelId] - Parse Error: Cound not parse: {:?}", e), _ => {} } }, } } 1 => { // println!("sending a single message (GetManufacturerId)"); // log::info!("sending a single message (GetManufacturerId)"); // client.send(&modem::GetManufacturerId).await.unwrap(); // log::info!("(GetManufacturerId) sent"); match client.send(&modem::GetManufacturerId).await { Ok(d) => log::info!("GetManufacturerId Sent: {:?}", d), Err(e) => { match e { atat::Error::Timeout => log::error!("[GetManufacturerId] - Timeout Error: {:?}", e), atat::Error::Parse => log::error!("[GetManufacturerId] - Parse Error: Cound not parse: {:?}", e), _ => {} } }, } } 2 => { // println!("sending a single message (GetSoftwareVersion)"); // log::info!("sending a single message (GetSoftwareVersion)"); // client.send(&modem::GetSoftwareVersion).await.unwrap(); // log::info!("(GetSoftwareVersion) sent"); match client.send(&modem::GetSoftwareVersion).await { Ok(d) => log::info!("GetSoftwareVersion Sent: {:?}", d), Err(e) => { match e { atat::Error::Timeout => log::error!("[GetSoftwareVersion] - Timeout Error: {:?}", e), atat::Error::Parse => log::error!("[GetSoftwareVersion] - Parse Error: Cound not parse: {:?}", e), _ => {} } }, } } 3 => { // println!("sending a single message (GetWifiMac)"); // log::info!("sending a single message (GetWifiMac)"); // client.send(&modem::GetWifiMac).await.unwrap(); // log::info!("(GetWifiMac) sent"); match client.send(&modem::GetWifiMac).await { Ok(d) => log::info!("GetWifiMac Sent: {:?}", d), Err(e) => { match e { atat::Error::Timeout => log::error!("[GetWifiMac] - Timeout Error: {:?}", e), atat::Error::Parse => log::error!("[GetWifiMac] - Parse Error: Cound not parse: {:?}", e), _ => {} } }, } } 4 => { // println!("sending a single message (GetAT)"); // log::info!("sending a single message (GetAT)"); // client.send(&modem::GetAT).await.unwrap(); // log::info!("(GetAT) sent"); match client.send(&modem::GetAT).await { Ok(d) => log::info!("GetAT Sent: {:?}", d), Err(e) => { match e { atat::Error::Timeout => log::error!("[GetAT] - Timeout Error: {:?}", e), atat::Error::Parse => log::error!("[GetAT] - Parse Error: Cound not parse: {:?}", e), _ => {} } }, } // log::info!("AT Command Hit"); } // _ => state = 0, _ => break, } embassy_time::Timer::after(embassy_time::Duration::from_secs(2)).await; // log::info!("{}", state); state += 1; } } pub struct LossyStr<'a>(pub &'a [u8]); impl<'a> core::fmt::Debug for LossyStr<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match core::str::from_utf8(self.0) { Ok(s) => write!(f, "{:?}", s), Err(_) => write!(f, "{:?}", self.0), } } } #[entry] fn main() -> ! { init_heap(); esp_println::logger::init_logger_from_env(); log::info!("Logger is setup"); let peripherals = Peripherals::take(); let system = peripherals.SYSTEM.split(); let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock240MHz).freeze(); let mut delay = Delay::new(&clocks); let timer_group0 = TimerGroup::new( peripherals.TIMG0, &clocks, ); embassy::init(&clocks, timer_group0.timer0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); interrupt::enable(Interrupt::UART1, interrupt::Priority::Priority1).unwrap(); let (ingress, client, rx14) = // let (tx, rx, signal) = uart_device_setup( // serial::uart_serial_setup( delay, io.pins.gpio15, io.pins.gpio14, peripherals.UART1, &clocks, ); println!("Starting embassy executor ..."); // let executor = make_static!(embassy_executor::Executor::new()); // let executor = make_static!(hal::embassy::executor::Executor::new()); static CELL: static_cell::StaticCell = static_cell::StaticCell::new(); let executor = CELL.init(hal::embassy::executor::Executor::new()); executor.run(|spawner| { let _ = spawner.spawn(ingress_task(ingress, rx14)); let _ = spawner.spawn(test_send(client)); }) } pub fn uart_device_setup( mut delay: Delay, gpio15: GpioPin, gpio14: GpioPin, UART1_per: UART1, clocks: &Clocks<'static> ) -> ( Ingress<'static, AtDigester, modem::Urc, INGRESS_BUF_SIZE, URC_CAPACITY, URC_SUBSCRIBERS>, atat::asynch::Client<'static, UartTx<'static, hal::peripherals::UART1>, INGRESS_BUF_SIZE>, UartRx<'static, UART1> ){ let modem_uart_pins = TxRxPins::new_tx_rx( gpio15.into_push_pull_output(), gpio14.into_floating_input(), ); let config = Config { baudrate: 115200, data_bits: DataBits::DataBits8, parity: Parity::ParityNone, stop_bits: StopBits::STOP1, }; // UART interface for the GSM modem let mut uart = Uart::new_with_config( UART1_per, config, Some(modem_uart_pins), &clocks, ); uart.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None)); uart.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16).unwrap(); // uart.set_rx_fifo_full_threshold(1).unwrap(); let (mut tx, mut rx) = uart.split(); static BUFFERS: Buffers = Buffers::::new(); let digester = DefaultDigester::::default(); // .with_custom_success(|buf| { // let mut mbuf = buf.to_vec(); // Make a mutable copy // let filtered_buf = filter_sequence(&mut mbuf); // let result = core::str::from_utf8(&filtered_buf);//.unwrap_or("Invalid UTF-8"); // match result { // Ok(data_str) => { // println!("Valid UTF-8:\n {}", data_str); // } // Err(e) => { // // println!("Invalid UTF-8:\n {:?}", mbuf); // println!("Invalid UTF-8:\n {:?}", e); // } // } // Ok((buf, buf.len())) // }); // Atat client let config = atat::Config::default() .flush_timeout(Duration::from_millis(2000)) .cmd_cooldown(Duration::from_millis(200)) .tx_timeout(Duration::from_millis(2000)); let (ingress, client) = BUFFERS.split( tx, digester, config, ); (ingress, client, rx) } fn filter_sequence(buf: &mut [u8]) -> &[u8] { let mut read_idx = 0; let mut write_idx = 0; while read_idx < buf.len() { let byte = buf[read_idx]; if byte != 0 && byte != 202 && byte != 61 && byte != 129 && byte != 37 { buf[write_idx] = byte; write_idx += 1; } read_idx += 1; } &buf[..write_idx] } fn replace_newline_with_ctrl_d(input_str: &[u8]) -> alloc::vec::Vec { // Byte value for Ctrl+D let ctrl_d: u8 = 4; // Replace "\n" with Ctrl+D in the input string let mut replaced_str = input_str.to_vec(); for byte in replaced_str.iter_mut() { if *byte == b'\n' { *byte = ctrl_d; } } replaced_str }