Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kriegsman <kriegsman@tr.org>2015-12-29 07:38:13 +0300
committerMark Kriegsman <kriegsman@tr.org>2015-12-29 07:38:13 +0300
commit315e13a7ea73edc976c97d135032a383a8d01f85 (patch)
treea2c2e7c86a81e64b0a44947d436ba95329ff4280
parent5b1f831a341e72fcc6bc4d69fd44a06c71848a17 (diff)
Added avg16 & avg15, for fast unsigned and signed averages (respectively). Note that avg15, which is signed, has the same rounding behavior as avg7 (also signed), which is that it rounds up if the first argument is odd, and down if the first argument is even, resulting in a more even distribution of results -- but may result in mild surprise because avg15(a,b) is not always the same as (a+b)/2. If you're using this function though, you probably know enough to read the docs and/or not be TOO surprised.
-rw-r--r--lib8tion.h8
-rw-r--r--lib8tion/math8.h53
2 files changed, 61 insertions, 0 deletions
diff --git a/lib8tion.h b/lib8tion.h
index 93f51cb1..9d66624a 100644
--- a/lib8tion.h
+++ b/lib8tion.h
@@ -213,6 +213,8 @@ Lib8tion is pronounced like 'libation': lie-BAY-shun
#define EASE8_C 1
#define AVG8_C 1
#define AVG7_C 1
+#define AVG16_C 1
+#define AVG15_C 1
#elif defined(__AVR__)
@@ -227,6 +229,8 @@ Lib8tion is pronounced like 'libation': lie-BAY-shun
#define SUB8_C 0
#define AVG8_C 0
#define AVG7_C 0
+#define AVG16_C 0
+#define AVG15_C 0
#define QADD8_AVRASM 1
#define QADD7_AVRASM 1
@@ -236,6 +240,8 @@ Lib8tion is pronounced like 'libation': lie-BAY-shun
#define SUB8_AVRASM 1
#define AVG8_AVRASM 1
#define AVG7_AVRASM 1
+#define AVG16_AVRASM 1
+#define AVG15_AVRASM 1
// Note: these require hardware MUL instruction
// -- sorry, ATtiny!
@@ -287,6 +293,8 @@ Lib8tion is pronounced like 'libation': lie-BAY-shun
#define EASE8_C 1
#define AVG8_C 1
#define AVG7_C 1
+#define AVG16_C 1
+#define AVG15_C 1
#endif
diff --git a/lib8tion/math8.h b/lib8tion/math8.h
index 9e87adc4..f41352a9 100644
--- a/lib8tion/math8.h
+++ b/lib8tion/math8.h
@@ -163,6 +163,31 @@ LIB8STATIC uint8_t avg8( uint8_t i, uint8_t j)
#endif
}
+/// Calculate an integer average of two unsigned
+/// 16-bit integer values (uint16_t).
+/// Fractional results are rounded down, e.g. avg16(20,41) = 30
+LIB8STATIC uint16_t avg16( uint16_t i, uint16_t j)
+{
+#if AVG16_C == 1
+ return (uint32_t)((uint32_t)(i) + (uint32_t)(j)) >> 1;
+#elif AVG16_AVRASM == 1
+ asm volatile(
+ /* First, add jLo (heh) to iLo, 9th bit overflows into C flag */
+ "add %A[i], %A[j] \n\t"
+ /* Now, add C + jHi to iHi, 17th bit overflows into C flag */
+ "adc %B[i], %B[j] \n\t"
+ /* Divide iHi by two, moving C flag into high 16th bit, old 9th bit now in C */
+ "ror %B[i] \n\t"
+ /* Divide iLo by two, moving C flag into high 8th bit */
+ "ror %A[i] \n\t"
+ : [i] "+a" (i)
+ : [j] "a" (j) );
+ return i;
+#else
+#error "No implementation for avg16 available."
+#endif
+}
+
/// Calculate an integer average of two signed 7-bit
/// integers (int8_t)
@@ -185,6 +210,34 @@ LIB8STATIC int8_t avg7( int8_t i, int8_t j)
#endif
}
+/// Calculate an integer average of two signed 15-bit
+/// integers (int16_t)
+/// If the first argument is even, result is rounded down.
+/// If the first argument is odd, result is result up.
+LIB8STATIC int16_t avg15( int16_t i, int16_t j)
+{
+#if AVG15_C == 1
+ return ((int32_t)((int32_t)(i) + (int32_t)(j)) >> 1) + (i & 0x1);
+#elif AVG15_AVRASM == 1
+ asm volatile(
+ /* first divide j by 2, throwing away lowest bit */
+ "asr %B[j] \n\t"
+ "ror %A[j] \n\t"
+ /* now divide i by 2, with lowest bit going into C */
+ "asr %B[i] \n\t"
+ "ror %A[i] \n\t"
+ /* add j + C to i */
+ "adc %A[i], %A[j] \n\t"
+ "adc %B[i], %B[j] \n\t"
+ : [i] "+a" (i)
+ : [j] "a" (j) );
+ return i;
+#else
+#error "No implementation for avg15 available."
+#endif
+}
+
+
/// Calculate the remainder of one unsigned 8-bit
/// value divided by anoter, aka A % M.
/// Implemented by repeated subtraction, which is