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