1 /*
2  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #if __cpp_exceptions
8 
9 #include <array>
10 #include "driver/gpio.h"
11 #include "gpio_cxx.hpp"
12 
13 namespace idf {
14 
15 #define GPIO_CHECK_THROW(err) CHECK_THROW_SPECIFIC((err), GPIOException)
16 
17 namespace {
18 #if CONFIG_IDF_TARGET_LINUX
19 constexpr std::array<uint32_t, 1> INVALID_GPIOS = {24};
20 #elif CONFIG_IDF_TARGET_ESP32
21 constexpr std::array<uint32_t, 1> INVALID_GPIOS = {24};
22 #elif CONFIG_IDF_TARGET_ESP32S2
23 constexpr std::array<uint32_t, 4> INVALID_GPIOS = {22, 23, 24, 25};
24 #elif CONFIG_IDF_TARGET_ESP32S3
25 constexpr std::array<uint32_t, 4> INVALID_GPIOS = {22, 23, 24, 25};
26 #elif CONFIG_IDF_TARGET_ESP32C3
27 constexpr std::array<uint32_t, 0> INVALID_GPIOS = {};
28 #else
29 #error "No GPIOs defined for the current target"
30 #endif
31 
gpio_to_driver_type(const GPIONum & gpio_num)32 gpio_num_t gpio_to_driver_type(const GPIONum &gpio_num)
33 {
34     return static_cast<gpio_num_t>(gpio_num.get_num());
35 }
36 
37 }
38 
GPIOException(esp_err_t error)39 GPIOException::GPIOException(esp_err_t error) : ESPException(error) { }
40 
check_gpio_pin_num(uint32_t pin_num)41 esp_err_t check_gpio_pin_num(uint32_t pin_num) noexcept
42 {
43     if (pin_num >= GPIO_NUM_MAX) {
44         return ESP_ERR_INVALID_ARG;
45     }
46 
47     for (auto num: INVALID_GPIOS)
48     {
49         if (pin_num == num) {
50             return ESP_ERR_INVALID_ARG;
51         }
52     }
53 
54     return ESP_OK;
55 }
56 
check_gpio_drive_strength(uint32_t strength)57 esp_err_t check_gpio_drive_strength(uint32_t strength) noexcept
58 {
59     if (strength >= GPIO_DRIVE_CAP_MAX) {
60         return ESP_ERR_INVALID_ARG;
61     }
62 
63     return ESP_OK;
64 }
65 
FLOATING()66 GPIOPullMode GPIOPullMode::FLOATING()
67 {
68     return GPIOPullMode(GPIO_FLOATING);
69 }
70 
PULLUP()71 GPIOPullMode GPIOPullMode::PULLUP()
72 {
73     return GPIOPullMode(GPIO_PULLUP_ONLY);
74 }
75 
PULLDOWN()76 GPIOPullMode GPIOPullMode::PULLDOWN()
77 {
78     return GPIOPullMode(GPIO_PULLDOWN_ONLY);
79 }
80 
LOW_LEVEL()81 GPIOWakeupIntrType GPIOWakeupIntrType::LOW_LEVEL()
82 {
83     return GPIOWakeupIntrType(GPIO_INTR_LOW_LEVEL);
84 }
85 
HIGH_LEVEL()86 GPIOWakeupIntrType GPIOWakeupIntrType::HIGH_LEVEL()
87 {
88     return GPIOWakeupIntrType(GPIO_INTR_HIGH_LEVEL);
89 }
90 
DEFAULT()91 GPIODriveStrength GPIODriveStrength::DEFAULT()
92 {
93     return MEDIUM();
94 }
95 
WEAK()96 GPIODriveStrength GPIODriveStrength::WEAK()
97 {
98     return GPIODriveStrength(GPIO_DRIVE_CAP_0);
99 }
100 
LESS_WEAK()101 GPIODriveStrength GPIODriveStrength::LESS_WEAK()
102 {
103     return GPIODriveStrength(GPIO_DRIVE_CAP_1);
104 }
105 
MEDIUM()106 GPIODriveStrength GPIODriveStrength::MEDIUM()
107 {
108     return GPIODriveStrength(GPIO_DRIVE_CAP_2);
109 }
110 
STRONGEST()111 GPIODriveStrength GPIODriveStrength::STRONGEST()
112 {
113     return GPIODriveStrength(GPIO_DRIVE_CAP_3);
114 }
115 
GPIOBase(GPIONum num)116 GPIOBase::GPIOBase(GPIONum num) : gpio_num(num)
117 {
118     GPIO_CHECK_THROW(gpio_reset_pin(gpio_to_driver_type(gpio_num)));
119 }
120 
hold_en()121 void GPIOBase::hold_en()
122 {
123     GPIO_CHECK_THROW(gpio_hold_en(gpio_to_driver_type(gpio_num)));
124 }
125 
hold_dis()126 void GPIOBase::hold_dis()
127 {
128     GPIO_CHECK_THROW(gpio_hold_dis(gpio_to_driver_type(gpio_num)));
129 }
130 
set_drive_strength(GPIODriveStrength strength)131 void GPIOBase::set_drive_strength(GPIODriveStrength strength)
132 {
133     GPIO_CHECK_THROW(gpio_set_drive_capability(gpio_to_driver_type(gpio_num),
134             static_cast<gpio_drive_cap_t>(strength.get_strength())));
135 }
136 
GPIO_Output(GPIONum num)137 GPIO_Output::GPIO_Output(GPIONum num) : GPIOBase(num)
138 {
139     GPIO_CHECK_THROW(gpio_set_direction(gpio_to_driver_type(gpio_num), GPIO_MODE_OUTPUT));
140 }
141 
set_high()142 void GPIO_Output::set_high()
143 {
144     GPIO_CHECK_THROW(gpio_set_level(gpio_to_driver_type(gpio_num), 1));
145 }
146 
set_low()147 void GPIO_Output::set_low()
148 {
149     GPIO_CHECK_THROW(gpio_set_level(gpio_to_driver_type(gpio_num), 0));
150 }
151 
get_drive_strength()152 GPIODriveStrength GPIOBase::get_drive_strength()
153 {
154     gpio_drive_cap_t strength;
155     GPIO_CHECK_THROW(gpio_get_drive_capability(gpio_to_driver_type(gpio_num), &strength));
156     return GPIODriveStrength(static_cast<uint32_t>(strength));
157 }
158 
GPIOInput(GPIONum num)159 GPIOInput::GPIOInput(GPIONum num) : GPIOBase(num)
160 {
161     GPIO_CHECK_THROW(gpio_set_direction(gpio_to_driver_type(gpio_num), GPIO_MODE_INPUT));
162 }
163 
get_level() const164 GPIOLevel GPIOInput::get_level() const noexcept
165 {
166     int level = gpio_get_level(gpio_to_driver_type(gpio_num));
167     if (level) {
168         return GPIOLevel::HIGH;
169     } else {
170         return GPIOLevel::LOW;
171     }
172 }
173 
set_pull_mode(GPIOPullMode mode)174 void GPIOInput::set_pull_mode(GPIOPullMode mode)
175 {
176     GPIO_CHECK_THROW(gpio_set_pull_mode(gpio_to_driver_type(gpio_num),
177             static_cast<gpio_pull_mode_t>(mode.get_pull_mode())));
178 }
179 
wakeup_enable(GPIOWakeupIntrType interrupt_type)180 void GPIOInput::wakeup_enable(GPIOWakeupIntrType interrupt_type)
181 {
182     GPIO_CHECK_THROW(gpio_wakeup_enable(gpio_to_driver_type(gpio_num),
183             static_cast<gpio_int_type_t>(interrupt_type.get_level())));
184 }
185 
wakeup_disable()186 void GPIOInput::wakeup_disable()
187 {
188     GPIO_CHECK_THROW(gpio_wakeup_disable(gpio_to_driver_type(gpio_num)));
189 }
190 
GPIO_OpenDrain(GPIONum num)191 GPIO_OpenDrain::GPIO_OpenDrain(GPIONum num) : GPIOInput(num)
192 {
193     GPIO_CHECK_THROW(gpio_set_direction(gpio_to_driver_type(gpio_num), GPIO_MODE_INPUT_OUTPUT_OD));
194 }
195 
set_floating()196 void GPIO_OpenDrain::set_floating()
197 {
198     GPIO_CHECK_THROW(gpio_set_level(gpio_to_driver_type(gpio_num), 1));
199 }
200 
set_low()201 void GPIO_OpenDrain::set_low()
202 {
203     GPIO_CHECK_THROW(gpio_set_level(gpio_to_driver_type(gpio_num), 0));
204 }
205 
206 }
207 
208 #endif
209