Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: NEOPIXEL_SAMPLE ppd
Revision 0:a81364d9a67b, committed 2017-03-21
- Comitter:
- MightyPork
- Date:
- Tue Mar 21 21:17:08 2017 +0000
- Child:
- 1:415459e3f93b
- Commit message:
- initial
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/colorspace.cpp Tue Mar 21 21:17:08 2017 +0000
@@ -0,0 +1,174 @@
+#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));
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/colorspace.h Tue Mar 21 21:17:08 2017 +0000
@@ -0,0 +1,64 @@
+#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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/neopixel.cpp Tue Mar 21 21:17:08 2017 +0000
@@ -0,0 +1,91 @@
+#include "mbed.h"
+#include "neopixel.h"
+
+NeoPixelOut::NeoPixelOut(PinName pin) : DigitalOut(pin)
+{
+ normalize = false;
+ global_scale = 1.0f;
+}
+
+// The timing should be approximately 800ns/300ns, 300ns/800ns
+void NeoPixelOut::byte(register uint32_t byte)
+{
+ for (int i = 0; i < 8; i++) {
+ gpio_write(&gpio, 1);
+
+ // duty cycle determines bit value
+ if (byte & 0x80) {
+ // one
+ for(int j = 0; j < 6; j++) __nop();
+
+ gpio_write(&gpio, 0);
+ for(int j = 0; j < 2; j++) __nop();
+ }
+ else {
+ // zero
+ for(int j = 0; j < 2; j++) __nop();
+
+ gpio_write(&gpio, 0);
+ for(int j = 0; j < 5; j++) __nop();
+ }
+
+ byte = byte << 1; // shift to next bit
+ }
+
+}
+
+void NeoPixelOut::send(Pixel *colors, uint32_t count, bool flipwait)
+{
+ // 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;
+
+ // 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);
+
+ #ifdef __HAL_FLASH_INSTRUCTION_CACHE_ENABLE
+ __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ #endif
+ }
+
+ __enable_irq();
+
+ if (flipwait) flip();
+}
+
+
+void NeoPixelOut::flip(void)
+{
+ wait_us(50);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/neopixel.h Tue Mar 21 21:17:08 2017 +0000
@@ -0,0 +1,69 @@
+#ifndef NEOPIXEL_H
+#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
+ };
+
+ /** RGB color as a single uint32_t */
+ uint32_t hex;
+};
+
+
+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