#![deny(rust_2018_compatibility)]
#![deny(rust_2018_idioms)]
#![deny(warnings)]
#![allow(clippy::multiple_crate_versions)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::unused_unit)]
#![allow(clippy::clippy::used_underscore_binding)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::unused_unit)]
#![allow(clippy::used_underscore_binding)]
#![cfg_attr(not(test), no_std)]
mod client;
mod error;
mod ingress_manager;
mod queues;
mod traits;
#[cfg(feature = "derive")]
pub use atat_derive;
#[cfg(feature = "derive")]
pub mod derive;
#[cfg(feature = "derive")]
pub use self::derive::AtatLen;
#[cfg(feature = "derive")]
pub use serde_at;
#[cfg(feature = "derive")]
pub use typenum;
#[cfg(feature = "derive")]
pub use heapless;
pub use self::client::Client;
pub use self::error::Error;
pub use self::ingress_manager::{
get_line, IngressManager, NoopUrcMatcher, UrcMatcher, UrcMatcherResult,
};
pub use self::queues::{ComQueue, ResQueue, UrcQueue};
pub use self::traits::{AtatClient, AtatCmd, AtatResp, AtatUrc};
use heapless::ArrayLength;
use queues::{
ComConsumer, ComItem, ComProducer, ResConsumer, ResItem, ResProducer, UrcConsumer, UrcItem,
UrcProducer,
};
pub mod prelude {
pub use crate::AtatClient as _atat_AtatClient;
pub use crate::AtatCmd as _atat_AtatCmd;
pub use crate::AtatResp as _atat_AtatResp;
pub use crate::AtatUrc as _atat_AtatUrc;
#[cfg(feature = "derive")]
pub use crate::AtatLen as _atat_AtatLen;
}
#[cfg(all(
feature = "log-logging",
not(any(
feature = "defmt-default",
feature = "defmt-trace",
feature = "defmt-debug",
feature = "defmt-info",
feature = "defmt-warn",
feature = "defmt-error"
))
))]
#[macro_export]
macro_rules! atat_log {
($level:ident, $($arg:tt)+) => {
log::$level!($($arg)+);
}
}
#[cfg(all(
any(
feature = "defmt-default",
feature = "defmt-trace",
feature = "defmt-debug",
feature = "defmt-info",
feature = "defmt-warn",
feature = "defmt-error"
),
not(feature = "log-logging")
))]
#[macro_export]
macro_rules! atat_log {
($level:ident, $($arg:tt)+) => {
defmt::$level!($($arg)+);
}
}
#[cfg(any(
all(
any(
feature = "defmt-default",
feature = "defmt-trace",
feature = "defmt-debug",
feature = "defmt-info",
feature = "defmt-warn",
feature = "defmt-error"
),
feature = "log-logging"
),
not(any(
any(
feature = "defmt-default",
feature = "defmt-trace",
feature = "defmt-debug",
feature = "defmt-info",
feature = "defmt-warn",
feature = "defmt-error"
),
feature = "log-logging"
))
))]
#[macro_export]
macro_rules! atat_log {
($level:ident, $($arg:tt)+) => {
();
};
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Mode {
Blocking,
NonBlocking,
Timeout,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Command {
ClearBuffer,
ForceState(ingress_manager::State),
SetLineTerm(u8),
SetFormat(u8),
SetEcho(bool),
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Config {
mode: Mode,
line_term_char: u8,
format_char: u8,
at_echo_enabled: bool,
cmd_cooldown: u32,
}
impl Default for Config {
fn default() -> Self {
Self {
mode: Mode::Blocking,
line_term_char: b'\r',
format_char: b'\n',
at_echo_enabled: true,
cmd_cooldown: 20,
}
}
}
impl Config {
#[must_use]
pub fn new(mode: Mode) -> Self {
Self {
mode,
..Self::default()
}
}
#[must_use]
pub const fn with_line_term(mut self, c: u8) -> Self {
self.line_term_char = c;
self
}
#[must_use]
pub const fn with_format_char(mut self, c: u8) -> Self {
self.format_char = c;
self
}
#[must_use]
pub const fn with_at_echo(mut self, e: bool) -> Self {
self.at_echo_enabled = e;
self
}
#[must_use]
pub const fn cmd_cooldown(mut self, ms: u32) -> Self {
self.cmd_cooldown = ms;
self
}
}
type ClientParser<Tx, T, U, BufLen, ComCapacity, ResCapacity, UrcCapacity> = (
Client<Tx, T, BufLen, ComCapacity, ResCapacity, UrcCapacity>,
IngressManager<BufLen, U, ComCapacity, ResCapacity, UrcCapacity>,
);
pub struct Queues<BufLen, ComCapacity, ResCapacity, UrcCapacity>
where
BufLen: ArrayLength<u8>,
ComCapacity: ArrayLength<ComItem>,
ResCapacity: ArrayLength<ResItem<BufLen>>,
UrcCapacity: ArrayLength<UrcItem<BufLen>>,
{
pub res_queue: (
ResProducer<BufLen, ResCapacity>,
ResConsumer<BufLen, ResCapacity>,
),
pub urc_queue: (
UrcProducer<BufLen, UrcCapacity>,
UrcConsumer<BufLen, UrcCapacity>,
),
pub com_queue: (ComProducer<ComCapacity>, ComConsumer<ComCapacity>),
}
pub struct ClientBuilder<Tx, T, U, BufLen, ComCapacity, ResCapacity, UrcCapacity> {
serial_tx: Tx,
timer: T,
config: Config,
custom_urc_matcher: Option<U>,
#[doc(hidden)]
_internal: core::marker::PhantomData<(BufLen, ComCapacity, ResCapacity, UrcCapacity)>,
}
impl<Tx, T, U, BufLen, ComCapacity, ResCapacity, UrcCapacity>
ClientBuilder<Tx, T, U, BufLen, ComCapacity, ResCapacity, UrcCapacity>
where
Tx: embedded_hal::serial::Write<u8>,
T: embedded_hal::timer::CountDown,
T::Time: From<u32>,
U: UrcMatcher<BufLen>,
BufLen: ArrayLength<u8>,
ComCapacity: ArrayLength<ComItem>,
ResCapacity: ArrayLength<ResItem<BufLen>>,
UrcCapacity: ArrayLength<UrcItem<BufLen>>,
{
pub fn new(serial_tx: Tx, timer: T, config: Config) -> Self {
Self {
serial_tx,
timer,
config,
custom_urc_matcher: None,
#[doc(hidden)]
_internal: core::marker::PhantomData,
}
}
pub fn with_custom_urc_matcher(mut self, matcher: U) -> Self {
self.custom_urc_matcher = Some(matcher);
self
}
pub fn build(
self,
queues: Queues<BufLen, ComCapacity, ResCapacity, UrcCapacity>,
) -> ClientParser<Tx, T, U, BufLen, ComCapacity, ResCapacity, UrcCapacity> {
let parser = IngressManager::with_custom_urc_matcher(
queues.res_queue.0,
queues.urc_queue.0,
queues.com_queue.1,
self.config,
self.custom_urc_matcher,
);
let client = Client::new(
self.serial_tx,
queues.res_queue.1,
queues.urc_queue.1,
queues.com_queue.0,
self.timer,
self.config,
);
(client, parser)
}
}