Skip to content

Commit 856904f

Browse files
committed
Added Mcpwm::operator_source_frequency
1 parent 004a9e9 commit 856904f

File tree

1 file changed

+78
-22
lines changed

1 file changed

+78
-22
lines changed

src/mcpwm.rs

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ impl From<CounterMode> for mcpwm_counter_type_t {
119119
}
120120
}
121121

122-
// TODO: Note that `red` and `fed` from the IDF's perspecitve is time as in number of clock cycles after the
123-
// MCPWM modules group prescaler. How do we want to expose this? Do we expose it as just that, a cycle count?
124-
// Or do we expose it as a time which we then calculate the cycle count from?
125-
/// Deadtime config for MCPWM operator
122+
/// Dead time config for MCPWM operator
123+
///
124+
/// `red` and `fed` is time as in number of clock cycles after the MCPWM modules group prescaler.
125+
///
126126
/// Note that the dead times are calculated from MCPWMXA's flanks unless explicitly stated otherwise
127127
#[derive(Copy, Clone, PartialEq, Debug)]
128128
pub enum DeadtimeConfig {
@@ -232,10 +232,7 @@ pub enum DeadtimeConfig {
232232
/// . . . .
233233
ActiveLow { red: u16, fed: u16 },
234234

235-
// TODO: Is this actually true? --------
236-
// |
237-
// v
238-
/// MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE - The most common deadtime mode
235+
/// MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE
239236
///
240237
/// . . . .
241238
/// . . . .
@@ -467,21 +464,23 @@ pub struct Mcpwm<U: Unit> {
467464
/// Those timers in turn have their own prescalers to scale this down even further
468465
///
469466
/// NOTE: This is only to be set by calling Self::lowest_frequency
470-
operator_input_frequency: u32,
467+
operator_source_frequency: u32,
471468
_instance: MCPWM<U>,
472469
}
473470

474471
impl<U: Unit> Mcpwm<U> {
475472
pub fn new(instance: MCPWM<U>) -> Result<Self, EspError> {
476473
let res = Self {
477474
#[cfg(not(esp_idf_version = "4.3"))]
478-
operator_input_frequency: 0,
475+
operator_source_frequency: 0,
479476
_instance: instance,
480477
};
481478

482479
#[cfg(not(esp_idf_version = "4.3"))]
483480
{
484-
res.lowest_frequency(15.Hz())
481+
// TODO: Do we want to make this into something more builder-pattern like to
482+
// avoid this potentially redundant function call?
483+
res.operator_source_frequency(10.MHz())
485484
}
486485

487486
#[cfg(esp_idf_version = "4.3")]
@@ -490,26 +489,53 @@ impl<U: Unit> Mcpwm<U> {
490489
}
491490
}
492491

492+
pub fn release(self) -> MCPWM<U> {
493+
// TODO: Do we need to reset any state here such as group_prescaler?
494+
self._instance
495+
}
496+
493497
/// Specify lowest reachable frequency
494498
///
495499
/// The lower this is set, the lower frequencies will be reachable. However, this is at the cost of worse
496500
/// resolution at higher frequencies.
497-
///
501+
///
498502
/// Same thing goes for the other way. The higher value set here, the more resolution and so on.
499503
#[cfg(not(esp_idf_version = "4.3"))]
500504
pub fn lowest_frequency(mut self, lowest_frequency: Hertz) -> Result<Self, EspError> {
501505
// TODO: Do we care about frequency < 1Hz?
502-
let operator_input_frequency =
506+
let operator_source_frequency =
503507
MAX_PWM_TIMER_PRESCALE * MAX_PWM_TIMER_PERIOD * u32::from(lowest_frequency);
504-
let group_pre_scale = MCPWM_CLOCK_SOURCE_FREQUENCY / operator_input_frequency;
508+
let group_pre_scale = MCPWM_CLOCK_SOURCE_FREQUENCY / operator_source_frequency;
505509
if !(1..=256).contains(&group_pre_scale) {
506510
return Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap());
507511
}
508512

509-
let resolution =
510-
MAX_PWM_TIMER_PRESCALE * MAX_PWM_TIMER_PERIOD * u32::from(lowest_frequency);
511-
esp!(unsafe { mcpwm_group_set_resolution(U::unit(), resolution) })?;
512-
self.operator_input_frequency = operator_input_frequency;
513+
esp!(unsafe { mcpwm_group_set_resolution(U::unit(), operator_source_frequency) })?;
514+
self.operator_source_frequency = operator_source_frequency;
515+
516+
Ok(self)
517+
}
518+
519+
/// Specify frequency passed to operators timers as clock source
520+
///
521+
/// The timers of the operators can then in turn scale this frequency down further.
522+
///
523+
/// The lower this is set, the lower frequencies will be reachable. However, this is
524+
/// at the cost of worse resolution at higher frequencies. Same thing goes for the
525+
/// other way. The higher value set here, the more resolution and so on.
526+
#[cfg(not(esp_idf_version = "4.3"))]
527+
pub fn operator_source_frequency(mut self, frequency: impl Into<Hertz>) -> Result<Self, EspError> {
528+
let frequency: Hertz = frequency.into();
529+
let frequency: u32 = frequency.into();
530+
531+
// TODO: Do we care about frequency < 1Hz?
532+
let group_pre_scale = MCPWM_CLOCK_SOURCE_FREQUENCY / frequency;
533+
if !(1..=256).contains(&group_pre_scale) {
534+
return Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap());
535+
}
536+
537+
esp!(unsafe { mcpwm_group_set_resolution(U::unit(), frequency) })?;
538+
self.operator_source_frequency = frequency;
513539

514540
Ok(self)
515541
}
@@ -584,7 +610,7 @@ impl_operator!(
584610
);
585611

586612
// TODO: How do we want syncing to fit in to this?
587-
// TODO: How do we want deadtime to fit into this?
613+
// TODO: How do we want dead time to fit into this?
588614
// TODO: How do we want carrier to fit into this?
589615
// TODO: How do we want capture to fit into this?
590616

@@ -597,8 +623,13 @@ pub struct Operator<U: Unit, O: HwOperator<U>, M: Borrow<Mcpwm<U>>, PA: OutputPi
597623
_pin_b: Option<PB>,
598624
}
599625

600-
impl<U: Unit, O: HwOperator<U>, M: Borrow<Mcpwm<U>>, PA: OutputPin, PB: OutputPin>
601-
Operator<U, O, M, PA, PB>
626+
impl<U, O, M, PA, PB> Operator<U, O, M, PA, PB>
627+
where
628+
U: Unit,
629+
O: HwOperator<U>,
630+
M: Borrow<Mcpwm<U>>,
631+
PA: OutputPin,
632+
PB: OutputPin,
602633
{
603634
pub fn new<A: Into<Option<PA>>, B: Into<Option<PB>>>(
604635
operator: O,
@@ -616,7 +647,7 @@ impl<U: Unit, O: HwOperator<U>, M: Borrow<Mcpwm<U>>, PA: OutputPin, PB: OutputPi
616647
return Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap());
617648
}
618649

619-
if config.lowest_frequency > mcpwm_module.borrow().operator_input_frequency.Hz() {
650+
if config.lowest_frequency > mcpwm_module.borrow().operator_source_frequency.Hz() {
620651
// Can not specify a lowest_frequency larger than the corresponding value for
621652
// the parent MCPWM module. Use `Mcpwm::lowest_frequency` to enable higher frequencies
622653
return Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap());
@@ -680,6 +711,31 @@ impl<U: Unit, O: HwOperator<U>, M: Borrow<Mcpwm<U>>, PA: OutputPin, PB: OutputPi
680711
})
681712
}
682713

714+
pub fn release(self) -> (O, Option<PA>, Option<PB>) {
715+
// mcpwm_stop will only fail when invalid args are given
716+
esp!(unsafe { mcpwm_stop(U::unit(), O::timer()) }).unwrap();
717+
718+
// TODO: Test and verify if this is the right way
719+
if self._pin_a.is_some() {
720+
// TODO: How to unset pin?
721+
// let io_signal = O::signal_a();
722+
// mcpwm_gpio_init(U::unit(), io_signal, -1)
723+
// does not seem to be it...
724+
todo!();
725+
}
726+
727+
if self._pin_b.is_some() {
728+
// TODO: How to unset pin?
729+
// let io_signal = O::signal_b();
730+
// mcpwm_gpio_init(U::unit(), io_signal, -1)
731+
// does not seem to be it...
732+
733+
todo!();
734+
}
735+
// TODO: Do we need to reset any more state here such as dead time config?
736+
(self._instance, self._pin_a, self._pin_b)
737+
}
738+
683739
/// Get duty as percentage between 0.0 and 100.0
684740
pub fn get_duty_a(&self) -> Duty {
685741
unsafe {

0 commit comments

Comments
 (0)