Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit 8254c34

Browse files
committed
Added benchmark define
some code cleanup and speedups
1 parent 83c92c9 commit 8254c34

File tree

2 files changed

+61
-18
lines changed

2 files changed

+61
-18
lines changed

libsrc/leddevice/LedDeviceWS2812b.cpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
//#include <sys/types.h>
1515
//#include <sys/ioctl.h>
1616

17+
#ifdef BENCHMARK
18+
#include <time.h>
19+
#endif
20+
1721
// hyperion local includes
1822
#include "LedDeviceWS2812b.h"
1923

@@ -230,31 +234,40 @@
230234
LedDeviceWS2812b::LedDeviceWS2812b() :
231235
LedDevice(),
232236
mLedCount(0)
237+
238+
#ifdef BENCHMARK
239+
,
240+
runCount(0),
241+
combinedNseconds(0),
242+
shortestNseconds(2147483647)
243+
#endif
244+
233245
{
246+
//shortestNseconds = 2147483647;
234247
// Init PWM generator and clear LED buffer
235248
initHardware();
236249
//clearLEDBuffer();
250+
printf("WS2812b init finished \n");
237251
}
238252

239253

240254
int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
241255
{
256+
#ifdef BENCHMARK
257+
timespec timeStart;
258+
timespec timeEnd;
259+
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &timeStart);
260+
#endif
261+
242262
mLedCount = ledValues.size();
243263
//printf("Set leds, number: %d\n", mLedCount);
244264

245-
// const unsigned dataLen = ledValues.size() * sizeof(ColorRgb);
246-
// const uint8_t * dataPtr = reinterpret_cast<const uint8_t *>(ledValues.data());
247-
248265
// Clear out the PWM buffer
249266
// Disabled, because we will overwrite the buffer anyway.
250267

251268
// Read data from LEDBuffer[], translate it into wire format, and write to PWMWaveform
252-
// unsigned int LEDBuffeWordPos = 0;
253-
// unsigned int PWMWaveformBitPos = 0;
254269
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
256270
unsigned int wireBit = 0; // Holds the current bit we will set in PWMWaveform
257-
// Color_t color;
258271

259272
for(size_t i=0; i<mLedCount; i++) {
260273
// 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)
265278

266279
// Iterate through color bits to get wire bits
267280
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
269287
switch(colorBit) {
270288
case 1:
271289
//wireBits = 0b110; // High, High, Low
@@ -279,13 +297,13 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
279297
setPWMBit(wireBit++, 0);
280298
setPWMBit(wireBit++, 0);
281299
break;
282-
}
300+
}*/
283301
}
284302
}
285303

286304
// Copy PWM waveform to DMA's data buffer
287305
//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;
289307
dma_cb_t *cbp = ctl->cb;
290308

291309
// 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)
298316

299317
// This block is a major CPU hog when there are lots of pixels to be transmitted.
300318
// 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
305323

306324
// Enable DMA and PWM engines, which should now send the data
307325
startTransfer();
@@ -312,6 +330,20 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
312330
//printf("Delay for %d μSec\n", (int)bitTimeUSec);
313331
//usleep((int)bitTimeUSec);
314332

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
315347
return 0;
316348
}
317349

@@ -325,6 +357,10 @@ LedDeviceWS2812b::~LedDeviceWS2812b()
325357
// Exit cleanly, freeing memory and stopping the DMA & PWM engines
326358
// We trap all signals (including Ctrl+C), so even if you don't get here, it terminates correctly
327359
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
328364
}
329365

330366

@@ -576,7 +612,7 @@ void LedDeviceWS2812b::initHardware() {
576612

577613
// Set up control block
578614
// ---------------------------------------------------------------
579-
ctl = (struct control_data_s *)virtbase;
615+
struct control_data_s *ctl = (struct control_data_s *)virtbase;
580616
dma_cb_t *cbp = ctl->cb;
581617
// FIXME: Change this to use DEFINEs
582618
unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18;
@@ -724,7 +760,7 @@ void LedDeviceWS2812b::initHardware() {
724760
// Begin the transfer
725761
void LedDeviceWS2812b::startTransfer() {
726762
// 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);
728764
dma_reg[DMA_CS] = DMA_CS_CONFIGWORD | (1 << DMA_CS_ACTIVE);
729765
usleep(100);
730766

libsrc/leddevice/LedDeviceWS2812b.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
// Hyperion includes
102102
#include <leddevice/LedDevice.h>
103103

104+
//#define BENCHMARK
104105

105106
// The page map contains pointers to memory that we will allocate below. It uses two pointers
106107
// per address. This is because the software (this program) deals only in virtual addresses,
@@ -150,7 +151,7 @@ class LedDeviceWS2812b : public LedDevice
150151
/// the number of leds (needed when switching off)
151152
size_t mLedCount;
152153

153-
page_map_t *page_map; // This will hold the page map, which we'll allocate below
154+
page_map_t *page_map; // This will hold the page map, which we'll allocate
154155
uint8_t *virtbase; // Pointer to some virtual memory that will be allocated
155156

156157
volatile unsigned int *pwm_reg; // PWM controller register set
@@ -174,7 +175,7 @@ class LedDeviceWS2812b : public LedDevice
174175
uint32_t sample[NUM_DATA_WORDS];
175176
};
176177

177-
struct control_data_s *ctl;
178+
//struct control_data_s *ctl;
178179

179180
// PWM waveform buffer (in words), 16 32-bit words are enough to hold 170 wire bits.
180181
// That's OK if we only transmit from the FIFO, but for DMA, we will use a much larger size.
@@ -193,6 +194,12 @@ class LedDeviceWS2812b : public LedDevice
193194
void fatal(const char *fmt, ...);
194195
void * map_peripheral(uint32_t base, uint32_t len);
195196
void printBinary(unsigned int i, unsigned int bits);
197+
198+
#ifdef BENCHMARK
199+
unsigned int runCount;
200+
long combinedNseconds;
201+
long shortestNseconds;
202+
#endif
196203
};
197204

198205

0 commit comments

Comments
 (0)