diff --git a/rp2040-hal/src/sio.rs b/rp2040-hal/src/sio.rs index 111376b..063df57 100644 --- a/rp2040-hal/src/sio.rs +++ b/rp2040-hal/src/sio.rs @@ -12,22 +12,34 @@ //! let pins = pac.IO_BANK0.split(pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS); //! ``` use super::*; -use core::marker::PhantomData; /// Marker struct for ownership of SIO gpio bank0 pub struct SioGpioBank0 { - _private: PhantomData<u32>, + _private: (), +} + +/// Marker struct for ownership of divide/modulo module +pub struct HwDivider { + _private: (), +} + +/// Result of divide/modulo operation +pub struct DivResult<T> { + /// The remainder of divide/modulo operation + pub remainder: T, + /// The quotient of divide/modulo operation + pub quotient: T, } /// Struct containing ownership markers for managing ownership of the SIO registers. pub struct Sio { _sio: pac::SIO, - /// GPIO Bank 0 registers pub gpio_bank0: SioGpioBank0, + /// 8-cycle hardware divide/modulo module + pub hwdivider: HwDivider, // we can hand out other things here, for example: // gpio_qspi - // divider // interp0 // interp1 } @@ -37,9 +49,51 @@ impl Sio { Self { _sio: sio, - gpio_bank0: SioGpioBank0 { - _private: PhantomData, - }, + gpio_bank0: SioGpioBank0 { _private: () }, + + hwdivider: HwDivider { _private: () }, + } + } +} + +impl HwDivider { + /// Perform hardware unsigned divide/modulo operation + pub fn unsigned(&self, dividend: u32, divisor: u32) -> DivResult<u32> { + let sio = unsafe { &(*pac::SIO::ptr()) }; + sio.div_sdividend.write(|w| unsafe { w.bits(dividend) }); + + sio.div_sdivisor.write(|w| unsafe { w.bits(divisor) }); + + cortex_m::asm::delay(8); + + // Note: quotient must be read last + let remainder = sio.div_remainder.read().bits(); + let quotient = sio.div_quotient.read().bits(); + + DivResult { + remainder, + quotient, + } + } + + /// Perform hardware signed divide/modulo operation + pub fn signed(&self, dividend: i32, divisor: i32) -> DivResult<i32> { + let sio = unsafe { &(*pac::SIO::ptr()) }; + sio.div_sdividend + .write(|w| unsafe { w.bits(dividend as u32) }); + + sio.div_sdivisor + .write(|w| unsafe { w.bits(divisor as u32) }); + + cortex_m::asm::delay(8); + + // Note: quotient must be read last + let remainder = sio.div_remainder.read().bits() as i32; + let quotient = sio.div_quotient.read().bits() as i32; + + DivResult { + remainder, + quotient, } } }