Frank Vannieuwkerke / HSI2RGBW_PWM

Dependents:   KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more

Committer:
frankvnk
Date:
Mon Dec 23 20:24:17 2013 +0000
Revision:
0:dd0e7a8a4572
Child:
2:d164d60999c4
Initial release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:dd0e7a8a4572 1 #include "hsi2rgbw_pwm.h"
frankvnk 0:dd0e7a8a4572 2
frankvnk 0:dd0e7a8a4572 3 #define PI 3.14159265
frankvnk 0:dd0e7a8a4572 4
frankvnk 0:dd0e7a8a4572 5 hsi2rgbw_pwm::hsi2rgbw_pwm(PinName red, PinName green, PinName blue, PinName white) : _red(red), _green(green), _blue(blue), _white(white)
frankvnk 0:dd0e7a8a4572 6 {
frankvnk 0:dd0e7a8a4572 7 parabol = 1;
frankvnk 0:dd0e7a8a4572 8 use_rgbw = RGBW;
frankvnk 0:dd0e7a8a4572 9 if(_red == NC && _green == NC && _blue == NC)
frankvnk 0:dd0e7a8a4572 10 {
frankvnk 0:dd0e7a8a4572 11 use_pwm = 0;
frankvnk 0:dd0e7a8a4572 12 }
frankvnk 0:dd0e7a8a4572 13 else
frankvnk 0:dd0e7a8a4572 14 {
frankvnk 0:dd0e7a8a4572 15 use_pwm = 1;
frankvnk 0:dd0e7a8a4572 16 //Setup PWM channels - default period = 4 ms (250Hz)
frankvnk 0:dd0e7a8a4572 17 _red.period_ms(4);
frankvnk 0:dd0e7a8a4572 18 _green.period_ms(4);
frankvnk 0:dd0e7a8a4572 19 _blue.period_ms(4);
frankvnk 0:dd0e7a8a4572 20 if(_white != NC)
frankvnk 0:dd0e7a8a4572 21 _white.period_ms(4);
frankvnk 0:dd0e7a8a4572 22
frankvnk 0:dd0e7a8a4572 23 // Initial RGB values.
frankvnk 0:dd0e7a8a4572 24 _red = 0.0f;
frankvnk 0:dd0e7a8a4572 25 _green = 0.0f;
frankvnk 0:dd0e7a8a4572 26 _blue = 0.0f;
frankvnk 0:dd0e7a8a4572 27 if(_white != NC)
frankvnk 0:dd0e7a8a4572 28 _white = 0.0f;
frankvnk 0:dd0e7a8a4572 29 }
frankvnk 0:dd0e7a8a4572 30 }
frankvnk 0:dd0e7a8a4572 31
frankvnk 0:dd0e7a8a4572 32 void hsi2rgbw_pwm::hsi2rgbw(float H, float S, float I, float* rgbw) {
frankvnk 0:dd0e7a8a4572 33 float _rgbw[4];
frankvnk 0:dd0e7a8a4572 34 if(rgbw == NULL)
frankvnk 0:dd0e7a8a4572 35 rgbw = _rgbw;
frankvnk 0:dd0e7a8a4572 36 float cos_h, Srgb;
frankvnk 0:dd0e7a8a4572 37 H = fmod(H,360); // cycle H around to 0-360 degrees
frankvnk 0:dd0e7a8a4572 38 H = PI*H/(float)180; // Convert to radians.
frankvnk 0:dd0e7a8a4572 39 S = S>0?(S<1?S:1):0; // clamp S and I to interval [0,1]
frankvnk 0:dd0e7a8a4572 40 I = I>0?(I<1?I:1):0;
frankvnk 0:dd0e7a8a4572 41 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 42 Srgb = 1;
frankvnk 0:dd0e7a8a4572 43 else
frankvnk 0:dd0e7a8a4572 44 {
frankvnk 0:dd0e7a8a4572 45 Srgb = S;
frankvnk 0:dd0e7a8a4572 46 S = 1;
frankvnk 0:dd0e7a8a4572 47 }
frankvnk 0:dd0e7a8a4572 48 // This section is modified by the addition of white so that it assumes
frankvnk 0:dd0e7a8a4572 49 // fully saturated colors, and then scales with white to lower saturation.
frankvnk 0:dd0e7a8a4572 50 //
frankvnk 0:dd0e7a8a4572 51 // Next, scale appropriately the pure color by mixing with the white channel.
frankvnk 0:dd0e7a8a4572 52 // Saturation is defined as "the ratio of colorfulness to brightness" so we will
frankvnk 0:dd0e7a8a4572 53 // do this by a simple ratio wherein the color values are scaled down by (1-S)
frankvnk 0:dd0e7a8a4572 54 // while the white LED is placed at S.
frankvnk 0:dd0e7a8a4572 55
frankvnk 0:dd0e7a8a4572 56 // This will maintain constant brightness because in HSI, R+B+G = I. Thus,
frankvnk 0:dd0e7a8a4572 57 // S*(R+B+G) = S*I. If we add to this (1-S)*I, where I is the total intensity,
frankvnk 0:dd0e7a8a4572 58 // the sum intensity stays constant while the ratio of colorfulness to brightness
frankvnk 0:dd0e7a8a4572 59 // goes down by S linearly relative to total Intensity, which is constant.
frankvnk 0:dd0e7a8a4572 60
frankvnk 0:dd0e7a8a4572 61 if(H < 2.09439) {
frankvnk 0:dd0e7a8a4572 62 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 63 rgbw[0] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 64 rgbw[1] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 65 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 66 {
frankvnk 0:dd0e7a8a4572 67 rgbw[2] = 0;
frankvnk 0:dd0e7a8a4572 68 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 69 }
frankvnk 0:dd0e7a8a4572 70 else
frankvnk 0:dd0e7a8a4572 71 rgbw[2] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 72 } else if(H < 4.188787) {
frankvnk 0:dd0e7a8a4572 73 H = H - 2.09439;
frankvnk 0:dd0e7a8a4572 74 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 75 rgbw[1] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 76 rgbw[2] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 77 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 78 {
frankvnk 0:dd0e7a8a4572 79 rgbw[0] = 0;
frankvnk 0:dd0e7a8a4572 80 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 81 }
frankvnk 0:dd0e7a8a4572 82 else
frankvnk 0:dd0e7a8a4572 83 rgbw[0] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 84 } else {
frankvnk 0:dd0e7a8a4572 85 H = H - 4.188787;
frankvnk 0:dd0e7a8a4572 86 cos_h = cos(H) / cos(1.047196667-H);
frankvnk 0:dd0e7a8a4572 87 rgbw[2] = S*I/3*(1+Srgb*cos_h);
frankvnk 0:dd0e7a8a4572 88 rgbw[0] = S*I/3*(1+Srgb*(1-cos_h));
frankvnk 0:dd0e7a8a4572 89 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 90 {
frankvnk 0:dd0e7a8a4572 91 rgbw[1] = 0;
frankvnk 0:dd0e7a8a4572 92 rgbw[3] = (1-S)*I;
frankvnk 0:dd0e7a8a4572 93 }
frankvnk 0:dd0e7a8a4572 94 else
frankvnk 0:dd0e7a8a4572 95 rgbw[1] = I/3*(1-Srgb);
frankvnk 0:dd0e7a8a4572 96 }
frankvnk 0:dd0e7a8a4572 97
frankvnk 0:dd0e7a8a4572 98 // parabolic mapping.
frankvnk 0:dd0e7a8a4572 99 if(parabol) {
frankvnk 0:dd0e7a8a4572 100 rgbw[0] *= rgbw[0]; // RED
frankvnk 0:dd0e7a8a4572 101 rgbw[1] *= rgbw[1]; // GREEN
frankvnk 0:dd0e7a8a4572 102 rgbw[2] *= rgbw[2]; // BLUE
frankvnk 0:dd0e7a8a4572 103 if(use_rgbw)
frankvnk 0:dd0e7a8a4572 104 rgbw[3] *= rgbw[3]; // WHITE
frankvnk 0:dd0e7a8a4572 105 }
frankvnk 0:dd0e7a8a4572 106 if(use_pwm)
frankvnk 0:dd0e7a8a4572 107 {
frankvnk 0:dd0e7a8a4572 108 _red = rgbw[0];
frankvnk 0:dd0e7a8a4572 109 _green = rgbw[1];
frankvnk 0:dd0e7a8a4572 110 _blue = rgbw[2];
frankvnk 0:dd0e7a8a4572 111 if(_white != NC)
frankvnk 0:dd0e7a8a4572 112 _white = rgbw[3];
frankvnk 0:dd0e7a8a4572 113 }
frankvnk 0:dd0e7a8a4572 114 }
frankvnk 0:dd0e7a8a4572 115
frankvnk 0:dd0e7a8a4572 116 void hsi2rgbw_pwm::period(uint32_t per)
frankvnk 0:dd0e7a8a4572 117 {
frankvnk 0:dd0e7a8a4572 118 if(use_pwm)
frankvnk 0:dd0e7a8a4572 119 {
frankvnk 0:dd0e7a8a4572 120 _red.period_ms(per);
frankvnk 0:dd0e7a8a4572 121 _green.period_ms(per);
frankvnk 0:dd0e7a8a4572 122 _blue.period_ms(per);
frankvnk 0:dd0e7a8a4572 123 if(_white != NC)
frankvnk 0:dd0e7a8a4572 124 _white.period_ms(per);
frankvnk 0:dd0e7a8a4572 125 }
frankvnk 0:dd0e7a8a4572 126 }
frankvnk 0:dd0e7a8a4572 127
frankvnk 0:dd0e7a8a4572 128 void hsi2rgbw_pwm::pwm(float* rgbw)
frankvnk 0:dd0e7a8a4572 129 {
frankvnk 0:dd0e7a8a4572 130 if(use_pwm)
frankvnk 0:dd0e7a8a4572 131 {
frankvnk 0:dd0e7a8a4572 132 _red = rgbw[0];
frankvnk 0:dd0e7a8a4572 133 _green = rgbw[1];
frankvnk 0:dd0e7a8a4572 134 _blue = rgbw[2];
frankvnk 0:dd0e7a8a4572 135 if(_white != NC)
frankvnk 0:dd0e7a8a4572 136 _white = rgbw[3];
frankvnk 0:dd0e7a8a4572 137 }
frankvnk 0:dd0e7a8a4572 138 }
frankvnk 0:dd0e7a8a4572 139
frankvnk 0:dd0e7a8a4572 140 void hsi2rgbw_pwm::parabolic(bool para)
frankvnk 0:dd0e7a8a4572 141 {
frankvnk 0:dd0e7a8a4572 142 parabol = para;
frankvnk 0:dd0e7a8a4572 143 }
frankvnk 0:dd0e7a8a4572 144
frankvnk 0:dd0e7a8a4572 145 void hsi2rgbw_pwm::colorMode(bool como)
frankvnk 0:dd0e7a8a4572 146 {
frankvnk 0:dd0e7a8a4572 147 use_rgbw = como;
frankvnk 0:dd0e7a8a4572 148 }