Frank Vannieuwkerke / HSI2RGBW_PWM

Dependents:   KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more

Committer:
frankvnk
Date:
Tue Dec 24 06:29:38 2013 +0000
Revision:
2:d164d60999c4
Parent:
0:dd0e7a8a4572
Child:
3:dda6914d713f
added GPL license info

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 2:d164d60999c4 1 /**************************************************************************************************************
frankvnk 2:d164d60999c4 2 ***** *****
frankvnk 2:d164d60999c4 3 ***** Name: hsi2rgbw.cpp *****
frankvnk 2:d164d60999c4 4 ***** Date: 22/12/2013 *****
frankvnk 2:d164d60999c4 5 ***** Auth: Frank Vannieuwkerke *****
frankvnk 2:d164d60999c4 6 ***** Func: library for converting HSI color space values to RGBW *****
frankvnk 2:d164d60999c4 7 ***** *****
frankvnk 2:d164d60999c4 8 ***** Code ported from http://saikoled.com - Copyright 2013, Brian Neltner *****
frankvnk 2:d164d60999c4 9 ***** http://blog.saikoled.com/post/44677718712/how-to-convert-from-hsi-to-rgb-white *****
frankvnk 2:d164d60999c4 10 ***** http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi-colorspace *****
frankvnk 2:d164d60999c4 11 ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_random_fade/myki_16_bit_random_fade.ino *****
frankvnk 2:d164d60999c4 12 ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_fade/myki_16_bit_fade.ino *****
frankvnk 2:d164d60999c4 13 ***** *****
frankvnk 2:d164d60999c4 14 ***** This program is free software: you can redistribute it and/or modify *****
frankvnk 2:d164d60999c4 15 ***** it under the terms of the GNU General Public License as published by *****
frankvnk 2:d164d60999c4 16 ***** the Free Software Foundation, version 3 of the License. *****
frankvnk 2:d164d60999c4 17 ***** *****
frankvnk 2:d164d60999c4 18 ***** This program is distributed in the hope that it will be useful, *****
frankvnk 2:d164d60999c4 19 ***** but WITHOUT ANY WARRANTY; without even the implied warranty of *****
frankvnk 2:d164d60999c4 20 ***** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *****
frankvnk 2:d164d60999c4 21 ***** GNU General Public License for more details. *****
frankvnk 2:d164d60999c4 22 ***** *****
frankvnk 2:d164d60999c4 23 ***** A copy of the GNU General Public License can be found at *****
frankvnk 2:d164d60999c4 24 ***** http://www.gnu.org/licenses/gpl.html *****
frankvnk 2:d164d60999c4 25 **************************************************************************************************************/
frankvnk 2:d164d60999c4 26
frankvnk 0:dd0e7a8a4572 27 #include "hsi2rgbw_pwm.h"
frankvnk 0:dd0e7a8a4572 28
frankvnk 0:dd0e7a8a4572 29 #define PI 3.14159265
frankvnk 0:dd0e7a8a4572 30
frankvnk 0:dd0e7a8a4572 31 hsi2rgbw_pwm::hsi2rgbw_pwm(PinName red, PinName green, PinName blue, PinName white) : _red(red), _green(green), _blue(blue), _white(white)
frankvnk 0:dd0e7a8a4572 32 {
frankvnk 0:dd0e7a8a4572 33 parabol = 1;
frankvnk 0:dd0e7a8a4572 34 use_rgbw = RGBW;
frankvnk 0:dd0e7a8a4572 35 if(_red == NC && _green == NC && _blue == NC)
frankvnk 0:dd0e7a8a4572 36 {
frankvnk 0:dd0e7a8a4572 37 use_pwm = 0;
frankvnk 0:dd0e7a8a4572 38 }
frankvnk 0:dd0e7a8a4572 39 else
frankvnk 0:dd0e7a8a4572 40 {
frankvnk 0:dd0e7a8a4572 41 use_pwm = 1;
frankvnk 0:dd0e7a8a4572 42 //Setup PWM channels - default period = 4 ms (250Hz)
frankvnk 0:dd0e7a8a4572 43 _red.period_ms(4);
frankvnk 0:dd0e7a8a4572 44 _green.period_ms(4);
frankvnk 0:dd0e7a8a4572 45 _blue.period_ms(4);
frankvnk 0:dd0e7a8a4572 46 if(_white != NC)
frankvnk 0:dd0e7a8a4572 47 _white.period_ms(4);
frankvnk 0:dd0e7a8a4572 48
frankvnk 0:dd0e7a8a4572 49 // Initial RGB values.
frankvnk 0:dd0e7a8a4572 50 _red = 0.0f;
frankvnk 0:dd0e7a8a4572 51 _green = 0.0f;
frankvnk 0:dd0e7a8a4572 52 _blue = 0.0f;
frankvnk 0:dd0e7a8a4572 53 if(_white != NC)
frankvnk 0:dd0e7a8a4572 54 _white = 0.0f;
frankvnk 0:dd0e7a8a4572 55 }
frankvnk 0:dd0e7a8a4572 56 }
frankvnk 0:dd0e7a8a4572 57
frankvnk 0:dd0e7a8a4572 58 void hsi2rgbw_pwm::hsi2rgbw(float H, float S, float I, float* rgbw) {
frankvnk 0:dd0e7a8a4572 59 float _rgbw[4];
frankvnk 0:dd0e7a8a4572 60 if(rgbw == NULL)
frankvnk 0:dd0e7a8a4572 61 rgbw = _rgbw;
frankvnk 0:dd0e7a8a4572 62 float cos_h, Srgb;
frankvnk 0:dd0e7a8a4572 63 H = fmod(H,360); // cycle H around to 0-360 degrees
frankvnk 0:dd0e7a8a4572 64 H = PI*H/(float)180; // Convert to radians.
frankvnk 0:dd0e7a8a4572 65 S = S>0?(S<1?S:1):0; // clamp S and I to interval [0,1]
frankvnk 0:dd0e7a8a4572 66 I = I>0?(I<1?I:1):0;
frankvnk 0:dd0e7a8a4572 67 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 68 Srgb = 1;
frankvnk 0:dd0e7a8a4572 69 else
frankvnk 0:dd0e7a8a4572 70 {
frankvnk 0:dd0e7a8a4572 71 Srgb = S;
frankvnk 0:dd0e7a8a4572 72 S = 1;
frankvnk 0:dd0e7a8a4572 73 }
frankvnk 0:dd0e7a8a4572 74 // This section is modified by the addition of white so that it assumes
frankvnk 0:dd0e7a8a4572 75 // fully saturated colors, and then scales with white to lower saturation.
frankvnk 0:dd0e7a8a4572 76 //
frankvnk 0:dd0e7a8a4572 77 // Next, scale appropriately the pure color by mixing with the white channel.
frankvnk 0:dd0e7a8a4572 78 // Saturation is defined as "the ratio of colorfulness to brightness" so we will
frankvnk 0:dd0e7a8a4572 79 // do this by a simple ratio wherein the color values are scaled down by (1-S)
frankvnk 0:dd0e7a8a4572 80 // while the white LED is placed at S.
frankvnk 0:dd0e7a8a4572 81
frankvnk 0:dd0e7a8a4572 82 // This will maintain constant brightness because in HSI, R+B+G = I. Thus,
frankvnk 0:dd0e7a8a4572 83 // S*(R+B+G) = S*I. If we add to this (1-S)*I, where I is the total intensity,
frankvnk 0:dd0e7a8a4572 84 // the sum intensity stays constant while the ratio of colorfulness to brightness
frankvnk 0:dd0e7a8a4572 85 // goes down by S linearly relative to total Intensity, which is constant.
frankvnk 0:dd0e7a8a4572 86
frankvnk 0:dd0e7a8a4572 87 if(H < 2.09439) {
frankvnk 0:dd0e7a8a4572 88 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 89 rgbw[0] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 90 rgbw[1] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 91 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 92 {
frankvnk 0:dd0e7a8a4572 93 rgbw[2] = 0;
frankvnk 0:dd0e7a8a4572 94 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 95 }
frankvnk 0:dd0e7a8a4572 96 else
frankvnk 0:dd0e7a8a4572 97 rgbw[2] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 98 } else if(H < 4.188787) {
frankvnk 0:dd0e7a8a4572 99 H = H - 2.09439;
frankvnk 0:dd0e7a8a4572 100 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 101 rgbw[1] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 102 rgbw[2] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 103 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 104 {
frankvnk 0:dd0e7a8a4572 105 rgbw[0] = 0;
frankvnk 0:dd0e7a8a4572 106 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 107 }
frankvnk 0:dd0e7a8a4572 108 else
frankvnk 0:dd0e7a8a4572 109 rgbw[0] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 110 } else {
frankvnk 0:dd0e7a8a4572 111 H = H - 4.188787;
frankvnk 0:dd0e7a8a4572 112 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 113 rgbw[2] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 114 rgbw[0] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 115 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 116 {
frankvnk 0:dd0e7a8a4572 117 rgbw[1] = 0;
frankvnk 0:dd0e7a8a4572 118 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 119 }
frankvnk 0:dd0e7a8a4572 120 else
frankvnk 0:dd0e7a8a4572 121 rgbw[1] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 122 }
frankvnk 0:dd0e7a8a4572 123
frankvnk 0:dd0e7a8a4572 124 // parabolic mapping.
frankvnk 0:dd0e7a8a4572 125 if(parabol) {
frankvnk 0:dd0e7a8a4572 126 rgbw[0] *= rgbw[0]; // RED
frankvnk 0:dd0e7a8a4572 127 rgbw[1] *= rgbw[1]; // GREEN
frankvnk 0:dd0e7a8a4572 128 rgbw[2] *= rgbw[2]; // BLUE
frankvnk 0:dd0e7a8a4572 129 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 130 rgbw[3] *= rgbw[3]; // WHITE
frankvnk 0:dd0e7a8a4572 131 }
frankvnk 0:dd0e7a8a4572 132 if(use_pwm)
frankvnk 0:dd0e7a8a4572 133 {
frankvnk 0:dd0e7a8a4572 134 _red = rgbw[0];
frankvnk 0:dd0e7a8a4572 135 _green = rgbw[1];
frankvnk 0:dd0e7a8a4572 136 _blue = rgbw[2];
frankvnk 0:dd0e7a8a4572 137 if(_white != NC)
frankvnk 0:dd0e7a8a4572 138 _white = rgbw[3];
frankvnk 0:dd0e7a8a4572 139 }
frankvnk 0:dd0e7a8a4572 140 }
frankvnk 0:dd0e7a8a4572 141
frankvnk 0:dd0e7a8a4572 142 void hsi2rgbw_pwm::period(uint32_t per)
frankvnk 0:dd0e7a8a4572 143 {
frankvnk 0:dd0e7a8a4572 144 if(use_pwm)
frankvnk 0:dd0e7a8a4572 145 {
frankvnk 0:dd0e7a8a4572 146 _red.period_ms(per);
frankvnk 0:dd0e7a8a4572 147 _green.period_ms(per);
frankvnk 0:dd0e7a8a4572 148 _blue.period_ms(per);
frankvnk 0:dd0e7a8a4572 149 if(_white != NC)
frankvnk 0:dd0e7a8a4572 150 _white.period_ms(per);
frankvnk 0:dd0e7a8a4572 151 }
frankvnk 0:dd0e7a8a4572 152 }
frankvnk 0:dd0e7a8a4572 153
frankvnk 0:dd0e7a8a4572 154 void hsi2rgbw_pwm::pwm(float* rgbw)
frankvnk 0:dd0e7a8a4572 155 {
frankvnk 0:dd0e7a8a4572 156 if(use_pwm)
frankvnk 0:dd0e7a8a4572 157 {
frankvnk 0:dd0e7a8a4572 158 _red = rgbw[0];
frankvnk 0:dd0e7a8a4572 159 _green = rgbw[1];
frankvnk 0:dd0e7a8a4572 160 _blue = rgbw[2];
frankvnk 0:dd0e7a8a4572 161 if(_white != NC)
frankvnk 0:dd0e7a8a4572 162 _white = rgbw[3];
frankvnk 0:dd0e7a8a4572 163 }
frankvnk 0:dd0e7a8a4572 164 }
frankvnk 0:dd0e7a8a4572 165
frankvnk 0:dd0e7a8a4572 166 void hsi2rgbw_pwm::parabolic(bool para)
frankvnk 0:dd0e7a8a4572 167 {
frankvnk 0:dd0e7a8a4572 168 parabol = para;
frankvnk 0:dd0e7a8a4572 169 }
frankvnk 0:dd0e7a8a4572 170
frankvnk 0:dd0e7a8a4572 171 void hsi2rgbw_pwm::colorMode(bool como)
frankvnk 0:dd0e7a8a4572 172 {
frankvnk 0:dd0e7a8a4572 173 use_rgbw = como;
frankvnk 0:dd0e7a8a4572 174 }