FastLED 3.9.3
Loading...
Searching...
No Matches
scale8.h
Go to the documentation of this file.
1#pragma once
2
3#include "lib8static.h"
4#include "crgb.h"
5#include "namespace.h"
6
7FASTLED_NAMESPACE_BEGIN
8
12
15
25
34LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale) {
35#if SCALE8_C == 1
36#if (FASTLED_SCALE8_FIXED == 1)
37 return (((uint16_t)i) * (1 + (uint16_t)(scale))) >> 8;
38#else
39 return ((uint16_t)i * (uint16_t)(scale)) >> 8;
40#endif
41#elif SCALE8_AVRASM == 1
42#if defined(LIB8_ATTINY)
43#if (FASTLED_SCALE8_FIXED == 1)
44 uint8_t work = i;
45#else
46 uint8_t work = 0;
47#endif
48 uint8_t cnt = 0x80;
49 asm volatile(
50#if (FASTLED_SCALE8_FIXED == 1)
51 " inc %[scale] \n\t"
52 " breq DONE_%= \n\t"
53 " clr %[work] \n\t"
54#endif
55 "LOOP_%=: \n\t"
56 /*" sbrc %[scale], 0 \n\t"
57 " add %[work], %[i] \n\t"
58 " ror %[work] \n\t"
59 " lsr %[scale] \n\t"
60 " clc \n\t"*/
61 " sbrc %[scale], 0 \n\t"
62 " add %[work], %[i] \n\t"
63 " ror %[work] \n\t"
64 " lsr %[scale] \n\t"
65 " lsr %[cnt] \n\t"
66 "brcc LOOP_%= \n\t"
67 "DONE_%=: \n\t"
68 : [work] "+r"(work), [cnt] "+r"(cnt)
69 : [scale] "r"(scale), [i] "r"(i)
70 :);
71 return work;
72#else
73 asm volatile(
74#if (FASTLED_SCALE8_FIXED == 1)
75 // Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0
76 "mul %0, %1 \n\t"
77 // Add i to r0, possibly setting the carry flag
78 "add r0, %0 \n\t"
79 // load the immediate 0 into i (note, this does _not_ touch any flags)
80 "ldi %0, 0x00 \n\t"
81 // walk and chew gum at the same time
82 "adc %0, r1 \n\t"
83#else
84 /* Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0 */
85 "mul %0, %1 \n\t"
86 /* Move the high 8-bits of the product (r1) back to i */
87 "mov %0, r1 \n\t"
88 /* Restore r1 to "0"; it's expected to always be that */
89#endif
90 "clr __zero_reg__ \n\t"
91
92 : "+d"(i) /* writes to i; r16-r31, restricted by ldi */
93 : "r"(scale) /* uses scale */
94 : "r0", "r1" /* clobbers r0, r1 */
95 );
96 /* Return the result */
97 return i;
98#endif
99#else
100#error "No implementation for scale8 available."
101#endif
102}
103
104constexpr uint8_t scale8_constexpr(uint8_t i, fract8 scale) {
105 return (((uint16_t)i) * (1 + (uint16_t)(scale))) >> 8;
106}
107
117LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video(uint8_t i, fract8 scale) {
118#if SCALE8_C == 1 || defined(LIB8_ATTINY)
119 uint8_t j = (((int)i * (int)scale) >> 8) + ((i && scale) ? 1 : 0);
120 // uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
121 // uint8_t j = (i == 0) ? 0 : (((int)i * (int)(scale) ) >> 8) +
122 // nonzeroscale;
123 return j;
124#elif SCALE8_AVRASM == 1
125 uint8_t j = 0;
126 asm volatile(" tst %[i]\n\t"
127 " breq L_%=\n\t"
128 " mul %[i], %[scale]\n\t"
129 " mov %[j], r1\n\t"
130 " clr __zero_reg__\n\t"
131 " cpse %[scale], r1\n\t"
132 " subi %[j], 0xFF\n\t"
133 "L_%=: \n\t"
134 : [j] "+d"(j) // r16-r31, restricted by subi
135 : [i] "r"(i), [scale] "r"(scale)
136 : "r0", "r1");
137 return j;
138 // uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
139 // asm volatile(
140 // " tst %0 \n"
141 // " breq L_%= \n"
142 // " mul %0, %1 \n"
143 // " mov %0, r1 \n"
144 // " add %0, %2 \n"
145 // " clr __zero_reg__ \n"
146 // "L_%=: \n"
147 // : "+a" (i)
148 // : "a" (scale), "a" (nonzeroscale)
149 // : "r0", "r1");
150 // // Return the result
151 // return i;
152#else
153#error "No implementation for scale8_video available."
154#endif
155}
156
161
170LIB8STATIC_ALWAYS_INLINE uint8_t scale8_LEAVING_R1_DIRTY(uint8_t i,
171 fract8 scale) {
172#if SCALE8_C == 1
173#if (FASTLED_SCALE8_FIXED == 1)
174 return (((uint16_t)i) * ((uint16_t)(scale) + 1)) >> 8;
175#else
176 return ((int)i * (int)(scale)) >> 8;
177#endif
178#elif SCALE8_AVRASM == 1
179 asm volatile(
180#if (FASTLED_SCALE8_FIXED == 1)
181 // Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0
182 "mul %0, %1 \n\t"
183 // Add i to r0, possibly setting the carry flag
184 "add r0, %0 \n\t"
185 // load the immediate 0 into i (note, this does _not_ touch any flags)
186 "ldi %0, 0x00 \n\t"
187 // walk and chew gum at the same time
188 "adc %0, r1 \n\t"
189#else
190 /* Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0 */
191 "mul %0, %1 \n\t"
192 /* Move the high 8-bits of the product (r1) back to i */
193 "mov %0, r1 \n\t"
194#endif
195 /* R1 IS LEFT DIRTY HERE; YOU MUST ZERO IT OUT YOURSELF */
196 /* "clr __zero_reg__ \n\t" */
197 : "+d"(i) /* writes to i; r16-r31, restricted by ldi */
198 : "r"(scale) /* uses scale */
199 : "r0", "r1" /* clobbers r0, r1 */
200 );
201 // Return the result
202 return i;
203#else
204#error "No implementation for scale8_LEAVING_R1_DIRTY available."
205#endif
206}
207
217LIB8STATIC_ALWAYS_INLINE void nscale8_LEAVING_R1_DIRTY(uint8_t &i,
218 fract8 scale) {
219#if SCALE8_C == 1
220#if (FASTLED_SCALE8_FIXED == 1)
221 i = (((uint16_t)i) * ((uint16_t)(scale) + 1)) >> 8;
222#else
223 i = ((int)i * (int)(scale)) >> 8;
224#endif
225#elif SCALE8_AVRASM == 1
226 asm volatile(
227#if (FASTLED_SCALE8_FIXED == 1)
228 // Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0
229 "mul %0, %1 \n\t"
230 // Add i to r0, possibly setting the carry flag
231 "add r0, %0 \n\t"
232 // load the immediate 0 into i (note, this does _not_ touch any flags)
233 "ldi %0, 0x00 \n\t"
234 // walk and chew gum at the same time
235 "adc %0, r1 \n\t"
236#else
237 /* Multiply 8-bit i * 8-bit scale, giving 16-bit r1,r0 */
238 "mul %0, %1 \n\t"
239 /* Move the high 8-bits of the product (r1) back to i */
240 "mov %0, r1 \n\t"
241#endif
242 /* R1 IS LEFT DIRTY HERE; YOU MUST ZERO IT OUT YOURSELF */
243 /* "clr __zero_reg__ \n\t" */
244
245 : "+d"(i) /* writes to i; r16-r31, restricted by ldi */
246 : "r"(scale) /* uses scale */
247 : "r0", "r1" /* clobbers r0, r1 */
248 );
249#else
250#error "No implementation for nscale8_LEAVING_R1_DIRTY available."
251#endif
252}
253
262LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video_LEAVING_R1_DIRTY(uint8_t i,
263 fract8 scale) {
264#if SCALE8_C == 1 || defined(LIB8_ATTINY)
265 uint8_t j = (((int)i * (int)scale) >> 8) + ((i && scale) ? 1 : 0);
266 // uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
267 // uint8_t j = (i == 0) ? 0 : (((int)i * (int)(scale) ) >> 8) +
268 // nonzeroscale;
269 return j;
270#elif SCALE8_AVRASM == 1
271 uint8_t j = 0;
272 asm volatile(" tst %[i]\n\t"
273 " breq L_%=\n\t"
274 " mul %[i], %[scale]\n\t"
275 " mov %[j], r1\n\t"
276 " breq L_%=\n\t"
277 " subi %[j], 0xFF\n\t"
278 "L_%=: \n\t"
279 : [j] "+d"(j) // r16-r31, restricted by subi
280 : [i] "r"(i), [scale] "r"(scale)
281 : "r0", "r1");
282 return j;
283 // uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
284 // asm volatile(
285 // " tst %0 \n"
286 // " breq L_%= \n"
287 // " mul %0, %1 \n"
288 // " mov %0, r1 \n"
289 // " add %0, %2 \n"
290 // " clr __zero_reg__ \n"
291 // "L_%=: \n"
292 // : "+a" (i)
293 // : "a" (scale), "a" (nonzeroscale)
294 // : "r0", "r1");
295 // // Return the result
296 // return i;
297#else
298#error "No implementation for scale8_video_LEAVING_R1_DIRTY available."
299#endif
300}
301
311LIB8STATIC_ALWAYS_INLINE void nscale8_video_LEAVING_R1_DIRTY(uint8_t &i,
312 fract8 scale) {
313#if SCALE8_C == 1 || defined(LIB8_ATTINY)
314 i = (((int)i * (int)scale) >> 8) + ((i && scale) ? 1 : 0);
315#elif SCALE8_AVRASM == 1
316 asm volatile(" tst %[i]\n\t"
317 " breq L_%=\n\t"
318 " mul %[i], %[scale]\n\t"
319 " mov %[i], r1\n\t"
320 " breq L_%=\n\t"
321 " subi %[i], 0xFF\n\t"
322 "L_%=: \n\t"
323 : [i] "+d"(i) // r16-r31, restricted by subi
324 : [scale] "r"(scale)
325 : "r0", "r1");
326#else
327#error "No implementation for scale8_video_LEAVING_R1_DIRTY available."
328#endif
329}
330
333LIB8STATIC_ALWAYS_INLINE void cleanup_R1() {
334#if CLEANUP_R1_AVRASM == 1
335 // Restore r1 to "0"; it's expected to always be that
336 asm volatile("clr __zero_reg__ \n\t" : : : "r1");
337#endif
338}
339
340constexpr CRGB nscale8x3_constexpr(uint8_t r, uint8_t g, uint8_t b, fract8 scale) {
341 return CRGB(((int)r * (int)(scale)) >> 8, ((int)g * (int)(scale)) >> 8,
342 ((int)b * (int)(scale)) >> 8);
343}
344
346
357LIB8STATIC void nscale8x3(uint8_t &r, uint8_t &g, uint8_t &b, fract8 scale) {
358#if SCALE8_C == 1
359#if (FASTLED_SCALE8_FIXED == 1)
360 uint16_t scale_fixed = scale + 1;
361 r = (((uint16_t)r) * scale_fixed) >> 8;
362 g = (((uint16_t)g) * scale_fixed) >> 8;
363 b = (((uint16_t)b) * scale_fixed) >> 8;
364#else
365 r = ((int)r * (int)(scale)) >> 8;
366 g = ((int)g * (int)(scale)) >> 8;
367 b = ((int)b * (int)(scale)) >> 8;
368#endif
369#elif SCALE8_AVRASM == 1
370 r = scale8_LEAVING_R1_DIRTY(r, scale);
371 g = scale8_LEAVING_R1_DIRTY(g, scale);
372 b = scale8_LEAVING_R1_DIRTY(b, scale);
373 cleanup_R1();
374#else
375#error "No implementation for nscale8x3 available."
376#endif
377}
378
391LIB8STATIC void nscale8x3_video(uint8_t &r, uint8_t &g, uint8_t &b,
392 fract8 scale) {
393#if SCALE8_C == 1
394 uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
395 r = (r == 0) ? 0 : (((int)r * (int)(scale)) >> 8) + nonzeroscale;
396 g = (g == 0) ? 0 : (((int)g * (int)(scale)) >> 8) + nonzeroscale;
397 b = (b == 0) ? 0 : (((int)b * (int)(scale)) >> 8) + nonzeroscale;
398#elif SCALE8_AVRASM == 1
402 cleanup_R1();
403#else
404#error "No implementation for nscale8x3 available."
405#endif
406}
407
417LIB8STATIC void nscale8x2(uint8_t &i, uint8_t &j, fract8 scale) {
418#if SCALE8_C == 1
419#if FASTLED_SCALE8_FIXED == 1
420 uint16_t scale_fixed = scale + 1;
421 i = (((uint16_t)i) * scale_fixed) >> 8;
422 j = (((uint16_t)j) * scale_fixed) >> 8;
423#else
424 i = ((uint16_t)i * (uint16_t)(scale)) >> 8;
425 j = ((uint16_t)j * (uint16_t)(scale)) >> 8;
426#endif
427#elif SCALE8_AVRASM == 1
428 i = scale8_LEAVING_R1_DIRTY(i, scale);
429 j = scale8_LEAVING_R1_DIRTY(j, scale);
430 cleanup_R1();
431#else
432#error "No implementation for nscale8x2 available."
433#endif
434}
435
447LIB8STATIC void nscale8x2_video(uint8_t &i, uint8_t &j, fract8 scale) {
448#if SCALE8_C == 1
449 uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
450 i = (i == 0) ? 0 : (((int)i * (int)(scale)) >> 8) + nonzeroscale;
451 j = (j == 0) ? 0 : (((int)j * (int)(scale)) >> 8) + nonzeroscale;
452#elif SCALE8_AVRASM == 1
455 cleanup_R1();
456#else
457#error "No implementation for nscale8x2 available."
458#endif
459}
460
468LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale) {
469 if (scale == 0) {
470 return 0; // Fixes non zero output when scale == 0 and
471 // FASTLED_SCALE8_FIXED==1
472 }
473#if SCALE16BY8_C == 1
474 uint16_t result;
475#if FASTLED_SCALE8_FIXED == 1
476 result = (i * (1 + ((uint16_t)scale))) >> 8;
477#else
478 result = (i * scale) / 256;
479#endif
480 return result;
481#elif SCALE16BY8_AVRASM == 1
482#if FASTLED_SCALE8_FIXED == 1
483 uint16_t result = 0;
484 asm volatile(
485 // result.A = HighByte( (i.A x scale) + i.A )
486 " mul %A[i], %[scale] \n\t"
487 " add r0, %A[i] \n\t"
488 // " adc r1, [zero] \n\t"
489 // " mov %A[result], r1 \n\t"
490 " adc %A[result], r1 \n\t"
491
492 // result.A-B += i.B x scale
493 " mul %B[i], %[scale] \n\t"
494 " add %A[result], r0 \n\t"
495 " adc %B[result], r1 \n\t"
496
497 // cleanup r1
498 " clr __zero_reg__ \n\t"
499
500 // result.A-B += i.B
501 " add %A[result], %B[i] \n\t"
502 " adc %B[result], __zero_reg__ \n\t"
503
504 : [result] "+r"(result)
505 : [i] "r"(i), [scale] "r"(scale)
506 : "r0", "r1");
507 return result;
508#else
509 uint16_t result = 0;
510 asm volatile(
511 // result.A = HighByte(i.A x j )
512 " mul %A[i], %[scale] \n\t"
513 " mov %A[result], r1 \n\t"
514 //" clr %B[result] \n\t"
515
516 // result.A-B += i.B x j
517 " mul %B[i], %[scale] \n\t"
518 " add %A[result], r0 \n\t"
519 " adc %B[result], r1 \n\t"
520
521 // cleanup r1
522 " clr __zero_reg__ \n\t"
523
524 : [result] "+r"(result)
525 : [i] "r"(i), [scale] "r"(scale)
526 : "r0", "r1");
527 return result;
528#endif
529#else
530#error "No implementation for scale16by8 available."
531#endif
532}
533
540LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale) {
541#if SCALE16_C == 1
542 uint16_t result;
543#if FASTLED_SCALE8_FIXED == 1
544 result = ((uint32_t)(i) * (1 + (uint32_t)(scale))) / 65536;
545#else
546 result = ((uint32_t)(i) * (uint32_t)(scale)) / 65536;
547#endif
548 return result;
549#elif SCALE16_AVRASM == 1
550#if FASTLED_SCALE8_FIXED == 1
551 // implemented sort of like
552 // result = ((i * scale) + i ) / 65536
553 //
554 // why not like this, you may ask?
555 // result = (i * (scale+1)) / 65536
556 // the answer is that if scale is 65535, then scale+1
557 // will be zero, which is not what we want.
558 uint32_t result;
559 asm volatile(
560 // result.A-B = i.A x scale.A
561 " mul %A[i], %A[scale] \n\t"
562 // save results...
563 // basic idea:
564 //" mov %A[result], r0 \n\t"
565 //" mov %B[result], r1 \n\t"
566 // which can be written as...
567 " movw %A[result], r0 \n\t"
568 // Because we're going to add i.A-B to
569 // result.A-D, we DO need to keep both
570 // the r0 and r1 portions of the product
571 // UNlike in the 'unfixed scale8' version.
572 // So the movw here is needed.
573 : [result] "=r"(result)
574 : [i] "r"(i), [scale] "r"(scale)
575 : "r0", "r1");
576
577 asm volatile(
578 // result.C-D = i.B x scale.B
579 " mul %B[i], %B[scale] \n\t"
580 //" mov %C[result], r0 \n\t"
581 //" mov %D[result], r1 \n\t"
582 " movw %C[result], r0 \n\t"
583 : [result] "+r"(result)
584 : [i] "r"(i), [scale] "r"(scale)
585 : "r0", "r1");
586
587 const uint8_t zero = 0;
588 asm volatile(
589 // result.B-D += i.B x scale.A
590 " mul %B[i], %A[scale] \n\t"
591
592 " add %B[result], r0 \n\t"
593 " adc %C[result], r1 \n\t"
594 " adc %D[result], %[zero] \n\t"
595
596 // result.B-D += i.A x scale.B
597 " mul %A[i], %B[scale] \n\t"
598
599 " add %B[result], r0 \n\t"
600 " adc %C[result], r1 \n\t"
601 " adc %D[result], %[zero] \n\t"
602
603 // cleanup r1
604 " clr r1 \n\t"
605
606 : [result] "+r"(result)
607 : [i] "r"(i), [scale] "r"(scale), [zero] "r"(zero)
608 : "r0", "r1");
609
610 asm volatile(
611 // result.A-D += i.A-B
612 " add %A[result], %A[i] \n\t"
613 " adc %B[result], %B[i] \n\t"
614 " adc %C[result], %[zero] \n\t"
615 " adc %D[result], %[zero] \n\t"
616 : [result] "+r"(result)
617 : [i] "r"(i), [zero] "r"(zero));
618
619 result = result >> 16;
620 return result;
621#else
622 uint32_t result;
623 asm volatile(
624 // result.A-B = i.A x scale.A
625 " mul %A[i], %A[scale] \n\t"
626 // save results...
627 // basic idea:
628 //" mov %A[result], r0 \n\t"
629 //" mov %B[result], r1 \n\t"
630 // which can be written as...
631 " movw %A[result], r0 \n\t"
632 // We actually don't need to do anything with r0,
633 // as result.A is never used again here, so we
634 // could just move the high byte, but movw is
635 // one clock cycle, just like mov, so might as
636 // well, in case we want to use this code for
637 // a generic 16x16 multiply somewhere.
638
639 : [result] "=r"(result)
640 : [i] "r"(i), [scale] "r"(scale)
641 : "r0", "r1");
642
643 asm volatile(
644 // result.C-D = i.B x scale.B
645 " mul %B[i], %B[scale] \n\t"
646 //" mov %C[result], r0 \n\t"
647 //" mov %D[result], r1 \n\t"
648 " movw %C[result], r0 \n\t"
649 : [result] "+r"(result)
650 : [i] "r"(i), [scale] "r"(scale)
651 : "r0", "r1");
652
653 const uint8_t zero = 0;
654 asm volatile(
655 // result.B-D += i.B x scale.A
656 " mul %B[i], %A[scale] \n\t"
657
658 " add %B[result], r0 \n\t"
659 " adc %C[result], r1 \n\t"
660 " adc %D[result], %[zero] \n\t"
661
662 // result.B-D += i.A x scale.B
663 " mul %A[i], %B[scale] \n\t"
664
665 " add %B[result], r0 \n\t"
666 " adc %C[result], r1 \n\t"
667 " adc %D[result], %[zero] \n\t"
668
669 // cleanup r1
670 " clr r1 \n\t"
671
672 : [result] "+r"(result)
673 : [i] "r"(i), [scale] "r"(scale), [zero] "r"(zero)
674 : "r0", "r1");
675
676 result = result >> 16;
677 return result;
678#endif
679#else
680#error "No implementation for scale16 available."
681#endif
682}
684
700
703LIB8STATIC uint8_t dim8_raw(uint8_t x) { return scale8(x, x); }
704
707LIB8STATIC uint8_t dim8_video(uint8_t x) { return scale8_video(x, x); }
708
710LIB8STATIC uint8_t dim8_lin(uint8_t x) {
711 if (x & 0x80) {
712 x = scale8(x, x);
713 } else {
714 x += 1;
715 x /= 2;
716 }
717 return x;
718}
719
721LIB8STATIC uint8_t brighten8_raw(uint8_t x) {
722 uint8_t ix = 255 - x;
723 return 255 - scale8(ix, ix);
724}
725
727LIB8STATIC uint8_t brighten8_video(uint8_t x) {
728 uint8_t ix = 255 - x;
729 return 255 - scale8_video(ix, ix);
730}
731
733LIB8STATIC uint8_t brighten8_lin(uint8_t x) {
734 uint8_t ix = 255 - x;
735 if (ix & 0x80) {
736 ix = scale8(ix, ix);
737 } else {
738 ix += 1;
739 ix /= 2;
740 }
741 return 255 - ix;
742}
743
746
747FASTLED_NAMESPACE_END
LIB8STATIC uint8_t brighten8_lin(uint8_t x)
Brighten a value (inverse of dim8_lin())
Definition scale8.h:733
LIB8STATIC uint8_t dim8_lin(uint8_t x)
Linear version of the dimming function that halves for values < 128.
Definition scale8.h:710
LIB8STATIC uint8_t dim8_video(uint8_t x)
Adjust a scaling value for dimming for video (value will never go below 1)
Definition scale8.h:707
LIB8STATIC uint8_t brighten8_video(uint8_t x)
Brighten a value (inverse of dim8_video())
Definition scale8.h:727
LIB8STATIC uint8_t dim8_raw(uint8_t x)
Adjust a scaling value for dimming.
Definition scale8.h:703
LIB8STATIC uint8_t brighten8_raw(uint8_t x)
Brighten a value (inverse of dim8_raw())
Definition scale8.h:721
uint8_t fract8
ANSI: unsigned short _Fract.
Definition types.h:30
uint16_t fract16
ANSI: unsigned _Fract.
Definition types.h:40
LIB8STATIC_ALWAYS_INLINE void nscale8_LEAVING_R1_DIRTY(uint8_t &i, fract8 scale)
In place modifying version of scale8() that does not clean up the R1 register on AVR.
Definition scale8.h:217
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 void nscale8_video_LEAVING_R1_DIRTY(uint8_t &i, fract8 scale)
In place modifying version of scale8_video() that does not clean up the R1 register on AVR.
Definition scale8.h:311
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 uint16_t scale16(uint16_t i, fract16 scale)
Scale a 16-bit unsigned value by an 16-bit value, which is treated as the numerator of a fraction who...
Definition scale8.h:540
LIB8STATIC void nscale8x3(uint8_t &r, uint8_t &g, uint8_t &b, fract8 scale)
Scale three one-byte values by a fourth one, which is treated as the numerator of a fraction whose de...
Definition scale8.h:357
LIB8STATIC void nscale8x2_video(uint8_t &i, uint8_t &j, fract8 scale)
Scale two one-byte values by a third one, which is treated as the numerator of a fraction whose demom...
Definition scale8.h:447
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 void nscale8x2(uint8_t &i, uint8_t &j, fract8 scale)
Scale two one-byte values by a third one, which is treated as the numerator of a fraction whose demom...
Definition scale8.h:417
LIB8STATIC void nscale8x3_video(uint8_t &r, uint8_t &g, uint8_t &b, fract8 scale)
Scale three one-byte values by a fourth one, which is treated as the numerator of a fraction whose de...
Definition scale8.h:391
LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale)
Scale a 16-bit unsigned value by an 8-bit value, which is treated as the numerator of a fraction whos...
Definition scale8.h:468
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
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:39