Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- impl embedded_hal_1::spi::SpiBus for SPI
- impl embedded_hal_1::digital traits for Pins
- Enable AF1 on GPIOE for pins [13, 14, 15] to support SPI communication
- Implement dead time calculations for complementary pwm

### Fixed

Expand Down
132 changes: 132 additions & 0 deletions src/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ use crate::rcc::Rcc;
use crate::time::Hertz;
use embedded_hal as hal;

/// Trait for complementary PWM pins that allows the setting of dead time
pub trait ComplementaryPwm {
/// Set the dead time for the pwm timer in ns (not the specific pin)
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32);
}

pub trait Pins<TIM, P> {
const C1: bool = false;
const C1N: bool = false;
Expand Down Expand Up @@ -409,6 +415,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C1> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
// Convert frequency to period in ns
let period = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / period;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};
unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C1N> {
type Duty = u16;

Expand Down Expand Up @@ -438,6 +465,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C1N> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / tclk;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};

unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C2> {
type Duty = u16;

Expand Down Expand Up @@ -467,6 +515,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C2> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / tclk;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};

unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C2N> {
type Duty = u16;

Expand Down Expand Up @@ -496,6 +565,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C2N> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / tclk;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};

unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C3> {
type Duty = u16;

Expand Down Expand Up @@ -525,6 +615,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C3> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / tclk;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};

unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C3N> {
type Duty = u16;

Expand Down Expand Up @@ -554,6 +665,27 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl ComplementaryPwm for PwmChannels<$TIMX, C3N> {
//NOTE(unsafe) atomic write with no side effects
fn set_dead_time(&mut self, rcc: &mut Rcc, duration: u32) {
let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 {
1000000000 / rcc.clocks.pclk().0
} else {
1000000000 / rcc.clocks.pclk().0 * 2
};
let t = duration / tclk;
let dtg = match t {
0..=127 => t,
128..=255 => t / 2 - 64 + 0b1000_0000,
256..=504 => t / 8 - 32 + 0b1100_0000,
512..=1008 => t / 16 - 32 + 0b1110_0000,
_ => 0,
};

unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(dtg as u8)) };
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C4> {
type Duty = u16;

Expand Down
Loading