1 /*
2  * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/kernel.h>
7 #include <zephyr/drivers/gpio.h>
8 #include <zephyr/sys/poweroff.h>
9 #include <esp_sleep.h>
10 #include <driver/rtc_io.h>
11 
12 #define WAKEUP_TIME_SEC		(20)
13 
14 #ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
15 #define EXT_WAKEUP_PIN_1	(2)
16 #define EXT_WAKEUP_PIN_2	(4)
17 #endif
18 
19 #ifdef CONFIG_EXAMPLE_GPIO_WAKEUP
20 #if !DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(wakeup_button))
21 #error "Unsupported: wakeup-button alias is not defined"
22 #else
23 static const struct gpio_dt_spec wakeup_button = GPIO_DT_SPEC_GET(DT_ALIAS(wakeup_button), gpios);
24 #endif
25 #endif
26 
main(void)27 int main(void)
28 {
29 	switch (esp_sleep_get_wakeup_cause()) {
30 #ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
31 	case ESP_SLEEP_WAKEUP_EXT1:
32 	{
33 		uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status();
34 
35 		if (wakeup_pin_mask != 0) {
36 			int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
37 
38 			printk("Wake up from GPIO %d\n", pin);
39 		} else {
40 			printk("Wake up from GPIO\n");
41 		}
42 		break;
43 	}
44 #endif /* CONFIG_EXAMPLE_EXT1_WAKEUP */
45 #ifdef CONFIG_EXAMPLE_GPIO_WAKEUP
46 	case ESP_SLEEP_WAKEUP_GPIO:
47 	{
48 		uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status();
49 
50 		if (wakeup_pin_mask != 0) {
51 			int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
52 
53 			printk("Wake up from GPIO %d\n", pin);
54 		} else {
55 			printk("Wake up from GPIO\n");
56 		}
57 		break;
58 	}
59 #endif /* CONFIG_EXAMPLE_GPIO_WAKEUP */
60 	case ESP_SLEEP_WAKEUP_TIMER:
61 		printk("Wake up from timer.\n");
62 		break;
63 	case ESP_SLEEP_WAKEUP_UNDEFINED:
64 	default:
65 		printk("Not a deep sleep reset\n");
66 	}
67 
68 	k_busy_wait(1000000);
69 
70 	const int wakeup_time_sec = WAKEUP_TIME_SEC;
71 
72 	printk("Enabling timer wakeup, %ds\n", wakeup_time_sec);
73 	esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
74 
75 #ifdef CONFIG_EXAMPLE_EXT1_WAKEUP
76 	const int ext_wakeup_pin_1 = EXT_WAKEUP_PIN_1;
77 	const uint64_t ext_wakeup_pin_1_mask = BIT64(ext_wakeup_pin_1);
78 	const int ext_wakeup_pin_2 = EXT_WAKEUP_PIN_2;
79 	const uint64_t ext_wakeup_pin_2_mask = BIT64(ext_wakeup_pin_2);
80 
81 	printk("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n",
82 			ext_wakeup_pin_1, ext_wakeup_pin_2);
83 	esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask,
84 			ESP_EXT1_WAKEUP_ANY_HIGH);
85 
86 	/* enable pull-down on ext1 pins to avoid random wake-ups */
87 	rtc_gpio_pullup_dis(EXT_WAKEUP_PIN_1);
88 	rtc_gpio_pulldown_en(EXT_WAKEUP_PIN_1);
89 	rtc_gpio_pullup_dis(EXT_WAKEUP_PIN_2);
90 	rtc_gpio_pulldown_en(EXT_WAKEUP_PIN_2);
91 #endif /* CONFIG_EXAMPLE_EXT1_WAKEUP */
92 #ifdef CONFIG_EXAMPLE_GPIO_WAKEUP
93 	if (!gpio_is_ready_dt(&wakeup_button)) {
94 		printk("Error: wakeup button device %s is not ready\n", wakeup_button.port->name);
95 		return 0;
96 	}
97 
98 	int ret = gpio_pin_configure_dt(&wakeup_button, GPIO_INPUT);
99 
100 	if (ret != 0) {
101 		printk("Error %d: failed to configure %s pin %d\n",
102 				ret, wakeup_button.port->name, wakeup_button.pin);
103 		return 0;
104 	}
105 
106 	esp_deep_sleep_enable_gpio_wakeup(BIT(wakeup_button.pin), ESP_GPIO_WAKEUP_GPIO_HIGH);
107 	printk("Enabling GPIO wakeup on pins GPIO%d\n", wakeup_button.pin);
108 #endif /* CONFIG_EXAMPLE_GPIO_WAKEUP */
109 
110 	printk("Powering off\n");
111 	sys_poweroff();
112 
113 	return 0;
114 }
115