mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Added benchmark define
some code cleanup and speedups Former-commit-id: 8254c34e1d10c598e127f46635ae6bafcb97087a
This commit is contained in:
parent
39ddfca5c0
commit
a92967fa7c
@ -14,6 +14,10 @@
|
||||
//#include <sys/types.h>
|
||||
//#include <sys/ioctl.h>
|
||||
|
||||
#ifdef BENCHMARK
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
// hyperion local includes
|
||||
#include "LedDeviceWS2812b.h"
|
||||
|
||||
@ -230,31 +234,40 @@
|
||||
LedDeviceWS2812b::LedDeviceWS2812b() :
|
||||
LedDevice(),
|
||||
mLedCount(0)
|
||||
|
||||
#ifdef BENCHMARK
|
||||
,
|
||||
runCount(0),
|
||||
combinedNseconds(0),
|
||||
shortestNseconds(2147483647)
|
||||
#endif
|
||||
|
||||
{
|
||||
//shortestNseconds = 2147483647;
|
||||
// Init PWM generator and clear LED buffer
|
||||
initHardware();
|
||||
//clearLEDBuffer();
|
||||
printf("WS2812b init finished \n");
|
||||
}
|
||||
|
||||
|
||||
int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
#ifdef BENCHMARK
|
||||
timespec timeStart;
|
||||
timespec timeEnd;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &timeStart);
|
||||
#endif
|
||||
|
||||
mLedCount = ledValues.size();
|
||||
//printf("Set leds, number: %d\n", mLedCount);
|
||||
|
||||
// const unsigned dataLen = ledValues.size() * sizeof(ColorRgb);
|
||||
// const uint8_t * dataPtr = reinterpret_cast<const uint8_t *>(ledValues.data());
|
||||
|
||||
// Clear out the PWM buffer
|
||||
// Disabled, because we will overwrite the buffer anyway.
|
||||
|
||||
// Read data from LEDBuffer[], translate it into wire format, and write to PWMWaveform
|
||||
// unsigned int LEDBuffeWordPos = 0;
|
||||
// unsigned int PWMWaveformBitPos = 0;
|
||||
unsigned int colorBits = 0; // Holds the GRB color before conversion to wire bit pattern
|
||||
unsigned char colorBit = 0; // Holds current bit out of colorBits to be processed
|
||||
unsigned int wireBit = 0; // Holds the current bit we will set in PWMWaveform
|
||||
// Color_t color;
|
||||
|
||||
for(size_t i=0; i<mLedCount; i++) {
|
||||
// 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)
|
||||
|
||||
// Iterate through color bits to get wire bits
|
||||
for(int j=23; j>=0; j--) {
|
||||
colorBit = (colorBits & (1 << j)) ? 1 : 0;
|
||||
unsigned char colorBit = (colorBits & (1 << j)) ? 1 : 0; // Holds current bit out of colorBits to be processed
|
||||
|
||||
setPWMBit(wireBit++, 1);
|
||||
setPWMBit(wireBit++, colorBit);
|
||||
setPWMBit(wireBit++, 0);
|
||||
/* old code for better understanding
|
||||
switch(colorBit) {
|
||||
case 1:
|
||||
//wireBits = 0b110; // High, High, Low
|
||||
@ -279,13 +297,13 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
||||
setPWMBit(wireBit++, 0);
|
||||
setPWMBit(wireBit++, 0);
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// Copy PWM waveform to DMA's data buffer
|
||||
//printf("Copying %d words to DMA data buffer\n", NUM_DATA_WORDS);
|
||||
ctl = (struct control_data_s *)virtbase;
|
||||
struct control_data_s *ctl = (struct control_data_s *)virtbase;
|
||||
dma_cb_t *cbp = ctl->cb;
|
||||
|
||||
// 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)
|
||||
|
||||
// This block is a major CPU hog when there are lots of pixels to be transmitted.
|
||||
// It would go quicker with DMA.
|
||||
for(unsigned int i = 0; i < (cbp->length / 4); i++) {
|
||||
ctl->sample[i] = PWMWaveform[i];
|
||||
}
|
||||
|
||||
// for(unsigned int i = 0; i < (cbp->length / 4); i++) {
|
||||
// ctl->sample[i] = PWMWaveform[i];
|
||||
// }
|
||||
memcpy ( ctl->sample, PWMWaveform, cbp->length ); // memcpy does the same and is potentially faster
|
||||
|
||||
// Enable DMA and PWM engines, which should now send the data
|
||||
startTransfer();
|
||||
@ -312,6 +330,20 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
||||
//printf("Delay for %d μSec\n", (int)bitTimeUSec);
|
||||
//usleep((int)bitTimeUSec);
|
||||
|
||||
#ifdef BENCHMARK
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &timeEnd);
|
||||
timespec result;
|
||||
|
||||
result.tv_sec = timeEnd.tv_sec - timeStart.tv_sec;
|
||||
result.tv_nsec = timeEnd.tv_nsec - timeStart.tv_nsec;
|
||||
if (result.tv_nsec < 0) {
|
||||
result.tv_nsec = 1e9 - result.tv_nsec;
|
||||
result.tv_sec -= 1;
|
||||
}
|
||||
runCount ++;
|
||||
combinedNseconds += result.tv_nsec;
|
||||
shortestNseconds = result.tv_nsec < shortestNseconds ? result.tv_nsec : shortestNseconds;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -325,6 +357,10 @@ LedDeviceWS2812b::~LedDeviceWS2812b()
|
||||
// Exit cleanly, freeing memory and stopping the DMA & PWM engines
|
||||
// We trap all signals (including Ctrl+C), so even if you don't get here, it terminates correctly
|
||||
terminate(0);
|
||||
#ifdef BENCHMARK
|
||||
printf("WS2812b Benchmark results: Runs %d - Avarage %lu (n) - Minimum %ld (n)\n",
|
||||
runCount, (runCount > 0 ? combinedNseconds / runCount : 0), shortestNseconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -576,7 +612,7 @@ void LedDeviceWS2812b::initHardware() {
|
||||
|
||||
// Set up control block
|
||||
// ---------------------------------------------------------------
|
||||
ctl = (struct control_data_s *)virtbase;
|
||||
struct control_data_s *ctl = (struct control_data_s *)virtbase;
|
||||
dma_cb_t *cbp = ctl->cb;
|
||||
// FIXME: Change this to use DEFINEs
|
||||
unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18;
|
||||
@ -724,7 +760,7 @@ void LedDeviceWS2812b::initHardware() {
|
||||
// Begin the transfer
|
||||
void LedDeviceWS2812b::startTransfer() {
|
||||
// Enable DMA
|
||||
dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(ctl->cb);
|
||||
dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(((struct control_data_s *) virtbase)->cb);
|
||||
dma_reg[DMA_CS] = DMA_CS_CONFIGWORD | (1 << DMA_CS_ACTIVE);
|
||||
usleep(100);
|
||||
|
||||
|
@ -101,6 +101,7 @@
|
||||
// Hyperion includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
//#define BENCHMARK
|
||||
|
||||
// The page map contains pointers to memory that we will allocate below. It uses two pointers
|
||||
// per address. This is because the software (this program) deals only in virtual addresses,
|
||||
@ -150,7 +151,7 @@ private:
|
||||
/// the number of leds (needed when switching off)
|
||||
size_t mLedCount;
|
||||
|
||||
page_map_t *page_map; // This will hold the page map, which we'll allocate below
|
||||
page_map_t *page_map; // This will hold the page map, which we'll allocate
|
||||
uint8_t *virtbase; // Pointer to some virtual memory that will be allocated
|
||||
|
||||
volatile unsigned int *pwm_reg; // PWM controller register set
|
||||
@ -174,7 +175,7 @@ private:
|
||||
uint32_t sample[NUM_DATA_WORDS];
|
||||
};
|
||||
|
||||
struct control_data_s *ctl;
|
||||
//struct control_data_s *ctl;
|
||||
|
||||
// PWM waveform buffer (in words), 16 32-bit words are enough to hold 170 wire bits.
|
||||
// That's OK if we only transmit from the FIFO, but for DMA, we will use a much larger size.
|
||||
@ -193,6 +194,12 @@ private:
|
||||
void fatal(const char *fmt, ...);
|
||||
void * map_peripheral(uint32_t base, uint32_t len);
|
||||
void printBinary(unsigned int i, unsigned int bits);
|
||||
|
||||
#ifdef BENCHMARK
|
||||
unsigned int runCount;
|
||||
long combinedNseconds;
|
||||
long shortestNseconds;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user