add background color for color wipe and my first unit test !
This commit is contained in:
		
							parent
							
								
									b718334392
								
							
						
					
					
						commit
						ee133379f2
					
				@ -2,21 +2,21 @@
 | 
				
			|||||||
    mac_addresses :
 | 
					    mac_addresses :
 | 
				
			||||||
      - C9:81:9C:BA:53:BC
 | 
					      - C9:81:9C:BA:53:BC
 | 
				
			||||||
    sequence:
 | 
					    sequence:
 | 
				
			||||||
      - pattern:
 | 
					#      - pattern:
 | 
				
			||||||
          type: Blink
 | 
					#          type: Blink
 | 
				
			||||||
          fade:
 | 
					#          fade:
 | 
				
			||||||
            current_iteration: 10
 | 
					#            current_iteration: 10
 | 
				
			||||||
            nbr_iterations: 20
 | 
					#            nbr_iterations: 20
 | 
				
			||||||
            begin_color: &black
 | 
					#            begin_color: &black
 | 
				
			||||||
              red: 0
 | 
					#              red: 0
 | 
				
			||||||
              green: 0
 | 
					#              green: 0
 | 
				
			||||||
              blue: 0
 | 
					#              blue: 0
 | 
				
			||||||
            end_color: &purple
 | 
					#            end_color: &purple
 | 
				
			||||||
              red: 255
 | 
					#              red: 255
 | 
				
			||||||
              green: 0
 | 
					#              green: 0
 | 
				
			||||||
              blue: 255
 | 
					#              blue: 255
 | 
				
			||||||
          max_iteration: 10
 | 
					#          max_iteration: 10
 | 
				
			||||||
        period: 50
 | 
					#        period: 50
 | 
				
			||||||
      - pattern:
 | 
					      - pattern:
 | 
				
			||||||
          type: Fade
 | 
					          type: Fade
 | 
				
			||||||
          nbr_iterations: 20
 | 
					          nbr_iterations: 20
 | 
				
			||||||
@ -36,7 +36,6 @@
 | 
				
			|||||||
            red: 0
 | 
					            red: 0
 | 
				
			||||||
            green: 255
 | 
					            green: 255
 | 
				
			||||||
            blue: 0
 | 
					            blue: 0
 | 
				
			||||||
          background_color: *purple
 | 
					 | 
				
			||||||
        period: 100
 | 
					        period: 100
 | 
				
			||||||
      - pattern:
 | 
					      - pattern:
 | 
				
			||||||
          type: FillRandom
 | 
					          type: FillRandom
 | 
				
			||||||
@ -45,17 +44,22 @@
 | 
				
			|||||||
        period: 80
 | 
					        period: 80
 | 
				
			||||||
  - name: titi
 | 
					  - name: titi
 | 
				
			||||||
    sequence:
 | 
					    sequence:
 | 
				
			||||||
      - pattern:
 | 
					#      - pattern:
 | 
				
			||||||
          type: Blink
 | 
					#          type: Blink
 | 
				
			||||||
          fade :
 | 
					#          fade :
 | 
				
			||||||
            nbr_iterations: 20
 | 
					#            nbr_iterations: 20
 | 
				
			||||||
            begin_color: *black
 | 
					#            begin_color: *black
 | 
				
			||||||
            end_color: &cyan
 | 
					#            end_color: &cyan
 | 
				
			||||||
                red: 0
 | 
					#                red: 0
 | 
				
			||||||
                green: 255
 | 
					#                green: 255
 | 
				
			||||||
                blue: 255
 | 
					#                blue: 255
 | 
				
			||||||
          max_iteration : 10
 | 
					#          max_iteration : 10
 | 
				
			||||||
        period: 50
 | 
					#        period: 50
 | 
				
			||||||
      - pattern:
 | 
					      - pattern:
 | 
				
			||||||
          type: Rainbow
 | 
					          type: Rainbow
 | 
				
			||||||
 | 
					          max_iteration: 200
 | 
				
			||||||
 | 
					        period: 10
 | 
				
			||||||
 | 
					      - pattern:
 | 
				
			||||||
 | 
					          type: ColorWipe
 | 
				
			||||||
 | 
					          color: *blue
 | 
				
			||||||
        period: 100
 | 
					        period: 100
 | 
				
			||||||
@ -5,6 +5,7 @@ mod rainbow;
 | 
				
			|||||||
mod fill_random;
 | 
					mod fill_random;
 | 
				
			||||||
mod fill_unstable;
 | 
					mod fill_unstable;
 | 
				
			||||||
mod blink;
 | 
					mod blink;
 | 
				
			||||||
 | 
					mod rain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use serde_derive::{Deserialize, Serialize};
 | 
					use serde_derive::{Deserialize, Serialize};
 | 
				
			||||||
use std::fmt;
 | 
					use std::fmt;
 | 
				
			||||||
@ -29,6 +30,12 @@ pub(crate) enum Patterns<const N: usize> {
 | 
				
			|||||||
    Blink(Blink<N>),
 | 
					    Blink(Blink<N>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait Pattern : Iterator {
 | 
				
			||||||
 | 
					    type Strip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for Patterns<N> {
 | 
					impl<const N: usize> Iterator for Patterns<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -45,6 +52,22 @@ impl<const N: usize> Iterator for Patterns<N> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for Patterns<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Patterns::Rainbow(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::Fade(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::ColorWipe(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::Scanner(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::FillRandom(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::FillUnstable(p) => p.init(),
 | 
				
			||||||
 | 
					            Patterns::Blink(p) => p.init(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// a struct for an RGB color
 | 
					/// a struct for an RGB color
 | 
				
			||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, Eq, Hash, PartialEq)]
 | 
					#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, Eq, Hash, PartialEq)]
 | 
				
			||||||
@ -84,17 +107,17 @@ impl SubAssign for PixelColor {
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// a basic newtype based on a fix array size.
 | 
					/// a basic newtype based on a fix array size.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
 | 
				
			||||||
pub struct Strip<const N: usize>([PixelColor; N]);
 | 
					pub struct Strip<const N: usize>([Option<PixelColor>; N]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Default for Strip<N> {
 | 
					impl<const N: usize> Default for Strip<N> {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        Strip([PixelColor::default(); N])
 | 
					        Strip([None; N])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Index<usize> for Strip<N> {
 | 
					impl<const N: usize> Index<usize> for Strip<N> {
 | 
				
			||||||
    type Output = PixelColor;
 | 
					    type Output = Option<PixelColor>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn index(&self, index: usize) -> &Self::Output {
 | 
					    fn index(&self, index: usize) -> &Self::Output {
 | 
				
			||||||
        &self.0[index]
 | 
					        &self.0[index]
 | 
				
			||||||
@ -102,7 +125,7 @@ impl<const N: usize> Index<usize> for Strip<N> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> IndexMut<usize> for Strip<N> {
 | 
					impl<const N: usize> IndexMut<usize> for Strip<N> {
 | 
				
			||||||
    fn index_mut(&mut self, index: usize) -> &mut PixelColor {
 | 
					    fn index_mut(&mut self, index: usize) -> &mut Option<PixelColor> {
 | 
				
			||||||
        &mut self.0[index]
 | 
					        &mut self.0[index]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -112,16 +135,17 @@ impl<const N: usize> Strip<N> {
 | 
				
			|||||||
        let mut data: Vec<u8> = vec![];
 | 
					        let mut data: Vec<u8> = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i in 0..N {
 | 
					        for i in 0..N {
 | 
				
			||||||
            data.append(&mut vec![self[i].green, self[i].red, self[i].blue]);
 | 
					            let color = self[i].unwrap_or(PixelColor::default());
 | 
				
			||||||
 | 
					            data.append(&mut vec![color.green, color.red, color.blue]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        data
 | 
					        data
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new(color: PixelColor) -> Strip<N> {
 | 
					    pub fn new(color: PixelColor) -> Strip<N> {
 | 
				
			||||||
        Strip { 0: [color; N] }
 | 
					        Strip { 0: [Some(color); N] }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn fill(&mut self, color: PixelColor) {
 | 
					    pub fn fill(&mut self, color: PixelColor) {
 | 
				
			||||||
        self.0.fill(color);
 | 
					        self.0.fill(Some(color));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
use crate::patterns::fade::Fade;
 | 
					use crate::patterns::fade::Fade;
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					use crate::patterns::Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// # Blink
 | 
					/// # Blink
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@ -13,6 +14,14 @@ pub struct Blink<const N: usize> {
 | 
				
			|||||||
    fade: Fade<N>,
 | 
					    fade: Fade<N>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for Blink<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for Blink<N> {
 | 
					impl<const N: usize> Iterator for Blink<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,6 +20,18 @@ pub struct ColorWipe<const N: usize> {
 | 
				
			|||||||
    pub(crate) background_color: Option<PixelColor>,
 | 
					    pub(crate) background_color: Option<PixelColor>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for ColorWipe<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        if let Some(color) = self.background_color {
 | 
				
			||||||
 | 
					            Some(Strip::<N>::new(color))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for ColorWipe<N> {
 | 
					impl<const N: usize> Iterator for ColorWipe<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,7 +48,7 @@ impl<const N: usize> Iterator for ColorWipe<N> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i in 0..iteration {
 | 
					        for i in 0..iteration {
 | 
				
			||||||
            strip[i] = self.color;
 | 
					            strip[i] = Some(self.color);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.current_iteration += 1;
 | 
					        self.current_iteration += 1;
 | 
				
			||||||
        Some(strip)
 | 
					        Some(strip)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,6 +17,14 @@ fn fade_value(value_start: u8, value_end: u8, index: usize, nbr_iter: usize) ->
 | 
				
			|||||||
    ((value_start as usize * (nbr_iter - index) + value_end as usize * index) / nbr_iter) as u8
 | 
					    ((value_start as usize * (nbr_iter - index) + value_end as usize * index) / nbr_iter) as u8
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for Fade<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for Fade<N> {
 | 
					impl<const N: usize> Iterator for Fade<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
use rand::Rng;
 | 
					use rand::Rng;
 | 
				
			||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,6 +13,14 @@ pub struct FillRandom<const N: usize> {
 | 
				
			|||||||
    pub(crate) max_iteration: Option<usize>,
 | 
					    pub(crate) max_iteration: Option<usize>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for FillRandom<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for FillRandom<N> {
 | 
					impl<const N: usize> Iterator for FillRandom<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -45,7 +53,7 @@ impl<const N: usize> Iterator for FillRandom<N> {
 | 
				
			|||||||
                blue = self.color.blue.saturating_sub(blue_delta);
 | 
					                blue = self.color.blue.saturating_sub(blue_delta);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            let c = PixelColor { red, green, blue };
 | 
					            let c = PixelColor { red, green, blue };
 | 
				
			||||||
            strip[i] = c;
 | 
					            strip[i] = Some(c);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Some(strip)
 | 
					        Some(strip)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
use rand::Rng;
 | 
					use rand::Rng;
 | 
				
			||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,6 +13,14 @@ pub struct FillUnstable<const N: usize> {
 | 
				
			|||||||
    pub(crate) max_iteration: Option<usize>,
 | 
					    pub(crate) max_iteration: Option<usize>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for FillUnstable<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for FillUnstable<N> {
 | 
					impl<const N: usize> Iterator for FillUnstable<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								src/patterns/rain.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/patterns/rain.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					use crate::patterns::PixelColor;
 | 
				
			||||||
 | 
					use crate::Strip;
 | 
				
			||||||
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// # scanner pattern
 | 
				
			||||||
 | 
					/// color one pixel with a color and leave a train of this color fading to black
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// # note
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// background_color work only for color not set by scanner pattern
 | 
				
			||||||
 | 
					#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)]
 | 
				
			||||||
 | 
					pub struct Scanner<const N: usize> {
 | 
				
			||||||
 | 
					    #[serde(default)]
 | 
				
			||||||
 | 
					    current_iteration: usize,
 | 
				
			||||||
 | 
					    pub(crate) color: PixelColor,
 | 
				
			||||||
 | 
					    pub(crate) background_color: Option<PixelColor>,
 | 
				
			||||||
 | 
					    pub(crate) stability: usize,
 | 
				
			||||||
 | 
					    #[serde(skip)]
 | 
				
			||||||
 | 
					    strip : Strip<N>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Iterator for Scanner<N> {
 | 
				
			||||||
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
 | 
					        let mut strip = Strip::<N>::default();
 | 
				
			||||||
 | 
					        if let Some(c) = self.background_color {
 | 
				
			||||||
 | 
					            strip.fill(c);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            strip.fill(PixelColor::default());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let current_led = self.current_iteration % N;
 | 
				
			||||||
 | 
					        let min_led;
 | 
				
			||||||
 | 
					        if current_led < 8 {
 | 
				
			||||||
 | 
					            min_led = 0;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            min_led = current_led - 8;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let mut c = self.color;
 | 
				
			||||||
 | 
					        for i in min_led..current_led {
 | 
				
			||||||
 | 
					            strip[i] = Some(c);
 | 
				
			||||||
 | 
					            c = c / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.current_iteration += 1;
 | 
				
			||||||
 | 
					        Some(strip)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,6 +20,14 @@ pub struct Rainbow<const N: usize> {
 | 
				
			|||||||
    pub(crate) step: Option<usize>,
 | 
					    pub(crate) step: Option<usize>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N: usize> Pattern for Rainbow<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for Rainbow<N> {
 | 
					impl<const N: usize> Iterator for Rainbow<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,7 +41,7 @@ impl<const N: usize> Iterator for Rainbow<N> {
 | 
				
			|||||||
        let step = self.step.unwrap_or(255 / N);
 | 
					        let step = self.step.unwrap_or(255 / N);
 | 
				
			||||||
        for i in 0..N {
 | 
					        for i in 0..N {
 | 
				
			||||||
            let pos = (i * step + self.current_iteration) as u8;
 | 
					            let pos = (i * step + self.current_iteration) as u8;
 | 
				
			||||||
            strip[i] = wheel(pos)
 | 
					            strip[i] = Some(wheel(pos))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.current_iteration += 1;
 | 
					        self.current_iteration += 1;
 | 
				
			||||||
        Some(strip)
 | 
					        Some(strip)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::patterns::PixelColor;
 | 
					use crate::patterns::{Pattern, PixelColor};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use serde::{Serialize, Deserialize};
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,6 +16,18 @@ pub struct Scanner<const N: usize> {
 | 
				
			|||||||
    pub(crate) background_color: Option<PixelColor>,
 | 
					    pub(crate) background_color: Option<PixelColor>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<const N:usize> Pattern for Scanner<N> {
 | 
				
			||||||
 | 
					    type Strip = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init(&self) -> Option<Self::Strip> {
 | 
				
			||||||
 | 
					        if let Some(color) = self.background_color {
 | 
				
			||||||
 | 
					            Some(Strip::<N>::new(color))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Iterator for Scanner<N> {
 | 
					impl<const N: usize> Iterator for Scanner<N> {
 | 
				
			||||||
    type Item = Strip<N>;
 | 
					    type Item = Strip<N>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,7 +48,7 @@ impl<const N: usize> Iterator for Scanner<N> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        let mut c = self.color;
 | 
					        let mut c = self.color;
 | 
				
			||||||
        for i in min_led..current_led {
 | 
					        for i in min_led..current_led {
 | 
				
			||||||
            strip[i] = c;
 | 
					            strip[i] = Some(c);
 | 
				
			||||||
            c = c / 2;
 | 
					            c = c / 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.current_iteration += 1;
 | 
					        self.current_iteration += 1;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
use crate::config::Config;
 | 
					use crate::config::Config;
 | 
				
			||||||
use crate::patterns::{Patterns, PixelColor};
 | 
					use crate::patterns::{Patterns, PixelColor, Pattern};
 | 
				
			||||||
use crate::Strip;
 | 
					use crate::Strip;
 | 
				
			||||||
use bluer::Address;
 | 
					use bluer::Address;
 | 
				
			||||||
use serde_derive::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
use std::future::Future;
 | 
					use std::future::Future;
 | 
				
			||||||
use std::str::FromStr;
 | 
					use std::str::FromStr;
 | 
				
			||||||
@ -41,27 +41,46 @@ pub struct Context<const N: usize> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub(crate) type DeviceSequence<const N: usize> = Vec<Context<N>>;
 | 
					pub(crate) type DeviceSequence<const N: usize> = Vec<Context<N>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn runner_loop<const N: usize>(runner: DeviceSequence<N>, tx: Sender<Strip<N>>) {
 | 
					pub async fn runner_loop<const N: usize>(runner: DeviceSequence<N>, tx: Sender<Strip<N>>) {
 | 
				
			||||||
 | 
					    let mut background = Strip::<N>::default();
 | 
				
			||||||
    for mut context in runner {
 | 
					    for mut context in runner {
 | 
				
			||||||
        let mut strip = context.pattern.next().unwrap();
 | 
					        let mut strip = context.pattern.init().unwrap_or(background);
 | 
				
			||||||
        let delay = context.period;
 | 
					        let delay = context.period;
 | 
				
			||||||
        while tx.send(strip).is_ok() {
 | 
					        while tx.send(strip).is_ok() {
 | 
				
			||||||
            if let Some(value) = context.pattern.next() {
 | 
					            if let Some(value) = context.pattern.next() {
 | 
				
			||||||
                strip = value;
 | 
					                strip = apply_mask(background, value);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            tokio::time::sleep(delay).await;
 | 
					            tokio::time::sleep(delay).await;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        background = strip;
 | 
				
			||||||
 | 
					        println!("{:?}", background);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn apply_mask<const N: usize>(previous_strip: Strip<N>, strip: Strip<{ N }>) -> Strip<N> {
 | 
				
			||||||
 | 
					    let mut new_strip = Strip::default();
 | 
				
			||||||
 | 
					    for i in 0..N {
 | 
				
			||||||
 | 
					        if let Some(color) = strip[i] {
 | 
				
			||||||
 | 
					            new_strip[i] = Some(color);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            new_strip[i] = previous_strip[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    new_strip
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct Spectacle<const N: usize> {
 | 
					pub struct Spectacle<const N: usize> {
 | 
				
			||||||
    runners: HashMap<DeviceSequence<N>, (Sender<Strip<N>>, Receiver<Strip<N>>)>,
 | 
					    runners: HashMap<DeviceSequence<N>, (Sender<Strip<N>>, Receiver<Strip<N>>)>,
 | 
				
			||||||
    channels: HashMap<Address, Receiver<Strip<N>>>,
 | 
					    channels: HashMap<Address, Receiver<Strip<N>>>,
 | 
				
			||||||
    default_runner: Option<(DeviceSequence<N>, Sender<Strip<N>>)>,
 | 
					    default_runner: Option<(DeviceSequence<N>, Sender<Strip<N>>)>,
 | 
				
			||||||
    default_receiver: Option<Receiver<Strip<N>>>,
 | 
					    default_receiver: Option<Receiver<Strip<N>>>,
 | 
				
			||||||
 | 
					    // #[serde(skip)]
 | 
				
			||||||
 | 
					    buffered_strip: Strip<N>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> Spectacle<N> {
 | 
					impl<const N: usize> Spectacle<N> {
 | 
				
			||||||
@ -134,6 +153,7 @@ impl<const N: usize> Spectacle<N> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        joinhandles
 | 
					        joinhandles
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<const N: usize> From<Config<N>> for Spectacle<N> {
 | 
					impl<const N: usize> From<Config<N>> for Spectacle<N> {
 | 
				
			||||||
@ -159,3 +179,35 @@ impl<const N: usize> From<Config<N>> for Spectacle<N> {
 | 
				
			|||||||
        spectacle
 | 
					        spectacle
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn apply_mask() {
 | 
				
			||||||
 | 
					        let pixel_entry = PixelColor {
 | 
				
			||||||
 | 
					            red: 10,
 | 
				
			||||||
 | 
					            green: 10,
 | 
				
			||||||
 | 
					            blue: 10
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let pixel_mask = PixelColor {
 | 
				
			||||||
 | 
					            red: 20,
 | 
				
			||||||
 | 
					            green: 20,
 | 
				
			||||||
 | 
					            blue: 20
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut entry = Strip::<5>::new(pixel_entry) ;
 | 
				
			||||||
 | 
					        entry[0] = None;
 | 
				
			||||||
 | 
					        entry[1] = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut mask = Strip::<5>::new(pixel_mask) ;
 | 
				
			||||||
 | 
					        mask[0] = None;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut expected = entry.clone();
 | 
				
			||||||
 | 
					        expected[1] = Some(pixel_mask);
 | 
				
			||||||
 | 
					        assert_eq!(expected, super::apply_mask(mask, entry));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user