Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more
hsi2rgbw_pwm.cpp
- Committer:
- frankvnk
- Date:
- 2014-02-02
- Revision:
- 4:a16b9c09561e
- Parent:
- 3:dda6914d713f
File content as of revision 4:a16b9c09561e:
/************************************************************************************************************** ***** ***** ***** Name: hsi2rgbw.cpp ***** ***** Date: 22/12/2013 ***** ***** Auth: Frank Vannieuwkerke ***** ***** Func: library for converting HSI color space values to RGBW ***** ***** ***** ***** Code ported from http://saikoled.com - Copyright 2013, Brian Neltner ***** ***** http://blog.saikoled.com/post/44677718712/how-to-convert-from-hsi-to-rgb-white ***** ***** http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi-colorspace ***** ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_random_fade/myki_16_bit_random_fade.ino ***** ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_fade/myki_16_bit_fade.ino ***** ***** ***** ***** This program is free software: you can redistribute it and/or modify ***** ***** it under the terms of the GNU General Public License as published by ***** ***** the Free Software Foundation, version 3 of the License. ***** ***** ***** ***** This program is distributed in the hope that it will be useful, ***** ***** but WITHOUT ANY WARRANTY; without even the implied warranty of ***** ***** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ***** ***** GNU General Public License for more details. ***** ***** ***** ***** A copy of the GNU General Public License can be found at ***** ***** http://www.gnu.org/licenses/gpl.html ***** **************************************************************************************************************/ #include "hsi2rgbw_pwm.h" #define PI 3.14159265 PwmOut *_red; PwmOut *_green; PwmOut *_blue; PwmOut *_white; hsi2rgbw_pwm::hsi2rgbw_pwm(PinName pred, PinName pgreen, PinName pblue, PinName pwhite) { parabol = 1; use_invpwm = 0; use_rgbw = RGBW; if(pred != NC) _red = new PwmOut (pred); if(pgreen != NC) _green = new PwmOut (pgreen); if(pblue != NC) _blue = new PwmOut (pblue); if(pwhite != NC) _white = new PwmOut (pwhite); if((pred != NC) && (pgreen != NC) && (pblue != NC) && (pwhite == NC)) use_rgbw = RGB; if((pred == NC) && (pgreen == NC) && (pblue == NC) && (pwhite == 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(pwhite != NC) _white->period_ms(4); // Initial RGB values. _red->write(0.0f); _green->write(0.0f); _blue->write(0.0f); if(pwhite != NC) _white->write(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 == 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) { 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) { 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) { rgbw[1] = 0; rgbw[3] = (1-S)*I; } else rgbw[1] = I/3*(1-Srgb); } if(use_invpwm) { rgbw[0] = (1.0f - rgbw[0]); rgbw[1] = (1.0f - rgbw[1]); rgbw[2] = (1.0f - rgbw[2]); if(use_rgbw == RGBW) rgbw[3] = (1.0f - rgbw[3]); } // parabolic mapping. if(parabol) { rgbw[0] *= rgbw[0]; // RED rgbw[1] *= rgbw[1]; // GREEN rgbw[2] *= rgbw[2]; // BLUE if(use_rgbw == RGBW) rgbw[3] *= rgbw[3]; // WHITE } if(use_pwm) { _red->write(rgbw[0]); _green->write(rgbw[1]); _blue->write(rgbw[2]); if(use_rgbw == RGBW) _white->write(rgbw[3]); } } void hsi2rgbw_pwm::period(uint32_t per) { if(use_pwm) { _red->period_us(per); _green->period_us(per); _blue->period_us(per); if(use_rgbw == RGBW) _white->period_us(per); } } void hsi2rgbw_pwm::pwm(float* rgbw) { if(use_pwm) { if(!use_invpwm) { _red->write(rgbw[0]); _green->write(rgbw[1]); _blue->write(rgbw[2]); if(use_rgbw == RGBW) _white->write(rgbw[3]); } else { _red->write(1.0f - rgbw[0]); _green->write(1.0f - rgbw[1]); _blue->write(1.0f - rgbw[2]); if(use_rgbw == RGBW) _white->write(1.0f - rgbw[3]); } } } void hsi2rgbw_pwm::parabolic(bool para) { parabol = para; } void hsi2rgbw_pwm::colorMode(bool como) { use_rgbw = como; } void hsi2rgbw_pwm::invertpwm(bool invpwm) { use_invpwm = invpwm; }