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:
authorDaniel Garcia <danielgarcia@gmail.com>2015-01-15 20:14:32 +0300
committerDaniel Garcia <danielgarcia@gmail.com>2015-01-15 20:14:32 +0300
commitea921d7762b0ed4a13c0939d62c7b52c289b6bf6 (patch)
treecb7233f3e99a9711d1d8b6546a95b9a9195858a5
parent83a6d769a52a1460d0d992f2ec6b62b7d8549bbc (diff)
parent1903e2f6a0a1e45dd428b291069e68ad40e73c09 (diff)
Merge branch 'FastLED3.1' of https://github.com/FastLED/FastLED into FastLED3.1
-rw-r--r--lib8tion.h6
-rw-r--r--platforms/avr/clockless_trinket.h59
2 files changed, 54 insertions, 11 deletions
diff --git a/lib8tion.h b/lib8tion.h
index 638cf18a..e774d0cc 100644
--- a/lib8tion.h
+++ b/lib8tion.h
@@ -897,12 +897,12 @@ LIB8STATIC uint16_t scale16by8( uint16_t i, fract8 scale )
#elif SCALE16BY8_AVRASM == 1
LIB8STATIC uint16_t scale16by8( uint16_t i, fract8 scale )
{
- uint16_t result;
+ uint16_t result = 0;
asm volatile(
// result.A = HighByte(i.A x j )
" mul %A[i], %[scale] \n\t"
" mov %A[result], r1 \n\t"
- " clr %B[result] \n\t"
+ //" clr %B[result] \n\t"
// result.A-B += i.B x j
" mul %B[i], %[scale] \n\t"
@@ -912,7 +912,7 @@ LIB8STATIC uint16_t scale16by8( uint16_t i, fract8 scale )
// cleanup r1
" clr __zero_reg__ \n\t"
- : [result] "=r" (result)
+ : [result] "+r" (result)
: [i] "r" (i), [scale] "r" (scale)
: "r0", "r1"
);
diff --git a/platforms/avr/clockless_trinket.h b/platforms/avr/clockless_trinket.h
index f2dc14c9..5a9a96c6 100644
--- a/platforms/avr/clockless_trinket.h
+++ b/platforms/avr/clockless_trinket.h
@@ -63,6 +63,10 @@ template<> __attribute__((always_inline)) inline void _dc<10>(register uint8_t &
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if (!defined(NO_CORRECTION) || (NO_CORRECTION == 0)) && (FASTLED_ALLOW_INTERRUPTS == 0)
+static uint8_t gTimeErrorAccum256ths;
+#endif
+
template <uint8_t DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 10>
class ClocklessController : public CLEDController {
typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
@@ -105,14 +109,53 @@ protected:
showRGBInternal(pixels);
// Adjust the timer
- #if (!defined(NO_CORRECTION) || (NO_CORRECTION == 0)) && (FASTLED_ALLOW_INTERRUPTS == 0)
- uint32_t microsTaken = (uint32_t)nLeds * (uint32_t)CLKS_TO_MICROS(24 * (T1 + T2 + T3));
- if(microsTaken > 1024) {
- MS_COUNTER += (microsTaken >> 10);
- } else {
- MS_COUNTER++;
- }
- #endif
+#if (!defined(NO_CORRECTION) || (NO_CORRECTION == 0)) && (FASTLED_ALLOW_INTERRUPTS == 0)
+ uint32_t microsTaken = (uint32_t)nLeds * (uint32_t)CLKS_TO_MICROS(24 * (T1 + T2 + T3));
+
+ // adust for approximate observed actal runtime (as of January 2015)
+ // roughly 9.6 cycles per pixel, which is 0.6us/pixel at 16MHz
+ // microsTaken += nLeds * 0.6 * CLKS_TO_MICROS(16);
+ microsTaken += scale16by8(nLeds,(0.6 * 256) + 1) * CLKS_TO_MICROS(16);
+
+ // if less than 1000us, there is NO timer impact,
+ // this is because the ONE interrupt that might come in while interrupts
+ // are disabled is queued up, and it will be serviced as soon as
+ // interrupts are re-enabled.
+ // This actually should technically also account for the runtime of the
+ // interrupt handler itself, but we're just not going to worry about that.
+ if( microsTaken > 1000) {
+
+ // Since up to one timer tick will be queued, we don't need
+ // to adjust the MS_COUNTER for that one.
+ microsTaken -= 1000;
+
+ // Now convert microseconds to 256ths of a second, approximately like this:
+ // 250ths = (us/4)
+ // 256ths = 250ths * (263/256);
+ uint16_t x256ths = microsTaken >> 2;
+ x256ths += scale16by8(x256ths,7);
+
+ x256ths += gTimeErrorAccum256ths;
+ MS_COUNTER += (x256ths >> 8);
+ gTimeErrorAccum256ths = x256ths & 0xFF;
+ }
+
+#if 0
+ // For pixel counts of 30 and under at 16Mhz, no correction is necessary.
+ // For pixel counts of 15 and under at 8Mhz, no correction is necessary.
+ //
+ // This code, below, is smaller, and quicker clock correction, which drifts much
+ // more significantly, but is a few bytes smaller. Presented here for consideration
+ // as an alternate on the ATtiny, which can't have more than about 150 pixels MAX
+ // anyway, meaning that microsTaken will never be more than about 4,500, which fits in
+ // a 16-bit variable. The difference between /1000 and /1024 only starts showing
+ // up in the range of about 100 pixels, so many ATtiny projects won't even
+ // see a clock difference due to the approximation there.
+ uint16_t microsTaken = (uint32_t)nLeds * (uint32_t)CLKS_TO_MICROS((24) * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken >> 10);
+#endif
+
+#endif
sei();
mWait.mark();