Permalink
Browse files

Merge branch 'ledvinap-cleanup-leds'

  • Loading branch information...
2 parents 192f626 + d687575 commit 9e768fcd729b26082d77fd8d2fcfac73c73c78e9 @hydra hydra committed May 30, 2016
@@ -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;
@@ -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;
}
@@ -16,4 +16,4 @@
*/
#pragma once
-rgbColor24bpp_t* hsvToRgb24(const hsvColor_t *c);
+rgbColor24bpp_t hsvToRgb24(const hsvColor_t *c);
@@ -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
@@ -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)
@@ -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;
@@ -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);
@@ -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;
@@ -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();
}
@@ -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();
}
Oops, something went wrong.

0 comments on commit 9e768fc

Please sign in to comment.