Frank Vannieuwkerke / HSI2RGBW_PWM

Dependents:   KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more

Committer:
frankvnk
Date:
Sun Feb 02 14:41:29 2014 +0000
Revision:
4:a16b9c09561e
Parent:
3:dda6914d713f
Fixed runtime error (RGB mode).
; Added invertpwm.

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 4:a16b9c09561e 31 PwmOut *_red;
frankvnk 4:a16b9c09561e 32 PwmOut *_green;
frankvnk 4:a16b9c09561e 33 PwmOut *_blue;
frankvnk 4:a16b9c09561e 34 PwmOut *_white;
frankvnk 4:a16b9c09561e 35
frankvnk 4:a16b9c09561e 36 hsi2rgbw_pwm::hsi2rgbw_pwm(PinName pred, PinName pgreen, PinName pblue, PinName pwhite)
frankvnk 0:dd0e7a8a4572 37 {
frankvnk 0:dd0e7a8a4572 38 parabol = 1;
frankvnk 4:a16b9c09561e 39 use_invpwm = 0;
frankvnk 0:dd0e7a8a4572 40 use_rgbw = RGBW;
frankvnk 4:a16b9c09561e 41 if(pred != NC) _red = new PwmOut (pred);
frankvnk 4:a16b9c09561e 42 if(pgreen != NC) _green = new PwmOut (pgreen);
frankvnk 4:a16b9c09561e 43 if(pblue != NC) _blue = new PwmOut (pblue);
frankvnk 4:a16b9c09561e 44 if(pwhite != NC) _white = new PwmOut (pwhite);
frankvnk 4:a16b9c09561e 45 if((pred != NC) && (pgreen != NC) && (pblue != NC) && (pwhite == NC))
frankvnk 4:a16b9c09561e 46 use_rgbw = RGB;
frankvnk 4:a16b9c09561e 47 if((pred == NC) && (pgreen == NC) && (pblue == NC) && (pwhite == NC))
frankvnk 0:dd0e7a8a4572 48 {
frankvnk 0:dd0e7a8a4572 49 use_pwm = 0;
frankvnk 0:dd0e7a8a4572 50 }
frankvnk 0:dd0e7a8a4572 51 else
frankvnk 0:dd0e7a8a4572 52 {
frankvnk 0:dd0e7a8a4572 53 use_pwm = 1;
frankvnk 0:dd0e7a8a4572 54 //Setup PWM channels - default period = 4 ms (250Hz)
frankvnk 4:a16b9c09561e 55 _red->period_ms(4);
frankvnk 4:a16b9c09561e 56 _green->period_ms(4);
frankvnk 4:a16b9c09561e 57 _blue->period_ms(4);
frankvnk 4:a16b9c09561e 58 if(pwhite != NC)
frankvnk 4:a16b9c09561e 59 _white->period_ms(4);
frankvnk 0:dd0e7a8a4572 60
frankvnk 0:dd0e7a8a4572 61 // Initial RGB values.
frankvnk 4:a16b9c09561e 62 _red->write(0.0f);
frankvnk 4:a16b9c09561e 63 _green->write(0.0f);
frankvnk 4:a16b9c09561e 64 _blue->write(0.0f);
frankvnk 4:a16b9c09561e 65 if(pwhite != NC)
frankvnk 4:a16b9c09561e 66 _white->write(0.0f);
frankvnk 0:dd0e7a8a4572 67 }
frankvnk 0:dd0e7a8a4572 68 }
frankvnk 0:dd0e7a8a4572 69
frankvnk 0:dd0e7a8a4572 70 void hsi2rgbw_pwm::hsi2rgbw(float H, float S, float I, float* rgbw) {
frankvnk 0:dd0e7a8a4572 71 float _rgbw[4];
frankvnk 0:dd0e7a8a4572 72 if(rgbw == NULL)
frankvnk 0:dd0e7a8a4572 73 rgbw = _rgbw;
frankvnk 0:dd0e7a8a4572 74 float cos_h, Srgb;
frankvnk 0:dd0e7a8a4572 75 H = fmod(H,360); // cycle H around to 0-360 degrees
frankvnk 0:dd0e7a8a4572 76 H = PI*H/(float)180; // Convert to radians.
frankvnk 0:dd0e7a8a4572 77 S = S>0?(S<1?S:1):0; // clamp S and I to interval [0,1]
frankvnk 0:dd0e7a8a4572 78 I = I>0?(I<1?I:1):0;
frankvnk 4:a16b9c09561e 79 if(use_rgbw == RGBW)
frankvnk 0:dd0e7a8a4572 80 Srgb = 1;
frankvnk 0:dd0e7a8a4572 81 else
frankvnk 0:dd0e7a8a4572 82 {
frankvnk 0:dd0e7a8a4572 83 Srgb = S;
frankvnk 0:dd0e7a8a4572 84 S = 1;
frankvnk 0:dd0e7a8a4572 85 }
frankvnk 0:dd0e7a8a4572 86 // This section is modified by the addition of white so that it assumes
frankvnk 0:dd0e7a8a4572 87 // fully saturated colors, and then scales with white to lower saturation.
frankvnk 0:dd0e7a8a4572 88 //
frankvnk 0:dd0e7a8a4572 89 // Next, scale appropriately the pure color by mixing with the white channel.
frankvnk 0:dd0e7a8a4572 90 // Saturation is defined as "the ratio of colorfulness to brightness" so we will
frankvnk 0:dd0e7a8a4572 91 // do this by a simple ratio wherein the color values are scaled down by (1-S)
frankvnk 0:dd0e7a8a4572 92 // while the white LED is placed at S.
frankvnk 0:dd0e7a8a4572 93
frankvnk 0:dd0e7a8a4572 94 // This will maintain constant brightness because in HSI, R+B+G = I. Thus,
frankvnk 0:dd0e7a8a4572 95 // S*(R+B+G) = S*I. If we add to this (1-S)*I, where I is the total intensity,
frankvnk 0:dd0e7a8a4572 96 // the sum intensity stays constant while the ratio of colorfulness to brightness
frankvnk 0:dd0e7a8a4572 97 // goes down by S linearly relative to total Intensity, which is constant.
frankvnk 0:dd0e7a8a4572 98
frankvnk 0:dd0e7a8a4572 99 if(H < 2.09439) {
frankvnk 0:dd0e7a8a4572 100 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 101 rgbw[0] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 102 rgbw[1] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 4:a16b9c09561e 103 if(use_rgbw == RGBW)
frankvnk 0:dd0e7a8a4572 104 {
frankvnk 0:dd0e7a8a4572 105 rgbw[2] = 0;
frankvnk 0:dd0e7a8a4572 106 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 107 }
frankvnk 0:dd0e7a8a4572 108 else
frankvnk 0:dd0e7a8a4572 109 rgbw[2] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 110 } else if(H < 4.188787) {
frankvnk 0:dd0e7a8a4572 111 H = H - 2.09439;
frankvnk 0:dd0e7a8a4572 112 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 113 rgbw[1] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 114 rgbw[2] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 4:a16b9c09561e 115 if(use_rgbw == RGBW)
frankvnk 0:dd0e7a8a4572 116 {
frankvnk 0:dd0e7a8a4572 117 rgbw[0] = 0;
frankvnk 0:dd0e7a8a4572 118 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 119 }
frankvnk 0:dd0e7a8a4572 120 else
frankvnk 0:dd0e7a8a4572 121 rgbw[0] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 122 } else {
frankvnk 0:dd0e7a8a4572 123 H = H - 4.188787;
frankvnk 0:dd0e7a8a4572 124 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 125 rgbw[2] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 126 rgbw[0] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 4:a16b9c09561e 127 if(use_rgbw == RGBW)
frankvnk 0:dd0e7a8a4572 128 {
frankvnk 0:dd0e7a8a4572 129 rgbw[1] = 0;
frankvnk 0:dd0e7a8a4572 130 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 131 }
frankvnk 0:dd0e7a8a4572 132 else
frankvnk 0:dd0e7a8a4572 133 rgbw[1] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 134 }
frankvnk 4:a16b9c09561e 135
frankvnk 4:a16b9c09561e 136 if(use_invpwm)
frankvnk 4:a16b9c09561e 137 {
frankvnk 4:a16b9c09561e 138 rgbw[0] = (1.0f - rgbw[0]);
frankvnk 4:a16b9c09561e 139 rgbw[1] = (1.0f - rgbw[1]);
frankvnk 4:a16b9c09561e 140 rgbw[2] = (1.0f - rgbw[2]);
frankvnk 4:a16b9c09561e 141 if(use_rgbw == RGBW)
frankvnk 4:a16b9c09561e 142 rgbw[3] = (1.0f - rgbw[3]);
frankvnk 4:a16b9c09561e 143 }
frankvnk 4:a16b9c09561e 144
frankvnk 0:dd0e7a8a4572 145 // parabolic mapping.
frankvnk 0:dd0e7a8a4572 146 if(parabol) {
frankvnk 0:dd0e7a8a4572 147 rgbw[0] *= rgbw[0]; // RED
frankvnk 0:dd0e7a8a4572 148 rgbw[1] *= rgbw[1]; // GREEN
frankvnk 0:dd0e7a8a4572 149 rgbw[2] *= rgbw[2]; // BLUE
frankvnk 4:a16b9c09561e 150 if(use_rgbw == RGBW)
frankvnk 0:dd0e7a8a4572 151 rgbw[3] *= rgbw[3]; // WHITE
frankvnk 0:dd0e7a8a4572 152 }
frankvnk 4:a16b9c09561e 153
frankvnk 0:dd0e7a8a4572 154 if(use_pwm)
frankvnk 0:dd0e7a8a4572 155 {
frankvnk 4:a16b9c09561e 156 _red->write(rgbw[0]);
frankvnk 4:a16b9c09561e 157 _green->write(rgbw[1]);
frankvnk 4:a16b9c09561e 158 _blue->write(rgbw[2]);
frankvnk 4:a16b9c09561e 159 if(use_rgbw == RGBW)
frankvnk 4:a16b9c09561e 160 _white->write(rgbw[3]);
frankvnk 0:dd0e7a8a4572 161 }
frankvnk 0:dd0e7a8a4572 162 }
frankvnk 0:dd0e7a8a4572 163
frankvnk 0:dd0e7a8a4572 164 void hsi2rgbw_pwm::period(uint32_t per)
frankvnk 0:dd0e7a8a4572 165 {
frankvnk 0:dd0e7a8a4572 166 if(use_pwm)
frankvnk 0:dd0e7a8a4572 167 {
frankvnk 4:a16b9c09561e 168 _red->period_us(per);
frankvnk 4:a16b9c09561e 169 _green->period_us(per);
frankvnk 4:a16b9c09561e 170 _blue->period_us(per);
frankvnk 4:a16b9c09561e 171 if(use_rgbw == RGBW)
frankvnk 4:a16b9c09561e 172 _white->period_us(per);
frankvnk 0:dd0e7a8a4572 173 }
frankvnk 0:dd0e7a8a4572 174 }
frankvnk 0:dd0e7a8a4572 175
frankvnk 0:dd0e7a8a4572 176 void hsi2rgbw_pwm::pwm(float* rgbw)
frankvnk 0:dd0e7a8a4572 177 {
frankvnk 0:dd0e7a8a4572 178 if(use_pwm)
frankvnk 0:dd0e7a8a4572 179 {
frankvnk 4:a16b9c09561e 180 if(!use_invpwm)
frankvnk 4:a16b9c09561e 181 {
frankvnk 4:a16b9c09561e 182 _red->write(rgbw[0]);
frankvnk 4:a16b9c09561e 183 _green->write(rgbw[1]);
frankvnk 4:a16b9c09561e 184 _blue->write(rgbw[2]);
frankvnk 4:a16b9c09561e 185 if(use_rgbw == RGBW)
frankvnk 4:a16b9c09561e 186 _white->write(rgbw[3]);
frankvnk 4:a16b9c09561e 187 }
frankvnk 4:a16b9c09561e 188 else
frankvnk 4:a16b9c09561e 189 {
frankvnk 4:a16b9c09561e 190 _red->write(1.0f - rgbw[0]);
frankvnk 4:a16b9c09561e 191 _green->write(1.0f - rgbw[1]);
frankvnk 4:a16b9c09561e 192 _blue->write(1.0f - rgbw[2]);
frankvnk 4:a16b9c09561e 193 if(use_rgbw == RGBW)
frankvnk 4:a16b9c09561e 194 _white->write(1.0f - rgbw[3]);
frankvnk 4:a16b9c09561e 195 }
frankvnk 0:dd0e7a8a4572 196 }
frankvnk 0:dd0e7a8a4572 197 }
frankvnk 0:dd0e7a8a4572 198
frankvnk 0:dd0e7a8a4572 199 void hsi2rgbw_pwm::parabolic(bool para)
frankvnk 0:dd0e7a8a4572 200 {
frankvnk 0:dd0e7a8a4572 201 parabol = para;
frankvnk 0:dd0e7a8a4572 202 }
frankvnk 0:dd0e7a8a4572 203
frankvnk 0:dd0e7a8a4572 204 void hsi2rgbw_pwm::colorMode(bool como)
frankvnk 0:dd0e7a8a4572 205 {
frankvnk 0:dd0e7a8a4572 206 use_rgbw = como;
frankvnk 0:dd0e7a8a4572 207 }
frankvnk 3:dda6914d713f 208
frankvnk 4:a16b9c09561e 209 void hsi2rgbw_pwm::invertpwm(bool invpwm)
frankvnk 4:a16b9c09561e 210 {
frankvnk 4:a16b9c09561e 211 use_invpwm = invpwm;
frankvnk 4:a16b9c09561e 212 }