diff options
| -rw-r--r-- | embassy-nrf/src/pwm.rs | 108 | ||||
| -rw-r--r-- | examples/nrf/src/bin/pwm_sequence.rs | 22 | ||||
| -rw-r--r-- | examples/nrf/src/bin/pwm_sequence_ppi.rs | 13 | ||||
| -rw-r--r-- | examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 33 |
4 files changed, 68 insertions, 108 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 9146160cd..94dfdeda6 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs | |||
| @@ -25,14 +25,14 @@ pub struct SimplePwm<'d, T: Instance> { | |||
| 25 | 25 | ||
| 26 | /// SequencePwm allows you to offload the updating of a sequence of duty cycles | 26 | /// SequencePwm allows you to offload the updating of a sequence of duty cycles |
| 27 | /// to up to four channels, as well as repeat that sequence n times. | 27 | /// to up to four channels, as well as repeat that sequence n times. |
| 28 | pub struct SequencePwm<'d, T: Instance, const S0: usize, const S1: usize> { | 28 | pub struct SequencePwm<'d, T: Instance> { |
| 29 | phantom: PhantomData<&'d mut T>, | 29 | phantom: PhantomData<&'d mut T>, |
| 30 | ch0: Option<AnyPin>, | 30 | ch0: Option<AnyPin>, |
| 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<S0>>, | 34 | sequence0: Option<Sequence<'d>>, |
| 35 | sequence1: Option<Sequence<S1>>, | 35 | sequence1: Option<Sequence<'d>>, |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 38 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| @@ -43,17 +43,13 @@ pub enum Error { | |||
| 43 | SequenceTooLong, | 43 | SequenceTooLong, |
| 44 | /// Min Sequence count is 1 | 44 | /// Min Sequence count is 1 |
| 45 | SequenceTimesAtLeastOne, | 45 | SequenceTimesAtLeastOne, |
| 46 | /// Sequence 0 is required, Sequence 1 is NOT required | ||
| 47 | SequenceTimesRequireSeq0Only, | ||
| 48 | /// Sequence 0 is required, Sequence 1 is required | ||
| 49 | SequenceTimesRequireBothSeq0AndSeq1, | ||
| 50 | /// EasyDMA can only read from data memory, read only buffers in flash will fail. | 46 | /// EasyDMA can only read from data memory, read only buffers in flash will fail. |
| 51 | DMABufferNotInDataMemory, | 47 | DMABufferNotInDataMemory, |
| 52 | } | 48 | } |
| 53 | 49 | ||
| 54 | const MAX_SEQUENCE_LEN: usize = 32767; | 50 | const MAX_SEQUENCE_LEN: usize = 32767; |
| 55 | 51 | ||
| 56 | impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S1> { | 52 | impl<'d, T: Instance> SequencePwm<'d, T> { |
| 57 | /// Creates the interface to a `SequencePwm`. | 53 | /// Creates the interface to a `SequencePwm`. |
| 58 | /// | 54 | /// |
| 59 | /// Must be started by calling `start` | 55 | /// Must be started by calling `start` |
| @@ -72,10 +68,6 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 72 | ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 68 | ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, |
| 73 | config: Config, | 69 | config: Config, |
| 74 | ) -> Result<Self, Error> { | 70 | ) -> Result<Self, Error> { |
| 75 | if S0 > MAX_SEQUENCE_LEN || S1 > MAX_SEQUENCE_LEN { | ||
| 76 | return Err(Error::SequenceTooLong); | ||
| 77 | } | ||
| 78 | |||
| 79 | unborrow!(ch0, ch1, ch2, ch3); | 71 | unborrow!(ch0, ch1, ch2, ch3); |
| 80 | 72 | ||
| 81 | let r = T::regs(); | 73 | let r = T::regs(); |
| @@ -141,49 +133,31 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 141 | } | 133 | } |
| 142 | 134 | ||
| 143 | /// 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 |
| 144 | /// configuration. A second sequence must be provided when looping i.e. | 136 | /// configuration. Optionally takes a second sequence and its configuration. |
| 145 | /// when the sequence mode is anything other than Times(1). | 137 | /// In the case where no second sequence is provided then the first sequence |
| 138 | /// is used. The sequence mode applies to both sequences combined as one. | ||
| 146 | #[inline(always)] | 139 | #[inline(always)] |
| 147 | pub fn start( | 140 | pub fn start( |
| 148 | &mut self, | 141 | &mut self, |
| 149 | sequence0: Sequence<S0>, | 142 | sequence0: Sequence<'d>, |
| 150 | sequence1: Sequence<S1>, | 143 | sequence1: Option<Sequence<'d>>, |
| 151 | times: SequenceMode, | 144 | times: SequenceMode, |
| 152 | ) -> Result<(), Error> { | 145 | ) -> Result<(), Error> { |
| 153 | slice_in_ram_or(&sequence0.words, Error::DMABufferNotInDataMemory)?; | 146 | let alt_sequence = sequence1.as_ref().unwrap_or(&sequence0); |
| 154 | slice_in_ram_or(&sequence1.words, Error::DMABufferNotInDataMemory)?; | 147 | |
| 148 | slice_in_ram_or(sequence0.words, Error::DMABufferNotInDataMemory)?; | ||
| 149 | slice_in_ram_or(alt_sequence.words, Error::DMABufferNotInDataMemory)?; | ||
| 155 | 150 | ||
| 156 | let seq_0_word_count = sequence0.word_count.unwrap_or(S0); | 151 | if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN { |
| 157 | let seq_1_word_count = sequence0.word_count.unwrap_or(S1); | ||
| 158 | if seq_0_word_count > S0 || seq_1_word_count > S1 { | ||
| 159 | return Err(Error::SequenceTooLong); | 152 | return Err(Error::SequenceTooLong); |
| 160 | } | 153 | } |
| 161 | 154 | ||
| 162 | match times { | 155 | if let SequenceMode::Times(0) = times { |
| 163 | SequenceMode::Times(0) => return Err(Error::SequenceTimesAtLeastOne), | 156 | return Err(Error::SequenceTimesAtLeastOne); |
| 164 | SequenceMode::Times(1) if seq_0_word_count == 0 || seq_1_word_count != 0 => { | ||
| 165 | return Err(Error::SequenceTimesRequireSeq0Only) | ||
| 166 | } | ||
| 167 | SequenceMode::Times(1) => (), | ||
| 168 | SequenceMode::Times(_) | SequenceMode::Infinite | ||
| 169 | if seq_0_word_count == 0 || seq_1_word_count == 0 => | ||
| 170 | { | ||
| 171 | return Err(Error::SequenceTimesRequireBothSeq0AndSeq1) | ||
| 172 | } | ||
| 173 | SequenceMode::Times(_) | SequenceMode::Infinite => (), | ||
| 174 | } | 157 | } |
| 175 | 158 | ||
| 176 | let _ = self.stop(); | 159 | let _ = self.stop(); |
| 177 | 160 | ||
| 178 | // We now own these sequences and they will be moved. We want | ||
| 179 | // the peripheral to point at the right bits of memory hence | ||
| 180 | // moving the sequences early. | ||
| 181 | self.sequence0 = Some(sequence0); | ||
| 182 | self.sequence1 = Some(sequence1); | ||
| 183 | |||
| 184 | let sequence0 = self.sequence0.as_ref().unwrap(); | ||
| 185 | let sequence1 = self.sequence1.as_ref().unwrap(); | ||
| 186 | |||
| 187 | let r = T::regs(); | 161 | let r = T::regs(); |
| 188 | 162 | ||
| 189 | r.seq0 | 163 | r.seq0 |
| @@ -197,20 +171,20 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 197 | .write(|w| unsafe { w.bits(sequence0.words.as_ptr() as u32) }); | 171 | .write(|w| unsafe { w.bits(sequence0.words.as_ptr() as u32) }); |
| 198 | r.seq0 | 172 | r.seq0 |
| 199 | .cnt | 173 | .cnt |
| 200 | .write(|w| unsafe { w.bits(seq_0_word_count as u32) }); | 174 | .write(|w| unsafe { w.bits(sequence0.words.len() as u32) }); |
| 201 | 175 | ||
| 202 | r.seq1 | 176 | r.seq1 |
| 203 | .refresh | 177 | .refresh |
| 204 | .write(|w| unsafe { w.bits(sequence1.config.refresh) }); | 178 | .write(|w| unsafe { w.bits(alt_sequence.config.refresh) }); |
| 205 | r.seq1 | 179 | r.seq1 |
| 206 | .enddelay | 180 | .enddelay |
| 207 | .write(|w| unsafe { w.bits(sequence1.config.end_delay) }); | 181 | .write(|w| unsafe { w.bits(alt_sequence.config.end_delay) }); |
| 208 | r.seq1 | 182 | r.seq1 |
| 209 | .ptr | 183 | .ptr |
| 210 | .write(|w| unsafe { w.bits(sequence1.words.as_ptr() as u32) }); | 184 | .write(|w| unsafe { w.bits(alt_sequence.words.as_ptr() as u32) }); |
| 211 | r.seq1 | 185 | r.seq1 |
| 212 | .cnt | 186 | .cnt |
| 213 | .write(|w| unsafe { w.bits(seq_1_word_count as u32) }); | 187 | .write(|w| unsafe { w.bits(alt_sequence.words.len() as u32) }); |
| 214 | 188 | ||
| 215 | r.enable.write(|w| w.enable().enabled()); | 189 | r.enable.write(|w| w.enable().enabled()); |
| 216 | 190 | ||
| @@ -252,6 +226,9 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 252 | } | 226 | } |
| 253 | } | 227 | } |
| 254 | 228 | ||
| 229 | self.sequence0 = Some(sequence0); | ||
| 230 | self.sequence1 = sequence1; | ||
| 231 | |||
| 255 | Ok(()) | 232 | Ok(()) |
| 256 | } | 233 | } |
| 257 | 234 | ||
| @@ -359,7 +336,7 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 359 | /// cycle from the pin. Returns any sequences previously provided to | 336 | /// cycle from the pin. Returns any sequences previously provided to |
| 360 | /// `start` so that they may be further mutated. | 337 | /// `start` so that they may be further mutated. |
| 361 | #[inline(always)] | 338 | #[inline(always)] |
| 362 | pub fn stop(&mut self) -> (Option<Sequence<S0>>, Option<Sequence<S1>>) { | 339 | pub fn stop(&mut self) -> (Option<Sequence<'d>>, Option<Sequence<'d>>) { |
| 363 | let r = T::regs(); | 340 | let r = T::regs(); |
| 364 | 341 | ||
| 365 | r.shorts.reset(); | 342 | r.shorts.reset(); |
| @@ -375,7 +352,7 @@ impl<'d, T: Instance, const S0: usize, const S1: usize> SequencePwm<'d, T, S0, S | |||
| 375 | } | 352 | } |
| 376 | } | 353 | } |
| 377 | 354 | ||
| 378 | impl<'a, T: Instance, const S0: usize, const S1: usize> Drop for SequencePwm<'a, T, S0, S1> { | 355 | impl<'a, T: Instance> Drop for SequencePwm<'a, T> { |
| 379 | fn drop(&mut self) { | 356 | fn drop(&mut self) { |
| 380 | let r = T::regs(); | 357 | let r = T::regs(); |
| 381 | 358 | ||
| @@ -404,7 +381,6 @@ impl<'a, T: Instance, const S0: usize, const S1: usize> Drop for SequencePwm<'a, | |||
| 404 | } | 381 | } |
| 405 | } | 382 | } |
| 406 | 383 | ||
| 407 | /// Configuration for the PWM as a whole. | ||
| 408 | #[non_exhaustive] | 384 | #[non_exhaustive] |
| 409 | pub struct Config { | 385 | pub struct Config { |
| 410 | /// Selects up mode or up-and-down mode for the counter | 386 | /// Selects up mode or up-and-down mode for the counter |
| @@ -428,7 +404,6 @@ impl Default for Config { | |||
| 428 | } | 404 | } |
| 429 | } | 405 | } |
| 430 | 406 | ||
| 431 | /// Configuration per sequence | ||
| 432 | #[non_exhaustive] | 407 | #[non_exhaustive] |
| 433 | #[derive(Clone)] | 408 | #[derive(Clone)] |
| 434 | pub struct SequenceConfig { | 409 | pub struct SequenceConfig { |
| @@ -447,39 +422,20 @@ impl Default for SequenceConfig { | |||
| 447 | } | 422 | } |
| 448 | } | 423 | } |
| 449 | 424 | ||
| 450 | /// A composition of a sequence buffer and its configuration. | ||
| 451 | #[non_exhaustive] | 425 | #[non_exhaustive] |
| 452 | #[derive(Clone)] | 426 | pub struct Sequence<'d> { |
| 453 | pub struct Sequence<const S: usize> { | ||
| 454 | /// The words comprising the sequence. Must not exceed 32767 words. | 427 | /// The words comprising the sequence. Must not exceed 32767 words. |
| 455 | pub words: [u16; S], | 428 | pub words: &'d mut [u16], |
| 456 | /// The count of words to use. If None the S will be used. | ||
| 457 | pub word_count: Option<usize>, | ||
| 458 | /// Configuration associated with the sequence. | 429 | /// Configuration associated with the sequence. |
| 459 | pub config: SequenceConfig, | 430 | pub config: SequenceConfig, |
| 460 | } | 431 | } |
| 461 | 432 | ||
| 462 | impl<const S: usize> Sequence<S> { | 433 | impl<'d> Sequence<'d> { |
| 463 | pub const fn new(words: [u16; S], config: SequenceConfig) -> Self { | 434 | pub fn new(words: &'d mut [u16], config: SequenceConfig) -> Self { |
| 464 | Self { | 435 | Self { words, config } |
| 465 | words, | ||
| 466 | word_count: None, | ||
| 467 | config, | ||
| 468 | } | ||
| 469 | } | 436 | } |
| 470 | } | 437 | } |
| 471 | 438 | ||
| 472 | /// Declares an empty sequence which will cause it to be disabled. | ||
| 473 | /// Note that any looping i.e. !Times(1), will require a second | ||
| 474 | /// sequence given the way the PWM peripheral works. | ||
| 475 | pub const EMPTY_SEQ: Sequence<0> = Sequence::new( | ||
| 476 | [], | ||
| 477 | SequenceConfig { | ||
| 478 | refresh: 0, | ||
| 479 | end_delay: 0, | ||
| 480 | }, | ||
| 481 | ); | ||
| 482 | |||
| 483 | /// How many times to run the sequence | 439 | /// How many times to run the sequence |
| 484 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] | 440 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] |
| 485 | pub enum SequenceMode { | 441 | pub enum SequenceMode { |
| @@ -490,7 +446,7 @@ pub enum SequenceMode { | |||
| 490 | /// 5 to 6 = Run sequence 0, sequence 1, sequence 0, sequence 1, sequence 0 and then sequence 1 | 446 | /// 5 to 6 = Run sequence 0, sequence 1, sequence 0, sequence 1, sequence 0 and then sequence 1 |
| 491 | /// i.e the when >= 2 the loop count is determined by dividing by 2 and rounding up | 447 | /// i.e the when >= 2 the loop count is determined by dividing by 2 and rounding up |
| 492 | Times(u16), | 448 | Times(u16), |
| 493 | /// Repeat until `stop` is called. Both sequences must be provided. | 449 | /// Repeat until `stop` is called. |
| 494 | Infinite, | 450 | Infinite, |
| 495 | } | 451 | } |
| 496 | 452 | ||
diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index 6fe957d24..6fb861e8f 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs | |||
| @@ -8,13 +8,14 @@ use defmt::*; | |||
| 8 | use embassy::executor::Spawner; | 8 | use embassy::executor::Spawner; |
| 9 | use embassy::time::{Duration, Timer}; | 9 | use embassy::time::{Duration, Timer}; |
| 10 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 11 | use embassy_nrf::pwm::{ | 11 | use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; |
| 12 | Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, EMPTY_SEQ, | ||
| 13 | }; | ||
| 14 | use embassy_nrf::Peripherals; | 12 | use embassy_nrf::Peripherals; |
| 15 | 13 | ||
| 16 | #[embassy::main] | 14 | #[embassy::main] |
| 17 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async fn main(_spawner: Spawner, p: Peripherals) { |
| 16 | let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; | ||
| 17 | let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; | ||
| 18 | |||
| 18 | let mut config = Config::default(); | 19 | let mut config = Config::default(); |
| 19 | config.prescaler = Prescaler::Div128; | 20 | config.prescaler = Prescaler::Div128; |
| 20 | // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us | 21 | // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us |
| @@ -25,20 +26,25 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 25 | seq_config.refresh = 624; | 26 | seq_config.refresh = 624; |
| 26 | // thus our sequence takes 5 * 5000ms or 25 seconds | 27 | // thus our sequence takes 5 * 5000ms or 25 seconds |
| 27 | 28 | ||
| 28 | let seq_1 = Sequence::new([1000, 250, 100, 50, 0], seq_config.clone()); | ||
| 29 | let seq_2 = Sequence::new([0, 50, 100, 250, 1000], seq_config); | ||
| 30 | |||
| 31 | let mut pwm = unwrap!(SequencePwm::new( | 29 | let mut pwm = unwrap!(SequencePwm::new( |
| 32 | p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, | 30 | p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, |
| 33 | )); | 31 | )); |
| 34 | unwrap!(pwm.start(seq_1, EMPTY_SEQ, SequenceMode::Times(1))); | 32 | let _ = pwm.start( |
| 33 | Sequence::new(&mut seq_words_1, seq_config.clone()), | ||
| 34 | None, | ||
| 35 | SequenceMode::Infinite, | ||
| 36 | ); | ||
| 35 | 37 | ||
| 36 | info!("pwm started!"); | 38 | info!("pwm started!"); |
| 37 | 39 | ||
| 38 | Timer::after(Duration::from_millis(20000)).await; | 40 | Timer::after(Duration::from_millis(20000)).await; |
| 39 | info!("pwm starting with another sequence!"); | 41 | info!("pwm starting with another sequence!"); |
| 40 | 42 | ||
| 41 | unwrap!(pwm.start(seq_2, EMPTY_SEQ, SequenceMode::Times(1))); | 43 | let _ = pwm.start( |
| 44 | Sequence::new(&mut seq_words_2, seq_config), | ||
| 45 | None, | ||
| 46 | SequenceMode::Infinite, | ||
| 47 | ); | ||
| 42 | 48 | ||
| 43 | // we can abort a sequence if we need to before its complete with pwm.stop() | 49 | // we can abort a sequence if we need to before its complete with pwm.stop() |
| 44 | // or stop is also implicitly called when the pwm peripheral is dropped | 50 | // 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 4883222a8..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] |
| 18 | async fn main(_spawner: Spawner, p: Peripherals) { | 18 | async 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; |
| @@ -31,12 +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 | // If we loop in any way i.e. not Times(1), then we must provide | 34 | let _ = pwm.start( |
| 35 | // the PWM peripheral with two sequences. | 35 | Sequence::new(&mut seq_words, seq_config), |
| 36 | let seq_0 = Sequence::new(seq_words, seq_config); | 36 | None, |
| 37 | let seq_1 = seq_0.clone(); | 37 | SequenceMode::Infinite, |
| 38 | 38 | ); | |
| 39 | unwrap!(pwm.start(seq_0, seq_1, SequenceMode::Infinite)); | ||
| 40 | // 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 |
| 41 | // 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 |
| 42 | 41 | ||
diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 8acb209cc..0ce79cbe0 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs | |||
| @@ -30,6 +30,19 @@ const RES: u16 = 0x8000; | |||
| 30 | // line is assumed to be P1_05. | 30 | // line is assumed to be P1_05. |
| 31 | #[embassy::main] | 31 | #[embassy::main] |
| 32 | async fn main(_spawner: Spawner, p: Peripherals) { | 32 | async fn main(_spawner: Spawner, p: Peripherals) { |
| 33 | // Declare the bits of 24 bits | ||
| 34 | let mut color_seq_words = [ | ||
| 35 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G | ||
| 36 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R | ||
| 37 | T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B | ||
| 38 | ]; | ||
| 39 | let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); | ||
| 40 | |||
| 41 | let mut reset_seq_words = [RES; 1]; | ||
| 42 | let mut reset_seq_config = SequenceConfig::default(); | ||
| 43 | reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; | ||
| 44 | let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); | ||
| 45 | |||
| 33 | let mut config = Config::default(); | 46 | let mut config = Config::default(); |
| 34 | config.sequence_load = SequenceLoad::Common; | 47 | config.sequence_load = SequenceLoad::Common; |
| 35 | config.prescaler = Prescaler::Div1; | 48 | config.prescaler = Prescaler::Div1; |
| @@ -38,21 +51,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 38 | p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, | 51 | p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, |
| 39 | )); | 52 | )); |
| 40 | 53 | ||
| 41 | // Declare the bits of 24 bits | 54 | unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); |
| 42 | let color_seq = Sequence::new( | ||
| 43 | [ | ||
| 44 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G | ||
| 45 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R | ||
| 46 | T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B | ||
| 47 | ], | ||
| 48 | SequenceConfig::default(), | ||
| 49 | ); | ||
| 50 | |||
| 51 | let mut reset_seq_config = SequenceConfig::default(); | ||
| 52 | reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; | ||
| 53 | let reset_seq = Sequence::new([RES], reset_seq_config); | ||
| 54 | |||
| 55 | unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); | ||
| 56 | 55 | ||
| 57 | Timer::after(Duration::from_millis(1000)).await; | 56 | Timer::after(Duration::from_millis(1000)).await; |
| 58 | 57 | ||
| @@ -60,9 +59,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 60 | let mut bit_value = T0H; | 59 | let mut bit_value = T0H; |
| 61 | 60 | ||
| 62 | loop { | 61 | loop { |
| 63 | if let (Some(mut color_seq), Some(reset_seq)) = pwm.stop() { | 62 | if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { |
| 64 | color_seq.words[color_bit] = bit_value; | 63 | color_seq.words[color_bit] = bit_value; |
| 65 | unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); | 64 | unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); |
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | Timer::after(Duration::from_millis(50)).await; | 67 | Timer::after(Duration::from_millis(50)).await; |
