aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio_programs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio_programs')
-rw-r--r--embassy-rp/src/pio_programs/hd44780.rs2
-rw-r--r--embassy-rp/src/pio_programs/i2s.rs20
-rw-r--r--embassy-rp/src/pio_programs/onewire.rs26
-rw-r--r--embassy-rp/src/pio_programs/pwm.rs4
-rw-r--r--embassy-rp/src/pio_programs/rotary_encoder.rs2
-rw-r--r--embassy-rp/src/pio_programs/spi.rs4
-rw-r--r--embassy-rp/src/pio_programs/stepper.rs2
-rw-r--r--embassy-rp/src/pio_programs/uart.rs4
-rw-r--r--embassy-rp/src/pio_programs/ws2812.rs125
9 files changed, 146 insertions, 43 deletions
diff --git a/embassy-rp/src/pio_programs/hd44780.rs b/embassy-rp/src/pio_programs/hd44780.rs
index 546c85a89..78281ddd4 100644
--- a/embassy-rp/src/pio_programs/hd44780.rs
+++ b/embassy-rp/src/pio_programs/hd44780.rs
@@ -1,12 +1,12 @@
1//! [HD44780 display driver](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) 1//! [HD44780 display driver](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf)
2 2
3use crate::Peri;
3use crate::dma::{AnyChannel, Channel}; 4use crate::dma::{AnyChannel, Channel};
4use crate::pio::{ 5use crate::pio::{
5 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, 6 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection,
6 StateMachine, 7 StateMachine,
7}; 8};
8use crate::pio_programs::clock_divider::calculate_pio_clock_divider; 9use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
9use crate::Peri;
10 10
11/// This struct represents a HD44780 program that takes command words (<wait:24> <command:4> <0:4>) 11/// This struct represents a HD44780 program that takes command words (<wait:24> <command:4> <0:4>)
12pub struct PioHD44780CommandWordProgram<'a, PIO: Instance> { 12pub struct PioHD44780CommandWordProgram<'a, PIO: Instance> {
diff --git a/embassy-rp/src/pio_programs/i2s.rs b/embassy-rp/src/pio_programs/i2s.rs
index 2382a3f9f..5c49beecb 100644
--- a/embassy-rp/src/pio_programs/i2s.rs
+++ b/embassy-rp/src/pio_programs/i2s.rs
@@ -1,15 +1,15 @@
1//! Pio backed I2s output and output drivers 1//! Pio backed I2S output and output drivers
2 2
3use fixed::traits::ToFixed; 3use fixed::traits::ToFixed;
4 4
5use crate::Peri;
5use crate::dma::{AnyChannel, Channel, Transfer}; 6use crate::dma::{AnyChannel, Channel, Transfer};
6use crate::gpio::Pull; 7use crate::gpio::Pull;
7use crate::pio::{ 8use crate::pio::{
8 Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, 9 Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
9}; 10};
10use crate::Peri;
11 11
12/// This struct represents an i2s receiver & controller driver program 12/// This struct represents an I2S receiver & controller driver program
13pub struct PioI2sInProgram<'d, PIO: Instance> { 13pub struct PioI2sInProgram<'d, PIO: Instance> {
14 prg: LoadedProgram<'d, PIO>, 14 prg: LoadedProgram<'d, PIO>,
15} 15}
@@ -35,7 +35,7 @@ impl<'d, PIO: Instance> PioI2sInProgram<'d, PIO> {
35 } 35 }
36} 36}
37 37
38/// Pio backed I2s input driver 38/// Pio backed I2S input driver
39pub struct PioI2sIn<'d, P: Instance, const S: usize> { 39pub struct PioI2sIn<'d, P: Instance, const S: usize> {
40 dma: Peri<'d, AnyChannel>, 40 dma: Peri<'d, AnyChannel>,
41 sm: StateMachine<'d, P, S>, 41 sm: StateMachine<'d, P, S>,
@@ -50,7 +50,7 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> {
50 // Whether or not to use the MCU's internal pull-down resistor, as the 50 // Whether or not to use the MCU's internal pull-down resistor, as the
51 // Pico 2 is known to have problems with the inbuilt pulldowns, many 51 // Pico 2 is known to have problems with the inbuilt pulldowns, many
52 // opt to just use an external pull down resistor to meet requirements of common 52 // opt to just use an external pull down resistor to meet requirements of common
53 // i2s microphones such as the INMP441 53 // I2S microphones such as the INMP441
54 data_pulldown: bool, 54 data_pulldown: bool,
55 data_pin: Peri<'d, impl PioPin>, 55 data_pin: Peri<'d, impl PioPin>,
56 bit_clock_pin: Peri<'d, impl PioPin>, 56 bit_clock_pin: Peri<'d, impl PioPin>,
@@ -90,13 +90,13 @@ impl<'d, P: Instance, const S: usize> PioI2sIn<'d, P, S> {
90 Self { dma: dma.into(), sm } 90 Self { dma: dma.into(), sm }
91 } 91 }
92 92
93 /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. 93 /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer.
94 pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> { 94 pub fn read<'b>(&'b mut self, buff: &'b mut [u32]) -> Transfer<'b, AnyChannel> {
95 self.sm.rx().dma_pull(self.dma.reborrow(), buff, false) 95 self.sm.rx().dma_pull(self.dma.reborrow(), buff, false)
96 } 96 }
97} 97}
98 98
99/// This struct represents an i2s output driver program 99/// This struct represents an I2S output driver program
100/// 100///
101/// The sample bit-depth is set through scratch register `Y`. 101/// The sample bit-depth is set through scratch register `Y`.
102/// `Y` has to be set to sample bit-depth - 2. 102/// `Y` has to be set to sample bit-depth - 2.
@@ -128,14 +128,14 @@ impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> {
128 } 128 }
129} 129}
130 130
131/// Pio backed I2s output driver 131/// Pio backed I2S output driver
132pub struct PioI2sOut<'d, P: Instance, const S: usize> { 132pub struct PioI2sOut<'d, P: Instance, const S: usize> {
133 dma: Peri<'d, AnyChannel>, 133 dma: Peri<'d, AnyChannel>,
134 sm: StateMachine<'d, P, S>, 134 sm: StateMachine<'d, P, S>,
135} 135}
136 136
137impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> { 137impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
138 /// Configure a state machine to output I2s 138 /// Configure a state machine to output I2S
139 pub fn new( 139 pub fn new(
140 common: &mut Common<'d, P>, 140 common: &mut Common<'d, P>,
141 mut sm: StateMachine<'d, P, S>, 141 mut sm: StateMachine<'d, P, S>,
@@ -179,7 +179,7 @@ impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
179 Self { dma: dma.into(), sm } 179 Self { dma: dma.into(), sm }
180 } 180 }
181 181
182 /// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer. 182 /// Return an in-progress dma transfer future. Awaiting it will guarantee a complete transfer.
183 pub fn write<'b>(&'b mut self, buff: &'b [u32]) -> Transfer<'b, AnyChannel> { 183 pub fn write<'b>(&'b mut self, buff: &'b [u32]) -> Transfer<'b, AnyChannel> {
184 self.sm.tx().dma_push(self.dma.reborrow(), buff, false) 184 self.sm.tx().dma_push(self.dma.reborrow(), buff, false)
185 } 185 }
diff --git a/embassy-rp/src/pio_programs/onewire.rs b/embassy-rp/src/pio_programs/onewire.rs
index 980d0fe5f..3adab3b79 100644
--- a/embassy-rp/src/pio_programs/onewire.rs
+++ b/embassy-rp/src/pio_programs/onewire.rs
@@ -1,11 +1,11 @@
1//! OneWire pio driver 1//! OneWire pio driver
2 2
3use crate::Peri;
3use crate::clocks::clk_sys_freq; 4use crate::clocks::clk_sys_freq;
4use crate::gpio::Level; 5use crate::gpio::Level;
5use crate::pio::{ 6use crate::pio::{
6 Common, Config, Direction, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, 7 Common, Config, Direction, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
7}; 8};
8use crate::Peri;
9 9
10/// This struct represents a onewire driver program 10/// This struct represents a onewire driver program
11pub struct PioOneWireProgram<'a, PIO: Instance> { 11pub struct PioOneWireProgram<'a, PIO: Instance> {
@@ -163,7 +163,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
163 163
164 /// Write bytes to the onewire bus 164 /// Write bytes to the onewire bus
165 pub async fn write_bytes(&mut self, data: &[u8]) { 165 pub async fn write_bytes(&mut self, data: &[u8]) {
166 unsafe { self.sm.set_y(u32::MAX as u32) }; 166 unsafe {
167 self.sm.set_enable(false);
168 self.sm.set_y(u32::MAX as u32);
169 self.sm.set_enable(true);
170 }
167 let (rx, tx) = self.sm.rx_tx(); 171 let (rx, tx) = self.sm.rx_tx();
168 for b in data { 172 for b in data {
169 tx.wait_push(*b as u32).await; 173 tx.wait_push(*b as u32).await;
@@ -175,7 +179,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
175 179
176 /// Write bytes to the onewire bus, then apply a strong pullup 180 /// Write bytes to the onewire bus, then apply a strong pullup
177 pub async fn write_bytes_pullup(&mut self, data: &[u8], pullup_time: embassy_time::Duration) { 181 pub async fn write_bytes_pullup(&mut self, data: &[u8], pullup_time: embassy_time::Duration) {
178 unsafe { self.sm.set_y(data.len() as u32 * 8 - 1) }; 182 unsafe {
183 self.sm.set_enable(false);
184 self.sm.set_y(data.len() as u32 * 8 - 1);
185 self.sm.set_enable(true);
186 };
179 let (rx, tx) = self.sm.rx_tx(); 187 let (rx, tx) = self.sm.rx_tx();
180 for b in data { 188 for b in data {
181 tx.wait_push(*b as u32).await; 189 tx.wait_push(*b as u32).await;
@@ -195,7 +203,11 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
195 203
196 /// Read bytes from the onewire bus 204 /// Read bytes from the onewire bus
197 pub async fn read_bytes(&mut self, data: &mut [u8]) { 205 pub async fn read_bytes(&mut self, data: &mut [u8]) {
198 unsafe { self.sm.set_y(u32::MAX as u32) }; 206 unsafe {
207 self.sm.set_enable(false);
208 self.sm.set_y(u32::MAX as u32);
209 self.sm.set_enable(true);
210 };
199 let (rx, tx) = self.sm.rx_tx(); 211 let (rx, tx) = self.sm.rx_tx();
200 for b in data { 212 for b in data {
201 // Write all 1's so that we can read what the device responds 213 // Write all 1's so that we can read what the device responds
@@ -321,11 +333,7 @@ impl PioOneWireSearch {
321 333
322 /// Search for the next address on the bus 334 /// Search for the next address on the bus
323 pub async fn next<PIO: Instance, const SM: usize>(&mut self, pio: &mut PioOneWire<'_, PIO, SM>) -> Option<u64> { 335 pub async fn next<PIO: Instance, const SM: usize>(&mut self, pio: &mut PioOneWire<'_, PIO, SM>) -> Option<u64> {
324 if self.finished { 336 if self.finished { None } else { pio.search(self).await }
325 None
326 } else {
327 pio.search(self).await
328 }
329 } 337 }
330 338
331 /// Is finished when all devices have been found 339 /// Is finished when all devices have been found
diff --git a/embassy-rp/src/pio_programs/pwm.rs b/embassy-rp/src/pio_programs/pwm.rs
index f0f837bc5..e4ad4a6f0 100644
--- a/embassy-rp/src/pio_programs/pwm.rs
+++ b/embassy-rp/src/pio_programs/pwm.rs
@@ -6,7 +6,7 @@ use pio::InstructionOperands;
6 6
7use crate::gpio::Level; 7use crate::gpio::Level;
8use crate::pio::{Common, Config, Direction, Instance, LoadedProgram, Pin, PioPin, StateMachine}; 8use crate::pio::{Common, Config, Direction, Instance, LoadedProgram, Pin, PioPin, StateMachine};
9use crate::{clocks, Peri}; 9use crate::{Peri, clocks};
10 10
11/// This converts the duration provided into the number of cycles the PIO needs to run to make it take the same time 11/// This converts the duration provided into the number of cycles the PIO needs to run to make it take the same time
12fn to_pio_cycles(duration: Duration) -> u32 { 12fn to_pio_cycles(duration: Duration) -> u32 {
@@ -67,7 +67,7 @@ impl<'d, T: Instance, const SM: usize> PioPwm<'d, T, SM> {
67 Self { sm, pin } 67 Self { sm, pin }
68 } 68 }
69 69
70 /// Enable's the PIO program, continuing the wave generation from the PIO program. 70 /// Enables the PIO program, continuing the wave generation from the PIO program.
71 pub fn start(&mut self) { 71 pub fn start(&mut self) {
72 self.sm.set_enable(true); 72 self.sm.set_enable(true);
73 } 73 }
diff --git a/embassy-rp/src/pio_programs/rotary_encoder.rs b/embassy-rp/src/pio_programs/rotary_encoder.rs
index 70b3795e9..6347527e6 100644
--- a/embassy-rp/src/pio_programs/rotary_encoder.rs
+++ b/embassy-rp/src/pio_programs/rotary_encoder.rs
@@ -1,11 +1,11 @@
1//! PIO backed quadrature encoder 1//! PIO backed quadrature encoder
2 2
3use crate::Peri;
3use crate::gpio::Pull; 4use crate::gpio::Pull;
4use crate::pio::{ 5use crate::pio::{
5 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine, 6 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
6}; 7};
7use crate::pio_programs::clock_divider::calculate_pio_clock_divider; 8use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
8use crate::Peri;
9 9
10/// This struct represents an Encoder program loaded into pio instruction memory. 10/// This struct represents an Encoder program loaded into pio instruction memory.
11pub struct PioEncoderProgram<'a, PIO: Instance> { 11pub struct PioEncoderProgram<'a, PIO: Instance> {
diff --git a/embassy-rp/src/pio_programs/spi.rs b/embassy-rp/src/pio_programs/spi.rs
index b10fc6628..765ffaa06 100644
--- a/embassy-rp/src/pio_programs/spi.rs
+++ b/embassy-rp/src/pio_programs/spi.rs
@@ -1,4 +1,4 @@
1//! PIO backed SPi drivers 1//! PIO backed SPI drivers
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4 4
@@ -83,7 +83,7 @@ pub enum Error {
83 // No errors for now 83 // No errors for now
84} 84}
85 85
86/// PIO based Spi driver. 86/// PIO based SPI driver.
87/// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to 87/// Unlike other PIO programs, the PIO SPI driver owns and holds a reference to
88/// the PIO memory it uses. This is so that it can be reconfigured at runtime if 88/// the PIO memory it uses. This is so that it can be reconfigured at runtime if
89/// desired. 89/// desired.
diff --git a/embassy-rp/src/pio_programs/stepper.rs b/embassy-rp/src/pio_programs/stepper.rs
index 0e9a8daf9..5762ee189 100644
--- a/embassy-rp/src/pio_programs/stepper.rs
+++ b/embassy-rp/src/pio_programs/stepper.rs
@@ -2,9 +2,9 @@
2 2
3use core::mem::{self, MaybeUninit}; 3use core::mem::{self, MaybeUninit};
4 4
5use crate::Peri;
5use crate::pio::{Common, Config, Direction, Instance, Irq, LoadedProgram, PioPin, StateMachine}; 6use crate::pio::{Common, Config, Direction, Instance, Irq, LoadedProgram, PioPin, StateMachine};
6use crate::pio_programs::clock_divider::calculate_pio_clock_divider; 7use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
7use crate::Peri;
8 8
9/// This struct represents a Stepper driver program loaded into pio instruction memory. 9/// This struct represents a Stepper driver program loaded into pio instruction memory.
10pub struct PioStepperProgram<'a, PIO: Instance> { 10pub struct PioStepperProgram<'a, PIO: Instance> {
diff --git a/embassy-rp/src/pio_programs/uart.rs b/embassy-rp/src/pio_programs/uart.rs
index 04e39a571..d59596dd1 100644
--- a/embassy-rp/src/pio_programs/uart.rs
+++ b/embassy-rp/src/pio_programs/uart.rs
@@ -5,12 +5,12 @@ use core::convert::Infallible;
5use embedded_io_async::{ErrorType, Read, Write}; 5use embedded_io_async::{ErrorType, Read, Write};
6use fixed::traits::ToFixed; 6use fixed::traits::ToFixed;
7 7
8use crate::Peri;
8use crate::clocks::clk_sys_freq; 9use crate::clocks::clk_sys_freq;
9use crate::gpio::Level; 10use crate::gpio::Level;
10use crate::pio::{ 11use crate::pio::{
11 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine, 12 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
12}; 13};
13use crate::Peri;
14 14
15/// This struct represents a uart tx program loaded into pio instruction memory. 15/// This struct represents a uart tx program loaded into pio instruction memory.
16pub struct PioUartTxProgram<'d, PIO: Instance> { 16pub struct PioUartTxProgram<'d, PIO: Instance> {
@@ -130,7 +130,7 @@ impl<'d, PIO: Instance> PioUartRxProgram<'d, PIO> {
130 } 130 }
131} 131}
132 132
133/// PIO backed Uart reciever 133/// PIO backed Uart receiver
134pub struct PioUartRx<'d, PIO: Instance, const SM: usize> { 134pub struct PioUartRx<'d, PIO: Instance, const SM: usize> {
135 sm_rx: StateMachine<'d, PIO, SM>, 135 sm_rx: StateMachine<'d, PIO, SM>,
136} 136}
diff --git a/embassy-rp/src/pio_programs/ws2812.rs b/embassy-rp/src/pio_programs/ws2812.rs
index 37dd1c4e0..0b6035316 100644
--- a/embassy-rp/src/pio_programs/ws2812.rs
+++ b/embassy-rp/src/pio_programs/ws2812.rs
@@ -1,21 +1,69 @@
1//! [ws2812](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) 1//! [ws2812](https://www.sparkfun.com/categories/tags/ws2812)
2 2
3use embassy_time::Timer; 3use embassy_time::Timer;
4use fixed::types::U24F8; 4use fixed::types::U24F8;
5use smart_leds::{RGB8, RGBW}; 5use smart_leds::{RGB8, RGBW};
6 6
7use crate::Peri;
7use crate::clocks::clk_sys_freq; 8use crate::clocks::clk_sys_freq;
8use crate::dma::{AnyChannel, Channel}; 9use crate::dma::{AnyChannel, Channel};
9use crate::pio::{ 10use crate::pio::{
10 Common, Config, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine, 11 Common, Config, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
11}; 12};
12use crate::Peri;
13 13
14const T1: u8 = 2; // start bit 14const T1: u8 = 2; // start bit
15const T2: u8 = 5; // data bit 15const T2: u8 = 5; // data bit
16const T3: u8 = 3; // stop bit 16const T3: u8 = 3; // stop bit
17const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; 17const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32;
18 18
19/// Color orders for WS2812B, type RGB8
20pub trait RgbColorOrder {
21 /// Pack an 8-bit RGB color into a u32
22 fn pack(color: RGB8) -> u32;
23}
24
25/// Green, Red, Blue order is the common default for WS2812B
26pub struct Grb;
27impl RgbColorOrder for Grb {
28 /// Pack an 8-bit RGB color into a u32 in GRB order
29 fn pack(color: RGB8) -> u32 {
30 (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8)
31 }
32}
33
34/// Red, Green, Blue is used by some WS2812B implementations
35pub struct Rgb;
36impl RgbColorOrder for Rgb {
37 /// Pack an 8-bit RGB color into a u32 in RGB order
38 fn pack(color: RGB8) -> u32 {
39 (u32::from(color.r) << 24) | (u32::from(color.g) << 16) | (u32::from(color.b) << 8)
40 }
41}
42
43/// Color orders RGBW strips
44pub trait RgbwColorOrder {
45 /// Pack an RGB+W color into a u32
46 fn pack(color: RGBW<u8>) -> u32;
47}
48
49/// Green, Red, Blue, White order is the common default for RGBW strips
50pub struct Grbw;
51impl RgbwColorOrder for Grbw {
52 /// Pack an RGB+W color into a u32 in GRBW order
53 fn pack(color: RGBW<u8>) -> u32 {
54 (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8) | u32::from(color.a.0)
55 }
56}
57
58/// Red, Green, Blue, White order
59pub struct Rgbw;
60impl RgbwColorOrder for Rgbw {
61 /// Pack an RGB+W color into a u32 in RGBW order
62 fn pack(color: RGBW<u8>) -> u32 {
63 (u32::from(color.r) << 24) | (u32::from(color.g) << 16) | (u32::from(color.b) << 8) | u32::from(color.a.0)
64 }
65}
66
19/// This struct represents a ws2812 program loaded into pio instruction memory. 67/// This struct represents a ws2812 program loaded into pio instruction memory.
20pub struct PioWs2812Program<'a, PIO: Instance> { 68pub struct PioWs2812Program<'a, PIO: Instance> {
21 prg: LoadedProgram<'a, PIO>, 69 prg: LoadedProgram<'a, PIO>,
@@ -52,15 +100,37 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> {
52 100
53/// Pio backed RGB ws2812 driver 101/// Pio backed RGB ws2812 driver
54/// Const N is the number of ws2812 leds attached to this pin 102/// Const N is the number of ws2812 leds attached to this pin
55pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize> { 103pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize, ORDER>
104where
105 ORDER: RgbColorOrder,
106{
56 dma: Peri<'d, AnyChannel>, 107 dma: Peri<'d, AnyChannel>,
57 sm: StateMachine<'d, P, S>, 108 sm: StateMachine<'d, P, S>,
109 _order: core::marker::PhantomData<ORDER>,
58} 110}
59 111
60impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> { 112impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N, Grb> {
61 /// Configure a pio state machine to use the loaded ws2812 program. 113 /// Configure a pio state machine to use the loaded ws2812 program.
114 /// Uses the default GRB order.
62 pub fn new( 115 pub fn new(
63 pio: &mut Common<'d, P>, 116 pio: &mut Common<'d, P>,
117 sm: StateMachine<'d, P, S>,
118 dma: Peri<'d, impl Channel>,
119 pin: Peri<'d, impl PioPin>,
120 program: &PioWs2812Program<'d, P>,
121 ) -> Self {
122 Self::with_color_order(pio, sm, dma, pin, program)
123 }
124}
125
126impl<'d, P: Instance, const S: usize, const N: usize, ORDER> PioWs2812<'d, P, S, N, ORDER>
127where
128 ORDER: RgbColorOrder,
129{
130 /// Configure a pio state machine to use the loaded ws2812 program.
131 /// Uses the specified color order.
132 pub fn with_color_order(
133 pio: &mut Common<'d, P>,
64 mut sm: StateMachine<'d, P, S>, 134 mut sm: StateMachine<'d, P, S>,
65 dma: Peri<'d, impl Channel>, 135 dma: Peri<'d, impl Channel>,
66 pin: Peri<'d, impl PioPin>, 136 pin: Peri<'d, impl PioPin>,
@@ -93,7 +163,11 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
93 sm.set_config(&cfg); 163 sm.set_config(&cfg);
94 sm.set_enable(true); 164 sm.set_enable(true);
95 165
96 Self { dma: dma.into(), sm } 166 Self {
167 dma: dma.into(),
168 sm,
169 _order: core::marker::PhantomData,
170 }
97 } 171 }
98 172
99 /// Write a buffer of [smart_leds::RGB8] to the ws2812 string 173 /// Write a buffer of [smart_leds::RGB8] to the ws2812 string
@@ -101,8 +175,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
101 // Precompute the word bytes from the colors 175 // Precompute the word bytes from the colors
102 let mut words = [0u32; N]; 176 let mut words = [0u32; N];
103 for i in 0..N { 177 for i in 0..N {
104 let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8); 178 words[i] = ORDER::pack(colors[i]);
105 words[i] = word;
106 } 179 }
107 180
108 // DMA transfer 181 // DMA transfer
@@ -115,15 +188,37 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
115/// Pio backed RGBW ws2812 driver 188/// Pio backed RGBW ws2812 driver
116/// This version is intended for ws2812 leds with 4 addressable lights 189/// This version is intended for ws2812 leds with 4 addressable lights
117/// Const N is the number of ws2812 leds attached to this pin 190/// Const N is the number of ws2812 leds attached to this pin
118pub struct RgbwPioWs2812<'d, P: Instance, const S: usize, const N: usize> { 191pub struct RgbwPioWs2812<'d, P: Instance, const S: usize, const N: usize, ORDER>
192where
193 ORDER: RgbwColorOrder,
194{
119 dma: Peri<'d, AnyChannel>, 195 dma: Peri<'d, AnyChannel>,
120 sm: StateMachine<'d, P, S>, 196 sm: StateMachine<'d, P, S>,
197 _order: core::marker::PhantomData<ORDER>,
121} 198}
122 199
123impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N> { 200impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N, Grbw> {
124 /// Configure a pio state machine to use the loaded ws2812 program. 201 /// Configure a pio state machine to use the loaded ws2812 program.
202 /// Uses the default GRBW color order
125 pub fn new( 203 pub fn new(
126 pio: &mut Common<'d, P>, 204 pio: &mut Common<'d, P>,
205 sm: StateMachine<'d, P, S>,
206 dma: Peri<'d, impl Channel>,
207 pin: Peri<'d, impl PioPin>,
208 program: &PioWs2812Program<'d, P>,
209 ) -> Self {
210 Self::with_color_order(pio, sm, dma, pin, program)
211 }
212}
213
214impl<'d, P: Instance, const S: usize, const N: usize, ORDER> RgbwPioWs2812<'d, P, S, N, ORDER>
215where
216 ORDER: RgbwColorOrder,
217{
218 /// Configure a pio state machine to use the loaded ws2812 program.
219 /// Uses the specified color order
220 pub fn with_color_order(
221 pio: &mut Common<'d, P>,
127 mut sm: StateMachine<'d, P, S>, 222 mut sm: StateMachine<'d, P, S>,
128 dma: Peri<'d, impl Channel>, 223 dma: Peri<'d, impl Channel>,
129 pin: Peri<'d, impl PioPin>, 224 pin: Peri<'d, impl PioPin>,
@@ -156,7 +251,11 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N>
156 sm.set_config(&cfg); 251 sm.set_config(&cfg);
157 sm.set_enable(true); 252 sm.set_enable(true);
158 253
159 Self { dma: dma.into(), sm } 254 Self {
255 dma: dma.into(),
256 sm,
257 _order: core::marker::PhantomData,
258 }
160 } 259 }
161 260
162 /// Write a buffer of [smart_leds::RGBW] to the ws2812 string 261 /// Write a buffer of [smart_leds::RGBW] to the ws2812 string
@@ -164,11 +263,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N>
164 // Precompute the word bytes from the colors 263 // Precompute the word bytes from the colors
165 let mut words = [0u32; N]; 264 let mut words = [0u32; N];
166 for i in 0..N { 265 for i in 0..N {
167 let word = (u32::from(colors[i].g) << 24) 266 words[i] = ORDER::pack(colors[i]);
168 | (u32::from(colors[i].r) << 16)
169 | (u32::from(colors[i].b) << 8)
170 | u32::from(colors[i].a.0);
171 words[i] = word;
172 } 267 }
173 268
174 // DMA transfer 269 // DMA transfer