ra-hal 0.3.0

Hardware Abstraction Layer (HAL) for the Renesas RA family of MCUs.
//! Universal Asynchronous Receiver-Transmitter
//!
//! This module provides a UART driver for the `SCI` and `SCI_B` peripherals.

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;

/// Mode of transfer (e.g. blocking, interrupt, DMA).
#[allow(private_bounds)]
pub trait TransferMode: SealedTransferMode {}
trait SealedTransferMode {}

/// Asynchronous, interrupt driven, I/O.
pub struct Async {
    rx_int: Interrupt,
    tx_int: Interrupt,
}
impl TransferMode for Async {}
impl SealedTransferMode for Async {}

/// Blocking I/O.
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,
}

/// Word length.
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum DataBits {
    /// 7 bits.
    DataBits7,

    /// 8 bits.
    DataBits8,

    /// 9 bits.
    DataBits9,
}

/// Parity bit
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Parity {
    /// Even parity
    Even,

    /// Odd parity
    Odd,

    /// No parity bit
    None,
}

/// Number of stop bits
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum StopBits {
    /// 1 stop bit
    Stop1,

    /// 2 stop bits
    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};