ESPHome  2024.3.1
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 
6 namespace esphome {
7 namespace esp8266 {
8 
9 static const char *const TAG = "esp8266";
10 
11 static int IRAM_ATTR flags_to_mode(gpio::Flags flags, uint8_t pin) {
12  if (flags == gpio::FLAG_INPUT) { // NOLINT(bugprone-branch-clone)
13  return INPUT;
14  } else if (flags == gpio::FLAG_OUTPUT) {
15  return OUTPUT;
16  } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
17  if (pin == 16) {
18  // GPIO16 doesn't have a pullup, so pinMode would fail.
19  // However, sometimes this method is called with pullup mode anyway
20  // for example from dallas one_wire. For those cases convert this
21  // to a INPUT mode.
22  return INPUT;
23  }
24  return INPUT_PULLUP;
25  } else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) {
26  return INPUT_PULLDOWN_16;
27  } else if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) {
28  return OUTPUT_OPEN_DRAIN;
29  } else {
30  return 0;
31  }
32 }
33 
34 struct ISRPinArg {
35  uint8_t pin;
36  bool inverted;
37 };
38 
40  auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
41  arg->pin = pin_;
42  arg->inverted = inverted_;
43  return ISRInternalGPIOPin((void *) arg);
44 }
45 
46 void ESP8266GPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
47  uint8_t arduino_mode = 0;
48  switch (type) {
50  arduino_mode = inverted_ ? FALLING : RISING;
51  break;
53  arduino_mode = inverted_ ? RISING : FALLING;
54  break;
56  arduino_mode = CHANGE;
57  break;
59  arduino_mode = inverted_ ? ONHIGH : ONLOW;
60  break;
62  arduino_mode = inverted_ ? ONLOW : ONHIGH;
63  break;
64  }
65 
66  attachInterruptArg(pin_, func, arg, arduino_mode);
67 }
69  pinMode(pin_, flags_to_mode(flags, pin_)); // NOLINT
70 }
71 
72 std::string ESP8266GPIOPin::dump_summary() const {
73  char buffer[32];
74  snprintf(buffer, sizeof(buffer), "GPIO%u", pin_);
75  return buffer;
76 }
77 
79  return bool(digitalRead(pin_)) != inverted_; // NOLINT
80 }
82  digitalWrite(pin_, value != inverted_ ? 1 : 0); // NOLINT
83 }
84 void ESP8266GPIOPin::detach_interrupt() const { detachInterrupt(pin_); }
85 
86 } // namespace esp8266
87 
88 using namespace esp8266;
89 
90 bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
91  auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
92  return bool(digitalRead(arg->pin)) != arg->inverted; // NOLINT
93 }
94 void IRAM_ATTR ISRInternalGPIOPin::digital_write(bool value) {
95  auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
96  digitalWrite(arg->pin, value != arg->inverted ? 1 : 0); // NOLINT
97 }
98 void IRAM_ATTR ISRInternalGPIOPin::clear_interrupt() {
99  auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
100  GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1UL << arg->pin);
101 }
102 void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) {
103  auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
104  pinMode(arg->pin, flags_to_mode(flags, arg->pin)); // NOLINT
105 }
106 
107 } // namespace esphome
108 
109 #endif // USE_ESP8266
Copy of GPIOPin that is safe to use from ISRs (with no virtual functions)
Definition: gpio.h:66
void detach_interrupt() const override
Definition: gpio.cpp:84
void pin_mode(gpio::Flags flags) override
Definition: gpio.cpp:68
bool digital_read() override
Definition: gpio.cpp:78
void pin_mode(gpio::Flags flags)
Definition: gpio.cpp:128
uint8_t type
ISRInternalGPIOPin to_isr() const override
Definition: gpio.cpp:39
const uint32_t flags
Definition: stm32flash.h:85
InterruptType
Definition: gpio.h:40
void digital_write(bool value) override
Definition: gpio.cpp:81
std::string dump_summary() const override
Definition: gpio.cpp:72
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void digital_write(bool value)
Definition: gpio.cpp:121
void attach_interrupt(void(*func)(void *), void *arg, gpio::InterruptType type) const override
Definition: gpio.cpp:46