Skip to content

Commit

Permalink
Merge branch 'ledvinap-cleanup-leds'
Browse files Browse the repository at this point in the history
  • Loading branch information
hydra committed May 30, 2016
2 parents 192f626 + d687575 commit 9e768fc
Show file tree
Hide file tree
Showing 15 changed files with 869 additions and 1,161 deletions.
12 changes: 5 additions & 7 deletions src/main/common/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ typedef enum {

#define RGB_COLOR_COMPONENT_COUNT (RGB_BLUE + 1)

struct rgbColor24bpp_s {
uint8_t r;
uint8_t g;
uint8_t b;
};

typedef union {
struct rgbColor24bpp_s rgb;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
} rgb;
uint8_t raw[RGB_COLOR_COMPONENT_COUNT];
} rgbColor24bpp_t;

Expand Down
76 changes: 41 additions & 35 deletions src/main/common/colorconversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,61 +24,67 @@
* Source below found here: http://www.kasperkamperman.com/blog/arduino/arduino-programming-hsb-to-rgb/
*/

rgbColor24bpp_t* hsvToRgb24(const hsvColor_t* c)
rgbColor24bpp_t hsvToRgb24(const hsvColor_t* c)
{
static rgbColor24bpp_t r;
rgbColor24bpp_t r;

uint16_t val = c->v;
uint16_t sat = 255 - c->s;
uint32_t base;
uint16_t hue = c->h;
int val = c->v;
int isat = c->s;
int hue = c->h;

if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
if (isat == 255) { // Acromatic color (gray). Hue doesn't mind.
r.rgb.r = val;
r.rgb.g = val;
r.rgb.b = val;
} else {

base = ((255 - sat) * val) >> 8;
int base = (isat * val) / 256;
// TODO - rotating/inverting sector will allow all possible color ordering combinations
// probably good place to handle led type configuration
int sector = hue / 60;
hue = hue % 60;
if(sector % 2) // invert direction for odd sectors
hue = 60 - hue;
int itp = (((val - base) * hue) / 60) + base;

switch (hue / 60) {
switch (sector) {
case 0:
r.rgb.r = val;
r.rgb.g = (((val - base) * hue) / 60) + base;
r.rgb.b = base;
break;
r.rgb.r = val;
r.rgb.g = itp;
r.rgb.b = base;
break;

case 1:
r.rgb.r = (((val - base) * (60 - (hue % 60))) / 60) + base;
r.rgb.g = val;
r.rgb.b = base;
break;
r.rgb.r = itp;
r.rgb.g = val;
r.rgb.b = base;
break;

case 2:
r.rgb.r = base;
r.rgb.g = val;
r.rgb.b = (((val - base) * (hue % 60)) / 60) + base;
break;
r.rgb.r = base;
r.rgb.g = val;
r.rgb.b = itp;
break;

case 3:
r.rgb.r = base;
r.rgb.g = (((val - base) * (60 - (hue % 60))) / 60) + base;
r.rgb.b = val;
break;
r.rgb.r = base;
r.rgb.g = itp;
r.rgb.b = val;
break;

case 4:
r.rgb.r = (((val - base) * (hue % 60)) / 60) + base;
r.rgb.g = base;
r.rgb.b = val;
break;
r.rgb.r = itp;
r.rgb.g = base;
r.rgb.b = val;
break;

case 5:
r.rgb.r = val;
r.rgb.g = base;
r.rgb.b = (((val - base) * (60 - (hue % 60))) / 60) + base;
break;

r.rgb.r = val;
r.rgb.g = base;
r.rgb.b = itp;
break;
}
}
return &r;
return r;
}

2 changes: 1 addition & 1 deletion src/main/common/colorconversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
*/
#pragma once

rgbColor24bpp_t* hsvToRgb24(const hsvColor_t *c);
rgbColor24bpp_t hsvToRgb24(const hsvColor_t *c);
4 changes: 4 additions & 0 deletions src/main/common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
static inline int16_t cmp16(uint16_t a, uint16_t b) { return a-b; }
static inline int32_t cmp32(uint32_t a, uint32_t b) { return a-b; }

// using memcpy_fn will force memcpy function call, instead of inlining it. In most cases function call takes fewer instructions
// than inlined version (inlining is cheaper for very small moves < 8 bytes / 2 store instructions)
void * memcpy_fn ( void * destination, const void * source, size_t num ) asm("memcpy");

#endif
77 changes: 18 additions & 59 deletions src/main/drivers/light_ws2811strip.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,30 @@ volatile uint8_t ws2811LedDataTransferInProgress = 0;

static hsvColor_t ledColorBuffer[WS2811_LED_STRIP_LENGTH];

void setLedHsv(uint16_t index, const hsvColor_t *color)
void setLedHsv(int index, const hsvColor_t *color)
{
ledColorBuffer[index] = *color;
}

void getLedHsv(uint16_t index, hsvColor_t *color)
void getLedHsv(int index, hsvColor_t *color)
{
*color = ledColorBuffer[index];
}

void setLedValue(uint16_t index, const uint8_t value)
void setLedValue(int index, const uint8_t value)
{
ledColorBuffer[index].v = value;
}

void scaleLedValue(uint16_t index, const uint8_t scalePercent)
void scaleLedValue(int index, const uint8_t scalePercent)
{
ledColorBuffer[index].v = ((uint16_t)ledColorBuffer[index].v * scalePercent / 100);
ledColorBuffer[index].v = (ledColorBuffer[index].v * scalePercent / 100);
}

void setStripColor(const hsvColor_t *color)
{
uint16_t index;
for (index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
for (int index = 0; index < WS2811_LED_STRIP_LENGTH; index++)
setLedHsv(index, color);
}
}

void setStripColors(const hsvColor_t *colors)
Expand Down Expand Up @@ -98,72 +96,33 @@ bool isWS2811LedStripReady(void)
return !ws2811LedDataTransferInProgress;
}

STATIC_UNIT_TESTED uint16_t dmaBufferOffset;
static int16_t ledIndex;

#define USE_FAST_DMA_BUFFER_IMPL
#ifdef USE_FAST_DMA_BUFFER_IMPL

STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(rgbColor24bpp_t *color)
{
uint32_t grb = (color->rgb.g << 16) | (color->rgb.r << 8) | (color->rgb.b);

for (int8_t index = 23; index >= 0; index--) {
ledStripDMABuffer[dmaBufferOffset++] = (grb & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
}
}
#else
STATIC_UNIT_TESTED void updateLEDDMABuffer(uint8_t componentValue)
STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(uint8_t **buffer, rgbColor24bpp_t color)
{
uint8_t bitIndex;

for (bitIndex = 0; bitIndex < 8; bitIndex++)
{
if ((componentValue << bitIndex) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB
{
ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_1;
}
else
{
ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_0; // compare value for logical 0
}
dmaBufferOffset++;
uint32_t grb = (color.rgb.g << 16) | (color.rgb.r << 8) | (color.rgb.b);
// uint32_t grb = (color.rgb.r << 16) | (color.rgb.g << 8) | (color.rgb.b);
for (int bit = 0; bit < 24; bit++) {
*(*buffer)++ = (grb & (1 << 23)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
grb <<= 1;
}
}
#endif

/*
* This method is non-blocking unless an existing LED update is in progress.
* it does not wait until all the LEDs have been updated, that happens in the background.
*/
void ws2811UpdateStrip(void)
{
static uint32_t waitCounter = 0;
static rgbColor24bpp_t *rgb24;

// wait until previous transfer completes
while(ws2811LedDataTransferInProgress) {
waitCounter++;
}
while(ws2811LedDataTransferInProgress);

dmaBufferOffset = 0; // reset buffer memory index
ledIndex = 0; // reset led index
uint8_t *dst = ledStripDMABuffer; // reset buffer memory index

// fill transmit buffer with correct compare values to achieve
// correct pulse widths according to color values
while (ledIndex < WS2811_LED_STRIP_LENGTH)
{
rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);

#ifdef USE_FAST_DMA_BUFFER_IMPL
fastUpdateLEDDMABuffer(rgb24);
#else
updateLEDDMABuffer(rgb24->rgb.g);
updateLEDDMABuffer(rgb24->rgb.r);
updateLEDDMABuffer(rgb24->rgb.b);
#endif

ledIndex++;
for (int ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
rgbColor24bpp_t rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);

fastUpdateLEDDMABuffer(&dst, rgb24);
}

ws2811LedDataTransferInProgress = 1;
Expand Down
11 changes: 4 additions & 7 deletions src/main/drivers/light_ws2811strip.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ void ws2811LedStripDMAEnable(void);

void ws2811UpdateStrip(void);

void setLedHsv(uint16_t index, const hsvColor_t *color);
void getLedHsv(uint16_t index, hsvColor_t *color);
void setLedHsv(int index, const hsvColor_t *color);
void getLedHsv(int index, hsvColor_t *color);

void scaleLedValue(uint16_t index, const uint8_t scalePercent);
void setLedValue(uint16_t index, const uint8_t value);
void scaleLedValue(int index, const uint8_t scalePercent);
void setLedValue(int index, const uint8_t value);

void setStripColor(const hsvColor_t *color);
void setStripColors(const hsvColor_t *colors);
Expand All @@ -48,6 +48,3 @@ bool isWS2811LedStripReady(void);

extern uint8_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE];
extern volatile uint8_t ws2811LedDataTransferInProgress;

extern const hsvColor_t hsv_white;
extern const hsvColor_t hsv_black;
2 changes: 1 addition & 1 deletion src/main/drivers/light_ws2811strip_stm32f10x.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void ws2811LedStripHardwareInit(void)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

const hsvColor_t hsv_white = { 0, 255, 255};
setStripColor(&hsv_white);
ws2811UpdateStrip();
}
Expand Down
1 change: 1 addition & 0 deletions src/main/drivers/light_ws2811strip_stm32f30x.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ void ws2811LedStripHardwareInit(void)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

const hsvColor_t hsv_white = { 0, 255, 255};
setStripColor(&hsv_white);
ws2811UpdateStrip();
}
Expand Down

0 comments on commit 9e768fc

Please sign in to comment.