1 #ifndef __INC_LIB8TION_SCALE_H
2 #define __INC_LIB8TION_SCALE_H
23 #if (FASTLED_SCALE8_FIXED == 1)
24 return (((uint16_t)i) * (1+(uint16_t)(scale))) >> 8;
26 return ((uint16_t)i * (uint16_t)(scale) ) >> 8;
28 #elif SCALE8_AVRASM == 1
29 #if defined(LIB8_ATTINY)
30 #if (FASTLED_SCALE8_FIXED == 1)
37 #if (FASTLED_SCALE8_FIXED == 1)
48 " sbrc %[scale], 0 \n\t"
49 " add %[work], %[i] \n\t"
55 : [work]
"+r" (work), [cnt]
"+r" (cnt)
56 : [scale]
"r" (scale), [i]
"r" (i)
62 #if (FASTLED_SCALE8_FIXED==1)
78 "clr __zero_reg__ \n\t"
88 #error "No implementation for scale8 available."
100 #if SCALE8_C == 1 || defined(LIB8_ATTINY)
101 uint8_t j = (((int)i * (
int)scale) >> 8) + ((i&&scale)?1:0);
105 #elif SCALE8_AVRASM == 1
110 " mul %[i], %[scale]\n\t"
112 " clr __zero_reg__\n\t"
113 " cpse %[scale], r1\n\t"
114 " subi %[j], 0xFF\n\t"
117 : [i]
"a" (i), [scale]
"a" (scale)
138 #error "No implementation for scale8_video available."
149 #if (FASTLED_SCALE8_FIXED == 1)
150 return (((uint16_t)i) * ((uint16_t)(scale)+1)) >> 8;
152 return ((
int)i * (
int)(scale) ) >> 8;
154 #elif SCALE8_AVRASM == 1
156 #if (FASTLED_SCALE8_FIXED==1)
181 #error "No implementation for scale8_LEAVING_R1_DIRTY available."
193 #if (FASTLED_SCALE8_FIXED == 1)
194 i = (((uint16_t)i) * ((uint16_t)(scale)+1)) >> 8;
196 i = ((int)i * (
int)(scale) ) >> 8;
198 #elif SCALE8_AVRASM == 1
200 #if (FASTLED_SCALE8_FIXED==1)
222 #error "No implementation for nscale8_LEAVING_R1_DIRTY available."
232 #if SCALE8_C == 1 || defined(LIB8_ATTINY)
233 uint8_t j = (((int)i * (
int)scale) >> 8) + ((i&&scale)?1:0);
237 #elif SCALE8_AVRASM == 1
242 " mul %[i], %[scale]\n\t"
245 " subi %[j], 0xFF\n\t"
248 : [i]
"a" (i), [scale]
"a" (scale)
269 #error "No implementation for scale8_video_LEAVING_R1_DIRTY available."
279 #if SCALE8_C == 1 || defined(LIB8_ATTINY)
280 i = (((int)i * (
int)scale) >> 8) + ((i&&scale)?1:0);
281 #elif SCALE8_AVRASM == 1
285 " mul %[i], %[scale]\n\t"
288 " subi %[i], 0xFF\n\t"
291 : [scale]
"a" (scale)
294 #error "No implementation for scale8_video_LEAVING_R1_DIRTY available."
301 #if CLEANUP_R1_AVRASM == 1
303 asm volatile(
"clr __zero_reg__ \n\t" : : :
"r1" );
317 #if (FASTLED_SCALE8_FIXED == 1)
318 uint16_t scale_fixed = scale + 1;
319 r = (((uint16_t)r) * scale_fixed) >> 8;
320 g = (((uint16_t)g) * scale_fixed) >> 8;
321 b = (((uint16_t)b) * scale_fixed) >> 8;
323 r = ((int)r * (
int)(scale) ) >> 8;
324 g = ((int)g * (
int)(scale) ) >> 8;
325 b = ((int)b * (
int)(scale) ) >> 8;
327 #elif SCALE8_AVRASM == 1
333 #error "No implementation for nscale8x3 available."
347 uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
348 r = (r == 0) ? 0 : (((
int)r * (int)(scale) ) >> 8) + nonzeroscale;
349 g = (g == 0) ? 0 : (((
int)g * (int)(scale) ) >> 8) + nonzeroscale;
350 b = (b == 0) ? 0 : (((
int)b * (int)(scale) ) >> 8) + nonzeroscale;
351 #elif SCALE8_AVRASM == 1
357 #error "No implementation for nscale8x3 available."
370 #if FASTLED_SCALE8_FIXED == 1
371 uint16_t scale_fixed = scale + 1;
372 i = (((uint16_t)i) * scale_fixed ) >> 8;
373 j = (((uint16_t)j) * scale_fixed ) >> 8;
375 i = ((uint16_t)i * (uint16_t)(scale) ) >> 8;
376 j = ((uint16_t)j * (uint16_t)(scale) ) >> 8;
378 #elif SCALE8_AVRASM == 1
383 #error "No implementation for nscale8x2 available."
399 uint8_t nonzeroscale = (scale != 0) ? 1 : 0;
400 i = (i == 0) ? 0 : (((
int)i * (int)(scale) ) >> 8) + nonzeroscale;
401 j = (j == 0) ? 0 : (((
int)j * (int)(scale) ) >> 8) + nonzeroscale;
402 #elif SCALE8_AVRASM == 1
407 #error "No implementation for nscale8x2 available."
418 #if SCALE16BY8_C == 1
420 #if FASTLED_SCALE8_FIXED == 1
421 result = (i * (1+((uint16_t)scale))) >> 8;
423 result = (i * scale) / 256;
426 #elif SCALE16BY8_AVRASM == 1
430 " mul %A[i], %[scale] \n\t"
431 " mov %A[result], r1 \n\t"
435 " mul %B[i], %[scale] \n\t"
436 " add %A[result], r0 \n\t"
437 " adc %B[result], r1 \n\t"
440 " clr __zero_reg__ \n\t"
442 : [result]
"+r" (result)
443 : [i]
"r" (i), [scale]
"r" (scale)
448 #error "No implementation for scale16by8 available."
460 #if FASTLED_SCALE8_FIXED == 1
461 result = ((uint32_t)(i) * (1+(uint32_t)(scale))) / 65536;
463 result = ((uint32_t)(i) * (uint32_t)(scale)) / 65536;
466 #elif SCALE16_AVRASM == 1
470 " mul %A[i], %A[scale] \n\t"
476 " movw %A[result], r0 \n\t"
484 : [result]
"=r" (result)
492 " mul %B[i], %B[scale] \n\t"
495 " movw %C[result], r0 \n\t"
496 : [result]
"+r" (result)
502 const uint8_t zero = 0;
505 " mul %B[i], %A[scale] \n\t"
507 " add %B[result], r0 \n\t"
508 " adc %C[result], r1 \n\t"
509 " adc %D[result], %[zero] \n\t"
512 " mul %A[i], %B[scale] \n\t"
514 " add %B[result], r0 \n\t"
515 " adc %C[result], r1 \n\t"
516 " adc %D[result], %[zero] \n\t"
521 : [result]
"+r" (result)
528 result = result >> 16;
531 #error "No implementation for scale16 available."
576 uint8_t ix = 255 - x;
577 return 255 -
scale8( ix, ix);
583 uint8_t ix = 255 - x;
590 uint8_t ix = 255 - x;
LIB8STATIC uint8_t dim8_raw(uint8_t x)
Adjust a scaling value for dimming.
LIB8STATIC uint8_t brighten8_lin(uint8_t x)
inverse of the dimming function, brighten a value
LIB8STATIC_ALWAYS_INLINE void nscale8_video_LEAVING_R1_DIRTY(uint8_t &i, fract8 scale)
In place modifying version of scale8_video, also this version of nscale8_video does not clean up the ...
LIB8STATIC_ALWAYS_INLINE void cleanup_R1()
Clean up the r1 register after a series of *LEAVING_R1_DIRTY calls.
uint16_t fract16
ANSI: unsigned _Fract.
LIB8STATIC uint8_t dim8_lin(uint8_t x)
Linear version of the dimming function that halves for values < 128.
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...
LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale)
scale a 16-bit unsigned value by a 16-bit value, considered as numerator of a fraction whose denomina...
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 If you are doing several 'scale...
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 i...
LIB8STATIC uint8_t brighten8_raw(uint8_t x)
inverse of the dimming function, brighten a value
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...
LIB8STATIC uint8_t brighten8_video(uint8_t x)
inverse of the dimming function, brighten a value
uint8_t fract8
ANSI unsigned short _Fract.
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...
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...
LIB8STATIC_ALWAYS_INLINE void nscale8_LEAVING_R1_DIRTY(uint8_t &i, fract8 scale)
In place modifying version of scale8, also this version of nscale8 does not clean up the R1 register ...
LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale)
scale a 16-bit unsigned value by an 8-bit value, considered as numerator of a fraction whose denomina...
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 ...
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 If you are doing several 'scale8's in...
LIB8STATIC uint8_t dim8_video(uint8_t x)
Adjust a scaling value for dimming for video (value will never go below 1)