use fugit::HertzU32;
use micromath::F32Ext as _;
use crate::interrupt::Interrupt;
#[cfg_attr(not(sci_b), path = "uart/sci.rs")]
#[cfg_attr(sci_b, path = "uart/sci_b.rs")]
pub(crate) mod sci;
#[allow(private_bounds)]
pub trait TransferMode: SealedTransferMode {}
trait SealedTransferMode {}
pub struct Async {
rx_int: Interrupt,
tx_int: Interrupt,
}
impl TransferMode for Async {}
impl SealedTransferMode for Async {}
pub struct Blocking {}
impl TransferMode for Blocking {}
impl SealedTransferMode for Blocking {}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Copy, Clone)]
struct BaudGenConfig {
small_n: u32,
big_n: u32,
err: f32,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum DataBits {
DataBits7,
DataBits8,
DataBits9,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Parity {
Even,
Odd,
None,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum StopBits {
Stop1,
Stop2,
}
fn calc_baud_gen(baud: u32, clock: HertzU32) -> Option<BaudGenConfig> {
let semr = 64.0;
let mut big_n = 0_u32;
let mut small_n = 3_u32;
let mut best: Option<BaudGenConfig> = None;
loop {
let mut last_config: Option<BaudGenConfig> = None;
for _ in 0..256 {
let new_error = (clock.to_Hz() as f32
/ (baud as f32
* semr
* (2_f32.powi(2 * small_n as i32 - 1))
* (big_n as f32 + 1.0)))
- 1.0;
if let Some(last_config) = last_config {
if new_error.abs() > last_config.err.abs() {
break;
}
}
last_config = Some(BaudGenConfig {
small_n,
big_n,
err: new_error,
});
big_n += 1;
}
if let Some(ref mut best) = best {
if last_config.unwrap().err.abs() < best.err.abs() {
*best = last_config.unwrap();
}
} else {
best = last_config;
}
if small_n == 0 {
break;
} else {
small_n -= 1;
big_n = 0;
}
}
best
}
pub use sci::{Config, Instance, RxInterruptHandler, TeInterruptHandler, TxInterruptHandler, Uart};