Working buttons & menu
This commit is contained in:
parent
97ca331f34
commit
a6ccd36ab5
73
Cargo.lock
generated
73
Cargo.lock
generated
@ -160,7 +160,7 @@ version = "4.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
@ -359,7 +359,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
@ -393,6 +393,7 @@ dependencies = [
|
||||
"bit_field",
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 1.0.0",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -585,12 +586,6 @@ dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@ -670,19 +665,6 @@ version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "maybe-async-cfg"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1e083394889336bc66a4eaf1011ffbfa74893e910f902a9f271fa624c61e1b2"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maze"
|
||||
version = "0.1.0"
|
||||
@ -851,17 +833,6 @@ dependencies = [
|
||||
"embedded-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
@ -913,7 +884,6 @@ dependencies = [
|
||||
"rand",
|
||||
"shared",
|
||||
"strum",
|
||||
"weact-studio-epd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -952,18 +922,6 @@ dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sealed"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4a8caec23b7800fb97971a1c6ae365b6239aaeddfb934d6265f8505e795699d"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
@ -1034,7 +992,7 @@ version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
@ -1116,15 +1074,6 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
@ -1167,20 +1116,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "weact-studio-epd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e531b21e70dfc6294be2429e4f616f634c8ca1a328325dceefc4f92c12d6e9b"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"embedded-graphics",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"maybe-async-cfg",
|
||||
"sealed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
|
@ -8,14 +8,13 @@ display-interface-spi = "0.5.0"
|
||||
embedded-graphics = "0.8.1"
|
||||
embedded-hal-bus = "0.2.0"
|
||||
esp-backtrace = { version = "0.13.0", features = ["esp32c6", "exception-handler", "panic-handler", "println"] }
|
||||
esp-hal = { version = "0.20", features = ["esp32c6", "embedded-hal"] }
|
||||
esp-hal = { version = "0.20.1", features = ["esp32c6", "embedded-hal"] }
|
||||
esp-println = { version = "0.10.0", default-features = false, features = ["esp32c6", "log", "auto"] }
|
||||
heapless = "0.8.0"
|
||||
log = { version = "0.4.21" }
|
||||
nutype = { version = "0.5.0", default-features = false }
|
||||
profont = "0.7.0"
|
||||
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
|
||||
weact-studio-epd = { version = "0.1.2", features = ["blocking"] }
|
||||
|
||||
shared = { path = "./shared", features = ['trng'] }
|
||||
maze = { path = "./maze" }
|
||||
|
@ -19,6 +19,7 @@ edition = "2021"
|
||||
embedded-graphics-core = { version = "0.4", optional = true }
|
||||
embedded-hal = "1.0.0"
|
||||
bit_field = "0.10.1"
|
||||
log = { version = "0.4.21" }
|
||||
|
||||
[dev-dependencies]
|
||||
embedded-graphics = "0.8"
|
||||
|
@ -60,32 +60,51 @@ where
|
||||
DELAY: DelayNs,
|
||||
{
|
||||
fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
|
||||
log::info!("self.interface.reset(delay, 30, 10)");
|
||||
// reset the device
|
||||
self.interface.reset(delay, 30, 10);
|
||||
|
||||
log::info!("self.interface.cmd(spi, Command::SwReset)?");
|
||||
self.interface.cmd(spi, Command::SwReset)?;
|
||||
log::info!("delay.delay_us(300000u32)");
|
||||
delay.delay_us(300000u32);
|
||||
|
||||
log::info!(".cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7])?;
|
||||
self.interface.wait_until_idle(delay, IS_BUSY_LOW);
|
||||
log::info!("1 .wait_until_idle(delay, IS_BUSY_LOW)");
|
||||
if let Err(e) = self.interface.wait_until_idle(delay, IS_BUSY_LOW) {
|
||||
log::error!("{e}");
|
||||
panic!("{e}");
|
||||
};
|
||||
log::info!(".cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7])?;
|
||||
self.interface.wait_until_idle(delay, IS_BUSY_LOW);
|
||||
log::info!("2 .wait_until_idle(delay, IS_BUSY_LOW)");
|
||||
if let Err(e) = self.interface.wait_until_idle(delay, IS_BUSY_LOW) {
|
||||
log::error!("{e}");
|
||||
panic!("{e}");
|
||||
}
|
||||
|
||||
log::info!(".cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00])?;
|
||||
log::info!(".cmd_with_data(spi, Command::GateVoltage, &[0x00])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::GateVoltage, &[0x00])?;
|
||||
log::info!(".cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32])?;
|
||||
|
||||
log::info!(".cmd_with_data(spi, Command::DataEntrySequence, &[0x03])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::DataEntrySequence, &[0x03])?;
|
||||
|
||||
log::info!(".cmd_with_data(spi, Command::BorderWaveformControl, &[0x03])?");
|
||||
self.interface
|
||||
.cmd_with_data(spi, Command::BorderWaveformControl, &[0x03])?;
|
||||
|
||||
log::info!(".cmd_with_data( spi, Command::BoosterSoftStartControl, &[0xAE, 0xC7, 0xC3, 0xC0, 0xC0],)?");
|
||||
self.interface.cmd_with_data(
|
||||
spi,
|
||||
Command::BoosterSoftStartControl,
|
||||
@ -142,11 +161,13 @@ where
|
||||
delay: &mut DELAY,
|
||||
delay_us: Option<u32>,
|
||||
) -> Result<Self, SPI::Error> {
|
||||
log::info!("DisplayInterface::new(busy, dc, rst, delay_us)");
|
||||
let mut epd = EPD3in7 {
|
||||
interface: DisplayInterface::new(busy, dc, rst, delay_us),
|
||||
background_color: DEFAULT_BACKGROUND_COLOR,
|
||||
};
|
||||
|
||||
log::info!("init");
|
||||
epd.init(spi, delay)?;
|
||||
Ok(epd)
|
||||
}
|
||||
|
@ -35,7 +35,9 @@ where
|
||||
/// If no delay is given, a default delay of 10ms is used.
|
||||
pub fn new(busy: BUSY, dc: DC, rst: RST, delay_us: Option<u32>) -> Self {
|
||||
// default delay of 10ms
|
||||
log::info!("delay_us.unwrap_or(10_000)");
|
||||
let delay_us = delay_us.unwrap_or(10_000);
|
||||
log::info!("delay_us.unwrap_or(10_000) done");
|
||||
DisplayInterface {
|
||||
_spi: PhantomData,
|
||||
_delay: PhantomData,
|
||||
@ -134,8 +136,20 @@ where
|
||||
/// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?)
|
||||
///
|
||||
/// Most likely there was a mistake with the 2in9 busy connection
|
||||
pub(crate) fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) {
|
||||
pub(crate) fn wait_until_idle(
|
||||
&mut self,
|
||||
delay: &mut DELAY,
|
||||
is_busy_low: bool,
|
||||
) -> Result<(), &'static str> {
|
||||
let mut times = 0;
|
||||
while self.is_busy(is_busy_low) {
|
||||
times += 1;
|
||||
if times % 10 == 0 {
|
||||
log::warn!("wait_until_idle {times}");
|
||||
}
|
||||
if times == 1_000 {
|
||||
return Err("Failed to wait 1 000 times despite idle");
|
||||
}
|
||||
// This has been removed and added many time :
|
||||
// - it is faster to not have it
|
||||
// - it is complicated to pass the delay everywhere all the time
|
||||
@ -146,6 +160,7 @@ where
|
||||
delay.delay_us(self.delay_us);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Same as `wait_until_idle` for device needing a command to probe Busy pin
|
||||
|
@ -1,3 +1,4 @@
|
||||
use epd_waveshare::{color::Color, prelude::WaveshareDisplay};
|
||||
use maze::{BinaryMapVisitor, Direction};
|
||||
|
||||
use crate::Button;
|
||||
@ -6,18 +7,24 @@ use super::*;
|
||||
|
||||
pub struct MazeGame {
|
||||
map: maze::BinaryMap<122, 122, 14884>,
|
||||
player: (u16, u16),
|
||||
player: Point,
|
||||
}
|
||||
|
||||
impl MazeGame {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: maze::BinaryMap::new(),
|
||||
player: (0, 1),
|
||||
player: Point { x: 0, y: 1 },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MazeGame {
|
||||
fn player_pos(&self) -> (u16, u16) {
|
||||
(self.player.x as u16, self.player.y as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl App for MazeGame {
|
||||
fn start(&mut self, trng: &mut Trng) {
|
||||
let mut grid = maze::Grid::<60, 60, 3600>::new();
|
||||
@ -25,17 +32,46 @@ impl App for MazeGame {
|
||||
BinaryMapVisitor.format(&mut grid, &mut self.map.0);
|
||||
}
|
||||
|
||||
fn draw(&self, ctx: &mut Context) {
|
||||
/*
|
||||
fn update_and_draw(&mut self, ctx: &mut Context) -> Option<Action> {
|
||||
let Some(button) = ctx.button_pressed else {
|
||||
return None;
|
||||
};
|
||||
let player_old = self.player.clone();
|
||||
|
||||
Some(match button {
|
||||
Button::Up if self.map.can_move(self.player_pos(), Direction::North) => {
|
||||
self.player.y -= 1;
|
||||
}
|
||||
Button::Down if self.map.can_move(self.player_pos(), Direction::South) => {
|
||||
self.player.y += 1;
|
||||
}
|
||||
Button::Left if self.map.can_move(self.player_pos(), Direction::West) => {
|
||||
self.player.x -= 1;
|
||||
}
|
||||
Button::Right if self.map.can_move(self.player_pos(), Direction::East) => {
|
||||
self.player.x += 1;
|
||||
}
|
||||
Button::Back => {}
|
||||
_ => {}
|
||||
});
|
||||
ctx.epaper.partial_update(
|
||||
player_old,
|
||||
Size {
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
&[Color::White as u8],
|
||||
);
|
||||
|
||||
let wall_style = PrimitiveStyleBuilder::new()
|
||||
.stroke_color(TriColor::Black)
|
||||
.stroke_color(Color::Black)
|
||||
.stroke_width(3)
|
||||
.fill_color(TriColor::Black)
|
||||
.fill_color(Color::Black)
|
||||
.build();
|
||||
let player_style = PrimitiveStyleBuilder::new()
|
||||
.stroke_color(TriColor::Red)
|
||||
.stroke_width(3)
|
||||
.fill_color(TriColor::Red)
|
||||
.stroke_color(Color::Black)
|
||||
.stroke_width(1)
|
||||
.fill_color(Color::Black)
|
||||
.build();
|
||||
|
||||
const X_OFFSET: i32 = 2;
|
||||
@ -49,43 +85,27 @@ impl App for MazeGame {
|
||||
Point::new(x as i32 + X_OFFSET, y as i32 + Y_OFFSET),
|
||||
Size::new(1, 1),
|
||||
);
|
||||
p.draw_styled(&wall_style, display).unwrap();
|
||||
p.draw_styled(&wall_style, &mut ctx.epaper.display).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let p = Rectangle::new(
|
||||
Point::new(
|
||||
self.player.0 as i32 + X_OFFSET,
|
||||
self.player.1 as i32 + Y_OFFSET,
|
||||
self.player.x as i32 + X_OFFSET,
|
||||
self.player.y as i32 + Y_OFFSET,
|
||||
),
|
||||
Size::new(1, 1),
|
||||
);
|
||||
p.draw_styled(&player_style, ctx.display).unwrap();
|
||||
p.draw_styled(&player_style, &mut ctx.epaper.display)
|
||||
.unwrap();
|
||||
}
|
||||
*/
|
||||
None
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut Context) -> Option<Action> {
|
||||
let Some(button) = ctx.button_pressed else {
|
||||
return None;
|
||||
};
|
||||
Some(match button {
|
||||
Button::Up if self.map.can_move(self.player, Direction::North) => {
|
||||
self.player.1 -= 1;
|
||||
}
|
||||
Button::Down if self.map.can_move(self.player, Direction::South) => {
|
||||
self.player.1 += 1;
|
||||
}
|
||||
Button::Left if self.map.can_move(self.player, Direction::West) => {
|
||||
self.player.0 -= 1;
|
||||
}
|
||||
Button::Right if self.map.can_move(self.player, Direction::East) => {
|
||||
self.player.0 += 1;
|
||||
}
|
||||
Button::Back => {}
|
||||
_ => {}
|
||||
});
|
||||
fn draw(&self, _ctx: &mut Context) {}
|
||||
|
||||
fn update(&mut self, _ctx: &mut Context) -> Option<Action> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::Button;
|
||||
|
||||
use super::*;
|
||||
use epd_waveshare::color::Color;
|
||||
use profont::PROFONT_18_POINT;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@ -70,9 +71,8 @@ impl App for Menu {
|
||||
}
|
||||
|
||||
fn draw(&self, ctx: &mut Context) {
|
||||
/*
|
||||
let style = MonoTextStyle::new(&PROFONT_18_POINT, TriColor::Black);
|
||||
let selected_style = MonoTextStyle::new(&PROFONT_18_POINT, TriColor::Red);
|
||||
let style = MonoTextStyle::new(&PROFONT_18_POINT, Color::Black);
|
||||
let selected_style = MonoTextStyle::new(&PROFONT_18_POINT, Color::Black);
|
||||
|
||||
MenuEntry::iter().for_each(|entry| {
|
||||
if entry == self.selected {
|
||||
@ -82,7 +82,7 @@ impl App for Menu {
|
||||
selected_style,
|
||||
TextStyle::default(),
|
||||
)
|
||||
.draw(display)
|
||||
.draw(&mut ctx.epaper.display)
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
@ -96,9 +96,8 @@ impl App for Menu {
|
||||
},
|
||||
TextStyle::default(),
|
||||
)
|
||||
.draw(display)
|
||||
.draw(&mut ctx.epaper.display)
|
||||
.unwrap();
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ use embedded_graphics::{
|
||||
Drawable,
|
||||
};
|
||||
use esp_hal::rng::Trng;
|
||||
use esp_println::println;
|
||||
use maze_game::MazeGame;
|
||||
use menu::Menu;
|
||||
use weact_studio_epd::{graphics::Display290TriColor, TriColor};
|
||||
|
||||
use crate::Context;
|
||||
|
||||
@ -16,6 +16,7 @@ pub mod guess_game;
|
||||
pub mod maze_game;
|
||||
pub mod menu;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Action {
|
||||
GoToMenu,
|
||||
StartMaze,
|
||||
@ -27,6 +28,12 @@ pub enum Application {
|
||||
Maze(maze_game::MazeGame),
|
||||
}
|
||||
|
||||
impl Default for Application {
|
||||
fn default() -> Self {
|
||||
Self::Menu(Menu::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl Application {
|
||||
pub fn update(&mut self, ctx: &mut Context, trng: &mut Trng) {
|
||||
let Some(action) = (match self {
|
||||
@ -51,23 +58,52 @@ impl Application {
|
||||
}
|
||||
|
||||
pub fn draw(&self, ctx: &mut Context) {
|
||||
ctx.epaper.full_erase();
|
||||
match self {
|
||||
Self::Menu(menu) => menu.draw(ctx),
|
||||
Self::Maze(maze) => maze.draw(ctx),
|
||||
};
|
||||
ctx.epaper.full_update();
|
||||
}
|
||||
|
||||
pub fn update_and_draw(&mut self, ctx: &mut Context, trng: &mut Trng) {
|
||||
let Some(action) = (match self {
|
||||
Self::Menu(menu) => menu.update_and_draw(ctx),
|
||||
Self::Maze(maze) => maze.update_and_draw(ctx),
|
||||
}) else {
|
||||
println!("No action");
|
||||
return;
|
||||
};
|
||||
println!("Action: {action:?}");
|
||||
match action {
|
||||
Action::StartMaze => {
|
||||
let mut maze = MazeGame::new();
|
||||
maze.start(trng);
|
||||
*self = Application::Maze(maze);
|
||||
}
|
||||
Action::GoToMenu => {
|
||||
let mut menu = Menu::new();
|
||||
menu.start(trng);
|
||||
*self = Application::Menu(menu);
|
||||
}
|
||||
Action::StartPairs => {}
|
||||
};
|
||||
self.draw(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait App {
|
||||
fn start(&mut self, trng: &mut Trng);
|
||||
|
||||
fn draw(&self, display: &mut Context);
|
||||
fn draw(&self, ctx: &mut Context);
|
||||
|
||||
fn update(&mut self, ctx: &mut Context) -> Option<Action>;
|
||||
|
||||
fn draw_and_update(&mut self, ctx: &mut Context) -> Option<Action> {
|
||||
fn update_and_draw(&mut self, ctx: &mut Context) -> Option<Action> {
|
||||
let action = self.update(ctx);
|
||||
if action.is_none() {
|
||||
self.draw(ctx);
|
||||
}
|
||||
action
|
||||
}
|
||||
}
|
||||
|
177
src/main.rs
177
src/main.rs
@ -1,16 +1,19 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod epaper;
|
||||
|
||||
use apps::{menu::Menu, Application};
|
||||
use display_interface_spi::SPIInterface;
|
||||
use embedded_graphics::{
|
||||
geometry::Point,
|
||||
mono_font::{MonoTextStyle, MonoTextStyleBuilder},
|
||||
text::{Baseline, Text, TextStyle, TextStyleBuilder},
|
||||
geometry::{Point, Size},
|
||||
mono_font::MonoTextStyleBuilder,
|
||||
primitives::{Primitive, PrimitiveStyleBuilder, Rectangle, StyledDrawable},
|
||||
text::{Baseline, Text, TextStyleBuilder},
|
||||
Drawable,
|
||||
};
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use epaper::Epaper;
|
||||
use epd_waveshare::epd3in7::*;
|
||||
use epd_waveshare::prelude::*;
|
||||
use esp_backtrace as _;
|
||||
@ -18,8 +21,8 @@ use esp_hal::{
|
||||
clock::ClockControl,
|
||||
delay::Delay,
|
||||
gpio::{
|
||||
Gpio10, Gpio2, Gpio20, Gpio21, Gpio22, Gpio23, Gpio3, Gpio4, Gpio5, Gpio6, Gpio7, Gpio8,
|
||||
Input, Io, Level, Output, OutputOpenDrain, Pull, NO_PIN,
|
||||
Gpio0, Gpio1, Gpio10, Gpio11, Gpio2, Gpio20, Gpio21, Gpio22, Gpio23, Gpio3, Gpio4, Gpio5,
|
||||
Gpio6, Gpio7, Gpio8, Input, Io, Level, Output, OutputOpenDrain, Pull, NO_PIN,
|
||||
},
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
@ -46,7 +49,7 @@ fn main() -> ! {
|
||||
let system = SystemControl::new(peripherals.SYSTEM);
|
||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||
let mut delay = Delay::new(&clocks);
|
||||
let delay = Delay::new(&clocks);
|
||||
|
||||
esp_println::logger::init_logger(LevelFilter::Trace);
|
||||
// esp_println::logger::init_logger_from_env();
|
||||
@ -57,7 +60,7 @@ fn main() -> ! {
|
||||
// Configure SPI
|
||||
// Settings are taken from
|
||||
|
||||
// Pins for WeAct
|
||||
// Pins for e-paper
|
||||
let mosi /* sda */ = io.pins.gpio18; // D10 / GPIO18
|
||||
let sclk = io.pins.gpio19; // D8 / GPIO19
|
||||
let cs = io.pins.gpio20; // D9 / GPIO20
|
||||
@ -65,104 +68,45 @@ fn main() -> ! {
|
||||
let rst = io.pins.gpio22; // D4 / GPIO22
|
||||
let busy = io.pins.gpio23; // D5 / GPIO23
|
||||
|
||||
let spi_bus: SpiBus = Spi::new(peripherals.SPI2, 4_000.kHz(), SpiMode::Mode0, &clocks)
|
||||
.with_pins(
|
||||
Some(sclk),
|
||||
Some(mosi),
|
||||
NO_PIN,
|
||||
NO_PIN, // cs is handled by the exclusive device
|
||||
);
|
||||
let mut epaper = epaper::Epaper::new(mosi, sclk, cs, dc, rst, busy, peripherals.SPI2, &clocks);
|
||||
|
||||
// Convert pins into InputPins and OutputPins
|
||||
/*
|
||||
CS: OutputPin,
|
||||
BUSY: InputPin,
|
||||
DC: OutputPin,
|
||||
RST: OutputPin,
|
||||
*/
|
||||
|
||||
let cs: CS = Output::new(cs, Level::High);
|
||||
let busy: BUS = Input::new(busy, esp_hal::gpio::Pull::Up);
|
||||
let dc: DC = Output::new(dc, Level::Low);
|
||||
let rst = Output::new(rst, Level::High);
|
||||
|
||||
log::info!("Intializing SPI Device...");
|
||||
let mut spi: SPI =
|
||||
ExclusiveDevice::new(spi_bus, cs, delay).expect("SPI device initialize error");
|
||||
// let spi_interface = SPIInterface::new(spi_device, dc);
|
||||
let mut driver =
|
||||
EPD3in7::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error");
|
||||
|
||||
let mut display = Display3in7::default();
|
||||
display.set_rotation(DisplayRotation::Rotate90);
|
||||
|
||||
// draw white on black background
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(&embedded_graphics::mono_font::ascii::FONT_6X10)
|
||||
.text_color(Color::White)
|
||||
.background_color(Color::Black)
|
||||
.build();
|
||||
let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build();
|
||||
let _ =
|
||||
Text::with_text_style("Witamy!", Point::new(90, 10), style, text_style).draw(&mut display);
|
||||
driver
|
||||
.update_and_display_frame(&mut spi, display.buffer(), &mut delay)
|
||||
.expect("display frame new graphics");
|
||||
delay.delay_ms(500);
|
||||
|
||||
// epd2in13
|
||||
// .set_refresh(&mut spi, &mut delay, RefreshLut::Quick)
|
||||
// .unwrap();
|
||||
driver.clear_frame(&mut spi, &mut delay).unwrap();
|
||||
epaper.full_erase();
|
||||
epaper.print_welcome();
|
||||
|
||||
let mut kbd = Keypad {
|
||||
i1: Input::new(io.pins.gpio2, Pull::Up),
|
||||
i2: Input::new(io.pins.gpio3, Pull::Up),
|
||||
i3: Input::new(io.pins.gpio4, Pull::Up),
|
||||
i4: Input::new(io.pins.gpio5, Pull::Up),
|
||||
i1: Input::new(io.pins.gpio4, Pull::Up),
|
||||
i2: Input::new(io.pins.gpio5, Pull::Up),
|
||||
i3: Input::new(io.pins.gpio6, Pull::Up),
|
||||
i4: Input::new(io.pins.gpio7, Pull::Up),
|
||||
//---------------------------
|
||||
o1: OutputOpenDrain::new(io.pins.gpio6, Level::Low, Pull::Up),
|
||||
o2: OutputOpenDrain::new(io.pins.gpio7, Level::Low, Pull::Up),
|
||||
o1: OutputOpenDrain::new(io.pins.gpio0, Level::Low, Pull::Up),
|
||||
o2: OutputOpenDrain::new(io.pins.gpio1, Level::Low, Pull::Up),
|
||||
o3: OutputOpenDrain::new(io.pins.gpio8, Level::Low, Pull::Up),
|
||||
o4: OutputOpenDrain::new(io.pins.gpio10, Level::Low, Pull::Up),
|
||||
};
|
||||
|
||||
let mut ctx = Context {
|
||||
button_pressed: None,
|
||||
driver,
|
||||
display,
|
||||
spi,
|
||||
epaper,
|
||||
delay,
|
||||
};
|
||||
let mut app = Application::Menu(Menu::new());
|
||||
let mut app = Application::default();
|
||||
let mut trng = Trng::new(peripherals.RNG, peripherals.ADC1);
|
||||
|
||||
//app.draw(&mut display);
|
||||
//driver.full_update(&display).unwrap();
|
||||
//driver.sleep().unwrap();
|
||||
ctx.driver.clear_frame(&mut ctx.spi, &mut delay).unwrap();
|
||||
ctx.driver
|
||||
.update_and_display_frame(&mut ctx.spi, ctx.display.buffer(), &mut delay)
|
||||
.expect("display frame new graphics");
|
||||
let _ = ctx.driver.sleep(&mut ctx.spi, &mut delay);
|
||||
app.draw(&mut ctx);
|
||||
app.update_and_draw(&mut ctx, &mut trng);
|
||||
|
||||
// ctx.epaper.sleep();
|
||||
|
||||
loop {
|
||||
ctx.button_pressed = kbd.pressed();
|
||||
if !ctx.button_pressed.is_none() {
|
||||
log::info!("Wake up!");
|
||||
ctx.driver.wake_up(&mut ctx.spi, &mut delay).unwrap();
|
||||
//display.clear(TriColor::White);
|
||||
//app.update(&ctx, &mut trng);
|
||||
// app.draw(&mut display);
|
||||
//driver.full_update(&display).unwrap();
|
||||
ctx.driver.clear_frame(&mut ctx.spi, &mut delay).unwrap();
|
||||
ctx.driver
|
||||
.update_and_display_frame(&mut ctx.spi, ctx.display.buffer(), &mut delay)
|
||||
.expect("display frame new graphics");
|
||||
let _ = ctx.driver.sleep(&mut ctx.spi, &mut delay);
|
||||
// ctx.epaper.wake_up();
|
||||
app.update_and_draw(&mut ctx, &mut trng);
|
||||
}
|
||||
|
||||
log::info!("Sleeping for 100ms...");
|
||||
// log::info!("Sleeping for 100ms...");
|
||||
//driver.sleep().unwrap();
|
||||
delay.delay(300.millis());
|
||||
}
|
||||
@ -200,42 +144,79 @@ pub enum Button {
|
||||
Back,
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn from_idx(idx: usize) -> Option<Button> {
|
||||
Some(match idx {
|
||||
0 => Button::A,
|
||||
1 => Button::Up,
|
||||
2 => Button::B,
|
||||
3 => Button::X,
|
||||
//
|
||||
4 => Button::Left,
|
||||
5 => Button::Circle,
|
||||
6 => Button::Right,
|
||||
7 => Button::Y,
|
||||
//
|
||||
8 => Button::C,
|
||||
9 => Button::Down,
|
||||
10 => Button::D,
|
||||
11 => Button::Z,
|
||||
//
|
||||
12 => Button::A,
|
||||
13 => Button::A,
|
||||
14 => Button::A,
|
||||
15 => Button::A,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Context<'d> {
|
||||
pub button_pressed: Option<Button>,
|
||||
pub display: Display3in7,
|
||||
pub driver: Driver<'d>,
|
||||
pub spi: SPI<'d>,
|
||||
pub epaper: Epaper<'d>,
|
||||
pub delay: Delay,
|
||||
}
|
||||
struct Keypad<'d> {
|
||||
o1: OutputOpenDrain<'d, Gpio6>, //
|
||||
o2: OutputOpenDrain<'d, Gpio7>, //
|
||||
// COLS
|
||||
o1: OutputOpenDrain<'d, Gpio0>, //
|
||||
o2: OutputOpenDrain<'d, Gpio1>, //
|
||||
o3: OutputOpenDrain<'d, Gpio8>, //
|
||||
o4: OutputOpenDrain<'d, Gpio10>, //
|
||||
// --------------------------------------
|
||||
i1: Input<'d, Gpio2>, //
|
||||
i2: Input<'d, Gpio3>, //
|
||||
i3: Input<'d, Gpio4>, //
|
||||
i4: Input<'d, Gpio5>, //
|
||||
// ROWS
|
||||
i1: Input<'d, Gpio4>, //
|
||||
i2: Input<'d, Gpio5>, //
|
||||
i3: Input<'d, Gpio6>, //
|
||||
i4: Input<'d, Gpio7>, //
|
||||
}
|
||||
impl<'d> Keypad<'d> {
|
||||
pub fn pressed(&mut self) -> Option<Button> {
|
||||
let res: [[bool; 4]; 4] = core::array::from_fn(|x| {
|
||||
core::array::from_fn(|y| {
|
||||
self.set_high(x as u8);
|
||||
let v = self.is_low(y as u8);
|
||||
self.set_low(x as u8);
|
||||
let v = self.is_low(y as u8);
|
||||
self.set_high(x as u8);
|
||||
v
|
||||
})
|
||||
});
|
||||
|
||||
if res.iter().any(|a| a.iter().any(|b| !b)) {
|
||||
if res.iter().any(|a| a.iter().any(|b| *b)) {
|
||||
println!("***************************************");
|
||||
for a in res {
|
||||
println!("col {a:?}");
|
||||
}
|
||||
}
|
||||
None
|
||||
let c = res
|
||||
.into_iter()
|
||||
.map(|v| v.into_iter())
|
||||
.flatten()
|
||||
.enumerate()
|
||||
.find(|(_idx, b)| *b)
|
||||
.and_then(|(idx, _)| Button::from_idx(idx));
|
||||
|
||||
println!("Button: {c:?}");
|
||||
|
||||
c
|
||||
}
|
||||
|
||||
fn set_high(&mut self, o: u8) {
|
||||
|
Loading…
Reference in New Issue
Block a user