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

◆ hsv2rgb_rainbow() [1/3]

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

Definition at line 267 of file hsv2rgb.cpp.

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

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

+ Here is the call graph for this function: