diff --git a/src/lib8.rs b/src/lib8.rs new file mode 100644 index 0000000..222e99a --- /dev/null +++ b/src/lib8.rs @@ -0,0 +1,44 @@ +use palette::convert::{IntoColor, IntoColorUnclamped, FromColorUnclamped}; +use palette::encoding::srgb::Srgb; +use palette::Hsv; + +#[derive(PartialEq, Debug)] +pub struct RGB8 { + pub red: u8, + pub green: u8, + pub blue: u8 +} + +impl RGB8 { + fn new(red : u8, green : u8, blue : u8) -> Self { + Self { + red: red, + green: green, + blue: blue + } + } +} + +impl FromColorUnclamped> for RGB8 { + fn from_color_unclamped(hsv: Hsv) -> RGB8 { + if hsv.saturation == 0 { + return RGB8::new(hsv.value, hsv.value, hsv.value); + } + + let region = hsv.hue.into_inner() / 43; + let remainder = (hsv.hue.into_inner() - (region * 43)) * 6; + + let p = (hsv.value.wrapping_mul(255 - hsv.saturation).wrapping_shr(8)); + let q = (hsv.value.wrapping_mul(255 - ((hsv.saturation.wrapping_mul(remainder)).wrapping_shr(8)))).wrapping_shr(8); + let t = (hsv.value.wrapping_mul(255 - ((hsv.saturation.wrapping_mul(255 - remainder)).wrapping_shr(8)))).wrapping_shr(8); + + match region { + 0 => RGB8::new(hsv.value, t, p), + 1 => RGB8::new(q, hsv.value, p), + 2 => RGB8::new(p, hsv.value, t), + 3 => RGB8::new(p, q, hsv.value), + 4 => RGB8::new(t, p, hsv.value), + _ => RGB8::new(hsv.value, p, q) + } + } +} diff --git a/src/main.rs b/src/main.rs index ddee6d9..74114d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,75 +3,15 @@ use esp_idf_svc::hal::prelude::Peripherals; use ws2812_esp32_rmt_driver::lib_embedded_graphics::{LedPixelStrip, Ws2812DrawTarget}; use embedded_graphics::{ prelude::*, - pixelcolor::{Rgb888, RgbColor}, + pixelcolor::Rgb888, }; -use std::thread::sleep; -use std::time::Duration; -use palette::{Hsv, Srgb}; -use palette::convert::{IntoColor, IntoColorUnclamped, FromColorUnclamped}; +use palette::Hsv; +use palette::convert::IntoColorUnclamped; -fn colorToMW(color : impl RgbColor) -> u32 { - const gRed_mW : u32 = 16 * 5; //< 16mA @ 5v = 80mW - const gGreen_mW : u32 = 11 * 5; //< 11mA @ 5v = 55mW - const gBlue_mW : u32 = 15 * 5; //< 15mA @ 5v = 75mW - const gDark_mW : u32 = 1 * 5; //< 1mA @ 5v = 5mW - let redMW = (color.r() as u32 * gRed_mW).wrapping_shr(8); - let greenMW = (color.g() as u32 * gGreen_mW).wrapping_shr(8); - let blueMW = (color.b() as u32 * gBlue_mW).wrapping_shr(8); +mod power; +mod lib8; - return redMW + greenMW + blueMW + gDark_mW; -} - -fn brightnessForMW(totalMW : u32, target : u8, maxPower: u32) -> u8 { - let target32 = target as u32; - let requestedMW = (totalMW * target32) / 256; - if requestedMW > maxPower { - return ((target32 * maxPower) / requestedMW).try_into().unwrap(); - } - return target; -} - -#[derive(PartialEq, Debug)] -struct RGB8 { - red: u8, - green: u8, - blue: u8 -} - -impl RGB8 { - fn new(red : u8, green : u8, blue : u8) -> Self { - Self { - red: red, - green: green, - blue: blue - } - } -} - -impl FromColorUnclamped> for RGB8 { - fn from_color_unclamped(hsv: Hsv) -> RGB8 { - if hsv.saturation == 0 { - return RGB8::new(hsv.value, hsv.value, hsv.value); - } - - let region = hsv.hue.into_inner() / 43; - let remainder = (hsv.hue.into_inner() - (region * 43)) * 6; - - let p = (hsv.value.wrapping_mul(255 - hsv.saturation).wrapping_shr(8)); - let q = (hsv.value.wrapping_mul(255 - ((hsv.saturation.wrapping_mul(remainder)).wrapping_shr(8)))).wrapping_shr(8); - let t = (hsv.value.wrapping_mul(255 - ((hsv.saturation.wrapping_mul(255 - remainder)).wrapping_shr(8)))).wrapping_shr(8); - - match region { - 0 => RGB8::new(hsv.value, t, p), - 1 => RGB8::new(q, hsv.value, p), - 2 => RGB8::new(p, hsv.value, t), - 3 => RGB8::new(p, q, hsv.value), - 4 => RGB8::new(t, p, hsv.value), - _ => RGB8::new(hsv.value, p, q) - } - } -} fn main() { // It is necessary to call this function once. Otherwise some patches to the runtime @@ -87,8 +27,10 @@ fn main() { let led_pin = peripherals.pins.gpio14; let channel = peripherals.rmt.channel0; - const NUM_PIXELS : usize = 255; - const MAX_POWER_MW : u32 = 1000; + const NUM_PIXELS : usize = 300; + const POWER_VOLTS : u32 = 5; + const POWER_MA : u32 = 500; + const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; let mut draw = Ws2812DrawTarget::>::new(channel, led_pin).unwrap(); let mut hue : u8 = 0; @@ -98,16 +40,14 @@ fn main() { let mut totalMW = 0; draw.clear(Rgb888::BLACK); for i in 0..length { - //let color = HSV::new(hue.wrapping_add(i as u8), 255, 255); let hsvColor = Hsv::new_srgb(hue.wrapping_add(i as u8), 255, 255); - let rgbColor : RGB8 = hsvColor.into_color_unclamped(); - //let rgbColor : Srgb = hsvColor.into_color(); + let rgbColor : lib8::RGB8 = hsvColor.into_color_unclamped(); let color = Rgb888::new(rgbColor.red, rgbColor.green, rgbColor.blue); - totalMW += colorToMW(color); + totalMW += power::colorToMW(color); Pixel(Point::new(i as i32, 0), color).draw(&mut draw).unwrap(); } - let brightness = brightnessForMW(totalMW, 255, MAX_POWER_MW); + let brightness = power::brightnessForMW(totalMW, 255, MAX_POWER_MW); draw.set_brightness(brightness); draw.flush().unwrap(); log::info!("Frame hue={} power={} brightness={}", hue, totalMW, brightness); diff --git a/src/power.rs b/src/power.rs new file mode 100644 index 0000000..3e2d2bf --- /dev/null +++ b/src/power.rs @@ -0,0 +1,23 @@ +use embedded_graphics::pixelcolor::RgbColor; + +pub fn colorToMW(color : impl RgbColor) -> u32 { + const gRed_mW : u32 = 16 * 5; //< 16mA @ 5v = 80mW + const gGreen_mW : u32 = 11 * 5; //< 11mA @ 5v = 55mW + const gBlue_mW : u32 = 15 * 5; //< 15mA @ 5v = 75mW + const gDark_mW : u32 = 1 * 5; //< 1mA @ 5v = 5mW + + let redMW = (color.r() as u32 * gRed_mW).wrapping_shr(8); + let greenMW = (color.g() as u32 * gGreen_mW).wrapping_shr(8); + let blueMW = (color.b() as u32 * gBlue_mW).wrapping_shr(8); + + return redMW + greenMW + blueMW + gDark_mW; +} + +pub fn brightnessForMW(totalMW : u32, target : u8, maxPower: u32) -> u8 { + let target32 = target as u32; + let requestedMW = (totalMW * target32) / 256; + if requestedMW > maxPower { + return ((target32 * maxPower) / requestedMW).try_into().unwrap(); + } + return target; +}