aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorhuntc <[email protected]>2022-01-25 18:06:42 +1100
committerhuntc <[email protected]>2022-01-28 11:20:04 +1100
commit47aeab152fff59e64d8244475dfbec338e6f98e5 (patch)
tree0bc694c01f575d9a26071416f803494b6988dbb7 /examples
parentd76cd5ceaf5140c48ef97180beae156c0c0e07c8 (diff)
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.
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf/src/bin/pwm_sequence.rs23
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ppi.rs9
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ws2812b.rs60
3 files changed, 83 insertions, 9 deletions
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::*;
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::{Prescaler, SequenceConfig, SequenceMode, SequencePwm}; 11use embassy_nrf::pwm::{Config, Prescaler, SequenceMode, SequencePwm};
12use embassy_nrf::Peripherals; 12use embassy_nrf::Peripherals;
13 13
14#[embassy::main] 14#[embassy::main]
@@ -16,26 +16,39 @@ async fn main(_spawner: Spawner, p: Peripherals) {
16 let seq_values_1: [u16; 5] = [1000, 250, 100, 50, 0]; 16 let seq_values_1: [u16; 5] = [1000, 250, 100, 50, 0];
17 let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000]; 17 let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000];
18 18
19 let mut config = SequenceConfig::default(); 19 let mut config = Config::default();
20 config.prescaler = Prescaler::Div128; 20 config.prescaler = Prescaler::Div128;
21 // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us 21 // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us
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 config.refresh = 624; 25 let mut seq_config = Config::default();
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 mut pwm = unwrap!(SequencePwm::new( 29 let mut pwm = unwrap!(SequencePwm::new(
29 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 30 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
30 )); 31 ));
31 let _ = pwm.start(&seq_values_1, SequenceMode::Infinite); 32 let _ = pwm.start(
33 &seq_values_1,
34 seq_config,
35 None,
36 None,
37 SeqSequenceMode::Infinite,
38 );
32 39
33 info!("pwm started!"); 40 info!("pwm started!");
34 41
35 Timer::after(Duration::from_millis(20000)).await; 42 Timer::after(Duration::from_millis(20000)).await;
36 info!("pwm starting with another sequence!"); 43 info!("pwm starting with another sequence!");
37 44
38 let _ = pwm.start(&seq_values_2, SequenceMode::Infinite); 45 let _ = pwm.start(
46 &seq_values_2,
47 seq_config,
48 None,
49 None,
50 SequenceMode::Infinite,
51 );
39 52
40 // we can abort a sequence if we need to before its complete with pwm.stop() 53 // we can abort a sequence if we need to before its complete with pwm.stop()
41 // or stop is also implicitly called when the pwm peripheral is dropped 54 // 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;
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::{Prescaler, SequenceConfig, SequenceMode, SequencePwm}; 14use embassy_nrf::pwm::{Config, Prescaler, 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_values: [u16; 5] = [1000, 250, 100, 50, 0];
20 20
21 let mut config = SequenceConfig::default(); 21 let mut config = Config::default();
22 config.prescaler = Prescaler::Div128; 22 config.prescaler = Prescaler::Div128;
23 // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us 23 // 1 period is 1000 * (128/16mhz = 0.000008s = 0.008ms) = 8us
24 // but say we want to hold the value for 250ms 250ms/8 = 31.25 periods 24 // but say we want to hold the value for 250ms 250ms/8 = 31.25 periods
25 // so round to 31 - 1 (we get the one period for free remember) 25 // so round to 31 - 1 (we get the one period for free remember)
26 // thus our sequence takes 5 * 250ms or 1.25 seconds 26 // thus our sequence takes 5 * 250ms or 1.25 seconds
27 config.refresh = 30; 27 let mut seq_config = SequenceConfig::default();
28 seq_config.refresh = 30;
28 29
29 let mut pwm = unwrap!(SequencePwm::new( 30 let mut pwm = unwrap!(SequencePwm::new(
30 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, 31 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
31 )); 32 ));
32 33
33 let _ = pwm.start(&seq_values, SequenceMode::Times(1)); 34 let _ = pwm.start(&seq_values, seq_config, None, None, SequenceMode::Infinite);
34 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 35 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
35 // so its going to have to start running in order load the configuration 36 // so its going to have to start running in order load the configuration
36 37
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 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use defmt::*;
8use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer};
10use embassy_nrf::gpio::NoPin;
11use embassy_nrf::pwm::{
12 Config, Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm,
13};
14use embassy_nrf::Peripherals;
15
16// WS2812B LED light demonstration. Drives just one light.
17// The following reference on WS2812B may be of use:
18// https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf
19
20// In the following declarations, setting the high bit tells the PWM
21// to reverse polarity, which is what the WS2812B expects.
22
23const T1H: u16 = 0x8000 | 13; // Duty = 13/20 ticks (0.8us/1.25us) for a 1
24const T0H: u16 = 0x8000 | 7; // Duty 7/20 ticks (0.4us/1.25us) for a 0
25const RES: u16 = 0x8000;
26
27// Provides data to a WS2812b (Neopixel) LED and makes it go blue. The data
28// line is assumed to be P1_05.
29#[embassy::main]
30async fn main(_spawner: Spawner, p: Peripherals) {
31 // Declare the bits of 24 bits
32 let mut blue_seq: [u16; 8 * 3] = [
33 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G
34 T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R
35 T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B
36 ];
37 let reset_seq = [RES; 1];
38
39 let mut config = Config::default();
40 config.sequence_load = SequenceLoad::Common;
41 config.prescaler = Prescaler::Div1;
42 config.max_duty = 20; // 1.25us (1s / 16Mhz * 20)
43 let mut pwm = unwrap!(SequencePwm::new(
44 p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config,
45 ));
46
47 let blue_seq_config = SequenceConfig::default();
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
58 Timer::after(Duration::from_millis(20000)).await;
59 info!("Program stopped");
60}