aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhuntc <[email protected]>2022-02-04 19:11:15 +1100
committerhuntc <[email protected]>2022-02-04 19:11:15 +1100
commit965a5f2c3fba365519bed1c2a955145783d6a05b (patch)
treecc0b60b0a809d01e0e2634032693e6c4bae879d4
parent9e36ede363b66c3e007d8cb0c477234b88ba0737 (diff)
Introduced the SingleSequencer and a more complex Sequencer
-rw-r--r--embassy-nrf/src/pwm.rs113
-rw-r--r--examples/nrf/src/bin/pwm_double_sequence.rs46
-rw-r--r--examples/nrf/src/bin/pwm_sequence.rs22
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ppi.rs14
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ws2812b.rs7
5 files changed, 134 insertions, 68 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 55863ea56..c0d73bdc5 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -314,26 +314,58 @@ impl<'s> Sequence<'s> {
314 } 314 }
315} 315}
316 316
317/// A single sequence that can be started and stopped.
318/// Takes at one sequence along with its configuration.
319#[non_exhaustive]
320pub struct SingleSequencer<'d, 's, T: Instance> {
321 pub sequencer: Sequencer<'d, 's, T>,
322}
323
324impl<'d, 's, T: Instance> SingleSequencer<'d, 's, T> {
325 /// Create a new sequencer
326 pub fn new(pwm: &'s mut SequencePwm<'d, T>, sequence: Sequence<'s>) -> Self {
327 Self {
328 sequencer: Sequencer::new(pwm, sequence, None),
329 }
330 }
331
332 /// Start or restart playback.
333 #[inline(always)]
334 pub fn start(&self, times: SingleSequenceMode) -> Result<(), Error> {
335 let (start_seq, times) = match times {
336 SingleSequenceMode::Times(n) if n == 1 => (StartSequence::One, SequenceMode::Loop(1)),
337 SingleSequenceMode::Times(n) if n & 1 == 1 => {
338 (StartSequence::One, SequenceMode::Loop((n / 2) + 1))
339 }
340 SingleSequenceMode::Times(n) => (StartSequence::Zero, SequenceMode::Loop(n / 2)),
341 SingleSequenceMode::Infinite => (StartSequence::Zero, SequenceMode::Infinite),
342 };
343 self.sequencer.start(start_seq, times)
344 }
345}
346
317/// A composition of sequences that can be started and stopped. 347/// A composition of sequences that can be started and stopped.
318/// Takes at least one sequence along with its configuration. 348/// Takes at least one sequence along with its configuration.
319/// Optionally takes a second sequence and its configuration. 349/// Optionally takes a second sequence and its configuration.
320/// In the case where no second sequence is provided then the first sequence 350/// In the case where no second sequence is provided then the first sequence
321/// is used. 351/// is used.
322#[non_exhaustive] 352#[non_exhaustive]
323pub struct Sequences<'d, 's, T: Instance> { 353pub struct Sequencer<'d, 's, T: Instance> {
324 pub pwm: &'s mut SequencePwm<'d, T>, 354 _pwm: &'s mut SequencePwm<'d, T>,
325 sequence0: Sequence<'s>, 355 sequence0: Sequence<'s>,
326 sequence1: Option<Sequence<'s>>, 356 sequence1: Option<Sequence<'s>>,
327} 357}
328 358
329impl<'d, 's, T: Instance> Sequences<'d, 's, T> { 359impl<'d, 's, T: Instance> Sequencer<'d, 's, T> {
360 /// Create a new double sequence. In the absence of sequence 1, sequence 0
361 /// will be used twice in the one loop.
330 pub fn new( 362 pub fn new(
331 pwm: &'s mut SequencePwm<'d, T>, 363 pwm: &'s mut SequencePwm<'d, T>,
332 sequence0: Sequence<'s>, 364 sequence0: Sequence<'s>,
333 sequence1: Option<Sequence<'s>>, 365 sequence1: Option<Sequence<'s>>,
334 ) -> Self { 366 ) -> Self {
335 Sequences { 367 Sequencer {
336 pwm, 368 _pwm: pwm,
337 sequence0, 369 sequence0,
338 sequence1, 370 sequence1,
339 } 371 }
@@ -341,7 +373,7 @@ impl<'d, 's, T: Instance> Sequences<'d, 's, T> {
341 373
342 /// Start or restart playback. The sequence mode applies to both sequences combined as one. 374 /// Start or restart playback. The sequence mode applies to both sequences combined as one.
343 #[inline(always)] 375 #[inline(always)]
344 pub fn start(&self, times: SequenceMode) -> Result<(), Error> { 376 pub fn start(&self, start_seq: StartSequence, times: SequenceMode) -> Result<(), Error> {
345 let sequence0 = &self.sequence0; 377 let sequence0 = &self.sequence0;
346 let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0); 378 let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0);
347 379
@@ -352,7 +384,7 @@ impl<'d, 's, T: Instance> Sequences<'d, 's, T> {
352 return Err(Error::SequenceTooLong); 384 return Err(Error::SequenceTooLong);
353 } 385 }
354 386
355 if let SequenceMode::Times(0) = times { 387 if let SequenceMode::Loop(0) = times {
356 return Err(Error::SequenceTimesAtLeastOne); 388 return Err(Error::SequenceTimesAtLeastOne);
357 } 389 }
358 390
@@ -391,41 +423,27 @@ impl<'d, 's, T: Instance> Sequences<'d, 's, T> {
391 // defensive before seqstart 423 // defensive before seqstart
392 compiler_fence(Ordering::SeqCst); 424 compiler_fence(Ordering::SeqCst);
393 425
426 let seqstart_index = if start_seq == StartSequence::One {
427 1
428 } else {
429 0
430 };
431
394 match times { 432 match times {
395 // just the one time, no loop count 433 // just the one time, no loop count
396 SequenceMode::Times(1) => { 434 SequenceMode::Loop(n) => {
397 r.loop_.write(|w| w.cnt().disabled()); 435 r.loop_.write(|w| unsafe { w.cnt().bits(n) });
398 // tasks_seqstart() doesn't exist in all svds so write its bit instead
399 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
400 }
401 // loop count is how many times to play BOTH sequences
402 // 2 total (1 x 2)
403 // 3 total, (2 x 2) - 1
404 SequenceMode::Times(n) => {
405 let odd = n & 1 == 1;
406 let times = if odd { (n / 2) + 1 } else { n / 2 };
407
408 r.loop_.write(|w| unsafe { w.cnt().bits(times) });
409
410 // we can subtract 1 by starting at seq1 instead of seq0
411 if odd {
412 // tasks_seqstart() doesn't exist in all svds so write its bit instead
413 r.tasks_seqstart[1].write(|w| unsafe { w.bits(0x01) });
414 } else {
415 // tasks_seqstart() doesn't exist in all svds so write its bit instead
416 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
417 }
418 } 436 }
419 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again 437 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again
420 SequenceMode::Infinite => { 438 SequenceMode::Infinite => {
421 r.loop_.write(|w| unsafe { w.cnt().bits(0x1) }); 439 r.loop_.write(|w| unsafe { w.cnt().bits(0x1) });
422 r.shorts.write(|w| w.loopsdone_seqstart0().enabled()); 440 r.shorts.write(|w| w.loopsdone_seqstart0().enabled());
423
424 // tasks_seqstart() doesn't exist in all svds so write its bit instead
425 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
426 } 441 }
427 } 442 }
428 443
444 // tasks_seqstart() doesn't exist in all svds so write its bit instead
445 r.tasks_seqstart[seqstart_index].write(|w| unsafe { w.bits(0x01) });
446
429 Ok(()) 447 Ok(())
430 } 448 }
431 449
@@ -447,26 +465,39 @@ impl<'d, 's, T: Instance> Sequences<'d, 's, T> {
447 } 465 }
448} 466}
449 467
450impl<'d, 's, T: Instance> Drop for Sequences<'d, 's, T> { 468impl<'d, 's, T: Instance> Drop for Sequencer<'d, 's, T> {
451 fn drop(&mut self) { 469 fn drop(&mut self) {
452 let _ = self.stop(); 470 let _ = self.stop();
453 } 471 }
454} 472}
455 473
456/// How many times to run the sequence 474/// How many times to run a single sequence
457#[derive(Debug, Eq, PartialEq, Clone, Copy)] 475#[derive(Debug, Eq, PartialEq, Clone, Copy)]
458pub enum SequenceMode { 476pub enum SingleSequenceMode {
459 /// Run sequence n Times total. 477 /// Run a single sequence n Times total.
460 /// 1 = Run sequence 0 once
461 /// 2 = Run sequence 0 and then sequence 1
462 /// 3 = Run sequence 1, sequence 0, sequence 1 and then sequence 0
463 /// 4 = Run sequence 0, sequence 1, sequence 0 and then sequence 1
464 /// ...and so on.
465 Times(u16), 478 Times(u16),
466 /// Repeat until `stop` is called. 479 /// Repeat until `stop` is called.
467 Infinite, 480 Infinite,
468} 481}
469 482
483/// Which sequence to start a loop with
484#[derive(Debug, Eq, PartialEq, Clone, Copy)]
485pub enum StartSequence {
486 /// Start with Sequence 0
487 Zero,
488 /// Start with Sequence 1
489 One,
490}
491
492/// How many loops to run two sequences
493#[derive(Debug, Eq, PartialEq, Clone, Copy)]
494pub enum SequenceMode {
495 /// Run two sequences n loops i.e. (n * (seq0 + seq1.unwrap_or(seq0)))
496 Loop(u16),
497 /// Repeat until `stop` is called.
498 Infinite,
499}
500
470/// PWM Base clock is system clock (16MHz) divided by prescaler 501/// PWM Base clock is system clock (16MHz) divided by prescaler
471#[derive(Debug, Eq, PartialEq, Clone, Copy)] 502#[derive(Debug, Eq, PartialEq, Clone, Copy)]
472pub enum Prescaler { 503pub enum Prescaler {
diff --git a/examples/nrf/src/bin/pwm_double_sequence.rs b/examples/nrf/src/bin/pwm_double_sequence.rs
new file mode 100644
index 000000000..269015f4a
--- /dev/null
+++ b/examples/nrf/src/bin/pwm_double_sequence.rs
@@ -0,0 +1,46 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use defmt::*;
8use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer};
10use embassy_nrf::gpio::NoPin;
11use embassy_nrf::pwm::{
12 Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequencer,
13 StartSequence,
14};
15use embassy_nrf::Peripherals;
16
17#[embassy::main]
18async fn main(_spawner: Spawner, p: Peripherals) {
19 let seq_words_0: [u16; 5] = [1000, 250, 100, 50, 0];
20 let seq_words_1: [u16; 4] = [50, 100, 250, 1000];
21
22 let mut config = Config::default();
23 config.prescaler = Prescaler::Div128;
24 // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us
25 // but say we want to hold the value for 5000ms
26 // so we want to repeat our value as many times as necessary until 5000ms passes
27 // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember)
28 let mut seq_config = SequenceConfig::default();
29 seq_config.refresh = 624;
30 // thus our sequence takes 5 * 5000ms or 25 seconds
31
32 let mut pwm = unwrap!(SequencePwm::new(
33 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
34 ));
35
36 let sequence_0 = Sequence::new(&seq_words_0, seq_config.clone());
37 let sequence_1 = Sequence::new(&seq_words_1, seq_config);
38 let sequencer = Sequencer::new(&mut pwm, sequence_0, Some(sequence_1));
39 unwrap!(sequencer.start(StartSequence::Zero, SequenceMode::Loop(1)));
40
41 // we can abort a sequence if we need to before its complete with pwm.stop()
42 // or stop is also implicitly called when the pwm peripheral is dropped
43 // when it goes out of scope
44 Timer::after(Duration::from_millis(40000)).await;
45 info!("pwm stopped early!");
46}
diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs
index b31c12a23..761ac0f03 100644
--- a/examples/nrf/src/bin/pwm_sequence.rs
+++ b/examples/nrf/src/bin/pwm_sequence.rs
@@ -9,14 +9,13 @@ use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer}; 9use embassy::time::{Duration, Timer};
10use embassy_nrf::gpio::NoPin; 10use embassy_nrf::gpio::NoPin;
11use embassy_nrf::pwm::{ 11use embassy_nrf::pwm::{
12 Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, 12 Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer,
13}; 13};
14use embassy_nrf::Peripherals; 14use embassy_nrf::Peripherals;
15 15
16#[embassy::main] 16#[embassy::main]
17async fn main(_spawner: Spawner, p: Peripherals) { 17async fn main(_spawner: Spawner, p: Peripherals) {
18 let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; 18 let seq_words: [u16; 5] = [1000, 250, 100, 50, 0];
19 let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000];
20 19
21 let mut config = Config::default(); 20 let mut config = Config::default();
22 config.prescaler = Prescaler::Div128; 21 config.prescaler = Prescaler::Div128;
@@ -32,20 +31,9 @@ async fn main(_spawner: Spawner, p: Peripherals) {
32 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 31 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
33 )); 32 ));
34 33
35 let sequence0 = Sequence::new(&seq_words_1, seq_config.clone()); 34 let sequence = Sequence::new(&seq_words, seq_config.clone());
36 let sequences = Sequences::new(&mut pwm, sequence0, None); 35 let sequencer = SingleSequencer::new(&mut pwm, sequence);
37 unwrap!(sequences.start(SequenceMode::Times(1))); 36 unwrap!(sequencer.start(SingleSequenceMode::Times(1)));
38
39 info!("pwm started!");
40
41 Timer::after(Duration::from_millis(20000)).await;
42 info!("pwm starting with another sequence!");
43
44 drop(sequences); // This stops the previous sequence and returns pwm ownership back
45
46 let sequence0 = Sequence::new(&seq_words_2, seq_config);
47 let sequences = Sequences::new(&mut pwm, sequence0, None);
48 unwrap!(sequences.start(SequenceMode::Times(1)));
49 37
50 // we can abort a sequence if we need to before its complete with pwm.stop() 38 // we can abort a sequence if we need to before its complete with pwm.stop()
51 // or stop is also implicitly called when the pwm peripheral is dropped 39 // or stop is also implicitly called when the pwm peripheral is dropped
diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs
index 593e7590d..7e58c37e6 100644
--- a/examples/nrf/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs
@@ -12,7 +12,7 @@ use embassy_nrf::gpio::{Input, NoPin, Pull};
12use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; 12use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity};
13use embassy_nrf::ppi::Ppi; 13use embassy_nrf::ppi::Ppi;
14use embassy_nrf::pwm::{ 14use embassy_nrf::pwm::{
15 Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, 15 Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer,
16}; 16};
17use embassy_nrf::Peripherals; 17use embassy_nrf::Peripherals;
18 18
@@ -33,10 +33,6 @@ async fn main(_spawner: Spawner, p: Peripherals) {
33 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 33 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
34 )); 34 ));
35 35
36 let sequence0 = Sequence::new(&seq_words, seq_config);
37 let sequences = Sequences::new(&mut pwm, sequence0, None);
38 unwrap!(sequences.start(SequenceMode::Infinite));
39
40 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 36 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
41 // so its going to have to start running in order load the configuration 37 // so its going to have to start running in order load the configuration
42 38
@@ -54,8 +50,12 @@ async fn main(_spawner: Spawner, p: Peripherals) {
54 50
55 // messing with the pwm tasks is ill advised 51 // messing with the pwm tasks is ill advised
56 // Times::Ininite and Times even are seq0, Times odd is seq1 52 // Times::Ininite and Times even are seq0, Times odd is seq1
57 let start = unsafe { sequences.pwm.task_start_seq0() }; 53 let start = unsafe { pwm.task_start_seq0() };
58 let stop = unsafe { sequences.pwm.task_stop() }; 54 let stop = unsafe { pwm.task_stop() };
55
56 let sequence = Sequence::new(&seq_words, seq_config);
57 let sequencer = SingleSequencer::new(&mut pwm, sequence);
58 unwrap!(sequencer.start(SingleSequenceMode::Infinite));
59 59
60 let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button1.event_in(), start); 60 let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button1.event_in(), start);
61 ppi.enable(); 61 ppi.enable();
diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
index c0c10373a..71ddd5283 100644
--- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
@@ -9,7 +9,8 @@ use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer}; 9use embassy::time::{Duration, Timer};
10use embassy_nrf::gpio::NoPin; 10use embassy_nrf::gpio::NoPin;
11use embassy_nrf::pwm::{ 11use embassy_nrf::pwm::{
12 Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, 12 Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode,
13 SingleSequencer,
13}; 14};
14use embassy_nrf::Peripherals; 15use embassy_nrf::Peripherals;
15 16
@@ -54,8 +55,8 @@ async fn main(_spawner: Spawner, p: Peripherals) {
54 55
55 loop { 56 loop {
56 let sequence0 = Sequence::new(&seq_words, seq_config.clone()); 57 let sequence0 = Sequence::new(&seq_words, seq_config.clone());
57 let sequences = Sequences::new(&mut pwm, sequence0, None); 58 let sequences = SingleSequencer::new(&mut pwm, sequence0);
58 unwrap!(sequences.start(SequenceMode::Times(1))); 59 unwrap!(sequences.start(SingleSequenceMode::Times(1)));
59 60
60 Timer::after(Duration::from_millis(50)).await; 61 Timer::after(Duration::from_millis(50)).await;
61 62