mirror of
https://github.com/FliegendeWurst/raspi-oled.git
synced 2024-11-25 03:34:58 +00:00
Expiration system
This commit is contained in:
parent
ca73b6545a
commit
13c5a472ce
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1934,6 +1934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
@ -1956,9 +1957,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-tz"
|
||||
version = "1.0.3"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a422f65dfdf08a81317d54fa00b45dc58cbccab69be78c1447391cc39ae8c9d4"
|
||||
checksum = "733bc522e97980eb421cbf381160ff225bd14262a48a739110f6653c6258d625"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"parse-zoneinfo",
|
||||
@ -1967,6 +1968,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde-xml-rs",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -13,7 +13,7 @@ embedded-hal = "0.2.5"
|
||||
libc = "0.2.98"
|
||||
rusqlite = "0.27.0"
|
||||
time = { version = "0.3.9", features = ["parsing"] }
|
||||
time-tz = "1.0.1"
|
||||
time-tz = "2"
|
||||
image = { version = "0.24.1", optional = true }
|
||||
serde_json = "1.0.79"
|
||||
serde_derive = "1.0.136"
|
||||
|
@ -16,7 +16,7 @@ rustPlatform.buildRustPackage {
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
||||
cargoBuildFlags = [ "--no-default-features" ];
|
||||
cargoBuildFlags = [ "--no-default-features" "--bin" "main_loop" ];
|
||||
|
||||
buildInputs = [ sqlite ];
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![feature(array_windows)]
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
thread,
|
||||
@ -67,7 +69,21 @@ impl<D: DrawTarget<Color = Rgb565>> ContextDefault<D> {
|
||||
return false;
|
||||
}
|
||||
let a = active.last().unwrap();
|
||||
a.draw(disp, rng).unwrap_or(true)
|
||||
if !a.expired() {
|
||||
return a.draw(disp, rng).unwrap_or(true);
|
||||
}
|
||||
drop(active);
|
||||
self.active.borrow_mut().pop();
|
||||
self.loop_iter(disp, rng)
|
||||
}
|
||||
|
||||
fn pop_action_and_clear(&mut self, disp: &mut D) -> Result<(), D::Error> {
|
||||
let active = self.active.get_mut();
|
||||
if active.len() > 1 {
|
||||
active.pop();
|
||||
disp.clear(BLACK)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,8 +94,10 @@ impl<D: DrawTarget<Color = Rgb565>> Context for ContextDefault<D> {
|
||||
for s in &self.screensavers {
|
||||
if s.id() == id {
|
||||
self.active.borrow_mut().push(s.convert_draw());
|
||||
return;
|
||||
}
|
||||
}
|
||||
println!("warning: screensaver not found");
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -90,7 +108,7 @@ fn pc_main() {}
|
||||
|
||||
#[cfg(feature = "pc")]
|
||||
fn pc_main() {
|
||||
use std::num::NonZeroU32;
|
||||
use std::{env, num::NonZeroU32};
|
||||
|
||||
use winit::{
|
||||
dpi::LogicalSize,
|
||||
@ -102,6 +120,16 @@ fn pc_main() {
|
||||
use crate::screensaver::{Screensaver, DUOLINGO};
|
||||
use raspi_oled::FrameOutput;
|
||||
|
||||
let args: Vec<_> = env::args().map(|x| x.to_string()).collect();
|
||||
for [key, val] in args.array_windows() {
|
||||
match key.as_str() {
|
||||
"--speed" => {
|
||||
screensaver::SPEED.store(val.parse().unwrap(), std::sync::atomic::Ordering::Relaxed);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new()
|
||||
.with_inner_size(LogicalSize::new(128, 128))
|
||||
@ -116,6 +144,7 @@ fn pc_main() {
|
||||
let mut buffer_dirty = true;
|
||||
|
||||
let mut ctx = ContextDefault::new();
|
||||
ctx.do_action(Action::Screensaver("plate"));
|
||||
let mut rng = Xoroshiro128StarStar::seed_from_u64(17381);
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
@ -156,81 +185,9 @@ fn pc_main() {
|
||||
.unwrap();
|
||||
|
||||
// redraw
|
||||
if Instant::now().duration_since(start) > Duration::from_millis(iters * 1000) {
|
||||
if Instant::now().duration_since(start) > Duration::from_millis(iters * 66) {
|
||||
iters += 1;
|
||||
buffer_dirty = ctx.loop_iter(&mut disp, &mut rng);
|
||||
//loop_iter(&mut disp).unwrap();
|
||||
/*
|
||||
let mut time = OffsetDateTime::now_utc().to_timezone(BERLIN);
|
||||
//time += Duration::new(iters * 60, 0);
|
||||
disp.clear(Rgb565::new(0, 0, 0)).unwrap();
|
||||
display_clock(&mut disp, &time).unwrap();
|
||||
*/
|
||||
//DUOLINGO.draw(&mut disp, &mut rng).unwrap();
|
||||
/*
|
||||
let iters = iters % 300;
|
||||
let (s, c) = (iters as f32 * 0.1).sin_cos();
|
||||
let (mut x, mut y) = (s * iters as f32 * 0.005, c * iters as f32 * 0.005);
|
||||
x *= 64.;
|
||||
y *= 64.;
|
||||
x += 64.;
|
||||
y += 64.;
|
||||
let variation = iters as u32 / 16 + 1;
|
||||
for _ in 0..16 {
|
||||
let dx = (rng.next_u32() % variation) as i32 - variation as i32 / 2;
|
||||
let dy = (rng.next_u32() % variation) as i32 - variation as i32 / 2;
|
||||
let color = rng.next_u32();
|
||||
let p = Rectangle::new(Point::new(x as i32 + dx, y as i32 + dy), Size::new(1, 1));
|
||||
let s = PrimitiveStyleBuilder::new()
|
||||
.fill_color(Rgb565::new(
|
||||
color as u8 & 0b11111,
|
||||
((color >> 8) & 0b111111) as u8,
|
||||
((color >> 16) & 0b111111) as u8,
|
||||
))
|
||||
.build();
|
||||
p.draw_styled(&s, &mut disp).unwrap();
|
||||
}
|
||||
if iters % 300 == 0 {
|
||||
disp.clear(Rgb565::new(0, 0, 0)).unwrap();
|
||||
}
|
||||
*/
|
||||
/*
|
||||
for _ in 0..16 {
|
||||
let x = (rng.next_u32() % 128) as usize;
|
||||
let y = (rng.next_u32() % 128) as usize;
|
||||
let dx = (rng.next_u32() % 8) as i32 - 4;
|
||||
let dy = (rng.next_u32() % 8) as i32 - 4;
|
||||
let red = STAR[y * 128 * 3 + x * 3];
|
||||
let green = STAR[y * 128 * 3 + x * 3 + 1];
|
||||
if red == 0xff {
|
||||
let color = rng.next_u32();
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
// star
|
||||
r = (color as u8 & 0b11111).saturating_mul(2);
|
||||
g = (((color >> 8) & 0b111111) as u8).saturating_mul(2);
|
||||
b = ((color >> 16) & 0b111111) as u8 / 3;
|
||||
// rpi
|
||||
/*
|
||||
if red > green {
|
||||
r = (color as u8 & 0b11111).saturating_mul(2);
|
||||
g = ((color >> 8) & 0b111111) as u8 / 3;
|
||||
b = ((color >> 16) & 0b111111) as u8 / 3;
|
||||
} else {
|
||||
r = (color as u8 & 0b11111) / 2;
|
||||
g = (((color >> 8) & 0b111111) as u8).saturating_mul(2);
|
||||
b = ((color >> 16) & 0b111111) as u8 / 3;
|
||||
}
|
||||
*/
|
||||
let p = Rectangle::new(Point::new(x as i32 + dx, y as i32 + dy), Size::new(1, 1));
|
||||
let s = PrimitiveStyleBuilder::new()
|
||||
.fill_color(Rgb565::new(r as u8, g as u8, b as u8))
|
||||
.build();
|
||||
p.draw_styled(&s, &mut disp).unwrap();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
let mut buffer = surface.buffer_mut().unwrap();
|
||||
@ -256,6 +213,9 @@ fn pc_main() {
|
||||
|
||||
pub trait Draw<D: DrawTarget<Color = Rgb565>> {
|
||||
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error>;
|
||||
fn expired(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn rpi_main() {
|
||||
@ -318,7 +278,6 @@ fn main_loop(mut disp: Oled) {
|
||||
},
|
||||
6 => {
|
||||
menu.push(2);
|
||||
ctx.do_action(Action::Screensaver("rpi"));
|
||||
},
|
||||
5 => {
|
||||
menu.push(3);
|
||||
@ -327,6 +286,15 @@ fn main_loop(mut disp: Oled) {
|
||||
println!("unknown offset: {}", e.offset);
|
||||
},
|
||||
}
|
||||
match &*menu {
|
||||
[2] => {
|
||||
let _ = ctx.pop_action_and_clear(&mut disp);
|
||||
},
|
||||
[3] => {
|
||||
ctx.do_action(Action::Screensaver("rpi"));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
//println!("menu: {menu:?}");
|
||||
}
|
||||
// clean up stale menu selection
|
||||
@ -338,6 +306,6 @@ fn main_loop(mut disp: Oled) {
|
||||
if dirty {
|
||||
let _ = disp.flush(); // ignore bus write errors, they are harmless
|
||||
}
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
thread::sleep(Duration::from_millis(66));
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ impl Reminder {
|
||||
|
||||
static DUOLINGO: Reminder = Reminder::new(11, 30, Action::Screensaver("duolingo"));
|
||||
static DUOLINGO_NIGHT: Reminder = Reminder::new(23, 30, Action::Screensaver("duolingo"));
|
||||
static FOOD: Reminder = Reminder::new(13, 15, Action::Screensaver("plate"));
|
||||
|
||||
pub fn reminders() -> Vec<Box<dyn Schedule>> {
|
||||
vec![Box::new(DUOLINGO), Box::new(DUOLINGO_NIGHT)]
|
||||
vec![Box::new(DUOLINGO), Box::new(DUOLINGO_NIGHT), Box::new(FOOD)]
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64};
|
||||
|
||||
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
||||
use embedded_graphics::{
|
||||
@ -15,15 +16,28 @@ use time_tz::{timezones::db::europe::BERLIN, OffsetDateTimeExt};
|
||||
|
||||
use crate::{Draw, Rng};
|
||||
|
||||
pub static SPEED: AtomicU64 = AtomicU64::new(32);
|
||||
|
||||
pub trait Screensaver<D: DrawTarget<Color = Rgb565>>: Draw<D> {
|
||||
fn id(&self) -> &'static str;
|
||||
fn convert_draw(&self) -> Box<dyn Draw<D>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug)]
|
||||
pub struct SimpleScreensaver {
|
||||
id: &'static str,
|
||||
data: &'static [u8],
|
||||
iters: AtomicU32,
|
||||
}
|
||||
|
||||
impl Clone for SimpleScreensaver {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
id: self.id,
|
||||
data: self.data,
|
||||
iters: AtomicU32::new(self.iters.load(std::sync::atomic::Ordering::Relaxed)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DrawTarget<Color = Rgb565>> Screensaver<D> for SimpleScreensaver {
|
||||
@ -32,13 +46,13 @@ impl<D: DrawTarget<Color = Rgb565>> Screensaver<D> for SimpleScreensaver {
|
||||
}
|
||||
|
||||
fn convert_draw(&self) -> Box<dyn Draw<D>> {
|
||||
Box::new(*self)
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DrawTarget<Color = Rgb565>> Draw<D> for SimpleScreensaver {
|
||||
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error> {
|
||||
for _ in 0..512 {
|
||||
for _ in 0..SPEED.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
let x = (rng.next_u32() % 128) as usize;
|
||||
let y = (rng.next_u32() % 128) as usize;
|
||||
let dx = (rng.next_u32() % 8) as i32 - 4;
|
||||
@ -59,8 +73,13 @@ impl<D: DrawTarget<Color = Rgb565>> Draw<D> for SimpleScreensaver {
|
||||
p.draw_styled(&s, disp)?;
|
||||
}
|
||||
}
|
||||
self.iters.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn expired(&self) -> bool {
|
||||
self.iters.load(std::sync::atomic::Ordering::Relaxed) > 1000
|
||||
}
|
||||
}
|
||||
|
||||
impl SimpleScreensaver {
|
||||
@ -68,7 +87,11 @@ impl SimpleScreensaver {
|
||||
if data.len() != 128 * 128 * 3 {
|
||||
panic!("invalid screensaver size");
|
||||
}
|
||||
SimpleScreensaver { id, data }
|
||||
SimpleScreensaver {
|
||||
id,
|
||||
data,
|
||||
iters: AtomicU32::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +163,15 @@ impl<D: DrawTarget<Color = Rgb565>> Draw<D> for TimeDisplay {
|
||||
pub static STAR: SimpleScreensaver = SimpleScreensaver::new("star", include_bytes!("./star.raw"));
|
||||
pub static RPI: SimpleScreensaver = SimpleScreensaver::new("rpi", include_bytes!("./rpi.raw"));
|
||||
pub static DUOLINGO: SimpleScreensaver = SimpleScreensaver::new("duolingo", include_bytes!("./duolingo.raw"));
|
||||
pub static SPAGHETTI: SimpleScreensaver = SimpleScreensaver::new("spaghetti", include_bytes!("./spaghetti.raw"));
|
||||
pub static PLATE: SimpleScreensaver = SimpleScreensaver::new("plate", include_bytes!("./plate.raw"));
|
||||
|
||||
pub fn screensavers<D: DrawTarget<Color = Rgb565>>() -> Vec<Box<dyn Screensaver<D>>> {
|
||||
vec![Box::new(STAR), Box::new(RPI), Box::new(DUOLINGO)]
|
||||
vec![
|
||||
Box::new(STAR.clone()),
|
||||
Box::new(RPI.clone()),
|
||||
Box::new(DUOLINGO.clone()),
|
||||
Box::new(SPAGHETTI.clone()),
|
||||
Box::new(PLATE.clone()),
|
||||
]
|
||||
}
|
||||
|
BIN
src/bin/screensaver/plate.raw
Normal file
BIN
src/bin/screensaver/plate.raw
Normal file
Binary file not shown.
BIN
src/bin/screensaver/spaghetti.raw
Normal file
BIN
src/bin/screensaver/spaghetti.raw
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user