arduino-esp32/cores/esp32/esp32-hal-gpio.c
Rodrigo Garcia 99e68a0518
Change "neopixel" references to use RGB LED naming (#10225)
* fix(rgbled): fixes core rgbledWrite()

* fix(rgbled): fixes examples - rgbledWrite()

* fix(rgbled): fixes variants commetaries - rgbledWrite()

* fix(rgbled): examples and doc - use RGB_LED naming

* fix(rgbled): variants - use RGB_LED naming

* fix(rgbled): other places for RGB LED naming

* fix(typo): cores - rgbLed instead of rgbled

* fix(typo): examples - rgbLed instead of rgbled

* fix(typo): variants commentaties - rgbLed instead of rgbled

* fix(rgbled): bad file name

* fix(typo): typo and commentaries

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>

* fix(rgbled): deprecating neopixelWrite()

* fix(rgbled): use RGB LED naming

* fix(rgbled): document formatting

* fix(rgbled): neopixelWrite() is now deprecated

* fix(rgbled): removed attribute in wrong place

* just a git push test

* restart git bash test

* ci(pre-commit): Apply automatic fixes

* removed wrong test file

* fix(rgbled): new Arduino style depreacted attribute

---------

Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2024-08-28 09:53:24 +03:00

282 lines
8.7 KiB
C

// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp32-hal-gpio.h"
#include "esp32-hal-periman.h"
#include "hal/gpio_hal.h"
#include "soc/soc_caps.h"
// RGB_BUILTIN is defined in pins_arduino.h
// If RGB_BUILTIN is defined, it will be used as a pin number for the RGB LED
// If RGB_BUILTIN has a side effect that prevents using RMT Legacy driver in IDF 5.1
// Define ESP32_ARDUINO_NO_RGB_BUILTIN in build_opt.h or through CLI to disable RGB_BUILTIN
#ifdef ESP32_ARDUINO_NO_RGB_BUILTIN
#ifdef RGB_BUILTIN
#undef RGB_BUILTIN
#endif
#endif
// It fixes lack of pin definition for S3 and for any future SoC
// this function works for ESP32, ESP32-S2 and ESP32-S3 - including the C3, it will return -1 for any pin
#if SOC_TOUCH_SENSOR_NUM > 0
#include "soc/touch_sensor_periph.h"
int8_t digitalPinToTouchChannel(uint8_t pin) {
int8_t ret = -1;
if (pin < SOC_GPIO_PIN_COUNT) {
for (uint8_t i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
if (touch_sensor_channel_io_map[i] == pin) {
ret = i;
break;
}
}
}
return ret;
}
#else
// No Touch Sensor available
int8_t digitalPinToTouchChannel(uint8_t pin) {
return -1;
}
#endif
#ifdef SOC_ADC_SUPPORTED
#include "soc/adc_periph.h"
int8_t digitalPinToAnalogChannel(uint8_t pin) {
uint8_t channel = 0;
if (pin < SOC_GPIO_PIN_COUNT) {
for (uint8_t i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
for (uint8_t j = 0; j < SOC_ADC_MAX_CHANNEL_NUM; j++) {
if (adc_channel_io_map[i][j] == pin) {
return channel;
}
channel++;
}
}
}
return -1;
}
int8_t analogChannelToDigitalPin(uint8_t channel) {
if (channel >= (SOC_ADC_PERIPH_NUM * SOC_ADC_MAX_CHANNEL_NUM)) {
return -1;
}
uint8_t adc_unit = (channel / SOC_ADC_MAX_CHANNEL_NUM);
uint8_t adc_chan = (channel % SOC_ADC_MAX_CHANNEL_NUM);
return adc_channel_io_map[adc_unit][adc_chan];
}
#else
// No Analog channels available
int8_t analogChannelToDigitalPin(uint8_t channel) {
return -1;
}
#endif
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void *);
typedef struct {
voidFuncPtr fn;
void *arg;
bool functional;
} InterruptHandle_t;
static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {
0,
};
#include "driver/rtc_io.h"
static bool gpioDetachBus(void *bus) {
return true;
}
extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode) {
#ifdef RGB_BUILTIN
if (pin == RGB_BUILTIN) {
__pinMode(RGB_BUILTIN - SOC_GPIO_PIN_COUNT, mode);
return;
}
#endif
if (pin >= SOC_GPIO_PIN_COUNT) {
log_e("Invalid IO %i selected", pin);
return;
}
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) {
perimanSetBusDeinit(ESP32_BUS_TYPE_GPIO, gpioDetachBus);
if (!perimanClearPinBus(pin)) {
log_e("Deinit of previous bus from IO %i failed", pin);
return;
}
}
gpio_hal_context_t gpiohal;
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
gpio_config_t conf = {
.pin_bit_mask = (1ULL << pin), /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
.mode = GPIO_MODE_DISABLE, /*!< GPIO mode: set input/output mode */
.pull_up_en = GPIO_PULLUP_DISABLE, /*!< GPIO pull-up */
.pull_down_en = GPIO_PULLDOWN_DISABLE, /*!< GPIO pull-down */
.intr_type = gpiohal.dev->pin[pin].int_type /*!< GPIO interrupt type - previously set */
};
if (mode < 0x20) { //io
conf.mode = mode & (INPUT | OUTPUT);
if (mode & OPEN_DRAIN) {
conf.mode |= GPIO_MODE_DEF_OD;
}
if (mode & PULLUP) {
conf.pull_up_en = GPIO_PULLUP_ENABLE;
}
if (mode & PULLDOWN) {
conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
}
}
if (gpio_config(&conf) != ESP_OK) {
log_e("IO %i config failed", pin);
return;
}
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) == NULL) {
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_GPIO, (void *)(pin + 1), -1, -1)) {
//gpioDetachBus((void *)(pin+1));
return;
}
}
}
#ifdef RGB_BUILTIN
uint8_t RGB_BUILTIN_storage = 0;
#endif
extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
#ifdef RGB_BUILTIN
if (pin == RGB_BUILTIN) {
//use RMT to set all channels on/off
RGB_BUILTIN_storage = val;
const uint8_t comm_val = val != 0 ? RGB_BRIGHTNESS : 0;
rgbLedWrite(RGB_BUILTIN, comm_val, comm_val, comm_val);
return;
}
#endif // RGB_BUILTIN
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
gpio_set_level((gpio_num_t)pin, val);
} else {
log_e("IO %i is not set as GPIO.", pin);
}
}
extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin) {
#ifdef RGB_BUILTIN
if (pin == RGB_BUILTIN) {
return RGB_BUILTIN_storage;
}
#endif
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_GPIO) != NULL) {
return gpio_get_level((gpio_num_t)pin);
} else {
log_e("IO %i is not set as GPIO.", pin);
return 0;
}
}
static void ARDUINO_ISR_ATTR __onPinInterrupt(void *arg) {
InterruptHandle_t *isr = (InterruptHandle_t *)arg;
if (isr->fn) {
if (isr->arg) {
((voidFuncPtrArg)isr->fn)(isr->arg);
} else {
isr->fn();
}
}
}
extern void cleanupFunctional(void *arg);
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void *arg, int intr_type, bool functional) {
static bool interrupt_initialized = false;
// makes sure that pin -1 (255) will never work -- this follows Arduino standard
if (pin >= SOC_GPIO_PIN_COUNT) {
return;
}
if (!interrupt_initialized) {
esp_err_t err = gpio_install_isr_service((int)ARDUINO_ISR_FLAG);
interrupt_initialized = (err == ESP_OK) || (err == ESP_ERR_INVALID_STATE);
}
if (!interrupt_initialized) {
log_e("IO %i ISR Service Failed To Start", pin);
return;
}
// if new attach without detach remove old info
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) {
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc;
__pinInterruptHandlers[pin].arg = arg;
__pinInterruptHandlers[pin].functional = functional;
gpio_set_intr_type((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
if (intr_type & 0x8) {
gpio_wakeup_enable((gpio_num_t)pin, (gpio_int_type_t)(intr_type & 0x7));
}
gpio_isr_handler_add((gpio_num_t)pin, __onPinInterrupt, &__pinInterruptHandlers[pin]);
//FIX interrupts on peripherals outputs (eg. LEDC,...)
//Enable input in GPIO register
gpio_hal_context_t gpiohal;
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
gpio_hal_input_enable(&gpiohal, pin);
}
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void *arg, int intr_type) {
__attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false);
}
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) {
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false);
}
extern void __detachInterrupt(uint8_t pin) {
gpio_isr_handler_remove((gpio_num_t)pin); //remove handle and disable isr for pin
gpio_wakeup_disable((gpio_num_t)pin);
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg) {
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = NULL;
__pinInterruptHandlers[pin].arg = NULL;
__pinInterruptHandlers[pin].functional = false;
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_DISABLE);
}
extern void enableInterrupt(uint8_t pin) {
gpio_intr_enable((gpio_num_t)pin);
}
extern void disableInterrupt(uint8_t pin) {
gpio_intr_disable((gpio_num_t)pin);
}
extern void pinMode(uint8_t pin, uint8_t mode) __attribute__((weak, alias("__pinMode")));
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__((weak, alias("__digitalWrite")));
extern int digitalRead(uint8_t pin) __attribute__((weak, alias("__digitalRead")));
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__((weak, alias("__attachInterrupt")));
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void *arg, int mode) __attribute__((weak, alias("__attachInterruptArg")));
extern void detachInterrupt(uint8_t pin) __attribute__((weak, alias("__detachInterrupt")));