4#include "lib8tion/lib8static.h"
31LIB8STATIC_ALWAYS_INLINE uint8_t
qadd8(uint8_t i, uint8_t j) {
33 unsigned int t = i + j;
37#elif QADD8_AVRASM == 1
52#elif QADD8_ARM_DSP_ASM == 1
53 asm volatile(
"uqadd8 %0, %0, %1" :
"+r"(i) :
"r"(j));
56#error "No implementation for qadd8 available."
64LIB8STATIC_ALWAYS_INLINE int8_t
qadd7(int8_t i, int8_t j) {
72#elif QADD7_AVRASM == 1
86 "adc %0, __zero_reg__\n\t"
91#elif QADD7_ARM_DSP_ASM == 1
92 asm volatile(
"qadd8 %0, %0, %1" :
"+r"(i) :
"r"(j));
95#error "No implementation for qadd7 available."
103LIB8STATIC_ALWAYS_INLINE uint8_t
qsub8(uint8_t i, uint8_t j) {
109#elif QSUB8_AVRASM == 1
126#error "No implementation for qsub8 available."
135LIB8STATIC_ALWAYS_INLINE uint8_t
add8(uint8_t i, uint8_t j) {
139#elif ADD8_AVRASM == 1
141 asm volatile(
"add %0, %1" :
"+r"(i) :
"r"(j));
144#error "No implementation for add8 available."
153LIB8STATIC_ALWAYS_INLINE uint16_t
add8to16(uint8_t i, uint16_t j) {
157#elif ADD8_AVRASM == 1
159 asm volatile(
"add %A[j], %[i] \n\t"
160 "adc %B[j], __zero_reg__ \n\t"
165#error "No implementation for add8to16 available."
174LIB8STATIC_ALWAYS_INLINE uint8_t
sub8(uint8_t i, uint8_t j) {
178#elif SUB8_AVRASM == 1
180 asm volatile(
"sub %0, %1" :
"+r"(i) :
"r"(j));
183#error "No implementation for sub8 available."
193LIB8STATIC_ALWAYS_INLINE uint8_t
avg8(uint8_t i, uint8_t j) {
196#elif AVG8_AVRASM == 1
206#error "No implementation for avg8 available."
216LIB8STATIC_ALWAYS_INLINE uint16_t
avg16(uint16_t i, uint16_t j) {
218 return (uint32_t)((uint32_t)(i) + (uint32_t)(j)) >> 1;
219#elif AVG16_AVRASM == 1
222 "add %A[i], %A[j] \n\t"
224 "adc %B[i], %B[j] \n\t"
235#error "No implementation for avg16 available."
245LIB8STATIC_ALWAYS_INLINE uint8_t
avg8r(uint8_t i, uint8_t j) {
247 return (i + j + 1) >> 1;
248#elif AVG8R_AVRASM == 1
256 "adc %0, __zero_reg__\n\t"
261#error "No implementation for avg8r available."
271LIB8STATIC_ALWAYS_INLINE uint16_t
avg16r(uint16_t i, uint16_t j) {
273 return (uint32_t)((uint32_t)(i) + (uint32_t)(j) + 1) >> 1;
274#elif AVG16R_AVRASM == 1
277 "add %A[i], %A[j] \n\t"
279 "adc %B[i], %B[j] \n\t"
289 "adc %A[i], __zero_reg__\n\t"
290 "adc %B[i], __zero_reg__\n\t"
295#error "No implementation for avg16r available."
306LIB8STATIC_ALWAYS_INLINE int8_t
avg7(int8_t i, int8_t j) {
308 return (i >> 1) + (j >> 1) + (i & 0x1);
309#elif AVG7_AVRASM == 1
310 asm volatile(
"asr %1 \n\t"
317#error "No implementation for avg7 available."
328LIB8STATIC_ALWAYS_INLINE int16_t
avg15(int16_t i, int16_t j) {
330 return (i >> 1) + (j >> 1) + (i & 0x1);
331#elif AVG15_AVRASM == 1
340 "adc %A[i], %A[j] \n\t"
341 "adc %B[i], %B[j] \n\t"
346#error "No implementation for avg15 available."
361LIB8STATIC_ALWAYS_INLINE uint8_t
mod8(uint8_t a, uint8_t m) {
363 asm volatile(
"L_%=: sub %[a],%[m] \n\t"
365 " add %[a],%[m] \n\t"
392LIB8STATIC uint8_t
addmod8(uint8_t a, uint8_t b, uint8_t m) {
394 asm volatile(
" add %[a],%[b] \n\t"
395 "L_%=: sub %[a],%[m] \n\t"
397 " add %[a],%[m] \n\t"
399 : [b]
"r"(b), [m]
"r"(m));
425LIB8STATIC uint8_t
submod8(uint8_t a, uint8_t b, uint8_t m) {
427 asm volatile(
" sub %[a],%[b] \n\t"
428 "L_%=: sub %[a],%[m] \n\t"
430 " add %[a],%[m] \n\t"
432 : [b]
"r"(b), [m]
"r"(m));
446LIB8STATIC_ALWAYS_INLINE uint8_t
mul8(uint8_t i, uint8_t j) {
448 return ((
int)i * (
int)(j)) & 0xFF;
449#elif MUL8_AVRASM == 1
456 "clr __zero_reg__ \n\t"
462#error "No implementation for mul8 available."
470LIB8STATIC_ALWAYS_INLINE uint8_t
qmul8(uint8_t i, uint8_t j) {
472 unsigned p = (unsigned)i * (
unsigned)j;
476#elif QMUL8_AVRASM == 1
484 " breq Lnospill_%= \n\t"
489 " clr __zero_reg__ \n\t"
495#error "No implementation for qmul8 available."
500LIB8STATIC_ALWAYS_INLINE int8_t
abs8(int8_t i) {
505#elif ABS8_AVRASM == 1
517#error "No implementation for abs8 available."
539 mid = (low + hi) >> 1;
540 if ((uint16_t)(mid * mid) > x) {
553LIB8STATIC_ALWAYS_INLINE uint8_t sqrt8(uint8_t x) {
554 return sqrt16(map8_to_16(x));
562#if (FASTLED_BLEND_FIXED == 1)
563LIB8STATIC uint8_t
blend8(uint8_t a, uint8_t b, uint8_t amountOfB) {
591#if (FASTLED_SCALE8_FIXED == 1)
592 partial = (a << 8) | b;
595 partial += (b * amountOfB);
596 partial -= (a * amountOfB);
599 uint8_t amountOfA = 255 - amountOfB;
603 partial = (a * amountOfA);
604 partial += (b * amountOfB);
607 result = partial >> 8;
611#elif BLEND8_AVRASM == 1
613#if (FASTLED_SCALE8_FIXED == 1)
616 partial = (a << 8) | b;
619 asm volatile(
" mul %[a], %[amountOfB] \n\t"
620 " sub %A[partial], r0 \n\t"
621 " sbc %B[partial], r1 \n\t"
622 " mul %[b], %[amountOfB] \n\t"
623 " add %A[partial], r0 \n\t"
624 " adc %B[partial], r1 \n\t"
625 " clr __zero_reg__ \n\t"
626 : [partial]
"+r"(partial)
627 : [amountOfB]
"r"(amountOfB), [a]
"r"(a), [b]
"r"(b)
637 " mul %[b], %[amountOfB] \n\t"
638 " movw %A[partial], r0 \n\t"
641 " com %[amountOfB] \n\t"
644 " mul %[a], %[amountOfB] \n\t"
646 " add %A[partial], r0 \n\t"
647 " adc %B[partial], r1 \n\t"
649 " clr __zero_reg__ \n\t"
651 : [partial]
"=r"(partial), [amountOfB]
"+r"(amountOfB)
652 : [a]
"r"(a), [b]
"r"(b)
657 result = partial >> 8;
662#error "No implementation for blend8 available."
667LIB8STATIC uint8_t
blend8(uint8_t a, uint8_t b, uint8_t amountOfB) {
672 uint8_t amountOfA = 255 - amountOfB;
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
LIB8STATIC_ALWAYS_INLINE int8_t abs8(int8_t i)
Take the absolute value of a signed 8-bit uint8_t.
LIB8STATIC_ALWAYS_INLINE uint8_t qmul8(uint8_t i, uint8_t j)
8x8 bit multiplication with 8-bit result, saturating at 0xFF.
LIB8STATIC_ALWAYS_INLINE uint16_t avg16(uint16_t i, uint16_t j)
Calculate an integer average of two unsigned 16-bit integer values (uint16_t), rounded down.
LIB8STATIC_ALWAYS_INLINE int16_t avg15(int16_t i, int16_t j)
Calculate an integer average of two signed 15-bit integers (int16_t).
LIB8STATIC uint8_t addmod8(uint8_t a, uint8_t b, uint8_t m)
Add two numbers, and calculate the modulo of the sum and a third number, M.
LIB8STATIC_ALWAYS_INLINE uint16_t avg16r(uint16_t i, uint16_t j)
Calculate an integer average of two unsigned 16-bit integer values (uint16_t), rounded up.
LIB8STATIC_ALWAYS_INLINE int8_t qadd7(int8_t i, int8_t j)
Add one byte to another, saturating at 0x7F and -0x80.
LIB8STATIC_ALWAYS_INLINE uint8_t avg8(uint8_t i, uint8_t j)
Calculate an integer average of two unsigned 8-bit integer values (uint8_t), rounded down.
LIB8STATIC uint8_t sqrt16(uint16_t x)
Square root for 16-bit integers.
LIB8STATIC_ALWAYS_INLINE uint8_t add8(uint8_t i, uint8_t j)
Add one byte to another, with 8-bit result.
LIB8STATIC_ALWAYS_INLINE uint8_t avg8r(uint8_t i, uint8_t j)
Calculate an integer average of two unsigned 8-bit integer values (uint8_t), rounded up.
LIB8STATIC uint8_t submod8(uint8_t a, uint8_t b, uint8_t m)
Subtract two numbers, and calculate the modulo of the difference and a third number,...
LIB8STATIC uint8_t blend8(uint8_t a, uint8_t b, uint8_t amountOfB)
Blend a variable proportion (0-255) of one byte to another.
LIB8STATIC_ALWAYS_INLINE uint8_t mod8(uint8_t a, uint8_t m)
Calculate the remainder of one unsigned 8-bit value divided by anoter, aka A % M.
LIB8STATIC_ALWAYS_INLINE uint16_t add8to16(uint8_t i, uint16_t j)
Add one byte to two bytes, with 16-bit result.
LIB8STATIC_ALWAYS_INLINE uint8_t sub8(uint8_t i, uint8_t j)
Subtract one byte from another, 8-bit result.
LIB8STATIC_ALWAYS_INLINE int8_t avg7(int8_t i, int8_t j)
Calculate an integer average of two signed 7-bit integers (int8_t).
LIB8STATIC_ALWAYS_INLINE uint8_t qsub8(uint8_t i, uint8_t j)
Subtract one byte from another, saturating at 0x00.
LIB8STATIC_ALWAYS_INLINE uint8_t mul8(uint8_t i, uint8_t j)
8x8 bit multiplication, with 8-bit result.
LIB8STATIC_ALWAYS_INLINE void cleanup_R1()
Clean up the r1 register after a series of *LEAVING_R1_DIRTY calls.
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.
Fast, efficient 8-bit scaling functions specifically designed for high-performance LED programming.