RGB LED library for Grove - Chainable RGB LED using P9813

Dependents:   Seeed_Grove_Chainable_RGB_LED_Example Temperature_Color SEEED_RGB_COLOR_LED_Example LoRaWAN_actility ... more

Fork of Chainable_RGB_LED by Seeed Studio

Committer:
sam_grove
Date:
Sun May 03 01:34:41 2015 +0000
Revision:
1:50d0a66599e1
Parent:
0:24631ceaa38a
Bug fixes including RAM being clobbered if more than one LED was used. Other speed optimizations and simplifications.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
seeed 0:24631ceaa38a 1 /*
seeed 0:24631ceaa38a 2 * Copyright (C) 2013 Seeed Technology Inc.
seeed 0:24631ceaa38a 3 * Copyright (C) 2012 Paulo Marques (pjp.marques@gmail.com)
seeed 0:24631ceaa38a 4 *
sam_grove 1:50d0a66599e1 5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
seeed 0:24631ceaa38a 6 * this software and associated documentation files (the "Software"), to deal in
seeed 0:24631ceaa38a 7 * the Software without restriction, including without limitation the rights to
seeed 0:24631ceaa38a 8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
seeed 0:24631ceaa38a 9 * the Software, and to permit persons to whom the Software is furnished to do so,
seeed 0:24631ceaa38a 10 * subject to the following conditions:
sam_grove 1:50d0a66599e1 11 *
sam_grove 1:50d0a66599e1 12 * The above copyright notice and this permission notice shall be included in all
seeed 0:24631ceaa38a 13 * copies or substantial portions of the Software.
sam_grove 1:50d0a66599e1 14 *
seeed 0:24631ceaa38a 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
seeed 0:24631ceaa38a 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
seeed 0:24631ceaa38a 17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
seeed 0:24631ceaa38a 18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
sam_grove 1:50d0a66599e1 19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
seeed 0:24631ceaa38a 20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
seeed 0:24631ceaa38a 21 */
seeed 0:24631ceaa38a 22
seeed 0:24631ceaa38a 23 /* Information about the P9813 protocol obtained from:
seeed 0:24631ceaa38a 24 * http://www.seeedstudio.com/wiki/index.php?title=Twig_-_Chainable_RGB_LED
seeed 0:24631ceaa38a 25 *
seeed 0:24631ceaa38a 26 * HSB to RGB routine adapted from:
seeed 0:24631ceaa38a 27 * http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
seeed 0:24631ceaa38a 28 *
seeed 0:24631ceaa38a 29 * This library is ported from Arduino to mbed
seeed 0:24631ceaa38a 30 */
seeed 0:24631ceaa38a 31
sam_grove 1:50d0a66599e1 32 #include "ChainableLED.h"
sam_grove 1:50d0a66599e1 33
sam_grove 1:50d0a66599e1 34 float hue2rgb(float p, float q, float t)
sam_grove 1:50d0a66599e1 35 {
sam_grove 1:50d0a66599e1 36 if (t < 0.0f) {
sam_grove 1:50d0a66599e1 37 t += 1.0f;
sam_grove 1:50d0a66599e1 38 }
sam_grove 1:50d0a66599e1 39 if(t > 1.0f) {
sam_grove 1:50d0a66599e1 40 t -= 1.0f;
sam_grove 1:50d0a66599e1 41 }
sam_grove 1:50d0a66599e1 42 if(t < 1.0f/6.0f) {
sam_grove 1:50d0a66599e1 43 return p + (q - p) * 6.0f * t;
sam_grove 1:50d0a66599e1 44 }
sam_grove 1:50d0a66599e1 45 if(t < 1.0f/2.0f) {
sam_grove 1:50d0a66599e1 46 return q;
sam_grove 1:50d0a66599e1 47 }
sam_grove 1:50d0a66599e1 48 if(t < 2.0f/3.0f) {
sam_grove 1:50d0a66599e1 49 return p + (q - p) * (2.0f/3.0f - t) * 6.0f;
sam_grove 1:50d0a66599e1 50 }
sam_grove 1:50d0a66599e1 51
sam_grove 1:50d0a66599e1 52 return p;
sam_grove 1:50d0a66599e1 53 }
seeed 0:24631ceaa38a 54
seeed 0:24631ceaa38a 55 // --------------------------------------------------------------------------------------
seeed 0:24631ceaa38a 56
sam_grove 1:50d0a66599e1 57 ChainableLED::ChainableLED(PinName clk_pin, PinName data_pin, uint32_t number_of_leds) :
sam_grove 1:50d0a66599e1 58 _clk_pin(clk_pin),
sam_grove 1:50d0a66599e1 59 _data_pin(data_pin),
sam_grove 1:50d0a66599e1 60 _num_leds(number_of_leds)
seeed 0:24631ceaa38a 61 {
sam_grove 1:50d0a66599e1 62 _leds = new led_val_t [number_of_leds];
sam_grove 1:50d0a66599e1 63 _clk_pin = 0;
sam_grove 1:50d0a66599e1 64 _data_pin = 0;
sam_grove 1:50d0a66599e1 65 ledsOff();
seeed 0:24631ceaa38a 66 }
seeed 0:24631ceaa38a 67
seeed 0:24631ceaa38a 68 ChainableLED::~ChainableLED()
seeed 0:24631ceaa38a 69 {
sam_grove 1:50d0a66599e1 70 delete [] _leds;
seeed 0:24631ceaa38a 71 }
seeed 0:24631ceaa38a 72
sam_grove 1:50d0a66599e1 73 void ChainableLED::ledsOff(void)
seeed 0:24631ceaa38a 74 {
sam_grove 1:50d0a66599e1 75 for (uint8_t i=0; i<_num_leds; i++) {
sam_grove 1:50d0a66599e1 76 setColorRGB(i, 0, 0, 0);
sam_grove 1:50d0a66599e1 77 }
seeed 0:24631ceaa38a 78 }
seeed 0:24631ceaa38a 79
seeed 0:24631ceaa38a 80 void ChainableLED::sendByte(uint8_t b)
seeed 0:24631ceaa38a 81 {
seeed 0:24631ceaa38a 82 // Send one bit at a time, starting with the MSB
sam_grove 1:50d0a66599e1 83 for (uint8_t i=0; i<8; i++) {
sam_grove 1:50d0a66599e1 84 _data_pin = (b & 0x80) ? 1 : 0;
sam_grove 1:50d0a66599e1 85 _clk_pin = 1;
sam_grove 1:50d0a66599e1 86 _clk_pin = 0;
seeed 0:24631ceaa38a 87 b <<= 1;
seeed 0:24631ceaa38a 88 }
seeed 0:24631ceaa38a 89 }
sam_grove 1:50d0a66599e1 90
seeed 0:24631ceaa38a 91 void ChainableLED::sendColor(uint8_t red, uint8_t green, uint8_t blue)
seeed 0:24631ceaa38a 92 {
sam_grove 1:50d0a66599e1 93 uint8_t r67 = ~(red & 0xC0) >> 6;;
sam_grove 1:50d0a66599e1 94 uint8_t g67 = ~(green & 0xC0) >> 4;
sam_grove 1:50d0a66599e1 95 uint8_t b67 = ~(blue & 0xC0) >> 2;
sam_grove 1:50d0a66599e1 96 uint8_t verify = 0xC0 | r67 | g67 | b67;
sam_grove 1:50d0a66599e1 97
sam_grove 1:50d0a66599e1 98 sendByte(verify);
seeed 0:24631ceaa38a 99 sendByte(blue);
seeed 0:24631ceaa38a 100 sendByte(green);
seeed 0:24631ceaa38a 101 sendByte(red);
seeed 0:24631ceaa38a 102 }
seeed 0:24631ceaa38a 103
sam_grove 1:50d0a66599e1 104 void ChainableLED::setColorRGB(uint32_t led, uint8_t red, uint8_t green, uint8_t blue)
seeed 0:24631ceaa38a 105 {
seeed 0:24631ceaa38a 106 // Send data frame prefix (32x "0")
seeed 0:24631ceaa38a 107 sendByte(0x00);
seeed 0:24631ceaa38a 108 sendByte(0x00);
seeed 0:24631ceaa38a 109 sendByte(0x00);
seeed 0:24631ceaa38a 110 sendByte(0x00);
sam_grove 1:50d0a66599e1 111
seeed 0:24631ceaa38a 112 // Send color data for each one of the leds
sam_grove 1:50d0a66599e1 113 for (uint8_t i=0; i<_num_leds; i++) {
sam_grove 1:50d0a66599e1 114 if (i == led) {
sam_grove 1:50d0a66599e1 115 _leds->rgb[i*3 + 0] = red;
sam_grove 1:50d0a66599e1 116 _leds->rgb[i*3 + 1] = green;
sam_grove 1:50d0a66599e1 117 _leds->rgb[i*3 + 2] = blue;
seeed 0:24631ceaa38a 118 }
sam_grove 1:50d0a66599e1 119 sendColor(_leds->rgb[i*3 + 0], _leds->rgb[i*3 + 1], _leds->rgb[i*3 + 2]);
seeed 0:24631ceaa38a 120 }
seeed 0:24631ceaa38a 121
seeed 0:24631ceaa38a 122 // Terminate data frame (32x "0")
seeed 0:24631ceaa38a 123 sendByte(0x00);
seeed 0:24631ceaa38a 124 sendByte(0x00);
seeed 0:24631ceaa38a 125 sendByte(0x00);
seeed 0:24631ceaa38a 126 sendByte(0x00);
seeed 0:24631ceaa38a 127 }
seeed 0:24631ceaa38a 128
sam_grove 1:50d0a66599e1 129 template<typename T>
sam_grove 1:50d0a66599e1 130 T min(T a, T b) { return (a < b) ? a : b; }
sam_grove 1:50d0a66599e1 131
sam_grove 1:50d0a66599e1 132 template<typename T>
sam_grove 1:50d0a66599e1 133 static inline T max(T a, T b) { return (a > b) ? a : b; }
sam_grove 1:50d0a66599e1 134
sam_grove 1:50d0a66599e1 135 void ChainableLED::setColorHSB(uint32_t led, float hue, float saturation, float brightness)
seeed 0:24631ceaa38a 136 {
seeed 0:24631ceaa38a 137 float r, g, b;
seeed 0:24631ceaa38a 138
sam_grove 1:50d0a66599e1 139 hue = min<float>(hue, 1.0f);//constrain(hue, 0.0, 1.0);
sam_grove 1:50d0a66599e1 140 hue = max<float>(hue, 0.0f);
sam_grove 1:50d0a66599e1 141 saturation = min<float>(saturation, 1.0f);//constrain(saturation, 0.0, 1.0);
sam_grove 1:50d0a66599e1 142 saturation = max<float>(saturation, 0.0f);
sam_grove 1:50d0a66599e1 143 brightness = min<float>(brightness, 1.0f);//constrain(brightness, 0.0, 1.0);
sam_grove 1:50d0a66599e1 144 brightness = max<float>(brightness, 0.0f);
seeed 0:24631ceaa38a 145
sam_grove 1:50d0a66599e1 146 if(saturation == 0.0f) {
seeed 0:24631ceaa38a 147 r = g = b = brightness;
sam_grove 1:50d0a66599e1 148 } else {
sam_grove 1:50d0a66599e1 149 float q = (brightness < 0.5f) ? (brightness * (1.0f + saturation)) : (brightness + saturation - brightness * saturation);
sam_grove 1:50d0a66599e1 150 float p = 2.0f * brightness - q;
sam_grove 1:50d0a66599e1 151 r = hue2rgb(p, q, hue + 1.0f/3.0f);
seeed 0:24631ceaa38a 152 g = hue2rgb(p, q, hue);
sam_grove 1:50d0a66599e1 153 b = hue2rgb(p, q, hue - 1.0f/3.0f);
seeed 0:24631ceaa38a 154 }
seeed 0:24631ceaa38a 155
sam_grove 1:50d0a66599e1 156 setColorRGB(led, (uint8_t)(255.0f*r), (uint8_t)(255.0f*g), (uint8_t)(255.0f*b));
seeed 0:24631ceaa38a 157 }