From 5d33f358d6b5e28303484e0dc394f8c38234ce30 Mon Sep 17 00:00:00 2001 From: Rudis Muiznieks Date: Sun, 1 Sep 2024 09:13:12 -0500 Subject: [PATCH] basic game loop and some ic2 and display stuff --- Cargo.lock | 183 +++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 4 +- cmd | 13 ++-- src/game.rs | 135 ++++++++++++++++++++++++++++++++++++ src/main.rs | 60 +++------------- src/strings.rs | 2 + 6 files changed, 337 insertions(+), 60 deletions(-) create mode 100644 src/game.rs create mode 100644 src/strings.rs diff --git a/Cargo.lock b/Cargo.lock index eea8e98..509cb6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byte-slice-cast" version = "0.3.5" @@ -26,6 +32,21 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", +] + [[package]] name = "display-interface" version = "0.4.1" @@ -53,6 +74,16 @@ dependencies = [ "embedded-hal 0.2.7", ] +[[package]] +name = "ds323x" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5157c16c530fa971b40f2b591edd86b9ce300ec1e5c267a4d6df6ee7df890a6" +dependencies = [ + "embedded-hal 0.2.7", + "rtcc", +] + [[package]] name = "embedded-graphics" version = "0.8.1" @@ -111,12 +142,37 @@ dependencies = [ "num-traits", ] +[[package]] +name = "game-loop" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f565189f0b27943213411d9d1c2df8b5d066e14d2e75f041d3b53c13b24ac80" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "micromath" version = "2.1.0" @@ -148,12 +204,27 @@ dependencies = [ ] [[package]] -name = "pipod" -version = "0.1.0" +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ - "embedded-graphics", - "rppal", - "ssd1306", + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", ] [[package]] @@ -171,6 +242,26 @@ dependencies = [ "void", ] +[[package]] +name = "rtcc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95973c3a0274adc4f3c5b70d2b5b85618d6de9559a6737d3293ecae9a2fc0839" +dependencies = [ + "chrono", +] + +[[package]] +name = "sojourn" +version = "0.1.0" +dependencies = [ + "ds323x", + "embedded-graphics", + "game-loop", + "rppal", + "ssd1306", +] + [[package]] name = "spin_sleep" version = "1.2.1" @@ -193,12 +284,94 @@ dependencies = [ "embedded-hal 0.2.7", ] +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index b391df1..3462c18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,11 @@ [package] -name = "pipod" +name = "sojourn" version = "0.1.0" edition = "2021" [dependencies] +ds323x = "0.5.1" embedded-graphics = "0.8.1" +game-loop = "1.2.0" rppal = { version = "0.19.0", features = ["hal"] } ssd1306 = "0.8.4" diff --git a/cmd b/cmd index ebe7ab3..05737f7 100755 --- a/cmd +++ b/cmd @@ -19,13 +19,13 @@ else fi ssh_run_cmd() { - ssh -i "$SSH_KEY" "$SSH_HOST" "$@" + ssh -i "$SSH_KEY" -t "$SSH_HOST" "$@" } copy_and_run() { file=$1 scp -i "$SSH_KEY" "$file" "$SSH_HOST":"$SSH_DEST_DIR" - ssh_run_cmd "${SSH_DEST_DIR:-.}/pipod" + ssh_run_cmd "${SSH_DEST_DIR:-.}/sojourn" } { @@ -34,9 +34,12 @@ copy_and_run() { "clean") cargo clean;; "build") cargo build --target arm-unknown-linux-gnueabihf;; "release") cargo build --release --target arm-unknown-linux-gnueabihf;; - "debug") ./cmd build && copy_and_run ./target/arm-unknown-linux-gnueabihf/debug/pipod;; - "run") ./cmd release && copy_and_run ./target/arm-unknown-linux-gnueabihf/release/pipod;; - "remote-clean") ssh_run_cmd rm -f "${SSH_DEST_DIR:-.}/pipod";; + "debug") ./cmd build && copy_and_run ./target/arm-unknown-linux-gnueabihf/debug/sojourn;; + "run") ./cmd release && copy_and_run ./target/arm-unknown-linux-gnueabihf/release/sojourn;; + "remote-clean") + ssh_run_cmd killall sojourn + ssh_run_cmd rm -f "${SSH_DEST_DIR:-.}/sojourn" + ;; "help") echo "Usage: ./cmd [task]" echo "Tasks: clean, build, release, debug, run, remote-clean, help" diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..3e35e93 --- /dev/null +++ b/src/game.rs @@ -0,0 +1,135 @@ +use crate::strings; +use embedded_graphics::{ + mono_font::{ascii::FONT_4X6, MonoTextStyleBuilder, MonoTextStyle}, + pixelcolor::BinaryColor, + image::{Image, ImageRaw}, + prelude::*, + primitives::{PrimitiveStyleBuilder, PrimitiveStyle, Line}, + text::{Baseline, Text}, +}; +use rppal::i2c::I2c; +use ssd1306::{ + prelude::{ + I2CInterface as SsdRtc, + DisplaySize128x64, + DisplayRotation, + }, + mode::{ + BufferedGraphicsMode, + DisplayConfig, + }, + I2CDisplayInterface, + Ssd1306, +}; +use ds323x::{ + ic::DS3231, + interface::I2cInterface as RtcI2c, + Ds323x, + DateTimeAccess, + NaiveDateTime, +}; + +const ADDR_PISUGAR: u16 = 0x57; +const BATT_POLL_SECONDS: u64 = 3; +const REG_PERCENT: u8 = 0x2a; + +const BAT_DATA: &'static [u8] = &[ + 0b11111110, + 0b10000010, + 0b10000001, + 0b10000001, + 0b10000010, + 0b11111110, +]; + +pub struct Game<'a> { + batt_i2c: I2c, + display: Ssd1306, DisplaySize128x64, BufferedGraphicsMode>, + rtc: Ds323x, DS3231>, + style: PrimitiveStyle, + text_style: MonoTextStyle<'a, BinaryColor>, + last_batt_poll: Option, + batt_pct: u8, + title: String, +} + +impl Game<'_> { + + pub fn new() -> Game<'static> { + let display_i2c = I2c::new().unwrap(); + let interface = I2CDisplayInterface::new(display_i2c); + let rtc_i2c = I2c::new().unwrap(); + let mut game: Game = Game { + batt_i2c: I2c::new().unwrap(), + display: Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) + .into_buffered_graphics_mode(), + rtc: Ds323x::new_ds3231(rtc_i2c), + style: PrimitiveStyleBuilder::new() + .stroke_width(1) + .stroke_color(BinaryColor::On) + .build(), + text_style: MonoTextStyleBuilder::new() + .font(&FONT_4X6) + .text_color(BinaryColor::On) + .build(), + last_batt_poll: None, + batt_pct: 0, + title: format!("{} v{}", strings::SOJOURN, strings::VERSION), + }; + game.batt_i2c.set_slave_address(ADDR_PISUGAR).unwrap(); + game.display.init().unwrap(); + return game; + } + + pub fn update(&mut self) { + let dt = self.rtc.datetime().unwrap(); + if !self.last_batt_poll.is_some() || (dt - self.last_batt_poll.unwrap()) + .num_seconds().unsigned_abs() > BATT_POLL_SECONDS { + self.read_batt_pct(); + self.last_batt_poll = Some(dt); + } + } + + pub fn draw(&mut self) { + self.draw_status(); + self.display.flush().unwrap(); + } + + fn read_batt_pct(&mut self) { + let mut buf = [0u8; 1]; + self.batt_i2c.block_read(REG_PERCENT, &mut buf).unwrap(); + self.batt_pct = buf[0]; + } + + fn draw_status(&mut self) { + self.display.clear_buffer(); + + Line::new(Point::new(0, 8), Point::new(127, 8)) + .into_styled(self.style) + .draw(&mut self.display) + .unwrap(); + + Text::with_baseline( + &format!("{: >3}%", self.batt_pct), + Point::new(111, 0), + self.text_style, + Baseline::Top, + ) + .draw(&mut self.display) + .unwrap(); + + let raw_image = ImageRaw::::new(BAT_DATA, 8); + let image = Image::new(&raw_image, Point::new(102, 0)); + image.draw(&mut self.display).unwrap(); + + // 24 chars for title max + Text::with_baseline( + &self.title, + Point::new(0, 0), + self.text_style, + Baseline::Top, + ) + .draw(&mut self.display) + .unwrap(); + } +} diff --git a/src/main.rs b/src/main.rs index e35afbc..8d74f5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,53 +1,15 @@ -use embedded_graphics::{ - mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder}, - pixelcolor::BinaryColor, - prelude::*, - primitives::{Circle, PrimitiveStyleBuilder, Rectangle, Triangle}, - text::{Baseline, Text}, -}; -use rppal::i2c::I2c; -use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; +mod game; +mod strings; +mod display; -const ADDR_PISUGAR: u16 = 0x57; -const REG_PERCENT: u8 = 0x2a; -const REG_RTC: u8 = 0x68; +use game::Game; +use game_loop::game_loop; fn main() { - let mut batt_i2c = I2c::new().unwrap(); - batt_i2c.set_slave_address(ADDR_PISUGAR); - - let mut buf = [0u8; 1]; - batt_i2c.block_read(REG_PERCENT, &mut buf).unwrap(); - - let display_i2c = I2c::new().unwrap(); - let interface = I2CDisplayInterface::new(display_i2c); - let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) - .into_buffered_graphics_mode(); - display.init().unwrap(); - - /*let style = PrimitiveStyleBuilder::new() - .stroke_width(1) - .stroke_color(BinaryColor::On) - .build(); - - Rectangle::new(Point::new(0, 0), Size::new(127, 63)) - .into_styled(style) - .draw(&mut display) - .unwrap(); - - let text_style = MonoTextStyleBuilder::new() - .font(&FONT_6X10) - .text_color(BinaryColor::On) - .build(); - - Text::with_baseline( - &format!("Battery: {}%", buf[0]), - Point::new(2, 2), - text_style, - Baseline::Top, - ) - .draw(&mut display) - .unwrap();*/ - - display.flush().unwrap(); + let game = Game::new(); + game_loop(game, 60, 0.1, |g| { + g.game.update(); + }, |g| { + g.game.draw(); + }); } diff --git a/src/strings.rs b/src/strings.rs new file mode 100644 index 0000000..87d084b --- /dev/null +++ b/src/strings.rs @@ -0,0 +1,2 @@ +pub const SOJOURN: &str = "sojourn"; +pub const VERSION: &str = "0.1.0";