From 47aeab152fff59e64d8244475dfbec338e6f98e5 Mon Sep 17 00:00:00 2001 From: huntc Date: Tue, 25 Jan 2022 18:06:42 +1100 Subject: PWM WS2812B example and per sequence config Demonstrates how to set the colour of a WS2812B to blue using PWM, and the use of multiple sequences along with their own config. This required an API change. --- examples/nrf/src/bin/pwm_sequence.rs | 23 ++++++++--- examples/nrf/src/bin/pwm_sequence_ppi.rs | 9 +++-- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 60 ++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 examples/nrf/src/bin/pwm_sequence_ws2812b.rs (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index 56c865d1c..2dcbc7475 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; -use embassy_nrf::pwm::{Prescaler, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{Config, Prescaler, SequenceMode, SequencePwm}; use embassy_nrf::Peripherals; #[embassy::main] @@ -16,26 +16,39 @@ async fn main(_spawner: Spawner, p: Peripherals) { 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 = Config::default(); config.prescaler = Prescaler::Div128; // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us // but say we want to hold the value for 5000ms // so we want to repeat our value as many times as necessary until 5000ms passes // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember) - config.refresh = 624; + let mut seq_config = Config::default(); + seq_config.refresh = 624; // thus our sequence takes 5 * 5000ms or 25 seconds let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start(&seq_values_1, SequenceMode::Infinite); + let _ = pwm.start( + &seq_values_1, + seq_config, + None, + None, + SeqSequenceMode::Infinite, + ); info!("pwm started!"); Timer::after(Duration::from_millis(20000)).await; info!("pwm starting with another sequence!"); - let _ = pwm.start(&seq_values_2, SequenceMode::Infinite); + let _ = pwm.start( + &seq_values_2, + seq_config, + None, + None, + SequenceMode::Infinite, + ); // 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 diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs index f03c5716a..9523671a4 100644 --- a/examples/nrf/src/bin/pwm_sequence_ppi.rs +++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs @@ -11,26 +11,27 @@ use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, NoPin, Pull}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; -use embassy_nrf::pwm::{Prescaler, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequenceMode, SequencePwm}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { let seq_values: [u16; 5] = [1000, 250, 100, 50, 0]; - let mut config = SequenceConfig::default(); + let mut config = Config::default(); config.prescaler = Prescaler::Div128; // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us // but say we want to hold the value for 250ms 250ms/8 = 31.25 periods // so round to 31 - 1 (we get the one period for free remember) // thus our sequence takes 5 * 250ms or 1.25 seconds - config.refresh = 30; + let mut seq_config = SequenceConfig::default(); + seq_config.refresh = 30; let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start(&seq_values, SequenceMode::Times(1)); + let _ = pwm.start(&seq_values, seq_config, None, None, SequenceMode::Infinite); // 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 diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs new file mode 100644 index 000000000..01afd043b --- /dev/null +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs @@ -0,0 +1,60 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use defmt::*; +use embassy::executor::Spawner; +use embassy::time::{Duration, Timer}; +use embassy_nrf::gpio::NoPin; +use embassy_nrf::pwm::{ + Config, Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, +}; +use embassy_nrf::Peripherals; + +// WS2812B LED light demonstration. Drives just one light. +// The following reference on WS2812B may be of use: +// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf + +// In the following declarations, setting the high bit tells the PWM +// to reverse polarity, which is what the WS2812B expects. + +const T1H: u16 = 0x8000 | 13; // Duty = 13/20 ticks (0.8us/1.25us) for a 1 +const T0H: u16 = 0x8000 | 7; // Duty 7/20 ticks (0.4us/1.25us) for a 0 +const RES: u16 = 0x8000; + +// Provides data to a WS2812b (Neopixel) LED and makes it go blue. The data +// line is assumed to be P1_05. +#[embassy::main] +async fn main(_spawner: Spawner, p: Peripherals) { + // Declare the bits of 24 bits + let mut blue_seq: [u16; 8 * 3] = [ + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R + T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B + ]; + let reset_seq = [RES; 1]; + + let mut config = Config::default(); + config.sequence_load = SequenceLoad::Common; + config.prescaler = Prescaler::Div1; + config.max_duty = 20; // 1.25us (1s / 16Mhz * 20) + let mut pwm = unwrap!(SequencePwm::new( + p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, + )); + + let blue_seq_config = SequenceConfig::default(); + let mut reset_seq_config = SequenceConfig::default(); + reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES + unwrap!(pwm.start( + &blue_seq, + blue_seq_config, + Some(&reset_seq), + Some(reset_seq_config), + SequenceMode::Times(2) + )); + + Timer::after(Duration::from_millis(20000)).await; + info!("Program stopped"); +} -- cgit From 12ce02457438c1dd1566f3f3c43537ae4f54f699 Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 28 Jan 2022 13:38:20 +1100 Subject: Make the sequence a little nicer to pass around --- examples/nrf/src/bin/pwm_sequence.rs | 18 +++++++----------- examples/nrf/src/bin/pwm_sequence_ppi.rs | 10 +++++++--- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 22 +++++++++------------- 3 files changed, 23 insertions(+), 27 deletions(-) (limited to 'examples/nrf/src/bin') 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::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; -use embassy_nrf::pwm::{Config, Prescaler, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_values_1: [u16; 5] = [1000, 250, 100, 50, 0]; - let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000]; + let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { // but say we want to hold the value for 5000ms // so we want to repeat our value as many times as necessary until 5000ms passes // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember) - let mut seq_config = Config::default(); + let mut seq_config = SequenceConfig::default(); seq_config.refresh = 624; // thus our sequence takes 5 * 5000ms or 25 seconds @@ -30,11 +30,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); let _ = pwm.start( - &seq_values_1, - seq_config, + Sequence::new(&seq_words_1, seq_config.clone()), None, - None, - SeqSequenceMode::Infinite, + SequenceMode::Infinite, ); info!("pwm started!"); @@ -43,9 +41,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { info!("pwm starting with another sequence!"); let _ = pwm.start( - &seq_values_2, - seq_config, - None, + Sequence::new(&seq_words_2, seq_config), None, SequenceMode::Infinite, ); 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; use embassy_nrf::gpio::{Input, NoPin, Pull}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; -use embassy_nrf::pwm::{Config, Prescaler, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_values: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -31,7 +31,11 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start(&seq_values, seq_config, None, None, SequenceMode::Infinite); + let _ = pwm.start( + Sequence::new(&seq_words, seq_config), + None, + SequenceMode::Infinite, + ); // 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 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; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, + Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, }; use embassy_nrf::Peripherals; @@ -29,12 +29,17 @@ const RES: u16 = 0x8000; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { // Declare the bits of 24 bits - let mut blue_seq: [u16; 8 * 3] = [ + let blue_seq_words = [ T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B ]; - let reset_seq = [RES; 1]; + let blue_seq = Sequence::new(&blue_seq_words, SequenceConfig::default()); + + let reset_seq_words = [RES; 1]; + let mut reset_seq_config = SequenceConfig::default(); + reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; + let reset_seq = Sequence::new(&reset_seq_words, reset_seq_config); let mut config = Config::default(); config.sequence_load = SequenceLoad::Common; @@ -44,16 +49,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - let blue_seq_config = SequenceConfig::default(); - let mut reset_seq_config = SequenceConfig::default(); - reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES - unwrap!(pwm.start( - &blue_seq, - blue_seq_config, - Some(&reset_seq), - Some(reset_seq_config), - SequenceMode::Times(2) - )); + unwrap!(pwm.start(blue_seq, Some(reset_seq), SequenceMode::Times(2))); Timer::after(Duration::from_millis(20000)).await; info!("Program stopped"); -- cgit From 9ac52a768bbcd4bc8b753c64805fc23906b2c91f Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 28 Jan 2022 16:21:53 +1100 Subject: Now permits sequences to be mutated subsequently --- examples/nrf/src/bin/pwm_sequence.rs | 8 +++--- examples/nrf/src/bin/pwm_sequence_ppi.rs | 4 +-- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 43 ++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'examples/nrf/src/bin') 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; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; - let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; + let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; + let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -30,7 +30,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); let _ = pwm.start( - Sequence::new(&seq_words_1, seq_config.clone()), + Sequence::new(&mut seq_words_1, seq_config.clone()), None, SequenceMode::Infinite, ); @@ -41,7 +41,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { info!("pwm starting with another sequence!"); let _ = pwm.start( - Sequence::new(&seq_words_2, seq_config), + Sequence::new(&mut seq_words_2, seq_config), None, SequenceMode::Infinite, ); 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; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; + let mut seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { )); let _ = pwm.start( - Sequence::new(&seq_words, seq_config), + Sequence::new(&mut seq_words, seq_config), None, SequenceMode::Infinite, ); 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; // WS2812B LED light demonstration. Drives just one light. // The following reference on WS2812B may be of use: -// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf +// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf. +// This demo lights up a single LED in blue. It then proceeds +// to pulsate the LED rapidly. // In the following declarations, setting the high bit tells the PWM // to reverse polarity, which is what the WS2812B expects. @@ -29,17 +31,17 @@ const RES: u16 = 0x8000; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { // Declare the bits of 24 bits - let blue_seq_words = [ + let mut color_seq_words = [ T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B ]; - let blue_seq = Sequence::new(&blue_seq_words, SequenceConfig::default()); + let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); - let reset_seq_words = [RES; 1]; + let mut reset_seq_words = [RES; 1]; let mut reset_seq_config = SequenceConfig::default(); reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; - let reset_seq = Sequence::new(&reset_seq_words, reset_seq_config); + let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); let mut config = Config::default(); config.sequence_load = SequenceLoad::Common; @@ -49,8 +51,33 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - unwrap!(pwm.start(blue_seq, Some(reset_seq), SequenceMode::Times(2))); + unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); - Timer::after(Duration::from_millis(20000)).await; - info!("Program stopped"); + Timer::after(Duration::from_millis(1000)).await; + + let mut color_bit = 16; + let mut bit_value = T0H; + + loop { + if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { + color_seq.words[color_bit] = bit_value; + unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); + } + + Timer::after(Duration::from_millis(50)).await; + + if bit_value == T0H { + if color_bit == 20 { + bit_value = T1H; + } else { + color_bit += 1; + } + } else { + if color_bit == 16 { + bit_value = T0H; + } else { + color_bit -= 1; + } + } + } } -- cgit From 482389a6911d8d3505872e6ad03d5b0af565eaf9 Mon Sep 17 00:00:00 2001 From: huntc Date: Sat, 29 Jan 2022 15:26:31 +1100 Subject: Own the sequence buffer This approach owns the sequence buffers which, while introducing an extra move, it eliminates the need to guard the lifetime of the sequence buffer. Given ownership, the buffer will be retained until the PWM sequence task is stopped. --- examples/nrf/src/bin/pwm_sequence.rs | 22 +++++++------------ examples/nrf/src/bin/pwm_sequence_ppi.rs | 13 ++++++----- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 33 ++++++++++++++-------------- 3 files changed, 32 insertions(+), 36 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index 6fb861e8f..6fe957d24 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -8,14 +8,13 @@ use defmt::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; -use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{ + Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, EMPTY_SEQ, +}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; - let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; - let mut config = Config::default(); config.prescaler = Prescaler::Div128; // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us @@ -26,25 +25,20 @@ async fn main(_spawner: Spawner, p: Peripherals) { seq_config.refresh = 624; // thus our sequence takes 5 * 5000ms or 25 seconds + let seq_1 = Sequence::new([1000, 250, 100, 50, 0], seq_config.clone()); + let seq_2 = Sequence::new([0, 50, 100, 250, 1000], seq_config); + let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start( - Sequence::new(&mut seq_words_1, seq_config.clone()), - None, - SequenceMode::Infinite, - ); + unwrap!(pwm.start(seq_1, EMPTY_SEQ, SequenceMode::Times(1))); info!("pwm started!"); Timer::after(Duration::from_millis(20000)).await; info!("pwm starting with another sequence!"); - let _ = pwm.start( - Sequence::new(&mut seq_words_2, seq_config), - None, - SequenceMode::Infinite, - ); + unwrap!(pwm.start(seq_2, EMPTY_SEQ, SequenceMode::Times(1))); // 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 diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs index f5d734bb1..4883222a8 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; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let mut seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -31,11 +31,12 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start( - Sequence::new(&mut seq_words, seq_config), - None, - SequenceMode::Infinite, - ); + // If we loop in any way i.e. not Times(1), then we must provide + // the PWM peripheral with two sequences. + let seq_0 = Sequence::new(seq_words, seq_config); + let seq_1 = seq_0.clone(); + + unwrap!(pwm.start(seq_0, seq_1, SequenceMode::Infinite)); // 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 diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 0ce79cbe0..8acb209cc 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs @@ -30,19 +30,6 @@ const RES: u16 = 0x8000; // line is assumed to be P1_05. #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - // Declare the bits of 24 bits - let mut color_seq_words = [ - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R - T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B - ]; - let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); - - let mut reset_seq_words = [RES; 1]; - let mut reset_seq_config = SequenceConfig::default(); - reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; - let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); - let mut config = Config::default(); config.sequence_load = SequenceLoad::Common; config.prescaler = Prescaler::Div1; @@ -51,7 +38,21 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); + // Declare the bits of 24 bits + let color_seq = Sequence::new( + [ + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R + T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B + ], + SequenceConfig::default(), + ); + + let mut reset_seq_config = SequenceConfig::default(); + reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; + let reset_seq = Sequence::new([RES], reset_seq_config); + + unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); Timer::after(Duration::from_millis(1000)).await; @@ -59,9 +60,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut bit_value = T0H; loop { - if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { + if let (Some(mut color_seq), Some(reset_seq)) = pwm.stop() { color_seq.words[color_bit] = bit_value; - unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); + unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); } Timer::after(Duration::from_millis(50)).await; -- cgit From 1c67bd46433734d9280e976da33975cf5beb773e Mon Sep 17 00:00:00 2001 From: huntc Date: Sun, 30 Jan 2022 16:21:23 +1100 Subject: Revert "Own the sequence buffer" This reverts commit 482389a6911d8d3505872e6ad03d5b0af565eaf9. --- examples/nrf/src/bin/pwm_sequence.rs | 22 ++++++++++++------- examples/nrf/src/bin/pwm_sequence_ppi.rs | 13 +++++------ examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 33 ++++++++++++++-------------- 3 files changed, 36 insertions(+), 32 deletions(-) (limited to 'examples/nrf/src/bin') 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::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; -use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, EMPTY_SEQ, -}; +use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { + let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; + let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; + let mut config = Config::default(); config.prescaler = Prescaler::Div128; // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us @@ -25,20 +26,25 @@ async fn main(_spawner: Spawner, p: Peripherals) { seq_config.refresh = 624; // thus our sequence takes 5 * 5000ms or 25 seconds - let seq_1 = Sequence::new([1000, 250, 100, 50, 0], seq_config.clone()); - let seq_2 = Sequence::new([0, 50, 100, 250, 1000], seq_config); - let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - unwrap!(pwm.start(seq_1, EMPTY_SEQ, SequenceMode::Times(1))); + let _ = pwm.start( + Sequence::new(&mut seq_words_1, seq_config.clone()), + None, + SequenceMode::Infinite, + ); info!("pwm started!"); Timer::after(Duration::from_millis(20000)).await; info!("pwm starting with another sequence!"); - unwrap!(pwm.start(seq_2, EMPTY_SEQ, SequenceMode::Times(1))); + let _ = pwm.start( + Sequence::new(&mut seq_words_2, seq_config), + None, + SequenceMode::Infinite, + ); // 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 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; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; + let mut seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -31,12 +31,11 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - // If we loop in any way i.e. not Times(1), then we must provide - // the PWM peripheral with two sequences. - let seq_0 = Sequence::new(seq_words, seq_config); - let seq_1 = seq_0.clone(); - - unwrap!(pwm.start(seq_0, seq_1, SequenceMode::Infinite)); + let _ = pwm.start( + Sequence::new(&mut seq_words, seq_config), + None, + SequenceMode::Infinite, + ); // 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 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; // line is assumed to be P1_05. #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { + // Declare the bits of 24 bits + let mut color_seq_words = [ + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R + T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B + ]; + let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); + + let mut reset_seq_words = [RES; 1]; + let mut reset_seq_config = SequenceConfig::default(); + reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; + let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); + let mut config = Config::default(); config.sequence_load = SequenceLoad::Common; config.prescaler = Prescaler::Div1; @@ -38,21 +51,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - // Declare the bits of 24 bits - let color_seq = Sequence::new( - [ - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R - T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B - ], - SequenceConfig::default(), - ); - - let mut reset_seq_config = SequenceConfig::default(); - reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; - let reset_seq = Sequence::new([RES], reset_seq_config); - - unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); + unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); Timer::after(Duration::from_millis(1000)).await; @@ -60,9 +59,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut bit_value = T0H; loop { - if let (Some(mut color_seq), Some(reset_seq)) = pwm.stop() { + if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { color_seq.words[color_bit] = bit_value; - unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2))); + unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); } Timer::after(Duration::from_millis(50)).await; -- cgit From 986295998a3fa8c665364d7b4a5fc009d186dee9 Mon Sep 17 00:00:00 2001 From: huntc Date: Sun, 30 Jan 2022 16:26:09 +1100 Subject: Some more doco --- examples/nrf/src/bin/pwm_sequence.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index 6fb861e8f..d3ddf558c 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let _ = pwm.start( Sequence::new(&mut seq_words_1, seq_config.clone()), None, - SequenceMode::Infinite, + SequenceMode::Times(1), ); info!("pwm started!"); @@ -43,7 +43,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let _ = pwm.start( Sequence::new(&mut seq_words_2, seq_config), None, - SequenceMode::Infinite, + SequenceMode::Times(1), ); // we can abort a sequence if we need to before its complete with pwm.stop() -- cgit From 1af6b23f970d80d881bbc83fe69846e14c512e1c Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 13:04:55 +1100 Subject: Introduces a Sequences struct --- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 39 +++++++++++++--------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 0ce79cbe0..310842d8d 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; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, + Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, }; use embassy_nrf::Peripherals; @@ -30,19 +30,6 @@ const RES: u16 = 0x8000; // line is assumed to be P1_05. #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - // Declare the bits of 24 bits - let mut color_seq_words = [ - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G - T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R - T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B - ]; - let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); - - let mut reset_seq_words = [RES; 1]; - let mut reset_seq_config = SequenceConfig::default(); - reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; - let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); - let mut config = Config::default(); config.sequence_load = SequenceLoad::Common; config.prescaler = Prescaler::Div1; @@ -51,18 +38,24 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); - - Timer::after(Duration::from_millis(1000)).await; + // Declare the bits of 24 bits in a buffer we'll be + // mutating later. + let mut seq_words = [ + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G + T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R + T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B + RES, + ]; + let mut seq_config = SequenceConfig::default(); + seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; let mut color_bit = 16; let mut bit_value = T0H; loop { - if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { - color_seq.words[color_bit] = bit_value; - unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); - } + let sequence0 = Sequence::new(&seq_words, seq_config.clone()); + let sequences = Sequences::new(&mut pwm, sequence0, None); + unwrap!(sequences.start(SequenceMode::Times(2))); Timer::after(Duration::from_millis(50)).await; @@ -79,5 +72,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { color_bit -= 1; } } + + drop(sequences); + + seq_words[color_bit] = bit_value; } } -- cgit From fe5501293f39307fbfa419d6f882f4a2cd10c115 Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 16:26:23 +1100 Subject: Expose PWM --- examples/nrf/src/bin/pwm_sequence_ppi.rs | 19 ++++++++++--------- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 9 +++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs index f5d734bb1..593e7590d 100644 --- a/examples/nrf/src/bin/pwm_sequence_ppi.rs +++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs @@ -11,12 +11,14 @@ use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, NoPin, Pull}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; -use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{ + Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, +}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let mut seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -31,11 +33,10 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start( - Sequence::new(&mut seq_words, seq_config), - None, - SequenceMode::Infinite, - ); + let sequence0 = Sequence::new(&seq_words, seq_config); + let sequences = Sequences::new(&mut pwm, sequence0, None); + unwrap!(sequences.start(SequenceMode::Infinite)); + // 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 @@ -53,8 +54,8 @@ async fn main(_spawner: Spawner, p: Peripherals) { // messing with the pwm tasks is ill advised // Times::Ininite and Times even are seq0, Times odd is seq1 - let start = unsafe { pwm.task_start_seq0() }; - let stop = unsafe { pwm.task_stop() }; + let start = unsafe { sequences.pwm.task_start_seq0() }; + let stop = unsafe { sequences.pwm.task_stop() }; let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button1.event_in(), start); ppi.enable(); diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 310842d8d..7706f91da 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs @@ -7,11 +7,12 @@ mod example_common; use defmt::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; +use embassy::util::Forever; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, }; -use embassy_nrf::Peripherals; +use embassy_nrf::{peripherals, Peripherals}; // WS2812B LED light demonstration. Drives just one light. // The following reference on WS2812B may be of use: @@ -26,6 +27,8 @@ const T1H: u16 = 0x8000 | 13; // Duty = 13/20 ticks (0.8us/1.25us) for a 1 const T0H: u16 = 0x8000 | 7; // Duty 7/20 ticks (0.4us/1.25us) for a 0 const RES: u16 = 0x8000; +static PWM: Forever> = Forever::new(); + // Provides data to a WS2812b (Neopixel) LED and makes it go blue. The data // line is assumed to be P1_05. #[embassy::main] @@ -34,10 +37,12 @@ async fn main(_spawner: Spawner, p: Peripherals) { config.sequence_load = SequenceLoad::Common; config.prescaler = Prescaler::Div1; config.max_duty = 20; // 1.25us (1s / 16Mhz * 20) - let mut pwm = unwrap!(SequencePwm::new( + let pwm = unwrap!(SequencePwm::new( p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); + let mut pwm = PWM.put(pwm); + // Declare the bits of 24 bits in a buffer we'll be // mutating later. let mut seq_words = [ -- cgit From 81f98c32aaec61171678ba6cbdd9c82860a1802f Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 16:34:25 +1100 Subject: Update another example --- examples/nrf/src/bin/pwm_sequence.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index d3ddf558c..b31c12a23 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -8,13 +8,15 @@ use defmt::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; -use embassy_nrf::pwm::{Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm}; +use embassy_nrf::pwm::{ + Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, +}; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let mut seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; - let mut seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; + let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -29,22 +31,21 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let _ = pwm.start( - Sequence::new(&mut seq_words_1, seq_config.clone()), - None, - SequenceMode::Times(1), - ); + + let sequence0 = Sequence::new(&seq_words_1, seq_config.clone()); + let sequences = Sequences::new(&mut pwm, sequence0, None); + unwrap!(sequences.start(SequenceMode::Times(1))); info!("pwm started!"); Timer::after(Duration::from_millis(20000)).await; info!("pwm starting with another sequence!"); - let _ = pwm.start( - Sequence::new(&mut seq_words_2, seq_config), - None, - SequenceMode::Times(1), - ); + drop(sequences); // This stops the previous sequence and returns pwm ownership back + + let sequence0 = Sequence::new(&seq_words_2, seq_config); + let sequences = Sequences::new(&mut pwm, sequence0, None); + unwrap!(sequences.start(SequenceMode::Times(1))); // 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 -- cgit From e9e4d058d1fbb1eefa0b2d58b0a76075e0a32487 Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 16:39:14 +1100 Subject: Revert the use of forever --- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 7706f91da..310842d8d 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs @@ -7,12 +7,11 @@ mod example_common; use defmt::*; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; -use embassy::util::Forever; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, }; -use embassy_nrf::{peripherals, Peripherals}; +use embassy_nrf::Peripherals; // WS2812B LED light demonstration. Drives just one light. // The following reference on WS2812B may be of use: @@ -27,8 +26,6 @@ const T1H: u16 = 0x8000 | 13; // Duty = 13/20 ticks (0.8us/1.25us) for a 1 const T0H: u16 = 0x8000 | 7; // Duty 7/20 ticks (0.4us/1.25us) for a 0 const RES: u16 = 0x8000; -static PWM: Forever> = Forever::new(); - // Provides data to a WS2812b (Neopixel) LED and makes it go blue. The data // line is assumed to be P1_05. #[embassy::main] @@ -37,12 +34,10 @@ async fn main(_spawner: Spawner, p: Peripherals) { config.sequence_load = SequenceLoad::Common; config.prescaler = Prescaler::Div1; config.max_duty = 20; // 1.25us (1s / 16Mhz * 20) - let pwm = unwrap!(SequencePwm::new( + let mut pwm = unwrap!(SequencePwm::new( p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, )); - let mut pwm = PWM.put(pwm); - // Declare the bits of 24 bits in a buffer we'll be // mutating later. let mut seq_words = [ -- cgit From 9e36ede363b66c3e007d8cb0c477234b88ba0737 Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 16:48:26 +1100 Subject: Small correction to times --- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 310842d8d..c0c10373a 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs @@ -55,7 +55,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { loop { let sequence0 = Sequence::new(&seq_words, seq_config.clone()); let sequences = Sequences::new(&mut pwm, sequence0, None); - unwrap!(sequences.start(SequenceMode::Times(2))); + unwrap!(sequences.start(SequenceMode::Times(1))); Timer::after(Duration::from_millis(50)).await; -- cgit From 965a5f2c3fba365519bed1c2a955145783d6a05b Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 19:11:15 +1100 Subject: Introduced the SingleSequencer and a more complex Sequencer --- examples/nrf/src/bin/pwm_double_sequence.rs | 46 ++++++++++++++++++++++++++++ examples/nrf/src/bin/pwm_sequence.rs | 22 +++---------- examples/nrf/src/bin/pwm_sequence_ppi.rs | 14 ++++----- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 7 +++-- 4 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 examples/nrf/src/bin/pwm_double_sequence.rs (limited to 'examples/nrf/src/bin') 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 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use defmt::*; +use embassy::executor::Spawner; +use embassy::time::{Duration, Timer}; +use embassy_nrf::gpio::NoPin; +use embassy_nrf::pwm::{ + Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequencer, + StartSequence, +}; +use embassy_nrf::Peripherals; + +#[embassy::main] +async fn main(_spawner: Spawner, p: Peripherals) { + let seq_words_0: [u16; 5] = [1000, 250, 100, 50, 0]; + let seq_words_1: [u16; 4] = [50, 100, 250, 1000]; + + let mut config = Config::default(); + config.prescaler = Prescaler::Div128; + // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us + // but say we want to hold the value for 5000ms + // so we want to repeat our value as many times as necessary until 5000ms passes + // want 5000/8 = 625 periods total to occur, so 624 (we get the one period for free remember) + let mut seq_config = SequenceConfig::default(); + seq_config.refresh = 624; + // thus our sequence takes 5 * 5000ms or 25 seconds + + let mut pwm = unwrap!(SequencePwm::new( + p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, + )); + + let sequence_0 = Sequence::new(&seq_words_0, seq_config.clone()); + let sequence_1 = Sequence::new(&seq_words_1, seq_config); + let sequencer = Sequencer::new(&mut pwm, sequence_0, Some(sequence_1)); + unwrap!(sequencer.start(StartSequence::Zero, SequenceMode::Loop(1))); + + // 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 + // when it goes out of scope + Timer::after(Duration::from_millis(40000)).await; + info!("pwm stopped early!"); +} 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; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, + Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, }; use embassy_nrf::Peripherals; #[embassy::main] async fn main(_spawner: Spawner, p: Peripherals) { - let seq_words_1: [u16; 5] = [1000, 250, 100, 50, 0]; - let seq_words_2: [u16; 5] = [0, 50, 100, 250, 1000]; + let seq_words: [u16; 5] = [1000, 250, 100, 50, 0]; let mut config = Config::default(); config.prescaler = Prescaler::Div128; @@ -32,20 +31,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let sequence0 = Sequence::new(&seq_words_1, seq_config.clone()); - let sequences = Sequences::new(&mut pwm, sequence0, None); - unwrap!(sequences.start(SequenceMode::Times(1))); - - info!("pwm started!"); - - Timer::after(Duration::from_millis(20000)).await; - info!("pwm starting with another sequence!"); - - drop(sequences); // This stops the previous sequence and returns pwm ownership back - - let sequence0 = Sequence::new(&seq_words_2, seq_config); - let sequences = Sequences::new(&mut pwm, sequence0, None); - unwrap!(sequences.start(SequenceMode::Times(1))); + let sequence = Sequence::new(&seq_words, seq_config.clone()); + let sequencer = SingleSequencer::new(&mut pwm, sequence); + unwrap!(sequencer.start(SingleSequenceMode::Times(1))); // 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 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}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequences, + Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, }; use embassy_nrf::Peripherals; @@ -33,10 +33,6 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let sequence0 = Sequence::new(&seq_words, seq_config); - let sequences = Sequences::new(&mut pwm, sequence0, None); - unwrap!(sequences.start(SequenceMode::Infinite)); - // 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 @@ -54,8 +50,12 @@ async fn main(_spawner: Spawner, p: Peripherals) { // messing with the pwm tasks is ill advised // Times::Ininite and Times even are seq0, Times odd is seq1 - let start = unsafe { sequences.pwm.task_start_seq0() }; - let stop = unsafe { sequences.pwm.task_stop() }; + let start = unsafe { pwm.task_start_seq0() }; + let stop = unsafe { pwm.task_stop() }; + + let sequence = Sequence::new(&seq_words, seq_config); + let sequencer = SingleSequencer::new(&mut pwm, sequence); + unwrap!(sequencer.start(SingleSequenceMode::Infinite)); let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button1.event_in(), start); 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; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, + Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, + SingleSequencer, }; use embassy_nrf::Peripherals; @@ -54,8 +55,8 @@ async fn main(_spawner: Spawner, p: Peripherals) { loop { let sequence0 = Sequence::new(&seq_words, seq_config.clone()); - let sequences = Sequences::new(&mut pwm, sequence0, None); - unwrap!(sequences.start(SequenceMode::Times(1))); + let sequences = SingleSequencer::new(&mut pwm, sequence0); + unwrap!(sequences.start(SingleSequenceMode::Times(1))); Timer::after(Duration::from_millis(50)).await; -- cgit From 81d31e43ebf947ff2cd91b3a6f6af092fcb7e2b7 Mon Sep 17 00:00:00 2001 From: huntc Date: Fri, 4 Feb 2022 19:18:10 +1100 Subject: Removed unrequired clone --- examples/nrf/src/bin/pwm_sequence.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index 761ac0f03..a76b1110b 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -31,7 +31,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let sequence = Sequence::new(&seq_words, seq_config.clone()); + let sequence = Sequence::new(&seq_words, seq_config); let sequencer = SingleSequencer::new(&mut pwm, sequence); unwrap!(sequencer.start(SingleSequenceMode::Times(1))); -- cgit From df5ba727f2c8bd3f2a67f51a3f43d7f47b011b1c Mon Sep 17 00:00:00 2001 From: huntc Date: Sat, 5 Feb 2022 08:05:23 +1100 Subject: Further API simplification for the single seq scenario --- examples/nrf/src/bin/pwm_sequence.rs | 5 ++--- examples/nrf/src/bin/pwm_sequence_ppi.rs | 5 ++--- examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'examples/nrf/src/bin') diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs index a76b1110b..f06ea0b19 100644 --- a/examples/nrf/src/bin/pwm_sequence.rs +++ b/examples/nrf/src/bin/pwm_sequence.rs @@ -9,7 +9,7 @@ use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, + Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, }; use embassy_nrf::Peripherals; @@ -31,8 +31,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, )); - let sequence = Sequence::new(&seq_words, seq_config); - let sequencer = SingleSequencer::new(&mut pwm, sequence); + let sequencer = SingleSequencer::new(&mut pwm, &seq_words, seq_config); unwrap!(sequencer.start(SingleSequenceMode::Times(1))); // we can abort a sequence if we need to before its complete with pwm.stop() diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs index 7e58c37e6..c25c5e10d 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}; use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::ppi::Ppi; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, + Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, }; use embassy_nrf::Peripherals; @@ -53,8 +53,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let start = unsafe { pwm.task_start_seq0() }; let stop = unsafe { pwm.task_stop() }; - let sequence = Sequence::new(&seq_words, seq_config); - let sequencer = SingleSequencer::new(&mut pwm, sequence); + let sequencer = SingleSequencer::new(&mut pwm, &seq_words, seq_config); unwrap!(sequencer.start(SingleSequenceMode::Infinite)); let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button1.event_in(), start); diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 71ddd5283..d1a027a7e 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; use embassy::time::{Duration, Timer}; use embassy_nrf::gpio::NoPin; use embassy_nrf::pwm::{ - Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, + Config, Prescaler, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, SingleSequencer, }; use embassy_nrf::Peripherals; @@ -54,8 +54,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut bit_value = T0H; loop { - let sequence0 = Sequence::new(&seq_words, seq_config.clone()); - let sequences = SingleSequencer::new(&mut pwm, sequence0); + let sequences = SingleSequencer::new(&mut pwm, &seq_words, seq_config.clone()); unwrap!(sequences.start(SingleSequenceMode::Times(1))); Timer::after(Duration::from_millis(50)).await; -- cgit