Add exiting, settings, changing tick time
This commit is contained in:
parent
d4408ed005
commit
6c0a379aa7
12
src/main.rs
12
src/main.rs
@ -39,9 +39,17 @@ use ui::console_ui_loop;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let (tx, rx) = channel::<Message>();
|
let (tx, rx) = channel::<Message>();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut strip = LEDStrip::new(3);
|
let mut strip = LEDStrip::new(strip::Config {
|
||||||
|
// I have 89 right now, but start off with 20
|
||||||
|
num_lights: 20,
|
||||||
|
// Skip 14 lights
|
||||||
|
shift_lights: 14,
|
||||||
|
// Scaling factor (scale 0..255)
|
||||||
|
global_brightness_max: 20,
|
||||||
|
tick_time_ms: strip::DEFAULT_TICK_TIME_MS,
|
||||||
|
});
|
||||||
strip.strip_loop(&rx);
|
strip.strip_loop(&rx);
|
||||||
println!("Dead therad");
|
panic!("Dead strip thread. Terminating");
|
||||||
});
|
});
|
||||||
|
|
||||||
console_ui_loop(&tx);
|
console_ui_loop(&tx);
|
||||||
|
@ -190,13 +190,6 @@ impl Pattern for Collide {
|
|||||||
} else {
|
} else {
|
||||||
(self.left_color, self.right_color)
|
(self.left_color, self.right_color)
|
||||||
};
|
};
|
||||||
// let colors = match self.step {
|
|
||||||
// // If we are in the conjoined bounds region, these will be the same color
|
|
||||||
// // (self.conjoined_bounds.0)..=(self.conjoined_bounds.1) => (self.conjoined_color, self.conjoined_color),
|
|
||||||
// l..=r => (self.conjoined_color, self.conjoined_color),
|
|
||||||
// // If
|
|
||||||
// _ => (self.left_color, self.right_color),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Turn off the previous LED
|
// Turn off the previous LED
|
||||||
lights_buf[usize::from(self.previous_offset)] = color::BLACK;
|
lights_buf[usize::from(self.previous_offset)] = color::BLACK;
|
||||||
|
92
src/strip.rs
92
src/strip.rs
@ -1,53 +1,85 @@
|
|||||||
use crate::color::{self, RGB};
|
use crate::color::{self, RGB};
|
||||||
use crate::pattern::{self, Pattern};
|
use crate::pattern::{self, Pattern};
|
||||||
|
use std::cmp;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use std::process;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use ws2818_rgb_led_spi_driver::adapter_gen::WS28xxAdapter;
|
use ws2818_rgb_led_spi_driver::adapter_gen::WS28xxAdapter;
|
||||||
use ws2818_rgb_led_spi_driver::adapter_spi::WS28xxSpiAdapter;
|
use ws2818_rgb_led_spi_driver::adapter_spi::WS28xxSpiAdapter;
|
||||||
|
|
||||||
const MAX_NUM_LIGHTS: u16 = 32;
|
/// Maximum number of lights allowed
|
||||||
const TICK_TIME: u64 = 400;
|
const MAX_NUM_LIGHTS: u16 = 128;
|
||||||
|
/// Default time per tick
|
||||||
|
pub const DEFAULT_TICK_TIME_MS: u64 = 50;
|
||||||
|
/// Minimum time per tick before strip breaks
|
||||||
|
const MIN_TICK_TIME: u64 = 10;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
/// Number of lights
|
||||||
|
pub num_lights: u16,
|
||||||
|
/// Number of lights to skip
|
||||||
|
pub shift_lights: u16,
|
||||||
|
/// Global brightness multiplier
|
||||||
|
pub global_brightness_max: u8,
|
||||||
|
/// Time per tick
|
||||||
|
pub tick_time_ms: u64,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
ClearLights,
|
ClearLights,
|
||||||
ChangePattern(Box<dyn Pattern + Send>),
|
ChangePattern(Box<dyn Pattern + Send>),
|
||||||
SetNumLights(u16),
|
SetNumLights(u16),
|
||||||
|
SetTickTime(u64),
|
||||||
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::module_name_repetitions)]
|
#[allow(clippy::module_name_repetitions)]
|
||||||
pub struct LEDStrip {
|
pub struct LEDStrip {
|
||||||
pub adapter: Box<dyn WS28xxAdapter>,
|
pub adapter: Box<dyn WS28xxAdapter>,
|
||||||
pub num_lights: u16,
|
pub config: Config,
|
||||||
pub pattern: Box<dyn Pattern>,
|
pub pattern: Box<dyn Pattern>,
|
||||||
pub lights_buf: Vec<RGB>,
|
pub lights_buf: Vec<RGB>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LEDStrip {
|
impl LEDStrip {
|
||||||
pub fn new(num_lights: u16) -> Self {
|
pub fn new(config: Config) -> Self {
|
||||||
let adapter = Box::new(
|
let adapter = Box::new(
|
||||||
WS28xxSpiAdapter::new("/dev/spidev0.0").expect("Cannot locate device /dev/spidev0.0!"),
|
WS28xxSpiAdapter::new("/dev/spidev0.0").expect("Cannot locate device /dev/spidev0.0!"),
|
||||||
);
|
);
|
||||||
// let pattern = Pattern::default();
|
|
||||||
let pattern = Box::new(pattern::Solid::new(color::BLACK));
|
let pattern = Box::new(pattern::Solid::new(color::BLACK));
|
||||||
|
let num_lights = config.num_lights;
|
||||||
let lights_buf = vec![color::BLACK; num_lights.into()];
|
let lights_buf = vec![color::BLACK; num_lights.into()];
|
||||||
let mut ret = Self {
|
let mut ret = Self {
|
||||||
adapter,
|
adapter,
|
||||||
pattern,
|
pattern,
|
||||||
lights_buf,
|
lights_buf,
|
||||||
num_lights,
|
config,
|
||||||
};
|
};
|
||||||
ret.set_num_lights(num_lights);
|
ret.set_num_lights(num_lights);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_buf(&mut self) {
|
fn write_buf(&mut self) {
|
||||||
let data = self
|
let data = vec![color::BLACK]
|
||||||
.lights_buf
|
|
||||||
.as_slice()
|
|
||||||
.iter()
|
.iter()
|
||||||
.take(self.num_lights.into())
|
.cycle()
|
||||||
|
.take(self.config.shift_lights.into())
|
||||||
|
.chain(
|
||||||
|
self.lights_buf
|
||||||
|
.as_slice()
|
||||||
|
.iter()
|
||||||
|
.take(self.config.num_lights.into()),
|
||||||
|
)
|
||||||
.map(|c| c.to_tuple())
|
.map(|c| c.to_tuple())
|
||||||
|
.map(|(r, g, b)| {
|
||||||
|
(
|
||||||
|
cmp::min(r, self.config.global_brightness_max),
|
||||||
|
cmp::min(g, self.config.global_brightness_max),
|
||||||
|
cmp::min(b, self.config.global_brightness_max),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Vec<(u8, u8, u8)>>();
|
.collect::<Vec<(u8, u8, u8)>>();
|
||||||
self.adapter
|
self.adapter
|
||||||
.write_rgb(data.as_slice())
|
.write_rgb(data.as_slice())
|
||||||
@ -63,19 +95,23 @@ impl LEDStrip {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if self.pattern.init(&mut self.lights_buf, num_lights).is_ok() {
|
if self.pattern.init(&mut self.lights_buf, num_lights).is_ok() {
|
||||||
self.num_lights = num_lights;
|
self.config.num_lights = num_lights;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strip_loop(&mut self, rx: &Receiver<Message>) {
|
pub fn strip_loop(&mut self, rx: &Receiver<Message>) {
|
||||||
|
let mut exit = false;
|
||||||
loop {
|
loop {
|
||||||
let target_time = Instant::now().add(Duration::from_millis(TICK_TIME));
|
let target_time = Instant::now().add(Duration::from_millis(self.config.tick_time_ms));
|
||||||
|
|
||||||
if let Ok(message) = rx.try_recv() {
|
if let Ok(message) = rx.try_recv() {
|
||||||
match message {
|
match message {
|
||||||
Message::ClearLights => {
|
Message::ClearLights => {
|
||||||
let mut pat = Box::new(pattern::Solid::new(color::BLACK));
|
let mut pat = Box::new(pattern::Solid::new(color::BLACK));
|
||||||
if pat.init(&mut self.lights_buf, self.num_lights).is_ok() {
|
if pat
|
||||||
|
.init(&mut self.lights_buf, self.config.num_lights)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
self.pattern = pat;
|
self.pattern = pat;
|
||||||
} else {
|
} else {
|
||||||
println!("Clearing light strip: {:?}", pat);
|
println!("Clearing light strip: {:?}", pat);
|
||||||
@ -83,7 +119,10 @@ impl LEDStrip {
|
|||||||
}
|
}
|
||||||
Message::ChangePattern(pat) => {
|
Message::ChangePattern(pat) => {
|
||||||
let mut pat = pat;
|
let mut pat = pat;
|
||||||
if pat.init(&mut self.lights_buf, self.num_lights).is_ok() {
|
if pat
|
||||||
|
.init(&mut self.lights_buf, self.config.num_lights)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
self.pattern = pat;
|
self.pattern = pat;
|
||||||
} else {
|
} else {
|
||||||
println!("Error with pattern: {:?}", pat);
|
println!("Error with pattern: {:?}", pat);
|
||||||
@ -92,6 +131,24 @@ impl LEDStrip {
|
|||||||
Message::SetNumLights(num_lights) => {
|
Message::SetNumLights(num_lights) => {
|
||||||
self.set_num_lights(num_lights);
|
self.set_num_lights(num_lights);
|
||||||
}
|
}
|
||||||
|
Message::SetTickTime(tick_time_ms) => {
|
||||||
|
if tick_time_ms < MIN_TICK_TIME {
|
||||||
|
println!("Error with tick time: {}", tick_time_ms);
|
||||||
|
}
|
||||||
|
self.config.tick_time_ms = tick_time_ms;
|
||||||
|
}
|
||||||
|
Message::Quit => {
|
||||||
|
exit = true;
|
||||||
|
let mut pat = pattern::Solid::new(color::BLACK);
|
||||||
|
if pat
|
||||||
|
.init(&mut self.lights_buf, self.config.num_lights)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
self.pattern = Box::new(pat);
|
||||||
|
} else {
|
||||||
|
println!("Could not construct clear pattern");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,12 +156,15 @@ impl LEDStrip {
|
|||||||
self.write_buf();
|
self.write_buf();
|
||||||
}
|
}
|
||||||
|
|
||||||
// let mut num_iter = 0;
|
if exit {
|
||||||
|
println!("Exiting as requested");
|
||||||
|
process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if Instant::now() >= target_time {
|
if Instant::now() >= target_time {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// num_iter += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,14 +73,19 @@ fn parse_cmd(tx: &Sender<strip::Message>, s: &str) -> Result<(), String> {
|
|||||||
["x"] => tx
|
["x"] => tx
|
||||||
.send(strip::Message::ClearLights)
|
.send(strip::Message::ClearLights)
|
||||||
.map_err(|e| e.to_string()),
|
.map_err(|e| e.to_string()),
|
||||||
["q"] => Ok(()),
|
["q"] => tx.send(strip::Message::Quit).map_err(|e| e.to_string()),
|
||||||
["s", n] => tx
|
["s", n] => tx
|
||||||
.send(strip::Message::SetNumLights(
|
.send(strip::Message::SetNumLights(
|
||||||
n.parse::<u16>()
|
n.parse::<u16>()
|
||||||
.map_err(|_| String::from("Could not parse light count"))?,
|
.map_err(|_| String::from("Could not parse light count"))?,
|
||||||
))
|
))
|
||||||
.map_err(|e| e.to_string()),
|
.map_err(|e| e.to_string()),
|
||||||
_ => Err(String::from("Unknown command. Available commands: solidColor movingRainbow Bouncing Fade clear(X) Setnumlights")),
|
["t", n] => tx.send(strip::Message::SetTickTime(
|
||||||
|
n.parse::<u64>()
|
||||||
|
.map_err(|_| String::from("Could not parse light count"))?,
|
||||||
|
))
|
||||||
|
.map_err(|e| e.to_string()),
|
||||||
|
_ => Err(String::from("Unknown command. Available commands: solidColor movingRainbow Bouncing Fade clear(X) Setnumlights setTicktime")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user