#![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::{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(); let sys = p.SYSTEM.split(); let clocks = ClockControl::boot_defaults(sys.clock_control).freeze(); let mut ledc = LEDC::new(p.LEDC, &clocks); ledc.set_global_slow_clock(LSGlobalClkSource::APBClk); let mut timer = ledc.get_timer(timer::Number::Timer0); timer .configure(timer::config::Config { clock_source: timer::LSClockSource::APBClk, duty: timer::config::Duty::Duty8Bit, frequency: 24.kHz(), }) .unwrap(); 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, io.pins.gpio5.into_push_pull_output(), ); let mut g = ledc.get_channel( channel::Number::Channel1, io.pins.gpio6.into_push_pull_output(), ); let mut b = ledc.get_channel( channel::Number::Channel2, io.pins.gpio7.into_push_pull_output(), ); r.configure(channel::config::Config { duty_pct: 0, pin_config: channel::config::PinConfig::PushPull, timer: &timer, }) .unwrap(); g.configure(channel::config::Config { duty_pct: 0, pin_config: channel::config::PinConfig::PushPull, timer: &timer, }) .unwrap(); b.configure(channel::config::Config { duty_pct: 0, pin_config: channel::config::PinConfig::PushPull, timer: &timer, }) .unwrap(); io.pins.gpio9.into_pull_up_input().listen(Event::RisingEdge); let delay = Delay::new(&clocks); 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()); }); }