From ab1fbde849dc1af9aa1ecf71e94f1098e2ba2fef Mon Sep 17 00:00:00 2001 From: Peter Hayman Date: Mon, 7 Nov 2022 18:00:53 +1100 Subject: [PATCH] initial commit --- esp-hal-common/src/utils/mod.rs | 4 + .../src/utils/smart_leds_adapter.rs | 29 +++++-- .../src/utils/smart_leds_adapter_rgbw.rs | 86 +++++++++++++++++++ 3 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 esp-hal-common/src/utils/smart_leds_adapter_rgbw.rs diff --git a/esp-hal-common/src/utils/mod.rs b/esp-hal-common/src/utils/mod.rs index 4338692394b..2a36888f71e 100644 --- a/esp-hal-common/src/utils/mod.rs +++ b/esp-hal-common/src/utils/mod.rs @@ -5,6 +5,10 @@ pub mod smart_leds_adapter; #[cfg(feature = "smartled")] pub use smart_leds_adapter::SmartLedsAdapter; +#[cfg(feature = "smartled")] +pub mod smart_leds_adapter_rgbw; +#[cfg(feature = "smartled")] +pub use smart_leds_adapter_rgbw::SmartLedsAdapterRGBW; // Re-export the macro that due to the macro_export configuration was already exported // in the root module (i.e., `esp-hal-common`) diff --git a/esp-hal-common/src/utils/smart_leds_adapter.rs b/esp-hal-common/src/utils/smart_leds_adapter.rs index c61c802b969..b039d5dbca7 100644 --- a/esp-hal-common/src/utils/smart_leds_adapter.rs +++ b/esp-hal-common/src/utils/smart_leds_adapter.rs @@ -94,9 +94,24 @@ where { /// Create a new adapter object that drives the pin using the RMT channel. pub fn new( - mut channel: UnconfiguredChannel, + channel: UnconfiguredChannel, pin: PIN, ) -> SmartLedsAdapter + where + UnconfiguredChannel: OutputChannel, + { + Self { + channel: SmartLedsAdapter::::configure_channel(channel, pin), + rmt_buffer: [0; BUFFER_SIZE], + _pin: PhantomData, + } + } + + /// prepare channel for led signals + pub fn configure_channel( + mut channel: UnconfiguredChannel, + pin: PIN, + ) -> CHANNEL where UnconfiguredChannel: OutputChannel, { @@ -115,12 +130,7 @@ where .set_idle_output(true) .set_clock_source(ClockSource::APB); - let channel = channel.assign_pin(pin); - Self { - channel, - rmt_buffer: [0; BUFFER_SIZE], - _pin: PhantomData, - } + channel.assign_pin(pin) } fn convert_rgb_to_pulse( @@ -139,8 +149,9 @@ where Ok(()) } - - fn convert_rgb_channel_to_pulses( + /// Transform individual bytes into pulse codes. Useful for custom + /// implementations, ie RGBW + pub fn convert_rgb_channel_to_pulses( channel_value: u8, mut_iter: &mut IterMut, ) -> Result<(), LedAdapterError> { diff --git a/esp-hal-common/src/utils/smart_leds_adapter_rgbw.rs b/esp-hal-common/src/utils/smart_leds_adapter_rgbw.rs new file mode 100644 index 00000000000..c9b5f450d64 --- /dev/null +++ b/esp-hal-common/src/utils/smart_leds_adapter_rgbw.rs @@ -0,0 +1,86 @@ +use core::{marker::PhantomData, slice::IterMut}; + +use smart_leds_trait::RGBA; + +use crate::{ + pulse_control::{ConfiguredChannel, OutputChannel, RepeatMode}, + utils::smart_leds_adapter::*, + OutputPin, +}; +pub type RGBA8 = RGBA; + +#[macro_export] +macro_rules! smartLedAdapterRGBW { + ($buffer_size: literal ) => { + SmartLedsAdapterRGBW::<_, _, { $buffer_size * 32 + 1 }> + }; +} + +pub struct SmartLedsAdapterRGBW { + channel: CHANNEL, + rmt_buffer: [u32; BUFFER_SIZE], + _pin: PhantomData, +} + +impl SmartLedsAdapterRGBW +where + CHANNEL: ConfiguredChannel, + PIN: OutputPin, +{ + pub fn new( + channel: UnconfiguredChannel, + pin: PIN, + ) -> SmartLedsAdapterRGBW + where + UnconfiguredChannel: OutputChannel, + { + Self { + channel: SmartLedsAdapter::::configure_channel(channel, pin), + rmt_buffer: [0; BUFFER_SIZE], + _pin: PhantomData, + } + } + + fn convert_rgbw_to_pulse( + value: RGBA8, + mut_iter: &mut IterMut, + ) -> Result<(), LedAdapterError> { + SmartLedsAdapter::::convert_rgb_channel_to_pulses( + value.g, mut_iter, + )?; + SmartLedsAdapter::::convert_rgb_channel_to_pulses( + value.r, mut_iter, + )?; + SmartLedsAdapter::::convert_rgb_channel_to_pulses( + value.b, mut_iter, + )?; + SmartLedsAdapter::::convert_rgb_channel_to_pulses( + value.a, mut_iter, + )?; + Ok(()) + } + + // this is a duplicate of the smart_leds_adaptor implementation, except for the + // convert_rgbw_to_pulse function + pub fn write(&mut self, iterator: T) -> Result<(), LedAdapterError> + where + T: Iterator, + { + let mut seq_iter = self.rmt_buffer.iter_mut(); + for item in iterator { + SmartLedsAdapterRGBW::::convert_rgbw_to_pulse( + item, + &mut seq_iter, + )?; + } + *seq_iter.next().ok_or(LedAdapterError::BufferSizeExceeded)? = 0; + + match self + .channel + .send_pulse_sequence_raw(RepeatMode::SingleShot, &self.rmt_buffer) + { + Ok(_) => Ok(()), + Err(x) => Err(LedAdapterError::TransmissionError(x)), + } + } +}