Lixie-Labs / Emotiscope

Let your eyes enjoy the music too ✨ Extremely low-latency audio processing lets LEDs perfectly synchronize to your music's notation and tempo.
GNU General Public License v3.0
27 stars 5 forks source link

APA102 support #112

Open chrismiller opened 3 weeks ago

chrismiller commented 3 weeks ago

I was looking to see how feasible it would be to use APA102 strips with this project, but this comment and the associated custom RMT driver made me think it wouldn't be easy. However I see that as of a couple of weeks ago, FastLED 3.7.0 now has support for ESP-IDF version 5.x. Does that mean it would be possible to switch back to using FastLED, and hence gain support for APA102 (and other) LED strip types?

connornishijima commented 2 weeks ago

Let me investigate soon! FastLED releases only come once a millenia, (I can't believe they just barely added RP2040 from 2020) so I'm curious to try it out!

Emotiscope uses a custom RMT driver for the LEDs since it allowed the use of non-blocking DMA frame transmissions to the LEDs while the next frame is rendering on the GPU core, which is a big contributor to the existing speed. (The 128 WS2812B compatibles inside are quite limited by their 8-bit resolution, so Emotiscope uses dithering at 200-500 FPS on two strands of 64 LEDs to trick your eyes into seeing better color reproduction.)

You could in theory re-include the FastLED library, let Emotiscope do all its custom stuff during rendering, then pass the dithered 8-bit image to FastLED for output at the very last step:

Before (in led_driver.h):

// Get to safety, THE PHOTONS ARE COMING!!!
if( filesystem_ready == true ){
    rmt_transmit( tx_chan_a, led_encoder_a, raw_led_data, (sizeof(raw_led_data) >> 1), &tx_config);
    rmt_transmit( tx_chan_b, led_encoder_b, raw_led_data+((NUM_LEDS>>1)*3), (sizeof(raw_led_data) >> 1), &tx_config );
}

After:

// Get to safety, THE PHOTONS ARE COMING!!!
if( filesystem_ready == true ){
    FastLED.show()
}

You can pass the existing "raw_led_data[NUM_LEDS]" CRGB array to FastLED.begin(), then comment my homebrew CRGB typedef out of "types.h". That way you can change the GPIO and LED type to your liking during FastLED.begin(), which you can shim inside "init_rmt_driver()" in led_driver.h.

chrismiller commented 2 weeks ago

You could in theory re-include the FastLED library, let Emotiscope do all its custom stuff during rendering, then pass the dithered 8-bit image to FastLED for output at the very last step

Thanks for the pointers! I'd come to a similar conclusion and was trying to get FastLED compiling into the project yesterday. I haven't had much luck yet since I seem to have version mismatch issues between FastLED and the ESP32 libraries. FastLED's clockless_rmt_esp32.h / cpp code seems to depend on an old IDF version (for example one error I get is with this line, which I believe should now use mem_rd_rst_chn?), though this commit implies IDF 5.x should be supported. I must point out however I'm fairly clueless about ESP32 and C library dependencies in general, so there's a high chance I'm just doing something dumb! I'll continue to play around with it this weekend and hopefully figure out where I'm going wrong.

EDIT: It seems like I'm not the only one hitting this: https://github.com/FastLED/FastLED/issues/1628, also here: https://github.com/FastLED/FastLED/issues/1631. And I also found another ESP32-S3 related issue: https://github.com/FastLED/FastLED/issues/1615.

One thing I was thinking is that with APA102s it should be possible to skip the gamma correction and dithering steps, since APA102s have much better dynamic range than WS2812s, plus I see that FastLED 3.7.0 now supports hardware gamma correction for them using the extra 5 "brightness" bits they provide.