1use atsamd_hal_macros::hal_cfg;
4
5use super::{BaudMode, BitOrder, CharSizeEnum, Flags, Oversampling, Parity, Status, StopBits};
6
7use crate::pac;
8use crate::sercom::Sercom;
9
10#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
11use pac::sercom0::usart::ctrla::Modeselect;
12
13#[hal_cfg("sercom0-d5x")]
14use pac::sercom0::usart_int::ctrla::Modeselect;
15
16use crate::time::Hertz;
17
18pub(super) struct Registers<S: Sercom> {
19 sercom: S,
20}
21
22unsafe impl<S: Sercom> Sync for Registers<S> {}
25
26impl<S: Sercom> Registers<S> {
27 #[inline]
29 pub(super) fn new(sercom: S) -> Self {
30 Self { sercom }
31 }
32
33 #[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
35 #[inline]
36 fn usart(&self) -> &pac::sercom0::Usart {
37 self.sercom.usart()
38 }
39
40 #[hal_cfg("sercom0-d5x")]
43 #[inline]
44 fn usart(&self) -> &pac::sercom0::UsartInt {
45 self.sercom.usart_int()
46 }
47
48 #[cfg(feature = "dma")]
49 pub(super) fn data_ptr<T>(&self) -> *mut T {
51 self.usart().data().as_ptr() as *mut _
52 }
53
54 #[inline]
56 pub(super) fn free(self) -> S {
57 self.sercom
58 }
59
60 #[inline]
62 pub(super) fn swrst(&mut self) {
63 self.usart().ctrla().write(|w| w.swrst().set_bit());
64 while self.usart().syncbusy().read().swrst().bit_is_set() {}
65 }
66
67 #[inline]
69 pub(super) fn configure_mode(&mut self) {
70 self.usart()
71 .ctrla()
72 .modify(|_, w| w.mode().variant(Modeselect::UsartIntClk));
73 }
74
75 #[inline]
77 pub(super) fn configure_pads(&mut self, rxpo: u8, txpo: u8) {
78 self.usart().ctrla().modify(|_, w| unsafe {
79 w.rxpo().bits(rxpo);
80 w.txpo().bits(txpo)
81 });
82 }
83
84 #[inline]
86 pub(super) fn set_char_size(&mut self, size: CharSizeEnum) {
87 self.usart()
88 .ctrlb()
89 .modify(|_, w| unsafe { w.chsize().bits(size as u8) });
90 }
91
92 #[inline]
94 pub(super) fn get_char_size(&self) -> CharSizeEnum {
95 let size = self.usart().ctrlb().read().chsize().bits();
96 match size {
97 0x5 => CharSizeEnum::FiveBit,
98 0x6 => CharSizeEnum::SixBit,
99 0x7 => CharSizeEnum::SevenBit,
100 0x0 => CharSizeEnum::EightBit,
101 0x1 => CharSizeEnum::NineBit,
102 _ => unreachable!(),
103 }
104 }
105
106 #[inline]
108 pub(super) fn set_bit_order(&mut self, bit_order: BitOrder) {
109 let bits = match bit_order {
110 BitOrder::MsbFirst => false,
111 BitOrder::LsbFirst => true,
112 };
113
114 self.usart().ctrla().modify(|_, w| w.dord().bit(bits));
115 }
116
117 #[inline]
119 pub(super) fn get_bit_order(&self) -> BitOrder {
120 let bits = self.usart().ctrla().read().dord().bit();
121
122 match bits {
123 false => BitOrder::MsbFirst,
124 true => BitOrder::LsbFirst,
125 }
126 }
127
128 #[inline]
130 pub(super) fn set_parity(&mut self, parity: Parity) {
131 let enabled = match parity {
134 Parity::None => false,
135 Parity::Odd => {
136 self.usart().ctrlb().modify(|_, w| w.pmode().bit(true));
137 true
138 }
139 Parity::Even => {
140 self.usart().ctrlb().modify(|_, w| w.pmode().bit(false));
141 true
142 }
143 };
144
145 self.usart()
146 .ctrla()
147 .modify(|_, w| unsafe { w.form().bits(enabled as u8) });
148 }
149
150 #[inline]
152 pub(super) fn get_parity(&self) -> Parity {
153 let form = self.usart().ctrla().read().form().bits();
154 let enabled = form == 0x1 || form == 0x5;
155
156 if !enabled {
157 return Parity::None;
158 }
159
160 let pmode = self.usart().ctrlb().read().pmode().bit();
161
162 match pmode {
163 false => Parity::Even,
164 true => Parity::Odd,
165 }
166 }
167
168 #[inline]
170 pub(super) fn set_stop_bits(&mut self, stop_bits: StopBits) {
171 let bits = match stop_bits {
172 StopBits::OneBit => false,
173 StopBits::TwoBits => true,
174 };
175
176 self.usart().ctrlb().modify(|_, w| w.sbmode().bit(bits));
177 }
178
179 #[inline]
181 pub(super) fn get_stop_bits(&self) -> StopBits {
182 let bits = self.usart().ctrlb().read().sbmode().bit();
183 match bits {
184 false => StopBits::OneBit,
185 true => StopBits::TwoBits,
186 }
187 }
188
189 #[inline]
194 pub(super) fn set_start_of_frame_detection(&mut self, enabled: bool) {
195 self.usart().ctrlb().modify(|_, w| w.sfde().bit(enabled));
196 }
197
198 #[inline]
200 pub(super) fn get_start_of_frame_detection(&self) -> bool {
201 self.usart().ctrlb().read().sfde().bit()
202 }
203
204 #[inline]
209 pub(super) fn set_collision_detection(&mut self, enabled: bool) {
210 self.usart().ctrlb().modify(|_, w| w.colden().bit(enabled));
211 }
212
213 #[inline]
215 pub(super) fn get_collision_detection(&self) -> bool {
216 self.usart().ctrlb().read().colden().bit()
217 }
218
219 #[inline]
228 pub(super) fn set_baud(&mut self, freq: Hertz, baud: Hertz, mode: BaudMode) {
229 use BaudMode::*;
230 use Oversampling::*;
231
232 let usart = self.usart();
233
234 let sampr = match mode {
235 Arithmetic(n) => match n {
236 Bits16 => 0,
237 Bits8 => 2,
238 },
239
240 Fractional(n) => match n {
241 Bits16 => 1,
242 Bits8 => 3,
243 },
244 };
245
246 usart
247 .ctrla()
248 .modify(|_, w| unsafe { w.sampr().bits(sampr) });
249
250 match mode {
251 BaudMode::Arithmetic(n) => {
252 let baud = calculate_baud_asynchronous_arithm(baud.to_Hz(), freq.to_Hz(), n as u8);
253 unsafe { usart.baud_usartfp_mode().write(|w| w.baud().bits(baud)) };
254 }
255
256 BaudMode::Fractional(n) => {
257 let (baud, frac) =
258 calculate_baud_asynchronous_fractional(baud.to_Hz(), freq.to_Hz(), n as u8);
259 unsafe {
260 usart.baud_frac_mode().write(|w| {
261 w.fp().bits(frac);
262 w.baud().bits(baud)
263 });
264 }
265 }
266 };
267 }
268
269 #[inline]
274 pub(super) fn get_baud(&self) -> (u16, BaudMode) {
275 use BaudMode::*;
276 use Oversampling::*;
277
278 let baud = self.usart().baud_usartfp_mode().read().bits();
279 let sampr = self.usart().ctrla().read().sampr().bits();
280 let mode = match sampr {
281 0 => Arithmetic(Bits16),
282 1 => Fractional(Bits16),
283 2 => Arithmetic(Bits8),
284 3 => Fractional(Bits8),
285 _ => unreachable!(),
286 };
287
288 (baud, mode)
289 }
290
291 #[inline]
297 pub(super) fn set_immediate_overflow_notification(&mut self, set: bool) {
298 self.usart().ctrla().modify(|_, w| w.ibon().bit(set));
299 }
300
301 #[inline]
303 pub(super) fn get_immediate_overflow_notification(&self) -> bool {
304 self.usart().ctrla().read().ibon().bit()
305 }
306
307 #[inline]
312 pub(super) fn set_run_in_standby(&mut self, set: bool) {
313 self.usart().ctrla().modify(|_, w| w.runstdby().bit(set));
314 }
315
316 #[inline]
318 pub(super) fn get_run_in_standby(&self) -> bool {
319 self.usart().ctrla().read().runstdby().bit()
320 }
321
322 #[inline]
327 pub(super) fn set_irda_encoding(&mut self, pulse_length: Option<u8>) {
328 match pulse_length {
329 Some(l) => {
330 self.usart().rxpl().write(|w| unsafe { w.rxpl().bits(l) });
331 self.usart().ctrlb().modify(|_, w| w.enc().bit(true));
332 }
333 None => {
334 self.usart().ctrlb().modify(|_, w| w.enc().bit(false));
335 }
336 }
337 }
338
339 #[inline]
342 pub(super) fn get_irda_encoding(&self) -> Option<u8> {
343 if self.usart().ctrlb().read().enc().bit() {
344 Some(self.usart().rxpl().read().bits())
345 } else {
346 None
347 }
348 }
349
350 #[inline]
352 pub(super) fn clear_flags(&mut self, flags: Flags) {
353 self.usart()
354 .intflag()
355 .modify(|_, w| unsafe { w.bits(flags.bits()) });
356 }
357
358 #[inline]
360 pub(super) fn read_flags(&self) -> Flags {
361 Flags::from_bits_truncate(self.usart().intflag().read().bits())
362 }
363
364 #[inline]
366 pub(super) fn enable_interrupts(&mut self, flags: Flags) {
367 self.usart()
368 .intenset()
369 .write(|w| unsafe { w.bits(flags.bits()) });
370 }
371
372 #[inline]
374 pub(super) fn disable_interrupts(&mut self, flags: Flags) {
375 self.usart()
376 .intenclr()
377 .write(|w| unsafe { w.bits(flags.bits()) });
378 }
379
380 #[inline]
382 pub(super) fn clear_status(&mut self, status: Status) {
383 self.usart()
384 .status()
385 .modify(|_, w| unsafe { w.bits(status.bits()) });
386 }
387
388 #[inline]
390 pub(super) fn read_status(&self) -> Status {
391 Status::from_bits_truncate(self.usart().status().read().bits())
392 }
393
394 #[inline]
396 pub(super) unsafe fn read_data(&mut self) -> super::DataReg {
397 self.usart().data().read().data().bits()
398 }
399
400 #[inline]
402 pub(super) unsafe fn write_data(&mut self, data: super::DataReg) {
403 self.usart().data().write(|w| w.data().bits(data))
404 }
405
406 #[inline]
410 pub(super) fn enable(&mut self, rxen: bool, txen: bool) {
411 let usart = self.usart();
412
413 if rxen {
415 usart.ctrlb().modify(|_, w| w.rxen().set_bit());
416 while usart.syncbusy().read().ctrlb().bit_is_set() {}
417 }
418
419 if txen {
421 usart.ctrlb().modify(|_, w| w.txen().set_bit());
422 while usart.syncbusy().read().ctrlb().bit_is_set() {}
423 }
424
425 self.enable_peripheral(true);
427 }
428
429 #[inline]
430 pub(super) fn disable(&mut self) {
431 let usart = self.usart();
432
433 usart.ctrlb().modify(|_, w| w.rxen().clear_bit());
435 while usart.syncbusy().read().ctrlb().bit_is_set() {}
436
437 usart.ctrlb().modify(|_, w| w.txen().clear_bit());
439 while usart.syncbusy().read().ctrlb().bit_is_set() {}
440
441 self.enable_peripheral(false);
442 }
443
444 pub(super) fn enable_peripheral(&mut self, enable: bool) {
447 self.usart().ctrla().modify(|_, w| w.enable().bit(enable));
448 while self.usart().syncbusy().read().enable().bit_is_set() {}
449 }
450}
451
452#[inline]
455fn calculate_baud_asynchronous_arithm(baudrate: u32, clk_freq: u32, n_samples: u8) -> u16 {
456 const SHIFT: u8 = 32;
457 let sample_rate = (n_samples as u64 * baudrate as u64) << SHIFT;
458 let ratio = sample_rate / clk_freq as u64;
459 let scale = (1u64 << SHIFT) - ratio;
460 let baud_calculated = (65536u64 * scale) >> SHIFT;
461 baud_calculated as u16
462}
463
464#[inline]
467fn calculate_baud_asynchronous_fractional(
468 baudrate: u32,
469 clk_freq: u32,
470 n_samples: u8,
471) -> (u16, u8) {
472 let baud_mult = (clk_freq * 8) / (n_samples as u32 * baudrate);
473 ((baud_mult / 8) as u16, (baud_mult % 8) as u8)
474}