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:
authorCraig Link <craigl@zillowgroup.com>2021-02-28 11:48:39 +0300
committerCraig Link <craigl@zillowgroup.com>2021-02-28 11:48:39 +0300
commita8a2be7513bd9bc0f9450739826453689a6823c9 (patch)
treecedc6e0dd7268ae5b1dda227e48277517e014d39
parentb779b04f36e95eb74b0f5614af4786a47ce3d02c (diff)
optimize Ardunio Nano Every pin out to single cycle by using VPORTs
from the ATMEga4809 Datasheet - http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega4808-4809-Data-Sheet-DS40002173A.pdf 16.3.2.3 Virtual Ports The Virtual PORT registers map the most frequently used regular PORT registers into the bit-accessible I/O space. Writing to the Virtual PORT registers has the same effect as writing to the regular registers, but allows for memoryspecific instructions, such as bit-manipulation instructions, which are not valid for the extended I/O memory space where the regular PORT registers reside
-rw-r--r--src/platforms/avr/clockless_trinket.h17
-rw-r--r--src/platforms/avr/fastpin_avr.h13
2 files changed, 27 insertions, 3 deletions
diff --git a/src/platforms/avr/clockless_trinket.h b/src/platforms/avr/clockless_trinket.h
index 971a5a71..2cfbef0d 100644
--- a/src/platforms/avr/clockless_trinket.h
+++ b/src/platforms/avr/clockless_trinket.h
@@ -172,7 +172,8 @@ protected:
#define USE_ASM_MACROS
#if defined(__AVR_ATmega4809__)
-#define ASM_VAR_PORT "r" (((PORT_t*)FastPin<DATA_PIN>::port())->OUT)
+// Not used - place holder so existing ASM_VARS macro can remain the same
+#define ASM_VAR_PORT "r" (*FastPin<DATA_PIN>::port())
#else
#define ASM_VAR_PORT "M" (FastPin<DATA_PIN>::port() - 0x20)
#endif
@@ -204,12 +205,24 @@ protected:
[O1] "M" (RGB_BYTE1(RGB_ORDER)), \
[O2] "M" (RGB_BYTE2(RGB_ORDER)) \
: "cc" /* clobber registers */
-// Note: the code in the else in HI1/LO1 will be turned into an sts (2 cycle, 2 word) opcode
+
+#if defined(__AVR_ATmega4809__)
+
+// 1 cycle, write hi to the port
+#define HI1 do {*FastPin<DATA_PIN>::port()=hi;} while(0);
+// 1 cycle, write lo to the port
+#define LO1 do {*FastPin<DATA_PIN>::port()=lo;} while(0);
+
+#else
+
+// Note: the code in the else in HI1/LO1 will be turned into an sts (2 cycle, 2 word)
// 1 cycle, write hi to the port
#define HI1 FASTLED_SLOW_CLOCK_ADJUST if((int)(FastPin<DATA_PIN>::port())-0x20 < 64) { asm __volatile__("out %[PORT], %[hi]" ASM_VARS ); } else { *FastPin<DATA_PIN>::port()=hi; }
// 1 cycle, write lo to the port
#define LO1 if((int)(FastPin<DATA_PIN>::port())-0x20 < 64) { asm __volatile__("out %[PORT], %[lo]" ASM_VARS ); } else { *FastPin<DATA_PIN>::port()=lo; }
+#endif
+
// 2 cycles, sbrs on flipping the line to lo if we're pushing out a 0
#define QLO2(B, N) asm __volatile__("sbrs %[" #B "], " #N ASM_VARS ); LO1;
// load a byte from ram into the given var with the given offset
diff --git a/src/platforms/avr/fastpin_avr.h b/src/platforms/avr/fastpin_avr.h
index 8087e2a2..08dcdc13 100644
--- a/src/platforms/avr/fastpin_avr.h
+++ b/src/platforms/avr/fastpin_avr.h
@@ -37,6 +37,7 @@ public:
inline static port_t hival() __attribute__ ((always_inline)) { return _PORT::r() | _MASK; }
inline static port_t loval() __attribute__ ((always_inline)) { return _PORT::r() & ~_MASK; }
inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PORT::r(); }
+
inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; }
};
@@ -46,15 +47,25 @@ public:
/// a custom type for each GPIO register with a single, static, aggressively inlined function that returns that specific GPIO register. A similar
/// trick is used a bit further below for the ARM GPIO registers (of which there are far more than on AVR!)
typedef volatile uint8_t & reg8_t;
+
#define _R(T) struct __gen_struct_ ## T
#define _RD8(T) struct __gen_struct_ ## T { static inline reg8_t r() { return T; }};
// Register name equivalent (using flat names)
-#if defined(AVR_ATtinyxy7) || defined(AVR_ATtinyxy6) || defined(AVR_ATtinyxy4) || defined(AVR_ATtinyxy2) || defined(__AVR_ATmega4809__)
+#if defined(AVR_ATtinyxy7) || defined(AVR_ATtinyxy6) || defined(AVR_ATtinyxy4) || defined(AVR_ATtinyxy2)
+
// ATtiny series 0/1 and ATmega series 0
#define _FL_IO(L,C) _RD8(PORT ## L ## _DIR); _RD8(PORT ## L ## _OUT); _RD8(PORT ## L ## _IN); _FL_DEFINE_PORT3(L, C, _R(PORT ## L ## _OUT));
#define _FL_DEFPIN(_PIN, BIT, L) template<> class FastPin<_PIN> : public _AVRPIN<_PIN, 1<<BIT, _R(PORT ## L ## _OUT), _R(PORT ## L ## _DIR), _R(PORT ## L ## _IN)> {};
+
+#elif defined(__AVR_ATmega4809__)
+
+
+#define _FL_IO(L,C) _RD8(VPORT ## L ## _DIR); _RD8(VPORT ## L ## _OUT); _RD8(VPORT ## L ## _IN); _FL_DEFINE_PORT3(L, C, _R(VPORT ## L ## _OUT));
+#define _FL_DEFPIN(_PIN, BIT, L) template<> class FastPin<_PIN> : public _AVRPIN<_PIN, 1<<BIT, _R(VPORT ## L ## _OUT), _R(VPORT ## L ## _DIR), _R(VPORT ## L ## _IN)> {};
+
#else
+
// Others
#define _FL_IO(L,C) _RD8(DDR ## L); _RD8(PORT ## L); _RD8(PIN ## L); _FL_DEFINE_PORT3(L, C, _R(PORT ## L));
#define _FL_DEFPIN(_PIN, BIT, L) template<> class FastPin<_PIN> : public _AVRPIN<_PIN, 1<<BIT, _R(PORT ## L), _R(DDR ## L), _R(PIN ## L)> {};