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/types.h>
|
||||||
//#include <sys/ioctl.h>
|
//#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#ifdef BENCHMARK
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// hyperion local includes
|
// hyperion local includes
|
||||||
#include "LedDeviceWS2812b.h"
|
#include "LedDeviceWS2812b.h"
|
||||||
|
|
||||||
@ -230,31 +234,40 @@
|
|||||||
LedDeviceWS2812b::LedDeviceWS2812b() :
|
LedDeviceWS2812b::LedDeviceWS2812b() :
|
||||||
LedDevice(),
|
LedDevice(),
|
||||||
mLedCount(0)
|
mLedCount(0)
|
||||||
|
|
||||||
|
#ifdef BENCHMARK
|
||||||
|
,
|
||||||
|
runCount(0),
|
||||||
|
combinedNseconds(0),
|
||||||
|
shortestNseconds(2147483647)
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
|
//shortestNseconds = 2147483647;
|
||||||
// Init PWM generator and clear LED buffer
|
// Init PWM generator and clear LED buffer
|
||||||
initHardware();
|
initHardware();
|
||||||
//clearLEDBuffer();
|
//clearLEDBuffer();
|
||||||
|
printf("WS2812b init finished \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
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();
|
mLedCount = ledValues.size();
|
||||||
//printf("Set leds, number: %d\n", mLedCount);
|
//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
|
// Clear out the PWM buffer
|
||||||
// Disabled, because we will overwrite the buffer anyway.
|
// Disabled, because we will overwrite the buffer anyway.
|
||||||
|
|
||||||
// Read data from LEDBuffer[], translate it into wire format, and write to PWMWaveform
|
// 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 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
|
unsigned int wireBit = 0; // Holds the current bit we will set in PWMWaveform
|
||||||
// Color_t color;
|
|
||||||
|
|
||||||
for(size_t i=0; i<mLedCount; i++) {
|
for(size_t i=0; i<mLedCount; i++) {
|
||||||
// Create bits necessary to represent one color triplet (in GRB, not RGB, order)
|
// 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
|
// Iterate through color bits to get wire bits
|
||||||
for(int j=23; j>=0; j--) {
|
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) {
|
switch(colorBit) {
|
||||||
case 1:
|
case 1:
|
||||||
//wireBits = 0b110; // High, High, Low
|
//wireBits = 0b110; // High, High, Low
|
||||||
@ -279,13 +297,13 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
|||||||
setPWMBit(wireBit++, 0);
|
setPWMBit(wireBit++, 0);
|
||||||
setPWMBit(wireBit++, 0);
|
setPWMBit(wireBit++, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy PWM waveform to DMA's data buffer
|
// Copy PWM waveform to DMA's data buffer
|
||||||
//printf("Copying %d words to DMA data buffer\n", NUM_DATA_WORDS);
|
//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;
|
dma_cb_t *cbp = ctl->cb;
|
||||||
|
|
||||||
// 72 bits per pixel / 32 bits per word = 2.25 words per pixel
|
// 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.
|
// This block is a major CPU hog when there are lots of pixels to be transmitted.
|
||||||
// It would go quicker with DMA.
|
// It would go quicker with DMA.
|
||||||
for(unsigned int i = 0; i < (cbp->length / 4); i++) {
|
// for(unsigned int i = 0; i < (cbp->length / 4); i++) {
|
||||||
ctl->sample[i] = PWMWaveform[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
|
// Enable DMA and PWM engines, which should now send the data
|
||||||
startTransfer();
|
startTransfer();
|
||||||
@ -312,6 +330,20 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
|
|||||||
//printf("Delay for %d μSec\n", (int)bitTimeUSec);
|
//printf("Delay for %d μSec\n", (int)bitTimeUSec);
|
||||||
//usleep((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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +357,10 @@ LedDeviceWS2812b::~LedDeviceWS2812b()
|
|||||||
// Exit cleanly, freeing memory and stopping the DMA & PWM engines
|
// 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
|
// We trap all signals (including Ctrl+C), so even if you don't get here, it terminates correctly
|
||||||
terminate(0);
|
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
|
// 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;
|
dma_cb_t *cbp = ctl->cb;
|
||||||
// FIXME: Change this to use DEFINEs
|
// FIXME: Change this to use DEFINEs
|
||||||
unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18;
|
unsigned int phys_pwm_fifo_addr = 0x7e20c000 + 0x18;
|
||||||
@ -724,7 +760,7 @@ void LedDeviceWS2812b::initHardware() {
|
|||||||
// Begin the transfer
|
// Begin the transfer
|
||||||
void LedDeviceWS2812b::startTransfer() {
|
void LedDeviceWS2812b::startTransfer() {
|
||||||
// Enable DMA
|
// 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);
|
dma_reg[DMA_CS] = DMA_CS_CONFIGWORD | (1 << DMA_CS_ACTIVE);
|
||||||
usleep(100);
|
usleep(100);
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@
|
|||||||
// Hyperion includes
|
// Hyperion includes
|
||||||
#include <leddevice/LedDevice.h>
|
#include <leddevice/LedDevice.h>
|
||||||
|
|
||||||
|
//#define BENCHMARK
|
||||||
|
|
||||||
// The page map contains pointers to memory that we will allocate below. It uses two pointers
|
// 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,
|
// 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)
|
/// the number of leds (needed when switching off)
|
||||||
size_t mLedCount;
|
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
|
uint8_t *virtbase; // Pointer to some virtual memory that will be allocated
|
||||||
|
|
||||||
volatile unsigned int *pwm_reg; // PWM controller register set
|
volatile unsigned int *pwm_reg; // PWM controller register set
|
||||||
@ -174,7 +175,7 @@ private:
|
|||||||
uint32_t sample[NUM_DATA_WORDS];
|
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.
|
// 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.
|
// 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 fatal(const char *fmt, ...);
|
||||||
void * map_peripheral(uint32_t base, uint32_t len);
|
void * map_peripheral(uint32_t base, uint32_t len);
|
||||||
void printBinary(unsigned int i, unsigned int bits);
|
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