basic game loop and some ic2 and display stuff

This commit is contained in:
Rudis Muiznieks 2024-09-01 09:13:12 -05:00
parent 54e54a90e7
commit 5d33f358d6
Signed by: rudism
GPG key ID: CABF2F86EF7884F9
6 changed files with 337 additions and 60 deletions

183
Cargo.lock generated
View file

@ -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"

View file

@ -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"

13
cmd
View file

@ -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"

135
src/game.rs Normal file
View file

@ -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<SsdRtc<I2c>, DisplaySize128x64, BufferedGraphicsMode<DisplaySize128x64>>,
rtc: Ds323x<RtcI2c<I2c>, DS3231>,
style: PrimitiveStyle<BinaryColor>,
text_style: MonoTextStyle<'a, BinaryColor>,
last_batt_poll: Option<NaiveDateTime>,
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::<BinaryColor>::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();
}
}

View file

@ -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();
});
}

2
src/strings.rs Normal file
View file

@ -0,0 +1,2 @@
pub const SOJOURN: &str = "sojourn";
pub const VERSION: &str = "0.1.0";