Improve ws2812 api
This commit is contained in:
51
src/main.rs
51
src/main.rs
@ -11,7 +11,6 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
extern crate cortex_m_rt;
|
extern crate cortex_m_rt;
|
||||||
//extern crate panic_halt;
|
|
||||||
|
|
||||||
mod board;
|
mod board;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
@ -22,10 +21,7 @@ mod ws2812;
|
|||||||
|
|
||||||
use board::Board;
|
use board::Board;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::{
|
use embassy_rp::gpio::{Level, Output, Pin};
|
||||||
gpio::{Level, Output, Pin},
|
|
||||||
pio::PioPeripheral,
|
|
||||||
};
|
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use ws2812::Rgb;
|
use ws2812::Rgb;
|
||||||
|
|
||||||
@ -64,9 +60,8 @@ async fn main(spawner: Spawner) {
|
|||||||
//let mut led = Output::new(board.d13, Level::Low);
|
//let mut led = Output::new(board.d13, Level::Low);
|
||||||
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
||||||
|
|
||||||
let (_, sm, ..) = p.PIO0.split();
|
let mut neopixel = ws2812::Ws2812::new(p.PIO0, p.DMA_CH0, board.neopixel.degrade());
|
||||||
let mut neopixel = ws2812::Ws2812::new(sm, p.DMA_CH0, board.neopixel.degrade());
|
let mut neopixels_d5 = ws2812::Ws2812::new(p.PIO1, p.DMA_CH1, board.d5.degrade());
|
||||||
//let mut neopixel = ws2812::Ws2812::new(sm, p.DMA_CH0, board.d5.degrade());
|
|
||||||
|
|
||||||
neopixel.write(&[Rgb::new(0xb7, 0x31, 0x2c)]).await;
|
neopixel.write(&[Rgb::new(0xb7, 0x31, 0x2c)]).await;
|
||||||
|
|
||||||
@ -111,18 +106,32 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
//keyboard::test::type_string("Hello there!\n").await;
|
//keyboard::test::type_string("Hello there!\n").await;
|
||||||
//keyboard::test::rollover(['h', 'e', 'l', 'o', 't', 'r', 'a', 'b', 'c', 'd', 'i']).await;
|
//keyboard::test::rollover(['h', 'e', 'l', 'o', 't', 'r', 'a', 'b', 'c', 'd', 'i']).await;
|
||||||
loop {
|
for w in 0usize.. {
|
||||||
//neopixel
|
neopixel.write(&[wheel(w as u8)]).await;
|
||||||
// .write(&[
|
neopixels_d5
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
.write(&[
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
wheel((w + 50) as u8),
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
wheel((w + 100) as u8),
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
wheel((w + 150) as u8),
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
wheel((w + 200) as u8),
|
||||||
// Rgb::new(0xAA, 0xFF, 0x00),
|
])
|
||||||
// ])
|
.await;
|
||||||
// .await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
//Timer::after(Duration::from_millis(10)).await;
|
//Timer::after(Duration::from_secs(10)).await;
|
||||||
Timer::after(Duration::from_secs(10)).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Input a value 0 to 255 to get a color value
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
fn wheel(mut wheel_pos: u8) -> Rgb {
|
||||||
|
wheel_pos = 255 - wheel_pos;
|
||||||
|
if wheel_pos < 85 {
|
||||||
|
return Rgb::new(255 - wheel_pos * 3, 0, wheel_pos * 3);
|
||||||
|
}
|
||||||
|
if wheel_pos < 170 {
|
||||||
|
wheel_pos -= 85;
|
||||||
|
return Rgb::new(0, wheel_pos * 3, 255 - wheel_pos * 3);
|
||||||
|
}
|
||||||
|
wheel_pos -= 170;
|
||||||
|
Rgb::new(wheel_pos * 3, 255 - wheel_pos * 3, 0)
|
||||||
|
}
|
||||||
|
|||||||
@ -3,27 +3,30 @@ use core::mem::transmute;
|
|||||||
|
|
||||||
use embassy_rp::dma::{self, AnyChannel};
|
use embassy_rp::dma::{self, AnyChannel};
|
||||||
use embassy_rp::pio::{
|
use embassy_rp::pio::{
|
||||||
FifoJoin, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance,
|
FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection,
|
||||||
|
SmInstanceBase,
|
||||||
};
|
};
|
||||||
use embassy_rp::pio_instr_util;
|
use embassy_rp::pio_instr_util;
|
||||||
use embassy_rp::relocate::RelocatedProgram;
|
use embassy_rp::relocate::RelocatedProgram;
|
||||||
use embassy_rp::{gpio, PeripheralRef};
|
use embassy_rp::{gpio, PeripheralRef};
|
||||||
|
|
||||||
pub struct Ws2812<P: PioInstance, S: SmInstance> {
|
pub struct Ws2812<P: PioInstance> {
|
||||||
sm: PioStateMachineInstance<P, S>,
|
sm: PioStateMachineInstance<P, SmInstanceBase<0>>,
|
||||||
dma: PeripheralRef<'static, AnyChannel>,
|
dma: PeripheralRef<'static, AnyChannel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An Rgb value that can be safely transmuted to u32 for use with Ws2812.
|
/// An Rgb value that can be safely transmuted to u32 for use with Ws2812.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Rgb(u32);
|
pub struct Rgb(u32);
|
||||||
|
|
||||||
impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
impl<P: PioInstance> Ws2812<P> {
|
||||||
pub fn new(
|
pub fn new<PP: PioPeripheral<Pio = P>>(
|
||||||
mut sm: PioStateMachineInstance<P, S>,
|
pio: PP,
|
||||||
dma: impl dma::Channel,
|
dma: impl dma::Channel,
|
||||||
pin: gpio::AnyPin,
|
pin: gpio::AnyPin,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let (_, mut sm, ..) = pio.split();
|
||||||
// prepare the PIO program
|
// prepare the PIO program
|
||||||
let side_set = pio::SideSet::new(false, 1, false);
|
let side_set = pio::SideSet::new(false, 1, false);
|
||||||
let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set);
|
let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set);
|
||||||
@ -94,28 +97,29 @@ impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write(&mut self, colors: &[Rgb]) {
|
pub async fn write(&mut self, colors: &[Rgb]) {
|
||||||
let colors = rgbs_to_u32s(colors);
|
let colors = Rgb::slice_as_u32s(colors);
|
||||||
self.sm.dma_push(self.dma.reborrow(), colors).await;
|
self.sm.dma_push(self.dma.reborrow(), colors).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn rgbs_to_u32s(rgbs: &[Rgb]) -> &[u32] {
|
|
||||||
// SAFETY: Rgb contains only a u32, and is #[repr(transparent)]
|
|
||||||
unsafe { transmute(rgbs) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rgb {
|
impl Rgb {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn new(r: u8, g: u8, b: u8) -> Self {
|
pub const fn new(r: u8, g: u8, b: u8) -> Self {
|
||||||
Self(u32::from_be_bytes([g, r, b, 0]))
|
Self(u32::from_be_bytes([g, r, b, 0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the red, green, and blue components of this Rgb.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn components(&self) -> (u8, u8, u8) {
|
pub const fn components(&self) -> (u8, u8, u8) {
|
||||||
let [g, r, b, _] = self.0.to_be_bytes();
|
let [g, r, b, _] = self.0.to_be_bytes();
|
||||||
(r, g, b)
|
(r, g, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn slice_as_u32s(rgbs: &[Rgb]) -> &[u32] {
|
||||||
|
// SAFETY: Rgb contains only a u32, and is #[repr(transparent)]
|
||||||
|
unsafe { transmute(rgbs) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Rgb {
|
impl Debug for Rgb {
|
||||||
|
|||||||
Reference in New Issue
Block a user