aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/pwm.rs24
-rw-r--r--examples/nrf/src/bin/pwm_sequence.rs8
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ppi.rs4
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ws2812b.rs43
4 files changed, 58 insertions, 21 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 41dcce049..94dfdeda6 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -31,6 +31,8 @@ pub struct SequencePwm<'d, T: Instance> {
31 ch1: Option<AnyPin>, 31 ch1: Option<AnyPin>,
32 ch2: Option<AnyPin>, 32 ch2: Option<AnyPin>,
33 ch3: Option<AnyPin>, 33 ch3: Option<AnyPin>,
34 sequence0: Option<Sequence<'d>>,
35 sequence1: Option<Sequence<'d>>,
34} 36}
35 37
36#[derive(Debug, Clone, Copy, PartialEq, Eq)] 38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -125,11 +127,13 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
125 ch1: ch1.degrade_optional(), 127 ch1: ch1.degrade_optional(),
126 ch2: ch2.degrade_optional(), 128 ch2: ch2.degrade_optional(),
127 ch3: ch3.degrade_optional(), 129 ch3: ch3.degrade_optional(),
130 sequence0: None,
131 sequence1: None,
128 }) 132 })
129 } 133 }
130 134
131 /// Start or restart playback. Takes at least one sequence along with its 135 /// Start or restart playback. Takes at least one sequence along with its
132 /// configuration. Optionally takes a second sequence and/or its configuration. 136 /// configuration. Optionally takes a second sequence and its configuration.
133 /// In the case where no second sequence is provided then the first sequence 137 /// In the case where no second sequence is provided then the first sequence
134 /// is used. The sequence mode applies to both sequences combined as one. 138 /// is used. The sequence mode applies to both sequences combined as one.
135 #[inline(always)] 139 #[inline(always)]
@@ -152,7 +156,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
152 return Err(Error::SequenceTimesAtLeastOne); 156 return Err(Error::SequenceTimesAtLeastOne);
153 } 157 }
154 158
155 self.stop(); 159 let _ = self.stop();
156 160
157 let r = T::regs(); 161 let r = T::regs();
158 162
@@ -222,6 +226,9 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
222 } 226 }
223 } 227 }
224 228
229 self.sequence0 = Some(sequence0);
230 self.sequence1 = sequence1;
231
225 Ok(()) 232 Ok(())
226 } 233 }
227 234
@@ -326,9 +333,10 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
326 } 333 }
327 334
328 /// Stop playback. Disables the peripheral. Does NOT clear the last duty 335 /// Stop playback. Disables the peripheral. Does NOT clear the last duty
329 /// cycle from the pin. 336 /// cycle from the pin. Returns any sequences previously provided to
337 /// `start` so that they may be further mutated.
330 #[inline(always)] 338 #[inline(always)]
331 pub fn stop(&self) { 339 pub fn stop(&mut self) -> (Option<Sequence<'d>>, Option<Sequence<'d>>) {
332 let r = T::regs(); 340 let r = T::regs();
333 341
334 r.shorts.reset(); 342 r.shorts.reset();
@@ -339,6 +347,8 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
339 r.tasks_stop.write(|w| unsafe { w.bits(0x01) }); 347 r.tasks_stop.write(|w| unsafe { w.bits(0x01) });
340 348
341 r.enable.write(|w| w.enable().disabled()); 349 r.enable.write(|w| w.enable().disabled());
350
351 (self.sequence0.take(), self.sequence1.take())
342 } 352 }
343} 353}
344 354
@@ -346,7 +356,7 @@ impl<'a, T: Instance> Drop for SequencePwm<'a, T> {
346 fn drop(&mut self) { 356 fn drop(&mut self) {
347 let r = T::regs(); 357 let r = T::regs();
348 358
349 self.stop(); 359 let _ = self.stop();
350 360
351 if let Some(pin) = &self.ch0 { 361 if let Some(pin) = &self.ch0 {
352 pin.set_low(); 362 pin.set_low();
@@ -415,13 +425,13 @@ impl Default for SequenceConfig {
415#[non_exhaustive] 425#[non_exhaustive]
416pub struct Sequence<'d> { 426pub struct Sequence<'d> {
417 /// The words comprising the sequence. Must not exceed 32767 words. 427 /// The words comprising the sequence. Must not exceed 32767 words.
418 pub words: &'d [u16], 428 pub words: &'d mut [u16],
419 /// Configuration associated with the sequence. 429 /// Configuration associated with the sequence.
420 pub config: SequenceConfig, 430 pub config: SequenceConfig,
421} 431}
422 432
423impl<'d> Sequence<'d> { 433impl<'d> Sequence<'d> {
424 pub fn new(words: &'d [u16], config: SequenceConfig) -> Self { 434 pub fn new(words: &'d mut [u16], config: SequenceConfig) -> Self {
425 Self { words, config } 435 Self { words, config }
426 } 436 }
427} 437}
diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs
index 78787d531..6fb861e8f 100644
--- a/examples/nrf/src/bin/pwm_sequence.rs
+++ b/examples/nrf/src/bin/pwm_sequence.rs
@@ -13,8 +13,8 @@ use embassy_nrf::Peripherals;
13 13
14#[embassy::main] 14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; 16 let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0];
17 let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; 17 let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000];
18 18
19 let mut config = Config::default(); 19 let mut config = Config::default();
20 config.prescaler = Prescaler::Div128; 20 config.prescaler = Prescaler::Div128;
@@ -30,7 +30,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
30 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 30 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
31 )); 31 ));
32 let _ = pwm.start( 32 let _ = pwm.start(
33 Sequence::new(&seq_words_1, seq_config.clone()), 33 Sequence::new(&mut seq_words_1, seq_config.clone()),
34 None, 34 None,
35 SequenceMode::Infinite, 35 SequenceMode::Infinite,
36 ); 36 );
@@ -41,7 +41,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
41 info!("pwm starting with another sequence!"); 41 info!("pwm starting with another sequence!");
42 42
43 let _ = pwm.start( 43 let _ = pwm.start(
44 Sequence::new(&seq_words_2, seq_config), 44 Sequence::new(&mut seq_words_2, seq_config),
45 None, 45 None,
46 SequenceMode::Infinite, 46 SequenceMode::Infinite,
47 ); 47 );
diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs
index c80820f84..f5d734bb1 100644
--- a/examples/nrf/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs
@@ -16,7 +16,7 @@ use embassy_nrf::Peripherals;
16 16
17#[embassy::main] 17#[embassy::main]
18async fn main(_spawner: Spawner, p: Peripherals) { 18async fn main(_spawner: Spawner, p: Peripherals) {
19 let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; 19 let mut seq_words: [u16; 5] = [1000, 250, 100, 50, 0];
20 20
21 let mut config = Config::default(); 21 let mut config = Config::default();
22 config.prescaler = Prescaler::Div128; 22 config.prescaler = Prescaler::Div128;
@@ -32,7 +32,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
32 )); 32 ));
33 33
34 let _ = pwm.start( 34 let _ = pwm.start(
35 Sequence::new(&seq_words, seq_config), 35 Sequence::new(&mut seq_words, seq_config),
36 None, 36 None,
37 SequenceMode::Infinite, 37 SequenceMode::Infinite,
38 ); 38 );
diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
index 2fb37015d..0ce79cbe0 100644
--- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
@@ -15,7 +15,9 @@ use embassy_nrf::Peripherals;
15 15
16// WS2812B LED light demonstration. Drives just one light. 16// WS2812B LED light demonstration. Drives just one light.
17// The following reference on WS2812B may be of use: 17// The following reference on WS2812B may be of use:
18// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf 18// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf.
19// This demo lights up a single LED in blue. It then proceeds
20// to pulsate the LED rapidly.
19 21
20// In the following declarations, setting the high bit tells the PWM 22// In the following declarations, setting the high bit tells the PWM
21// to reverse polarity, which is what the WS2812B expects. 23// to reverse polarity, which is what the WS2812B expects.
@@ -29,17 +31,17 @@ const RES: u16 = 0x8000;
29#[embassy::main] 31#[embassy::main]
30async fn main(_spawner: Spawner, p: Peripherals) { 32async fn main(_spawner: Spawner, p: Peripherals) {
31 // Declare the bits of 24 bits 33 // Declare the bits of 24 bits
32 let blue_seq_words = [ 34 let mut color_seq_words = [
33 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G 35 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G
34 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R 36 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R
35 T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B 37 T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B
36 ]; 38 ];
37 let blue_seq = Sequence::new(&blue_seq_words, SequenceConfig::default()); 39 let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default());
38 40
39 let reset_seq_words = [RES; 1]; 41 let mut reset_seq_words = [RES; 1];
40 let mut reset_seq_config = SequenceConfig::default(); 42 let mut reset_seq_config = SequenceConfig::default();
41 reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; 43 reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES;
42 let reset_seq = Sequence::new(&reset_seq_words, reset_seq_config); 44 let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config);
43 45
44 let mut config = Config::default(); 46 let mut config = Config::default();
45 config.sequence_load = SequenceLoad::Common; 47 config.sequence_load = SequenceLoad::Common;
@@ -49,8 +51,33 @@ async fn main(_spawner: Spawner, p: Peripherals) {
49 p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, 51 p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config,
50 )); 52 ));
51 53
52 unwrap!(pwm.start(blue_seq, Some(reset_seq), SequenceMode::Times(2))); 54 unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2)));
53 55
54 Timer::after(Duration::from_millis(20000)).await; 56 Timer::after(Duration::from_millis(1000)).await;
55 info!("Program stopped"); 57
58 let mut color_bit = 16;
59 let mut bit_value = T0H;
60
61 loop {
62 if let (Some(color_seq), Some(reset_seq)) = pwm.stop() {
63 color_seq.words[color_bit] = bit_value;
64 unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2)));
65 }
66
67 Timer::after(Duration::from_millis(50)).await;
68
69 if bit_value == T0H {
70 if color_bit == 20 {
71 bit_value = T1H;
72 } else {
73 color_bit += 1;
74 }
75 } else {
76 if color_bit == 16 {
77 bit_value = T0H;
78 } else {
79 color_bit -= 1;
80 }
81 }
82 }
56} 83}