HSI to RGB/RGBW conversion library with optional direct PWM output

Dependents:   KL25Z_HSI2RGBW_PWM KL25Z_HSI2RGBW_PWM_local KL25Z_FFT_Demo FFT_BUENA ... more

HSI to RGB / RGBW with optional PWM output

Library for converting HSI color space values to RGB or RGBW and, optionally, directly send the converted values to PWM outputs.

Code ported from http://saikoled.com - Copyright 2013, Brian Neltner
http://blog.saikoled.com/post/44677718712/how-to-convert-from-hsi-to-rgb-white

Info on the HSI color space can be found here and here.

KL25Z PTA4 as PWM output

By default, PTA4 is defined as the NMI input in the the mbed library. When PTA4 is to be used as a PWM output, we MUST disable the NMI assignment, otherwise the system will lock-up when this pin is pulled low. Read this page for more information.
The easiest way (without changing mbed-src) to disable the NMI input is by adding following code at the start of your main program (this is present in the demo program mentioned below):

// Dummy ISR for disabling NMI on PTA4 - !! DO NOT REMOVE THIS !!
extern "C" void NMI_Handler() {
    DigitalIn test(PTA4);
}

Demo code using the KL25Z-FRDM board:

Import programKL25Z_HSI2RGBW_PWM

SaikoLED fade demo using the HSI2RGBW_PWM libary


Constructor & conversion function
When 3 PWM ouptuts are declared, the library automatically selects RGB mode.
When 4 PWM ouptuts are declared, the library automatically selects RGBW mode.
When no PWM outputs are declared, the library defaults to RGBW mode. Use .colorMode(RGB) to switch to RGB mode.
depending on the way you want to use this library, you can call the conversion function in different ways

// Assign 4 PWM outputs and also allow to return the converted RGBW value.
hsi2rgbw_pwm led(PTD4, PTA12, PTA4, PTA5);
// Call to the conversion function
float H, S, I;
float rgbw[4];
led.hsi2rgbw(H, S, I, rgbw);

// Assign 4 PWM outputs, no converted RGBW value will be returned.
hsi2rgbw_pwm led(PTD4, PTA12, PTA4, PTA5);
// Call to the conversion function
float H, S, I;
led.hsi2rgbw(H, S, I);

// No PWM outputs are assigned, only the converted RGBW value will be returned.
hsi2rgbw_pwm led(NC);
// Call to the conversion function
float H, S, I;
float rgbw[4];
led.hsi2rgbw(H, S, I, rgbw);

// Assign 3 PWM outputs and also allow to return the converted RGB value.
hsi2rgbw_pwm led(PTD4, PTA12, PTA4);
// Call to the conversion function
float H, S, I;
float rgb[4];
led.hsi2rgbw(H, S, I, rgbw);

// Assign 3 PWM outputs, no converted RGB value will be returned.
hsi2rgbw_pwm led(PTD4, PTA12, PTA4);
// Call to the conversion function
float H, S, I;
led.hsi2rgbw(H, S, I);

// No PWM outputs are assigned, only the converted RGB value will be returned.
hsi2rgbw_pwm led(NC);
//Set RGB mode
led.colorMode(RGB);
// Call to the conversion function
float H, S, I;
float rgb[4];
led.hsi2rgbw(H, S, I, rgb);


Hue, Saturation and Intesity range

Hue0...360Color value : 0 or 360 = red, 120 = green, 240 = blue, 60 = yellow, 300 = magenta, ...
Saturation0...1Color saturation : 0 = white, 1 = max. color, 0.7 is a nice pastel
Intensity0...1Color intensity : 0 = off, 1 = full intensity


RGB(W) return value
In your main program, declare an array of 4 float values and pass the pointer to this array to the function:
Even when RGB is used, do declare an array of 4 float values.

float rgbw[4];

Upon exit, the function will return the values in rgbw[], representing the red, green, blue and white component that corresponds to the chosen HSI values. Range : 0...1 where 0 = minimum and 1 = maximum.

rgbw[0]RED
rgbw[1]GREEN
rgbw[2]BLUE
rgbw[3]WHITENote : this value has no significance when RGB mode is used.


parabolic mode
By default, each component of the RGB(W) return value is mapped to a parabolic scale.
Call led.parabolic(0); to disable the parabolic mapping.

Choose RGB or RGBW mode
By default, the conversion return value is set to RGBW.
Call led.colorMode(RGB); to change to RGB mode.
Call led.colorMode(RGBW); to go back to RGBW mode.

Change PWM period
By default, the PWM period is set to 4ms (250Hz).
Call led.period(n); to change the PWM period (replace n with a value in ms).

Change PWM values
We can alter the PWM outputs directly, without passing through the HSI to RGB(W) conversion.
declare float rgbw[4]; and set each value of this array.
Call led.pwm(rgbw); to write the values directly to the PWM outputs.

Invert PWM channels
When common anode LEDs are used, we need to invert the PWM signal..
Call led.invertpwm(1); to use the inverted PWM signal.

NOTES
period() and pwm() will not change any value if no PWM pins are declared.
Do not forget to replace led. with the declared function name.

Committer:
frankvnk
Date:
Mon Dec 30 11:22:53 2013 +0000
Revision:
3:dda6914d713f
Parent:
1:191c9b17351c
Child:
4:a16b9c09561e
doc error corrected.
; changed period_ms to period_us

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:dd0e7a8a4572 1 /**************************************************************************************************************
frankvnk 0:dd0e7a8a4572 2 ***** *****
frankvnk 0:dd0e7a8a4572 3 ***** Name: hsi2rgbw.h *****
frankvnk 0:dd0e7a8a4572 4 ***** Date: 22/12/2013 *****
frankvnk 0:dd0e7a8a4572 5 ***** Auth: Frank Vannieuwkerke *****
frankvnk 0:dd0e7a8a4572 6 ***** Func: library for converting HSI color space values to RGBW *****
frankvnk 0:dd0e7a8a4572 7 ***** *****
frankvnk 0:dd0e7a8a4572 8 ***** Code ported from http://saikoled.com - Copyright 2013, Brian Neltner *****
frankvnk 0:dd0e7a8a4572 9 ***** http://blog.saikoled.com/post/44677718712/how-to-convert-from-hsi-to-rgb-white *****
frankvnk 0:dd0e7a8a4572 10 ***** http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi-colorspace *****
frankvnk 0:dd0e7a8a4572 11 ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_random_fade/myki_16_bit_random_fade.ino *****
frankvnk 0:dd0e7a8a4572 12 ***** https://github.com/saikoLED/MyKi/blob/master/myki_16_bit_fade/myki_16_bit_fade.ino *****
frankvnk 0:dd0e7a8a4572 13 ***** *****
frankvnk 0:dd0e7a8a4572 14 ***** This program is free software: you can redistribute it and/or modify *****
frankvnk 0:dd0e7a8a4572 15 ***** it under the terms of the GNU General Public License as published by *****
frankvnk 0:dd0e7a8a4572 16 ***** the Free Software Foundation, version 3 of the License. *****
frankvnk 0:dd0e7a8a4572 17 ***** *****
frankvnk 0:dd0e7a8a4572 18 ***** This program is distributed in the hope that it will be useful, *****
frankvnk 0:dd0e7a8a4572 19 ***** but WITHOUT ANY WARRANTY; without even the implied warranty of *****
frankvnk 0:dd0e7a8a4572 20 ***** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *****
frankvnk 0:dd0e7a8a4572 21 ***** GNU General Public License for more details. *****
frankvnk 0:dd0e7a8a4572 22 ***** *****
frankvnk 0:dd0e7a8a4572 23 ***** A copy of the GNU General Public License can be found at *****
frankvnk 0:dd0e7a8a4572 24 ***** http://www.gnu.org/licenses/gpl.html *****
frankvnk 0:dd0e7a8a4572 25 **************************************************************************************************************/
frankvnk 0:dd0e7a8a4572 26
frankvnk 0:dd0e7a8a4572 27 #include "mbed.h"
frankvnk 0:dd0e7a8a4572 28
frankvnk 0:dd0e7a8a4572 29 #ifndef HSI2RGBW_PWM_H
frankvnk 0:dd0e7a8a4572 30 #define HSI2RGBW_PWM_H
frankvnk 0:dd0e7a8a4572 31
frankvnk 0:dd0e7a8a4572 32 #define RGBW 1
frankvnk 0:dd0e7a8a4572 33 #define RGB 0
frankvnk 0:dd0e7a8a4572 34
frankvnk 0:dd0e7a8a4572 35 /** Class to convert HSI colorspace value to its corresponding RGBW value.
frankvnk 0:dd0e7a8a4572 36 * 'red', 'green', 'blue' and 'white' pin can be any PWM pin.
frankvnk 0:dd0e7a8a4572 37 */
frankvnk 0:dd0e7a8a4572 38
frankvnk 0:dd0e7a8a4572 39 class hsi2rgbw_pwm {
frankvnk 0:dd0e7a8a4572 40 public:
frankvnk 0:dd0e7a8a4572 41 /** Create a HSI2RGBW object connected to 4 PWM pins.
frankvnk 0:dd0e7a8a4572 42 *
frankvnk 0:dd0e7a8a4572 43 * @param red = RED PWM pin\n
frankvnk 0:dd0e7a8a4572 44 * @param blue = BLUE PWM pin\n
frankvnk 0:dd0e7a8a4572 45 * @param green = GREEN PWM pin\n
frankvnk 0:dd0e7a8a4572 46 * @param white = WHITE PWM pin\n
frankvnk 0:dd0e7a8a4572 47 * @return none\n
frankvnk 0:dd0e7a8a4572 48 * When you want to use hsi2rgbw standalone (no PWMout), use following initializer:\n
frankvnk 0:dd0e7a8a4572 49 * hsi2rgbw_pwm led; OR hsi2rgbw_pwm led(NC, NC, NC, NC);\n
frankvnk 0:dd0e7a8a4572 50 * Create a float array in your program to return the rgbw values, eg : float rgbw[4]\n
frankvnk 0:dd0e7a8a4572 51 * Call hsi2rgbw with the rgbw pointer : hsi2rgbw(H, S, I, rgbw)\n
frankvnk 0:dd0e7a8a4572 52 */
frankvnk 0:dd0e7a8a4572 53 hsi2rgbw_pwm(PinName red = NC, PinName green = NC, PinName blue = NC, PinName white = NC);
frankvnk 0:dd0e7a8a4572 54
frankvnk 0:dd0e7a8a4572 55 /** Convert HSI to RGBW or RGB.
frankvnk 0:dd0e7a8a4572 56 *
frankvnk 0:dd0e7a8a4572 57 * @param Hue = float (0..1)\n
frankvnk 0:dd0e7a8a4572 58 * @param Saturation = float (0..1)\n
frankvnk 0:dd0e7a8a4572 59 * @param Intensity = float (0..1)\n
frankvnk 0:dd0e7a8a4572 60 * @param rgbw = Optional pointer to float array[4]\n
frankvnk 0:dd0e7a8a4572 61 * This parameter can be omitted when PWM output is enabled:\n
frankvnk 0:dd0e7a8a4572 62 * hsi2rgbw(H, S, I)\n
frankvnk 1:191c9b17351c 63 *
frankvnk 0:dd0e7a8a4572 64 * This function can be used to convert HSI to RGBW or RGB:\n
frankvnk 0:dd0e7a8a4572 65 * call colorMode(RGBW) to enable HSI->RGBW\n
frankvnk 3:dda6914d713f 66 * call colorMode(RGB) to enable HSI->RGB\n
frankvnk 0:dd0e7a8a4572 67 * IMPORTANT NOTE : When RGB is selected and you want the function to return\n
frankvnk 0:dd0e7a8a4572 68 * the converted value, do declare a 4 element array!!\n
frankvnk 0:dd0e7a8a4572 69 * The value in the 4th element can be discarded.\n
frankvnk 0:dd0e7a8a4572 70 */
frankvnk 0:dd0e7a8a4572 71 void hsi2rgbw(float H, float S, float I, float* rgbw = NULL);
frankvnk 0:dd0e7a8a4572 72
frankvnk 0:dd0e7a8a4572 73 /** Change PWM period.
frankvnk 0:dd0e7a8a4572 74 *
frankvnk 3:dda6914d713f 75 * @param Period (in us)\n
frankvnk 0:dd0e7a8a4572 76 * @return none\n
frankvnk 0:dd0e7a8a4572 77 */
frankvnk 0:dd0e7a8a4572 78 void period(uint32_t per);
frankvnk 0:dd0e7a8a4572 79
frankvnk 0:dd0e7a8a4572 80 /** Change PWM value.
frankvnk 0:dd0e7a8a4572 81 *
frankvnk 0:dd0e7a8a4572 82 * @param pointer to float array[4]\n
frankvnk 0:dd0e7a8a4572 83 * @param array[0] = RED PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 84 * @param array[1] = BLUE PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 85 * @param array[2] = GREEN PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 86 * @param array[3] = WHITE PWM value (0...1)\n
frankvnk 1:191c9b17351c 87 *
frankvnk 0:dd0e7a8a4572 88 * Use this function to set the PWM values without conversion.\n
frankvnk 0:dd0e7a8a4572 89 * @return none\n
frankvnk 0:dd0e7a8a4572 90 */
frankvnk 0:dd0e7a8a4572 91 void pwm(float* rgbw);
frankvnk 0:dd0e7a8a4572 92
frankvnk 0:dd0e7a8a4572 93 /** Set parabolic mode.
frankvnk 0:dd0e7a8a4572 94 *
frankvnk 1:191c9b17351c 95 * @param Parabolic 1 = map rgbw output value to a parabolic curve (default).\n
frankvnk 0:dd0e7a8a4572 96 * 0 = linear mapping.\n
frankvnk 0:dd0e7a8a4572 97 * @return none\n
frankvnk 0:dd0e7a8a4572 98 */
frankvnk 0:dd0e7a8a4572 99 void parabolic(bool para);
frankvnk 0:dd0e7a8a4572 100
frankvnk 0:dd0e7a8a4572 101 /** Set color conversion mode.
frankvnk 0:dd0e7a8a4572 102 *
frankvnk 1:191c9b17351c 103 * @param Colormode RGBW (1) = convert HSI to RGBW (default).\n
frankvnk 0:dd0e7a8a4572 104 * RGB (0) = convert HSI to RGB.\n
frankvnk 0:dd0e7a8a4572 105 * @return none\n
frankvnk 0:dd0e7a8a4572 106 */
frankvnk 0:dd0e7a8a4572 107 void colorMode(bool como);
frankvnk 0:dd0e7a8a4572 108
frankvnk 0:dd0e7a8a4572 109 private:
frankvnk 0:dd0e7a8a4572 110 PwmOut _red;
frankvnk 0:dd0e7a8a4572 111 PwmOut _green;
frankvnk 0:dd0e7a8a4572 112 PwmOut _blue;
frankvnk 0:dd0e7a8a4572 113 PwmOut _white;
frankvnk 0:dd0e7a8a4572 114 bool parabol;
frankvnk 0:dd0e7a8a4572 115 bool use_pwm;
frankvnk 0:dd0e7a8a4572 116 bool use_rgbw;
frankvnk 0:dd0e7a8a4572 117 };
frankvnk 0:dd0e7a8a4572 118 #endif