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
colorspace.cpp@0:a81364d9a67b, 2017-03-21 (annotated)
- Committer:
- MightyPork
- Date:
- Tue Mar 21 21:17:08 2017 +0000
- Revision:
- 0:a81364d9a67b
initial
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MightyPork | 0:a81364d9a67b | 1 | #include "mbed.h" |
MightyPork | 0:a81364d9a67b | 2 | #include "colorspace.h" |
MightyPork | 0:a81364d9a67b | 3 | #include "math.h" |
MightyPork | 0:a81364d9a67b | 4 | |
MightyPork | 0:a81364d9a67b | 5 | #define max(a,b) ((a)>(b)?(a):(b)) |
MightyPork | 0:a81364d9a67b | 6 | #define min(a,b) ((a)>(b)?(b):(a)) |
MightyPork | 0:a81364d9a67b | 7 | |
MightyPork | 0:a81364d9a67b | 8 | static float threeway_max(float a, float b, float c) { |
MightyPork | 0:a81364d9a67b | 9 | return max(a, max(b, c)); |
MightyPork | 0:a81364d9a67b | 10 | } |
MightyPork | 0:a81364d9a67b | 11 | |
MightyPork | 0:a81364d9a67b | 12 | |
MightyPork | 0:a81364d9a67b | 13 | static float threeway_min(float a, float b, float c) { |
MightyPork | 0:a81364d9a67b | 14 | return min(a, min(b, c)); |
MightyPork | 0:a81364d9a67b | 15 | } |
MightyPork | 0:a81364d9a67b | 16 | |
MightyPork | 0:a81364d9a67b | 17 | |
MightyPork | 0:a81364d9a67b | 18 | static float hue2rgb(float p, float q, float t) { |
MightyPork | 0:a81364d9a67b | 19 | if(t < 0) t += 1; |
MightyPork | 0:a81364d9a67b | 20 | if(t > 1) t -= 1; |
MightyPork | 0:a81364d9a67b | 21 | if(t < 1/6.0f) return p + (q - p) * 6 * t; |
MightyPork | 0:a81364d9a67b | 22 | if(t < 1/2.0f) return q; |
MightyPork | 0:a81364d9a67b | 23 | if(t < 2/3.0f) return p + (q - p) * (2/3.0f - t) * 6; |
MightyPork | 0:a81364d9a67b | 24 | return p; |
MightyPork | 0:a81364d9a67b | 25 | } |
MightyPork | 0:a81364d9a67b | 26 | |
MightyPork | 0:a81364d9a67b | 27 | |
MightyPork | 0:a81364d9a67b | 28 | void hsl2rgb(const FloatHSL *hsl, FloatRGB *rgb) |
MightyPork | 0:a81364d9a67b | 29 | { |
MightyPork | 0:a81364d9a67b | 30 | float h = hsl->h; |
MightyPork | 0:a81364d9a67b | 31 | float s = hsl->s; |
MightyPork | 0:a81364d9a67b | 32 | float l = hsl->l; |
MightyPork | 0:a81364d9a67b | 33 | |
MightyPork | 0:a81364d9a67b | 34 | if (s == 0) { |
MightyPork | 0:a81364d9a67b | 35 | rgb->r = rgb->g = rgb->b = l; // achromatic |
MightyPork | 0:a81364d9a67b | 36 | } else { |
MightyPork | 0:a81364d9a67b | 37 | float q = l < 0.5f ? l * (1 + s) : l + s - l * s; |
MightyPork | 0:a81364d9a67b | 38 | float p = 2 * l - q; |
MightyPork | 0:a81364d9a67b | 39 | rgb->r = hue2rgb(p, q, h + 1/3.0f); |
MightyPork | 0:a81364d9a67b | 40 | rgb->g = hue2rgb(p, q, h); |
MightyPork | 0:a81364d9a67b | 41 | rgb->b = hue2rgb(p, q, h - 1/3.0f); |
MightyPork | 0:a81364d9a67b | 42 | } |
MightyPork | 0:a81364d9a67b | 43 | } |
MightyPork | 0:a81364d9a67b | 44 | |
MightyPork | 0:a81364d9a67b | 45 | |
MightyPork | 0:a81364d9a67b | 46 | void hsv2rgb(const FloatHSV *hsv, FloatRGB *rgb) |
MightyPork | 0:a81364d9a67b | 47 | { |
MightyPork | 0:a81364d9a67b | 48 | float r, g, b; |
MightyPork | 0:a81364d9a67b | 49 | |
MightyPork | 0:a81364d9a67b | 50 | int i = floor(hsv->h * 6); |
MightyPork | 0:a81364d9a67b | 51 | float f = hsv->h * 6 - i; |
MightyPork | 0:a81364d9a67b | 52 | float p = hsv->v * (1 - hsv->s); |
MightyPork | 0:a81364d9a67b | 53 | float q = hsv->v * (1 - f * hsv->s); |
MightyPork | 0:a81364d9a67b | 54 | float t = hsv->v * (1 - (1 - f) * hsv->s); |
MightyPork | 0:a81364d9a67b | 55 | |
MightyPork | 0:a81364d9a67b | 56 | switch(i % 6) { |
MightyPork | 0:a81364d9a67b | 57 | case 0: |
MightyPork | 0:a81364d9a67b | 58 | r = hsv->v; |
MightyPork | 0:a81364d9a67b | 59 | g = t; |
MightyPork | 0:a81364d9a67b | 60 | b = p; |
MightyPork | 0:a81364d9a67b | 61 | break; |
MightyPork | 0:a81364d9a67b | 62 | case 1: |
MightyPork | 0:a81364d9a67b | 63 | r = q; |
MightyPork | 0:a81364d9a67b | 64 | g = hsv->v; |
MightyPork | 0:a81364d9a67b | 65 | b = p; |
MightyPork | 0:a81364d9a67b | 66 | break; |
MightyPork | 0:a81364d9a67b | 67 | case 2: |
MightyPork | 0:a81364d9a67b | 68 | r = p; |
MightyPork | 0:a81364d9a67b | 69 | g = hsv->v; |
MightyPork | 0:a81364d9a67b | 70 | b = t; |
MightyPork | 0:a81364d9a67b | 71 | break; |
MightyPork | 0:a81364d9a67b | 72 | case 3: |
MightyPork | 0:a81364d9a67b | 73 | r = p; |
MightyPork | 0:a81364d9a67b | 74 | g = q; |
MightyPork | 0:a81364d9a67b | 75 | b = hsv->v; |
MightyPork | 0:a81364d9a67b | 76 | break; |
MightyPork | 0:a81364d9a67b | 77 | case 4: |
MightyPork | 0:a81364d9a67b | 78 | r = t; |
MightyPork | 0:a81364d9a67b | 79 | g = p; |
MightyPork | 0:a81364d9a67b | 80 | b = hsv->v; |
MightyPork | 0:a81364d9a67b | 81 | break; |
MightyPork | 0:a81364d9a67b | 82 | case 5: |
MightyPork | 0:a81364d9a67b | 83 | r = hsv->v; |
MightyPork | 0:a81364d9a67b | 84 | g = p; |
MightyPork | 0:a81364d9a67b | 85 | b = q; |
MightyPork | 0:a81364d9a67b | 86 | break; |
MightyPork | 0:a81364d9a67b | 87 | } |
MightyPork | 0:a81364d9a67b | 88 | |
MightyPork | 0:a81364d9a67b | 89 | rgb->r = r; |
MightyPork | 0:a81364d9a67b | 90 | rgb->g = g; |
MightyPork | 0:a81364d9a67b | 91 | rgb->b = b; |
MightyPork | 0:a81364d9a67b | 92 | } |
MightyPork | 0:a81364d9a67b | 93 | |
MightyPork | 0:a81364d9a67b | 94 | void rgb2hsl(const FloatRGB *rgb, FloatHSL *hsl) |
MightyPork | 0:a81364d9a67b | 95 | { |
MightyPork | 0:a81364d9a67b | 96 | float rd = rgb->r; |
MightyPork | 0:a81364d9a67b | 97 | float gd = rgb->g; |
MightyPork | 0:a81364d9a67b | 98 | float bd = rgb->b; |
MightyPork | 0:a81364d9a67b | 99 | float max = threeway_max(rd, gd, bd); |
MightyPork | 0:a81364d9a67b | 100 | float min = threeway_min(rd, gd, bd); |
MightyPork | 0:a81364d9a67b | 101 | float h, s, l = (max + min) / 2.0f; |
MightyPork | 0:a81364d9a67b | 102 | |
MightyPork | 0:a81364d9a67b | 103 | if (max == min) { |
MightyPork | 0:a81364d9a67b | 104 | h = s = 0; // achromatic |
MightyPork | 0:a81364d9a67b | 105 | } else { |
MightyPork | 0:a81364d9a67b | 106 | float d = max - min; |
MightyPork | 0:a81364d9a67b | 107 | s = l > 0.5f ? d / (2 - max - min) : d / (max + min); |
MightyPork | 0:a81364d9a67b | 108 | if (max == rd) { |
MightyPork | 0:a81364d9a67b | 109 | h = (gd - bd) / d + (gd < bd ? 6 : 0); |
MightyPork | 0:a81364d9a67b | 110 | } else if (max == gd) { |
MightyPork | 0:a81364d9a67b | 111 | h = (bd - rd) / d + 2; |
MightyPork | 0:a81364d9a67b | 112 | } else if (max == bd) { |
MightyPork | 0:a81364d9a67b | 113 | h = (rd - gd) / d + 4; |
MightyPork | 0:a81364d9a67b | 114 | } |
MightyPork | 0:a81364d9a67b | 115 | h /= 6; |
MightyPork | 0:a81364d9a67b | 116 | } |
MightyPork | 0:a81364d9a67b | 117 | hsl->h = h; |
MightyPork | 0:a81364d9a67b | 118 | hsl->s = s; |
MightyPork | 0:a81364d9a67b | 119 | hsl->l = l; |
MightyPork | 0:a81364d9a67b | 120 | } |
MightyPork | 0:a81364d9a67b | 121 | |
MightyPork | 0:a81364d9a67b | 122 | |
MightyPork | 0:a81364d9a67b | 123 | |
MightyPork | 0:a81364d9a67b | 124 | /** Convert from HSV to HSL (this is possibly wrong) */ |
MightyPork | 0:a81364d9a67b | 125 | void hsv2hsl(const FloatHSV *hsv, FloatHSL *hsl) |
MightyPork | 0:a81364d9a67b | 126 | { |
MightyPork | 0:a81364d9a67b | 127 | float l = (2 - hsv->s) * hsv->v / 2.0f; |
MightyPork | 0:a81364d9a67b | 128 | float s = hsv->s; |
MightyPork | 0:a81364d9a67b | 129 | |
MightyPork | 0:a81364d9a67b | 130 | if (l != 0) { |
MightyPork | 0:a81364d9a67b | 131 | if (l == 1) { |
MightyPork | 0:a81364d9a67b | 132 | s = 0; |
MightyPork | 0:a81364d9a67b | 133 | } else if (l < 0.5f) { |
MightyPork | 0:a81364d9a67b | 134 | s = s * hsv->v / (l * 2); |
MightyPork | 0:a81364d9a67b | 135 | } else { |
MightyPork | 0:a81364d9a67b | 136 | s = s * hsv->v / (2 - l * 2); |
MightyPork | 0:a81364d9a67b | 137 | } |
MightyPork | 0:a81364d9a67b | 138 | } |
MightyPork | 0:a81364d9a67b | 139 | |
MightyPork | 0:a81364d9a67b | 140 | hsl->h = hsv->h; |
MightyPork | 0:a81364d9a67b | 141 | hsl->s = s; |
MightyPork | 0:a81364d9a67b | 142 | hsl->l = l; |
MightyPork | 0:a81364d9a67b | 143 | } |
MightyPork | 0:a81364d9a67b | 144 | |
MightyPork | 0:a81364d9a67b | 145 | /** Convert from HSL to HSV */ |
MightyPork | 0:a81364d9a67b | 146 | void hsl2hsv(const FloatHSL *hsl, FloatHSV *hsv) |
MightyPork | 0:a81364d9a67b | 147 | { |
MightyPork | 0:a81364d9a67b | 148 | float sat = hsv->s * ((hsl->l < 0.5f) ? hsl->l : (1 - hsl->l)); |
MightyPork | 0:a81364d9a67b | 149 | hsv->s = 2*sat / (hsl->l + sat); |
MightyPork | 0:a81364d9a67b | 150 | hsv->h = hsl->h; |
MightyPork | 0:a81364d9a67b | 151 | hsv->v = hsl->l + sat; |
MightyPork | 0:a81364d9a67b | 152 | } |
MightyPork | 0:a81364d9a67b | 153 | |
MightyPork | 0:a81364d9a67b | 154 | |
MightyPork | 0:a81364d9a67b | 155 | uint32_t hsl2hex(const FloatHSL *hsl) |
MightyPork | 0:a81364d9a67b | 156 | { |
MightyPork | 0:a81364d9a67b | 157 | FloatRGB rgb; |
MightyPork | 0:a81364d9a67b | 158 | hsl2rgb(hsl, &rgb); |
MightyPork | 0:a81364d9a67b | 159 | return rgb2hex(&rgb); |
MightyPork | 0:a81364d9a67b | 160 | } |
MightyPork | 0:a81364d9a67b | 161 | |
MightyPork | 0:a81364d9a67b | 162 | uint32_t hsv2hex(const FloatHSV *hsv) |
MightyPork | 0:a81364d9a67b | 163 | { |
MightyPork | 0:a81364d9a67b | 164 | FloatRGB rgb; |
MightyPork | 0:a81364d9a67b | 165 | hsv2rgb(hsv, &rgb); |
MightyPork | 0:a81364d9a67b | 166 | return rgb2hex(&rgb); |
MightyPork | 0:a81364d9a67b | 167 | } |
MightyPork | 0:a81364d9a67b | 168 | |
MightyPork | 0:a81364d9a67b | 169 | |
MightyPork | 0:a81364d9a67b | 170 | uint32_t rgb2hex(FloatRGB *rgb) |
MightyPork | 0:a81364d9a67b | 171 | { |
MightyPork | 0:a81364d9a67b | 172 | return ((int)floor(rgb->r*255 + 0.5f) << 16) | ((int)floor(rgb->g*255 + 0.5f) << 8) | ((int)floor(rgb->b*255 + 0.5f)); |
MightyPork | 0:a81364d9a67b | 173 | } |
MightyPork | 0:a81364d9a67b | 174 |