9
9
#endif
10
10
11
11
#include " idf5_rmt.h"
12
- #include " rmt_worker_pool.h"
13
12
14
13
#include " freertos/FreeRTOS.h"
15
14
#include " freertos/task.h"
18
17
#include " fl/convert.h" // for convert_fastled_timings_to_timedeltas(...)
19
18
#include " fl/namespace.h"
20
19
#include " strip_rmt.h"
21
- #include " platforms/esp/32/esp_log_control.h"
22
- #include " esp_log.h"
23
20
24
21
25
22
#define IDF5_RMT_TAG " idf5_rmt.cpp"
26
23
27
- // Worker pool configuration
28
- // Enable worker pool by default - can be disabled via compile flag
29
- #ifndef FASTLED_RMT5_DISABLE_WORKER_POOL
30
- #define FASTLED_RMT5_USE_WORKER_POOL 1
31
- #else
32
- #define FASTLED_RMT5_USE_WORKER_POOL 0
33
- #endif
34
-
35
- // Runtime worker pool control (can be overridden in constructor)
36
- #ifndef FASTLED_RMT5_FORCE_LEGACY_MODE
37
- #define FASTLED_RMT5_FORCE_LEGACY_MODE 0
38
- #endif
39
-
40
24
namespace fl {
41
25
26
+
42
27
RmtController5::RmtController5 (int DATA_PIN, int T1, int T2, int T3, RmtController5::DmaMode dma_mode)
43
- : mPin (DATA_PIN), mT1 (T1), mT2 (T2), mT3 (T3), mDmaMode (dma_mode)
44
- , mWorkerConfig (nullptr )
45
- , mRegisteredWithPool (false )
46
- , mUseWorkerPool (FASTLED_RMT5_USE_WORKER_POOL && !FASTLED_RMT5_FORCE_LEGACY_MODE) {
47
-
48
- if (mUseWorkerPool ) {
49
- // Register with worker pool
50
- RmtWorkerPool::getInstance ().registerController (this );
51
- mRegisteredWithPool = true ;
52
- FASTLED_ESP_LOGD (IDF5_RMT_TAG, " RmtController5 registered with worker pool (pin %d)" , mPin );
53
- } else {
54
- FASTLED_ESP_LOGD (IDF5_RMT_TAG, " RmtController5 using legacy mode (pin %d)" , mPin );
55
- }
28
+ : mPin (DATA_PIN), mT1 (T1), mT2 (T2), mT3 (T3), mDmaMode (dma_mode) {
56
29
}
57
30
58
31
RmtController5::~RmtController5 () {
59
- if (mRegisteredWithPool ) {
60
- RmtWorkerPool::getInstance ().unregisterController (this );
61
- }
62
-
63
32
if (mLedStrip ) {
64
33
delete mLedStrip ;
65
34
}
66
-
67
- if (mWorkerConfig ) {
68
- delete mWorkerConfig ;
69
- }
70
35
}
71
36
72
- IRmtStrip::DmaMode RmtController5::convertDmaMode ( DmaMode dma_mode) {
37
+ static IRmtStrip::DmaMode convertDmaMode ( RmtController5::DmaMode dma_mode) {
73
38
switch (dma_mode) {
74
- case DMA_AUTO:
39
+ case RmtController5:: DMA_AUTO:
75
40
return IRmtStrip::DMA_AUTO;
76
- case DMA_ENABLED:
41
+ case RmtController5:: DMA_ENABLED:
77
42
return IRmtStrip::DMA_ENABLED;
78
- case DMA_DISABLED:
43
+ case RmtController5:: DMA_DISABLED:
79
44
return IRmtStrip::DMA_DISABLED;
80
45
default :
81
46
FL_ASSERT (false , " Invalid DMA mode" );
@@ -84,141 +49,42 @@ IRmtStrip::DmaMode RmtController5::convertDmaMode(DmaMode dma_mode) {
84
49
}
85
50
86
51
void RmtController5::loadPixelData (PixelIterator &pixels) {
87
- if (mUseWorkerPool ) {
88
- // Worker pool mode - store pixel data in persistent buffer
89
- storePixelData (pixels);
90
- } else {
91
- // Legacy mode - use direct RMT strip
92
- const bool is_rgbw = pixels.get_rgbw ().active ();
93
- if (!mLedStrip ) {
94
- uint16_t t0h, t0l, t1h, t1l;
95
- convert_fastled_timings_to_timedeltas (mT1 , mT2 , mT3 , &t0h, &t0l, &t1h, &t1l);
96
- mLedStrip = IRmtStrip::Create (
97
- mPin , pixels.size (),
98
- is_rgbw, t0h, t0l, t1h, t1l, 280 ,
99
- convertDmaMode (mDmaMode ));
100
-
101
- } else {
102
- FASTLED_ASSERT (
103
- mLedStrip ->numPixels () == pixels.size (),
104
- " mLedStrip->numPixels() (" << mLedStrip ->numPixels () << " ) != pixels.size() (" << pixels.size () << " )" );
105
- }
52
+ const bool is_rgbw = pixels.get_rgbw ().active ();
53
+ if (!mLedStrip ) {
54
+ uint16_t t0h, t0l, t1h, t1l;
55
+ convert_fastled_timings_to_timedeltas (mT1 , mT2 , mT3 , &t0h, &t0l, &t1h, &t1l);
56
+ mLedStrip = IRmtStrip::Create (
57
+ mPin , pixels.size (),
58
+ is_rgbw, t0h, t0l, t1h, t1l, 280 ,
59
+ convertDmaMode (mDmaMode ));
106
60
107
- if (is_rgbw) {
108
- uint8_t r, g, b, w;
109
- for (uint16_t i = 0 ; pixels.has (1 ); i++) {
110
- pixels.loadAndScaleRGBW (&r, &g, &b, &w);
111
- mLedStrip ->setPixelRGBW (i, r, g, b, w);
112
- pixels.advanceData ();
113
- pixels.stepDithering ();
114
- }
115
- } else {
116
- uint8_t r, g, b;
117
- for (uint16_t i = 0 ; pixels.has (1 ); i++) {
118
- pixels.loadAndScaleRGB (&r, &g, &b);
119
- mLedStrip ->setPixel (i, r, g, b);
120
- pixels.advanceData ();
121
- pixels.stepDithering ();
122
- }
123
- }
124
- }
125
- }
126
-
127
- void RmtController5::showPixels () {
128
- if (mUseWorkerPool ) {
129
- // Worker pool mode - execute coordinated draw cycle
130
- executeWithWorkerPool ();
131
61
} else {
132
- // Legacy mode - direct async draw
133
- FL_ASSERT ( mLedStrip != nullptr , " RMT strip not initialized " );
134
- mLedStrip ->drawAsync ( );
62
+ FASTLED_ASSERT (
63
+ mLedStrip -> numPixels () == pixels. size (),
64
+ " mLedStrip->numPixels() ( " << mLedStrip -> numPixels () << " ) != pixels.size() ( " << pixels. size () << " ) " );
135
65
}
136
- }
137
-
138
- void RmtController5::storePixelData (PixelIterator& pixels) {
139
- const bool is_rgbw = pixels.get_rgbw ().active ();
140
- const int bytesPerPixel = is_rgbw ? 4 : 3 ;
141
- const int bufferSize = pixels.size () * bytesPerPixel;
142
-
143
- // Resize buffer if needed
144
- mPixelBuffer .resize (bufferSize);
145
-
146
- // Update worker config with current pixel data info
147
- initializeWorkerConfig ();
148
- mWorkerConfig ->ledCount = pixels.size ();
149
- mWorkerConfig ->isRgbw = is_rgbw;
150
-
151
- // Copy pixel data to persistent buffer
152
- uint8_t * bufPtr = mPixelBuffer .data ();
153
66
if (is_rgbw) {
154
- while (pixels. has ( 1 )) {
155
- uint8_t r, g, b, w;
67
+ uint8_t r, g, b, w;
68
+ for ( uint16_t i = 0 ; pixels. has ( 1 ); i++) {
156
69
pixels.loadAndScaleRGBW (&r, &g, &b, &w);
157
- *bufPtr++ = r;
158
- *bufPtr++ = g;
159
- *bufPtr++ = b;
160
- *bufPtr++ = w;
70
+ mLedStrip ->setPixelRGBW (i, r, g, b, w); // Tested to be faster than memcpy of direct bytes.
161
71
pixels.advanceData ();
162
72
pixels.stepDithering ();
163
73
}
164
74
} else {
165
- while (pixels. has ( 1 )) {
166
- uint8_t r, g, b;
75
+ uint8_t r, g, b;
76
+ for ( uint16_t i = 0 ; pixels. has ( 1 ); i++) {
167
77
pixels.loadAndScaleRGB (&r, &g, &b);
168
- *bufPtr++ = r;
169
- *bufPtr++ = g;
170
- *bufPtr++ = b;
78
+ mLedStrip ->setPixel (i, r, g, b); // Tested to be faster than memcpy of direct bytes.
171
79
pixels.advanceData ();
172
80
pixels.stepDithering ();
173
81
}
174
82
}
175
- }
176
-
177
- void RmtController5::executeWithWorkerPool () {
178
- RmtWorkerPool& pool = RmtWorkerPool::getInstance ();
179
-
180
- if (pool.canStartImmediately (this )) {
181
- // Async path - return immediately
182
- pool.startControllerImmediate (this );
183
- } else {
184
- // This controller is queued - must wait for worker
185
- pool.startControllerQueued (this );
186
- }
187
- }
188
-
189
- void RmtController5::initializeWorkerConfig () const {
190
- if (!mWorkerConfig ) {
191
- mWorkerConfig = new RmtWorkerConfig ();
192
-
193
- // Convert FastLED timings to time deltas
194
- uint16_t t0h, t0l, t1h, t1l;
195
- convert_fastled_timings_to_timedeltas (mT1 , mT2 , mT3 , &t0h, &t0l, &t1h, &t1l);
196
-
197
- // Initialize configuration
198
- mWorkerConfig ->pin = mPin ;
199
- mWorkerConfig ->ledCount = 0 ; // Will be set in storePixelData
200
- mWorkerConfig ->isRgbw = false ; // Will be set in storePixelData
201
- mWorkerConfig ->t0h = t0h;
202
- mWorkerConfig ->t0l = t0l;
203
- mWorkerConfig ->t1h = t1h;
204
- mWorkerConfig ->t1l = t1l;
205
- mWorkerConfig ->reset = 280 ;
206
- mWorkerConfig ->dmaMode = convertDmaMode (mDmaMode );
207
- mWorkerConfig ->interruptPriority = 3 ;
208
- }
209
- }
210
-
211
- const RmtWorkerConfig& RmtController5::getWorkerConfig () const {
212
- initializeWorkerConfig ();
213
- return *mWorkerConfig ;
214
- }
215
83
216
- const uint8_t * RmtController5::getPixelBuffer () const {
217
- return mPixelBuffer .data ();
218
84
}
219
85
220
- size_t RmtController5::getBufferSize () const {
221
- return mPixelBuffer . size ();
86
+ void RmtController5::showPixels () {
87
+ mLedStrip -> drawAsync ();
222
88
}
223
89
224
90
} // namespace fl
0 commit comments