FastLED 3.9.15
Loading...
Searching...
No Matches

◆ hsv2rgb_rainbow() [1/2]

void hsv2rgb_rainbow ( const CHSV & hsv,
CRGB & rgb )

Definition at line 251 of file hsv2rgb.cpp.

252{
253 // Yellow has a higher inherent brightness than
254 // any other color; 'pure' yellow is perceived to
255 // be 93% as bright as white. In order to make
256 // yellow appear the correct relative brightness,
257 // it has to be rendered brighter than all other
258 // colors.
259 // Level Y1 is a moderate boost, the default.
260 // Level Y2 is a strong boost.
261 const uint8_t Y1 = 1;
262 const uint8_t Y2 = 0;
263
264 // G2: Whether to divide all greens by two.
265 // Depends GREATLY on your particular LEDs
266 const uint8_t G2 = 0;
267
268 // Gscale: what to scale green down by.
269 // Depends GREATLY on your particular LEDs
270 const uint8_t Gscale = 0;
271
272
273 uint8_t hue = hsv.hue;
274 uint8_t sat = hsv.sat;
275 uint8_t val = hsv.val;
276
277 uint8_t offset = hue & 0x1F; // 0..31
278
279 // offset8 = offset * 8
280 uint8_t offset8 = offset;
281 {
282#if defined(__AVR__)
283 // Left to its own devices, gcc turns "x <<= 3" into a loop
284 // It's much faster and smaller to just do three single-bit shifts
285 // So this business is to force that.
286 offset8 <<= 1;
287 asm volatile("");
288 offset8 <<= 1;
289 asm volatile("");
290 offset8 <<= 1;
291#else
292 // On ARM and other non-AVR platforms, we just shift 3.
293 offset8 <<= 3;
294#endif
295 }
296
297 uint8_t third = scale8( offset8, (256 / 3)); // max = 85
298
299 uint8_t r, g, b;
300
301 if( ! (hue & 0x80) ) {
302 // 0XX
303 if( ! (hue & 0x40) ) {
304 // 00X
305 //section 0-1
306 if( ! (hue & 0x20) ) {
307 // 000
308 //case 0: // R -> O
309 r = K255 - third;
310 g = third;
311 b = 0;
313 } else {
314 // 001
315 //case 1: // O -> Y
316 if( Y1 ) {
317 r = K171;
318 g = K85 + third ;
319 b = 0;
321 }
322 if( Y2 ) {
323 r = K170 + third;
324 //uint8_t twothirds = (third << 1);
325 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
326 g = K85 + twothirds;
327 b = 0;
329 }
330 }
331 } else {
332 //01X
333 // section 2-3
334 if( ! (hue & 0x20) ) {
335 // 010
336 //case 2: // Y -> G
337 if( Y1 ) {
338 //uint8_t twothirds = (third << 1);
339 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
340 r = K171 - twothirds;
341 g = K170 + third;
342 b = 0;
344 }
345 if( Y2 ) {
346 r = K255 - offset8;
347 g = K255;
348 b = 0;
350 }
351 } else {
352 // 011
353 // case 3: // G -> A
354 r = 0;
356 g = K255 - third;
357 b = third;
358 }
359 }
360 } else {
361 // section 4-7
362 // 1XX
363 if( ! (hue & 0x40) ) {
364 // 10X
365 if( ! ( hue & 0x20) ) {
366 // 100
367 //case 4: // A -> B
368 r = 0;
370 //uint8_t twothirds = (third << 1);
371 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
372 g = K171 - twothirds; //K170?
373 b = K85 + twothirds;
374
375 } else {
376 // 101
377 //case 5: // B -> P
378 r = third;
379 g = 0;
381 b = K255 - third;
382
383 }
384 } else {
385 if( ! (hue & 0x20) ) {
386 // 110
387 //case 6: // P -- K
388 r = K85 + third;
389 g = 0;
391 b = K171 - third;
392
393 } else {
394 // 111
395 //case 7: // K -> R
396 r = K170 + third;
397 g = 0;
399 b = K85 - third;
400
401 }
402 }
403 }
404
405 // This is one of the good places to scale the green down,
406 // although the client can scale green down as well.
407 if( G2 ) g = g >> 1;
408 if( Gscale ) g = scale8_video_LEAVING_R1_DIRTY( g, Gscale);
409
410 // Scale down colors if we're desaturated at all
411 // and add the brightness_floor to r, g, and b.
412 if( sat != 255 ) {
413 if( sat == 0) {
414 r = 255; b = 255; g = 255;
415 } else {
416 uint8_t desat = 255 - sat;
417 desat = scale8_video( desat, desat);
418
419 uint8_t satscale = 255 - desat;
420 //satscale = sat; // uncomment to revert to pre-2021 saturation behavior
421
422 //nscale8x3_video( r, g, b, sat);
423#if (FASTLED_SCALE8_FIXED==1)
424 r = scale8_LEAVING_R1_DIRTY( r, satscale);
425 asm volatile(""); // Fixes jumping red pixel: https://github.com/FastLED/FastLED/pull/943
426 g = scale8_LEAVING_R1_DIRTY( g, satscale);
427 asm volatile("");
428 b = scale8_LEAVING_R1_DIRTY( b, satscale);
429 asm volatile("");
430 cleanup_R1();
431#else
432 if( r ) r = scale8( r, satscale) + 1;
433 if( g ) g = scale8( g, satscale) + 1;
434 if( b ) b = scale8( b, satscale) + 1;
435#endif
436 uint8_t brightness_floor = desat;
437 r += brightness_floor;
438 g += brightness_floor;
439 b += brightness_floor;
440 }
441 }
442
443 // Now scale everything down if we're at value < 255.
444 if( val != 255 ) {
445
446 val = scale8_video_LEAVING_R1_DIRTY( val, val);
447 if( val == 0 ) {
448 r=0; g=0; b=0;
449 } else {
450 // nscale8x3_video( r, g, b, val);
451#if (FASTLED_SCALE8_FIXED==1)
452 r = scale8_LEAVING_R1_DIRTY( r, val);
453 asm volatile(""); // Fixes jumping red pixel: https://github.com/FastLED/FastLED/pull/943
454 g = scale8_LEAVING_R1_DIRTY( g, val);
455 asm volatile("");
456 b = scale8_LEAVING_R1_DIRTY( b, val);
457 asm volatile("");
458 cleanup_R1();
459#else
460 if( r ) r = scale8( r, val) + 1;
461 if( g ) g = scale8( g, val) + 1;
462 if( b ) b = scale8( b, val) + 1;
463#endif
464 }
465 }
466
467 // Here we have the old AVR "missing std X+n" problem again
468 // It turns out that fixing it winds up costing more than
469 // not fixing it.
470 // To paraphrase Dr Bronner, profile! profile! profile!
471 //asm volatile( "" : : : "r26", "r27" );
472 //asm volatile (" movw r30, r26 \n" : : : "r30", "r31");
473 rgb.r = r;
474 rgb.g = g;
475 rgb.b = b;
476}
LIB8STATIC_ALWAYS_INLINE void cleanup_R1()
Clean up the r1 register after a series of *LEAVING_R1_DIRTY calls.
Definition scale8.h:333
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_LEAVING_R1_DIRTY(uint8_t i, fract8 scale)
This version of scale8() does not clean up the R1 register on AVR.
Definition scale8.h:170
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video_LEAVING_R1_DIRTY(uint8_t i, fract8 scale)
This version of scale8_video() does not clean up the R1 register on AVR.
Definition scale8.h:262
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video(uint8_t i, fract8 scale)
The "video" version of scale8() guarantees that the output will be only be zero if one or both of the...
Definition scale8.h:117
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:34
#define FORCE_REFERENCE(var)
Force a variable reference to avoid compiler over-optimization.
Definition hsv2rgb.cpp:241

References cleanup_R1(), FORCE_REFERENCE, scale8(), scale8_LEAVING_R1_DIRTY(), scale8_video(), and scale8_video_LEAVING_R1_DIRTY().

Referenced by hsv2rgb_rainbow().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: