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@0:dd0e7a8a4572, 2013-12-23 (annotated)
- 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?
User | Revision | Line number | New 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 | } |