Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Support for RGBW leds #252

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions esp-hal-common/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
29 changes: 20 additions & 9 deletions esp-hal-common/src/utils/smart_leds_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,24 @@ where
{
/// Create a new adapter object that drives the pin using the RMT channel.
pub fn new<UnconfiguredChannel>(
mut channel: UnconfiguredChannel,
channel: UnconfiguredChannel,
pin: PIN,
) -> SmartLedsAdapter<CHANNEL, PIN, BUFFER_SIZE>
where
UnconfiguredChannel: OutputChannel<CHANNEL>,
{
Self {
channel: SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::configure_channel(channel, pin),
rmt_buffer: [0; BUFFER_SIZE],
_pin: PhantomData,
}
}

/// prepare channel for led signals
pub fn configure_channel<UnconfiguredChannel>(
mut channel: UnconfiguredChannel,
pin: PIN,
) -> CHANNEL
where
UnconfiguredChannel: OutputChannel<CHANNEL>,
{
Expand All @@ -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(
Expand All @@ -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<u32>,
) -> Result<(), LedAdapterError> {
Expand Down
86 changes: 86 additions & 0 deletions esp-hal-common/src/utils/smart_leds_adapter_rgbw.rs
Original file line number Diff line number Diff line change
@@ -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<u8>;

#[macro_export]
macro_rules! smartLedAdapterRGBW {
($buffer_size: literal ) => {
SmartLedsAdapterRGBW::<_, _, { $buffer_size * 32 + 1 }>
};
}

pub struct SmartLedsAdapterRGBW<CHANNEL, PIN, const BUFFER_SIZE: usize> {
channel: CHANNEL,
rmt_buffer: [u32; BUFFER_SIZE],
_pin: PhantomData<PIN>,
}

impl<CHANNEL, PIN, const BUFFER_SIZE: usize> SmartLedsAdapterRGBW<CHANNEL, PIN, BUFFER_SIZE>
where
CHANNEL: ConfiguredChannel,
PIN: OutputPin,
{
pub fn new<UnconfiguredChannel>(
channel: UnconfiguredChannel,
pin: PIN,
) -> SmartLedsAdapterRGBW<CHANNEL, PIN, BUFFER_SIZE>
where
UnconfiguredChannel: OutputChannel<CHANNEL>,
{
Self {
channel: SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::configure_channel(channel, pin),
rmt_buffer: [0; BUFFER_SIZE],
_pin: PhantomData,
}
}

fn convert_rgbw_to_pulse(
value: RGBA8,
mut_iter: &mut IterMut<u32>,
) -> Result<(), LedAdapterError> {
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
value.g, mut_iter,
)?;
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
value.r, mut_iter,
)?;
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
value.b, mut_iter,
)?;
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::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<T>(&mut self, iterator: T) -> Result<(), LedAdapterError>
where
T: Iterator<Item = RGBA8>,
{
let mut seq_iter = self.rmt_buffer.iter_mut();
for item in iterator {
SmartLedsAdapterRGBW::<CHANNEL, PIN, BUFFER_SIZE>::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)),
}
}
}