ESPHome 2026.1.4
Loading...
Searching...
No Matches
gpio.cpp
Go to the documentation of this file.
1#ifdef USE_ESP8266
2
3#include "gpio.h"
4#include "esphome/core/log.h"
5
6namespace esphome::esp8266 {
7
8static const char *const TAG = "esp8266";
9
10static int flags_to_mode(gpio::Flags flags, uint8_t pin) {
12 return OUTPUT;
13 }
14 if (flags == gpio::FLAG_INPUT) {
15 return INPUT;
16 }
18 if (pin == 16) {
19 // GPIO16 doesn't have a pullup, so pinMode would fail.
20 // However, sometimes this method is called with pullup mode anyway
21 // for example from dallas one_wire. For those cases convert this
22 // to a INPUT mode.
23 return INPUT;
24 }
25 return INPUT_PULLUP;
26 }
28 return INPUT_PULLDOWN_16;
29 }
31 return OUTPUT_OPEN_DRAIN;
32 }
33 return INPUT;
34}
35
36struct ISRPinArg {
37 uint8_t pin;
38 bool inverted;
39 volatile uint32_t *in_reg;
40 volatile uint32_t *out_set_reg;
41 volatile uint32_t *out_clr_reg;
42 volatile uint32_t *mode_set_reg;
43 volatile uint32_t *mode_clr_reg;
44 volatile uint32_t *func_reg;
45 volatile uint32_t *control_reg;
46 uint32_t mask;
47};
48
50 auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
51 arg->pin = this->pin_;
52 arg->inverted = this->inverted_;
53 if (this->pin_ < 16) {
54 arg->in_reg = &GPI;
55 arg->out_set_reg = &GPOS;
56 arg->out_clr_reg = &GPOC;
57 arg->mode_set_reg = &GPES;
58 arg->mode_clr_reg = &GPEC;
59 arg->func_reg = &GPF(this->pin_);
60 arg->control_reg = &GPC(this->pin_);
61 arg->mask = 1 << this->pin_;
62 } else {
63 arg->in_reg = &GP16I;
64 arg->out_set_reg = &GP16O;
65 arg->out_clr_reg = nullptr;
66 arg->mode_set_reg = &GP16E;
67 arg->mode_clr_reg = nullptr;
68 arg->func_reg = &GPF16;
69 arg->control_reg = nullptr;
70 arg->mask = 1;
71 }
72 return ISRInternalGPIOPin((void *) arg);
73}
74
75void ESP8266GPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
76 uint8_t arduino_mode = 0;
77 switch (type) {
79 arduino_mode = inverted_ ? FALLING : RISING;
80 break;
82 arduino_mode = inverted_ ? RISING : FALLING;
83 break;
85 arduino_mode = CHANGE;
86 break;
88 arduino_mode = inverted_ ? ONHIGH : ONLOW;
89 break;
91 arduino_mode = inverted_ ? ONLOW : ONHIGH;
92 break;
93 }
94
95 attachInterruptArg(pin_, func, arg, arduino_mode);
96}
98 pinMode(pin_, flags_to_mode(flags, pin_)); // NOLINT
99}
100
101size_t ESP8266GPIOPin::dump_summary(char *buffer, size_t len) const {
102 return snprintf(buffer, len, "GPIO%u", this->pin_);
103}
104
106 return bool(digitalRead(pin_)) != inverted_; // NOLINT
107}
109 digitalWrite(pin_, value != inverted_ ? 1 : 0); // NOLINT
110}
111void ESP8266GPIOPin::detach_interrupt() const { detachInterrupt(pin_); }
112
113} // namespace esphome::esp8266
114
115namespace esphome {
116
117using esp8266::ISRPinArg;
118
119bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
120 auto *arg = reinterpret_cast<ISRPinArg *>(this->arg_);
121 return bool(*arg->in_reg & arg->mask) != arg->inverted;
122}
123
124void IRAM_ATTR ISRInternalGPIOPin::digital_write(bool value) {
125 auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
126 if (arg->pin < 16) {
127 if (value != arg->inverted) {
128 *arg->out_set_reg = arg->mask;
129 } else {
130 *arg->out_clr_reg = arg->mask;
131 }
132 } else {
133 if (value != arg->inverted) {
134 *arg->out_set_reg = *arg->out_set_reg | 1;
135 } else {
136 *arg->out_set_reg = *arg->out_set_reg & ~1;
137 }
138 }
139}
140
142 auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
143 GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1UL << arg->pin);
144}
145
147 auto *arg = reinterpret_cast<ISRPinArg *>(this->arg_);
148 if (arg->pin < 16) {
149 if (flags & gpio::FLAG_OUTPUT) {
150 *arg->mode_set_reg = arg->mask;
152 *arg->control_reg = *arg->control_reg | (1 << GPCD);
153 } else {
154 *arg->control_reg &= ~(1 << GPCD);
155 }
156 } else if (flags & gpio::FLAG_INPUT) {
157 *arg->mode_clr_reg = arg->mask;
158 }
159 if (flags & gpio::FLAG_PULLUP) {
160 *arg->func_reg = *arg->func_reg | (1 << GPFPU);
161 *arg->control_reg = *arg->control_reg | (1 << GPCD);
162 } else {
163 *arg->func_reg = *arg->func_reg & ~(1 << GPFPU);
164 }
165 } else {
166 if (flags & gpio::FLAG_OUTPUT) {
167 *arg->mode_set_reg = *arg->mode_set_reg | 1;
168 } else {
169 *arg->mode_set_reg = *arg->mode_set_reg & ~1;
170 }
172 *arg->func_reg = *arg->func_reg | (1 << GP16FPD);
173 } else {
174 *arg->func_reg = *arg->func_reg & ~(1 << GP16FPD);
175 }
176 }
177}
178
179} // namespace esphome
180
181#endif // USE_ESP8266
Copy of GPIOPin that is safe to use from ISRs (with no virtual functions)
Definition gpio.h:92
void digital_write(bool value)
Definition gpio.cpp:148
void pin_mode(gpio::Flags flags)
Definition gpio.cpp:157
bool digital_read() override
Definition gpio.cpp:105
ISRInternalGPIOPin to_isr() const override
Definition gpio.cpp:49
void digital_write(bool value) override
Definition gpio.cpp:108
void attach_interrupt(void(*func)(void *), void *arg, gpio::InterruptType type) const override
Definition gpio.cpp:75
void detach_interrupt() const override
Definition gpio.cpp:111
void pin_mode(gpio::Flags flags) override
Definition gpio.cpp:97
size_t dump_summary(char *buffer, size_t len) const override
Definition gpio.cpp:101
uint16_t type
uint16_t flags
@ INTERRUPT_FALLING_EDGE
Definition gpio.h:51
@ INTERRUPT_RISING_EDGE
Definition gpio.h:50
@ INTERRUPT_HIGH_LEVEL
Definition gpio.h:54
@ INTERRUPT_LOW_LEVEL
Definition gpio.h:53
@ INTERRUPT_ANY_EDGE
Definition gpio.h:52
@ FLAG_OUTPUT
Definition gpio.h:28
@ FLAG_OPEN_DRAIN
Definition gpio.h:29
@ FLAG_PULLUP
Definition gpio.h:30
@ FLAG_INPUT
Definition gpio.h:27
@ FLAG_PULLDOWN
Definition gpio.h:31
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:595