Simple neopixel (WS2812) library, tuned for stm32 (L432) at 80 MHz Should be compatible with any stm32, different clock speed may require timing adjustments in neopixel.c
Dependents: Nucleo_neopixel_ovgu Nucleo_neopixel_ovgu1 Nucleo_neopixel_ovgu3
Fork of NeoPixel by
Revision 1:037882a8e193, committed 2017-12-11
- Comitter:
- Hinz
- Date:
- Mon Dec 11 12:54:00 2017 +0000
- Parent:
- 0:a81364d9a67b
- Commit message:
- ok
Changed in this revision
diff -r a81364d9a67b -r 037882a8e193 colorspace.cpp --- a/colorspace.cpp Tue Mar 21 21:17:08 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -#include "mbed.h" -#include "colorspace.h" -#include "math.h" - -#define max(a,b) ((a)>(b)?(a):(b)) -#define min(a,b) ((a)>(b)?(b):(a)) - -static float threeway_max(float a, float b, float c) { - return max(a, max(b, c)); -} - - -static float threeway_min(float a, float b, float c) { - return min(a, min(b, c)); -} - - -static float hue2rgb(float p, float q, float t) { - if(t < 0) t += 1; - if(t > 1) t -= 1; - if(t < 1/6.0f) return p + (q - p) * 6 * t; - if(t < 1/2.0f) return q; - if(t < 2/3.0f) return p + (q - p) * (2/3.0f - t) * 6; - return p; -} - - -void hsl2rgb(const FloatHSL *hsl, FloatRGB *rgb) -{ - float h = hsl->h; - float s = hsl->s; - float l = hsl->l; - - if (s == 0) { - rgb->r = rgb->g = rgb->b = l; // achromatic - } else { - float q = l < 0.5f ? l * (1 + s) : l + s - l * s; - float p = 2 * l - q; - rgb->r = hue2rgb(p, q, h + 1/3.0f); - rgb->g = hue2rgb(p, q, h); - rgb->b = hue2rgb(p, q, h - 1/3.0f); - } -} - - -void hsv2rgb(const FloatHSV *hsv, FloatRGB *rgb) -{ - float r, g, b; - - int i = floor(hsv->h * 6); - float f = hsv->h * 6 - i; - float p = hsv->v * (1 - hsv->s); - float q = hsv->v * (1 - f * hsv->s); - float t = hsv->v * (1 - (1 - f) * hsv->s); - - switch(i % 6) { - case 0: - r = hsv->v; - g = t; - b = p; - break; - case 1: - r = q; - g = hsv->v; - b = p; - break; - case 2: - r = p; - g = hsv->v; - b = t; - break; - case 3: - r = p; - g = q; - b = hsv->v; - break; - case 4: - r = t; - g = p; - b = hsv->v; - break; - case 5: - r = hsv->v; - g = p; - b = q; - break; - } - - rgb->r = r; - rgb->g = g; - rgb->b = b; -} - -void rgb2hsl(const FloatRGB *rgb, FloatHSL *hsl) -{ - float rd = rgb->r; - float gd = rgb->g; - float bd = rgb->b; - float max = threeway_max(rd, gd, bd); - float min = threeway_min(rd, gd, bd); - float h, s, l = (max + min) / 2.0f; - - if (max == min) { - h = s = 0; // achromatic - } else { - float d = max - min; - s = l > 0.5f ? d / (2 - max - min) : d / (max + min); - if (max == rd) { - h = (gd - bd) / d + (gd < bd ? 6 : 0); - } else if (max == gd) { - h = (bd - rd) / d + 2; - } else if (max == bd) { - h = (rd - gd) / d + 4; - } - h /= 6; - } - hsl->h = h; - hsl->s = s; - hsl->l = l; -} - - - -/** Convert from HSV to HSL (this is possibly wrong) */ -void hsv2hsl(const FloatHSV *hsv, FloatHSL *hsl) -{ - float l = (2 - hsv->s) * hsv->v / 2.0f; - float s = hsv->s; - - if (l != 0) { - if (l == 1) { - s = 0; - } else if (l < 0.5f) { - s = s * hsv->v / (l * 2); - } else { - s = s * hsv->v / (2 - l * 2); - } - } - - hsl->h = hsv->h; - hsl->s = s; - hsl->l = l; -} - -/** Convert from HSL to HSV */ -void hsl2hsv(const FloatHSL *hsl, FloatHSV *hsv) -{ - float sat = hsv->s * ((hsl->l < 0.5f) ? hsl->l : (1 - hsl->l)); - hsv->s = 2*sat / (hsl->l + sat); - hsv->h = hsl->h; - hsv->v = hsl->l + sat; -} - - -uint32_t hsl2hex(const FloatHSL *hsl) -{ - FloatRGB rgb; - hsl2rgb(hsl, &rgb); - return rgb2hex(&rgb); -} - -uint32_t hsv2hex(const FloatHSV *hsv) -{ - FloatRGB rgb; - hsv2rgb(hsv, &rgb); - return rgb2hex(&rgb); -} - - -uint32_t rgb2hex(FloatRGB *rgb) -{ - return ((int)floor(rgb->r*255 + 0.5f) << 16) | ((int)floor(rgb->g*255 + 0.5f) << 8) | ((int)floor(rgb->b*255 + 0.5f)); -} -
diff -r a81364d9a67b -r 037882a8e193 colorspace.h --- a/colorspace.h Tue Mar 21 21:17:08 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -#ifndef HSL_H -#define HSL_H - -// -// Utilities for working with colors in different color spaces -// - -#include "mbed.h" - -// all values 0 to 1 - -// adapted from: https://github.com/ratkins/RGBConverter - -struct FloatRGB { - float r; - float g; - float b; -}; - - -struct FloatHSL { - float h; - float s; - float l; -}; - - -struct FloatHSV { - float h; - float s; - float v; -}; - - -// --- Converting to RGB hex --- - -/** Convert HSL to RGB hex */ -uint32_t hsl2hex(const FloatHSL *hsl); - -/** Convert HSV to RGB hex */ -uint32_t hsv2hex(const FloatHSV *hsv); - -/** Convert RGB to RGB hex */ -uint32_t rgb2hex(FloatRGB *rgb); - - -// --- Itner-space conversion functions --- - -/** Convert HSL to RGB */ -void hsl2rgb(const FloatHSL *hsl, FloatRGB *rgb); - -/** Convert RGB to HSL */ -void rgb2hsl(const FloatRGB *rgb, FloatHSL *hsl); - -/** Convert from HSV to HSL */ -void hsv2hsl(const FloatHSV *hsv, FloatHSL *hsl); - -/** Convert from HSL to HSV */ -void hsl2hsv(const FloatHSL *hsl, FloatHSV *hsv); - -/** Convert HSV to RGB ("handy" algo) */ -void hsv2rgb(const FloatHSV *hsv, FloatRGB *rgb); - -#endif /* HSL_H */ \ No newline at end of file
diff -r a81364d9a67b -r 037882a8e193 neopixel.cpp --- a/neopixel.cpp Tue Mar 21 21:17:08 2017 +0000 +++ b/neopixel.cpp Mon Dec 11 12:54:00 2017 +0000 @@ -1,14 +1,15 @@ #include "mbed.h" #include "neopixel.h" -NeoPixelOut::NeoPixelOut(PinName pin) : DigitalOut(pin) +NeoPixel::NeoPixel(PinName pin, int n) : DigitalOut(pin) { - normalize = false; - global_scale = 1.0f; + _pixels = (Pixel*)malloc(n*sizeof(Pixel)); + memset(_pixels, 0, n*sizeof(Pixel)); + _npixels = n; } // The timing should be approximately 800ns/300ns, 300ns/800ns -void NeoPixelOut::byte(register uint32_t byte) +void NeoPixel::byte(register uint32_t byte) { for (int i = 0; i < 8; i++) { gpio_write(&gpio, 1); @@ -34,45 +35,20 @@ } -void NeoPixelOut::send(Pixel *colors, uint32_t count, bool flipwait) +void NeoPixel::show(void) { // Disable interrupts in the critical section __disable_irq(); - - Pixel* rgb; - float fr,fg,fb; - for (int i = 0; i < count; i++) { - rgb = colors++; - fr = (int)rgb->r; - fg = (int)rgb->g; - fb = (int)rgb->b; - - if (normalize) { - float scale = 255.0f/(fr+fg+fb); - fr *= scale; - fg *= scale; - fb *= scale; - } - - fr *= global_scale; - fg *= global_scale; - fb *= global_scale; - - if (fr > 255) fr = 255; - if (fg > 255) fg = 255; - if (fb > 255) fb = 255; - if (fr < 0) fr = 0; - if (fg < 0) fg = 0; - if (fb < 0) fb = 0; - + + for (int i = 0; i < _npixels; i++) { // Black magic to fix distorted timing #ifdef __HAL_FLASH_INSTRUCTION_CACHE_DISABLE __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); #endif - byte((int)fg); - byte((int)fr); - byte((int)fb); + byte((_pixels+i)->g); + byte((_pixels+i)->r); + byte((_pixels+i)->b); #ifdef __HAL_FLASH_INSTRUCTION_CACHE_ENABLE __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); @@ -80,12 +56,19 @@ } __enable_irq(); - - if (flipwait) flip(); + wait_us(50); } -void NeoPixelOut::flip(void) +void NeoPixel::setColor(int i, uint32_t color) { - wait_us(50); + if ((i>=0) && (i<_npixels)) + (_pixels+i)->hex = color; } + + +void NeoPixel::clear(void) +{ + for (int i=0; i<_npixels; i++) + (_pixels+i)->hex = 0; +} \ No newline at end of file
diff -r a81364d9a67b -r 037882a8e193 neopixel.h --- a/neopixel.h Tue Mar 21 21:17:08 2017 +0000 +++ b/neopixel.h Mon Dec 11 12:54:00 2017 +0000 @@ -2,68 +2,27 @@ #define NEOPIXEL_H #include "mbed.h" -/* -// Example - -NeoPixelOut npx(D12); - -int main() { - wait(0.2); // wait for HSE to stabilize - - npx.global_scale = 1.0f; // Adjust brightness - npx.normalize = true; // Equalize brightness to make r + g + b = 255 - - Pixel strip[6]; - strip[0].hex = 0xFF0000; - strip[1].hex = 0xFFFF00; - strip[2].hex = 0x00FF00; - strip[3].hex = 0x00FFFF; - strip[4].hex = 0x0000FF; - strip[5].hex = 0xFF00FF; - - npx.send(strip, 6); - - while(1); -} -*/ - - - -/** - * @brief Struct for easy manipulation of RGB colors. - * - * Set components in the xrgb.r (etc.) and you will get - * the hex in xrgb.num. - */ union Pixel { - /** Struct for access to individual color components */ struct __attribute__((packed)) { uint8_t b; uint8_t g; uint8_t r; uint8_t a; // unused }; + uint32_t hex; +}; - /** RGB color as a single uint32_t */ - uint32_t hex; +class NeoPixel : DigitalOut { +private: + void byte(uint32_t b); + int _npixels; + Pixel *_pixels; +public: + NeoPixel(PinName, int ); + void show(void); + void setColor(int, uint32_t); + void clear(void); }; -class NeoPixelOut : DigitalOut { -private: - void byte(uint32_t b); - -public: - bool normalize; - float global_scale; - - NeoPixelOut(PinName pin); - - void send(Pixel *colors, uint32_t count, bool flipwait=true); - - /** Wait long enough to make the colors show up */ - void flip(void); -}; - - -#endif /* NEOPIXEL_H */ \ No newline at end of file +#endif /* NEOPIXEL_H */