Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement getPixelColor() and setBrightness() #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 51 additions & 8 deletions src/WS2812B.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,43 @@ uint32_t WS2812B::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}

uint32_t WS2812B::getPixelColor(uint16_t n) const {
if(n >= numLEDs) return 0; // Out of bounds, return no color.

// Extract the g,r,b values from the 3 bit encoded data.
// A positive bit of rgb appears in the middle (2nd) bit of the encoded 3 bit tuple.
// Encoded bit positions for a single pixel byte: -7--6--5,--4--3--,2--1--0-
uint8_t *bptr = pixels + (n<<3) + n +1;
uint8_t grb[3] = {0, 0, 0};
for(uint8_t i = 0; i < 3; i++) {
grb[i] |= (*bptr & 0b01000000) << 1; // bit 7
grb[i] |= (*bptr & 0b00001000) << 3; // bit 6
grb[i] |= (*bptr & 0b00000001) << 5; // bit 5
bptr++;
grb[i] |= (*bptr & 0b00100000) >> 1; // bit 4
grb[i] |= (*bptr & 0b00000100) << 1; // bit 3
bptr++;
grb[i] |= (*bptr & 0b10000000) >> 5; // bit 2
grb[i] |= (*bptr & 0b00010000) >> 3; // bit 1
grb[i] |= (*bptr & 0b00000010) >> 1; // bit 0
bptr++;
}
if (brightness) {
// Stored color was decimated by setBrightness(). Returned value
// attempts to scale back to an approximation of the original 24-bit
// value used when setting the pixel color, but there will always be
// some error -- those bits are simply gone. Issue is most
// pronounced at low brightness levels.
return (((uint32_t)(grb[1] << 8) / brightness) << 16) |
(((uint32_t)(grb[0] << 8) / brightness) << 8) |
( (uint32_t)(grb[2] << 8) / brightness );
} else {
// No brightness adjustment has been made -- return 'raw' color
return ((uint32_t)grb[1] << 16) |
((uint32_t)grb[0] << 8) |
(uint32_t)grb[2];
}
}

uint16_t WS2812B::numPixels(void) const {
return numLEDs;
Expand All @@ -198,18 +235,24 @@ void WS2812B::setBrightness(uint8_t b) {
// brightness (off), 255 = just below max brightness.
uint8_t newBrightness = b + 1;
if(newBrightness != brightness) { // Compare against prior value
// Brightness has changed -- re-scale existing data in RAM
uint8_t c,
*ptr = pixels,
oldBrightness = brightness - 1; // De-wrap old brightness value
// Brightness has changed -- re-scale encoded data in RAM
uint8_t c,
*ptr,
oldBrightness = brightness - 1; // De-wrap old brightness value
uint16_t scale;
if(oldBrightness == 0) scale = 0; // Avoid /0
else if(b == 255) scale = 65535 / oldBrightness;
else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
for(uint16_t i=0; i<numBytes; i++)
{
c = *ptr;
*ptr++ = (c * scale) >> 8;

brightness = 0; // Turn off brightness scaling in setPixelColor

for(uint16_t i = 0; i < numPixels(); i++) {
uint32_t rgb = getPixelColor(i);
ptr = (uint8_t*)(&rgb);
c = *ptr; *ptr++ = (c * scale) >> 8;
c = *ptr; *ptr++ = (c * scale) >> 8;
c = *ptr; *ptr++ = (c * scale) >> 8;
setPixelColor(i, rgb);
}
brightness = newBrightness;
}
Expand Down
14 changes: 3 additions & 11 deletions src/WS2812B.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,8 @@ class WS2812B {
static uint32_t
Color(uint8_t r, uint8_t g, uint8_t b),
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
// uint32_t
// getPixelColor(uint16_t n) const;
inline bool
canShow(void) { return (micros() - endTime) >= 300L; }
uint32_t
getPixelColor(uint16_t n) const;

private:

Expand All @@ -90,13 +88,7 @@ class WS2812B {
uint8_t
brightness,
*pixels, // Holds the current LED color values, which the external API calls interact with 9 bytes per pixel + start + end empty bytes
*doubleBuffer, // Holds the start of the double buffer (1 buffer for async DMA transfer and one for the API interaction.
rOffset, // Index of red byte within each 3- or 4-byte pixel
gOffset, // Index of green byte
bOffset, // Index of blue byte
wOffset; // Index of white byte (same as rOffset if no white)
uint32_t
endTime; // Latch timing reference
*doubleBuffer; // Holds the start of the double buffer (1 buffer for async DMA transfer and one for the API interaction.
};


Expand Down