Frank Vannieuwkerke / HSI2RGBW_PWM

Dependents:   KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more

Revision:
0:dd0e7a8a4572
Child:
2:d164d60999c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hsi2rgbw_pwm.cpp	Mon Dec 23 20:24:17 2013 +0000
@@ -0,0 +1,148 @@
+#include "hsi2rgbw_pwm.h"
+
+#define PI 3.14159265
+
+hsi2rgbw_pwm::hsi2rgbw_pwm(PinName red, PinName green, PinName blue, PinName white) : _red(red), _green(green), _blue(blue), _white(white)
+{
+    parabol = 1;
+    use_rgbw = RGBW;
+    if(_red == NC && _green == NC && _blue == NC)
+    {
+        use_pwm = 0;
+    }
+    else
+    {
+        use_pwm = 1;
+        //Setup PWM channels - default period = 4 ms (250Hz) 
+        _red.period_ms(4);
+        _green.period_ms(4);
+        _blue.period_ms(4);
+        if(_white != NC)
+            _white.period_ms(4);
+
+        // Initial RGB values.
+        _red   = 0.0f;
+        _green = 0.0f;
+        _blue  = 0.0f;
+        if(_white != NC)
+            _white = 0.0f;
+    }
+}
+
+void hsi2rgbw_pwm::hsi2rgbw(float H, float S, float I, float* rgbw) {
+    float _rgbw[4]; 
+    if(rgbw == NULL)
+        rgbw = _rgbw;
+    float cos_h, Srgb;
+    H = fmod(H,360); // cycle H around to 0-360 degrees
+    H = PI*H/(float)180; // Convert to radians.
+    S = S>0?(S<1?S:1):0; // clamp S and I to interval [0,1]
+    I = I>0?(I<1?I:1):0;
+    if(use_rgbw)
+        Srgb = 1;
+    else
+    {
+        Srgb = S;
+        S = 1;
+    }
+    // This section is modified by the addition of white so that it assumes 
+    // fully saturated colors, and then scales with white to lower saturation.
+    //
+    // Next, scale appropriately the pure color by mixing with the white channel.
+    // Saturation is defined as "the ratio of colorfulness to brightness" so we will
+    // do this by a simple ratio wherein the color values are scaled down by (1-S)
+    // while the white LED is placed at S.
+
+    // This will maintain constant brightness because in HSI, R+B+G = I. Thus, 
+    // S*(R+B+G) = S*I. If we add to this (1-S)*I, where I is the total intensity,
+    // the sum intensity stays constant while the ratio of colorfulness to brightness
+    // goes down by S linearly relative to total Intensity, which is constant.
+
+    if(H < 2.09439) {
+        cos_h = cos(H) / cos(1.047196667-H);
+        rgbw[0] = S*I/3*(1+Srgb*cos_h);
+        rgbw[1] = S*I/3*(1+Srgb*(1-cos_h));
+        if(use_rgbw)
+        {
+            rgbw[2] = 0;
+            rgbw[3] = (1-S)*I;
+        }
+        else
+            rgbw[2] = I/3*(1-Srgb);
+    } else if(H < 4.188787) {
+        H = H - 2.09439;
+        cos_h = cos(H) / cos(1.047196667-H);
+        rgbw[1] = S*I/3*(1+Srgb*cos_h);
+        rgbw[2] = S*I/3*(1+Srgb*(1-cos_h));
+        if(use_rgbw)
+        {
+            rgbw[0] = 0;
+            rgbw[3] = (1-S)*I;
+        }
+        else
+            rgbw[0] = I/3*(1-Srgb);
+    } else {
+        H = H - 4.188787;
+        cos_h = cos(H) / cos(1.047196667-H);
+        rgbw[2] = S*I/3*(1+Srgb*cos_h);
+        rgbw[0] = S*I/3*(1+Srgb*(1-cos_h));
+        if(use_rgbw)
+        {
+            rgbw[1] = 0;
+            rgbw[3] = (1-S)*I;
+        }
+        else
+            rgbw[1] = I/3*(1-Srgb);
+    }
+  
+    // parabolic mapping.
+    if(parabol) {
+        rgbw[0] *= rgbw[0];     // RED
+        rgbw[1] *= rgbw[1];     // GREEN
+        rgbw[2] *= rgbw[2];     // BLUE
+        if(use_rgbw)
+            rgbw[3] *= rgbw[3]; // WHITE
+    }
+    if(use_pwm)
+    {
+        _red = rgbw[0];
+        _green = rgbw[1];
+        _blue = rgbw[2];
+        if(_white != NC)
+            _white = rgbw[3];
+    }
+}
+
+void hsi2rgbw_pwm::period(uint32_t per)
+{
+    if(use_pwm)
+    {
+        _red.period_ms(per);
+        _green.period_ms(per);
+        _blue.period_ms(per);
+        if(_white != NC)
+            _white.period_ms(per);
+    }
+}
+    
+void hsi2rgbw_pwm::pwm(float* rgbw)
+{
+    if(use_pwm)
+    {
+        _red = rgbw[0];
+        _green = rgbw[1];
+        _blue = rgbw[2];
+        if(_white != NC)
+            _white = rgbw[3];
+    }
+}
+
+void hsi2rgbw_pwm::parabolic(bool para)
+{
+    parabol = para;
+}
+
+void hsi2rgbw_pwm::colorMode(bool como)
+{
+    use_rgbw = como;
+}