//! Template project for Rust on ESP32 (`no_std`) based on [`esp-hal`](https://github.com/esp-rs/esp-hal)
//!
//! Useful resources:
//! - [The Rust on ESP Book](https://docs.esp-rs.org/book/)
//! - [Embedded Rust (no_std) on Espressif](https://docs.esp-rs.org/no_std-training/)
//! - [Matrix channel](https://matrix.to/#/#esp-rs:matrix.org)

#![no_std]
#![no_main]

use esp_backtrace as _;
use esp_hal::ledc::channel::config::Config as ChannelConfig;
use esp_hal::ledc::channel::Number as ChannelNumber;

use esp_hal::ledc::timer::config::Config as TimerConfig;
use esp_hal::ledc::timer::Number as TimerNumber;

use core::cell::RefCell;
use core::sync::atomic::AtomicBool;
use core::sync::atomic::Ordering;
use critical_section::with;
use critical_section::Mutex;
use esp_hal::delay::Delay;
use esp_hal::gpio::Event;
use esp_hal::gpio::Input;
use esp_hal::gpio::Io;
use esp_hal::gpio::Level;
use esp_hal::gpio::Output;
use esp_hal::gpio::Pull;
use esp_hal::ledc::channel::config::PinConfig;
use esp_hal::ledc::timer::config::Duty;
use esp_hal::ledc::timer::LSClockSource;
use esp_hal::ledc::LSGlobalClkSource;
use esp_hal::ledc::Ledc;
use esp_hal::prelude::*;
use esp_hal::rng::Rng;
use log::info;
use log::warn;

pub static COLORS: [(u8, u8, u8); 7] = [
    (100, 0, 0), 
    (100, 50, 0),  
    (100, 100, 0), 
    (0, 100, 0),   
    (0, 0, 100),   
    (50, 0, 100),  
    (100, 0, 100), 
];
static BUTTON_0: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
static LED_0: Mutex<RefCell<Option<Output>>> = Mutex::new(RefCell::new(None));
// static LED_FLAG: Mutex<RefCell<bool>> = Mutex::new(RefCell::new(false));
static LED_FLAG: AtomicBool = AtomicBool::new(false);

#[entry]
fn main() -> ! {
    esp_println::logger::init_logger_from_env();

    info!("SYSTEM INIT...");
    let perp = esp_hal::init(esp_hal::Config::default());
    let delay = Delay::new();

    info!("IO PINS INIT...");
    let mut io = Io::new(perp.IO_MUX);
    io.set_interrupt_handler(interrupt_handler);

    info!("LED0 INIT...");
    let led0 = Output::new(perp.GPIO18, Level::Low);

    info!("BUTTON(KEY2) INIT...");
    let mut button = Input::new(perp.GPIO6, Pull::Up);

    info!("INTERRUPTER INIT...");

    with(|cs| {
        button.listen(Event::FallingEdge);
        BUTTON_0.borrow_ref_mut(cs).replace(button);
        LED_0.borrow_ref_mut(cs).replace(led0);
    });

    info!("LEDC INIT...");
    let mut ledc = Ledc::new(perp.LEDC);
    ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);
    let mut low_speed_timer0 = ledc.timer(TimerNumber::Timer0);
    low_speed_timer0
        .configure(TimerConfig {
            duty:         Duty::Duty5Bit,
            clock_source: LSClockSource::APBClk,
            frequency:    24u32.kHz(),
        })
        .unwrap();
    let mut blue_chann = ledc.channel(ChannelNumber::Channel0, perp.GPIO3);
    let mut red_chann = ledc.channel(ChannelNumber::Channel1, perp.GPIO4);
    let mut green_chann = ledc.channel(ChannelNumber::Channel2, perp.GPIO5);

    blue_chann
        .configure(ChannelConfig {
            timer:      &low_speed_timer0,
            duty_pct:   100,
            pin_config: PinConfig::PushPull,
        })
        .unwrap();
    red_chann
        .configure(ChannelConfig {
            timer:      &low_speed_timer0,
            duty_pct:   100,
            pin_config: PinConfig::PushPull,
        })
        .unwrap();
    green_chann
        .configure(ChannelConfig {
            timer:      &low_speed_timer0,
            duty_pct:   100,
            pin_config: PinConfig::PushPull,
        })
        .unwrap();

    info!("RANDOM NUMBER GENERATOR INIT...");
    let _rng = Rng::new(perp.RNG);

    let mut color_idx = 0;
    loop {
        info!("LOOP...");
        with(|cs| {
            // let led_flag = LED_FLAG.borrow(cs).borrow();

            let led_flag = LED_FLAG.load(Ordering::SeqCst);
            if led_flag {
                let (r, g, b) = COLORS[color_idx];
                info!("COLOR R: {}, G: {}, B: {}", r, g, b);
                green_chann.set_duty(g).unwrap();
                red_chann.set_duty(r).unwrap();
                blue_chann.set_duty(b).unwrap();
                color_idx = (color_idx + 1) % COLORS.len();
            } else {
                green_chann.set_duty(0).unwrap();
                red_chann.set_duty(0).unwrap();
                blue_chann.set_duty(0).unwrap()
            }
        });
        delay.delay_millis(1000);
    }
}

#[handler]
fn interrupt_handler() {
    with(|cs| {
        warn!("GPIO INTERRUPT");
        warn!("TRUN OFF THE RGB LIGHT");
        if let Some(led) = LED_0.borrow_ref_mut(cs).as_mut() {
            led.toggle();
        } else {
            warn!("LED_0 TOGGLE FAILED");
        }
        if let Some(button) = BUTTON_0.borrow_ref_mut(cs).as_mut() {
            button.clear_interrupt();
        } else {
            warn!("BUTTON CLEAR INTERRUPT FAILED");
        }

        // let mut led_flag = LED_FLAG.borrow(cs).borrow_mut();
        // *led_flag = !(*led_flag);
        LED_FLAG.store(!LED_FLAG.load(Ordering::SeqCst), Ordering::SeqCst)
    });
}

Loading
esp32-c3-devkitm-1