diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eb8f4e45ef..53da85a4502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-matrix.c cores/esp32/esp32-hal-misc.c cores/esp32/esp32-hal-psram.c + cores/esp32/esp32-hal-rgb-led.c cores/esp32/esp32-hal-sigmadelta.c cores/esp32/esp32-hal-spi.c cores/esp32/esp32-hal-time.c diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c index 359682c3433..ceef3bdfa5c 100644 --- a/cores/esp32/esp32-hal-gpio.c +++ b/cores/esp32/esp32-hal-gpio.c @@ -91,6 +91,13 @@ static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,}; extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode) { +#ifdef BOARD_HAS_NEOPIXEL + if (pin == LED_BUILTIN){ + __pinMode(LED_BUILTIN-SOC_GPIO_PIN_COUNT, mode); + return; + } +#endif + if (!GPIO_IS_VALID_GPIO(pin)) { log_e("Invalid pin selected"); return; @@ -127,6 +134,14 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode) extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val) { + #ifdef BOARD_HAS_NEOPIXEL + if(pin == LED_BUILTIN){ + //use RMT to set all channels on/off + const uint8_t comm_val = val != 0 ? LED_BRIGHTNESS : 0; + neopixelWrite(LED_BUILTIN, comm_val, comm_val, comm_val); + return; + } + #endif gpio_set_level((gpio_num_t)pin, val); } diff --git a/cores/esp32/esp32-hal-gpio.h b/cores/esp32/esp32-hal-gpio.h index ff3808e9856..9f143811685 100644 --- a/cores/esp32/esp32-hal-gpio.h +++ b/cores/esp32/esp32-hal-gpio.h @@ -26,6 +26,7 @@ extern "C" { #include "esp32-hal.h" #include "soc/soc_caps.h" +#include "pins_arduino.h" #if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define NUM_OUPUT_PINS 46 @@ -63,6 +64,7 @@ extern "C" { #define ONLOW_WE 0x0C #define ONHIGH_WE 0x0D + #define digitalPinIsValid(pin) GPIO_IS_VALID_GPIO(pin) #define digitalPinCanOutput(pin) GPIO_IS_VALID_OUTPUT_GPIO(pin) diff --git a/cores/esp32/esp32-hal-rgb-led.c b/cores/esp32/esp32-hal-rgb-led.c new file mode 100644 index 00000000000..6776d324d99 --- /dev/null +++ b/cores/esp32/esp32-hal-rgb-led.c @@ -0,0 +1,47 @@ +#include "esp32-hal-rgb-led.h" + + +void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val){ + rmt_data_t led_data[24]; + static rmt_obj_t* rmt_send = NULL; + static bool initialized = false; + + uint8_t _pin = pin; +#ifdef BOARD_HAS_NEOPIXEL + if(pin == LED_BUILTIN){ + _pin = LED_BUILTIN-SOC_GPIO_PIN_COUNT; + } +#endif + + if(!initialized){ + if((rmt_send = rmtInit(_pin, RMT_TX_MODE, RMT_MEM_64)) == NULL){ + log_e("RGB LED driver initialization failed!"); + rmt_send = NULL; + return; + } + rmtSetTick(rmt_send, 100); + initialized = true; + } + + int color[] = {green_val, red_val, blue_val}; // Color coding is in order GREEN, RED, BLUE + int i = 0; + for(int col=0; col<3; col++ ){ + for(int bit=0; bit<8; bit++){ + if((color[col] & (1<<(7-bit)))){ + // HIGH bit + led_data[i].level0 = 1; // T1H + led_data[i].duration0 = 8; // 0.8us + led_data[i].level1 = 0; // T1L + led_data[i].duration1 = 4; // 0.4us + }else{ + // LOW bit + led_data[i].level0 = 1; // T0H + led_data[i].duration0 = 4; // 0.4us + led_data[i].level1 = 0; // T0L + led_data[i].duration1 = 8; // 0.8us + } + i++; + } + } + rmtWrite(rmt_send, led_data, 24); +} diff --git a/cores/esp32/esp32-hal-rgb-led.h b/cores/esp32/esp32-hal-rgb-led.h new file mode 100644 index 00000000000..e2db0e91046 --- /dev/null +++ b/cores/esp32/esp32-hal-rgb-led.h @@ -0,0 +1,20 @@ +#ifndef MAIN_ESP32_HAL_RGB_LED_H_ +#define MAIN_ESP32_HAL_RGB_LED_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp32-hal.h" + +#ifndef LED_BRIGHTNESS + #define LED_BRIGHTNESS 64 +#endif + +void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val); + +#ifdef __cplusplus +} +#endif + +#endif /* MAIN_ESP32_HAL_RGB_LED_H_ */ \ No newline at end of file diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index 55e9f95769b..9039d3544c8 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -88,6 +88,7 @@ void yield(void); #include "esp32-hal-timer.h" #include "esp32-hal-bt.h" #include "esp32-hal-psram.h" +#include "esp32-hal-rgb-led.h" #include "esp32-hal-cpu.h" void analogWrite(uint8_t pin, int value); diff --git a/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino new file mode 100644 index 00000000000..3c2ed4864c1 --- /dev/null +++ b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino @@ -0,0 +1,39 @@ +/* + BlinkRGB + + Demonstrates usage of onboard RGB LED on some ESP dev boards. + + Calling digitalWrite(LED_BUILTIN, HIGH) will use hidden RGB driver. + + RGBLedWrite demonstrates controll of each channel: + void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val) + + WARNING: After using digitalWrite to drive RGB LED it will be impossible to drive the same pin + with normal HIGH/LOW level +*/ +//#define LED_BRIGHTNESS 64 // Change white brightness (max 255) + +// the setup function runs once when you press reset or power the board + +void setup() { + // No need to initialize the RGB LED +} + +// the loop function runs over and over again forever +void loop() { +#ifdef BOARD_HAS_NEOPIXEL + digitalWrite(LED_BUILTIN, HIGH); // Turn the RGB LED white + delay(1000); + digitalWrite(LED_BUILTIN, LOW); // Turn the RGB LED off + delay(1000); + + neopixelWrite(LED_BUILTIN,LED_BRIGHTNESS,0,0); // Red + delay(1000); + neopixelWrite(LED_BUILTIN,0,LED_BRIGHTNESS,0); // Green + delay(1000); + neopixelWrite(LED_BUILTIN,0,0,LED_BRIGHTNESS); // Blue + delay(1000); + neopixelWrite(LED_BUILTIN,0,0,0); // Off / black + delay(1000); +#endif +} diff --git a/variants/esp32c3/pins_arduino.h b/variants/esp32c3/pins_arduino.h index 8ce191ad23a..0fce6340e08 100644 --- a/variants/esp32c3/pins_arduino.h +++ b/variants/esp32c3/pins_arduino.h @@ -2,11 +2,18 @@ #define Pins_Arduino_h #include +#include "soc/soc_caps.h" #define EXTERNAL_NUM_INTERRUPTS 22 #define NUM_DIGITAL_PINS 22 #define NUM_ANALOG_INPUTS 6 +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+8; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN +#define BOARD_HAS_NEOPIXEL +#define LED_BRIGHTNESS 64 + #define analogInputToDigitalPin(p) (((p) +#include "soc/soc_caps.h" #define EXTERNAL_NUM_INTERRUPTS 46 #define NUM_DIGITAL_PINS 48 #define NUM_ANALOG_INPUTS 20 +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+18; // GPIO pin for Saola-1 & DevKitM-1 = 18 +//static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+45; // GPIO pin for Kaluga = 45 +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN +#define BOARD_HAS_NEOPIXEL +#define LED_BRIGHTNESS 64 + #define analogInputToDigitalPin(p) (((p)<20)?(analogChannelToDigitalPin(p)):-1) #define digitalPinToInterrupt(p) (((p)<48)?(p):-1) #define digitalPinHasPWM(p) (p < 46) diff --git a/variants/esp32s3/pins_arduino.h b/variants/esp32s3/pins_arduino.h index 59f298e4965..fc48ac691d5 100644 --- a/variants/esp32s3/pins_arduino.h +++ b/variants/esp32s3/pins_arduino.h @@ -2,6 +2,7 @@ #define Pins_Arduino_h #include +#include "soc/soc_caps.h" #define USB_VID 0x303a #define USB_PID 0x1001 @@ -10,6 +11,15 @@ #define NUM_DIGITAL_PINS 48 #define NUM_ANALOG_INPUTS 20 +// Some boards have too low voltage on this pin (board design bug) +// Use different pin with 3V and connect with 48 +// and change this setup for the chosen pin (for example 38) +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+48; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN +#define BOARD_HAS_NEOPIXEL +#define LED_BRIGHTNESS 64 + #define analogInputToDigitalPin(p) (((p)<20)?(analogChannelToDigitalPin(p)):-1) #define digitalPinToInterrupt(p) (((p)<48)?(p):-1) #define digitalPinHasPWM(p) (p < 46)