YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
gpio_esp8266.cpp
1// ---------------------------------------------
2// This file is part of
3// _ _ __ _ _ __ __
4// ( \/ ) /__\ ( )_( ) /__\ ( )
5// \ / /(__)\ ) _ ( /(__)\ )(__
6// (__)(__)(__)(_) (_)(__)(__)(____)
7//
8// Yet Another HW Abstraction Library
9// Copyright (C) Andreas Terstegge
10// BSD Licensed (see file LICENSE)
11//
12// ---------------------------------------------
13//
14// GPIO implementation for ESP8266.
15//
16#include "gpio_esp8266.h"
17#include "ESP8266.h"
18#include <cassert>
19
20using namespace _IO_MUX_;
21
22extern "C"
23{
24#include "ets_sys.h"
25}
26
27const uint8_t gpio_esp8266::GPIO_TO_IOMUX[] = { 12,5,13,4,14,15,6,7,8,9,10,11,0,1,2,3 };
28
29gpio_esp8266::gpio_esp8266(gpio_pin_t gpio)
30: _gpio(gpio)
31{
32 for (int i = 0; i < 16; ++i) {
33 intHandler[i] = 0;
34 intMode[i] = _GPIO_::PIN_INT_TYPE__DISABLE;
35 }
36 ETS_GPIO_INTR_ATTACH(gpio_irq_handler, this);
37 ETS_GPIO_INTR_ENABLE();
38}
39
40void gpio_esp8266::setGpio(gpio_pin_t gpio) {
41 assert(gpio < 16);
42 _gpio = gpio;
43 _mask = 1 << gpio;
44}
45
46gpio_pin_t gpio_esp8266::getGpio() const {
47 return _gpio;
48}
49
50void gpio_esp8266::gpioMode(uint16_t mode) {
51 assert(_gpio < 16);
52
53 // Select GPIO as pin function
54 uint8_t mux_idx = GPIO_TO_IOMUX[_gpio];
55 IO_MUX.ENTRY[mux_idx].FUNC = (mux_idx > 11) ? 1 : 4;
56
57 // Configure basic GPIO modes
58 if (mode & GPIO::INPUT) {
59 IO_MUX.ENTRY[mux_idx].OE = 0;
60 _GPIO_::GPIO.ENABLE_W1TC = _mask;
61 }
62 else if (mode & GPIO::OUTPUT) {
63 IO_MUX.ENTRY[mux_idx].OE = 1;
64 _GPIO_::GPIO.ENABLE_W1TS = _mask;
65 _GPIO_::GPIO.PIN[_gpio].DRIVER = _GPIO_::PIN_DRIVER__PUSH_PULL;
66 }
67 else if (mode & GPIO::OUTPUT_OPEN_DRAIN) {
68 IO_MUX.ENTRY[mux_idx].OE = 1;
69 _GPIO_::GPIO.ENABLE_W1TS = _mask;
70 _GPIO_::GPIO.PIN[_gpio].DRIVER = _GPIO_::PIN_DRIVER__OPEN_DRAIN;
71 }
72 else assert(false);
73
74 IO_MUX.ENTRY[mux_idx].PULLUP = (mode & GPIO::PULLUP) ? 1 : 0;
75 IO_MUX.ENTRY[mux_idx].PULLDOWN = (mode & GPIO::PULLDOWN) ? 1 : 0;
76 if (mode & GPIO::INIT_HIGH) {
77 _GPIO_::GPIO.OUT_W1TS = _mask;
78 }
79 if (mode & GPIO::INIT_LOW) {
80 _GPIO_::GPIO.OUT_W1TC = _mask;
81 }
82}
83
84bool gpio_esp8266::gpioRead() const {
85 assert(_gpio < 16);
86 return (_GPIO_::GPIO.IN.DATA & _mask);
87}
88
89void gpio_esp8266::gpioWrite(bool value) {
90 assert(_gpio < 16);
91 if (value) {
92 _GPIO_::GPIO.OUT_W1TS = _mask;
93 } else {
94 _GPIO_::GPIO.OUT_W1TC = _mask;;
95 }
96}
97
98void gpio_esp8266::gpioToggle() {
99 assert(_gpio < 16);
100 _GPIO_::GPIO.OUT ^= _mask;
101}
102
103void gpio_esp8266::gpioAttachIrq(uint16_t irq_mode,
104 function<void()> handler) {
105 assert(_gpio < 16);
106 intHandler[_gpio] = handler;
107 int esp_mode = _GPIO_::PIN_INT_TYPE__DISABLE;
108 switch (irq_mode)
109 {
110 case GPIO::RISING:
111 esp_mode = _GPIO_::PIN_INT_TYPE__RAISING_EDGE;
112 break;
113 case GPIO::FALLING:
114 esp_mode = _GPIO_::PIN_INT_TYPE__FALLING_EDGE;
115 break;
116 case GPIO::RISING | GPIO::FALLING:
117 esp_mode = _GPIO_::PIN_INT_TYPE__BOTH_EDGES;
118 break;
119 case GPIO::LEVEL_HIGH:
120 esp_mode = _GPIO_::PIN_INT_TYPE__LEVEL_HIGH;
121 break;
122 case GPIO::LEVEL_LOW:
123 esp_mode = _GPIO_::PIN_INT_TYPE__LEVEL_LOW;
124 break;
125 default:
126 assert(false);
127 }
128 intMode[_gpio] = esp_mode;
129 _GPIO_::GPIO.PIN[_gpio].INT_TYPE = esp_mode;
130}
131
132void gpio_esp8266::gpioDetachIrq() {
133 assert(_gpio < 16);
134 gpioDisableIrq();
135 intMode[_gpio] = _GPIO_::PIN_INT_TYPE__DISABLE;
136 intHandler[_gpio] = nullptr;
137}
138
139void gpio_esp8266::gpioEnableIrq() {
140 assert(_gpio < 16);
141 // Clear pending interrupts
142 _GPIO_::GPIO.STATUS_W1TC = (1 << _gpio);
143 _GPIO_::GPIO.PIN[_gpio].INT_TYPE = intMode[_gpio];
144}
145
146void gpio_esp8266::gpioDisableIrq() {
147 assert(_gpio < 16);
148 _GPIO_::GPIO.PIN[_gpio].INT_TYPE = _GPIO_::PIN_INT_TYPE__DISABLE;
149}
150
151void gpio_esp8266::handleInterrupt() {
152 // Acknowledge all pending IRQs
153 uint16_t status = _GPIO_::GPIO.STATUS;
154 _GPIO_::GPIO.STATUS_W1TC = status;
155
156 // Serve all pending IRQs
157 while (uint8_t gpio = __builtin_ffs(status)) {
158 --gpio;
159 status &= ~(1 << gpio);
160 if (intHandler[gpio])
161 intHandler[gpio]();
162 }
163}
164
165void gpio_irq_handler(gpio_esp8266 * gpio) {
166 gpio->handleInterrupt();
167}
168
169void gpio_esp8266::brightnessControl(bool on) {
170 assert(_gpio < 16);
171 if (on) {
172 _GPIO_::GPIO.PIN[_gpio].SOURCE = _GPIO_::PIN_SOURCE__SIGMA_DELTA;
173 } else {
174 _GPIO_::GPIO.PIN[_gpio].SOURCE = _GPIO_::PIN_SOURCE__GPIO;
175 }
176}
177
178void gpio_esp8266::setBrightness(uint8_t value) {
179 _GPIO_::GPIO.SIGMA_DELTA.ENABLE = 1;
180 _GPIO_::GPIO.SIGMA_DELTA.PRESCALE = 0x80;
181 _GPIO_::GPIO.SIGMA_DELTA.TARGET = value;
182}
183