// src/sleep/stop.rs

use cortex_m::Peripherals;
use cortex_m::asm;

/// Enter STOPx mode parameter
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub enum StopEntry {
    Wfi,
    Wfe,
    WfeNoEventClear,
}

impl From<StopEntry> for u8 {
    fn from(value: StopEntry) -> Self {
        match value {
            StopEntry::Wfi => 0x01,
            StopEntry::Wfe => 0x02,
            StopEntry::WfeNoEventClear => 0x03,
        }
    }
}

pub fn enter_stop0() {
    unsafe extern "C" {
        fn rust_LL_PWR_SetPowerMode(mode: u32);
    }

    const LL_PWR_STOP0_MODE: u32 = 0; //stm32u5xx_ll_pwr.h

    unsafe {
        rust_LL_PWR_SetPowerMode(LL_PWR_STOP0_MODE);

        let mut core = Peripherals::steal();
        core.SCB.set_sleepdeep();
        asm::wfi();
        core.SCB.clear_sleepdeep();
    }
}

pub fn enter_stop1(entry: StopEntry) {
    unsafe extern "C" {
        fn HAL_PWREx_EnterSTOP1Mode(entry: u8);
    }

    unsafe {
        HAL_PWREx_EnterSTOP1Mode(entry.into());
    }
}

pub fn enter_stop2(entry: StopEntry) {
    unsafe extern "C" {
        fn HAL_PWREx_EnterSTOP2Mode(entry: u8);
    }

    unsafe {
        HAL_PWREx_EnterSTOP2Mode(entry.into());
    }
}

pub fn enter_stop3(entry: StopEntry) {
    unsafe extern "C" {
        fn HAL_PWREx_EnterSTOP3Mode(entry: u8);
    }

    unsafe {
        HAL_PWREx_EnterSTOP3Mode(entry.into());
    }
}
