334 lines
11 KiB
Rust
334 lines
11 KiB
Rust
|
//! 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>,
|
||
|
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<hal::embassy::executor::Executor> = 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<hal::gpio::Unknown, 15>,
|
||
|
gpio14: GpioPin<hal::gpio::Unknown, 14>,
|
||
|
UART1_per: UART1,
|
||
|
clocks: &Clocks<'static>
|
||
|
) -> (
|
||
|
Ingress<'static, AtDigester<modem::Urc>, 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<modem::Urc, INGRESS_BUF_SIZE, URC_CAPACITY, URC_SUBSCRIBERS> =
|
||
|
Buffers::<modem::Urc, INGRESS_BUF_SIZE, URC_CAPACITY, URC_SUBSCRIBERS>::new();
|
||
|
|
||
|
let digester = DefaultDigester::<modem::Urc>::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<u8> {
|
||
|
// 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
|
||
|
}
|