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:
Sun Feb 02 14:41:29 2014 +0000
Revision:
4:a16b9c09561e
Parent:
3:dda6914d713f
Child:
5:68daa710ba3f
Fixed runtime error (RGB mode).
; Added invertpwm.

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 4:a16b9c09561e 49 * hsi2rgbw_pwm led(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 4:a16b9c09561e 52 * When PWM ouptuts are used, RGB or RGBW mode is automatically set.\n
frankvnk 4:a16b9c09561e 53 * When no PWM outputs are used, the default output is RGBW.\n
frankvnk 0:dd0e7a8a4572 54 */
frankvnk 4:a16b9c09561e 55 hsi2rgbw_pwm(PinName pred = NC, PinName pgreen = NC, PinName pblue = NC, PinName pwhite = NC);
frankvnk 0:dd0e7a8a4572 56
frankvnk 0:dd0e7a8a4572 57 /** Convert HSI to RGBW or RGB.
frankvnk 0:dd0e7a8a4572 58 *
frankvnk 0:dd0e7a8a4572 59 * @param Hue = float (0..1)\n
frankvnk 0:dd0e7a8a4572 60 * @param Saturation = float (0..1)\n
frankvnk 0:dd0e7a8a4572 61 * @param Intensity = float (0..1)\n
frankvnk 4:a16b9c09561e 62 * @param rgbw Optional pointer to float array[4]\n
frankvnk 4:a16b9c09561e 63 * This parameter can be omitted when PWM output is enabled:\n
frankvnk 4:a16b9c09561e 64 * hsi2rgbw(H, S, I)\n
frankvnk 1:191c9b17351c 65 *
frankvnk 0:dd0e7a8a4572 66 * This function can be used to convert HSI to RGBW or RGB:\n
frankvnk 0:dd0e7a8a4572 67 * call colorMode(RGBW) to enable HSI->RGBW\n
frankvnk 3:dda6914d713f 68 * call colorMode(RGB) to enable HSI->RGB\n
frankvnk 0:dd0e7a8a4572 69 * IMPORTANT NOTE : When RGB is selected and you want the function to return\n
frankvnk 0:dd0e7a8a4572 70 * the converted value, do declare a 4 element array!!\n
frankvnk 0:dd0e7a8a4572 71 * The value in the 4th element can be discarded.\n
frankvnk 0:dd0e7a8a4572 72 */
frankvnk 0:dd0e7a8a4572 73 void hsi2rgbw(float H, float S, float I, float* rgbw = NULL);
frankvnk 0:dd0e7a8a4572 74
frankvnk 0:dd0e7a8a4572 75 /** Change PWM period.
frankvnk 0:dd0e7a8a4572 76 *
frankvnk 3:dda6914d713f 77 * @param Period (in us)\n
frankvnk 0:dd0e7a8a4572 78 * @return none\n
frankvnk 0:dd0e7a8a4572 79 */
frankvnk 0:dd0e7a8a4572 80 void period(uint32_t per);
frankvnk 0:dd0e7a8a4572 81
frankvnk 0:dd0e7a8a4572 82 /** Change PWM value.
frankvnk 0:dd0e7a8a4572 83 *
frankvnk 0:dd0e7a8a4572 84 * @param pointer to float array[4]\n
frankvnk 0:dd0e7a8a4572 85 * @param array[0] = RED PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 86 * @param array[1] = BLUE PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 87 * @param array[2] = GREEN PWM value (0...1)\n
frankvnk 0:dd0e7a8a4572 88 * @param array[3] = WHITE PWM value (0...1)\n
frankvnk 1:191c9b17351c 89 *
frankvnk 0:dd0e7a8a4572 90 * Use this function to set the PWM values without conversion.\n
frankvnk 0:dd0e7a8a4572 91 * @return none\n
frankvnk 0:dd0e7a8a4572 92 */
frankvnk 0:dd0e7a8a4572 93 void pwm(float* rgbw);
frankvnk 0:dd0e7a8a4572 94
frankvnk 0:dd0e7a8a4572 95 /** Set parabolic mode.
frankvnk 0:dd0e7a8a4572 96 *
frankvnk 1:191c9b17351c 97 * @param Parabolic 1 = map rgbw output value to a parabolic curve (default).\n
frankvnk 0:dd0e7a8a4572 98 * 0 = linear mapping.\n
frankvnk 0:dd0e7a8a4572 99 * @return none\n
frankvnk 0:dd0e7a8a4572 100 */
frankvnk 0:dd0e7a8a4572 101 void parabolic(bool para);
frankvnk 0:dd0e7a8a4572 102
frankvnk 0:dd0e7a8a4572 103 /** Set color conversion mode.
frankvnk 0:dd0e7a8a4572 104 *
frankvnk 4:a16b9c09561e 105 * @param Colormode RGBW (1) = convert HSI to RGBW.\n
frankvnk 0:dd0e7a8a4572 106 * RGB (0) = convert HSI to RGB.\n
frankvnk 0:dd0e7a8a4572 107 * @return none\n
frankvnk 0:dd0e7a8a4572 108 */
frankvnk 0:dd0e7a8a4572 109 void colorMode(bool como);
frankvnk 0:dd0e7a8a4572 110
frankvnk 4:a16b9c09561e 111 /** Invert PWM output.
frankvnk 4:a16b9c09561e 112 *
frankvnk 4:a16b9c09561e 113 * @param InvertPWM 0 : Normal PWM output.\n
frankvnk 4:a16b9c09561e 114 * 1 : PWM output is inverted.\n
frankvnk 4:a16b9c09561e 115 * @return none\n
frankvnk 4:a16b9c09561e 116 *
frankvnk 4:a16b9c09561e 117 * Enable (1) when common anode LEDs are used.\n
frankvnk 4:a16b9c09561e 118 */
frankvnk 4:a16b9c09561e 119 void invertpwm(bool invpwm);
frankvnk 4:a16b9c09561e 120
frankvnk 0:dd0e7a8a4572 121 private:
frankvnk 0:dd0e7a8a4572 122 bool parabol;
frankvnk 0:dd0e7a8a4572 123 bool use_pwm;
frankvnk 0:dd0e7a8a4572 124 bool use_rgbw;
frankvnk 4:a16b9c09561e 125 bool use_invpwm;
frankvnk 0:dd0e7a8a4572 126 };
frankvnk 0:dd0e7a8a4572 127 #endif