Revert "Update Adafruit_NeoPixel library to commit fd74287"

This commit is contained in:
Daniel Öster 2025-03-26 23:55:28 +02:00 committed by GitHub
parent 6824f0633a
commit 6f59924b4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 3945 additions and 4326 deletions

View file

@ -92,11 +92,6 @@
} }
init = true; init = true;
#endif #endif
#if defined(ESP32)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
espInit();
#endif
#endif
} }
/*! /*!
@ -122,13 +117,6 @@
@brief Deallocate Adafruit_NeoPixel object, set data pin back to INPUT. @brief Deallocate Adafruit_NeoPixel object, set data pin back to INPUT.
*/ */
Adafruit_NeoPixel::~Adafruit_NeoPixel() { Adafruit_NeoPixel::~Adafruit_NeoPixel() {
#ifdef ARDUINO_ARCH_ESP32
// Release RMT resources (RMT channels and led_data)
// by indirectly calling into espShow()
memset(pixels, 0, numBytes);
numLEDs = numBytes = 0;
show();
#endif
free(pixels); free(pixels);
if (pin >= 0) if (pin >= 0)
pinMode(pin, INPUT); pinMode(pin, INPUT);
@ -236,162 +224,7 @@
// Bits for transmission must be shifted to top 8 bits // Bits for transmission must be shifted to top 8 bits
pio_sm_put_blocking(pio, sm, ((uint32_t)*pixels++)<< 24); pio_sm_put_blocking(pio, sm, ((uint32_t)*pixels++)<< 24);
} }
#elif defined(ARDUINO_ARCH_CH32)
// F_CPU is defined to SystemCoreClock (not constant number)
#if SYSCLK_FREQ_144MHz_HSE == 144000000 || SYSCLK_FREQ_HSE == 144000000 || \
SYSCLK_FREQ_144MHz_HSI == 144000000 || SYSCLK_FREQ_HSI == 144000000
#define CH32_F_CPU 144000000
#elif SYSCLK_FREQ_120MHz_HSE == 120000000 || SYSCLK_FREQ_HSE == 120000000 || \
SYSCLK_FREQ_120MHz_HSI == 120000000 || SYSCLK_FREQ_HSI == 120000000
#define CH32_F_CPU 120000000
#elif SYSCLK_FREQ_96MHz_HSE == 96000000 || SYSCLK_FREQ_HSE == 96000000 || \
SYSCLK_FREQ_96MHz_HSI == 96000000 || SYSCLK_FREQ_HSI == 96000000
#define CH32_F_CPU 96000000
#elif SYSCLK_FREQ_72MHz_HSE == 72000000 || SYSCLK_FREQ_HSE == 72000000 || \
SYSCLK_FREQ_72MHz_HSI == 72000000 || SYSCLK_FREQ_HSI == 72000000
#define CH32_F_CPU 72000000
#elif SYSCLK_FREQ_56MHz_HSE == 56000000 || SYSCLK_FREQ_HSE == 56000000 || \
SYSCLK_FREQ_56MHz_HSI == 56000000 || SYSCLK_FREQ_HSI == 56000000
#define CH32_F_CPU 56000000
#elif SYSCLK_FREQ_48MHz_HSE == 48000000 || SYSCLK_FREQ_HSE == 48000000 || \
SYSCLK_FREQ_48MHz_HSI == 48000000 || SYSCLK_FREQ_HSI == 48000000
#define CH32_F_CPU 48000000
#endif
static void ch32Show(GPIO_TypeDef* ch_port, uint32_t ch_pin, uint8_t* pixels, uint32_t numBytes, bool is800KHz) {
// not support 400khz
if (!is800KHz) return;
volatile uint32_t* set = &ch_port->BSHR;
volatile uint32_t* clr = &ch_port->BCR;
uint8_t* ptr = pixels;
uint8_t* end = ptr + numBytes;
uint8_t p = *ptr++;
uint8_t bitMask = 0x80;
// NVIC_DisableIRQ(SysTicK_IRQn);
while (1) {
if (p & bitMask) { // ONE
// High 800ns
*set = ch_pin;
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop;"
#if CH32_F_CPU >= 72000000
"nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 96000000
"nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 120000000
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 144000000
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
);
// Low 450ns
*clr = ch_pin;
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop;"
#if CH32_F_CPU >= 72000000
"nop; nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 96000000
"nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 120000000
"nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 144000000
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
);
} else { // ZERO
// High 400ns
*set = ch_pin;
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop;"
#if CH32_F_CPU >= 72000000
"nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 96000000
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 120000000
"nop; nop; nop; "
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 144000000
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
);
// Low 850ns
*clr = ch_pin;
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop;"
#if CH32_F_CPU >= 72000000
"nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 96000000
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 120000000
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop;"
#endif
#if CH32_F_CPU >= 144000000
"nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
#endif
);
}
if (bitMask >>= 1) {
// Move on to the next pixel
asm("nop;");
}
else {
if (ptr >= end) {
break;
}
p = *ptr++;
bitMask = 0x80;
}
}
// NVIC_EnableIRQ(SysTicK_IRQn);
}
#endif #endif
#if defined(ESP8266) #if defined(ESP8266)
@ -401,7 +234,6 @@
#elif defined(ESP32) #elif defined(ESP32)
extern "C" void espShow(uint16_t pin, uint8_t *pixels, uint32_t numBytes, extern "C" void espShow(uint16_t pin, uint8_t *pixels, uint32_t numBytes,
uint8_t type); uint8_t type);
#endif // ESP8266 #endif // ESP8266
#if defined(K210) #if defined(K210)
@ -2424,7 +2256,7 @@
#elif defined(__SAMD21E17A__) || defined(__SAMD21G18A__) || \ #elif defined(__SAMD21E17A__) || defined(__SAMD21G18A__) || \
defined(__SAMD21E18A__) || defined(__SAMD21J18A__) || \ defined(__SAMD21E18A__) || defined(__SAMD21J18A__) || \
defined(__SAMD11C14A__) || defined(__SAMD21G17A__) defined (__SAMD11C14A__)
// Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo // Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo
// and others // and others
// Tried this with a timer/counter, couldn't quite get adequate // Tried this with a timer/counter, couldn't quite get adequate
@ -3082,89 +2914,7 @@
; // Wait for last bit ; // Wait for last bit
TC_Stop(TC1, 0); TC_Stop(TC1, 0);
#endif // end Due
// RENESAS including UNO R4
#elif defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_RENESAS_UNO) || defined(ARDUINO_ARCH_RENESAS_PORTENTA)
// Definition for a single channel clockless controller for RA4M1 (Cortex M4)
// See clockless.h for detailed info on how the template parameters are used.
#define ARM_DEMCR (*(volatile uint32_t *)0xE000EDFC) // Debug Exception and Monitor Control
#define ARM_DEMCR_TRCENA (1 << 24) // Enable debugging & monitoring blocks
#define ARM_DWT_CTRL (*(volatile uint32_t *)0xE0001000) // DWT control register
#define ARM_DWT_CTRL_CYCCNTENA (1 << 0) // Enable cycle count
#define ARM_DWT_CYCCNT (*(volatile uint32_t *)0xE0001004) // Cycle count register
#define F_CPU 48000000
#define CYCLES_800_T0H (F_CPU / 4000000)
#define CYCLES_800_T1H (F_CPU / 1250000)
#define CYCLES_800 (F_CPU / 800000)
#define CYCLES_400_T0H (F_CPU / 2000000)
#define CYCLES_400_T1H (F_CPU / 833333)
#define CYCLES_400 (F_CPU / 400000)
uint8_t *p = pixels, *end = p + numBytes, pix, mask;
bsp_io_port_pin_t io_pin = g_pin_cfg[pin].pin;
#define PIN_IO_PORT_ADDR(pn) (R_PORT0 + ((uint32_t) (R_PORT1 - R_PORT0) * ((pn) >> 8u)))
volatile uint16_t *set = &(PIN_IO_PORT_ADDR(io_pin)->POSR);
volatile uint16_t *clr = &(PIN_IO_PORT_ADDR(io_pin)->PORR);
uint16_t msk = (1U << (io_pin & 0xFF));
uint32_t cyc;
ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if (is800KHz) {
#endif
cyc = ARM_DWT_CYCCNT + CYCLES_800;
while (p < end) {
pix = *p++;
for (mask = 0x80; mask; mask >>= 1) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
;
cyc = ARM_DWT_CYCCNT;
*set = msk;
if (pix & mask) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H)
;
} else {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H)
;
}
*clr = msk;
}
}
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
;
#if defined(NEO_KHZ400)
} else { // 400 kHz bitstream
cyc = ARM_DWT_CYCCNT + CYCLES_400;
while (p < end) {
pix = *p++;
for (mask = 0x80; mask; mask >>= 1) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400)
;
cyc = ARM_DWT_CYCCNT;
*set = msk;
if (pix & mask) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H)
;
} else {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H)
;
}
*clr = msk;
}
}
while (ARM_DWT_CYCCNT - cyc < CYCLES_400)
;
}
#endif // NEO_KHZ400
#endif // ARM
// END ARM ---------------------------------------------------------------- // END ARM ----------------------------------------------------------------
@ -3276,8 +3026,6 @@
} }
} }
#elif defined(ARDUINO_ARCH_CH32)
ch32Show(gpioPort, gpioPin, pixels, numBytes, is800KHz);
#else #else
#error Architecture not supported #error Architecture not supported
#endif #endif
@ -3311,15 +3059,6 @@
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) #if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
gpioPort = digitalPinToPort(p); gpioPort = digitalPinToPort(p);
gpioPin = STM_LL_GPIO_PIN(digitalPinToPinName(p)); gpioPin = STM_LL_GPIO_PIN(digitalPinToPinName(p));
#elif defined(ARDUINO_ARCH_CH32)
PinName const pin_name = digitalPinToPinName(pin);
gpioPort = get_GPIO_Port(CH_PORT(pin_name));
gpioPin = CH_GPIO_PIN(pin_name);
#if defined (CH32V20x_D6)
if (gpioPort == GPIOC && ((*(volatile uint32_t*)0x40022030) & 0x0F000000) == 0) {
gpioPin = gpioPin >> 13;
}
#endif
#endif #endif
} }
@ -3733,4 +3472,3 @@
if (w < 0) w = r; // If 'w' not specified, duplicate r bits if (w < 0) w = r; // If 'w' not specified, duplicate r bits
return (w << 6) | (r << 4) | ((g & 3) << 2) | (b & 3); return (w << 6) | (r << 4) | ((g & 3) << 2) | (b & 3);
} }

View file

@ -208,15 +208,6 @@
218, 220, 223, 225, 227, 230, 232, 235, 237, 240, 242, 245, 247, 250, 252, 218, 220, 223, 225, 227, 230, 232, 235, 237, 240, 242, 245, 247, 250, 252,
255}; 255};
/* Declare external methods required by the Adafruit_NeoPixel implementation
for specific hardware/library versions
*/
#if defined(ESP32)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
extern "C" void espInit();
#endif
#endif
/*! /*!
@brief Class that stores state and functions for interacting with @brief Class that stores state and functions for interacting with
Adafruit NeoPixels and compatible devices. Adafruit NeoPixels and compatible devices.
@ -407,7 +398,7 @@
volatile uint8_t *port; ///< Output PORT register volatile uint8_t *port; ///< Output PORT register
uint8_t pinMask; ///< Output PORT bitmask uint8_t pinMask; ///< Output PORT bitmask
#endif #endif
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_CH32) #if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
GPIO_TypeDef *gpioPort; ///< Output GPIO PORT GPIO_TypeDef *gpioPort; ///< Output GPIO PORT
uint32_t gpioPin; ///< Output GPIO PIN uint32_t gpioPin; ///< Output GPIO PIN
#endif #endif
@ -419,4 +410,3 @@
}; };
#endif // ADAFRUIT_NEOPIXEL_H #endif // ADAFRUIT_NEOPIXEL_H

View file

@ -20,109 +20,13 @@
#if defined(ESP32) #if defined(ESP32)
#include <Arduino.h> #include <Arduino.h>
#include "driver/rmt.h"
#if defined(ESP_IDF_VERSION) #if defined(ESP_IDF_VERSION)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
#define HAS_ESP_IDF_4 #define HAS_ESP_IDF_4
#endif #endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#define HAS_ESP_IDF_5
#endif #endif
#endif
#ifdef HAS_ESP_IDF_5
static SemaphoreHandle_t show_mutex = NULL;
void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
// Note: Because rmtPin is shared between all instances, we will
// end up releasing/initializing the RMT channels each time we
// invoke on different pins. This is probably ok, just not
// efficient. led_data is shared between all instances but will
// be allocated with enough space for the largest instance; data
// is not used beyond the mutex lock so this should be fine.
#define SEMAPHORE_TIMEOUT_MS 50
static rmt_data_t *led_data = NULL;
static uint32_t led_data_size = 0;
static int rmtPin = -1;
if (show_mutex && xSemaphoreTake(show_mutex, SEMAPHORE_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
uint32_t requiredSize = numBytes * 8;
if (requiredSize > led_data_size) {
free(led_data);
if (led_data = (rmt_data_t *)malloc(requiredSize * sizeof(rmt_data_t))) {
led_data_size = requiredSize;
} else {
led_data_size = 0;
}
} else if (requiredSize == 0) {
// To release RMT resources (RMT channels and led_data), call
// .updateLength(0) to set number of pixels/bytes to zero,
// then call .show() to invoke this code and free resources.
free(led_data);
led_data = NULL;
if (rmtPin >= 0) {
rmtDeinit(rmtPin);
rmtPin = -1;
}
led_data_size = 0;
}
if (led_data_size > 0 && requiredSize <= led_data_size) {
if (pin != rmtPin) {
if (rmtPin >= 0) {
rmtDeinit(rmtPin);
rmtPin = -1;
}
if (!rmtInit(pin, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) {
log_e("Failed to init RMT TX mode on pin %d", pin);
return;
}
rmtPin = pin;
}
if (rmtPin >= 0) {
int i=0;
for (int b=0; b < numBytes; b++) {
for (int bit=0; bit<8; bit++){
if ( pixels[b] & (1<<(7-bit)) ) {
led_data[i].level0 = 1;
led_data[i].duration0 = 8;
led_data[i].level1 = 0;
led_data[i].duration1 = 4;
} else {
led_data[i].level0 = 1;
led_data[i].duration0 = 4;
led_data[i].level1 = 0;
led_data[i].duration1 = 8;
}
i++;
}
}
rmtWrite(pin, led_data, numBytes * 8, RMT_WAIT_FOR_EVER);
}
}
xSemaphoreGive(show_mutex);
}
}
// To avoid race condition initializing the mutex, all instances of
// Adafruit_NeoPixel must be constructed before launching and child threads
void espInit() {
if (!show_mutex) {
show_mutex = xSemaphoreCreateMutex();
}
}
#else
#include "driver/rmt.h"
// This code is adapted from the ESP-IDF v3.4 RMT "led_strip" example, altered // This code is adapted from the ESP-IDF v3.4 RMT "led_strip" example, altered
// to work with the Arduino version of the ESP-IDF (3.2) // to work with the Arduino version of the ESP-IDF (3.2)
@ -152,9 +56,8 @@
bool rmt_reserved_channels[ADAFRUIT_RMT_CHANNEL_MAX]; bool rmt_reserved_channels[ADAFRUIT_RMT_CHANNEL_MAX];
static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, static void IRAM_ATTR ws2812_rmt_adapter(const void* src, rmt_item32_t* dest, size_t src_size, size_t wanted_num,
size_t wanted_num, size_t *translated_size, size_t *item_num) size_t* translated_size, size_t* item_num) {
{
if (src == NULL || dest == NULL) { if (src == NULL || dest == NULL) {
*translated_size = 0; *translated_size = 0;
*item_num = 0; *item_num = 0;
@ -191,13 +94,13 @@
if (rmt_initialized == false) { if (rmt_initialized == false) {
// Reserve channel // Reserve channel
rmt_channel_t channel = 0; rmt_channel_t channel = 0;
#if defined(HAS_ESP_IDF_4) #if defined(HAS_ESP_IDF_4)
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin, channel); rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin, channel);
config.clk_div = 2; config.clk_div = 2;
#else #else
// Match default TX config from ESP-IDF version 3.4 // Match default TX config from ESP-IDF version 3.4
rmt_config_t config = { rmt_config_t config = {.rmt_mode = RMT_MODE_TX,
.rmt_mode = RMT_MODE_TX,
.channel = channel, .channel = channel,
.gpio_num = pin, .gpio_num = pin,
.clk_div = 2, .clk_div = 2,
@ -210,8 +113,7 @@
.carrier_en = false, .carrier_en = false,
.loop_en = false, .loop_en = false,
.idle_output_en = true, .idle_output_en = true,
} }};
};
#endif #endif
rmt_config(&config); rmt_config(&config);
rmt_driver_install(config.channel, 0, 0); rmt_driver_install(config.channel, 0, 0);
@ -256,17 +158,6 @@
// Write and wait to finish // Write and wait to finish
rmt_write_sample(0, pixels, (size_t)numBytes, false); rmt_write_sample(0, pixels, (size_t)numBytes, false);
//rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));
// Free channel again
//rmt_driver_uninstall(config.channel);
//rmt_reserved_channels[channel] = false;
//gpio_set_direction(pin, GPIO_MODE_OUTPUT);
} }
#endif // ifndef IDF5 #endif
#endif // ifdef(ESP32)