aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhuntc <[email protected]>2022-01-28 13:38:20 +1100
committerhuntc <[email protected]>2022-01-28 13:38:20 +1100
commit12ce02457438c1dd1566f3f3c43537ae4f54f699 (patch)
tree1631a972fe5de3f2e2850c6302abaea596101f7c
parent47aeab152fff59e64d8244475dfbec338e6f98e5 (diff)
Make the sequence a little nicer to pass around
-rw-r--r--embassy-nrf/src/pwm.rs46
-rw-r--r--examples/nrf/src/bin/pwm_sequence.rs18
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ppi.rs10
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ws2812b.rs22
4 files changed, 52 insertions, 44 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 21b450b19..97c02eddc 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -137,19 +137,16 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
137 #[inline(always)] 137 #[inline(always)]
138 pub fn start( 138 pub fn start(
139 &mut self, 139 &mut self,
140 sequence0: &'d [u16], 140 sequence0: Sequence<'d>,
141 sequence_config0: SequenceConfig, 141 sequence1: Option<Sequence<'d>>,
142 sequence1: Option<&'d [u16]>,
143 sequence_config1: Option<SequenceConfig>,
144 times: SequenceMode, 142 times: SequenceMode,
145 ) -> Result<(), Error> { 143 ) -> Result<(), Error> {
146 let alt_sequence = sequence1.unwrap_or(sequence0); 144 let alt_sequence = sequence1.as_ref().unwrap_or(&sequence0);
147 let alt_sequence_config = (&sequence_config1).as_ref().unwrap_or(&sequence_config0);
148 145
149 slice_in_ram_or(sequence0, Error::DMABufferNotInDataMemory)?; 146 slice_in_ram_or(sequence0.words, Error::DMABufferNotInDataMemory)?;
150 slice_in_ram_or(alt_sequence, Error::DMABufferNotInDataMemory)?; 147 slice_in_ram_or(alt_sequence.words, Error::DMABufferNotInDataMemory)?;
151 148
152 if sequence0.len() > MAX_SEQUENCE_LEN || alt_sequence.len() > MAX_SEQUENCE_LEN { 149 if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN {
153 return Err(Error::SequenceTooLong); 150 return Err(Error::SequenceTooLong);
154 } 151 }
155 152
@@ -163,29 +160,29 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
163 160
164 r.seq0 161 r.seq0
165 .refresh 162 .refresh
166 .write(|w| unsafe { w.bits(sequence_config0.refresh) }); 163 .write(|w| unsafe { w.bits(sequence0.config.refresh) });
167 r.seq0 164 r.seq0
168 .enddelay 165 .enddelay
169 .write(|w| unsafe { w.bits(sequence_config0.end_delay) }); 166 .write(|w| unsafe { w.bits(sequence0.config.end_delay) });
170 r.seq0 167 r.seq0
171 .ptr 168 .ptr
172 .write(|w| unsafe { w.bits(sequence0.as_ptr() as u32) }); 169 .write(|w| unsafe { w.bits(sequence0.words.as_ptr() as u32) });
173 r.seq0 170 r.seq0
174 .cnt 171 .cnt
175 .write(|w| unsafe { w.bits(sequence0.len() as u32) }); 172 .write(|w| unsafe { w.bits(sequence0.words.len() as u32) });
176 173
177 r.seq1 174 r.seq1
178 .refresh 175 .refresh
179 .write(|w| unsafe { w.bits(alt_sequence_config.refresh) }); 176 .write(|w| unsafe { w.bits(alt_sequence.config.refresh) });
180 r.seq1 177 r.seq1
181 .enddelay 178 .enddelay
182 .write(|w| unsafe { w.bits(alt_sequence_config.end_delay) }); 179 .write(|w| unsafe { w.bits(alt_sequence.config.end_delay) });
183 r.seq1 180 r.seq1
184 .ptr 181 .ptr
185 .write(|w| unsafe { w.bits(alt_sequence.as_ptr() as u32) }); 182 .write(|w| unsafe { w.bits(alt_sequence.words.as_ptr() as u32) });
186 r.seq1 183 r.seq1
187 .cnt 184 .cnt
188 .write(|w| unsafe { w.bits(alt_sequence.len() as u32) }); 185 .write(|w| unsafe { w.bits(alt_sequence.words.len() as u32) });
189 186
190 r.enable.write(|w| w.enable().enabled()); 187 r.enable.write(|w| w.enable().enabled());
191 188
@@ -400,6 +397,7 @@ impl Default for Config {
400} 397}
401 398
402#[non_exhaustive] 399#[non_exhaustive]
400#[derive(Clone)]
403pub struct SequenceConfig { 401pub struct SequenceConfig {
404 /// Number of PWM periods to delay between each sequence sample 402 /// Number of PWM periods to delay between each sequence sample
405 pub refresh: u32, 403 pub refresh: u32,
@@ -416,6 +414,20 @@ impl Default for SequenceConfig {
416 } 414 }
417} 415}
418 416
417#[non_exhaustive]
418pub struct Sequence<'d> {
419 /// The words comprising the sequence. Must not exceed 32767 words.
420 pub words: &'d [u16],
421 /// Configuration associated with the sequence.
422 pub config: SequenceConfig,
423}
424
425impl<'d> Sequence<'d> {
426 pub fn new(words: &'d [u16], config: SequenceConfig) -> Self {
427 Self { words, config }
428 }
429}
430
419/// How many times to run the sequence 431/// How many times to run the sequence
420#[derive(Debug, Eq, PartialEq, Clone, Copy)] 432#[derive(Debug, Eq, PartialEq, Clone, Copy)]
421pub enum SequenceMode { 433pub enum SequenceMode {
diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs
index 2dcbc7475..78787d531 100644
--- a/examples/nrf/src/bin/pwm_sequence.rs
+++ b/examples/nrf/src/bin/pwm_sequence.rs
@@ -8,13 +8,13 @@ use defmt::*;
8use embassy::executor::Spawner; 8use 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::{Config, Prescaler, SequenceMode, SequencePwm}; 11use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm};
12use embassy_nrf::Peripherals; 12use 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_values_1: [u16; 5] = [1000, 250, 100, 50, 0]; 16 let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0];
17 let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000]; 17 let 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;
@@ -22,7 +22,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
22 // but say we want to hold the value for 5000ms 22 // but say we want to hold the value for 5000ms
23 // so we want to repeat our value as many times as necessary until 5000ms passes 23 // so we want to repeat our value as many times as necessary until 5000ms passes
24 // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember) 24 // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember)
25 let mut seq_config = Config::default(); 25 let mut seq_config = SequenceConfig::default();
26 seq_config.refresh = 624; 26 seq_config.refresh = 624;
27 // thus our sequence takes 5 * 5000ms or 25 seconds 27 // thus our sequence takes 5 * 5000ms or 25 seconds
28 28
@@ -30,11 +30,9 @@ 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 &seq_values_1, 33 Sequence::new(&seq_words_1, seq_config.clone()),
34 seq_config,
35 None, 34 None,
36 None, 35 SequenceMode::Infinite,
37 SeqSequenceMode::Infinite,
38 ); 36 );
39 37
40 info!("pwm started!"); 38 info!("pwm started!");
@@ -43,9 +41,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
43 info!("pwm starting with another sequence!"); 41 info!("pwm starting with another sequence!");
44 42
45 let _ = pwm.start( 43 let _ = pwm.start(
46 &seq_values_2, 44 Sequence::new(&seq_words_2, seq_config),
47 seq_config,
48 None,
49 None, 45 None,
50 SequenceMode::Infinite, 46 SequenceMode::Infinite,
51 ); 47 );
diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs
index 9523671a4..c80820f84 100644
--- a/examples/nrf/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs
@@ -11,12 +11,12 @@ use embassy::executor::Spawner;
11use embassy_nrf::gpio::{Input, NoPin, Pull}; 11use 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::{Config, Prescaler, SequenceConfig, SequenceMode, SequencePwm}; 14use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm};
15use embassy_nrf::Peripherals; 15use 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_values: [u16; 5] = [1000, 250, 100, 50, 0]; 19 let 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;
@@ -31,7 +31,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
31 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 31 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
32 )); 32 ));
33 33
34 let _ = pwm.start(&seq_values, seq_config, None, None, SequenceMode::Infinite); 34 let _ = pwm.start(
35 Sequence::new(&seq_words, seq_config),
36 None,
37 SequenceMode::Infinite,
38 );
35 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 39 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
36 // so its going to have to start running in order load the configuration 40 // so its going to have to start running in order load the configuration
37 41
diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
index 01afd043b..2fb37015d 100644
--- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs
@@ -9,7 +9,7 @@ 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, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, 12 Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm,
13}; 13};
14use embassy_nrf::Peripherals; 14use embassy_nrf::Peripherals;
15 15
@@ -29,12 +29,17 @@ const RES: u16 = 0x8000;
29#[embassy::main] 29#[embassy::main]
30async fn main(_spawner: Spawner, p: Peripherals) { 30async fn main(_spawner: Spawner, p: Peripherals) {
31 // Declare the bits of 24 bits 31 // Declare the bits of 24 bits
32 let mut blue_seq: [u16; 8 * 3] = [ 32 let blue_seq_words = [
33 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G 33 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G
34 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R 34 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R
35 T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B 35 T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B
36 ]; 36 ];
37 let reset_seq = [RES; 1]; 37 let blue_seq = Sequence::new(&blue_seq_words, SequenceConfig::default());
38
39 let reset_seq_words = [RES; 1];
40 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;
42 let reset_seq = Sequence::new(&reset_seq_words, reset_seq_config);
38 43
39 let mut config = Config::default(); 44 let mut config = Config::default();
40 config.sequence_load = SequenceLoad::Common; 45 config.sequence_load = SequenceLoad::Common;
@@ -44,16 +49,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
44 p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, 49 p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config,
45 )); 50 ));
46 51
47 let blue_seq_config = SequenceConfig::default(); 52 unwrap!(pwm.start(blue_seq, Some(reset_seq), SequenceMode::Times(2)));
48 let mut reset_seq_config = SequenceConfig::default();
49 reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES
50 unwrap!(pwm.start(
51 &blue_seq,
52 blue_seq_config,
53 Some(&reset_seq),
54 Some(reset_seq_config),
55 SequenceMode::Times(2)
56 ));
57 53
58 Timer::after(Duration::from_millis(20000)).await; 54 Timer::after(Duration::from_millis(20000)).await;
59 info!("Program stopped"); 55 info!("Program stopped");