stm32/hrtim: impl. bridge, dead-time part. res.
This commit is contained in:
parent
3252eaa060
commit
8c4997c5fc
@ -9,33 +9,44 @@ use crate::gpio::AnyPin;
|
|||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
use crate::Peripheral;
|
use crate::Peripheral;
|
||||||
|
|
||||||
// Re-implement the channels for hrtim
|
pub enum Source {
|
||||||
pub struct Master<T: AdvancedCaptureCompare16bitInstance> {
|
Master,
|
||||||
|
ChA,
|
||||||
|
ChB,
|
||||||
|
ChC,
|
||||||
|
ChD,
|
||||||
|
ChE,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BurstController<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
pub struct ChA<T: AdvancedCaptureCompare16bitInstance> {
|
pub struct Master<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
pub struct ChB<T: AdvancedCaptureCompare16bitInstance> {
|
pub struct ChA<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
pub struct ChC<T: AdvancedCaptureCompare16bitInstance> {
|
pub struct ChB<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
pub struct ChD<T: AdvancedCaptureCompare16bitInstance> {
|
pub struct ChC<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
pub struct ChE<T: AdvancedCaptureCompare16bitInstance> {
|
pub struct ChD<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
|
phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
pub struct ChE<T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod sealed {
|
mod sealed {
|
||||||
use crate::pwm::AdvancedCaptureCompare16bitInstance;
|
use crate::pwm::HighResolutionCaptureCompare16bitInstance;
|
||||||
|
|
||||||
pub trait AdvancedChannel<T: AdvancedCaptureCompare16bitInstance> {}
|
pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AdvancedChannel<T: AdvancedCaptureCompare16bitInstance>: sealed::AdvancedChannel<T> {
|
pub trait AdvancedChannel<T: HighResolutionCaptureCompare16bitInstance>: sealed::AdvancedChannel<T> {
|
||||||
fn raw() -> usize;
|
fn raw() -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +62,7 @@ pub struct ComplementaryPwmPin<'d, Perip, Channel> {
|
|||||||
|
|
||||||
macro_rules! advanced_channel_impl {
|
macro_rules! advanced_channel_impl {
|
||||||
($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
|
($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => {
|
||||||
impl<'d, Perip: AdvancedCaptureCompare16bitInstance> PwmPin<'d, Perip, $channel<Perip>> {
|
impl<'d, Perip: HighResolutionCaptureCompare16bitInstance> PwmPin<'d, Perip, $channel<Perip>> {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
|
pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
@ -67,7 +78,7 @@ macro_rules! advanced_channel_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, Perip: AdvancedCaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> {
|
impl<'d, Perip: HighResolutionCaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> {
|
||||||
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
|
pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
@ -83,8 +94,8 @@ macro_rules! advanced_channel_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AdvancedCaptureCompare16bitInstance> sealed::AdvancedChannel<T> for $channel<T> {}
|
impl<T: HighResolutionCaptureCompare16bitInstance> sealed::AdvancedChannel<T> for $channel<T> {}
|
||||||
impl<T: AdvancedCaptureCompare16bitInstance> AdvancedChannel<T> for $channel<T> {
|
impl<T: HighResolutionCaptureCompare16bitInstance> AdvancedChannel<T> for $channel<T> {
|
||||||
fn raw() -> usize {
|
fn raw() -> usize {
|
||||||
$ch_num
|
$ch_num
|
||||||
}
|
}
|
||||||
@ -99,9 +110,10 @@ advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin);
|
|||||||
advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin);
|
advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin);
|
||||||
|
|
||||||
/// Struct used to divide a high resolution timer into multiple channels
|
/// Struct used to divide a high resolution timer into multiple channels
|
||||||
pub struct AdvancedPwm<'d, T: AdvancedCaptureCompare16bitInstance> {
|
pub struct AdvancedPwm<'d, T: HighResolutionCaptureCompare16bitInstance> {
|
||||||
_inner: PeripheralRef<'d, T>,
|
_inner: PeripheralRef<'d, T>,
|
||||||
pub master: Master<T>,
|
pub master: Master<T>,
|
||||||
|
pub burst_controller: BurstController<T>,
|
||||||
pub ch_a: ChA<T>,
|
pub ch_a: ChA<T>,
|
||||||
pub ch_b: ChB<T>,
|
pub ch_b: ChB<T>,
|
||||||
pub ch_c: ChC<T>,
|
pub ch_c: ChC<T>,
|
||||||
@ -109,7 +121,7 @@ pub struct AdvancedPwm<'d, T: AdvancedCaptureCompare16bitInstance> {
|
|||||||
pub ch_e: ChE<T>,
|
pub ch_e: ChE<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: AdvancedCaptureCompare16bitInstance> AdvancedPwm<'d, T> {
|
impl<'d, T: HighResolutionCaptureCompare16bitInstance> AdvancedPwm<'d, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tim: impl Peripheral<P = T> + 'd,
|
tim: impl Peripheral<P = T> + 'd,
|
||||||
_cha: Option<PwmPin<'d, T, ChA<T>>>,
|
_cha: Option<PwmPin<'d, T, ChA<T>>>,
|
||||||
@ -135,6 +147,7 @@ impl<'d, T: AdvancedCaptureCompare16bitInstance> AdvancedPwm<'d, T> {
|
|||||||
Self {
|
Self {
|
||||||
_inner: tim,
|
_inner: tim,
|
||||||
master: Master { phantom: PhantomData },
|
master: Master { phantom: PhantomData },
|
||||||
|
burst_controller: BurstController { phantom: PhantomData },
|
||||||
ch_a: ChA { phantom: PhantomData },
|
ch_a: ChA { phantom: PhantomData },
|
||||||
ch_b: ChB { phantom: PhantomData },
|
ch_b: ChB { phantom: PhantomData },
|
||||||
ch_c: ChC { phantom: PhantomData },
|
ch_c: ChC { phantom: PhantomData },
|
||||||
@ -142,54 +155,162 @@ impl<'d, T: AdvancedCaptureCompare16bitInstance> AdvancedPwm<'d, T> {
|
|||||||
ch_e: ChE { phantom: PhantomData },
|
ch_e: ChE { phantom: PhantomData },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the dead time as a proportion of max_duty
|
impl<T: HighResolutionCaptureCompare16bitInstance> BurstController<T> {
|
||||||
pub fn set_dead_time(&mut self, _value: u16) {
|
pub fn set_source(&mut self, source: Source) {
|
||||||
todo!()
|
let regs = T::regs();
|
||||||
// let (ckd, value) = compute_dead_time_value(value);
|
|
||||||
//
|
|
||||||
// self.inner.set_dead_time_clock_division(ckd);
|
|
||||||
// self.inner.set_dead_time_value(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a fixed-frequency bridge converter
|
/// Represents a fixed-frequency bridge converter
|
||||||
pub struct BridgeConverter<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> {
|
///
|
||||||
|
/// Our implementation of the bridge converter uses a single channel and two compare registers,
|
||||||
|
/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous
|
||||||
|
/// conduction mode.
|
||||||
|
///
|
||||||
|
/// It is important to remember that in synchronous topologies, energy can flow in reverse during
|
||||||
|
/// light loading conditions, and that the low-side switch must be active for a short time to drive
|
||||||
|
/// a bootstrapped high-side switch.
|
||||||
|
pub struct BridgeConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
pub ch: C,
|
pub ch: C,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> {
|
||||||
pub fn new(channel: C, frequency: Hertz) -> Self {
|
pub fn new(channel: C, frequency: Hertz) -> Self {
|
||||||
|
use crate::pac::hrtim::vals::{Activeeffect, Cont, Inactiveeffect};
|
||||||
|
|
||||||
|
T::set_channel_frequency(C::raw(), frequency);
|
||||||
|
|
||||||
|
// Always enable preload
|
||||||
|
T::regs().tim(C::raw()).cr().modify(|w| {
|
||||||
|
w.set_preen(true);
|
||||||
|
|
||||||
|
// TODO: fix metapac
|
||||||
|
w.set_cont(Cont(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set output 1 to active on a period event
|
||||||
|
T::regs()
|
||||||
|
.tim(C::raw())
|
||||||
|
.setr(0)
|
||||||
|
.modify(|w| w.set_per(Activeeffect::SETACTIVE));
|
||||||
|
|
||||||
|
// Set output 1 to inactive on a compare 1 event
|
||||||
|
T::regs()
|
||||||
|
.tim(C::raw())
|
||||||
|
.rstr(0)
|
||||||
|
.modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE));
|
||||||
|
|
||||||
|
// Set output 2 to active on a compare 1 event
|
||||||
|
T::regs()
|
||||||
|
.tim(C::raw())
|
||||||
|
.setr(1)
|
||||||
|
.modify(|w| w.set_cmp(0, Activeeffect::SETACTIVE));
|
||||||
|
|
||||||
|
// Set output 2 to inactive on a compare 2 event
|
||||||
|
T::regs()
|
||||||
|
.tim(C::raw())
|
||||||
|
.rstr(1)
|
||||||
|
.modify(|w| w.set_cmp(1, Inactiveeffect::SETINACTIVE));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
ch: channel,
|
ch: channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_duty(&mut self, primary: u16, secondary: u16) {
|
pub fn start(&mut self) {
|
||||||
let _ = T::regs();
|
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true));
|
||||||
let _ = C::raw();
|
}
|
||||||
|
|
||||||
todo!()
|
pub fn stop(&mut self) {
|
||||||
|
T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the dead time as a proportion of the maximum compare value
|
||||||
|
pub fn set_dead_time(&mut self, value: u16) {
|
||||||
|
T::set_channel_dead_time(C::raw(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the maximum compare value of a duty cycle
|
||||||
|
pub fn get_max_compare_value(&mut self) -> u16 {
|
||||||
|
T::regs().tim(C::raw()).per().read().per()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The primary duty is the period in which the primary switch is active
|
||||||
|
///
|
||||||
|
/// In the case of a buck converter, this is the high-side switch
|
||||||
|
/// In the case of a boost converter, this is the low-side switch
|
||||||
|
pub fn set_primary_duty(&mut self, primary: u16) {
|
||||||
|
T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The primary duty is the period in any switch is active
|
||||||
|
///
|
||||||
|
/// If less than or equal to the primary duty, the secondary switch will never be active
|
||||||
|
pub fn set_secondary_duty(&mut self, secondary: u16) {
|
||||||
|
T::regs().tim(C::raw()).cmp(1).modify(|w| w.set_cmp(secondary));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a variable-frequency resonant converter
|
/// Represents a variable-frequency resonant converter
|
||||||
pub struct ResonantConverter<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> {
|
///
|
||||||
|
/// This implementation of a resonsant converter is appropriate for a half or full bridge,
|
||||||
|
/// but does not include secondary rectification, which is appropriate for applications
|
||||||
|
/// with a low-voltage on the secondary side.
|
||||||
|
pub struct ResonantConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
|
min_period: u16,
|
||||||
|
max_period: u16,
|
||||||
pub ch: C,
|
pub ch: C,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
|
impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> ResonantConverter<T, C> {
|
||||||
pub fn new(channel: C, min_frequency: Hertz) -> Self {
|
pub fn new(channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self {
|
||||||
|
use crate::pac::hrtim::vals::Cont;
|
||||||
|
|
||||||
|
T::set_channel_frequency(C::raw(), min_frequency);
|
||||||
|
|
||||||
|
// Always enable preload
|
||||||
|
T::regs().tim(C::raw()).cr().modify(|w| {
|
||||||
|
w.set_preen(true);
|
||||||
|
|
||||||
|
// TODO: fix metapac
|
||||||
|
w.set_cont(Cont(1));
|
||||||
|
w.set_half(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: compute min period value
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
min_period: 0,
|
||||||
|
max_period: T::regs().tim(C::raw()).per().read().per(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
ch: channel,
|
ch: channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_frequency(&mut self, frequency: Hertz) {
|
/// Set the dead time as a proportion of the maximum compare value
|
||||||
todo!()
|
pub fn set_dead_time(&mut self, value: u16) {
|
||||||
|
T::set_channel_dead_time(C::raw(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_period(&mut self, period: u16) {
|
||||||
|
assert!(period < self.max_period);
|
||||||
|
assert!(period > self.min_period);
|
||||||
|
|
||||||
|
T::regs().tim(C::raw()).per().modify(|w| w.set_per(period));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the minimum compare value of a duty cycle
|
||||||
|
pub fn get_min_period(&mut self) -> u16 {
|
||||||
|
self.min_period
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the maximum compare value of a duty cycle
|
||||||
|
pub fn get_max_period(&mut self) -> u16 {
|
||||||
|
self.max_period
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,11 +76,9 @@ pub(crate) enum HighResolutionControlPrescaler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(hrtim_v1)]
|
#[cfg(hrtim_v1)]
|
||||||
impl ops::Div<HighResolutionControlPrescaler> for Hertz {
|
impl From<HighResolutionControlPrescaler> for u32 {
|
||||||
type Output = Hertz;
|
fn from(val: HighResolutionControlPrescaler) -> Self {
|
||||||
|
match val {
|
||||||
fn div(self, rhs: HighResolutionControlPrescaler) -> Self::Output {
|
|
||||||
let divisor = match rhs {
|
|
||||||
HighResolutionControlPrescaler::Div1 => 1,
|
HighResolutionControlPrescaler::Div1 => 1,
|
||||||
HighResolutionControlPrescaler::Div2 => 2,
|
HighResolutionControlPrescaler::Div2 => 2,
|
||||||
HighResolutionControlPrescaler::Div4 => 4,
|
HighResolutionControlPrescaler::Div4 => 4,
|
||||||
@ -89,9 +87,7 @@ impl ops::Div<HighResolutionControlPrescaler> for Hertz {
|
|||||||
HighResolutionControlPrescaler::Div32 => 32,
|
HighResolutionControlPrescaler::Div32 => 32,
|
||||||
HighResolutionControlPrescaler::Div64 => 64,
|
HighResolutionControlPrescaler::Div64 => 64,
|
||||||
HighResolutionControlPrescaler::Div128 => 128,
|
HighResolutionControlPrescaler::Div128 => 128,
|
||||||
};
|
}
|
||||||
|
|
||||||
Hertz(self.0 / divisor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +107,26 @@ impl From<HighResolutionControlPrescaler> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(hrtim_v1)]
|
||||||
|
impl From<u8> for HighResolutionControlPrescaler {
|
||||||
|
fn from(val: u8) -> Self {
|
||||||
|
match val {
|
||||||
|
0b000 => HighResolutionControlPrescaler::Div1,
|
||||||
|
0b001 => HighResolutionControlPrescaler::Div2,
|
||||||
|
0b010 => HighResolutionControlPrescaler::Div4,
|
||||||
|
0b011 => HighResolutionControlPrescaler::Div8,
|
||||||
|
0b100 => HighResolutionControlPrescaler::Div16,
|
||||||
|
0b101 => HighResolutionControlPrescaler::Div32,
|
||||||
|
0b110 => HighResolutionControlPrescaler::Div64,
|
||||||
|
0b111 => HighResolutionControlPrescaler::Div128,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(hrtim_v1)]
|
#[cfg(hrtim_v1)]
|
||||||
impl HighResolutionControlPrescaler {
|
impl HighResolutionControlPrescaler {
|
||||||
pub fn compute_min(base_f: Hertz, frequency: Hertz) -> Self {
|
pub fn compute_min(val: u32) -> Self {
|
||||||
*[
|
*[
|
||||||
HighResolutionControlPrescaler::Div1,
|
HighResolutionControlPrescaler::Div1,
|
||||||
HighResolutionControlPrescaler::Div2,
|
HighResolutionControlPrescaler::Div2,
|
||||||
@ -125,7 +138,7 @@ impl HighResolutionControlPrescaler {
|
|||||||
HighResolutionControlPrescaler::Div128,
|
HighResolutionControlPrescaler::Div128,
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.skip_while(|psc| frequency <= base_f / **psc)
|
.skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val)
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
@ -135,11 +148,14 @@ pub(crate) mod sealed {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[cfg(hrtim_v1)]
|
#[cfg(hrtim_v1)]
|
||||||
pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance {
|
pub trait HighResolutionCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance {
|
||||||
fn set_master_frequency(frequency: Hertz);
|
fn set_master_frequency(frequency: Hertz);
|
||||||
|
|
||||||
fn set_channel_frequency(channnel: usize, frequency: Hertz);
|
fn set_channel_frequency(channnel: usize, frequency: Hertz);
|
||||||
|
|
||||||
|
/// Set the dead time as a proportion of max_duty
|
||||||
|
fn set_channel_dead_time(channnel: usize, dead_time: u16);
|
||||||
|
|
||||||
// fn enable_outputs(enable: bool);
|
// fn enable_outputs(enable: bool);
|
||||||
//
|
//
|
||||||
// fn enable_channel(&mut self, channel: usize, enable: bool);
|
// fn enable_channel(&mut self, channel: usize, enable: bool);
|
||||||
@ -178,7 +194,10 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(hrtim_v1)]
|
#[cfg(hrtim_v1)]
|
||||||
pub trait AdvancedCaptureCompare16bitInstance: sealed::AdvancedCaptureCompare16bitInstance + 'static {}
|
pub trait HighResolutionCaptureCompare16bitInstance:
|
||||||
|
sealed::HighResolutionCaptureCompare16bitInstance + 'static
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
pub trait CaptureCompare16bitInstance:
|
pub trait CaptureCompare16bitInstance:
|
||||||
sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static
|
sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static
|
||||||
@ -343,20 +362,19 @@ foreach_interrupt! {
|
|||||||
};
|
};
|
||||||
|
|
||||||
($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
|
($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
|
||||||
impl crate::pwm::sealed::AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst {
|
impl crate::pwm::sealed::HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
|
||||||
fn set_master_frequency(frequency: Hertz) {
|
fn set_master_frequency(frequency: Hertz) {
|
||||||
use crate::rcc::sealed::RccPeripheral;
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
use crate::timer::sealed::HighResolutionControlInstance;
|
use crate::timer::sealed::HighResolutionControlInstance;
|
||||||
|
|
||||||
let f = frequency.0;
|
let f = frequency.0;
|
||||||
// TODO: fix frequency source
|
let timer_f = Self::frequency().0;
|
||||||
// let timer_f = Self::frequency().0;
|
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
|
||||||
let timer_f = Hertz(144_000_000).0;
|
let psc = HighResolutionControlPrescaler::compute_min(psc_min);
|
||||||
let base_f = Hertz((32 * timer_f as u64 / u16::MAX as u64) as u32);
|
|
||||||
let psc = HighResolutionControlPrescaler::compute_min(base_f, frequency);
|
|
||||||
|
|
||||||
let psc_timer_f = Hertz(timer_f) / psc;
|
let psc_val: u32 = psc.into();
|
||||||
let per: u16 = (psc_timer_f / f).0 as u16;
|
let timer_f = timer_f / psc_val;
|
||||||
|
let per: u16 = (timer_f / f) as u16;
|
||||||
|
|
||||||
let regs = Self::regs();
|
let regs = Self::regs();
|
||||||
|
|
||||||
@ -369,23 +387,46 @@ foreach_interrupt! {
|
|||||||
use crate::timer::sealed::HighResolutionControlInstance;
|
use crate::timer::sealed::HighResolutionControlInstance;
|
||||||
|
|
||||||
let f = frequency.0;
|
let f = frequency.0;
|
||||||
// TODO: fix frequency source
|
let timer_f = Self::frequency().0;
|
||||||
// let timer_f = Self::frequency().0;
|
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
|
||||||
let timer_f = Hertz(144_000_000).0;
|
let psc = HighResolutionControlPrescaler::compute_min(psc_min);
|
||||||
let base_f = Hertz((32 * timer_f as u64 / u16::MAX as u64) as u32);
|
|
||||||
let psc = HighResolutionControlPrescaler::compute_min(base_f, frequency);
|
|
||||||
|
|
||||||
let psc_timer_f = Hertz(timer_f) / psc;
|
let psc_val: u32 = psc.into();
|
||||||
let per: u16 = (psc_timer_f / f).0 as u16;
|
let timer_f = timer_f / psc_val;
|
||||||
|
let per: u16 = (timer_f / f) as u16;
|
||||||
|
|
||||||
let regs = Self::regs();
|
let regs = Self::regs();
|
||||||
|
|
||||||
regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
|
regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
|
||||||
regs.tim(channel).per().modify(|w| w.set_per(per));
|
regs.tim(channel).per().modify(|w| w.set_per(per));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_channel_dead_time(channel: usize, dead_time: u16) {
|
||||||
|
use crate::rcc::sealed::RccPeripheral;
|
||||||
|
use crate::timer::sealed::HighResolutionControlInstance;
|
||||||
|
|
||||||
|
let regs = Self::regs();
|
||||||
|
|
||||||
|
let channel_psc: HighResolutionControlPrescaler = regs.tim(channel).cr().read().ckpsc().into();
|
||||||
|
let psc_val: u32 = channel_psc.into();
|
||||||
|
|
||||||
|
|
||||||
|
// The dead-time base clock runs 4 times slower than the hrtim base clock
|
||||||
|
// u9::MAX = 511
|
||||||
|
let psc_min = (psc_val * dead_time as u32) / (4 * 511);
|
||||||
|
let psc = HighResolutionControlPrescaler::compute_min(psc_min);
|
||||||
|
let dt_psc_val: u32 = psc.into();
|
||||||
|
let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
|
||||||
|
|
||||||
|
regs.tim(channel).dt().modify(|w| {
|
||||||
|
w.set_dtprsc(psc.into());
|
||||||
|
w.set_dtf(dt_val as u16);
|
||||||
|
w.set_dtr(dt_val as u16);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst {
|
impl HighResolutionCaptureCompare16bitInstance for crate::peripherals::$inst {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -411,16 +452,16 @@ pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
|
|||||||
mod hrtim_pins {
|
mod hrtim_pins {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pin_trait!(ChannelAPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelAPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelAComplementaryPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelAComplementaryPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelBPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelBPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelBComplementaryPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelBComplementaryPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelCPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelCPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelCComplementaryPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelCComplementaryPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelDPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelDPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelDComplementaryPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelDComplementaryPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelEPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelEPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
pin_trait!(ChannelEComplementaryPin, AdvancedCaptureCompare16bitInstance);
|
pin_trait!(ChannelEComplementaryPin, HighResolutionCaptureCompare16bitInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(hrtim_v1)]
|
#[cfg(hrtim_v1)]
|
||||||
|
@ -31,16 +31,17 @@ async fn main(_spawner: Spawner) {
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
pwm.set_dead_time(0);
|
|
||||||
|
|
||||||
let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(100));
|
let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(100));
|
||||||
|
|
||||||
buck_converter.set_duty(0, u16::MAX);
|
buck_converter.set_primary_duty(0);
|
||||||
|
buck_converter.set_secondary_duty(0);
|
||||||
|
buck_converter.set_dead_time(0);
|
||||||
|
|
||||||
// note: if the pins are not passed into the advanced pwm struct, they will not be output
|
// note: if the pins are not passed into the advanced pwm struct, they will not be output
|
||||||
let mut boost_converter = BridgeConverter::new(pwm.ch_b, khz(100));
|
let mut boost_converter = BridgeConverter::new(pwm.ch_b, khz(100));
|
||||||
|
|
||||||
boost_converter.set_duty(0, 0);
|
boost_converter.set_primary_duty(0);
|
||||||
|
boost_converter.set_secondary_duty(0);
|
||||||
|
|
||||||
// let max = pwm.get_max_duty();
|
// let max = pwm.get_max_duty();
|
||||||
// pwm.set_dead_time(max / 1024);
|
// pwm.set_dead_time(max / 1024);
|
||||||
|
Loading…
Reference in New Issue
Block a user