diff --git a/Cargo.lock b/Cargo.lock index f896991..f4cef1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,6 +284,7 @@ dependencies = [ name = "esp32c3-playground" version = "0.1.0" dependencies = [ + "critical-section", "esp-hal", "panic-halt", ] diff --git a/Cargo.toml b/Cargo.toml index 27c8f54..874d5e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +critical-section = "1.1.2" esp-hal = { version = "0.17.0", features = ["esp32c3"] } panic-halt = "0.2.0" diff --git a/src/main.rs b/src/main.rs index 149ed91..cbd323c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,35 @@ #![no_std] #![no_main] +use core::cell::Cell; + +use critical_section::Mutex; + use esp_hal::clock::ClockControl; use esp_hal::delay::Delay; -use esp_hal::gpio::IO; +use esp_hal::gpio::{Event, IO}; use esp_hal::ledc::{channel, timer, LSGlobalClkSource, LEDC}; use esp_hal::peripherals::Peripherals; use esp_hal::prelude::*; +use esp_hal::systimer::SystemTimer; use panic_halt as _; +const BUTTON_TIMEOUT: u64 = SystemTimer::TICKS_PER_SECOND / 10; + +const COLORS: [[u8; 3]; 6] = [ + [1, 0, 0], + [1, 1, 0], + [0, 1, 0], + [0, 1, 1], + [0, 0, 1], + [1, 0, 1], +]; + +static LAST_TRIGGERED: Mutex> = Mutex::new(Cell::new(0)); + +static STOP_CHASE: Mutex> = Mutex::new(Cell::new(false)); + #[entry] fn main() -> ! { let p = Peripherals::take(); @@ -28,7 +48,9 @@ fn main() -> ! { }) .unwrap(); - let io = IO::new(p.GPIO, p.IO_MUX); + let mut io = IO::new(p.GPIO, p.IO_MUX); + + io.set_interrupt_handler(gpio_handler); let mut r = ledc.get_channel( channel::Number::Channel0, @@ -62,27 +84,35 @@ fn main() -> ! { }) .unwrap(); - let _btn = io.pins.gpio9.into_pull_up_input(); + io.pins.gpio9.into_pull_up_input().listen(Event::RisingEdge); let delay = Delay::new(&clocks); - for [r_state, g_state, b_state] in [ - [1, 0, 0], - [1, 1, 0], - [0, 1, 0], - [0, 1, 1], - [0, 0, 1], - [1, 0, 1], - ] - .iter() - .cycle() - { - let _ = r.set_duty(*r_state); - let _ = g.set_duty(*g_state); - let _ = b.set_duty(*b_state); + for [r_duty, g_duty, b_duty] in COLORS.iter().cycle() { + let stop_chase = critical_section::with(|cs| STOP_CHASE.borrow(cs).get()); + if !stop_chase { + let _ = r.set_duty(*r_duty); + let _ = g.set_duty(*g_duty); + let _ = b.set_duty(*b_duty); + } delay.delay_millis(200u32); } loop {} } + +#[handler] +fn gpio_handler() { + critical_section::with(|cs| { + let last_triggered = LAST_TRIGGERED.borrow(cs); + if last_triggered.get() + BUTTON_TIMEOUT > SystemTimer::now() { + return; + } + + let stop_chase = STOP_CHASE.borrow(cs); + stop_chase.set(!stop_chase.get()); + + last_triggered.set(SystemTimer::now()); + }); +}