FastLED 3.9.15
Loading...
Searching...
No Matches
I2SClockLessLedDriveresp32s3.h
Go to the documentation of this file.
1
2
3#include "fl/has_include.h"
4
5#if !FL_HAS_INCLUDE("esp_memory_utils.h")
6#error \
7 "esp_memory_utils.h is not available, are you using esp-idf 4.4 or earlier?"
8#else
9
10#pragma GCC diagnostic push
11#pragma GCC diagnostic ignored "-Wattributes"
12#pragma GCC diagnostic ignored "-Wvolatile"
13
14#include "esp_attr.h"
15#include "esp_check.h"
16#include "esp_heap_caps.h"
17#include "esp_intr_alloc.h"
18#include "esp_memory_utils.h"
19#include "esp_pm.h"
20#include "fl/stdint.h"
21#include "platforms/assert_defs.h"
22#include <string.h>
23// #include "esp_lcd_panel_io_interface.h"
24// #include "esp_lcd_panel_io.h"
25#include "driver/gpio.h"
26#include "esp_memory_utils.h"
27#include "esp_private/gdma.h"
28#include "esp_rom_gpio.h"
29#include "hal/dma_types.h"
30#include "hal/gpio_hal.h"
31#include "soc/rtc.h" // for `rtc_clk_xtal_freq_get()`
32#include "soc/soc_caps.h"
33// #include "esp_private/periph_ctrl.h"
34
35// #include "esp_lcd_common.h"
36#include "hal/lcd_hal.h"
37#include "hal/lcd_ll.h"
38#include "soc/lcd_periph.h"
39
40#include "esp_heap_caps.h"
41#include "esp_lcd_panel_interface.h"
42#include "esp_lcd_panel_io.h"
43#include "esp_lcd_panel_io_interface.h"
44#include "esp_lcd_panel_ops.h"
45#include "esp_log.h"
46#include "esp_timer.h"
47#include "soc/gdma_reg.h"
48#include "platforms/esp/esp_version.h"
49
50#define IDF_5_4_OR_EARLIER (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0))
51
52// According to bug reports, this driver does not work well with the new WS2812-v5b. This is
53// probably due to the extrrra long reset time requirements of this chipset. so we put in
54// a hack that will always add 300 uS to the reset time.
55#define FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS 300
56
57#ifndef NUMSTRIPS
58#define NUMSTRIPS 16
59#endif
60
61#ifndef SNAKEPATTERN
62#define SNAKEPATTERN 1
63#endif
64
65#ifndef ALTERNATEPATTERN
66#define ALTERNATEPATTERN 1
67#endif
68
69#define I2S_DEVICE 0
70
71#pragma push_macro("AA")
72#pragma push_macro("CC")
73#pragma push_macro("FF")
74#pragma push_macro("FF2")
75
76// #ifndef AA
77// #define AA (0x00AA00AAL)
78// #endif
79
80#ifdef AA
81#undef AA
82#endif
83
84
85
86#ifdef BA
87#undef BA
88#endif
89
90#ifdef CC
91#undef CC
92#endif
93
94#ifdef FF
95#undef FF
96#endif
97
98#ifdef FF2
99#undef FF2
100#endif
101
102#define AA (0x00AA00AAL)
103#define CC (0x0000CCCCL)
104#define FF (0xF0F0F0F0L)
105#define FF2 (0x0F0F0F0FL)
106
107// ---------------------------------------------------------------------------
108// End scoped constants
109// ---------------------------------------------------------------------------
110
111#ifndef MIN
112#define MIN(a, b) (((a) < (b)) ? (a) : (b))
113#endif
114
115#define __OFFSET 0 // (24*3*2*2*2+2)
116
117#define __OFFSET_END (24 * 3 * 2 * 2 * 2 + 2)
118#ifndef HARDWARESPRITES
119#define HARDWARESPRITES 0
120#endif
121
122#if HARDWARESPRITES == 1
123#include "hardwareSprite.h"
124#endif
125
126#ifdef COLOR_ORDER_GRBW
127#define _p_r 1
128#define _p_g 0
129#define _p_b 2
130#define _nb_components 4
131#else
132#ifdef COLOR_ORDER_RGB
133#define _p_r 0
134#define _p_g 1
135#define _p_b 2
136#define _nb_components 3
137#else
138#ifdef COLOR_ORDER_RBG
139#define _p_r 0
140#define _p_g 2
141#define _p_b 1
142#define _nb_components 3
143#else
144#ifdef COLOR_ORDER_GBR
145#define _p_r 2
146#define _p_g 0
147#define _p_b 1
148#define _nb_components 3
149#else
150#ifdef COLOR_ORDER_BGR
151#define _p_r 2
152#define _p_g 1
153#define _p_b 0
154#define _nb_components 3
155#else
156#ifdef COLOR_ORDER_BRG
157#define _p_r 1
158#define _p_g 2
159#define _p_b 0
160#define _nb_components 3
161#else
162#ifdef COLOR_ORDER_GRB
163#define _p_r 1
164#define _p_g 0
165#define _p_b 2
166#define _nb_components 3
167#else
168
169#define _p_r 1
170#define _p_g 0
171#define _p_b 2
172#define _nb_components 3
173#endif
174#endif
175#endif
176#endif
177#endif
178#endif
179#endif
180
181#ifdef USE_PIXELSLIB
182// #include "pixelslib.h"
183#else
184#include "___pixeltypes.h"
185#endif
186
187#define LCD_DRIVER_PSRAM_DATA_ALIGNMENT 64
188
189// Note: I2S REQUIRES that the FASTLED_OVERCLOCK factor is a a build-level-define and
190// not an include level define. This is easy if you are already using PlatformIO or CMake.
191// If you are using ArduinoIDE you'll have to download FastLED source code and hack the src
192// to make this work.
193#ifdef FASTLED_OVERCLOCK
194#define FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE (FASTLED_OVERCLOCK)
195#else
196#define FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE (1)
197#endif
198
199#ifndef FASTLED_ESP32S3_I2S_CLOCK_HZ
200#define FASTLED_ESP32S3_I2S_CLOCK_HZ uint32_t((24 * 100 * 1000)*FASTLED_ESP32S3_I2S_CLOCK_HZ_SCALE)
201#endif
202
203namespace fl {
204
205static bool IRAM_ATTR flush_ready(esp_lcd_panel_io_handle_t panel_io,
206 esp_lcd_panel_io_event_data_t *edata,
207 void *user_ctx);
208
209typedef union {
210 uint8_t bytes[16];
211 uint32_t shorts[8];
212 uint32_t raw[2];
213} Lines;
214
215enum colorarrangment {
216 ORDER_GRBW,
217 ORDER_RGB,
218 ORDER_RBG,
219 ORDER_GRB,
220 ORDER_GBR,
221 ORDER_BRG,
222 ORDER_BGR,
223};
224
225enum displayMode {
226 NO_WAIT,
227 WAIT,
228 LOOP,
229 LOOP_INTERUPT,
230};
231
232bool DRIVER_READY = true;
233
234typedef struct led_driver_t led_driver_t;
235
236struct led_driver_t {
237 size_t (*init)();
238 void (*update)(uint8_t *colors, size_t len);
239};
240volatile xSemaphoreHandle I2SClocklessLedDriverS3_sem = NULL;
241volatile bool isDisplaying = false;
242volatile bool iswaiting = false;
243
244static void IRAM_ATTR transpose16x1_noinline2(unsigned char *A, uint16_t *B) {
245
246 uint32_t x, y, x1, y1, t;
247
248 y = *(unsigned int *)(A);
249#if NUMSTRIPS > 4
250 x = *(unsigned int *)(A + 4);
251#else
252 x = 0;
253#endif
254
255#if NUMSTRIPS > 8
256 y1 = *(unsigned int *)(A + 8);
257#else
258 y1 = 0;
259#endif
260#if NUMSTRIPS > 12
261 x1 = *(unsigned int *)(A + 12);
262#else
263 x1 = 0;
264#endif
265
266 // pre-transform x
267#if NUMSTRIPS > 4
268 t = (x ^ (x >> 7)) & AA;
269 x = x ^ t ^ (t << 7);
270 t = (x ^ (x >> 14)) & CC;
271 x = x ^ t ^ (t << 14);
272#endif
273#if NUMSTRIPS > 12
274 t = (x1 ^ (x1 >> 7)) & AA;
275 x1 = x1 ^ t ^ (t << 7);
276 t = (x1 ^ (x1 >> 14)) & CC;
277 x1 = x1 ^ t ^ (t << 14);
278#endif
279 // pre-transform y
280 t = (y ^ (y >> 7)) & AA;
281 y = y ^ t ^ (t << 7);
282 t = (y ^ (y >> 14)) & CC;
283 y = y ^ t ^ (t << 14);
284#if NUMSTRIPS > 8
285 t = (y1 ^ (y1 >> 7)) & AA;
286 y1 = y1 ^ t ^ (t << 7);
287 t = (y1 ^ (y1 >> 14)) & CC;
288 y1 = y1 ^ t ^ (t << 14);
289#endif
290 // final transform
291 t = (x & FF) | ((y >> 4) & FF2);
292 y = ((x << 4) & FF) | (y & FF2);
293 x = t;
294
295 t = (x1 & FF) | ((y1 >> 4) & FF2);
296 y1 = ((x1 << 4) & FF) | (y1 & FF2);
297 x1 = t;
298
299 *((uint16_t *)(B)) =
300 (uint16_t)(((x & 0xff000000) >> 8 | ((x1 & 0xff000000))) >> 16);
301 *((uint16_t *)(B + 3)) =
302 (uint16_t)(((x & 0xff0000) >> 16 | ((x1 & 0xff0000) >> 8)));
303 *((uint16_t *)(B + 6)) =
304 (uint16_t)(((x & 0xff00) | ((x1 & 0xff00) << 8)) >> 8);
305 *((uint16_t *)(B + 9)) = (uint16_t)((x & 0xff) | ((x1 & 0xff) << 8));
306 *((uint16_t *)(B + 12)) =
307 (uint16_t)(((y & 0xff000000) >> 8 | ((y1 & 0xff000000))) >> 16);
308 *((uint16_t *)(B + 15)) =
309 (uint16_t)(((y & 0xff0000) | ((y1 & 0xff0000) << 8)) >> 16);
310 *((uint16_t *)(B + 18)) =
311 (uint16_t)(((y & 0xff00) | ((y1 & 0xff00) << 8)) >> 8);
312 *((uint16_t *)(B + 21)) = (uint16_t)((y & 0xff) | ((y1 & 0xff) << 8));
313}
314
315esp_lcd_panel_io_handle_t led_io_handle = NULL;
316
317class I2SClocklessLedDriveresp32S3 {
318
319 public:
320 int testcount;
321 uint16_t *buffers[2];
322 uint16_t *led_output = NULL;
323 uint16_t *led_output2 = NULL;
324 uint8_t *ledsbuff = NULL;
325 int num_leds_per_strip;
326 int _numstrips;
327 int currentframe;
328
329 uint8_t __green_map[256];
330 uint8_t __blue_map[256];
331 uint8_t __red_map[256];
332 uint8_t __white_map[256];
333 uint8_t _brightness;
334 float _gammar, _gammab, _gammag, _gammaw;
335
336 void setBrightness(int brightness) {
337 _brightness = brightness;
338 float tmp;
339 for (int i = 0; i < 256; i++) {
340 tmp = powf((float)i / 255, 1 / _gammag);
341 __green_map[i] = (uint8_t)(tmp * brightness);
342 tmp = powf((float)i / 255, 1 / _gammab);
343 __blue_map[i] = (uint8_t)(tmp * brightness);
344 tmp = powf((float)i / 255, 1 / _gammar);
345 __red_map[i] = (uint8_t)(tmp * brightness);
346 tmp = powf((float)i / 255, 1 / _gammaw);
347 __white_map[i] = (uint8_t)(tmp * brightness);
348 }
349 }
350
351 void setGamma(float gammar, float gammab, float gammag, float gammaw) {
352 _gammag = gammag;
353 _gammar = gammar;
354 _gammaw = gammaw;
355 _gammab = gammab;
356 setBrightness(_brightness);
357 }
358
359 void setGamma(float gammar, float gammab, float gammag) {
360 _gammag = gammag;
361 _gammar = gammar;
362 _gammab = gammab;
363 setBrightness(_brightness);
364 }
365
366 void _initled(uint8_t *leds, const int *pins, int numstrip,
367 int NUM_LED_PER_STRIP) {
368
369 // esp_lcd_panel_io_handle_t init_lcd_driver(unsigned int
370 // FASTLED_ESP32S3_I2S_CLOCK_HZ, size_t _nb_components) {
371
372 esp_lcd_i80_bus_handle_t i80_bus = NULL;
373
374 esp_lcd_i80_bus_config_t bus_config;
375
376 bus_config.clk_src = LCD_CLK_SRC_PLL160M;
377 bus_config.dc_gpio_num = 0;
378 bus_config.wr_gpio_num = 0;
379 // bus_config.data_gpio_nums = (int*)malloc(16*sizeof(int));
380 for (int i = 0; i < numstrip; i++) {
381 bus_config.data_gpio_nums[i] = pins[i];
382 }
383 if (numstrip < 16) {
384 for (int i = numstrip; i < 16; i++) {
385 bus_config.data_gpio_nums[i] = 0;
386 }
387 }
388 bus_config.bus_width = 16;
389 bus_config.max_transfer_bytes =
390 _nb_components * NUM_LED_PER_STRIP * 8 * 3 * 2 + __OFFSET + __OFFSET_END;
391 #if IDF_5_4_OR_EARLIER
392 #pragma GCC diagnostic push
393 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
394 #endif
395 // In IDF 5.3, psram_trans_align became deprecated. We kick the can down
396 // the road a little bit and suppress the warning until idf 5.5 arrives.
397 bus_config.psram_trans_align = LCD_DRIVER_PSRAM_DATA_ALIGNMENT;
398 bus_config.sram_trans_align = 4;
399 #if IDF_5_4_OR_EARLIER
400 #pragma GCC diagnostic pop
401 #endif
402
403 esp_err_t bus_err = esp_lcd_new_i80_bus(&bus_config, &i80_bus);
404 FASTLED_ASSERT(bus_err == ESP_OK, "Failed to create ESP32 I2S LCD bus");
405
406 esp_lcd_panel_io_i80_config_t io_config;
407
408 io_config.cs_gpio_num = -1;
409 io_config.pclk_hz = FASTLED_ESP32S3_I2S_CLOCK_HZ;
410 io_config.trans_queue_depth = 1;
411 io_config.dc_levels = {
412 .dc_idle_level = 0,
413 .dc_cmd_level = 0,
414 .dc_dummy_level = 0,
415 .dc_data_level = 1,
416 };
417 //.on_color_trans_done = flush_ready,
418 // .user_ctx = nullptr,
419 io_config.lcd_cmd_bits = 0;
420 io_config.lcd_param_bits = 0;
421 io_config.user_ctx = this;
422
423 io_config.on_color_trans_done = flush_ready;
424 esp_err_t panel_err = esp_lcd_new_panel_io_i80(i80_bus, &io_config, &led_io_handle);
425 FASTLED_ASSERT(panel_err == ESP_OK, "Failed to create ESP32 I2S LCD panel IO");
426 }
427
428 void initled(uint8_t *leds, const int *pins, int numstrip,
429 int NUM_LED_PER_STRIP) {
430 currentframe = 0;
431 _gammab = 1;
432 _gammar = 1;
433 _gammag = 1;
434 _gammaw = 1;
435 setBrightness(255);
436 if (I2SClocklessLedDriverS3_sem == NULL) {
437 I2SClocklessLedDriverS3_sem = xSemaphoreCreateBinary();
438 }
439 // esp_lcd_panel_io_handle_t init_lcd_driver(unsigned int
440 // FASTLED_ESP32S3_I2S_CLOCK_HZ, size_t _nb_components) {
441 led_output = (uint16_t *)heap_caps_aligned_alloc(
442 LCD_DRIVER_PSRAM_DATA_ALIGNMENT,
443 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
444 __OFFSET_END,
445 MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
446 memset(led_output, 0,
447 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
448 __OFFSET_END);
449
450 led_output2 = (uint16_t *)heap_caps_aligned_alloc(
451 LCD_DRIVER_PSRAM_DATA_ALIGNMENT,
452 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
453 __OFFSET_END,
454 MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
455 memset(led_output2, 0,
456 8 * _nb_components * NUM_LED_PER_STRIP * 3 * 2 + __OFFSET +
457 __OFFSET_END);
458 buffers[0] = led_output;
459 buffers[1] = led_output2;
460 // led_output[0] = 0xFFFF; //the +1 because it's like the first value
461 // doesnt get pushed do not ask me why for now
462 // led_output2[0] = 0xFFFF;
463 led_output2 += __OFFSET / 2;
464 led_output += __OFFSET / 2;
465
466 for (int i = 0; i < NUM_LED_PER_STRIP * _nb_components * 8; i++) {
467 led_output[3 * i + 1] =
468 0xFFFF; // the +1 because it's like the first value doesnt get
469 // pushed do not ask me why for now
470 led_output2[3 * i + 1] = 0xFFFF;
471 }
472 ledsbuff = leds;
473 _numstrips = numstrip;
474 num_leds_per_strip = NUM_LED_PER_STRIP;
475 _initled(leds, pins, numstrip, NUM_LED_PER_STRIP);
476 }
477
478 void transposeAll(uint16_t *ledoutput) {
479
480 uint16_t ledToDisplay = 0;
481 Lines secondPixel[_nb_components];
482 uint16_t *buff =
483 ledoutput + 2; //+1 pour le premier empty +1 pour le 1 systématique
484 uint16_t jump = num_leds_per_strip * _nb_components;
485 for (int j = 0; j < num_leds_per_strip; j++) {
486 uint8_t *poli = ledsbuff + ledToDisplay * _nb_components;
487 for (int i = 0; i < _numstrips; i++) {
488
489 secondPixel[_p_g].bytes[i] = __green_map[*(poli + 1)];
490 secondPixel[_p_r].bytes[i] = __red_map[*(poli + 0)];
491 secondPixel[_p_b].bytes[i] = __blue_map[*(poli + 2)];
492 if (_nb_components > 3)
493 secondPixel[3].bytes[i] = __white_map[*(poli + 3)];
494 // #endif
495 poli += jump;
496 }
497 ledToDisplay++;
498 transpose16x1_noinline2(secondPixel[0].bytes, buff);
499 buff += 24;
500 transpose16x1_noinline2(secondPixel[1].bytes, buff);
501 buff += 24;
502 transpose16x1_noinline2(secondPixel[2].bytes, buff);
503 buff += 24;
504 if (_nb_components > 3) {
505 transpose16x1_noinline2(secondPixel[3].bytes, buff);
506 buff += 24;
507 }
508 }
509 }
510
511 void show() {
512 transposeAll(buffers[currentframe]);
513 if (isDisplaying) {
514 // Serial.println("on display dejà");
515 iswaiting = true;
516 if (I2SClocklessLedDriverS3_sem == NULL)
517 I2SClocklessLedDriverS3_sem = xSemaphoreCreateBinary();
518 xSemaphoreTake(I2SClocklessLedDriverS3_sem, portMAX_DELAY);
519 }
520 isDisplaying = true;
521
522 if (FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS) {
523 delayMicroseconds(FASTLED_EXPERIMENTAL_YVES_EXTRA_WAIT_MICROS);
524 }
525
526 led_io_handle->tx_color(led_io_handle, 0x2C, buffers[currentframe],
527 _nb_components * num_leds_per_strip * 8 * 3 *
528 2 +
529 __OFFSET + __OFFSET_END);
530
531 currentframe = (currentframe + 1) % 2;
532 }
533};
534
535static bool IRAM_ATTR flush_ready(esp_lcd_panel_io_handle_t panel_io,
536 esp_lcd_panel_io_event_data_t *edata,
537 void *user_ctx) {
538 DRIVER_READY = true;
539 isDisplaying = false;
540 I2SClocklessLedDriveresp32S3 *cont =
541 (I2SClocklessLedDriveresp32S3 *)user_ctx;
542 cont->testcount++;
543 if (iswaiting) {
544 portBASE_TYPE HPTaskAwoken = 0;
545 iswaiting = false;
546 xSemaphoreGiveFromISR(I2SClocklessLedDriverS3_sem, &HPTaskAwoken);
547 if (HPTaskAwoken == pdTRUE)
548 portYIELD_FROM_ISR(HPTaskAwoken);
549 }
550 return false;
551}
552
553#pragma GCC diagnostic pop
554
555} // namespace fl
556
557#pragma pop_macro("AA")
558#pragma pop_macro("CC")
559#pragma pop_macro("FF")
560#pragma pop_macro("FF2")
561
562#endif // FL_HAS_INCLUDE("esp_memory_utils.h")
CRGB leds[NUM_LEDS]
int y
Definition simple.h:93
int x
Definition simple.h:92
UISlider brightness("Brightness", 128, 0, 255, 1)
static uint32_t t
Definition Luminova.h:54
__SIZE_TYPE__ size_t
Definition cstddef.h:17
IMPORTANT!
Definition crgb.h:20