Skip to content

Commit 21bb136

Browse files
committed
m5stack-atom-s3: add reset via button click
1 parent 4a2efe1 commit 21bb136

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ cargo run --release
4040

4141
- https://docs.m5stack.com/en/core/AtomS3
4242

43+
Controls: Press button under display to reset the game state (GPIO 41).
44+
4345
The implementation is based on Rust no\_std, using mipidsi crate and Bevy ECS.
4446
It requires es-rs toolchain for ESP32-S3 version at [least 1.85](https://github.com/esp-rs/rust-build/releases/tag/v1.85.0.0), because of edition 2024.
4547

m5stack-atom-s3/src/main.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use esp_hal::dma::{DmaRxBuf, DmaTxBuf};
2323
use esp_hal::dma_buffers;
2424
use esp_hal::{
2525
Blocking,
26-
gpio::{DriveMode, Level, Output, OutputConfig},
26+
gpio::{DriveMode, Input, InputConfig, Level, Output, OutputConfig, Pull},
2727
main,
2828
rng::Rng,
2929
spi::master::{Spi, SpiDmaBus},
@@ -256,6 +256,16 @@ struct DisplayResource {
256256
display: MyDisplay,
257257
}
258258

259+
struct ButtonResource {
260+
button: Input<'static>,
261+
}
262+
263+
/// Resource to track the previous state of the button (for edge detection).
264+
#[derive(Default, Resource)]
265+
struct ButtonState {
266+
was_pressed: bool,
267+
}
268+
259269
fn update_game_of_life_system(
260270
mut game: ResMut<GameOfLifeResource>,
261271
mut rng_res: ResMut<RngResource>,
@@ -268,6 +278,26 @@ fn update_game_of_life_system(
268278
}
269279
}
270280

281+
/// System to check the button and reset the simulation when pressed.
282+
fn button_reset_system(
283+
mut game: ResMut<GameOfLifeResource>,
284+
mut rng_res: ResMut<RngResource>,
285+
mut btn_state: ResMut<ButtonState>,
286+
button_res: NonSend<ButtonResource>,
287+
) {
288+
// Check if the button is pressed (active low)
289+
if button_res.button.is_low() {
290+
if !btn_state.was_pressed {
291+
// Button press detected: reset simulation.
292+
randomize_grid(&mut rng_res.0, &mut game.grid);
293+
game.generation = 0;
294+
btn_state.was_pressed = true;
295+
}
296+
} else {
297+
btn_state.was_pressed = false;
298+
}
299+
}
300+
271301
/// Render the game state by drawing into the offscreen framebuffer and then flushing
272302
/// it to the display via DMA. After drawing the game grid and generation number,
273303
/// we overlay centered text.
@@ -355,11 +385,7 @@ fn main() -> ! {
355385
let mut display_delay = Delay::new();
356386
display_delay.delay_ns(500_000u32);
357387

358-
let reset = Output::new(
359-
peripherals.GPIO34,
360-
Level::High,
361-
OutputConfig::default(),
362-
);
388+
let reset = Output::new(peripherals.GPIO34, Level::High, OutputConfig::default());
363389
// Initialize the display using mipidsi's builder.
364390
let mut display: MyDisplay = Builder::new(GC9A01, di)
365391
.reset_pin(reset)
@@ -398,7 +424,20 @@ fn main() -> ! {
398424
// Insert the framebuffer resource as a normal resource.
399425
world.insert_resource(fb_res);
400426

427+
// --- Initialize Button Resource ---
428+
// Configure the button as an input with an internal pull-up (active low).
429+
let button = Input::new(
430+
peripherals.GPIO41,
431+
InputConfig::default().with_pull(Pull::Up),
432+
);
433+
world.insert_non_send_resource(ButtonResource { button });
434+
// Insert a resource to track button state for debouncing.
435+
world.insert_resource(ButtonState::default());
436+
437+
// --- Build ECS Schedule ---
438+
// We add the button system so that a button press resets the simulation.
401439
let mut schedule = Schedule::default();
440+
schedule.add_systems(button_reset_system);
402441
schedule.add_systems(update_game_of_life_system);
403442
schedule.add_systems(render_system);
404443

0 commit comments

Comments
 (0)