Skip to content

Commit

Permalink
i2c remap
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Oct 6, 2024
1 parent 93ed6c4 commit dea145b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 55 deletions.
79 changes: 56 additions & 23 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,53 +85,72 @@ impl From<Hertz> for Mode {
}
}

pub struct SclSda<SCL, SDA> {
pub scl: SCL,
pub sda: SDA,
}

impl<SCL, SDA> From<(SCL, SDA)> for SclSda<SCL, SDA> {
fn from(value: (SCL, SDA)) -> Self {
Self {
scl: value.0,
sda: value.1,
}
}
}

pub mod i2c1 {
use crate::afio::MAPR;

use super::*;

remap! {
Pins: [
No, PB6, PB7 => MAPR { |_, w| w.i2c1_remap().bit(false) };
Remap, PB8, PB9 => MAPR { |_, w| w.i2c1_remap().bit(true) };
[
PB6, PB7 => MAPR { |_, w| w.i2c1_remap().bit(false) };
PB8, PB9 => MAPR { |_, w| w.i2c1_remap().bit(true) };
]
}
}
pub mod i2c2 {
use super::*;

remap! {
Pins: [
No, PB10, PB11;
[
PB10, PB11;
]
}
}

macro_rules! remap {
($name:ident: [
$($rname:ident, $SCL:ident, $SDA:ident $( => $MAPR:ident { $remapex:expr })?;)+
([
$($SCL:ident, $SDA:ident $( => $MAPR:ident { $remapex:expr })?;)+
]) => {
pub enum $name {
pub enum Scl {
$(
$rname { scl: gpio::$SCL<Alternate<OpenDrain>>, sda: gpio::$SDA<Alternate<OpenDrain>> },
$SCL(gpio::$SCL<Alternate<OpenDrain>>),
)+
}
pub enum Sda {
$(
$SDA(gpio::$SDA<Alternate<OpenDrain>>),
)+
}

$(
impl From<(gpio::$SCL<Alternate<OpenDrain>>, gpio::$SDA<Alternate<OpenDrain>> $(, &mut $MAPR)?)> for $name {
impl From<(gpio::$SCL<Alternate<OpenDrain>>, gpio::$SDA<Alternate<OpenDrain>> $(, &mut $MAPR)?)> for SclSda<Scl, Sda> {
fn from(p: (gpio::$SCL<Alternate<OpenDrain>>, gpio::$SDA<Alternate<OpenDrain>> $(, &mut $MAPR)?)) -> Self {
$(p.2.modify_mapr($remapex);)?
Self::$rname { scl: p.0, sda: p.1 }
Self { scl: Scl::$SCL(p.0), sda: Sda::$SDA(p.1) }
}
}

impl From<(gpio::$SCL, gpio::$SDA $(, &mut $MAPR)?)> for $name {
impl From<(gpio::$SCL, gpio::$SDA $(, &mut $MAPR)?)> for SclSda<Scl, Sda> {
fn from(p: (gpio::$SCL, gpio::$SDA $(, &mut $MAPR)?)) -> Self {
let mut cr = Cr;
let scl = p.0.into_mode(&mut cr);
let sda = p.1.into_mode(&mut cr);
$(p.2.modify_mapr($remapex);)?
Self::$rname { scl, sda }
Self { scl: Scl::$SCL(scl), sda: Sda::$SDA(sda) }
}
}
)+
Expand All @@ -140,12 +159,17 @@ macro_rules! remap {
use remap;

pub trait I2cExt: Sized + Instance {
fn i2c(self, pins: impl Into<Self::Pins>, mode: impl Into<Mode>, clocks: &Clocks) -> I2c<Self>;
fn i2c(
self,
pins: impl Into<SclSda<Self::Scl, Self::Sda>>,
mode: impl Into<Mode>,
clocks: &Clocks,
) -> I2c<Self>;

#[allow(clippy::too_many_arguments)]
fn blocking_i2c(
self,
pins: impl Into<Self::Pins>,
pins: impl Into<SclSda<Self::Scl, Self::Sda>>,
mode: impl Into<Mode>,
clocks: &Clocks,
start_timeout_us: u32,
Expand All @@ -164,37 +188,45 @@ pub trait I2cExt: Sized + Instance {
}

impl<I2C: Instance> I2cExt for I2C {
fn i2c(self, pins: impl Into<Self::Pins>, mode: impl Into<Mode>, clocks: &Clocks) -> I2c<Self> {
fn i2c(
self,
pins: impl Into<SclSda<Self::Scl, Self::Sda>>,
mode: impl Into<Mode>,
clocks: &Clocks,
) -> I2c<Self> {
I2c::new(self, pins, mode, clocks)
}
}

/// I2C peripheral operating in master mode
pub struct I2c<I2C: Instance> {
i2c: I2C,
pins: I2C::Pins,
pins: (I2C::Scl, I2C::Sda),
mode: Mode,
pclk1: Hertz,
}

pub trait Instance:
crate::Sealed + Deref<Target = crate::pac::i2c1::RegisterBlock> + Enable + Reset + BusClock
{
type Pins;
type Scl;
type Sda;
}

impl Instance for I2C1 {
type Pins = i2c1::Pins;
type Scl = i2c1::Scl;
type Sda = i2c1::Sda;
}
impl Instance for I2C2 {
type Pins = i2c2::Pins;
type Scl = i2c2::Scl;
type Sda = i2c2::Sda;
}

impl<I2C: Instance> I2c<I2C> {
/// Creates a generic I2C object
pub fn new(
i2c: I2C,
pins: impl Into<I2C::Pins>,
pins: impl Into<SclSda<I2C::Scl, I2C::Sda>>,
mode: impl Into<Mode>,
clocks: &Clocks,
) -> Self {
Expand All @@ -206,10 +238,11 @@ impl<I2C: Instance> I2c<I2C> {
let pclk1 = I2C::clock(clocks);

assert!(mode.get_frequency() <= kHz(400));
let pins = pins.into();

let mut i2c = I2c {
i2c,
pins: pins.into(),
pins: (pins.scl, pins.sda),
mode,
pclk1,
};
Expand Down Expand Up @@ -284,7 +317,7 @@ impl<I2C: Instance> I2c<I2C> {
}

/// Releases the I2C peripheral and associated pins
pub fn release(self) -> (I2C, I2C::Pins) {
pub fn release(self) -> (I2C, (I2C::Scl, I2C::Sda)) {
(self.i2c, self.pins)
}
}
2 changes: 1 addition & 1 deletion src/i2c/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<I2C: Instance> BlockingI2c<I2C> {
#[allow(clippy::too_many_arguments)]
pub fn new(
i2c: I2C,
pins: impl Into<I2C::Pins>,
pins: impl Into<SclSda<I2C::Scl, I2C::Sda>>,
mode: impl Into<Mode>,
clocks: &Clocks,
start_timeout_us: u32,
Expand Down
54 changes: 23 additions & 31 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,80 +100,72 @@ pub mod usart1 {
use super::*;

remap! {
Tx, Rx, [
PA9, PA10 => { |_, w| w.usart1_remap().bit(false) };
PB6, PB7 => { |_, w| w.usart1_remap().bit(true) };
]
PA9, PA10 => { |_, w| w.usart1_remap().bit(false) };
PB6, PB7 => { |_, w| w.usart1_remap().bit(true) };
}
}

pub mod usart2 {
use super::*;

remap! {
Tx, Rx, [
PA2, PA3 => { |_, w| w.usart2_remap().bit(false) };
PD5, PD6 => { |_, w| w.usart2_remap().bit(true) };
]
PA2, PA3 => { |_, w| w.usart2_remap().bit(false) };
PD5, PD6 => { |_, w| w.usart2_remap().bit(true) };
}
}

pub mod usart3 {
use super::*;

remap! {
Tx, Rx, [
PB10, PB11 => { |_, w| unsafe { w.usart3_remap().bits(0b00)} };
PC10, PC11 => { |_, w| unsafe { w.usart3_remap().bits(0b01)} };
PD8, PD9 => { |_, w| unsafe { w.usart3_remap().bits(0b11)} };
]
PB10, PB11 => { |_, w| unsafe { w.usart3_remap().bits(0b00)} };
PC10, PC11 => { |_, w| unsafe { w.usart3_remap().bits(0b01)} };
PD8, PD9 => { |_, w| unsafe { w.usart3_remap().bits(0b11)} };
}
}

macro_rules! remap {
($txonly:ident, $rxonly:ident, [
$($TX:ident, $RX:ident => { $remapex:expr };)+
]) => {
pub enum $txonly<Otype> {
($($TX:ident, $RX:ident => { $remapex:expr };)+) => {
pub enum Tx<Otype> {
$(
$TX(gpio::$TX<Alternate<Otype>>),
)+
None(NoPin<Otype>),
}
pub enum $rxonly<PULL> {
pub enum Rx<PULL> {
$(
$RX(gpio::$RX<Input<PULL>>),
)+
None(NoPin<PULL>),
}

impl<'a, Otype, PULL> From<$txonly<Otype>> for TxRx<$txonly<Otype>, $rxonly<PULL>>
impl<'a, Otype, PULL> From<Tx<Otype>> for TxRx<Tx<Otype>, Rx<PULL>>
where
PULL: InMode,
{
fn from(p: $txonly<Otype>) -> Self {
Self { tx: p, rx: $rxonly::<PULL>::None(NoPin::new()) }
fn from(p: Tx<Otype>) -> Self {
Self { tx: p, rx: Rx::<PULL>::None(NoPin::new()) }
}
}

impl<'a, Otype, PULL> From<$rxonly<PULL>> for TxRx<$txonly<Otype>, $rxonly<PULL>>
impl<'a, Otype, PULL> From<Rx<PULL>> for TxRx<Tx<Otype>, Rx<PULL>>
where
PULL: InMode,
{
fn from(p: $rxonly<PULL>) -> Self {
Self { rx: p, tx: $txonly::<Otype>::None(NoPin::new()) }
fn from(p: Rx<PULL>) -> Self {
Self { rx: p, tx: Tx::<Otype>::None(NoPin::new()) }
}
}

$(
impl<Otype, PULL: InMode> From<(gpio::$TX<Alternate<Otype>>, gpio::$RX<Input<PULL>>, &mut MAPR)> for TxRx<$txonly<Otype>, $rxonly<PULL>> {
impl<Otype, PULL: InMode> From<(gpio::$TX<Alternate<Otype>>, gpio::$RX<Input<PULL>>, &mut MAPR)> for TxRx<Tx<Otype>, Rx<PULL>> {
fn from(p: (gpio::$TX<Alternate<Otype>>, gpio::$RX<Input<PULL>>, &mut MAPR)) -> Self {
p.2.modify_mapr($remapex);
Self { tx: $txonly::$TX(p.0), rx: $rxonly::$RX(p.1) }
Self { tx: Tx::$TX(p.0), rx: Rx::$RX(p.1) }
}
}

impl<Otype, PULL> From<(gpio::$TX, gpio::$RX, &mut MAPR)> for TxRx<$txonly<Otype>, $rxonly<PULL>>
impl<Otype, PULL> From<(gpio::$TX, gpio::$RX, &mut MAPR)> for TxRx<Tx<Otype>, Rx<PULL>>
where
Alternate<Otype>: PinMode,
Input<PULL>: PinMode,
Expand All @@ -184,18 +176,18 @@ macro_rules! remap {
let tx = p.0.into_mode(&mut cr);
let rx = p.1.into_mode(&mut cr);
p.2.modify_mapr($remapex);
Self { tx: $txonly::$TX(tx), rx: $rxonly::$RX(rx) }
Self { tx: Tx::$TX(tx), rx: Rx::$RX(rx) }
}
}

impl<Otype> From<(gpio::$TX<Alternate<Otype>>, &mut MAPR)> for $txonly<Otype> {
impl<Otype> From<(gpio::$TX<Alternate<Otype>>, &mut MAPR)> for Tx<Otype> {
fn from(p: (gpio::$TX<Alternate<Otype>>, &mut MAPR)) -> Self {
p.1.modify_mapr($remapex);
Self::$TX(p.0)
}
}

impl<Otype> From<(gpio::$TX, &mut MAPR)> for $txonly<Otype>
impl<Otype> From<(gpio::$TX, &mut MAPR)> for Tx<Otype>
where
Alternate<Otype>: PinMode,
{
Expand All @@ -206,7 +198,7 @@ macro_rules! remap {
}
}

impl<PULL> From<(gpio::$RX<Input<PULL>>, &mut MAPR)> for $rxonly<PULL>
impl<PULL> From<(gpio::$RX<Input<PULL>>, &mut MAPR)> for Rx<PULL>
where
PULL: InMode,
{
Expand Down

0 comments on commit dea145b

Please sign in to comment.