FastLED 3.10.8
Loading...
Searching...
No Matches

◆ hsv2rgb_rainbow() [2/3]

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

Definition at line 269 of file hsv2rgb.cpp.hpp.

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

References FL_NO_EXCEPT, FORCE_REFERENCE, hue, and offset().

+ Here is the call graph for this function: