14
14
// #include <sys/types.h>
15
15
// #include <sys/ioctl.h>
16
16
17
+ #ifdef BENCHMARK
18
+ #include < time.h>
19
+ #endif
20
+
17
21
// hyperion local includes
18
22
#include " LedDeviceWS2812b.h"
19
23
230
234
LedDeviceWS2812b::LedDeviceWS2812b () :
231
235
LedDevice(),
232
236
mLedCount(0 )
237
+
238
+ #ifdef BENCHMARK
239
+ ,
240
+ runCount (0 ),
241
+ combinedNseconds(0 ),
242
+ shortestNseconds(2147483647 )
243
+ #endif
244
+
233
245
{
246
+ // shortestNseconds = 2147483647;
234
247
// Init PWM generator and clear LED buffer
235
248
initHardware ();
236
249
// clearLEDBuffer();
250
+ printf (" WS2812b init finished \n " );
237
251
}
238
252
239
253
240
254
int LedDeviceWS2812b::write (const std::vector<ColorRgb> &ledValues)
241
255
{
256
+ #ifdef BENCHMARK
257
+ timespec timeStart;
258
+ timespec timeEnd;
259
+ clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &timeStart);
260
+ #endif
261
+
242
262
mLedCount = ledValues.size ();
243
263
// printf("Set leds, number: %d\n", mLedCount);
244
264
245
- // const unsigned dataLen = ledValues.size() * sizeof(ColorRgb);
246
- // const uint8_t * dataPtr = reinterpret_cast<const uint8_t *>(ledValues.data());
247
-
248
265
// Clear out the PWM buffer
249
266
// Disabled, because we will overwrite the buffer anyway.
250
267
251
268
// Read data from LEDBuffer[], translate it into wire format, and write to PWMWaveform
252
- // unsigned int LEDBuffeWordPos = 0;
253
- // unsigned int PWMWaveformBitPos = 0;
254
269
unsigned int colorBits = 0 ; // Holds the GRB color before conversion to wire bit pattern
255
- unsigned char colorBit = 0 ; // Holds current bit out of colorBits to be processed
256
270
unsigned int wireBit = 0 ; // Holds the current bit we will set in PWMWaveform
257
- // Color_t color;
258
271
259
272
for (size_t i=0 ; i<mLedCount ; i++) {
260
273
// Create bits necessary to represent one color triplet (in GRB, not RGB, order)
@@ -265,7 +278,12 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
265
278
266
279
// Iterate through color bits to get wire bits
267
280
for (int j=23 ; j>=0 ; j--) {
268
- colorBit = (colorBits & (1 << j)) ? 1 : 0 ;
281
+ unsigned char colorBit = (colorBits & (1 << j)) ? 1 : 0 ; // Holds current bit out of colorBits to be processed
282
+
283
+ setPWMBit (wireBit++, 1 );
284
+ setPWMBit (wireBit++, colorBit);
285
+ setPWMBit (wireBit++, 0 );
286
+ /* old code for better understanding
269
287
switch(colorBit) {
270
288
case 1:
271
289
//wireBits = 0b110; // High, High, Low
@@ -279,13 +297,13 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
279
297
setPWMBit(wireBit++, 0);
280
298
setPWMBit(wireBit++, 0);
281
299
break;
282
- }
300
+ }*/
283
301
}
284
302
}
285
303
286
304
// Copy PWM waveform to DMA's data buffer
287
305
// printf("Copying %d words to DMA data buffer\n", NUM_DATA_WORDS);
288
- ctl = (struct control_data_s *)virtbase;
306
+ struct control_data_s * ctl = (struct control_data_s *)virtbase;
289
307
dma_cb_t *cbp = ctl->cb ;
290
308
291
309
// 72 bits per pixel / 32 bits per word = 2.25 words per pixel
@@ -298,10 +316,10 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
298
316
299
317
// This block is a major CPU hog when there are lots of pixels to be transmitted.
300
318
// It would go quicker with DMA.
301
- for (unsigned int i = 0 ; i < (cbp->length / 4 ); i++) {
302
- ctl->sample [i] = PWMWaveform[i];
303
- }
304
-
319
+ // for(unsigned int i = 0; i < (cbp->length / 4); i++) {
320
+ // ctl->sample[i] = PWMWaveform[i];
321
+ // }
322
+ memcpy ( ctl-> sample , PWMWaveform, cbp-> length ); // memcpy does the same and is potentially faster
305
323
306
324
// Enable DMA and PWM engines, which should now send the data
307
325
startTransfer ();
@@ -312,6 +330,20 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
312
330
// printf("Delay for %d μSec\n", (int)bitTimeUSec);
313
331
// usleep((int)bitTimeUSec);
314
332
333
+ #ifdef BENCHMARK
334
+ clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &timeEnd);
335
+ timespec result;
336
+
337
+ result.tv_sec = timeEnd.tv_sec - timeStart.tv_sec ;
338
+ result.tv_nsec = timeEnd.tv_nsec - timeStart.tv_nsec ;
339
+ if (result.tv_nsec < 0 ) {
340
+ result.tv_nsec = 1e9 - result.tv_nsec ;
341
+ result.tv_sec -= 1 ;
342
+ }
343
+ runCount ++;
344
+ combinedNseconds += result.tv_nsec ;
345
+ shortestNseconds = result.tv_nsec < shortestNseconds ? result.tv_nsec : shortestNseconds;
346
+ #endif
315
347
return 0 ;
316
348
}
317
349
@@ -325,6 +357,10 @@ LedDeviceWS2812b::~LedDeviceWS2812b()
325
357
// Exit cleanly, freeing memory and stopping the DMA & PWM engines
326
358
// We trap all signals (including Ctrl+C), so even if you don't get here, it terminates correctly
327
359
terminate (0 );
360
+ #ifdef BENCHMARK
361
+ printf (" WS2812b Benchmark results: Runs %d - Avarage %lu (n) - Minimum %ld (n)\n " ,
362
+ runCount, (runCount > 0 ? combinedNseconds / runCount : 0 ), shortestNseconds);
363
+ #endif
328
364
}
329
365
330
366
@@ -576,7 +612,7 @@ void LedDeviceWS2812b::initHardware() {
576
612
577
613
// Set up control block
578
614
// ---------------------------------------------------------------
579
- ctl = (struct control_data_s *)virtbase;
615
+ struct control_data_s * ctl = (struct control_data_s *)virtbase;
580
616
dma_cb_t *cbp = ctl->cb ;
581
617
// FIXME: Change this to use DEFINEs
582
618
unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18 ;
@@ -724,7 +760,7 @@ void LedDeviceWS2812b::initHardware() {
724
760
// Begin the transfer
725
761
void LedDeviceWS2812b::startTransfer () {
726
762
// Enable DMA
727
- dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys (ctl ->cb );
763
+ dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys ((( struct control_data_s *) virtbase) ->cb );
728
764
dma_reg[DMA_CS] = DMA_CS_CONFIGWORD | (1 << DMA_CS_ACTIVE);
729
765
usleep (100 );
730
766
0 commit comments