From a2ab8ac8080dd731ef10f7295f3ca987d8965b57 Mon Sep 17 00:00:00 2001 From: Tobias Ollive Date: Mon, 21 Feb 2022 16:16:06 +0100 Subject: [PATCH] implement new patterns --- src/bluetooth.rs | 5 +-- src/main.rs | 73 ++++++++++++++++++++++---------- src/patterns.rs | 108 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 141 insertions(+), 45 deletions(-) diff --git a/src/bluetooth.rs b/src/bluetooth.rs index e7210b6..e098437 100644 --- a/src/bluetooth.rs +++ b/src/bluetooth.rs @@ -33,8 +33,7 @@ async fn bluetooth_scan(tx: mpsc::Sender, adapter: Adapter, uuid: Uuid) let mut already_scanned: HashSet
= HashSet::new(); pin_mut!(discover); while let Some(evt) = discover.next().await { - match evt { - AdapterEvent::DeviceAdded(addr) => { + if let AdapterEvent::DeviceAdded(addr) = evt { if already_scanned.contains(&addr) { continue; } @@ -50,8 +49,6 @@ async fn bluetooth_scan(tx: mpsc::Sender, adapter: Adapter, uuid: Uuid) Err(_) => continue, } } - _ => {} - } } Ok(()) } diff --git a/src/main.rs b/src/main.rs index 872c8f0..c07107f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,12 @@ mod bluetooth; mod patterns; -use crate::patterns::PixelColor; +use crate::patterns::{ColorWipe, Fade, PixelColor, Rainbow}; use bluer::gatt::remote::Characteristic; use patterns::Strip; use std::convert::TryFrom; use std::time::Duration; use tokio::sync::watch; -use tokio::sync::watch::error::SendError; const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8); const PIXEL_DATA_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0903c33242a893bd25e905756cb8); @@ -30,9 +29,9 @@ async fn main() -> bluer::Result<()> { }) } - let strip = Strip:: { - strip: <[PixelColor; 25]>::try_from(pixels).unwrap(), - }; + // let strip = Strip:: { + // strip: <[PixelColor; 25]>::try_from(pixels).unwrap(), + // }; let (tx, rx) = watch::channel(Strip::::default()); @@ -44,28 +43,58 @@ async fn main() -> bluer::Result<()> { tokio::spawn(async move { println!("device connected : {}", &device.address()); while rx_device.changed().await.is_ok() { - println!("ok"); - let strip = rx_device.borrow().clone(); + let strip = *rx_device.borrow(); write_strip(&strip, &char).await.unwrap(); } }); } } - loop { - match tx.send(strip) { - Ok(_) => {} - Err(_) => { - break; - } + + let mut colorwipe = ColorWipe::<25>{ + current_iteration: 0, + color: PixelColor { + red: 0, + green: 255, + blue: 0 + }, + infinite: true + }; + + + let mut fade = Fade::<25> { + current_iteration: 0, + nbr_iterations: 25, + begin_color: PixelColor { + red: 255, + green: 0, + blue: 0 + }, + end_color: PixelColor { + red: 0, + green: 0, + blue: 255 + }, + }; + + let mut pattern = Rainbow::<25>{ + current_iteration: 0, + max_iteration: None, + step: Some(10), + }; + + let mut strip = fade.next().unwrap(); + + while tx.send(strip).is_ok() { + if let Some(value) = fade.next() { + strip = value; + } else { + break; } - tokio::time::sleep(Duration::from_secs(1)).await; - match tx.send(Strip::::default()) { - Ok(_) => {} - Err(_) => { - break; - } - } - tokio::time::sleep(Duration::from_secs(1)).await; + tokio::time::sleep(Duration::from_millis(200)).await; + } + + while tx.send(pattern.next().unwrap()).is_ok() { + tokio::time::sleep(Duration::from_millis(10)).await; } Ok(()) } @@ -96,7 +125,7 @@ pub async fn write_strip( char: &Characteristic, ) -> bluer::Result<()> { let frame = [BASE_STRIP_DATA.to_vec(), data.to_array()].concat(); - print!("{:?}", frame); + // print!("{:?}", frame); char.write(&*frame).await?; Ok(()) } diff --git a/src/patterns.rs b/src/patterns.rs index 51bf5bc..159853b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,6 +1,6 @@ use std::fmt; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Default)] pub struct PixelColor { pub(crate) red: u8, pub(crate) green: u8, @@ -19,34 +19,28 @@ impl fmt::Display for PixelColor { } } -impl Default for PixelColor { - fn default() -> Self { - PixelColor { - red: 0, - green: 0, - blue: 0, - } - } -} - #[derive(Copy, Clone)] pub struct Strip { pub strip: [PixelColor; N], } impl Strip { - pub fn to_array(&self) -> Vec { + pub fn to_array(self) -> Vec { let mut data: Vec = vec![]; for i in 0..N { data.append(&mut vec![ - self.strip[i].red, self.strip[i].green, + self.strip[i].red, self.strip[i].blue, ]); } data } + + pub fn fill(&mut self, color: PixelColor) { + self.strip = [color; N]; + } } impl Default for Strip { @@ -57,12 +51,15 @@ impl Default for Strip { } } -pub struct RainbowPattern { +/// Rainbow pattern ///////////////////////////////////////////////// + +pub struct Rainbow { pub(crate) current_iteration: usize, pub(crate) max_iteration: Option, + pub(crate) step: Option, } -impl Iterator for RainbowPattern { +impl Iterator for Rainbow { type Item = Strip; fn next(&mut self) -> Option { @@ -72,12 +69,12 @@ impl Iterator for RainbowPattern { } } let mut strip = Strip::default(); - let step = 255 / N; + let step = self.step.unwrap_or( 255 / N ); for i in 0..N { let pos = (i * step + self.current_iteration) as u8; strip.strip[i] = wheel(pos) } - self.current_iteration = self.current_iteration + 1; + self.current_iteration += 1; Some(strip) } } @@ -100,11 +97,84 @@ fn wheel(index: u8) -> PixelColor { } _ => { let pos = pos - 170; - return PixelColor { + PixelColor { red: pos * 3, green: 255 - (pos * 3), blue: 0, - }; + } } } } + + +////////////////////////////////////////////////////////////////////////// +/// Colorwipe pattern //////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +pub struct ColorWipe { + pub(crate) current_iteration: usize, + pub (crate) color: PixelColor, + pub (crate) infinite: bool, +} + +impl Iterator for ColorWipe { + type Item = Strip; + + fn next(&mut self) -> Option { + let mut strip = Strip::default(); + if self.infinite { + self.current_iteration %= N; + } else if self.current_iteration >= N { + return None; + } + + + for i in 0..self.current_iteration { + strip.strip[i] = self.color; + } + self.current_iteration += 1; + Some(strip) + } +} + +////////////////////////////////////////////////////////////////////////// +/// fade pattern //////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +pub struct Fade { + pub(crate) current_iteration: usize, + pub(crate) nbr_iterations: usize, + pub(crate) begin_color: PixelColor, + pub(crate) end_color: PixelColor, +} + +fn fadeValue(value_start: u8, value_end: u8, index: usize, nbr_iter: usize) -> u8 { + ((value_start as usize * (nbr_iter - index) + value_end as usize * index )/ nbr_iter) as u8 +} + +impl Iterator for Fade { + type Item = Strip; + + fn next(&mut self) -> Option { + let mut strip = Strip::default(); + + if self.current_iteration >= self.nbr_iterations { + return None; + } + + let red = fadeValue(self.begin_color.red, self.end_color.red, self.current_iteration, self.nbr_iterations); + let green = fadeValue(self.begin_color.green, self.end_color.green, self.current_iteration, self.nbr_iterations); + let blue = fadeValue(self.begin_color.blue, self.end_color.blue, self.current_iteration, self.nbr_iterations); + + let current_color = PixelColor { + red, + green, + blue + }; + + strip.fill(current_color); + + self.current_iteration += 1; + Some(strip) + } +} \ No newline at end of file