mirror of
https://github.com/FliegendeWurst/raspi-oled.git
synced 2024-11-09 13:40:36 +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"
|
checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
|
"js-sys",
|
||||||
"serde",
|
"serde",
|
||||||
"time-core",
|
"time-core",
|
||||||
"time-macros",
|
"time-macros",
|
||||||
@ -1956,9 +1957,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-tz"
|
name = "time-tz"
|
||||||
version = "1.0.3"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a422f65dfdf08a81317d54fa00b45dc58cbccab69be78c1447391cc39ae8c9d4"
|
checksum = "733bc522e97980eb421cbf381160ff225bd14262a48a739110f6653c6258d625"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"parse-zoneinfo",
|
"parse-zoneinfo",
|
||||||
@ -1967,6 +1968,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde-xml-rs",
|
"serde-xml-rs",
|
||||||
"time",
|
"time",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -13,7 +13,7 @@ embedded-hal = "0.2.5"
|
|||||||
libc = "0.2.98"
|
libc = "0.2.98"
|
||||||
rusqlite = "0.27.0"
|
rusqlite = "0.27.0"
|
||||||
time = { version = "0.3.9", features = ["parsing"] }
|
time = { version = "0.3.9", features = ["parsing"] }
|
||||||
time-tz = "1.0.1"
|
time-tz = "2"
|
||||||
image = { version = "0.24.1", optional = true }
|
image = { version = "0.24.1", optional = true }
|
||||||
serde_json = "1.0.79"
|
serde_json = "1.0.79"
|
||||||
serde_derive = "1.0.136"
|
serde_derive = "1.0.136"
|
||||||
|
@ -16,7 +16,7 @@ rustPlatform.buildRustPackage {
|
|||||||
|
|
||||||
nativeBuildInputs = [ pkg-config ];
|
nativeBuildInputs = [ pkg-config ];
|
||||||
|
|
||||||
cargoBuildFlags = [ "--no-default-features" ];
|
cargoBuildFlags = [ "--no-default-features" "--bin" "main_loop" ];
|
||||||
|
|
||||||
buildInputs = [ sqlite ];
|
buildInputs = [ sqlite ];
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![feature(array_windows)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
thread,
|
thread,
|
||||||
@ -67,7 +69,21 @@ impl<D: DrawTarget<Color = Rgb565>> ContextDefault<D> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let a = active.last().unwrap();
|
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 {
|
for s in &self.screensavers {
|
||||||
if s.id() == id {
|
if s.id() == id {
|
||||||
self.active.borrow_mut().push(s.convert_draw());
|
self.active.borrow_mut().push(s.convert_draw());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("warning: screensaver not found");
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +108,7 @@ fn pc_main() {}
|
|||||||
|
|
||||||
#[cfg(feature = "pc")]
|
#[cfg(feature = "pc")]
|
||||||
fn pc_main() {
|
fn pc_main() {
|
||||||
use std::num::NonZeroU32;
|
use std::{env, num::NonZeroU32};
|
||||||
|
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
@ -102,6 +120,16 @@ fn pc_main() {
|
|||||||
use crate::screensaver::{Screensaver, DUOLINGO};
|
use crate::screensaver::{Screensaver, DUOLINGO};
|
||||||
use raspi_oled::FrameOutput;
|
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 event_loop = EventLoop::new();
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_inner_size(LogicalSize::new(128, 128))
|
.with_inner_size(LogicalSize::new(128, 128))
|
||||||
@ -116,6 +144,7 @@ fn pc_main() {
|
|||||||
let mut buffer_dirty = true;
|
let mut buffer_dirty = true;
|
||||||
|
|
||||||
let mut ctx = ContextDefault::new();
|
let mut ctx = ContextDefault::new();
|
||||||
|
ctx.do_action(Action::Screensaver("plate"));
|
||||||
let mut rng = Xoroshiro128StarStar::seed_from_u64(17381);
|
let mut rng = Xoroshiro128StarStar::seed_from_u64(17381);
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
@ -156,81 +185,9 @@ fn pc_main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// redraw
|
// 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;
|
iters += 1;
|
||||||
buffer_dirty = ctx.loop_iter(&mut disp, &mut rng);
|
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();
|
let mut buffer = surface.buffer_mut().unwrap();
|
||||||
@ -256,6 +213,9 @@ fn pc_main() {
|
|||||||
|
|
||||||
pub trait Draw<D: DrawTarget<Color = Rgb565>> {
|
pub trait Draw<D: DrawTarget<Color = Rgb565>> {
|
||||||
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error>;
|
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error>;
|
||||||
|
fn expired(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rpi_main() {
|
fn rpi_main() {
|
||||||
@ -318,7 +278,6 @@ fn main_loop(mut disp: Oled) {
|
|||||||
},
|
},
|
||||||
6 => {
|
6 => {
|
||||||
menu.push(2);
|
menu.push(2);
|
||||||
ctx.do_action(Action::Screensaver("rpi"));
|
|
||||||
},
|
},
|
||||||
5 => {
|
5 => {
|
||||||
menu.push(3);
|
menu.push(3);
|
||||||
@ -327,6 +286,15 @@ fn main_loop(mut disp: Oled) {
|
|||||||
println!("unknown offset: {}", e.offset);
|
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:?}");
|
//println!("menu: {menu:?}");
|
||||||
}
|
}
|
||||||
// clean up stale menu selection
|
// clean up stale menu selection
|
||||||
@ -338,6 +306,6 @@ fn main_loop(mut disp: Oled) {
|
|||||||
if dirty {
|
if dirty {
|
||||||
let _ = disp.flush(); // ignore bus write errors, they are harmless
|
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: Reminder = Reminder::new(11, 30, Action::Screensaver("duolingo"));
|
||||||
static DUOLINGO_NIGHT: Reminder = Reminder::new(23, 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>> {
|
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::cell::RefCell;
|
||||||
|
use std::sync::atomic::{AtomicU32, AtomicU64};
|
||||||
|
|
||||||
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
@ -15,15 +16,28 @@ use time_tz::{timezones::db::europe::BERLIN, OffsetDateTimeExt};
|
|||||||
|
|
||||||
use crate::{Draw, Rng};
|
use crate::{Draw, Rng};
|
||||||
|
|
||||||
|
pub static SPEED: AtomicU64 = AtomicU64::new(32);
|
||||||
|
|
||||||
pub trait Screensaver<D: DrawTarget<Color = Rgb565>>: Draw<D> {
|
pub trait Screensaver<D: DrawTarget<Color = Rgb565>>: Draw<D> {
|
||||||
fn id(&self) -> &'static str;
|
fn id(&self) -> &'static str;
|
||||||
fn convert_draw(&self) -> Box<dyn Draw<D>>;
|
fn convert_draw(&self) -> Box<dyn Draw<D>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug)]
|
||||||
pub struct SimpleScreensaver {
|
pub struct SimpleScreensaver {
|
||||||
id: &'static str,
|
id: &'static str,
|
||||||
data: &'static [u8],
|
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 {
|
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>> {
|
fn convert_draw(&self) -> Box<dyn Draw<D>> {
|
||||||
Box::new(*self)
|
Box::new(self.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: DrawTarget<Color = Rgb565>> Draw<D> for SimpleScreensaver {
|
impl<D: DrawTarget<Color = Rgb565>> Draw<D> for SimpleScreensaver {
|
||||||
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error> {
|
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 x = (rng.next_u32() % 128) as usize;
|
||||||
let y = (rng.next_u32() % 128) as usize;
|
let y = (rng.next_u32() % 128) as usize;
|
||||||
let dx = (rng.next_u32() % 8) as i32 - 4;
|
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)?;
|
p.draw_styled(&s, disp)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.iters.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expired(&self) -> bool {
|
||||||
|
self.iters.load(std::sync::atomic::Ordering::Relaxed) > 1000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleScreensaver {
|
impl SimpleScreensaver {
|
||||||
@ -68,7 +87,11 @@ impl SimpleScreensaver {
|
|||||||
if data.len() != 128 * 128 * 3 {
|
if data.len() != 128 * 128 * 3 {
|
||||||
panic!("invalid screensaver size");
|
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 STAR: SimpleScreensaver = SimpleScreensaver::new("star", include_bytes!("./star.raw"));
|
||||||
pub static RPI: SimpleScreensaver = SimpleScreensaver::new("rpi", include_bytes!("./rpi.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 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>>> {
|
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