Skip to content

Commit e9a91c5

Browse files
committed
into_mode
1 parent 51d7aff commit e9a91c5

File tree

5 files changed

+89
-63
lines changed

5 files changed

+89
-63
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Changed
1111

1212
- CI updates + cache
13-
- Remove pull resistor from `Input` mode, use `Pull` enum instead
13+
- Remove pull resistor from `Input` mode, use `Pull` enum instead, add universal `into_mode` pin converter
1414
- Move pin mode at the end of generics, add defaults for modes,
1515
bump MSRV to 1.59 [#418]
1616
- Move hd44780-driver to dev-dependencies

src/gpio.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ pub type Debugger = Alternate<0, PushPull>;
135135
impl sealed::Active for Input {}
136136
impl<Otype> sealed::Active for Output<Otype> {}
137137
impl<const A: u8, Otype> sealed::Active for Alternate<A, Otype> {}
138+
impl sealed::NotAlt for Input {}
139+
impl<Otype> sealed::NotAlt for Output<Otype> {}
140+
impl sealed::NotAlt for Analog {}
138141

139142
/// GPIO Pin speed selection
140143
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -159,6 +162,7 @@ mod sealed {
159162
pub trait Interruptable {}
160163
/// Marker trait for active pin modes
161164
pub trait Active {}
165+
pub trait NotAlt {}
162166
}
163167

164168
use sealed::Interruptable;

src/gpio/alt.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Alternate, Gpio, NoPin, OpenDrain, Pin, PinMode, PushPull};
1+
use super::{Alternate, NoPin, OpenDrain, Pin, PinMode, PushPull};
22
use crate::{gpio, i2c, i2s, pac, serial, spi};
33

44
pub struct Const<const A: u8>;
@@ -11,28 +11,23 @@ impl<Otype> SetAlternate<0, Otype> for NoPin {
1111
fn set_alt_mode(&mut self) {}
1212
fn restore_mode(&mut self) {}
1313
}
14-
impl<const P: char, const N: u8, MODE: PinMode, const A: u8> SetAlternate<A, PushPull>
15-
for Pin<P, N, MODE>
14+
impl<const P: char, const N: u8, MODE: PinMode + super::sealed::NotAlt, const A: u8>
15+
SetAlternate<A, PushPull> for Pin<P, N, MODE>
1616
{
1717
fn set_alt_mode(&mut self) {
18-
self.set_alternate::<A>();
18+
self.mode::<Alternate<A, PushPull>>();
1919
}
2020

2121
fn restore_mode(&mut self) {
2222
self.mode::<MODE>();
2323
}
2424
}
2525

26-
impl<const P: char, const N: u8, MODE: PinMode, const A: u8> SetAlternate<A, OpenDrain>
27-
for Pin<P, N, MODE>
26+
impl<const P: char, const N: u8, MODE: PinMode + super::sealed::NotAlt, const A: u8>
27+
SetAlternate<A, OpenDrain> for Pin<P, N, MODE>
2828
{
2929
fn set_alt_mode(&mut self) {
30-
self.set_alternate::<A>();
31-
unsafe {
32-
(*Gpio::<P>::ptr())
33-
.otyper
34-
.modify(|r, w| w.bits(r.bits() | (1 << N)))
35-
};
30+
self.mode::<Alternate<A, OpenDrain>>();
3631
}
3732

3833
fn restore_mode(&mut self) {

src/gpio/convert.rs

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ impl<const L: u8, const R: u8> Assert<L, R> {
1010
impl<const P: char, const N: u8, const A: u8> Pin<P, N, Alternate<A, PushPull>> {
1111
/// Turns pin alternate configuration pin into open drain
1212
pub fn set_open_drain(self) -> Pin<P, N, Alternate<A, OpenDrain>> {
13-
let offset = { N };
14-
unsafe {
15-
(*Gpio::<P>::ptr())
16-
.otyper
17-
.modify(|r, w| w.bits(r.bits() | (1 << offset)))
18-
};
19-
20-
Pin::new()
13+
self.into_mode()
2114
}
2215
}
2316

@@ -32,6 +25,8 @@ impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Input>>
3225

3326
impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
3427
for Pin<P, N, Alternate<A, PushPull>>
28+
where
29+
Output<MODE>: PinMode,
3530
{
3631
#[inline(always)]
3732
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
@@ -68,6 +63,8 @@ impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Input>>
6863

6964
impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
7065
for Pin<P, N, Alternate<A, OpenDrain>>
66+
where
67+
Output<MODE>: PinMode,
7168
{
7269
#[inline(always)]
7370
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
@@ -93,7 +90,10 @@ impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Altern
9390
}
9491
}
9592

96-
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Input> {
93+
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Input>
94+
where
95+
Output<MODE>: PinMode,
96+
{
9797
#[inline(always)]
9898
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
9999
f.into_input()
@@ -214,7 +214,10 @@ impl<const P: char, const N: u8> From<Pin<P, N, Input>> for Pin<P, N, Analog> {
214214
}
215215
}
216216

217-
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Analog> {
217+
impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Analog>
218+
where
219+
Output<MODE>: PinMode,
220+
{
218221
#[inline(always)]
219222
fn from(f: Pin<P, N, Output<MODE>>) -> Self {
220223
f.into_analog()
@@ -239,40 +242,24 @@ impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDr
239242
}
240243
}
241244

242-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
243-
pub(super) fn set_alternate<const A: u8>(&mut self) {
245+
impl<const P: char, const N: u8, MODE: PinMode> Pin<P, N, MODE> {
246+
/// Configures the pin to operate alternate mode
247+
pub fn into_alternate<const A: u8>(self) -> Pin<P, N, Alternate<A, PushPull>> {
244248
#[allow(path_statements, clippy::no_effect)]
245249
{
246250
Assert::<A, 16>::LESS;
247251
}
248-
let offset = 2 * { N };
249-
unsafe {
250-
if N < 8 {
251-
let offset2 = 4 * { N };
252-
(*Gpio::<P>::ptr()).afrl.modify(|r, w| {
253-
w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
254-
});
255-
} else {
256-
let offset2 = 4 * { N - 8 };
257-
(*Gpio::<P>::ptr()).afrh.modify(|r, w| {
258-
w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
259-
});
260-
}
261-
(*Gpio::<P>::ptr())
262-
.moder
263-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)));
264-
}
265-
}
266-
/// Configures the pin to operate alternate mode
267-
pub fn into_alternate<const A: u8>(mut self) -> Pin<P, N, Alternate<A, PushPull>> {
268-
self.set_alternate::<A>();
269-
Pin::new()
252+
self.into_mode()
270253
}
271254

272255
/// Configures the pin to operate in alternate open drain mode
273256
#[allow(path_statements)]
274257
pub fn into_alternate_open_drain<const A: u8>(self) -> Pin<P, N, Alternate<A, OpenDrain>> {
275-
self.into_alternate::<A>().set_open_drain()
258+
#[allow(path_statements, clippy::no_effect)]
259+
{
260+
Assert::<A, 16>::LESS;
261+
}
262+
self.into_mode()
276263
}
277264

278265
/// Configures the pin to operate as a input pin
@@ -349,26 +336,49 @@ impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
349336
pub(super) fn mode<M: PinMode>(&mut self) {
350337
let offset = 2 * N;
351338
unsafe {
352-
if let Some(pudpr) = M::PUPDR {
353-
(*Gpio::<P>::ptr())
354-
.pupdr
355-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (pudpr << offset)));
339+
if MODE::PUPDR != M::PUPDR {
340+
if let Some(pudpr) = M::PUPDR {
341+
(*Gpio::<P>::ptr())
342+
.pupdr
343+
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (pudpr << offset)));
344+
}
356345
}
357346

358-
if let Some(otyper) = M::OTYPER {
359-
(*Gpio::<P>::ptr())
360-
.otyper
361-
.modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
347+
if MODE::OTYPER != M::OTYPER {
348+
if let Some(otyper) = M::OTYPER {
349+
(*Gpio::<P>::ptr())
350+
.otyper
351+
.modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
352+
}
353+
}
354+
355+
if MODE::AFR != M::AFR {
356+
if let Some(afr) = M::AFR {
357+
if N < 8 {
358+
let offset2 = 4 * { N };
359+
(*Gpio::<P>::ptr()).afrl.modify(|r, w| {
360+
w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2))
361+
});
362+
} else {
363+
let offset2 = 4 * { N - 8 };
364+
(*Gpio::<P>::ptr()).afrh.modify(|r, w| {
365+
w.bits((r.bits() & !(0b1111 << offset2)) | (afr << offset2))
366+
});
367+
}
368+
}
362369
}
363370

364-
(*Gpio::<P>::ptr())
365-
.moder
366-
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
371+
if MODE::MODER != M::MODER {
372+
(*Gpio::<P>::ptr())
373+
.moder
374+
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
375+
}
367376
}
368377
}
369378

370379
#[inline(always)]
371-
pub(super) fn into_mode<M: PinMode>(mut self) -> Pin<P, N, M> {
380+
/// Converts pin into specified mode
381+
pub fn into_mode<M: PinMode>(mut self) -> Pin<P, N, M> {
372382
self.mode::<M>();
373383
Pin::new()
374384
}
@@ -489,9 +499,11 @@ pub trait PinMode: crate::Sealed {
489499
#[doc(hidden)]
490500
const PUPDR: Option<u32> = None;
491501
#[doc(hidden)]
492-
const MODER: u32;
502+
const MODER: u32 = u32::MAX;
493503
#[doc(hidden)]
494504
const OTYPER: Option<u32> = None;
505+
#[doc(hidden)]
506+
const AFR: Option<u32> = None;
495507
}
496508

497509
impl crate::Sealed for Input {}
@@ -505,14 +517,26 @@ impl PinMode for Analog {
505517
const MODER: u32 = 0b11;
506518
}
507519

508-
impl crate::Sealed for Output<OpenDrain> {}
520+
impl<Otype> crate::Sealed for Output<Otype> {}
509521
impl PinMode for Output<OpenDrain> {
510522
const MODER: u32 = 0b01;
511523
const OTYPER: Option<u32> = Some(0b1);
512524
}
513525

514-
impl crate::Sealed for Output<PushPull> {}
515526
impl PinMode for Output<PushPull> {
516527
const MODER: u32 = 0b01;
517528
const OTYPER: Option<u32> = Some(0b0);
518529
}
530+
531+
impl<const A: u8, Otype> crate::Sealed for Alternate<A, Otype> {}
532+
impl<const A: u8> PinMode for Alternate<A, OpenDrain> {
533+
const MODER: u32 = 0b10;
534+
const OTYPER: Option<u32> = Some(0b1);
535+
const AFR: Option<u32> = Some(A as _);
536+
}
537+
538+
impl<const A: u8> PinMode for Alternate<A, PushPull> {
539+
const MODER: u32 = 0b10;
540+
const OTYPER: Option<u32> = Some(0b0);
541+
const AFR: Option<u32> = Some(A as _);
542+
}

src/gpio/dynamic.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ impl Dynamic {
4343
// For convertion simplify
4444
struct Unknown;
4545

46+
impl crate::Sealed for Unknown {}
47+
impl PinMode for Unknown {}
48+
4649
impl<const P: char, const N: u8> DynamicPin<P, N> {
4750
pub const fn new(mode: Dynamic) -> Self {
4851
Self { mode }

0 commit comments

Comments
 (0)