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:
authordanielgarcia@gmail.com <danielgarcia@gmail.com@4ad4ec5c-605d-bd5c-5796-512c9b60011b>2013-06-19 10:35:20 +0400
committerdanielgarcia@gmail.com <danielgarcia@gmail.com@4ad4ec5c-605d-bd5c-5796-512c9b60011b>2013-06-19 10:35:20 +0400
commitae8c92019f7fda09df0522ee35dad8be7e58d181 (patch)
treedc2602844e17c56440761f10211a44d4355cae0d
parent1bd88e84936470887f60c1927a2bbc32e6c76eed (diff)
Preliminary support for due - only tested with clockless chips at the moment. If the SPI chipsets work, they will be using bit bang'd output.
-rw-r--r--FastSPI_LED2.cpp3
-rw-r--r--clockless.h11
-rw-r--r--clockless2.h265
-rw-r--r--controller.h2
-rw-r--r--delay.h5
-rw-r--r--examples/Fast2Dev/Fast2Dev.ino9
-rw-r--r--fastpin.h96
-rw-r--r--led_sysdefs.h30
8 files changed, 393 insertions, 28 deletions
diff --git a/FastSPI_LED2.cpp b/FastSPI_LED2.cpp
index b8e46e4d..34849fa1 100644
--- a/FastSPI_LED2.cpp
+++ b/FastSPI_LED2.cpp
@@ -1,5 +1,8 @@
#include "FastSPI_LED2.h"
+#if defined(__SAM3X8E__)
+volatile uint32_t fuckit;
+#endif
CFastSPI_LED2 LEDS;
CFastSPI_LED2 & FastSPI_LED = LEDS;
diff --git a/clockless.h b/clockless.h
index b7f8a0fe..2bd449bc 100644
--- a/clockless.h
+++ b/clockless.h
@@ -3,7 +3,7 @@
#include "controller.h"
#include "lib8tion.h"
-#include <avr/interrupt.h> // for cli/se definitions
+#include "led_sysdefs.h"
// Macro to convert from nano-seconds to clocks and clocks to nano-seconds
// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
@@ -21,6 +21,9 @@
#if defined(__MK20DX128__)
extern volatile uint32_t systick_millis_count;
# define MS_COUNTER systick_millis_count
+#elif defined(__SAM3X8E__)
+ extern volatile uint32_t fuckit;
+# define MS_COUNTER fuckit
#else
# if defined(CORE_TEENSY)
extern volatile unsigned long timer0_millis_count;
@@ -58,9 +61,7 @@ public:
mPort = FastPin<DATA_PIN>::port();
}
-#if defined(__MK20DX128__)
- // We don't use the bitSetFast methods for ARM.
-#else
+#if defined(FASTLED_AVR)
template <int N>inline static void bitSetFast(register data_ptr_t port, register data_t hi, register data_t lo, register uint8_t b) {
// First cycle
SET_HI; // 1/2 clock cycle if using out
@@ -152,7 +153,7 @@ public:
register data_t lo = *port & ~mask;
*port = lo;
-#if defined(__MK20DX128__)
+#if defined(FASTLED_ARM)
register uint32_t b;
if(ADVANCE) {
b = data[SKIP + RGB_BYTE0(RGB_ORDER)];
diff --git a/clockless2.h b/clockless2.h
new file mode 100644
index 00000000..e6823447
--- /dev/null
+++ b/clockless2.h
@@ -0,0 +1,265 @@
+#ifndef __INC_CLOCKLESS2_H
+#define __INC_CLOCKLESS2_H
+
+#include "controller.h"
+#include "lib8tion.h"
+#include "led_sysdefs.h"
+
+// Macro to convert from nano-seconds to clocks and clocks to nano-seconds
+// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
+#if F_CPU < 96000000
+#define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000
+#define CLKS_TO_MICROS(_CLKS) _CLKS / (F_CPU / 1000000L)
+#else
+#define NS(_NS) ( (_NS * (F_CPU / 2000000L))) / 1000
+#define CLKS_TO_MICROS(_CLKS) _CLKS / (F_CPU / 2000000L)
+#endif
+
+// Macro for making sure there's enough time available
+#define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6)
+
+#if defined(__MK20DX128__)
+ extern volatile uint32_t systick_millis_count;
+# define MS_COUNTER systick_millis_count
+#else
+# if defined(CORE_TEENSY)
+ extern volatile unsigned long timer0_millis_count;
+# define MS_COUNTER timer0_millis_count
+# else
+ extern volatile unsigned long timer0_millis;
+# define MS_COUNTER timer0_millis
+# endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Base template for clockless controllers. These controllers have 3 control points in their cycle for each bit. The first point
+// is where the line is raised hi. The second pointsnt is where the line is dropped low for a zero. The third point is where the
+// line is dropped low for a one. T1, T2, and T3 correspond to the timings for those three in clock cycles.
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Convinience macros to wrap around the toggling of hi vs. lo
+#define SET2_LO FLIP ? FastPin<DATA_PIN>::hi() : FastPin<DATA_PIN>::lo()
+#define SET2_HI FLIP ? FastPin<DATA_PIN>::lo() : FastPin<DATA_PIN>::hi()
+
+#define SET2_LO2 FLIP ? FastPin<DATA_PIN2>::hi() : FastPin<DATA_PIN2>::lo()
+#define SET2_HI2 FLIP ? FastPin<DATA_PIN2>::lo() : FastPin<DATA_PIN2>::hi()
+
+
+template <uint8_t DATA_PIN, uint8_t DATA_PIN2, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, bool FLIP = false, int WAIT_TIME = 50>
+class ClocklessController2 : public CLEDController {
+ typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
+ typedef typename FastPin<DATA_PIN>::port_t data_t;
+
+ CMinWait<WAIT_TIME> mWait;
+public:
+ virtual void init() {
+ FastPin<DATA_PIN>::setOutput();
+ FastPin<DATA_PIN2>::setOutput();
+ }
+
+
+ virtual void clearLeds(int nLeds) {
+ showColor(CRGB(0, 0, 0), nLeds, 0);
+ }
+
+ // set all the leds on the controller to a given color
+ virtual void showColor(const struct CRGB & data, int nLeds, uint8_t scale = 255) {
+ mWait.wait();
+ cli();
+
+ showRGBInternal<0, false>(nLeds, scale, (const byte*)&data, (const byte*)&data);
+
+ // Adjust the timer
+ long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken / 1000);
+ sei();
+ mWait.mark();
+ }
+
+ virtual void show(const struct CRGB *rgbdata, int nLeds, uint8_t scale = 255) {
+ mWait.wait();
+ cli();
+
+ showRGBInternal<0, true>(nLeds, scale, (const byte*)rgbdata, (const byte*)rgbdata);
+
+ // Adjust the timer
+ long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken / 1000);
+ sei();
+ mWait.mark();
+ }
+
+ virtual void show(const struct CRGB *rgbdata, const struct CRGB *rgbdata2, int nLeds, uint8_t scale = 255) {
+ mWait.wait();
+ cli();
+
+ showRGBInternal<0, true>(nLeds, scale, (const byte*)rgbdata, (const byte*)rgbdata2 );
+
+ // Adjust the timer
+ long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken / 1000);
+ sei();
+ mWait.mark();
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void show(const struct CARGB *rgbdata, int nLeds, uint8_t scale = 255) {
+ mWait.wait();
+ cli();
+
+ showRGBInternal<1, true>(nLeds, scale, (const byte*)rgbdata);
+
+ // Adjust the timer
+ long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken / 1000);
+ sei();
+ mWait.mark();
+ }
+#endif
+
+ // This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then
+ // gcc will use register Y for the this pointer.
+ template<int SKIP, bool ADVANCE> static void showRGBInternal(register int nLeds, register uint8_t scale, register const byte *rgbdata, register const byte *rgbdata2) {
+ register byte *data = (byte*)rgbdata;
+ register byte *data2 = (byte*)rgbdata2;
+
+ nLeds *= (3 + SKIP);
+ register uint8_t *end = data + nLeds;
+
+#if defined(__MK20DX128__)
+ register uint32_t b;
+ register uint32_t c;
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE0(RGB_ORDER)];
+ c = data2[SKIP + RGB_BYTE0(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
+ c = rgbdata2[SKIP + RGB_BYTE0(RGB_ORDER)];
+ }
+ b = scale8(b, scale);
+ c = scale8(c, scale);
+
+ while(data < end) {
+ // TODO: hand rig asm version of this method. The timings are based on adjusting/studying GCC compiler ouptut. This
+ // will bite me in the ass at some point, I know it.
+ for(register uint32_t i = 7; i > 0; i--) {
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>(); // 6 cycles - 1/1 store, 1/1 test, 1/1 if, 1/1 port lookup
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(c & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ b <<= 1; c <<=1;
+ delaycycles<T2 - 8>(); // 3 cycles, 1/1 store, 1/1 store/skip, 1/1 shift , 1/1 port lookup
+ SET2_LO; SET2_LO2;
+ delaycycles<T3 - 6>(); // 4 cycles, 1/1 store, 1 sub, 1 branch backwards, 1/1 port lookup
+ }
+ // extra delay because branch is faster falling through
+ delaycycles<1>();
+
+ // 8th bit, interleave loading rest of data
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>();
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(c & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ delaycycles<T2 - 6>(); // 4 cycles, 2/2 store, 1/1 store/skip, 1/1 port lookup
+ SET2_LO; SET2_LO2;
+
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE1(RGB_ORDER)];
+ c = data2[SKIP + RGB_BYTE1(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE1(RGB_ORDER)];
+ c = rgbdata2[SKIP + RGB_BYTE1(RGB_ORDER)];
+ }
+ b = scale8(b, scale);
+ c = scale8(c, scale);
+
+ delaycycles<T3 - 12>(); // 1/1 store, 2/2 load, 1/1 mul, 1/1 shift, , 1/1 port lookup
+
+ for(register uint32_t i = 7; i > 0; i--) {
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>(); // 3 cycles - 1 store, 1 test, 1 if
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(c & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ b <<= 1; c <<= 1;
+ delaycycles<T2 - 8>(); // 6 cycles, 1/1 store, 1/1 store/skip, 1/1 shift , 1/1 port lookup
+ SET2_LO; SET2_LO2;
+ delaycycles<T3 - 6>(); // 4 cycles, 1/1 store, 1 sub, 1 branch backwards, 1/1 port lookup
+ }
+ // extra delay because branch is faster falling through
+ delaycycles<1>();
+
+ // 8th bit, interleave loading rest of data
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>();
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(b & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ delaycycles<T2 - 6>(); // 4 cycles, 2 store, store/skip, 1/1 port lookup
+ SET2_LO; SET2_LO2;
+
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE2(RGB_ORDER)];
+ c = data2[SKIP + RGB_BYTE2(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE2(RGB_ORDER)];
+ c = rgbdata2[SKIP + RGB_BYTE2(RGB_ORDER)];
+ }
+ b = scale8(b, scale);
+ c = scale8(c, scale);
+
+ data += 3 + SKIP; data2 += 3 + SKIP;
+ if((RGB_ORDER & 0070) == 0) {
+ delaycycles<T3 - 14>(); // 1/1 store, 2/2 load, 1/1 mul, 1/1 shift, 1/1 adds if BRG or GRB, 1/1 port lookup
+ } else {
+ delaycycles<T3 - 12>(); // 1/1 store, 2/2 load, 1/1 mul, 1/1 shift, , 1/1 port lookup
+ }
+
+ for(register uint32_t i = 7; i > 0; i--) {
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>(); // 3 cycles - 1 store, 1 test, 1 if
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(c & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ b <<= 1; c <<= 1;
+ delaycycles<T2 - 8>(); // 3 cycles, 1 store, 1 store/skip, 1 shift , 1/1 port lookup
+ SET2_LO; SET2_LO2;
+ delaycycles<T3 - 6>(); // 3 cycles, 1/1 store, 1 sub, 1 branch backwards, 1/1 port lookup
+ }
+ // extra delay because branch is faster falling through
+ delaycycles<1>();
+
+ // 8th bit, interleave loading rest of data
+ SET2_HI; delaycycles<3>(); SET2_HI2;
+ delaycycles<T1 - 6>();
+ if(b & 0x80) { SET2_HI; } else { SET2_LO; }
+ if(c & 0x80) { SET2_HI2; } else { SET2_LO2; }
+ delaycycles<T2 - 6>(); // 4 cycles, 2/2 store, store/skip, 1/1 port lookup
+ SET2_LO; SET2_LO2;
+
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE0(RGB_ORDER)];
+ c = data2[SKIP + RGB_BYTE0(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
+ c = rgbdata2[SKIP + RGB_BYTE0(RGB_ORDER)];
+ }
+ b = scale8(b, scale);
+ c = scale8(c, scale);
+ delaycycles<T3 - 15>(); // 1/1 store, 2/2 load (with increment), 1/1 mul, 1/1 shift, 1 cmp, 1 branch backwards, 1 movim, 1/1 port lookup
+ };
+#endif
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void showARGB(struct CARGB *data, int nLeds) {
+ // TODO: IMPLEMENTME
+ }
+#endif
+};
+
+#undef SET2_HI
+#undef SET2_HI2
+#undef SET2_LO
+#undef SET2_LO2
+
+#endif \ No newline at end of file
diff --git a/controller.h b/controller.h
index 2c703f00..dd07130a 100644
--- a/controller.h
+++ b/controller.h
@@ -1,7 +1,7 @@
#ifndef __INC_CONTROLLER_H
#define __INC_CONTROLLER_H
-#include <avr/io.h>
+#include "led_sysdefs.h"
#include "pixeltypes.h"
diff --git a/delay.h b/delay.h
index 440ca97a..937e9b2a 100644
--- a/delay.h
+++ b/delay.h
@@ -17,6 +17,9 @@
template<int CYCLES> inline void delaycycles();
// TODO: ARM version of _delaycycles_
+
+// usable definition
+#if defined(FASTLED_AVR)
// worker template - this will nop for LOOP * 3 + PAD cycles total
template<int LOOP, int PAD> inline void _delaycycles_AVR() {
delaycycles<PAD>();
@@ -33,8 +36,6 @@ template<int LOOP, int PAD> inline void _delaycycles_AVR() {
);
}
-// usable definition
-#if !defined(__MK20DX128__)
template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() {
_delaycycles_AVR<CYCLES / 3, CYCLES % 3>();
}
diff --git a/examples/Fast2Dev/Fast2Dev.ino b/examples/Fast2Dev/Fast2Dev.ino
index 52ee867d..e8dd6742 100644
--- a/examples/Fast2Dev/Fast2Dev.ino
+++ b/examples/Fast2Dev/Fast2Dev.ino
@@ -16,7 +16,7 @@
//
//////////////////////////////////////////////////
-#define NUM_LEDS 15
+#define NUM_LEDS 256
CRGB leds[NUM_LEDS];
@@ -28,8 +28,8 @@ void setup() {
// setting brightness to 25% brightness
LEDS.setBrightness(64);
- // LEDS.addLeds<WS2811, 13>(leds, NUM_LEDS);
- LEDS.addLeds<TM1809, 13>(leds, NUM_LEDS);
+ LEDS.addLeds<WS2811, 13, BRG>(leds, NUM_LEDS);
+ // LEDS.addLeds<TM1809, 13, BRG>(leds, NUM_LEDS);
// LEDS.addLeds<UCS1903, 13>(leds, NUM_LEDS);
// LEDS.addLeds<TM1803, 13>(leds, NUM_LEDS);
// LEDS.addLeds<TM1829, 13>(leds, NUM_LEDS);
@@ -75,6 +75,9 @@ void loop() {
delay(10);
}
+ // leave the last pixel lit for a bit
+ delay(2000);
+
// fade up
for(int x = 0; x < 128; x++) {
// The showColor method sets all the leds in the strip to the same color
diff --git a/fastpin.h b/fastpin.h
index e91a272d..488f0fb9 100644
--- a/fastpin.h
+++ b/fastpin.h
@@ -1,10 +1,7 @@
#ifndef __INC_FASTPIN_H
#define __INC_FASTPIN_H
-#include<avr/io.h>
-
-// Arduino.h needed for convinience functions digitalPinToPort/BitMask/portOutputRegister and the pinMode methods.
-#include<Arduino.h>
+#include "led_sysdefs.h"
#define NO_PIN 255
@@ -41,10 +38,10 @@ public:
};
class Pin : public Selectable {
- uint8_t mPinMask;
+ RwReg mPinMask;
uint8_t mPin;
- volatile uint8_t *mPort;
- volatile uint8_t *mInPort;
+ volatile RwReg *mPort;
+ volatile RoReg *mInPort;
void _init() {
mPinMask = digitalPinToBitMask(mPin);
@@ -54,8 +51,8 @@ class Pin : public Selectable {
public:
Pin(int pin) : mPin(pin) { _init(); }
- typedef volatile uint8_t * port_ptr_t;
- typedef uint8_t port_t;
+ typedef volatile RwReg * port_ptr_t;
+ typedef RwReg port_t;
inline void setOutput() { pinMode(mPin, OUTPUT); }
inline void setInput() { pinMode(mPin, INPUT); }
@@ -107,17 +104,17 @@ public:
/// Note that these classes are all static functions. So the proper usage is Pin<13>::hi(); or such. Instantiating objects is not recommended,
/// as passing Pin objects around will likely -not- have the effect you're expecting.
template<uint8_t PIN> class FastPin {
- static uint8_t sPinMask;
- static volatile uint8_t *sPort;
- static volatile uint8_t *sInPort;
+ static RwReg sPinMask;
+ static volatile RwReg *sPort;
+ static volatile RoReg *sInPort;
static void _init() {
sPinMask = digitalPinToBitMask(PIN);
sPort = portOutputRegister(digitalPinToPort(PIN));
sInPort = portInputRegister(digitalPinToPort(PIN));
}
public:
- typedef volatile uint8_t * port_ptr_t;
- typedef uint8_t port_t;
+ typedef volatile RwReg * port_ptr_t;
+ typedef RwReg port_t;
inline static void setOutput() { _init(); pinMode(PIN, OUTPUT); }
inline static void setInput() { _init(); pinMode(PIN, INPUT); }
@@ -141,8 +138,9 @@ public:
static port_t mask() __attribute__ ((always_inline)) { return sPinMask; }
};
-template<uint8_t PIN> uint8_t FastPin<PIN>::sPinMask;
-template<uint8_t PIN> volatile uint8_t *FastPin<PIN>::sPort;
+template<uint8_t PIN> RwReg FastPin<PIN>::sPinMask;
+template<uint8_t PIN> volatile RwReg *FastPin<PIN>::sPort;
+template<uint8_t PIN> volatile RoReg *FastPin<PIN>::sInPort;
/// Class definition for a Pin where we know the port registers at compile time for said pin. This allows us to make
/// a lot of optimizations, as the inlined hi/lo methods will devolve to a single io register write/bitset.
@@ -172,9 +170,40 @@ public:
inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; }
};
+/// Template definition for arduino due style ARM pins, providing direct access to the various GPIO registers. Note that this
+/// uses the full port GPIO registers. In theory, in some way, bit-band register access -should- be faster, however I have found
+/// that something about the way gcc does register allocation results in the bit-band code being slower. It will need more fine tuning.
+/// The registers are data register, set output register, clear output register, set data direction register
+template<uint8_t PIN, uint32_t _MASK, typename _PDOR, typename _PSOR, typename _PCOR, typename _PDDR> class _DUEPIN {
+public:
+ typedef volatile uint32_t * port_ptr_t;
+ typedef uint32_t port_t;
+
+ inline static void setOutput() { pinMode(PIN, OUTPUT); } // TODO: perform MUX config { _PDDR::r() |= _MASK; }
+ inline static void setInput() { pinMode(PIN, INPUT); } // TODO: preform MUX config { _PDDR::r() &= ~_MASK; }
+
+ inline static void hi() __attribute__ ((always_inline)) { _PSOR::r() = _MASK; }
+ inline static void lo() __attribute__ ((always_inline)) { _PCOR::r() = _MASK; }
+ inline static void set(register port_t val) __attribute__ ((always_inline)) { _PDOR::r() = val; }
+
+ inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
+
+ inline static void toggle() __attribute__ ((always_inline)) { _PDOR::r() ^= _MASK; }
+
+ inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); }
+ inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); }
+ inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; }
+
+ inline static port_t hival() __attribute__ ((always_inline)) { return _PDOR::r() | _MASK; }
+ inline static port_t loval() __attribute__ ((always_inline)) { return _PDOR::r() & ~_MASK; }
+ inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PDOR::r(); }
+ inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; }
+};
+
/// Template definition for teensy 3.0 style ARM pins, providing direct access to the various GPIO registers. Note that this
/// uses the full port GPIO registers. In theory, in some way, bit-band register access -should- be faster, however I have found
/// that something about the way gcc does register allocation results in the bit-band code being slower. It will need more fine tuning.
+/// The registers are data output, set output, clear output, toggle output, input, and direction
template<uint8_t PIN, uint32_t _MASK, typename _PDOR, typename _PSOR, typename _PCOR, typename _PTOR, typename _PDIR, typename _PDDR> class _ARMPIN {
public:
typedef volatile uint32_t * port_ptr_t;
@@ -249,8 +278,12 @@ typedef volatile uint32_t * ptr_reg32_t;
template<int BIT> static __attribute__((always_inline)) inline ptr_reg32_t rx() { return GPIO_BITBAND_PTR(T, BIT); } };
#define _IO32(L) _RD32(GPIO ## L ## _PDOR); _RD32(GPIO ## L ## _PSOR); _RD32(GPIO ## L ## _PCOR); _RD32(GPIO ## L ## _PTOR); _RD32(GPIO ## L ## _PDIR); _RD32(GPIO ## L ## _PDDR);
-#define USE_BITBAND 1
+#define DUE_IO32(L) _RD32(REG_PIO ## L ## _ODSR); _RD32(REG_PIO ## L ## _SODR); _RD32(REG_PIO ## L ## _CODR); _RD32(REG_PIO ## L ## _OER);
+
+#define USE_BITBAND 0
#if USE_BITBAND == 0
+ #define _DEFPIN_DUE(PIN, BIT, L) template<> class FastPin<PIN> : public _DUEPIN<PIN, 1 << BIT, _R(REG_PIO ## L ## _ODSR), _R(REG_PIO ## L ## _SODR), _R(REG_PIO ## L ## _CODR), \
+ _R(GPIO ## L ## _OER)> {};
#define _DEFPIN_ARM(PIN, BIT, L) template<> class FastPin<PIN> : public _ARMPIN<PIN, 1 << BIT, _R(GPIO ## L ## _PDOR), _R(GPIO ## L ## _PSOR), _R(GPIO ## L ## _PCOR), \
_R(GPIO ## L ## _PTOR), _R(GPIO ## L ## _PDIR), _R(GPIO ## L ## _PDDR)> {};
#else
@@ -382,6 +415,35 @@ _DEFPIN_ARM(32, 18, B); _DEFPIN_ARM(33, 4, A);
#define SPI_DATA 11
#define SPI_CLOCK 13
#define ARM_HARDWARE_SPI
+
+#elif defined(__SAM3X8E__)
+
+DUE_IO32(A);
+DUE_IO32(B);
+DUE_IO32(C);
+DUE_IO32(D);
+
+_DEFPIN_DUE(0, 8, A); _DEFPIN_DUE(1, 9, A); _DEFPIN_DUE(2, 25, B); _DEFPIN_DUE(3, 28, C);
+_DEFPIN_DUE(4, 29, A); _DEFPIN_DUE(5, 25, C); _DEFPIN_DUE(6, 24, C); _DEFPIN_DUE(7, 23, C);
+_DEFPIN_DUE(8, 22, C); _DEFPIN_DUE(9, 21, C); _DEFPIN_DUE(10, 28, A); _DEFPIN_DUE(11, 7, D);
+_DEFPIN_DUE(12, 8, D); _DEFPIN_DUE(13, 27, B); _DEFPIN_DUE(14, 4, D); _DEFPIN_DUE(15, 5, D);
+_DEFPIN_DUE(16, 13, A); _DEFPIN_DUE(17, 12, A); _DEFPIN_DUE(18, 11, A); _DEFPIN_DUE(19, 10, A);
+_DEFPIN_DUE(20, 12, B); _DEFPIN_DUE(21, 13, B); _DEFPIN_DUE(22, 26, B); _DEFPIN_DUE(23, 14, A);
+_DEFPIN_DUE(24, 15, A); _DEFPIN_DUE(25, 0, D); _DEFPIN_DUE(26, 1, D); _DEFPIN_DUE(27, 2, D);
+_DEFPIN_DUE(28, 3, D); _DEFPIN_DUE(29, 6, D); _DEFPIN_DUE(30, 9, D); _DEFPIN_DUE(31, 7, A);
+_DEFPIN_DUE(32, 10, D); _DEFPIN_DUE(33, 1, C); _DEFPIN_DUE(34, 2, C); _DEFPIN_DUE(35, 3, C);
+_DEFPIN_DUE(36, 4, C); _DEFPIN_DUE(37, 5, C); _DEFPIN_DUE(38, 6, C); _DEFPIN_DUE(39, 7, C);
+_DEFPIN_DUE(40, 8, C); _DEFPIN_DUE(41, 9, C); _DEFPIN_DUE(42, 19, A); _DEFPIN_DUE(43, 20, A);
+_DEFPIN_DUE(44, 19, C); _DEFPIN_DUE(45, 18, C); _DEFPIN_DUE(46, 17, C); _DEFPIN_DUE(47, 16, C);
+_DEFPIN_DUE(48, 15, C); _DEFPIN_DUE(49, 14, C); _DEFPIN_DUE(50, 13, C); _DEFPIN_DUE(51, 12, C);
+_DEFPIN_DUE(52, 21, B); _DEFPIN_DUE(53, 14, B); _DEFPIN_DUE(54, 16, A); _DEFPIN_DUE(55, 24, A);
+_DEFPIN_DUE(56, 23, A); _DEFPIN_DUE(57, 22, A); _DEFPIN_DUE(58, 6, A); _DEFPIN_DUE(59, 4, A);
+_DEFPIN_DUE(60, 3, A); _DEFPIN_DUE(61, 2, A); _DEFPIN_DUE(62, 17, B); _DEFPIN_DUE(63, 18, B);
+_DEFPIN_DUE(64, 19, B); _DEFPIN_DUE(65, 20, B); _DEFPIN_DUE(66, 15, B); _DEFPIN_DUE(67, 16, B);
+_DEFPIN_DUE(68, 1, A); _DEFPIN_DUE(69, 0, A); _DEFPIN_DUE(70, 17, A); _DEFPIN_DUE(71, 18, A);
+_DEFPIN_DUE(72, 30, C); _DEFPIN_DUE(73, 21, A); _DEFPIN_DUE(74, 25, A); _DEFPIN_DUE(75, 26, A);
+_DEFPIN_DUE(76, 27, A); _DEFPIN_DUE(77, 28, A); _DEFPIN_DUE(78, 23, B);
+
#else
#warning "No pin/port mappings found, pin access will be slightly slower. See fastpin.h for info."
diff --git a/led_sysdefs.h b/led_sysdefs.h
new file mode 100644
index 00000000..83fe3122
--- /dev/null
+++ b/led_sysdefs.h
@@ -0,0 +1,30 @@
+#ifndef __INC_LED_SYSDEFS_H
+#define __INC_LED_SYSDEFS_H
+
+#ifndef __SAM3X8E__
+#include <avr/io.h>
+#include <avr/interrupt.h> // for cli/se definitions
+
+// Define the rgister types
+#if defined(ARDUINO) && ARDUINO < 150
+typedef volatile uint8_t RoReg; /**< Read only 8-bit register (volatile const unsigned int) */
+typedef volatile uint8_t RwReg; /**< Read-Write 8-bit register (volatile unsigned int) */
+#endif
+
+#else
+// reuseing/abusing cli/sei defs for due
+#define cli() __disable_irq()
+#define sei() __enable_irq()
+
+#endif
+
+#if defined(__MK20DX128__) || defined(__SAM3X8E__)
+#define FASTLED_ARM
+#else
+#define FASTLED_AVR
+#endif
+
+// Arduino.h needed for convinience functions digitalPinToPort/BitMask/portOutputRegister and the pinMode methods.
+#include<Arduino.h>
+
+#endif \ No newline at end of file