Merge #585
585: Permit many sequences to be passed r=huntc a=huntc Sequences are now passed in via the start method to avoid having to stop the PWM and restart it. Sequences continue to be constrained with the same lifetime of the Pwm struct itself. The pwm_sequence example has been extended to illustrate multiple sequences being passed around. Co-authored-by: huntc <huntchr@gmail.com>
This commit is contained in:
commit
0549a9dbaa
@ -63,14 +63,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
|||||||
ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||||
ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||||
config: SequenceConfig,
|
config: SequenceConfig,
|
||||||
sequence: &'d [u16],
|
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
slice_in_ram_or(sequence, Error::DMABufferNotInDataMemory)?;
|
|
||||||
|
|
||||||
if sequence.len() > 32767 {
|
|
||||||
return Err(Error::SequenceTooLong);
|
|
||||||
}
|
|
||||||
|
|
||||||
unborrow!(ch0, ch1, ch2, ch3);
|
unborrow!(ch0, ch1, ch2, ch3);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
@ -110,28 +103,6 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
|||||||
r.events_seqstarted[0].reset();
|
r.events_seqstarted[0].reset();
|
||||||
r.events_seqstarted[1].reset();
|
r.events_seqstarted[1].reset();
|
||||||
|
|
||||||
r.seq0
|
|
||||||
.ptr
|
|
||||||
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
|
||||||
r.seq0
|
|
||||||
.cnt
|
|
||||||
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
|
||||||
r.seq0.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
|
||||||
r.seq0
|
|
||||||
.enddelay
|
|
||||||
.write(|w| unsafe { w.bits(config.end_delay) });
|
|
||||||
|
|
||||||
r.seq1
|
|
||||||
.ptr
|
|
||||||
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
|
||||||
r.seq1
|
|
||||||
.cnt
|
|
||||||
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
|
||||||
r.seq1.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
|
||||||
r.seq1
|
|
||||||
.enddelay
|
|
||||||
.write(|w| unsafe { w.bits(config.end_delay) });
|
|
||||||
|
|
||||||
r.decoder.write(|w| {
|
r.decoder.write(|w| {
|
||||||
w.load().bits(config.sequence_load as u8);
|
w.load().bits(config.sequence_load as u8);
|
||||||
w.mode().refresh_count()
|
w.mode().refresh_count()
|
||||||
@ -146,6 +117,16 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
|||||||
r.countertop
|
r.countertop
|
||||||
.write(|w| unsafe { w.countertop().bits(config.max_duty) });
|
.write(|w| unsafe { w.countertop().bits(config.max_duty) });
|
||||||
|
|
||||||
|
r.seq0.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
||||||
|
r.seq0
|
||||||
|
.enddelay
|
||||||
|
.write(|w| unsafe { w.bits(config.end_delay) });
|
||||||
|
|
||||||
|
r.seq1.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
||||||
|
r.seq1
|
||||||
|
.enddelay
|
||||||
|
.write(|w| unsafe { w.bits(config.end_delay) });
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
ch0: ch0.degrade_optional(),
|
ch0: ch0.degrade_optional(),
|
||||||
@ -157,12 +138,33 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
|||||||
|
|
||||||
/// Start or restart playback
|
/// Start or restart playback
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn start(&self, times: SequenceMode) -> Result<(), Error> {
|
pub fn start(&mut self, sequence: &'d [u16], times: SequenceMode) -> Result<(), Error> {
|
||||||
|
slice_in_ram_or(sequence, Error::DMABufferNotInDataMemory)?;
|
||||||
|
|
||||||
|
if sequence.len() > 32767 {
|
||||||
|
return Err(Error::SequenceTooLong);
|
||||||
|
}
|
||||||
|
|
||||||
if let SequenceMode::Times(0) = times {
|
if let SequenceMode::Times(0) = times {
|
||||||
return Err(Error::SequenceTimesAtLeastOne);
|
return Err(Error::SequenceTimesAtLeastOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
|
r.seq0
|
||||||
|
.ptr
|
||||||
|
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
||||||
|
r.seq0
|
||||||
|
.cnt
|
||||||
|
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
||||||
|
|
||||||
|
r.seq1
|
||||||
|
.ptr
|
||||||
|
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
||||||
|
r.seq1
|
||||||
|
.cnt
|
||||||
|
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
||||||
|
|
||||||
self.stop();
|
self.stop();
|
||||||
|
|
||||||
r.enable.write(|w| w.enable().enabled());
|
r.enable.write(|w| w.enable().enabled());
|
||||||
|
@ -13,7 +13,8 @@ use embassy_nrf::Peripherals;
|
|||||||
|
|
||||||
#[embassy::main]
|
#[embassy::main]
|
||||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||||
let seq_values: [u16; 5] = [1000, 250, 100, 50, 0];
|
let seq_values_1: [u16; 5] = [1000, 250, 100, 50, 0];
|
||||||
|
let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000];
|
||||||
|
|
||||||
let mut config = SequenceConfig::default();
|
let mut config = SequenceConfig::default();
|
||||||
config.prescaler = Prescaler::Div128;
|
config.prescaler = Prescaler::Div128;
|
||||||
@ -24,19 +25,18 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
|||||||
config.refresh = 624;
|
config.refresh = 624;
|
||||||
// thus our sequence takes 5 * 5000ms or 25 seconds
|
// thus our sequence takes 5 * 5000ms or 25 seconds
|
||||||
|
|
||||||
let pwm = unwrap!(SequencePwm::new(
|
let mut pwm = unwrap!(SequencePwm::new(
|
||||||
p.PWM0,
|
p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
|
||||||
p.P0_13,
|
|
||||||
NoPin,
|
|
||||||
NoPin,
|
|
||||||
NoPin,
|
|
||||||
config,
|
|
||||||
&seq_values
|
|
||||||
));
|
));
|
||||||
let _ = pwm.start(SequenceMode::Infinite);
|
let _ = pwm.start(&seq_values_1, SequenceMode::Infinite);
|
||||||
|
|
||||||
info!("pwm started!");
|
info!("pwm started!");
|
||||||
|
|
||||||
|
Timer::after(Duration::from_millis(20000)).await;
|
||||||
|
info!("pwm starting with another sequence!");
|
||||||
|
|
||||||
|
let _ = pwm.start(&seq_values_2, SequenceMode::Infinite);
|
||||||
|
|
||||||
// we can abort a sequence if we need to before its complete with pwm.stop()
|
// we can abort a sequence if we need to before its complete with pwm.stop()
|
||||||
// or stop is also implicitly called when the pwm peripheral is dropped
|
// or stop is also implicitly called when the pwm peripheral is dropped
|
||||||
// when it goes out of scope
|
// when it goes out of scope
|
||||||
|
@ -26,17 +26,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
|||||||
// thus our sequence takes 5 * 250ms or 1.25 seconds
|
// thus our sequence takes 5 * 250ms or 1.25 seconds
|
||||||
config.refresh = 30;
|
config.refresh = 30;
|
||||||
|
|
||||||
let pwm = unwrap!(SequencePwm::new(
|
let mut pwm = unwrap!(SequencePwm::new(
|
||||||
p.PWM0,
|
p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
|
||||||
p.P0_13,
|
|
||||||
NoPin,
|
|
||||||
NoPin,
|
|
||||||
NoPin,
|
|
||||||
config,
|
|
||||||
&seq_values
|
|
||||||
));
|
));
|
||||||
|
|
||||||
let _ = pwm.start(SequenceMode::Times(1));
|
let _ = pwm.start(&seq_values, SequenceMode::Times(1));
|
||||||
// pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
|
// pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
|
||||||
// so its going to have to start running in order load the configuration
|
// so its going to have to start running in order load the configuration
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user