idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
sleep.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
33#include <idfxx/error>
34#include <idfxx/gpio>
35
36#include <chrono>
37#include <concepts>
38#include <cstdint>
39#include <initializer_list>
40#include <optional>
41#include <soc/soc_caps.h>
42#include <string>
43#include <type_traits>
44
45namespace idfxx::sleep {
46
54enum class wakeup_source : int {
55 // clang-format off
56 ext0 = 2,
57 ext1 = 3,
58 timer = 4,
59 touchpad = 5,
60 ulp = 6,
61 gpio = 7,
62 uart = 8,
63 wifi = 9,
64 cocpu = 10,
65 cocpu_trap = 11,
66 bt = 12,
67 other = 13,
68 // clang-format on
69};
70
80
81// =============================================================================
82// Wake-up source specifications
83// =============================================================================
84
92struct timer_wake {
93 std::chrono::microseconds after;
94};
95
111
112#if SOC_PM_SUPPORT_EXT0_WAKEUP
126#endif // SOC_PM_SUPPORT_EXT0_WAKEUP
127
129namespace detail {
130
133constexpr uint64_t pin_mask_of(std::initializer_list<idfxx::gpio> pins) noexcept {
134 uint64_t mask = 0;
135 for (const auto& pin : pins) {
136 if (!pin.is_connected()) {
137 return 0;
138 }
139 mask |= uint64_t{1} << static_cast<unsigned>(pin.num());
140 }
141 return mask;
142}
143
144} // namespace detail
146
147#if SOC_PM_SUPPORT_EXT1_WAKEUP
161enum class ext1_mode : int {
162#if CONFIG_IDF_TARGET_ESP32
163 all_low = 0,
164#else
165 any_low = 0,
166#endif
167 any_high = 1,
168};
169
182public:
190 constexpr ext1_wake(std::initializer_list<idfxx::gpio> pins, enum ext1_mode mode) noexcept
191 : _pin_mask(detail::pin_mask_of(pins))
192 , _mode(mode) {}
193
202 : _pin_mask(pin_mask)
203 , _mode(mode) {}
204
206 [[nodiscard]] constexpr uint64_t pin_mask() const noexcept { return _pin_mask; }
207
209 [[nodiscard]] constexpr enum ext1_mode mode() const noexcept { return _mode; }
210
211private:
212 uint64_t _pin_mask;
213 enum ext1_mode _mode;
214};
215#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
216
217#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
222enum class deep_sleep_gpio_mode : int {
223 wake_low = 0,
224 wake_high = 1,
225};
226
240public:
248 constexpr deep_sleep_gpio_wake(std::initializer_list<idfxx::gpio> pins, deep_sleep_gpio_mode mode) noexcept
249 : _pin_mask(detail::pin_mask_of(pins))
250 , _mode(mode) {}
251
261
263 [[nodiscard]] constexpr uint64_t pin_mask() const noexcept { return _pin_mask; }
264
266 [[nodiscard]] constexpr deep_sleep_gpio_mode mode() const noexcept { return _mode; }
267
268private:
269 uint64_t _pin_mask;
271};
272#endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
273
275namespace detail {
276
277[[nodiscard]] result<void> arm(const timer_wake& source);
278void disarm(const timer_wake& source) noexcept;
279[[nodiscard]] result<void> arm(const gpio_wake& source);
280void disarm(const gpio_wake& source) noexcept;
281#if SOC_PM_SUPPORT_EXT0_WAKEUP
282[[nodiscard]] result<void> arm(const ext0_wake& source);
283void disarm(const ext0_wake& source) noexcept;
284#endif
285#if SOC_PM_SUPPORT_EXT1_WAKEUP
286[[nodiscard]] result<void> arm(const ext1_wake& source);
287void disarm(const ext1_wake& source) noexcept;
288#endif
289#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
290[[nodiscard]] result<void> arm(const deep_sleep_gpio_wake& source);
291void disarm(const deep_sleep_gpio_wake& source) noexcept;
292#endif
293
296
300 result<void> r{};
301 ((r = arm(sources)) && ...);
302 return r;
303}
304
306template<typename... Sources>
307void disarm_all(const Sources&... sources) noexcept {
308 (disarm(sources), ...);
309}
310
311} // namespace detail
313
321template<typename T>
322concept wake_spec = requires(const std::remove_cvref_t<T>& source) {
323 { detail::arm(source) } -> std::same_as<result<void>>;
324 detail::disarm(source);
325};
326
327// =============================================================================
328// Entering sleep
329// =============================================================================
330
331template<wake_spec... Sources>
333
334#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
367template<wake_spec... Sources>
371#endif
372
398template<wake_spec... Sources>
400 if (auto armed = detail::arm_all(sources...); !armed) {
401 detail::disarm_all(sources...);
402 return error(armed.error());
403 }
404 auto cause = detail::do_light_sleep();
405 detail::disarm_all(sources...);
406 return cause;
407}
408
409#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
424[[nodiscard]] wakeup_source light_sleep_for(std::chrono::microseconds duration);
425#endif
426
442[[nodiscard]] result<wakeup_source> try_light_sleep_for(std::chrono::microseconds duration);
443
444template<wake_spec First, wake_spec... Rest>
446
447#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
471template<wake_spec First, wake_spec... Rest>
472[[noreturn]] void deep_sleep(const First& first, const Rest&... rest) {
474 detail::do_deep_sleep(); // unreachable: try_deep_sleep only returns on failure
475}
476#endif
477
497template<wake_spec First, wake_spec... Rest>
499 if (auto armed = detail::arm_all(first, rest...); !armed) {
500 detail::disarm_all(first, rest...);
501 return error(armed.error());
502 }
503 detail::do_deep_sleep();
504}
505
518
533[[noreturn]] void deep_sleep(std::chrono::microseconds duration) noexcept;
534
535// =============================================================================
536// Status
537// =============================================================================
538
560
561#if SOC_PM_SUPPORT_EXT1_WAKEUP
571#endif
572
573// =============================================================================
574// Persistent wake-up source configuration
575// =============================================================================
576
577#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
591template<wake_spec Source>
593 unwrap(detail::arm(source));
594}
595#endif
596
611template<wake_spec Source>
613 return detail::arm(source);
614}
615
616#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
626
634#endif
635
647
654
655} // namespace idfxx::sleep
656
659#include "sdkconfig.h"
660#ifdef CONFIG_IDFXX_STD_FORMAT
662#include <algorithm>
663#include <format>
664namespace std {
665template<>
667 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
668
669 template<typename FormatContext>
670 auto format(idfxx::sleep::wakeup_source source, FormatContext& ctx) const {
671 auto s = to_string(source);
672 return std::copy(s.begin(), s.end(), ctx.out());
673 }
674};
675} // namespace std
677#endif // CONFIG_IDFXX_STD_FORMAT
A GPIO pin.
Definition gpio.hpp:62
level
GPIO output/input level.
Definition gpio.hpp:68
Wakes the chip from deep sleep on levels of one or more pins.
Definition sleep.hpp:239
constexpr deep_sleep_gpio_wake(uint64_t pin_mask, deep_sleep_gpio_mode mode) noexcept
Specifies a deep-sleep GPIO wake on a mask of pins.
Definition sleep.hpp:258
constexpr deep_sleep_gpio_wake(std::initializer_list< idfxx::gpio > pins, deep_sleep_gpio_mode mode) noexcept
Specifies a deep-sleep GPIO wake on a set of pins.
Definition sleep.hpp:248
constexpr deep_sleep_gpio_mode mode() const noexcept
Whether high or low levels trigger the wake.
Definition sleep.hpp:266
constexpr uint64_t pin_mask() const noexcept
Bit mask of GPIO numbers to wake on.
Definition sleep.hpp:263
Wakes the chip on levels of one or more RTC-capable pins (EXT1).
Definition sleep.hpp:181
constexpr ext1_wake(std::initializer_list< idfxx::gpio > pins, enum ext1_mode mode) noexcept
Specifies an EXT1 wake on a set of pins.
Definition sleep.hpp:190
constexpr enum ext1_mode mode() const noexcept
Whether high or low levels trigger the wake.
Definition sleep.hpp:209
constexpr uint64_t pin_mask() const noexcept
Bit mask of GPIO numbers to wake on.
Definition sleep.hpp:206
constexpr ext1_wake(uint64_t pin_mask, enum ext1_mode mode) noexcept
Specifies an EXT1 wake on a mask of pins.
Definition sleep.hpp:201
High-resolution timer with microsecond precision.
Definition timer.hpp:41
A wake-up source specification accepted by the sleep functions.
Definition sleep.hpp:322
uint64_t ext1_wakeup_status() noexcept
Returns the pins that triggered the most recent EXT1 wake.
wakeup_source light_sleep(const Sources &... sources)
Enters light sleep until one of the given wake-up sources triggers.
Definition sleep.hpp:368
std::string to_string(wakeup_source source)
Returns a string representation of a wake-up source.
ext1_mode
EXT1 wake-up trigger mode.
Definition sleep.hpp:161
@ any_low
Wake when any selected pin goes low.
@ any_high
Wake when any selected pin goes high.
result< void > try_disable_wakeup_source(wakeup_source source)
Disarms a previously armed wake-up source.
void disable_wakeup_source(wakeup_source source)
Disarms a previously armed wake-up source.
void disable_all_wakeup_sources()
Disarms every armed wake-up source.
result< void > try_enable_wakeup(const Source &source)
Arms a wake-up source persistently.
Definition sleep.hpp:612
wakeup_source light_sleep_for(std::chrono::microseconds duration)
Enters light sleep for a fixed duration.
std::optional< wakeup_source > wakeup_cause() noexcept
Returns the cause of the most recent wake from sleep.
result< void > try_disable_all_wakeup_sources()
Disarms every armed wake-up source.
deep_sleep_gpio_mode
Trigger level for deep-sleep GPIO wake-up.
Definition sleep.hpp:222
@ wake_low
Wake when a selected pin goes low.
@ wake_high
Wake when a selected pin goes high.
void deep_sleep() noexcept
Enters deep sleep until a previously armed wake-up source triggers.
wakeup_source
Wake-up sources and causes.
Definition sleep.hpp:54
@ cocpu
ULP-RISC-V coprocessor interrupt.
@ wifi
Wi-Fi beacon (light sleep only).
@ bt
Bluetooth activity (light sleep only).
@ ulp
ULP coprocessor program.
@ uart
UART activity (light sleep only).
@ cocpu_trap
ULP-RISC-V coprocessor crash.
@ other
A source not represented in this enumeration (chip-specific).
@ ext0
Level on a single RTC-capable pin (EXT0).
@ ext1
Level on one or more RTC-capable pins (EXT1).
result< wakeup_source > try_light_sleep_for(std::chrono::microseconds duration)
Enters light sleep for a fixed duration.
void enable_wakeup(const Source &source)
Arms a wake-up source persistently.
Definition sleep.hpp:592
result< wakeup_source > try_light_sleep(const Sources &... sources)
Enters light sleep until one of the given wake-up sources triggers.
Definition sleep.hpp:399
result< void > try_deep_sleep(const First &first, const Rest &... rest)
Enters deep sleep until one of the given wake-up sources triggers.
Definition sleep.hpp:498
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
Definition error.hpp:187
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
Wakes the chip when a single RTC-capable pin is at a level (EXT0).
Definition sleep.hpp:122
idfxx::gpio::level level
The level that triggers the wake.
Definition sleep.hpp:124
idfxx::gpio pin
The pin to wake on; must be RTC-capable.
Definition sleep.hpp:123
Wakes the chip from light sleep when a digital pin is at a level.
Definition sleep.hpp:107
idfxx::gpio pin
The pin to wake on.
Definition sleep.hpp:108
idfxx::gpio::level level
The level that triggers the wake.
Definition sleep.hpp:109
Wakes the chip after a fixed duration of sleep.
Definition sleep.hpp:92
std::chrono::microseconds after
Time to sleep before waking.
Definition sleep.hpp:93