stm32f1-hal 0.12.2

HAL for the STM32F1 family
Documentation
mod spi1;
mod spi2;
#[cfg(feature = "connectivity")]
mod spi3;

use embedded_hal::digital::OutputPin;
use os_trait::{Mutex, OsInterface, prelude::*};

pub use crate::common::spi::*;
pub use embedded_hal::spi::{MODE_0, MODE_1, MODE_2, MODE_3};

use crate::{
    Mcu, Steal,
    afio::{RemapMode, spi_remap::*},
    fugit::NanosDurationU32,
    rcc::{Enable, GetClock, Reset},
};
use core::marker::PhantomData;

pub trait SpiInit<T> {
    fn init<OS: OsInterface>(self, mcu: &mut Mcu) -> Spi<OS, T>;
}

pub trait SpiPeriphConfig: SpiPeriph + GetClock + Enable + Reset + Steal {
    fn init_config<W: Word>(&mut self, mode: Mode, freq: KilohertzU32, master_mode: bool);
}

pub struct Spi<OS: OsInterface, T> {
    spi: T,
    _os: PhantomData<OS>,
}

impl<OS, T> Spi<OS, T>
where
    OS: OsInterface,
    T: SpiPeriphConfig,
{
    #[allow(clippy::too_many_arguments)]
    pub fn into_interrupt_sole<W: Word, REMAP: RemapMode<T>, CS: OutputPin>(
        mut self,
        pins: (
            impl SpiSckPin<REMAP>,
            impl SpiMisoPin<REMAP>,
            impl SpiMosiPin<REMAP>,
        ),
        mode: Mode,
        freq: KilohertzU32,
        cs: impl SpiCsPin<CS>,
        cs_delay: NanosDurationU32,
        max_operation: usize,
        mcu: &mut Mcu,
    ) -> (
        SpiSoleDevice<OS, CS, bus_it::SpiBus<OS, T>, W>,
        bus_it::InterruptHandler<OS, T>,
        bus_it::ErrorInterruptHandler<OS, T>,
    ) {
        let cs = cs.into_cs_pin();
        let _ = (pins.0.into_alternate(), pins.2.into_alternate());
        REMAP::remap(&mut mcu.afio);
        self.spi.init_config::<W>(mode, freq, true);
        let (bus, it, err_it) = bus_it::SpiBus::new(self.spi, freq, max_operation);
        (SpiSoleDevice::new(bus, cs, cs_delay), it, err_it)
    }

    pub fn into_interrupt_bus<REMAP: RemapMode<T>>(
        mut self,
        pins: (
            impl SpiSckPin<REMAP>,
            impl SpiMisoPin<REMAP>,
            impl SpiMosiPin<REMAP>,
        ),
        max_operation: usize,
        mcu: &mut Mcu,
    ) -> (
        SpiDeviceBuilder<OS, bus_it::SpiBus<OS, T>>,
        bus_it::InterruptHandler<OS, T>,
        bus_it::ErrorInterruptHandler<OS, T>,
    ) {
        let _ = (pins.0.into_alternate(), pins.2.into_alternate());
        REMAP::remap(&mut mcu.afio);
        let freq = 100.kHz();
        self.spi.init_config::<u8>(MODE_0, freq, true);
        let (bus, it, err_it) = bus_it::SpiBus::new(self.spi, freq, max_operation);
        (
            SpiDeviceBuilder {
                bus: Arc::new(OS::mutex(bus)),
                id: 0,
            },
            it,
            err_it,
        )
    }
}

pub struct SpiDeviceBuilder<OS: OsInterface, BUS> {
    bus: Arc<Mutex<OS, BUS>>,
    id: u8,
}

impl<OS, BUS> SpiDeviceBuilder<OS, BUS>
where
    OS: OsInterface,
    BUS: SpiBusInterface,
{
    pub fn new_device<W: Word, CS: OutputPin>(
        &mut self,
        mode: Mode,
        freq: KilohertzU32,
        cs: impl SpiCsPin<CS>,
        cs_delay: NanosDurationU32,
    ) -> SpiMutexDevice<OS, CS, BUS, W> {
        let cs = cs.into_cs_pin();
        self.id = self.id.strict_add(1);
        SpiMutexDevice::new(Arc::clone(&self.bus), cs, cs_delay, mode, freq, self.id)
    }
}

fn calculate_baud_rate(clock: HertzU32, freq: KilohertzU32) -> u8 {
    match clock / freq {
        0 => unreachable!(),
        1..=2 => 0b000,
        3..=5 => 0b001,
        6..=11 => 0b010,
        12..=23 => 0b011,
        24..=47 => 0b100,
        48..=95 => 0b101,
        96..=191 => 0b110,
        _ => 0b111,
    }
}