#![no_std]
#![no_main]

use esp_hal::{
    prelude::*,
    clock::ClockControl,
    system::SystemControl,
    timer::timg::TimerGroup,
    peripherals::Peripherals,
    gpio::{AnyOutput, Io, Level}
};

use esp_backtrace as _;
use static_cell::StaticCell;
use embassy_executor::Spawner;
use embassy_time::{Duration, Ticker};
use esp_hal_embassy::InterruptExecutor;

#[embassy_executor::task]
async fn led_one( mut pin: AnyOutput<'static>) {
    let mut ticker = Ticker::every(Duration::from_millis(250));
    loop {
        pin.toggle();
        ticker.next().await;
    }
}

#[embassy_executor::task]
async fn led_two( mut pin: AnyOutput<'static>) {
    let mut ticker = Ticker::every(Duration::from_millis(500));
    loop {
        pin.toggle();
        ticker.next().await;
    }
}

#[embassy_executor::task]
async fn led_three( mut pin: AnyOutput<'static>) {
    let mut ticker = Ticker::every(Duration::from_millis(1000));
    loop {
        pin.toggle();
        ticker.next().await;
    }
}

#[main]
async fn main(spawner: Spawner) {
    let peripherals = Peripherals::take();
    let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

    let led1 = AnyOutput::new(io.pins.gpio4, Level::Low);
    let led2 = AnyOutput::new(io.pins.gpio5, Level::Low);
    let led3 = AnyOutput::new(io.pins.gpio6, Level::Low);

    let system = SystemControl::new(peripherals.SYSTEM);
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
    esp_hal_embassy::init(&clocks, timg0);

    static EXECUTOR: StaticCell<InterruptExecutor<2>> = StaticCell::new();
    let executor = InterruptExecutor::new(system.software_interrupt_control.software_interrupt2);
    EXECUTOR.init(executor);

    spawner.must_spawn(led_one(led1));
    spawner.must_spawn(led_two(led2));
    spawner.must_spawn(led_three(led3));
}