-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial ctimer pwm implementation
- Loading branch information
1 parent
92754d6
commit 7460f7d
Showing
5 changed files
with
241 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#![no_main] | ||
#![no_std] | ||
|
||
extern crate panic_halt; | ||
|
||
use lpc8xx_hal::{cortex_m_rt::entry, delay::Delay, prelude::*, Peripherals}; | ||
|
||
#[entry] | ||
fn main() -> ! { | ||
// Get access to the device's peripherals. Since only one instance of this | ||
// struct can exist, the call to `take` returns an `Option<Peripherals>`. | ||
// If we tried to call the method a second time, it would return `None`, but | ||
// we're only calling it the one time here, so we can safely `unwrap` the | ||
// `Option` without causing a panic. | ||
let p = Peripherals::take().unwrap(); | ||
|
||
// Initialize the APIs of the peripherals we need. | ||
let swm = p.SWM.split(); | ||
let mut delay = Delay::new(p.SYST); | ||
let mut syscon = p.SYSCON.split(); | ||
|
||
// TODO | ||
// Wait until #183 is fixed | ||
let mut handle = swm | ||
.handle | ||
.disable(&mut syscon.handle) | ||
.enable(&mut syscon.handle); | ||
|
||
// Use 8 bit pwm | ||
let (red_pwm, green_pwm, blue_pwm) = | ||
p.CTIMER0.start_pwm(256, 0, &mut syscon.handle); | ||
|
||
// Select pin for the RGB LED | ||
let green = swm.pins.pio1_0.into_swm_pin(); | ||
let blue = swm.pins.pio1_1.into_swm_pin(); | ||
let red = swm.pins.pio1_2.into_swm_pin(); | ||
|
||
// Configure the LED pins. The API tracks the state of pins at compile time, | ||
// to prevent any mistakes. | ||
let (red, _) = swm.movable_functions.t0_mat0.assign(red, &mut handle); | ||
let (green, _) = swm.movable_functions.t0_mat1.assign(green, &mut handle); | ||
let (blue, _) = swm.movable_functions.t0_mat2.assign(blue, &mut handle); | ||
|
||
let mut red = red_pwm.configure(red); | ||
let mut green = green_pwm.configure(green); | ||
let mut blue = blue_pwm.configure(blue); | ||
// Fade each color after anothe | ||
loop { | ||
for i in 0..red.get_max_duty() { | ||
delay.delay_ms(4_u8); | ||
red.set_duty(i); | ||
} | ||
for i in (0..red.get_max_duty()).rev() { | ||
delay.delay_ms(4_u8); | ||
red.set_duty(i); | ||
} | ||
for i in 0..green.get_max_duty() { | ||
delay.delay_ms(4_u8); | ||
green.set_duty(i); | ||
} | ||
for i in (0..green.get_max_duty()).rev() { | ||
delay.delay_ms(4_u8); | ||
green.set_duty(i); | ||
} | ||
for i in 0..blue.get_max_duty() { | ||
delay.delay_ms(4_u8); | ||
blue.set_duty(i); | ||
} | ||
for i in (0..blue.get_max_duty()).rev() { | ||
delay.delay_ms(4_u8); | ||
blue.set_duty(i); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
//! PwmPin implementation based on CTimer | ||
//! | ||
//! | ||
|
||
// Use the timer as one 32 bit timer | ||
// Don't implement prescaling, since it isn't needed | ||
// Currently only implemented for lpc845 | ||
use crate::pac::CTIMER0; | ||
use crate::swm::{self, PinTrait, T0_MAT0, T0_MAT1, T0_MAT2}; | ||
use crate::syscon::{self}; | ||
use core::marker::PhantomData; | ||
use embedded_hal::PwmPin; | ||
|
||
/// Interface to a CTimer peripheral | ||
/// | ||
/// Controls the CTimer. Use [`Peripherals`] to gain access to an instance of | ||
/// this struct. | ||
/// | ||
/// Please refer to the [module documentation] for more information. | ||
/// | ||
/// [`Peripherals`]: ../struct.Peripherals.html | ||
/// [module documentation]: index.html | ||
pub struct CTimer { | ||
ct: CTIMER0, | ||
} | ||
|
||
/// An unconfigured PwmPin | ||
pub struct UnconfiguredPwmPin<CTOutput> { | ||
number: u8, | ||
// TODO Do the specific registers properly | ||
output: PhantomData<CTOutput>, | ||
} | ||
|
||
/// TODO | ||
pub struct CTimerPwmPin { | ||
number: u8, | ||
} | ||
|
||
impl CTimer { | ||
pub(crate) fn new(ct: CTIMER0) -> Self { | ||
Self { ct } | ||
} | ||
|
||
/// TODO | ||
pub fn start_pwm( | ||
self, | ||
period: u32, | ||
prescaler: u32, | ||
syscon: &mut syscon::Handle, | ||
) -> ( | ||
UnconfiguredPwmPin<T0_MAT0>, | ||
UnconfiguredPwmPin<T0_MAT1>, | ||
UnconfiguredPwmPin<T0_MAT2>, | ||
) { | ||
syscon.enable_clock(&self.ct); | ||
unsafe { self.ct.pr.write(|w| w.prval().bits(prescaler)) }; | ||
// Use MAT3 to reset the counter | ||
unsafe { self.ct.mr[3].write(|w| w.match_().bits(period)) }; | ||
self.ct.mcr.write(|w| { | ||
w.mr3r().set_bit(); | ||
// Use shadow registers for the pwm output matches | ||
w.mr0rl().set_bit(); | ||
w.mr1rl().set_bit(); | ||
w.mr2rl().set_bit() | ||
}); | ||
|
||
self.ct.pwmc.write(|w| { | ||
w.pwmen0().set_bit(); | ||
w.pwmen1().set_bit(); | ||
w.pwmen2().set_bit() | ||
}); | ||
|
||
// Start the timer | ||
self.ct.tcr.write(|w| w.cen().set_bit()); | ||
( | ||
UnconfiguredPwmPin { | ||
number: 0, | ||
output: PhantomData {}, | ||
}, | ||
UnconfiguredPwmPin { | ||
number: 1, | ||
output: PhantomData {}, | ||
}, | ||
UnconfiguredPwmPin { | ||
number: 2, | ||
output: PhantomData {}, | ||
}, | ||
) | ||
} | ||
|
||
/// Return the raw peripheral | ||
/// | ||
/// This method serves as an escape hatch from the HAL API. It returns the | ||
/// raw peripheral, allowing you to do whatever you want with it, without | ||
/// limitations imposed by the API. | ||
/// | ||
/// If you are using this method because a feature you need is missing from | ||
/// the HAL API, please [open an issue] or, if an issue for your feature | ||
/// request already exists, comment on the existing issue, so we can | ||
/// prioritize it accordingly. | ||
/// | ||
/// [open an issue]: https://github.com/lpc-rs/lpc8xx-hal/issues | ||
pub fn free(self) -> CTIMER0 { | ||
self.ct | ||
} | ||
} | ||
|
||
impl<CTOutput> UnconfiguredPwmPin<CTOutput> { | ||
/// Assings a pin to an `UnconfiguredPwmOutput`, | ||
/// allowing it to be used as a pwm output | ||
pub fn configure<PWM>( | ||
self, | ||
_: swm::Function<CTOutput, swm::state::Assigned<PWM>>, | ||
) -> CTimerPwmPin | ||
where | ||
PWM: PinTrait, | ||
{ | ||
CTimerPwmPin { | ||
number: self.number, | ||
} | ||
} | ||
} | ||
|
||
impl PwmPin for CTimerPwmPin { | ||
type Duty = u32; | ||
fn enable(&mut self) { | ||
// TODO | ||
} | ||
|
||
fn disable(&mut self) { | ||
// TODO | ||
} | ||
|
||
fn get_duty(&self) -> Self::Duty { | ||
unsafe { &(*CTIMER0::ptr()).msr[self.number as usize] } | ||
.read() | ||
.match_shadow() | ||
.bits() | ||
} | ||
|
||
fn get_max_duty(&self) -> Self::Duty { | ||
unsafe { &(*CTIMER0::ptr()).mr[3] }.read().match_().bits() | ||
} | ||
|
||
fn set_duty(&mut self, duty: Self::Duty) { | ||
let reg = unsafe { &(*CTIMER0::ptr()).msr[self.number as usize] }; | ||
unsafe { reg.write(|w| w.match_shadow().bits(duty)) }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters