SmartLeds.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "SmartLeds.h"
  2. /* PlatformIO 6 (ESP IDF 5) does no longer allow access to RMTMEM,
  3. see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/peripherals.html?highlight=rmtmem#id5
  4. As a dirty workaround, we copy the needed structures from rmt_struct.h
  5. In the long run, this should be replaced! */
  6. typedef struct rmt_item32_s {
  7. union {
  8. struct {
  9. uint32_t duration0 :15;
  10. uint32_t level0 :1;
  11. uint32_t duration1 :15;
  12. uint32_t level1 :1;
  13. };
  14. uint32_t val;
  15. };
  16. } rmt_item32_t;
  17. //Allow access to RMT memory using RMTMEM.chan[0].data32[8]
  18. typedef volatile struct rmt_mem_s {
  19. struct {
  20. rmt_item32_t data32[64];
  21. } chan[8];
  22. } rmt_mem_t;
  23. extern rmt_mem_t RMTMEM;
  24. IsrCore SmartLed::_interruptCore = CoreCurrent;
  25. intr_handle_t SmartLed::_interruptHandle = NULL;
  26. SmartLed*& IRAM_ATTR SmartLed::ledForChannel( int channel ) {
  27. static SmartLed* table[8] = { nullptr };
  28. assert( channel < 8 );
  29. return table[ channel ];
  30. }
  31. void IRAM_ATTR SmartLed::interruptHandler(void*) {
  32. for (int channel = 0; channel != 8; channel++) {
  33. auto self = ledForChannel( channel );
  34. if ( RMT.int_st.val & (1 << (24 + channel ) ) ) { // tx_thr_event
  35. if ( self )
  36. self->copyRmtHalfBlock();
  37. RMT.int_clr.val |= 1 << ( 24 + channel );
  38. } else if ( RMT.int_st.val & ( 1 << (3 * channel ) ) ) { // tx_end
  39. if ( self )
  40. xSemaphoreGiveFromISR( self->_finishedFlag, nullptr );
  41. RMT.int_clr.val |= 1 << ( 3 * channel );
  42. }
  43. }
  44. }
  45. void IRAM_ATTR SmartLed::copyRmtHalfBlock() {
  46. int offset = detail::MAX_PULSES * _halfIdx;
  47. _halfIdx = !_halfIdx;
  48. int len = 3 - _componentPosition + 3 * ( _count - 1 );
  49. len = std::min( len, detail::MAX_PULSES / 8 );
  50. if ( !len ) {
  51. for ( int i = 0; i < detail::MAX_PULSES; i++) {
  52. RMTMEM.chan[ _channel].data32[i + offset ].val = 0;
  53. }
  54. }
  55. int i;
  56. for ( i = 0; i != len && _pixelPosition != _count; i++ ) {
  57. uint8_t val = _buffer[ _pixelPosition ].getGrb( _componentPosition );
  58. for ( int j = 0; j != 8; j++, val <<= 1 ) {
  59. int bit = val >> 7;
  60. int idx = i * 8 + offset + j;
  61. RMTMEM.chan[ _channel ].data32[ idx ].val = _bitToRmt[ bit & 0x01 ].value;
  62. }
  63. if ( _pixelPosition == _count - 1 && _componentPosition == 2 ) {
  64. RMTMEM.chan[ _channel ].data32[ i * 8 + offset + 7 ].duration1 =
  65. _timing.TRS / ( detail::RMT_DURATION_NS * detail::DIVIDER );
  66. }
  67. _componentPosition++;
  68. if ( _componentPosition == 3 ) {
  69. _componentPosition = 0;
  70. _pixelPosition++;
  71. }
  72. }
  73. for ( i *= 8; i != detail::MAX_PULSES; i++ ) {
  74. RMTMEM.chan[ _channel ].data32[ i + offset ].val = 0;
  75. }
  76. }