//! The chip has two kinds of path. The digital path reads the pad through the high-performance GPIO
//! peripheral. It works on every pad, but it needs that peripheral powered. Every listening pin has
//! this path, because the driver writes the interrupt-enable bit and the wakeup-enable bit of a pin
//! continue to work when the peripheral is powered down. Deep sleep always powers the peripheral
//! down, and light sleep powers it down on request, so such a sleep needs a low-power path. Only
//! The [`path`] module holds the low-power paths of the chip, and divides the pins between them.
//! This module also isolates the digital pads before a deep sleep, because it holds the pad tables.
//! restores it. The hooks still use the [`ram`][crate::ram] attribute, to keep the flash out of the
/// listen is not a wakeup source.** A pin that listens wakes the chip from light sleep through the
/// A pad that is already at its wake level when the sleep starts ends the sleep immediately. The
/// configuration of the pin must hold the pad at the other level. Sleep keeps the pull resistors
/// A level-triggered wake pin needs a pull against the level that wakes the chip, or an external
/// Hardware records the digital path, in the wakeup-enable bit of the pad. No low-power register
/// per-pin low-power register. This record is therefore in software. It does not have to survive a
/// A sleep that ends without a reset has to undo the preparation. A light sleep is such a sleep,
/// Each path reports through a status that other code clears or overwrites later. The digital path
/// has no status of its own, only the interrupt of the pin, which the interrupt handler of the pin
/// [`record_wakeup`] therefore reads all the statuses when the sleep ends, and [`caused_wakeup`]
(LP_GPIOn $( (($_sig:ident, LP_GPIOn, $lp:literal), $gpio:ident, $_af:ident, $_in:tt $_out:tt) ),*) => {
pub(crate) fn apply_config(pin: &AnyPin<'_>, config: &WakeupConfig) -> Result<(), WakeConfigError> {
/// A sleep ends in one of two places: at the end of a light sleep, and in the sleep initialization
/// `listen` writes, or a low-power path that the entry hook assigns. If no pin can wake the chip,
/// the entry hook clears the mask bit again. A sleep with no other wakeup source is then refused,
/// Returns the number that the low-power registers use for `gpio`, or `None` if they do not reach
/// Returns every pad that the low-power registers reach, as a pin number and a low-power number.
/// Call this before the initialization clears the mask. The result tells the initialization whether
/// A deep sleep holds its wake pads, because it powers down the circuit that drives them. The wake
/// resets the chip, but it does not release the hold: the hold register is in the always-on domain.
/// The function releases the hold, and changes nothing else. A change of a pad function can take a
/// Assigns the listening pins to the hardware paths, and requests the power domains that they need.
/// A light sleep is such a sleep, and so is a deep sleep that the hardware rejects. The hooks of a
/// Returns the level that wakes the chip through this pad, or `None` if the trigger sets no level.
/// The wake paths accept a level only, so an edge trigger becomes the level at the end of the edge.
/// which is the meaning of "wake when the pin changes". This read of the pin can race with the pin,
/// but the result is safe. If the pin changes before the sleep starts, the path arms a level that
/// Moves the pad to the low-power IO MUX, which makes it readable while the high-performance GPIO
/// Before a deep sleep this function also holds the pad, because deep sleep powers down the circuit
/// that drives it. A light sleep does not hold the pad. A light sleep powers down no circuit that
// The low-power IO MUX has its own pull resistors, and the digital ones stop to work as soon as
/// Disconnects the pads that no hold keeps, so that a powered-down output driver does not increase
/// `esp_sleep_isolate_digital_gpio` in ESP-IDF. The step is destructive, because a pad loses the
/// peripheral function that drove it. It therefore runs at sleep entry, on the chips that cannot
/// hold a single pad through a deep sleep, and after the wakeup sources take the holds that they
/// ESP-IDF does this when `SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD` is set. The chip can still hold a
/// single pad, so a held pad is left alone. The pad list comes from `for_each_gpio_soft_isolate`,
/// Disconnects one digital pad so that a powered-down driver does not increase the sleep current.