2#if !__has_include("esp_memory_utils.h")
4 "esp_memory_utils.h is not available, are you using esp-idf 4.4 or earlier?"
7#pragma GCC diagnostic push
8#pragma GCC diagnostic ignored "-Wattributes"
9#pragma GCC diagnostic ignored "-Wvolatile"
13#include "esp_heap_caps.h"
14#include "esp_intr_alloc.h"
15#include "esp_memory_utils.h"
22#include "driver/gpio.h"
23#include "esp_memory_utils.h"
24#include "esp_private/gdma.h"
25#include "esp_rom_gpio.h"
26#include "hal/dma_types.h"
27#include "hal/gpio_hal.h"
29#include "soc/soc_caps.h"
33#include "hal/lcd_hal.h"
34#include "hal/lcd_ll.h"
35#include "soc/lcd_periph.h"
37#include "esp_heap_caps.h"
38#include "esp_lcd_panel_interface.h"
39#include "esp_lcd_panel_io.h"
40#include "esp_lcd_panel_io_interface.h"
41#include "esp_lcd_panel_ops.h"
44#include "soc/gdma_reg.h"
45#include "platforms/esp/esp_version.h"
47#define IDF_5_3_OR_EARLIER (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 0))
52#define FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS 300
62#ifndef ALTERNATEPATTERN
63#define ALTERNATEPATTERN 1
68#define AA (0x00AA00AAL)
69#define CC (0x0000CCCCL)
70#define FF (0xF0F0F0F0L)
71#define FF2 (0x0F0F0F0FL)
74#define MIN(a, b) (((a) < (b)) ? (a) : (b))
79#define __OFFSET_END (24 * 3 * 2 * 2 * 2 + 2)
80#ifndef HARDWARESPRITES
81#define HARDWARESPRITES 0
84#if HARDWARESPRITES == 1
85#include "hardwareSprite.h"
88#ifdef COLOR_ORDER_GRBW
92#define _nb_components 4
98#define _nb_components 3
100#ifdef COLOR_ORDER_RBG
104#define _nb_components 3
106#ifdef COLOR_ORDER_GBR
110#define _nb_components 3
112#ifdef COLOR_ORDER_BGR
116#define _nb_components 3
118#ifdef COLOR_ORDER_BRG
122#define _nb_components 3
124#ifdef COLOR_ORDER_GRB
128#define _nb_components 3
134#define _nb_components 3
149#define LCD_DRIVER_PSRAM_DATA_ALIGNMENT 64
155#ifdef FASTLED_OVERCLOCK
156#define FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE (FASTLED_OVERCLOCK)
158#define FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE (1)
161#ifndef FASTLED_ESP32S3_I2S_CLOCK_HZ
162#define FASTLED_ESP32S3_I2S_CLOCK_HZ uint32_t((24 * 100 * 1000)*FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE)
167static bool IRAM_ATTR flush_ready(esp_lcd_panel_io_handle_t panel_io,
168 esp_lcd_panel_io_event_data_t *edata,
177enum colorarrangment {
194bool DRIVER_READY =
true;
196typedef struct led_driver_t led_driver_t;
200 void (*update)(uint8_t *colors,
size_t len);
202volatile xSemaphoreHandle I2SClocklessLedDriverS3_sem = NULL;
203volatile bool isDisplaying =
false;
204volatile bool iswaiting =
false;
206static void IRAM_ATTR transpose16x1_noinline2(
unsigned char *A, uint16_t *B) {
208 uint32_t
x,
y, x1, y1, t;
210 y = *(
unsigned int *)(A);
212 x = *(
unsigned int *)(A + 4);
218 y1 = *(
unsigned int *)(A + 8);
223 x1 = *(
unsigned int *)(A + 12);
230 t = (
x ^ (
x >> 7)) & AA;
231 x =
x ^ t ^ (t << 7);
232 t = (
x ^ (
x >> 14)) & CC;
233 x =
x ^ t ^ (t << 14);
236 t = (x1 ^ (x1 >> 7)) & AA;
237 x1 = x1 ^ t ^ (t << 7);
238 t = (x1 ^ (x1 >> 14)) & CC;
239 x1 = x1 ^ t ^ (t << 14);
242 t = (
y ^ (
y >> 7)) & AA;
243 y =
y ^ t ^ (t << 7);
244 t = (
y ^ (
y >> 14)) & CC;
245 y =
y ^ t ^ (t << 14);
247 t = (y1 ^ (y1 >> 7)) & AA;
248 y1 = y1 ^ t ^ (t << 7);
249 t = (y1 ^ (y1 >> 14)) & CC;
250 y1 = y1 ^ t ^ (t << 14);
253 t = (
x & FF) | ((
y >> 4) & FF2);
254 y = ((
x << 4) & FF) | (
y & FF2);
257 t = (x1 & FF) | ((y1 >> 4) & FF2);
258 y1 = ((x1 << 4) & FF) | (y1 & FF2);
262 (uint16_t)(((
x & 0xff000000) >> 8 | ((x1 & 0xff000000))) >> 16);
263 *((uint16_t *)(B + 3)) =
264 (uint16_t)(((
x & 0xff0000) >> 16 | ((x1 & 0xff0000) >> 8)));
265 *((uint16_t *)(B + 6)) =
266 (uint16_t)(((
x & 0xff00) | ((x1 & 0xff00) << 8)) >> 8);
267 *((uint16_t *)(B + 9)) = (uint16_t)((
x & 0xff) | ((x1 & 0xff) << 8));
268 *((uint16_t *)(B + 12)) =
269 (uint16_t)(((
y & 0xff000000) >> 8 | ((y1 & 0xff000000))) >> 16);
270 *((uint16_t *)(B + 15)) =
271 (uint16_t)(((
y & 0xff0000) | ((y1 & 0xff0000) << 8)) >> 16);
272 *((uint16_t *)(B + 18)) =
273 (uint16_t)(((
y & 0xff00) | ((y1 & 0xff00) << 8)) >> 8);
274 *((uint16_t *)(B + 21)) = (uint16_t)((
y & 0xff) | ((y1 & 0xff) << 8));
277esp_lcd_panel_io_handle_t led_io_handle = NULL;
279class I2SClocklessLedDriveresp32S3 {
283 uint16_t *buffers[2];
284 uint16_t *led_output = NULL;
285 uint16_t *led_output2 = NULL;
286 uint8_t *ledsbuff = NULL;
287 int num_leds_per_strip;
291 uint8_t __green_map[256];
292 uint8_t __blue_map[256];
293 uint8_t __red_map[256];
294 uint8_t __white_map[256];
296 float _gammar, _gammab, _gammag, _gammaw;
301 for (
int i = 0; i < 256; i++) {
302 tmp = powf((
float)i / 255, 1 / _gammag);
304 tmp = powf((
float)i / 255, 1 / _gammag);
306 tmp = powf((
float)i / 255, 1 / _gammag);
308 tmp = powf((
float)i / 255, 1 / _gammag);
313 void setGamma(
float gammar,
float gammab,
float gammag,
float gammaw) {
318 setBrightness(_brightness);
321 void setGamma(
float gammar,
float gammab,
float gammag) {
325 setBrightness(_brightness);
328 void _initled(uint8_t *
leds,
const int *pins,
int numstrip,
329 int NUM_LED_PER_STRIP) {
334 esp_lcd_i80_bus_handle_t i80_bus = NULL;
336 esp_lcd_i80_bus_config_t bus_config;
338 bus_config.clk_src = LCD_CLK_SRC_PLL160M;
339 bus_config.dc_gpio_num = 0;
340 bus_config.wr_gpio_num = 0;
342 for (
int i = 0; i < numstrip; i++) {
343 bus_config.data_gpio_nums[i] = pins[i];
346 for (
int i = numstrip; i < 16; i++) {
347 bus_config.data_gpio_nums[i] = 0;
350 bus_config.bus_width = 16;
351 bus_config.max_transfer_bytes =
352 _nb_components * NUM_LED_PER_STRIP * 8 * 3 * 2 + __OFFSET + __OFFSET_END;
353 #if IDF_5_3_OR_EARLIER
354 #pragma GCC diagnostic push
355 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
359 bus_config.psram_trans_align = LCD_DRIVER_PSRAM_DATA_ALIGNMENT;
360 bus_config.sram_trans_align = 4;
361 #if IDF_5_3_OR_EARLIER
362 #pragma GCC diagnostic pop
365 ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
367 esp_lcd_panel_io_i80_config_t io_config;
369 io_config.cs_gpio_num = -1;
370 io_config.pclk_hz = FASTLED_ESP32S3_I2S_CLOCK_HZ;
371 io_config.trans_queue_depth = 1;
372 io_config.dc_levels = {
380 io_config.lcd_cmd_bits = 0;
381 io_config.lcd_param_bits = 0;
382 io_config.user_ctx =
this;
384 io_config.on_color_trans_done = flush_ready;
386 esp_lcd_new_panel_io_i80(i80_bus, &io_config, &led_io_handle));
389 void initled(uint8_t *
leds,
const int *pins,
int numstrip,
390 int NUM_LED_PER_STRIP) {
397 if (I2SClocklessLedDriverS3_sem == NULL) {
398 I2SClocklessLedDriverS3_sem = xSemaphoreCreateBinary();
402 led_output = (uint16_t *)heap_caps_aligned_alloc(
403 LCD_DRIVER_PSRAM_DATA_ALIGNMENT,
404 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
406 MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
407 memset(led_output, 0,
408 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
411 led_output2 = (uint16_t *)heap_caps_aligned_alloc(
412 LCD_DRIVER_PSRAM_DATA_ALIGNMENT,
413 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
415 MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
416 memset(led_output2, 0,
417 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
419 buffers[0] = led_output;
420 buffers[1] = led_output2;
424 led_output2 += __OFFSET / 2;
425 led_output += __OFFSET / 2;
427 for (
int i = 0; i < NUM_LED_PER_STRIP * _nb_components * 8; i++) {
428 led_output[3 * i + 1] =
431 led_output2[3 * i + 1] = 0xFFFF;
434 _numstrips = numstrip;
435 num_leds_per_strip = NUM_LED_PER_STRIP;
436 _initled(
leds, pins, numstrip, NUM_LED_PER_STRIP);
439 void transposeAll(uint16_t *ledoutput) {
441 uint16_t ledToDisplay = 0;
442 Lines secondPixel[_nb_components];
445 uint16_t jump = num_leds_per_strip * _nb_components;
446 for (
int j = 0; j < num_leds_per_strip; j++) {
447 uint8_t *poli = ledsbuff + ledToDisplay * _nb_components;
448 for (
int i = 0; i < _numstrips; i++) {
450 secondPixel[_p_g].bytes[i] = __green_map[*(poli + 1)];
451 secondPixel[_p_r].bytes[i] = __red_map[*(poli + 0)];
452 secondPixel[_p_b].bytes[i] = __blue_map[*(poli + 2)];
453 if (_nb_components > 3)
454 secondPixel[3].bytes[i] = __white_map[*(poli + 3)];
459 transpose16x1_noinline2(secondPixel[0].bytes, buff);
461 transpose16x1_noinline2(secondPixel[1].bytes, buff);
463 transpose16x1_noinline2(secondPixel[2].bytes, buff);
465 if (_nb_components > 3) {
466 transpose16x1_noinline2(secondPixel[3].bytes, buff);
473 transposeAll(buffers[currentframe]);
477 if (I2SClocklessLedDriverS3_sem == NULL)
478 I2SClocklessLedDriverS3_sem = xSemaphoreCreateBinary();
479 xSemaphoreTake(I2SClocklessLedDriverS3_sem, portMAX_DELAY);
483 if (FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS) {
484 delayMicroseconds(FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS);
487 led_io_handle->tx_color(led_io_handle, 0x2C, buffers[currentframe],
488 _nb_components * num_leds_per_strip * 8 * 3 *
490 __OFFSET + __OFFSET_END);
492 currentframe = (currentframe + 1) % 2;
496static bool IRAM_ATTR flush_ready(esp_lcd_panel_io_handle_t panel_io,
497 esp_lcd_panel_io_event_data_t *edata,
501 isDisplaying =
false;
502 I2SClocklessLedDriveresp32S3 *cont =
503 (I2SClocklessLedDriveresp32S3 *)user_ctx;
506 portBASE_TYPE HPTaskAwoken = 0;
508 xSemaphoreGiveFromISR(I2SClocklessLedDriverS3_sem, &HPTaskAwoken);
509 if (HPTaskAwoken == pdTRUE)
510 portYIELD_FROM_ISR(HPTaskAwoken);
515#pragma GCC diagnostic pop
UISlider brightness("Brightness", 255, 0, 255, 1)
Implements a simple red square effect for 2D LED grids.