1use fugit::HertzU32;
6use micromath::F32Ext as _;
7
8use crate::interrupt::Interrupt;
9
10#[cfg_attr(not(sci_b), path = "uart/sci.rs")]
11#[cfg_attr(sci_b, path = "uart/sci_b.rs")]
12pub(crate) mod sci;
13
14#[allow(private_bounds)]
16pub trait TransferMode: SealedTransferMode {}
17trait SealedTransferMode {}
18
19pub struct Async {
21 rx_int: Interrupt,
22 tx_int: Interrupt,
23}
24impl TransferMode for Async {}
25impl SealedTransferMode for Async {}
26
27pub struct Blocking {}
29impl TransferMode for Blocking {}
30impl SealedTransferMode for Blocking {}
31
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33#[derive(Debug, Copy, Clone)]
34struct BaudGenConfig {
35 small_n: u32,
36 big_n: u32,
37 err: f32,
38}
39
40#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42#[derive(Clone, Copy, PartialEq, Eq, Debug)]
43pub enum DataBits {
44 DataBits7,
46
47 DataBits8,
49
50 DataBits9,
52}
53
54#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56#[derive(Clone, Copy, PartialEq, Eq, Debug)]
57pub enum Parity {
58 Even,
60
61 Odd,
63
64 None,
66}
67
68#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70#[derive(Clone, Copy, PartialEq, Eq, Debug)]
71pub enum StopBits {
72 Stop1,
74
75 Stop2,
77}
78
79fn calc_baud_gen(baud: u32, clock: HertzU32) -> Option<BaudGenConfig> {
80 let semr = 64.0;
81 let mut big_n = 0_u32;
82 let mut small_n = 3_u32;
83
84 let mut best: Option<BaudGenConfig> = None;
85
86 loop {
87 let mut last_config: Option<BaudGenConfig> = None;
88
89 for _ in 0..256 {
90 let new_error = (clock.to_Hz() as f32
91 / (baud as f32
92 * semr
93 * (2_f32.powi(2 * small_n as i32 - 1))
94 * (big_n as f32 + 1.0)))
95 - 1.0;
96
97 if let Some(last_config) = last_config {
98 if new_error.abs() > last_config.err.abs() {
99 break;
100 }
101 }
102
103 last_config = Some(BaudGenConfig {
104 small_n,
105 big_n,
106 err: new_error,
107 });
108 big_n += 1;
109 }
110
111 if let Some(ref mut best) = best {
112 if last_config.unwrap().err.abs() < best.err.abs() {
113 *best = last_config.unwrap();
114 }
115 } else {
116 best = last_config;
117 }
118
119 if small_n == 0 {
120 break;
121 } else {
122 small_n -= 1;
123 big_n = 0;
124 }
125 }
126
127 best
128}
129
130pub use sci::{Config, Instance, RxInterruptHandler, TeInterruptHandler, TxInterruptHandler, Uart};