Skip to content

Commit

Permalink
Fade all Leds always (#26)
Browse files Browse the repository at this point in the history
* Add dial turn flash behavior and pulse interval setting

* Swap dial turn led indication to default on state

* Update to latest panel-protocol

* This is for Edward

* Add fade

* Fix fading

* Remove extra comments

* Update to latest 0.4

* Add full fading for all colors

* Slightly adjust fade constant for more of a trail

* Add dial turn flash behavior and pulse interval setting

* This is for Edward

* Add fade

* Update to latest 0.4

* Add full fading for all colors

* Slightly adjust fade constant for more of a trail

* Break out rgb, general cleanup, adjust constants

* Minor cleanup for dialturn logic

* Update fade constant and move it

* Cleanup naming and visibility

* Fix target_led_color naming

* One more naming fix

* One more naming fix again

Co-authored-by: Brian Schwind <[email protected]>
  • Loading branch information
efyang and bschwind authored Jul 16, 2021
1 parent 96c9faa commit 8554094
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 50 deletions.
58 changes: 27 additions & 31 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![no_main]
#![no_std]

use crate::rgb_led::LED_COUNT;
use crate::{rgb::Rgb, rgb_led::LED_COUNT};
use panel_protocol::PulseMode;
use panic_reset as _; // panic handler

Expand All @@ -11,7 +11,7 @@ use crate::{
button::{Active, Button, ButtonEvent, Debouncer},
counter::Counter,
overhead_light::OverheadLight,
rgb_led::{LedStrip, Pulser, Rgb},
rgb_led::{LedStrip, Pulser},
serial::{Command, Report, SerialProtocol},
};
use cortex_m_rt::entry;
Expand All @@ -32,10 +32,12 @@ mod bootload;
mod button;
mod counter;
mod overhead_light;
mod rgb;
mod rgb_led;
mod serial;

static mut USB_ENDPOINT_MEMORY: [u32; 1024] = [0; 1024];
const FADE_CONSTANT: f32 = 0.994;

#[entry]
fn main() -> ! {
Expand Down Expand Up @@ -122,7 +124,7 @@ fn main() -> ! {
let debounced_encoder_pin = Debouncer::new(button_pin, Active::Low, 30, 3000);
let mut encoder_button = Button::new(debounced_encoder_pin);

let mut led_color = (0u8, 30u8, 255u8);
let mut led_color = Rgb::new_from_u8(0, 30, 255);
let mut led_pulse = PulseMode::Solid;

// Set up USB communication.
Expand Down Expand Up @@ -165,8 +167,9 @@ fn main() -> ! {
// Turn the LED on to indicate we've powered up successfully.
led.set_low().unwrap();

let mut current_led = 0usize;
let mut led_intensities = [0.0; LED_COUNT];
let mut active_led_index = 0usize;
let mut current_led_colors = [Rgb::new_from_u8(0, 0, 0); LED_COUNT];
let mut target_led_colors = current_led_colors;

loop {
match encoder_button.poll() {
Expand All @@ -185,7 +188,7 @@ fn main() -> ! {
if !encoder_button.is_pressed() {
protocol.report(Report::DialValue { diff }).unwrap();

current_led = current_led.wrapping_add(diff as usize) % 4;
active_led_index = active_led_index.wrapping_add(diff as usize) % LED_COUNT;
}
}

Expand All @@ -203,7 +206,7 @@ fn main() -> ! {
_ => {},
},
Command::Led { r, g, b, pulse_mode } => {
led_color = (r, g, b);
led_color = Rgb::new_from_u8(r, g, b);
led_pulse = pulse_mode;
},
Command::Bootload => {
Expand All @@ -219,39 +222,32 @@ fn main() -> ! {
pulser.set_interval_ms(u16::from(interval_ms) as u32, &timer);
let intensity = pulser.intensity();

led_strip.set_all(Rgb::new(
(led_color.0 as f32 * intensity) as u8,
(led_color.1 as f32 * intensity) as u8,
(led_color.2 as f32 * intensity) as u8,
));
for target_led_color in target_led_colors.iter_mut() {
*target_led_color = led_color * intensity;
}
},
PulseMode::DialTurn => {
let mut new_led_intensities = [0.0; LED_COUNT];
new_led_intensities[current_led] = 1.0;
let mut leds = [Rgb::new(led_color.0, led_color.1, led_color.2); LED_COUNT];
for (led_intensity, new_led_intensity) in
led_intensities.iter_mut().zip(new_led_intensities.iter())
{
*led_intensity = 0.995 * *led_intensity + 0.005 * new_led_intensity;
}

for (mut led, intensity) in leds.iter_mut().zip(led_intensities.iter()) {
led.r = ((led.r as f32) * intensity) as u8;
led.g = ((led.g as f32) * intensity) as u8;
led.b = ((led.b as f32) * intensity) as u8;
for target_led_color in target_led_colors.iter_mut() {
*target_led_color = Rgb::new_from_u8(0, 0, 0);
}

led_strip.set_colors(&leds);
target_led_colors[active_led_index] = led_color;
},
PulseMode::Solid => {
let intensity = 1.0;

led_strip.set_all(Rgb::new(
(led_color.0 as f32 * intensity) as u8,
(led_color.1 as f32 * intensity) as u8,
(led_color.2 as f32 * intensity) as u8,
));
for target_led_color in target_led_colors.iter_mut() {
*target_led_color = led_color * intensity;
}
},
};

// Fade all leds toward the target led colors
for (current_led_color, target_led_color) in
current_led_colors.iter_mut().zip(target_led_colors.iter())
{
current_led_color.fade_towards(target_led_color, FADE_CONSTANT);
}
led_strip.set_colors(&current_led_colors);
}
}
53 changes: 53 additions & 0 deletions src/rgb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use core::ops::{Add, Mul};

#[derive(Copy, Clone)]
pub struct Rgb {
/// All in the range 0.0 - 255.0
/// Rounded when actually in use
r: f32,
g: f32,
b: f32,
}

impl Rgb {
pub fn new(r: f32, g: f32, b: f32) -> Self {
Self { r, g, b }
}

pub fn new_from_u8(r: u8, g: u8, b: u8) -> Self {
Self::new(r as f32, g as f32, b as f32)
}

/// Fade the current color toward the other one with a simple moving average
pub fn fade_towards(&mut self, other: &Self, fade_const: f32) {
*self = *self * fade_const + *other * (1.0 - fade_const);
}

pub fn r(&self) -> u8 {
self.r.clamp(0.0, 255.0) as u8
}

pub fn g(&self) -> u8 {
self.g.clamp(0.0, 255.0) as u8
}

pub fn b(&self) -> u8 {
self.b.clamp(0.0, 255.0) as u8
}
}

impl Mul<f32> for Rgb {
type Output = Rgb;

fn mul(self, rhs: f32) -> Self::Output {
Rgb::new(self.r * rhs, self.g * rhs, self.b * rhs)
}
}

impl Add<Rgb> for Rgb {
type Output = Rgb;

fn add(self, rhs: Rgb) -> Self::Output {
Rgb::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b)
}
}
28 changes: 9 additions & 19 deletions src/rgb_led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use embedded_hal::spi::FullDuplex;
use hal::timer::{Instant, MonoTimer};
use nb::block;

use crate::rgb::Rgb;

// Reference implementation:
// https://github.com/smart-leds-rs/ws2812-spi-rs/blob/fac281eb57b5f72c48e368682645e3b0bd5b4b83/src/lib.rs

Expand All @@ -14,31 +16,19 @@ pub struct LedStrip<F: FullDuplex<u8>> {
spi_bus: F,
}

#[derive(Copy, Clone)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}

impl Rgb {
pub fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
}

impl<F: FullDuplex<u8>> LedStrip<F> {
pub fn new(spi_bus: F) -> Self {
Self { spi_bus }
}

#[allow(unused)]
pub fn set_all(&mut self, rgb: Rgb) {
self.flush();

for _led in 0..LED_COUNT {
self.write_byte(rgb.g);
self.write_byte(rgb.r);
self.write_byte(rgb.b);
self.write_byte(rgb.g());
self.write_byte(rgb.r());
self.write_byte(rgb.b());
}

self.flush();
Expand All @@ -49,9 +39,9 @@ impl<F: FullDuplex<u8>> LedStrip<F> {
self.flush();

for led in rgb_data {
self.write_byte(led.g);
self.write_byte(led.r);
self.write_byte(led.b);
self.write_byte(led.g());
self.write_byte(led.r());
self.write_byte(led.b());
}

self.flush();
Expand Down

0 comments on commit 8554094

Please sign in to comment.