2022-01-25 07:06:42 +00:00
|
|
|
#![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::{
|
2022-01-28 02:38:20 +00:00
|
|
|
Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm,
|
2022-01-25 07:06:42 +00:00
|
|
|
};
|
|
|
|
use embassy_nrf::Peripherals;
|
|
|
|
|
|
|
|
// WS2812B LED light demonstration. Drives just one light.
|
|
|
|
// The following reference on WS2812B may be of use:
|
2022-01-28 05:21:53 +00:00
|
|
|
// 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.
|
2022-01-25 07:06:42 +00:00
|
|
|
|
|
|
|
// 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) {
|
|
|
|
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,
|
|
|
|
));
|
|
|
|
|
2022-01-29 04:26:31 +00:00
|
|
|
// 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)));
|
2022-01-25 07:06:42 +00:00
|
|
|
|
2022-01-28 05:21:53 +00:00
|
|
|
Timer::after(Duration::from_millis(1000)).await;
|
|
|
|
|
|
|
|
let mut color_bit = 16;
|
|
|
|
let mut bit_value = T0H;
|
|
|
|
|
|
|
|
loop {
|
2022-01-29 04:26:31 +00:00
|
|
|
if let (Some(mut color_seq), Some(reset_seq)) = pwm.stop() {
|
2022-01-28 05:21:53 +00:00
|
|
|
color_seq.words[color_bit] = bit_value;
|
2022-01-29 04:26:31 +00:00
|
|
|
unwrap!(pwm.start(color_seq, reset_seq, SequenceMode::Times(2)));
|
2022-01-28 05:21:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-25 07:06:42 +00:00
|
|
|
}
|