Skip to content

Commit

Permalink
Almost compiling
Browse files Browse the repository at this point in the history
  • Loading branch information
usbalbin committed Oct 9, 2022
1 parent ff2624b commit cc0e98e
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 148 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ heapless = "0.7"
embassy-sync = { version = "0.1", optional = true, git = "https://github.com/ivmarkov/embassy" }
embassy-time = { version = "0.1", optional = true, features = ["tick-hz-1_000_000"], git = "https://github.com/ivmarkov/embassy" }
edge-executor = { version = "0.2", optional = true, default-features = false }
libc = "0.2.134"


[build-dependencies]
embuild = "0.30.3"
Expand Down
93 changes: 58 additions & 35 deletions src/mcpwm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,18 @@ mod timer;
mod operator;
mod timer_connection;

use core::borrow::Borrow;
use core::ffi;

use crate::gpio::OutputPin;
use crate::units::{FromValueType, Hertz};
use crate::mcpwm::operator::{HwOperator, OPERATOR0, OPERATOR1, OPERATOR2};
use esp_idf_sys::*;
use crate::mcpwm::operator::{
HwOperator0, HwOperator1, HwOperator2,
OPERATOR00, OPERATOR01, OPERATOR02,
OPERATOR10, OPERATOR11, OPERATOR12
};

use crate::mcpwm::timer::{
TIMER00, TIMER01, TIMER02,
TIMER10, TIMER11, TIMER12
};

// MCPWM clock source frequency for ESP32 and ESP32-s3
const MCPWM_CLOCK_SOURCE_FREQUENCY: u32 = 160_000_000;
Expand All @@ -72,58 +78,75 @@ const MAX_PWM_TIMER_PRESCALE: u32 = 0x1_00;
const MAX_PWM_TIMER_PERIOD: u32 = 0x1_00_00;

/// The Motor Control Pulse Width Modulator peripheral
pub struct Peripheral<U: Unit> {
pub mcpwm: MCPWM<U>,
pub operator0: OPERATOR0<U>,
pub operator1: OPERATOR1<U>,
pub operator2: OPERATOR2<U>,
pub struct MCPWM0 {
timer0: TIMER00,
timer1: TIMER01,
timer2: TIMER02,

pub operator0: OPERATOR00,
pub operator1: OPERATOR01,
pub operator2: OPERATOR02,
}

impl<U: Unit> Peripheral<U> {
impl MCPWM0 {
/// # Safety
///
/// It is safe to instantiate this exactly one time per `Unit`.
/// It is safe to instantiate this exactly one time per `Group`.
pub unsafe fn new() -> Self {
Self {
mcpwm: MCPWM::new(),
operator0: OPERATOR0::new(),
operator1: OPERATOR1::new(),
operator2: OPERATOR2::new(),
timer0: TIMER00::new(),
timer1: TIMER01::new(),
timer2: TIMER02::new(),
operator0: OPERATOR00::new(),
operator1: OPERATOR01::new(),
operator2: OPERATOR02::new(),
}
}
}

#[derive(Default)]
pub struct UnitZero;

#[derive(Default)]
pub struct UnitOne;
pub struct MCPWM1 {
timer0: TIMER10,
timer1: TIMER11,
timer2: TIMER12,

pub type Duty = u16;

pub struct MCPWM<U: Unit> {
_unit: U,
pub operator0: OPERATOR10,
pub operator1: OPERATOR11,
pub operator2: OPERATOR12,
}

impl<U: Unit> MCPWM<U> {
impl MCPWM1 {
/// # Safety
///
/// It is safe to instantiate this exactly one time per `Unit`.
unsafe fn new() -> Self {
/// It is safe to instantiate this exactly one time per `Group`.
pub unsafe fn new() -> Self {
Self {
_unit: U::default(),
timer0: TIMER10::new(),
timer1: TIMER11::new(),
timer2: TIMER12::new(),
operator0: OPERATOR10::new(),
operator1: OPERATOR11::new(),
operator2: OPERATOR12::new(),
}
}
}

pub trait Unit: Default {
const ID: mcpwm_unit_t;
#[derive(Default)]
pub struct Group0;

#[derive(Default)]
pub struct Group1;

pub type Duty = u16;

// Note this was called `Unit` in IDF < 5.0
pub trait Group: Default {
const ID: ffi::c_int;
}

impl Unit for UnitZero {
const ID: mcpwm_unit_t = mcpwm_unit_t_MCPWM_UNIT_0;
impl Group for Group0 {
const ID: ffi::c_int = 0;
}

impl Unit for UnitOne {
const ID: mcpwm_unit_t = mcpwm_unit_t_MCPWM_UNIT_1;
impl Group for Group1 {
const ID: ffi::c_int = 1;
}
94 changes: 36 additions & 58 deletions src/mcpwm/operator.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,47 @@
use std::borrow::Borrow;
use esp_idf_sys::{EspError, mcpwm_oper_handle_t};

use esp_idf_sys::{mcpwm_io_signals_t, mcpwm_unit_t, mcpwm_operator_t,
mcpwm_io_signals_t_MCPWM0A, mcpwm_io_signals_t_MCPWM0B,
mcpwm_io_signals_t_MCPWM1A, mcpwm_io_signals_t_MCPWM1B,
mcpwm_io_signals_t_MCPWM2A, mcpwm_io_signals_t_MCPWM2B, EspError
};

use crate::{mcpwm::{Unit, UnitZero, UnitOne}, gpio::OutputPin};
use crate::{mcpwm::{Group, Group0, Group1}, gpio::OutputPin};

use super::{Duty, timer_connection::OptionalOutputPin};

use core::ffi;

// The hardware for ESP32 and ESP32-S3 can associate any operator(within the mcpwm module) with any
// timer(within the mcpwm module) for example allowing using the same timer for all three operators.
pub trait HwOperator<U: Unit> {
const SIGNAL_A: mcpwm_io_signals_t;
const SIGNAL_B: mcpwm_io_signals_t;
const UNIT_ID: mcpwm_unit_t = U::ID;
pub trait HwOperator<U: Group> {
const GROUP_ID: ffi::c_int = U::ID;
}

macro_rules! impl_operator_helper {
($instance:ident: $timer:expr, $signal_a:expr, $signal_b:expr, $unit:ty) => {
impl HwOperator<$unit> for $instance<$unit> {
const SIGNAL_A: mcpwm_io_signals_t = $signal_a;
const SIGNAL_B: mcpwm_io_signals_t = $signal_b;
}
macro_rules! impl_operator {
($t:ident, $g:ty) => {
crate::impl_peripheral!($t);

impl HwOperator<$g> for $t {}
};
}

macro_rules! impl_operator {
($instance:ident: $timer:expr, $signal_a:expr, $signal_b:expr) => {
pub struct $instance<U: Unit> {
_unit: U,
}
pub trait HwOperator0<G: Group>: HwOperator<G> {}
pub trait HwOperator1<G: Group>: HwOperator<G> {}
pub trait HwOperator2<G: Group>: HwOperator<G> {}

impl<U: Unit> $instance<U> {
/// # Safety
///
/// It is safe to instantiate this operator exactly one time per Unit.
pub unsafe fn new() -> Self {
$instance {
_unit: U::default(),
}
}
}
// Group 0
impl_operator!(OPERATOR00, Group0);
impl_operator!(OPERATOR01, Group0);
impl_operator!(OPERATOR02, Group0);

impl_operator_helper!($instance: $timer, $signal_a, $signal_b, UnitZero);
impl_operator_helper!($instance: $timer, $signal_a, $signal_b, UnitOne);
};
}
// Group 1
impl_operator!(OPERATOR10, Group1);
impl_operator!(OPERATOR11, Group1);
impl_operator!(OPERATOR12, Group1);

impl HwOperator0<Group0> for OPERATOR00 {}
impl HwOperator0<Group1> for OPERATOR10 {}

impl HwOperator1<Group0> for OPERATOR01 {}
impl HwOperator1<Group1> for OPERATOR11 {}

impl_operator!(
OPERATOR0: mcpwm_timer_t_MCPWM_TIMER_0,
mcpwm_io_signals_t_MCPWM0A,
mcpwm_io_signals_t_MCPWM0B
);
impl_operator!(
OPERATOR1: mcpwm_timer_t_MCPWM_TIMER_1,
mcpwm_io_signals_t_MCPWM1A,
mcpwm_io_signals_t_MCPWM1B
);
impl_operator!(
OPERATOR2: mcpwm_timer_t_MCPWM_TIMER_2,
mcpwm_io_signals_t_MCPWM2A,
mcpwm_io_signals_t_MCPWM2B
);
impl HwOperator2<Group0> for OPERATOR02 {}
impl HwOperator2<Group1> for OPERATOR12 {}

// TODO: How do we want syncing to fit in to this?
// TODO: How do we want carrier to fit into this?
Expand All @@ -73,8 +51,8 @@ impl_operator!(
///
/// Every Motor Control module has three operators. Every operator can generate two output signals called A and B.
/// A and B share the same timer and thus frequency and phase but can have induvidual duty set.
pub struct Operator<U: Unit, O: HwOperator<U>, PA: OptionalOutputPin, PB: OptionalOutputPin> {
handle: mcpwm_operator_t,
pub struct Operator<U: Group, O: HwOperator<U>, PA: OptionalOutputPin, PB: OptionalOutputPin> {
handle: mcpwm_oper_handle_t,
_instance: O,

_pin_a: PA,
Expand All @@ -85,7 +63,7 @@ pub struct Operator<U: Unit, O: HwOperator<U>, PA: OptionalOutputPin, PB: Option

impl<U, O, PA, PB> Operator<U, O, PA, PB>
where
U: Unit,
U: Group,
O: HwOperator<U>,
PA: OutputPin,
PB: OptionalOutputPin,
Expand All @@ -103,7 +81,7 @@ where

impl<U, O, PA, PB> Operator<U, O, PA, PB>
where
U: Unit,
U: Group,
O: HwOperator<U>,
PA: OptionalOutputPin,
PB: OutputPin,
Expand Down Expand Up @@ -187,10 +165,10 @@ pub enum DutyMode {
ActiveLow,
}

pub trait OptionalOperator<U: Unit, O: HwOperator<U>> {}
pub trait OptionalOperator<U: Group, O: HwOperator<U>> {}

pub struct NoOperator;
impl<U: Unit, O: HwOperator<U>> OptionalOperator<U, O> for NoOperator {}
impl<U: Group, O: HwOperator<U>> OptionalOperator<U, O> for NoOperator {}

/*
Expand Down
Loading

0 comments on commit cc0e98e

Please sign in to comment.