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>2014-11-18 10:53:57 +0300
committerDaniel Garcia <danielgarcia@gmail.com>2014-11-18 10:53:57 +0300
commitc7766f85f070f8dfab8727d105c78bb42db77f49 (patch)
tree1dcde4d004e4bb0105e17581d53a1c64b566e524
parent5b8c97da6f5629c5ee2b234744555e1eec4eeb8b (diff)
Re-arranging code layout, pulling off platform specific headers into their own directories.
-rw-r--r--FastLED.h29
-rw-r--r--chipsets.h1
-rw-r--r--clockless.h28
-rw-r--r--colorutils.cpp115
-rw-r--r--fastled_config.h12
-rw-r--r--fastpin.h58
-rw-r--r--fastspi.h44
-rw-r--r--fastspi_types.h37
-rw-r--r--hsv2rgb.cpp85
-rw-r--r--led_sysdefs.h82
-rw-r--r--lib8tion.h18
-rw-r--r--platforms.h15
-rw-r--r--platforms/arm/k20/clockless_arm_k20.h (renamed from clockless_arm_k20.h)0
-rw-r--r--platforms/arm/k20/clockless_block_arm_k20.h (renamed from clockless_block_arm_k20.h)0
-rw-r--r--platforms/arm/k20/fastled_arm_k20.h14
-rw-r--r--platforms/arm/k20/fastpin_arm_k20.h (renamed from fastpin_arm_k20.h)13
-rw-r--r--platforms/arm/k20/fastspi_arm_k20.h (renamed from fastspi_arm_k20.h)0
-rw-r--r--platforms/arm/k20/led_sysdefs_arm_k20.h26
-rw-r--r--platforms/arm/k20/octows2811_controller.h (renamed from octows2811_controller.h)0
-rw-r--r--platforms/arm/k20/smartmatrix_t3.h (renamed from smartmatrix_t3.h)0
-rw-r--r--platforms/arm/sam/clockless_arm_sam.h (renamed from clockless_arm_sam.h)0
-rw-r--r--platforms/arm/sam/clockless_block_arm_sam.h (renamed from clockless_block_arm_sam.h)5
-rw-r--r--platforms/arm/sam/fastled_arm_sam.h11
-rw-r--r--platforms/arm/sam/fastpin_arm_sam.h (renamed from fastpin_arm_sam.h)29
-rw-r--r--platforms/arm/sam/fastspi_arm_sam.h (renamed from fastspi_arm_sam.h)0
-rw-r--r--platforms/arm/sam/led_sysdefs_arm_sam.h30
-rw-r--r--platforms/avr/clockless_trinket.h (renamed from clockless_trinket.h)1
-rw-r--r--platforms/avr/fastled_avr.h9
-rw-r--r--platforms/avr/fastpin_avr.h (renamed from fastpin_avr.h)111
-rw-r--r--platforms/avr/fastspi_avr.h (renamed from fastspi_avr.h)0
-rw-r--r--platforms/avr/led_sysdefs_avr.h21
-rw-r--r--preview_changes.txt2
-rw-r--r--wiring.cpp3
33 files changed, 430 insertions, 369 deletions
diff --git a/FastLED.h b/FastLED.h
index 5c656aeb..951d105f 100644
--- a/FastLED.h
+++ b/FastLED.h
@@ -26,21 +26,29 @@
#include<DMXSerial.h>
#endif
+#include <stdint.h>
+
+#include "fastled_config.h"
+#include "led_sysdefs.h"
+
+#include "bitswap.h"
#include "controller.h"
#include "fastpin.h"
-#include "fastspi.h"
-#include "bitswap.h"
-#include "clockless.h"
+#include "fastspi_types.h"
+#include "./dmx.h"
+
+#include "platforms.h"
+
#include "lib8tion.h"
#include "hsv2rgb.h"
#include "colorutils.h"
#include "colorpalettes.h"
-#include "chipsets.h"
-#include "./dmx.h"
-#include "smartmatrix_t3.h"
+
#include "noise.h"
#include "power_mgt.h"
-#include "octows2811_controller.h"
+
+#include "fastspi.h"
+#include "chipsets.h"
enum ESPIChipsets {
LPD8806,
@@ -325,4 +333,11 @@ void delayMicroseconds(unsigned int us);
extern CFastLED FastLED;
+// Warnings for undefined things
+#ifndef HAS_HARDWARE_PIN_SUPPORT
+#warning "No pin/port mappings found, pin access will be slightly slower. See fastpin.h for info."
+#define NO_HARDWARE_PIN_SUPPORT
+#endif
+
+
#endif
diff --git a/chipsets.h b/chipsets.h
index ef16a53d..95b148ee 100644
--- a/chipsets.h
+++ b/chipsets.h
@@ -2,7 +2,6 @@
#define __INC_CHIPSETS_H
#include "pixeltypes.h"
-#include "clockless.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
diff --git a/clockless.h b/clockless.h
deleted file mode 100644
index 896cf046..00000000
--- a/clockless.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __INC_CLOCKLESS_H
-#define __INC_CLOCKLESS_H
-
-#include "controller.h"
-#include "lib8tion.h"
-#include "led_sysdefs.h"
-#include "delay.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// 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 SET_LO FLIP ? FastPin<DATA_PIN>::fastset(port, hi) : FastPin<DATA_PIN>::fastset(port, lo);
-#define SET_HI FLIP ? FastPin<DATA_PIN>::fastset(port, lo) : FastPin<DATA_PIN>::fastset(port, hi);
-
-// #include "clockless_avr.h"
-#include "clockless_trinket.h"
-#include "clockless_arm_k20.h"
-#include "clockless_arm_sam.h"
-#include "clockless_block_arm_sam.h"
-#include "clockless_block_arm_k20.h"
-
-#endif
diff --git a/colorutils.cpp b/colorutils.cpp
index 995db69e..9bb64b7e 100644
--- a/colorutils.cpp
+++ b/colorutils.cpp
@@ -2,8 +2,7 @@
#include <stdint.h>
-#include "hsv2rgb.h"
-#include "colorutils.h"
+#include "FastLED.h"
@@ -73,22 +72,22 @@ void fill_gradient_RGB( CRGB* leds,
endcolor = startcolor;
endpos = startpos;
}
-
+
saccum87 rdistance87;
saccum87 gdistance87;
saccum87 bdistance87;
-
+
rdistance87 = (endcolor.r - startcolor.r) << 7;
gdistance87 = (endcolor.g - startcolor.g) << 7;
bdistance87 = (endcolor.b - startcolor.b) << 7;
-
+
uint16_t pixeldistance = endpos - startpos;
int16_t divisor = pixeldistance ? pixeldistance : 1;
saccum87 rdelta87 = rdistance87 / divisor;
saccum87 gdelta87 = gdistance87 / divisor;
saccum87 bdelta87 = bdistance87 / divisor;
-
+
rdelta87 *= 2;
gdelta87 *= 2;
bdelta87 *= 2;
@@ -213,23 +212,23 @@ CRGB& nblend( CRGB& existing, const CRGB& overlay, fract8 amountOfOverlay )
if( amountOfOverlay == 0) {
return existing;
}
-
+
if( amountOfOverlay == 255) {
existing = overlay;
return existing;
}
-
+
fract8 amountOfKeep = 256 - amountOfOverlay;
-
+
existing.red = scale8_LEAVING_R1_DIRTY( existing.red, amountOfKeep)
+ scale8_LEAVING_R1_DIRTY( overlay.red, amountOfOverlay);
existing.green = scale8_LEAVING_R1_DIRTY( existing.green, amountOfKeep)
+ scale8_LEAVING_R1_DIRTY( overlay.green, amountOfOverlay);
existing.blue = scale8_LEAVING_R1_DIRTY( existing.blue, amountOfKeep)
+ scale8_LEAVING_R1_DIRTY( overlay.blue, amountOfOverlay);
-
+
cleanup_R1();
-
+
return existing;
}
@@ -266,30 +265,30 @@ CHSV& nblend( CHSV& existing, const CHSV& overlay, fract8 amountOfOverlay, TGrad
if( amountOfOverlay == 0) {
return existing;
}
-
+
if( amountOfOverlay == 255) {
existing = overlay;
return existing;
}
-
+
fract8 amountOfKeep = 256 - amountOfOverlay;
-
+
uint8_t huedelta8 = overlay.hue - existing.hue;
-
+
if( directionCode == SHORTEST_HUES ) {
directionCode = FORWARD_HUES;
if( huedelta8 > 127) {
directionCode = BACKWARD_HUES;
}
}
-
+
if( directionCode == LONGEST_HUES ) {
directionCode = FORWARD_HUES;
if( huedelta8 < 128) {
directionCode = BACKWARD_HUES;
}
}
-
+
if( directionCode == FORWARD_HUES) {
existing.hue = existing.hue + scale8( huedelta8, amountOfOverlay);
}
@@ -298,14 +297,14 @@ CHSV& nblend( CHSV& existing, const CHSV& overlay, fract8 amountOfOverlay, TGrad
huedelta8 = -huedelta8;
existing.hue = existing.hue - scale8( huedelta8, amountOfOverlay);
}
-
+
existing.sat = scale8_LEAVING_R1_DIRTY( existing.sat, amountOfKeep)
+ scale8_LEAVING_R1_DIRTY( overlay.sat, amountOfOverlay);
existing.val = scale8_LEAVING_R1_DIRTY( existing.val, amountOfKeep)
+ scale8_LEAVING_R1_DIRTY( overlay.val, amountOfOverlay);
-
+
cleanup_R1();
-
+
return existing;
}
@@ -351,37 +350,37 @@ CHSV* blend( const CHSV* src1, const CHSV* src2, CHSV* dest, uint16_t count, fra
CRGB HeatColor( uint8_t temperature)
{
CRGB heatcolor;
-
+
// Scale 'heat' down from 0-255 to 0-191,
// which can then be easily divided into three
// equal 'thirds' of 64 units each.
uint8_t t192 = scale8_video( temperature, 192);
-
+
// calculate a value that ramps up from
// zero to 255 in each 'third' of the scale.
uint8_t heatramp = t192 & 0x3F; // 0..63
heatramp <<= 2; // scale up to 0..252
-
+
// now figure out which third of the spectrum we're in:
if( t192 & 0x80) {
// we're in the hottest third
heatcolor.r = 255; // full red
heatcolor.g = 255; // full green
heatcolor.b = heatramp; // ramp up blue
-
+
} else if( t192 & 0x40 ) {
// we're in the middle third
heatcolor.r = 255; // full red
heatcolor.g = heatramp; // ramp up green
heatcolor.b = 0; // no blue
-
+
} else {
// we're in the coolest third
heatcolor.r = heatramp; // ramp up red
heatcolor.g = 0; // no green
heatcolor.b = 0; // no blue
}
-
+
return heatcolor;
}
@@ -391,33 +390,33 @@ CRGB ColorFromPalette( const CRGBPalette16& pal, uint8_t index, uint8_t brightne
{
uint8_t hi4 = index >> 4;
uint8_t lo4 = index & 0x0F;
-
+
// CRGB rgb1 = pal[ hi4];
const CRGB* entry = &(pal[0]) + hi4;
uint8_t red1 = entry->red;
uint8_t green1 = entry->green;
uint8_t blue1 = entry->blue;
-
+
uint8_t blend = lo4 && (blendType != NOBLEND);
-
+
if( blend ) {
-
+
if( hi4 == 15 ) {
entry = &(pal[0]);
} else {
entry++;
}
-
+
uint8_t f2 = lo4 << 4;
uint8_t f1 = 256 - f2;
-
+
// rgb1.nscale8(f1);
red1 = scale8_LEAVING_R1_DIRTY( red1, f1);
green1 = scale8_LEAVING_R1_DIRTY( green1, f1);
blue1 = scale8_LEAVING_R1_DIRTY( blue1, f1);
-
+
// cleanup_R1();
-
+
// CRGB rgb2 = pal[ hi4];
// rgb2.nscale8(f2);
uint8_t red2 = entry->red;
@@ -426,21 +425,21 @@ CRGB ColorFromPalette( const CRGBPalette16& pal, uint8_t index, uint8_t brightne
red2 = scale8_LEAVING_R1_DIRTY( red2, f2);
green2 = scale8_LEAVING_R1_DIRTY( green2, f2);
blue2 = scale8_LEAVING_R1_DIRTY( blue2, f2);
-
+
cleanup_R1();
-
+
// These sums can't overflow, so no qadd8 needed.
red1 += red2;
green1 += green2;
blue1 += blue2;
}
-
+
if( brightness != 255) {
nscale8x3_video( red1, green1, blue1, brightness);
}
-
- return CRGB( red1, green1, blue1);
+
+ return CRGB( red1, green1, blue1);
}
@@ -451,11 +450,11 @@ CRGB ColorFromPalette( const CRGBPalette256& pal, uint8_t index, uint8_t brightn
uint8_t red = entry->red;
uint8_t green = entry->green;
uint8_t blue = entry->blue;
-
+
if( brightness != 255) {
nscale8x3_video( red, green, blue, brightness);
}
-
+
return CRGB( red, green, blue);
}
@@ -464,27 +463,27 @@ CHSV ColorFromPalette( const struct CHSVPalette16& pal, uint8_t index, uint8_t b
{
uint8_t hi4 = index >> 4;
uint8_t lo4 = index & 0x0F;
-
+
// CRGB rgb1 = pal[ hi4];
const CHSV* entry = &(pal[0]) + hi4;
uint8_t hue1 = entry->hue;
uint8_t sat1 = entry->sat;
uint8_t val1 = entry->val;
-
+
uint8_t blend = lo4 && (blendType != NOBLEND);
-
+
if( blend ) {
-
+
if( hi4 == 15 ) {
entry = &(pal[0]);
} else {
entry++;
}
-
+
uint8_t f2 = lo4 << 4;
uint8_t f1 = 256 - f2;
-
+
uint8_t hue2 = entry->hue;
uint8_t sat2 = entry->sat;
uint8_t val2 = entry->val;
@@ -497,26 +496,26 @@ CHSV ColorFromPalette( const struct CHSVPalette16& pal, uint8_t index, uint8_t b
// of the other color, so that you get the expected
// brightness or saturation ramp, with hue staying
// constant:
-
+
// If we are starting from white (sat=0)
// or black (val=0), adopt the target hue.
if( sat1 == 0 || val1 == 0) {
hue1 = hue2;
}
-
+
// If we are ending at white (sat=0)
// or black (val=0), adopt the starting hue.
if( sat2 == 0 || val2 == 0) {
hue2 = hue1;
}
-
-
+
+
sat1 = scale8_LEAVING_R1_DIRTY( sat1, f1);
val1 = scale8_LEAVING_R1_DIRTY( val1, f1);
-
+
sat2 = scale8_LEAVING_R1_DIRTY( sat2, f2);
val2 = scale8_LEAVING_R1_DIRTY( val2, f2);
-
+
// cleanup_R1();
// These sums can't overflow, so no qadd8 needed.
@@ -531,15 +530,15 @@ CHSV ColorFromPalette( const struct CHSVPalette16& pal, uint8_t index, uint8_t b
// go forwards
hue1 += scale8( deltaHue, f2);
}
-
+
cleanup_R1();
}
-
+
if( brightness != 255) {
val1 = scale8_video( val1, brightness);
}
-
- return CHSV( hue1, sat1, val1);
+
+ return CHSV( hue1, sat1, val1);
}
@@ -550,7 +549,7 @@ CHSV ColorFromPalette( const struct CHSVPalette256& pal, uint8_t index, uint8_t
if( brightness != 255) {
hsv.value = scale8_video( hsv.value, brightness);
}
-
+
return hsv;
}
diff --git a/fastled_config.h b/fastled_config.h
new file mode 100644
index 00000000..3e5a8c4e
--- /dev/null
+++ b/fastled_config.h
@@ -0,0 +1,12 @@
+#ifndef __INC_FASTLED_CONFIG_H
+#define __INC_FASTLED_CONFIG_H
+
+// Use this option only for debugging pin access and forcing software pin access. Note that
+// software pin access only works in Arduino based environments. Forces use of digitalWrite
+// methods for pin access vs. direct hardware port access
+// #define FORCE_SOFTWARE_PINS
+
+// Use this option only for debugging bitbang'd spi access or to work around bugs in hardware
+// spi access. Forces use of bit-banged spi, even on pins that has hardware SPI available.
+// #define FORCE_SOFTWARE_SPI
+#endif
diff --git a/fastpin.h b/fastpin.h
index 56a9ea61..fc75d9a4 100644
--- a/fastpin.h
+++ b/fastpin.h
@@ -3,7 +3,7 @@
#include "led_sysdefs.h"
-#define NO_PIN 255
+#define NO_PIN 255
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@@ -18,13 +18,15 @@ public:
virtual bool isSelected() = 0;
};
-class Pin : public Selectable {
+#if defined(ARDUINO)
+
+class Pin : public Selectable {
volatile RwReg *mPort;
volatile RoReg *mInPort;
RwReg mPinMask;
uint8_t mPin;
- void _init() {
+ void _init() {
mPinMask = digitalPinToBitMask(mPin);
mPort = portOutputRegister(digitalPinToPort(mPin));
mInPort = portInputRegister(digitalPinToPort(mPin));
@@ -38,14 +40,14 @@ public:
inline void setOutput() { pinMode(mPin, OUTPUT); }
inline void setInput() { pinMode(mPin, INPUT); }
- inline void hi() __attribute__ ((always_inline)) { *mPort |= mPinMask; }
+ inline void hi() __attribute__ ((always_inline)) { *mPort |= mPinMask; }
inline void lo() __attribute__ ((always_inline)) { *mPort &= ~mPinMask; }
inline void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
inline void toggle() __attribute__ ((always_inline)) { *mInPort = mPinMask; }
- inline void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= mPinMask; }
- inline void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~mPinMask; }
+ inline void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= mPinMask; }
+ inline void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~mPinMask; }
inline void set(register port_t val) __attribute__ ((always_inline)) { *mPort = val; }
inline void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; }
@@ -75,20 +77,20 @@ public:
/// will provide pin level access on pretty much all arduino environments. In addition, it includes some methods to help optimize access in
/// various ways. Namely, the versions of hi, lo, and fastset that take the port register as a passed in register variable (saving a global
/// dereference), since these functions are aggressively inlined, that can help collapse out a lot of extraneous memory loads/dereferences.
-///
+///
/// In addition, if, while writing a bunch of data to a pin, you know no other pins will be getting written to, you can get/cache a value of
/// the pin's port register and use that to do a full set to the register. This results in one being able to simply do a store to the register,
/// vs. the load, and/or, and store that would be done normally.
///
/// There are platform specific instantiations of this class that provide direct i/o register access to pins for much higher speed pin twiddling.
///
-/// Note that these classes are all static functions. So the proper usage is Pin<13>::hi(); or such. Instantiating objects is not recommended,
+/// 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 {
+template<uint8_t PIN> class FastPin {
static RwReg sPinMask;
static volatile RwReg *sPort;
static volatile RoReg *sInPort;
- static void _init() {
+ static void _init() {
sPinMask = digitalPinToBitMask(PIN);
sPort = portOutputRegister(digitalPinToPort(PIN));
sInPort = portInputRegister(digitalPinToPort(PIN));
@@ -100,15 +102,15 @@ public:
inline static void setOutput() { _init(); pinMode(PIN, OUTPUT); }
inline static void setInput() { _init(); pinMode(PIN, INPUT); }
- inline static void hi() __attribute__ ((always_inline)) { *sPort |= sPinMask; }
+ inline static void hi() __attribute__ ((always_inline)) { *sPort |= sPinMask; }
inline static void lo() __attribute__ ((always_inline)) { *sPort &= ~sPinMask; }
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
inline static void toggle() __attribute__ ((always_inline)) { *sInPort = sPinMask; }
- inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= sPinMask; }
- inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~sPinMask; }
+ inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= sPinMask; }
+ inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~sPinMask; }
inline static void set(register port_t val) __attribute__ ((always_inline)) { *sPort = val; }
inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; }
@@ -124,37 +126,11 @@ template<uint8_t PIN> volatile RwReg *FastPin<PIN>::sPort;
template<uint8_t PIN> volatile RoReg *FastPin<PIN>::sInPort;
template<uint8_t PIN> class FastPinBB : public FastPin<PIN> {};
-
+#endif // defined(ARDUINO)
typedef volatile uint32_t & reg32_t;
typedef volatile uint32_t * ptr_reg32_t;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Pin definitions for AVR and ARM. If there are pin definitions supplied below for the platform being
-// built on, then much higher speed access will be possible, namely with direct GPIO register accesses.
-//
-///////////////////////////////////////////////////////////////////////////////////////////////////////////
-#if defined(FORCE_SOFTWARE_PINS)
-
-#warning "Softwrae pin support forced pin access will be slightly slower. See fastpin.h for info."
-#define NO_HARDWARE_PIN_SUPPORT
-#undef HAS_HARDWARE_PIN_SUPPORT
-
-#else
-
-// We want hardware pin support, include the hardware pin header files
-#include "fastpin_avr.h"
-#include "fastpin_arm_k20.h"
-#include "fastpin_arm_sam.h"
-
-#ifndef HAS_HARDWARE_PIN_SUPPORT
-#warning "No pin/port mappings found, pin access will be slightly slower. See fastpin.h for info."
-#define NO_HARDWARE_PIN_SUPPORT
-#endif
-
-#endif
-
-#endif
+#endif // __INC_FASTPIN_H
diff --git a/fastspi.h b/fastspi.h
index f80956f4..4c247157 100644
--- a/fastspi.h
+++ b/fastspi.h
@@ -3,40 +3,9 @@
#include "controller.h"
#include "lib8tion.h"
-#include "delay.h"
-
-// Some helper macros for getting at mis-ordered byte values
-#define SPI_B0 (RGB_BYTE0(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
-#define SPI_B1 (RGB_BYTE1(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
-#define SPI_B2 (RGB_BYTE2(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
-#define SPI_ADVANCE (3 + (MASK_SKIP_BITS & SKIP))
-
-/// Some of the SPI controllers will need to perform a transform on each byte before doing
-/// anyting with it. Creating a class of this form and passing it in as a template parameter to
-/// writeBytes/writeBytes3 below will ensure that the body of this method will get called on every
-/// byte worked on. Recommendation, make the adjust method aggressively inlined.
-///
-/// TODO: Convinience macro for building these
-class DATA_NOP {
-public:
- static __attribute__((always_inline)) inline uint8_t adjust(register uint8_t data) { return data; }
- static __attribute__((always_inline)) inline uint8_t adjust(register uint8_t data, register uint8_t scale) { return scale8(data, scale); }
- static __attribute__((always_inline)) inline void postBlock(int len) {}
-};
-
-#define FLAG_START_BIT 0x80
-#define MASK_SKIP_BITS 0x3F
-
-// Clock speed dividers
-#define SPEED_DIV_2 2
-#define SPEED_DIV_4 4
-#define SPEED_DIV_8 8
-#define SPEED_DIV_16 16
-#define SPEED_DIV_32 32
-#define SPEED_DIV_64 64
-#define SPEED_DIV_128 128
-
-#define MAX_DATA_RATE 0
+
+#include "fastspi_bitbang.h"
+
#if (CLK_DBL == 1)
#define DATA_RATE_MHZ(X) (((F_CPU / 1000000L) / X)/2)
#define DATA_RATE_KHZ(X) (((F_CPU / 1000L) / X)/2)
@@ -45,13 +14,6 @@ public:
#define DATA_RATE_KHZ(X) ((F_CPU / 1000L) / X)
#endif
-// Include the various specific SPI implementations
-#include "fastspi_bitbang.h"
-#include "fastspi_arm_k20.h"
-#include "fastspi_arm_sam.h"
-#include "fastspi_avr.h"
-#include "fastspi_dma.h"
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// External SPI template definition with partial instantiation(s) to map to hardware SPI ports on platforms/builds where the pin
diff --git a/fastspi_types.h b/fastspi_types.h
new file mode 100644
index 00000000..e0de6de3
--- /dev/null
+++ b/fastspi_types.h
@@ -0,0 +1,37 @@
+#ifndef __INC_FASTSPI_TYPES_H
+#define __INC_FASTSPI_TYPES_H
+
+// Some helper macros for getting at mis-ordered byte values
+#define SPI_B0 (RGB_BYTE0(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
+#define SPI_B1 (RGB_BYTE1(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
+#define SPI_B2 (RGB_BYTE2(RGB_ORDER) + (MASK_SKIP_BITS & SKIP))
+#define SPI_ADVANCE (3 + (MASK_SKIP_BITS & SKIP))
+
+/// Some of the SPI controllers will need to perform a transform on each byte before doing
+/// anyting with it. Creating a class of this form and passing it in as a template parameter to
+/// writeBytes/writeBytes3 below will ensure that the body of this method will get called on every
+/// byte worked on. Recommendation, make the adjust method aggressively inlined.
+///
+/// TODO: Convinience macro for building these
+class DATA_NOP {
+public:
+ static __attribute__((always_inline)) inline uint8_t adjust(register uint8_t data) { return data; }
+ static __attribute__((always_inline)) inline uint8_t adjust(register uint8_t data, register uint8_t scale) { return scale8(data, scale); }
+ static __attribute__((always_inline)) inline void postBlock(int len) {}
+};
+
+#define FLAG_START_BIT 0x80
+#define MASK_SKIP_BITS 0x3F
+
+// Clock speed dividers
+#define SPEED_DIV_2 2
+#define SPEED_DIV_4 4
+#define SPEED_DIV_8 8
+#define SPEED_DIV_16 16
+#define SPEED_DIV_32 32
+#define SPEED_DIV_64 64
+#define SPEED_DIV_128 128
+
+#define MAX_DATA_RATE 0
+
+#endif
diff --git a/hsv2rgb.cpp b/hsv2rgb.cpp
index 0844d1f2..203d1db6 100644
--- a/hsv2rgb.cpp
+++ b/hsv2rgb.cpp
@@ -1,7 +1,6 @@
#include <stdint.h>
-#include "lib8tion.h"
-#include "hsv2rgb.h"
+#include "FastLED.h"
// Functions to convert HSV colors to RGB colors.
//
@@ -71,29 +70,29 @@ void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb)
// Convert hue, saturation and brightness ( HSV/HSB ) to RGB
// "Dimming" is used on saturation and brightness to make
// the output more visually linear.
-
+
// Apply dimming curves
uint8_t value = APPLY_DIMMING( hsv.val);
uint8_t saturation = hsv.sat;
-
+
// The brightness floor is minimum number that all of
// R, G, and B will be set to.
uint8_t invsat = APPLY_DIMMING( 255 - saturation);
uint8_t brightness_floor = (value * invsat) / 256;
-
+
// The color amplitude is the maximum amount of R, G, and B
// that will be added on top of the brightness_floor to
// create the specific hue desired.
uint8_t color_amplitude = value - brightness_floor;
-
+
// Figure out which section of the hue wheel we're in,
// and how far offset we are withing that section
uint8_t section = hsv.hue / HSV_SECTION_3; // 0..2
uint8_t offset = hsv.hue % HSV_SECTION_3; // 0..63
-
+
uint8_t rampup = offset; // 0..63
uint8_t rampdown = (HSV_SECTION_3 - 1) - offset; // 63..0
-
+
// We now scale rampup and rampdown to a 0-255 range -- at least
// in theory, but here's where architecture-specific decsions
// come in to play:
@@ -113,25 +112,25 @@ void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb)
// faster to NOT multiply the ramp values by four, and just to
// divide the resulting product by 64 (instead of 256).
// Moral of the story: trust your profiler, not your insticts.
-
+
// Since there's an AVR assembly version elsewhere, we'll
// assume what we're on an architecture where any number of
// bit shifts has roughly the same cost, and we'll remove the
// redundant math at the source level:
-
+
// // scale up to 255 range
// //rampup *= 4; // 0..252
// //rampdown *= 4; // 0..252
-
+
// compute color-amplitude-scaled-down versions of rampup and rampdown
uint8_t rampup_amp_adj = (rampup * color_amplitude) / (256 / 4);
uint8_t rampdown_amp_adj = (rampdown * color_amplitude) / (256 / 4);
-
+
// add brightness_floor offset to everything
uint8_t rampup_adj_with_floor = rampup_amp_adj + brightness_floor;
uint8_t rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor;
-
-
+
+
if( section ) {
if( section == 1) {
// section 1: 0x40..0x7F
@@ -158,22 +157,22 @@ void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb)
void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
{
uint8_t hue, saturation, value;
-
+
hue = hsv.hue;
saturation = hsv.sat;
value = hsv.val;
-
+
// Saturation more useful the other way around
saturation = 255 - saturation;
uint8_t invsat = APPLY_DIMMING( saturation );
-
+
// Apply dimming curves
value = APPLY_DIMMING( value );
-
+
// The brightness floor is minimum number that all of
// R, G, and B will be set to, which is value * invsat
uint8_t brightness_floor;
-
+
asm volatile(
"mul %[value], %[invsat] \n"
"mov %[brightness_floor], r1 \n"
@@ -182,22 +181,22 @@ void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
[invsat] "r" (invsat)
: "r0", "r1"
);
-
+
// The color amplitude is the maximum amount of R, G, and B
// that will be added on top of the brightness_floor to
// create the specific hue desired.
uint8_t color_amplitude = value - brightness_floor;
-
+
// Figure how far we are offset into the section of the
// color wheel that we're in
uint8_t offset = hsv.hue & (HSV_SECTION_3 - 1); // 0..63
uint8_t rampup = offset * 4; // 0..252
-
-
+
+
// compute color-amplitude-scaled-down versions of rampup and rampdown
uint8_t rampup_amp_adj;
uint8_t rampdown_amp_adj;
-
+
asm volatile(
"mul %[rampup], %[color_amplitude] \n"
"mov %[rampup_amp_adj], r1 \n"
@@ -210,13 +209,13 @@ void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
: [color_amplitude] "r" (color_amplitude)
: "r0", "r1"
);
-
-
+
+
// add brightness_floor offset to everything
uint8_t rampup_adj_with_floor = rampup_amp_adj + brightness_floor;
uint8_t rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor;
-
-
+
+
// keep gcc from using "X" as the index register for storing
// results back in the return structure. AVR's X register can't
// do "std X+q, rnn", but the Y and Z registers can.
@@ -224,8 +223,8 @@ void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
// extra instructions. Simply killing X here seems to help it
// try Y or Z first.
asm volatile( "" : : : "r26", "r27" );
-
-
+
+
if( hue & 0x80 ) {
// section 2: 0x80..0xBF
rgb.r = rampup_adj_with_floor;
@@ -244,7 +243,7 @@ void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
rgb.b = brightness_floor;
}
}
-
+
cleanup_R1();
}
// End of AVR asm implementation
@@ -288,18 +287,18 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
// G2: Whether to divide all greens by two.
// Depends GREATLY on your particular LEDs
const uint8_t G2 = 0;
-
+
// Gscale: what to scale green down by.
// Depends GREATLY on your particular LEDs
const uint8_t Gscale = 0;
-
+
uint8_t hue = hsv.hue;
uint8_t sat = hsv.sat;
uint8_t val = hsv.val;
-
+
uint8_t offset = hue & 0x1F; // 0..31
-
+
// offset8 = offset * 8
uint8_t offset8 = offset;
{
@@ -309,11 +308,11 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
asm volatile("");
offset8 <<= 1;
}
-
+
uint8_t third = scale8( offset8, (256 / 3));
-
+
uint8_t r, g, b;
-
+
if( ! (hue & 0x80) ) {
// 0XX
if( ! (hue & 0x40) ) {
@@ -417,12 +416,12 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
}
}
}
-
+
// This is one of the good places to scale the green down,
// although the client can scale green down as well.
if( G2 ) g = g >> 1;
if( Gscale ) g = scale8_video_LEAVING_R1_DIRTY( g, Gscale);
-
+
// Scale down colors if we're desaturated at all
// and add the brightness_floor to r, g, and b.
if( sat != 255 ) {
@@ -431,7 +430,7 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
uint8_t desat = 255 - sat;
desat = scale8( desat, desat);
-
+
uint8_t brightness_floor = desat;
r += brightness_floor;
g += brightness_floor;
@@ -440,11 +439,11 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
// Now scale everything down if we're at value < 255.
if( val != 255 ) {
-
+
val = scale8_video_LEAVING_R1_DIRTY( val, val);
nscale8x3_video( r, g, b, val);
}
-
+
// Here we have the old AVR "missing std X+n" problem again
// It turns out that fixing it winds up costing more than
// not fixing it.
diff --git a/led_sysdefs.h b/led_sysdefs.h
index e16ce2db..29bced42 100644
--- a/led_sysdefs.h
+++ b/led_sysdefs.h
@@ -2,91 +2,21 @@
#define __INC_LED_SYSDEFS_H
#if defined(__MK20DX128__) || defined(__MK20DX256__)
-
-#define FASTLED_TEENSY3
-#define FASTLED_ARM
-#define FASTLED_ACCURATE_CLOCK
-#ifndef INTERRUPT_THRESHOLD
-#define INTERRUPT_THRESHOLD 1
-#endif
-#if (F_CPU == 96000000)
-#define CLK_DBL 1
-#endif
-
+// Include k20/T3 headers
+#include "platforms/arm/k20/led_sysdefs_arm_k20.h"
#elif defined(__SAM3X8E__)
-
-#define FASTLED_ARM
-
-// Setup DUE timer defines/channels/etc...
-#ifndef DUE_TIMER_CHANNEL
-#define DUE_TIMER_GROUP 0
-#endif
-
-#ifndef DUE_TIMER_CHANNEL
-#define DUE_TIMER_CHANNEL 0
-#endif
-
-#define DUE_TIMER ((DUE_TIMER_GROUP==0) ? TC0 : ((DUE_TIMER_GROUP==1) ? TC1 : TC2))
-#define DUE_TIMER_ID (ID_TC0 + (DUE_TIMER_GROUP*3) + DUE_TIMER_CHANNEL)
-#define DUE_TIMER_VAL (DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_CV << 1)
-#define DUE_TIMER_RUNNING ((DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_SR & TC_SR_CLKSTA) != 0)
-
+// Include sam/due headers
+#include "platforms/arm/sam/led_sysdefs_arm_sam.h"
#else
-
-#define FASTLED_AVR
-#define FASTLED_ACCURATE_CLOCK
-#ifndef INTERRUPT_THRESHOLD
-#define INTERRUPT_THRESHOLD 2
+// AVR platforms
+#include "platforms/avr/led_sysdefs_avr.h"
#endif
-#endif
-
-#ifndef CLK_DBL
-#define CLK_DBL 0
-#endif
-#if defined(FASTLED_AVR) || defined(FASTLED_TEENSY3)
-#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(); __disable_fault_irq();
-#define sei() __enable_irq(); __enable_fault_irq();
-
-#endif
-
-#if 0
-#if defined(ARDUINO) && defined(FASTLED_AVR) && ARDUINO >= 157
-#error Arduion versions 1.5.7 and later not yet supported by FastLED for AVR
-#endif
-
-#if defined(ARDUINO) && defined (FASTLED_AVR) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 7)
-#error gcc versions 4.8 and above are not yet supported by FastLED for AVR
-#endif
-#endif
// Arduino.h needed for convinience functions digitalPinToPort/BitMask/portOutputRegister and the pinMode methods.
#include<Arduino.h>
-// Scaling macro choice
-#if defined(LIB8_ATTINY)
-# define INLINE_SCALE(B, SCALE) delaycycles<3>()
-# warning "No hardware multiply, inline brightness scaling disabled"
-#else
-# define INLINE_SCALE(B, SCALE) B = scale8_video(B, SCALE)
-#endif
-
#define CLKS_PER_US (F_CPU/1000000)
-#ifndef INTERRUPT_THRESHOLD
-#define INTERRUPT_THRESHOLD 1
-#endif
-
#endif
diff --git a/lib8tion.h b/lib8tion.h
index 4edf7bf3..cdb3980f 100644
--- a/lib8tion.h
+++ b/lib8tion.h
@@ -1,3 +1,7 @@
+#ifndef __INC_LED_SYSDEFS_H
+#error WTH? led_sysdefs needs to be included first
+#endif
+
#ifndef __INC_LIB8TION_H
#define __INC_LIB8TION_H
@@ -109,7 +113,7 @@
faster and five times smaller than Arduino's built-in
generic 32-bit sqrt routine.
sqrt16( uint16_t x ) == sqrt( x)
-
+
- Dimming and brightening functions for 8-bit
light values.
dim8_video( x) == scale8_video( x, x)
@@ -145,7 +149,7 @@
Sine wave beat generators can specify a low and
high range for the output. Sawtooth wave beat
generators always range 0-255 or 0-65535.
- beatsin8( BPM, low8, high8)
+ beatsin8( BPM, low8, high8)
= (sine(beatphase) * (high8-low8)) + low8
beatsin16( BPM, low16, high16)
= (sine(beatphase) * (high16-low16)) + low16
@@ -1679,16 +1683,16 @@ LIB8STATIC uint8_t sqrt16(uint16_t x)
if( x <= 1) {
return x;
}
-
+
uint8_t low = 1; // lower bound
uint8_t hi, mid;
-
+
if( x > 7904) {
hi = 255;
} else {
hi = (x >> 5) + 8; // initial estimate for upper bound
}
-
+
do {
mid = (low + hi) >> 1;
if ((uint16_t)(mid * mid) > x) {
@@ -1700,7 +1704,7 @@ LIB8STATIC uint8_t sqrt16(uint16_t x)
low = mid + 1;
}
} while (hi >= low);
-
+
return low - 1;
}
@@ -1796,7 +1800,7 @@ LIB8STATIC uint16_t beat16( accum88 beats_per_minute)
{
// Convert simple 8-bit BPM's to full Q8.8 accum88's if needed
if( beats_per_minute < 256) beats_per_minute <<= 8;
-
+
// BPM is 'beats per minute', or 'beats per 60000ms'.
// To avoid using the (slower) division operator, we
// want to convert 'beats per 60000ms' to 'beats per 65536ms',
diff --git a/platforms.h b/platforms.h
new file mode 100644
index 00000000..9f1c7579
--- /dev/null
+++ b/platforms.h
@@ -0,0 +1,15 @@
+#ifndef __INC_PLATFORMS_H
+#define __INC_PLATFORMS_H
+
+#if defined(__MK20DX128__) || defined(__MK20DX256__)
+// Include k20/T3 headers
+#include "platforms/arm/k20/fastled_arm_k20.h"
+#elif defined(__SAM3X8E__)
+// Include sam/due headers
+#include "platforms/arm/sam/fastled_arm_sam.h"
+#else
+// AVR platforms
+#include "platforms/avr/fastled_avr.h"
+#endif
+
+#endif
diff --git a/clockless_arm_k20.h b/platforms/arm/k20/clockless_arm_k20.h
index d96c9bb2..d96c9bb2 100644
--- a/clockless_arm_k20.h
+++ b/platforms/arm/k20/clockless_arm_k20.h
diff --git a/clockless_block_arm_k20.h b/platforms/arm/k20/clockless_block_arm_k20.h
index 63dc5030..63dc5030 100644
--- a/clockless_block_arm_k20.h
+++ b/platforms/arm/k20/clockless_block_arm_k20.h
diff --git a/platforms/arm/k20/fastled_arm_k20.h b/platforms/arm/k20/fastled_arm_k20.h
new file mode 100644
index 00000000..48565ec5
--- /dev/null
+++ b/platforms/arm/k20/fastled_arm_k20.h
@@ -0,0 +1,14 @@
+#ifndef __INC_FASTLED_ARM_K20_H
+#define __INC_FASTLED_ARM_K20_H
+
+// Include the k20 headers
+#include "bitswap.h"
+#include "delay.h"
+#include "fastpin_arm_k20.h"
+#include "fastspi_arm_k20.h"
+#include "octows2811_controller.h"
+#include "smartmatrix_t3.h"
+#include "clockless_arm_k20.h"
+#include "clockless_block_arm_k20.h"
+
+#endif
diff --git a/fastpin_arm_k20.h b/platforms/arm/k20/fastpin_arm_k20.h
index 2fb75fbd..edbbd5b9 100644
--- a/fastpin_arm_k20.h
+++ b/platforms/arm/k20/fastpin_arm_k20.h
@@ -1,6 +1,14 @@
#ifndef __FASTPIN_ARM_K20_H
#define __FASTPIN_ARM_K20_H
+#if defined(FORCE_SOFTWARE_PINS)
+#warning "Software pin support forced, pin access will be sloightly slower."
+#define NO_HARDWARE_PIN_SUPPORT
+#undef HAS_HARDWARE_PIN_SUPPORT
+
+#else
+
+
/// 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.
@@ -65,6 +73,7 @@ public:
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
+#define _R(T) struct __gen_struct_ ## T
#define _RD32(T) struct __gen_struct_ ## T { static __attribute__((always_inline)) inline reg32_t r() { return 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);
@@ -104,4 +113,6 @@ _DEFPIN_ARM(32, 18, B); _DEFPIN_ARM(33, 4, A);
#define HAS_HARDWARE_PIN_SUPPORT
#endif
-#endif
+#endif // FORCE_SOFTWARE_PINS
+
+#endif // __INC_FASTPIN_ARM_K20
diff --git a/fastspi_arm_k20.h b/platforms/arm/k20/fastspi_arm_k20.h
index ad9598ae..ad9598ae 100644
--- a/fastspi_arm_k20.h
+++ b/platforms/arm/k20/fastspi_arm_k20.h
diff --git a/platforms/arm/k20/led_sysdefs_arm_k20.h b/platforms/arm/k20/led_sysdefs_arm_k20.h
new file mode 100644
index 00000000..abed80f9
--- /dev/null
+++ b/platforms/arm/k20/led_sysdefs_arm_k20.h
@@ -0,0 +1,26 @@
+#ifndef __INC_LED_SYSDEFS_ARM_K20_H
+#define __INC_LED_SYSDEFS_ARM_K20_H
+
+#define FASTLED_TEENSY3
+#define FASTLED_ARM
+#define FASTLED_ACCURATE_CLOCK
+
+#ifndef INTERRUPT_THRESHOLD
+#define INTERRUPT_THRESHOLD 1
+#endif
+
+#if (F_CPU == 96000000)
+#define CLK_DBL 1
+#endif
+
+// Get some system include files
+#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
+
+#endif
diff --git a/octows2811_controller.h b/platforms/arm/k20/octows2811_controller.h
index dd6c0b92..dd6c0b92 100644
--- a/octows2811_controller.h
+++ b/platforms/arm/k20/octows2811_controller.h
diff --git a/smartmatrix_t3.h b/platforms/arm/k20/smartmatrix_t3.h
index ba77d149..ba77d149 100644
--- a/smartmatrix_t3.h
+++ b/platforms/arm/k20/smartmatrix_t3.h
diff --git a/clockless_arm_sam.h b/platforms/arm/sam/clockless_arm_sam.h
index 6924cc9d..6924cc9d 100644
--- a/clockless_arm_sam.h
+++ b/platforms/arm/sam/clockless_arm_sam.h
diff --git a/clockless_block_arm_sam.h b/platforms/arm/sam/clockless_block_arm_sam.h
index c75e3ce6..51eb1b92 100644
--- a/clockless_block_arm_sam.h
+++ b/platforms/arm/sam/clockless_block_arm_sam.h
@@ -1,11 +1,6 @@
#ifndef __INC_BLOCK_CLOCKLESS_H
#define __INC_BLOCK_CLOCKLESS_H
-#include "controller.h"
-#include "lib8tion.h"
-#include "led_sysdefs.h"
-#include "delay.h"
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Base template for clockless controllers. These controllers have 3 control points in their cycle for each bit. The first point
diff --git a/platforms/arm/sam/fastled_arm_sam.h b/platforms/arm/sam/fastled_arm_sam.h
new file mode 100644
index 00000000..51e2f37c
--- /dev/null
+++ b/platforms/arm/sam/fastled_arm_sam.h
@@ -0,0 +1,11 @@
+#ifndef __INC_FASTLED_ARM_SAM_H
+#define __INC_FASTLED_ARM_SAM_H
+
+// Include the sam headers
+#include "delay.h"
+#include "fastpin_arm_sam.h"
+#include "fastspi_arm_sam.h"
+#include "clockless_arm_sam.h"
+#include "clockless_block_arm_sam.h"
+
+#endif
diff --git a/fastpin_arm_sam.h b/platforms/arm/sam/fastpin_arm_sam.h
index 0296bd50..e1a36990 100644
--- a/fastpin_arm_sam.h
+++ b/platforms/arm/sam/fastpin_arm_sam.h
@@ -1,11 +1,19 @@
#ifndef __INC_FASTPIN_ARM_SAM_H
#define __INC_FASTPIN_ARM_SAM_H
+#if defined(FORCE_SOFTWARE_PINS)
+#warning "Software pin support forced, pin access will be sloightly slower."
+#define NO_HARDWARE_PIN_SUPPORT
+#undef HAS_HARDWARE_PIN_SUPPORT
+
+#else
+
+
/// 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 {
+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;
@@ -18,7 +26,7 @@ public:
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(); }
@@ -34,9 +42,9 @@ public:
};
-/// Template definition for DUE style ARM pins using bit banding, providing direct access to the various GPIO registers. GCC
+/// Template definition for DUE style ARM pins using bit banding, providing direct access to the various GPIO registers. GCC
/// does a poor job of optimizing around these accesses so they are not being used just yet.
-template<uint8_t PIN, uint32_t _BIT, typename _PDOR, typename _PSOR, typename _PCOR, typename _PDDR> class _DUEPIN_BITBAND {
+template<uint8_t PIN, uint32_t _BIT, typename _PDOR, typename _PSOR, typename _PCOR, typename _PDDR> class _DUEPIN_BITBAND {
public:
typedef volatile uint32_t * port_ptr_t;
typedef uint32_t port_t;
@@ -49,7 +57,7 @@ public:
inline static void set(register port_t val) __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = val; }
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
-
+
inline static void toggle() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() ^= 1; }
inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); }
@@ -62,12 +70,18 @@ public:
inline static port_t mask() __attribute__ ((always_inline)) { return 1; }
};
+#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
+#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
+
+#define _R(T) struct __gen_struct_ ## T
+#define _RD32(T) struct __gen_struct_ ## T { static __attribute__((always_inline)) inline reg32_t r() { return T; } \
+ template<int BIT> static __attribute__((always_inline)) inline ptr_reg32_t rx() { return GPIO_BITBAND_PTR(T, BIT); } };
#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 _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)> {}; \
template<> class FastPinBB<PIN> : public _DUEPIN_BITBAND<PIN, BIT, _R(REG_PIO ## L ## _ODSR), _R(REG_PIO ## L ## _SODR), _R(REG_PIO ## L ## _CODR), \
- _R(GPIO ## L ## _OER)> {};
+ _R(GPIO ## L ## _OER)> {};
#if defined(__SAM3X8E__)
@@ -113,5 +127,6 @@ _DEFPIN_DUE(110, 29, B); _DEFPIN_DUE(111, 30, B); _DEFPIN_DUE(112, 31, B); _DEFP
#endif
+#endif // FORCE_SOFTWARE_PINS
-#endif
+#endif // __INC_FASTPIN_ARM_SAM_H
diff --git a/fastspi_arm_sam.h b/platforms/arm/sam/fastspi_arm_sam.h
index d756c221..d756c221 100644
--- a/fastspi_arm_sam.h
+++ b/platforms/arm/sam/fastspi_arm_sam.h
diff --git a/platforms/arm/sam/led_sysdefs_arm_sam.h b/platforms/arm/sam/led_sysdefs_arm_sam.h
new file mode 100644
index 00000000..e45f9609
--- /dev/null
+++ b/platforms/arm/sam/led_sysdefs_arm_sam.h
@@ -0,0 +1,30 @@
+#ifndef __INC_LED_SYSDEFS_ARM_SAM_H
+#define __INC_LED_SYSDEFS_ARM_SAM_H
+
+
+#define FASTLED_ARM
+
+// Setup DUE timer defines/channels/etc...
+#ifndef DUE_TIMER_CHANNEL
+#define DUE_TIMER_GROUP 0
+#endif
+
+#ifndef DUE_TIMER_CHANNEL
+#define DUE_TIMER_CHANNEL 0
+#endif
+
+#define DUE_TIMER ((DUE_TIMER_GROUP==0) ? TC0 : ((DUE_TIMER_GROUP==1) ? TC1 : TC2))
+#define DUE_TIMER_ID (ID_TC0 + (DUE_TIMER_GROUP*3) + DUE_TIMER_CHANNEL)
+#define DUE_TIMER_VAL (DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_CV << 1)
+#define DUE_TIMER_RUNNING ((DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_SR & TC_SR_CLKSTA) != 0)
+
+#ifndef INTERRUPT_THRESHOLD
+#define INTERRUPT_THRESHOLD 1
+#endif
+
+// reuseing/abusing cli/sei defs for due
+#define cli() __disable_irq(); __disable_fault_irq();
+#define sei() __enable_irq(); __enable_fault_irq();
+
+
+#endif
diff --git a/clockless_trinket.h b/platforms/avr/clockless_trinket.h
index 592ea537..4630719d 100644
--- a/clockless_trinket.h
+++ b/platforms/avr/clockless_trinket.h
@@ -3,7 +3,6 @@
#include "controller.h"
#include "lib8tion.h"
-#include "delay.h"
#include <avr/interrupt.h> // for cli/se definitions
#if defined(FASTLED_AVR)
diff --git a/platforms/avr/fastled_avr.h b/platforms/avr/fastled_avr.h
new file mode 100644
index 00000000..4c9b842e
--- /dev/null
+++ b/platforms/avr/fastled_avr.h
@@ -0,0 +1,9 @@
+#ifndef __INC_FASTLED_AVR_H
+#define __INC_FASTLED_AVR_H
+
+#include "delay.h"
+#include "fastpin_avr.h"
+#include "fastspi_avr.h"
+#include "clockless_trinket.h"
+
+#endif
diff --git a/fastpin_avr.h b/platforms/avr/fastpin_avr.h
index 103498c2..f5354a9d 100644
--- a/fastpin_avr.h
+++ b/platforms/avr/fastpin_avr.h
@@ -1,6 +1,13 @@
#ifndef __INC_FASTPIN_AVR_H
#define __INC_FASTPIN_AVR_H
+#if defined(FORCE_SOFTWARE_PINS)
+#warning "Software pin support forced, pin access will be sloightly slower."
+#define NO_HARDWARE_PIN_SUPPORT
+#undef HAS_HARDWARE_PIN_SUPPORT
+
+#else
+
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define AVR_PIN_CYCLES(_PIN) (((_PIN >= 62 ) || (_PIN>=42 && _PIN<=49) || (_PIN>=14 && _PIN <=17) || (_PIN>=6 && _PIN <=9)) ? 2 : 1)
#else
@@ -9,12 +16,12 @@
/// 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.
-template<uint8_t PIN, uint8_t _MASK, typename _PORT, typename _DDR, typename _PIN> class _AVRPIN {
+/// a lot of optimizations, as the inlined hi/lo methods will devolve to a single io register write/bitset.
+template<uint8_t PIN, uint8_t _MASK, typename _PORT, typename _DDR, typename _PIN> class _AVRPIN {
public:
typedef volatile uint8_t * port_ptr_t;
typedef uint8_t port_t;
-
+
inline static void setOutput() { _DDR::r() |= _MASK; }
inline static void setInput() { _DDR::r() &= ~_MASK; }
@@ -23,7 +30,7 @@ public:
inline static void set(register uint8_t val) __attribute__ ((always_inline)) { _PORT::r() = val; }
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
-
+
inline static void toggle() __attribute__ ((always_inline)) { _PIN::r() = _MASK; }
inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); }
@@ -55,7 +62,7 @@ _DEFPIN_AVR(4, 0x10, B); _DEFPIN_AVR(5, 0x20, B);
#define HAS_HARDWARE_PIN_SUPPORT 1
-#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__)
+#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__)
_IO(A); _IO(B);
_DEFPIN_AVR(0, 0x01, A); _DEFPIN_AVR(1, 0x02, A); _DEFPIN_AVR(2, 0x04, A); _DEFPIN_AVR(3, 0x08, A);
@@ -106,24 +113,24 @@ _DEFPIN_AVR(28, 1<<6, C); _DEFPIN_AVR(29, 1<<7, C); _DEFPIN_AVR(30, 1<<4, D); _D
_IO(A); _IO(B); _IO(C); _IO(D); _IO(E); _IO(F); _IO(G); _IO(H); _IO(J); _IO(K); _IO(L);
#define MAX_PIN 69
-_DEFPIN_AVR(0, 1, E); _DEFPIN_AVR(1, 2, E); _DEFPIN_AVR(2, 16, E); _DEFPIN_AVR(3, 32, E);
-_DEFPIN_AVR(4, 32, G); _DEFPIN_AVR(5, 8, E); _DEFPIN_AVR(6, 8, H); _DEFPIN_AVR(7, 16, H);
-_DEFPIN_AVR(8, 32, H); _DEFPIN_AVR(9, 64, H); _DEFPIN_AVR(10, 16, B); _DEFPIN_AVR(11, 32, B);
-_DEFPIN_AVR(12, 64, B); _DEFPIN_AVR(13, 128, B); _DEFPIN_AVR(14, 2, J); _DEFPIN_AVR(15, 1, J);
-_DEFPIN_AVR(16, 2, H); _DEFPIN_AVR(17, 1, H); _DEFPIN_AVR(18, 8, D); _DEFPIN_AVR(19, 4, D);
-_DEFPIN_AVR(20, 2, D); _DEFPIN_AVR(21, 1, D); _DEFPIN_AVR(22, 1, A); _DEFPIN_AVR(23, 2, A);
-_DEFPIN_AVR(24, 4, A); _DEFPIN_AVR(25, 8, A); _DEFPIN_AVR(26, 16, A); _DEFPIN_AVR(27, 32, A);
-_DEFPIN_AVR(28, 64, A); _DEFPIN_AVR(29, 128, A); _DEFPIN_AVR(30, 128, C); _DEFPIN_AVR(31, 64, C);
-_DEFPIN_AVR(32, 32, C); _DEFPIN_AVR(33, 16, C); _DEFPIN_AVR(34, 8, C); _DEFPIN_AVR(35, 4, C);
-_DEFPIN_AVR(36, 2, C); _DEFPIN_AVR(37, 1, C); _DEFPIN_AVR(38, 128, D); _DEFPIN_AVR(39, 4, G);
-_DEFPIN_AVR(40, 2, G); _DEFPIN_AVR(41, 1, G); _DEFPIN_AVR(42, 128, L); _DEFPIN_AVR(43, 64, L);
-_DEFPIN_AVR(44, 32, L); _DEFPIN_AVR(45, 16, L); _DEFPIN_AVR(46, 8, L); _DEFPIN_AVR(47, 4, L);
-_DEFPIN_AVR(48, 2, L); _DEFPIN_AVR(49, 1, L); _DEFPIN_AVR(50, 8, B); _DEFPIN_AVR(51, 4, B);
-_DEFPIN_AVR(52, 2, B); _DEFPIN_AVR(53, 1, B); _DEFPIN_AVR(54, 1, F); _DEFPIN_AVR(55, 2, F);
-_DEFPIN_AVR(56, 4, F); _DEFPIN_AVR(57, 8, F); _DEFPIN_AVR(58, 16, F); _DEFPIN_AVR(59, 32, F);
-_DEFPIN_AVR(60, 64, F); _DEFPIN_AVR(61, 128, F); _DEFPIN_AVR(62, 1, K); _DEFPIN_AVR(63, 2, K);
-_DEFPIN_AVR(64, 4, K); _DEFPIN_AVR(65, 8, K); _DEFPIN_AVR(66, 16, K); _DEFPIN_AVR(67, 32, K);
-_DEFPIN_AVR(68, 64, K); _DEFPIN_AVR(69, 128, K);
+_DEFPIN_AVR(0, 1, E); _DEFPIN_AVR(1, 2, E); _DEFPIN_AVR(2, 16, E); _DEFPIN_AVR(3, 32, E);
+_DEFPIN_AVR(4, 32, G); _DEFPIN_AVR(5, 8, E); _DEFPIN_AVR(6, 8, H); _DEFPIN_AVR(7, 16, H);
+_DEFPIN_AVR(8, 32, H); _DEFPIN_AVR(9, 64, H); _DEFPIN_AVR(10, 16, B); _DEFPIN_AVR(11, 32, B);
+_DEFPIN_AVR(12, 64, B); _DEFPIN_AVR(13, 128, B); _DEFPIN_AVR(14, 2, J); _DEFPIN_AVR(15, 1, J);
+_DEFPIN_AVR(16, 2, H); _DEFPIN_AVR(17, 1, H); _DEFPIN_AVR(18, 8, D); _DEFPIN_AVR(19, 4, D);
+_DEFPIN_AVR(20, 2, D); _DEFPIN_AVR(21, 1, D); _DEFPIN_AVR(22, 1, A); _DEFPIN_AVR(23, 2, A);
+_DEFPIN_AVR(24, 4, A); _DEFPIN_AVR(25, 8, A); _DEFPIN_AVR(26, 16, A); _DEFPIN_AVR(27, 32, A);
+_DEFPIN_AVR(28, 64, A); _DEFPIN_AVR(29, 128, A); _DEFPIN_AVR(30, 128, C); _DEFPIN_AVR(31, 64, C);
+_DEFPIN_AVR(32, 32, C); _DEFPIN_AVR(33, 16, C); _DEFPIN_AVR(34, 8, C); _DEFPIN_AVR(35, 4, C);
+_DEFPIN_AVR(36, 2, C); _DEFPIN_AVR(37, 1, C); _DEFPIN_AVR(38, 128, D); _DEFPIN_AVR(39, 4, G);
+_DEFPIN_AVR(40, 2, G); _DEFPIN_AVR(41, 1, G); _DEFPIN_AVR(42, 128, L); _DEFPIN_AVR(43, 64, L);
+_DEFPIN_AVR(44, 32, L); _DEFPIN_AVR(45, 16, L); _DEFPIN_AVR(46, 8, L); _DEFPIN_AVR(47, 4, L);
+_DEFPIN_AVR(48, 2, L); _DEFPIN_AVR(49, 1, L); _DEFPIN_AVR(50, 8, B); _DEFPIN_AVR(51, 4, B);
+_DEFPIN_AVR(52, 2, B); _DEFPIN_AVR(53, 1, B); _DEFPIN_AVR(54, 1, F); _DEFPIN_AVR(55, 2, F);
+_DEFPIN_AVR(56, 4, F); _DEFPIN_AVR(57, 8, F); _DEFPIN_AVR(58, 16, F); _DEFPIN_AVR(59, 32, F);
+_DEFPIN_AVR(60, 64, F); _DEFPIN_AVR(61, 128, F); _DEFPIN_AVR(62, 1, K); _DEFPIN_AVR(63, 2, K);
+_DEFPIN_AVR(64, 4, K); _DEFPIN_AVR(65, 8, K); _DEFPIN_AVR(66, 16, K); _DEFPIN_AVR(67, 32, K);
+_DEFPIN_AVR(68, 64, K); _DEFPIN_AVR(69, 128, K);
#define SPI_DATA 51
#define SPI_CLOCK 52
@@ -135,15 +142,15 @@ _DEFPIN_AVR(68, 64, K); _DEFPIN_AVR(69, 128, K);
#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
// teensy defs
-_IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
+_IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
#define MAX_PIN 23
-_DEFPIN_AVR(0, 1, B); _DEFPIN_AVR(1, 2, B); _DEFPIN_AVR(2, 4, B); _DEFPIN_AVR(3, 8, B);
-_DEFPIN_AVR(4, 128, B); _DEFPIN_AVR(5, 1, D); _DEFPIN_AVR(6, 2, D); _DEFPIN_AVR(7, 4, D);
-_DEFPIN_AVR(8, 8, D); _DEFPIN_AVR(9, 64, C); _DEFPIN_AVR(10, 128, C); _DEFPIN_AVR(11, 64, D);
-_DEFPIN_AVR(12, 128, D); _DEFPIN_AVR(13, 16, B); _DEFPIN_AVR(14, 32, B); _DEFPIN_AVR(15, 64, B);
-_DEFPIN_AVR(16, 128, F); _DEFPIN_AVR(17, 64, F); _DEFPIN_AVR(18, 32, F); _DEFPIN_AVR(19, 16, F);
-_DEFPIN_AVR(20, 2, F); _DEFPIN_AVR(21, 1, F); _DEFPIN_AVR(22, 16, D); _DEFPIN_AVR(23, 32, D);
+_DEFPIN_AVR(0, 1, B); _DEFPIN_AVR(1, 2, B); _DEFPIN_AVR(2, 4, B); _DEFPIN_AVR(3, 8, B);
+_DEFPIN_AVR(4, 128, B); _DEFPIN_AVR(5, 1, D); _DEFPIN_AVR(6, 2, D); _DEFPIN_AVR(7, 4, D);
+_DEFPIN_AVR(8, 8, D); _DEFPIN_AVR(9, 64, C); _DEFPIN_AVR(10, 128, C); _DEFPIN_AVR(11, 64, D);
+_DEFPIN_AVR(12, 128, D); _DEFPIN_AVR(13, 16, B); _DEFPIN_AVR(14, 32, B); _DEFPIN_AVR(15, 64, B);
+_DEFPIN_AVR(16, 128, F); _DEFPIN_AVR(17, 64, F); _DEFPIN_AVR(18, 32, F); _DEFPIN_AVR(19, 16, F);
+_DEFPIN_AVR(20, 2, F); _DEFPIN_AVR(21, 1, F); _DEFPIN_AVR(22, 16, D); _DEFPIN_AVR(23, 32, D);
#define SPI_DATA 2
#define SPI_CLOCK 1
@@ -154,21 +161,21 @@ _DEFPIN_AVR(20, 2, F); _DEFPIN_AVR(21, 1, F); _DEFPIN_AVR(22, 16, D); _DEFPIN_AV
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
// teensy++ 2 defs
-_IO(A); _IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
+_IO(A); _IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
#define MAX_PIN 45
-_DEFPIN_AVR(0, 1, D); _DEFPIN_AVR(1, 2, D); _DEFPIN_AVR(2, 4, D); _DEFPIN_AVR(3, 8, D);
-_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 32, D); _DEFPIN_AVR(6, 64, D); _DEFPIN_AVR(7, 128, D);
-_DEFPIN_AVR(8, 1, E); _DEFPIN_AVR(9, 2, E); _DEFPIN_AVR(10, 1, C); _DEFPIN_AVR(11, 2, C);
-_DEFPIN_AVR(12, 4, C); _DEFPIN_AVR(13, 8, C); _DEFPIN_AVR(14, 16, C); _DEFPIN_AVR(15, 32, C);
-_DEFPIN_AVR(16, 64, C); _DEFPIN_AVR(17, 128, C); _DEFPIN_AVR(18, 64, E); _DEFPIN_AVR(19, 128, E);
-_DEFPIN_AVR(20, 1, B); _DEFPIN_AVR(21, 2, B); _DEFPIN_AVR(22, 4, B); _DEFPIN_AVR(23, 8, B);
-_DEFPIN_AVR(24, 16, B); _DEFPIN_AVR(25, 32, B); _DEFPIN_AVR(26, 64, B); _DEFPIN_AVR(27, 128, B);
-_DEFPIN_AVR(28, 1, A); _DEFPIN_AVR(29, 2, A); _DEFPIN_AVR(30, 4, A); _DEFPIN_AVR(31, 8, A);
-_DEFPIN_AVR(32, 16, A); _DEFPIN_AVR(33, 32, A); _DEFPIN_AVR(34, 64, A); _DEFPIN_AVR(35, 128, A);
-_DEFPIN_AVR(36, 16, E); _DEFPIN_AVR(37, 32, E); _DEFPIN_AVR(38, 1, F); _DEFPIN_AVR(39, 2, F);
-_DEFPIN_AVR(40, 4, F); _DEFPIN_AVR(41, 8, F); _DEFPIN_AVR(42, 16, F); _DEFPIN_AVR(43, 32, F);
-_DEFPIN_AVR(44, 64, F); _DEFPIN_AVR(45, 128, F);
+_DEFPIN_AVR(0, 1, D); _DEFPIN_AVR(1, 2, D); _DEFPIN_AVR(2, 4, D); _DEFPIN_AVR(3, 8, D);
+_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 32, D); _DEFPIN_AVR(6, 64, D); _DEFPIN_AVR(7, 128, D);
+_DEFPIN_AVR(8, 1, E); _DEFPIN_AVR(9, 2, E); _DEFPIN_AVR(10, 1, C); _DEFPIN_AVR(11, 2, C);
+_DEFPIN_AVR(12, 4, C); _DEFPIN_AVR(13, 8, C); _DEFPIN_AVR(14, 16, C); _DEFPIN_AVR(15, 32, C);
+_DEFPIN_AVR(16, 64, C); _DEFPIN_AVR(17, 128, C); _DEFPIN_AVR(18, 64, E); _DEFPIN_AVR(19, 128, E);
+_DEFPIN_AVR(20, 1, B); _DEFPIN_AVR(21, 2, B); _DEFPIN_AVR(22, 4, B); _DEFPIN_AVR(23, 8, B);
+_DEFPIN_AVR(24, 16, B); _DEFPIN_AVR(25, 32, B); _DEFPIN_AVR(26, 64, B); _DEFPIN_AVR(27, 128, B);
+_DEFPIN_AVR(28, 1, A); _DEFPIN_AVR(29, 2, A); _DEFPIN_AVR(30, 4, A); _DEFPIN_AVR(31, 8, A);
+_DEFPIN_AVR(32, 16, A); _DEFPIN_AVR(33, 32, A); _DEFPIN_AVR(34, 64, A); _DEFPIN_AVR(35, 128, A);
+_DEFPIN_AVR(36, 16, E); _DEFPIN_AVR(37, 32, E); _DEFPIN_AVR(38, 1, F); _DEFPIN_AVR(39, 2, F);
+_DEFPIN_AVR(40, 4, F); _DEFPIN_AVR(41, 8, F); _DEFPIN_AVR(42, 16, F); _DEFPIN_AVR(43, 32, F);
+_DEFPIN_AVR(44, 64, F); _DEFPIN_AVR(45, 128, F);
#define SPI_DATA 22
#define SPI_CLOCK 21
@@ -179,15 +186,15 @@ _DEFPIN_AVR(44, 64, F); _DEFPIN_AVR(45, 128, F);
#elif defined(__AVR_ATmega32U4__)
// leonard defs
-_IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
+_IO(B); _IO(C); _IO(D); _IO(E); _IO(F);
#define MAX_PIN 23
-_DEFPIN_AVR(0, 4, D); _DEFPIN_AVR(1, 8, D); _DEFPIN_AVR(2, 2, D); _DEFPIN_AVR(3, 1, D);
-_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 64, C); _DEFPIN_AVR(6, 128, D); _DEFPIN_AVR(7, 64, E);
-_DEFPIN_AVR(8, 16, B); _DEFPIN_AVR(9, 32, B); _DEFPIN_AVR(10, 64, B); _DEFPIN_AVR(11, 128, B);
-_DEFPIN_AVR(12, 64, D); _DEFPIN_AVR(13, 128, C); _DEFPIN_AVR(14, 8, B); _DEFPIN_AVR(15, 2, B);
-_DEFPIN_AVR(16, 4, B); _DEFPIN_AVR(17, 1, B); _DEFPIN_AVR(18, 128, F); _DEFPIN_AVR(19, 64, F);
-_DEFPIN_AVR(20, 32, F); _DEFPIN_AVR(21, 16, F); _DEFPIN_AVR(22, 2, F); _DEFPIN_AVR(23, 0, F);
+_DEFPIN_AVR(0, 4, D); _DEFPIN_AVR(1, 8, D); _DEFPIN_AVR(2, 2, D); _DEFPIN_AVR(3, 1, D);
+_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 64, C); _DEFPIN_AVR(6, 128, D); _DEFPIN_AVR(7, 64, E);
+_DEFPIN_AVR(8, 16, B); _DEFPIN_AVR(9, 32, B); _DEFPIN_AVR(10, 64, B); _DEFPIN_AVR(11, 128, B);
+_DEFPIN_AVR(12, 64, D); _DEFPIN_AVR(13, 128, C); _DEFPIN_AVR(14, 8, B); _DEFPIN_AVR(15, 2, B);
+_DEFPIN_AVR(16, 4, B); _DEFPIN_AVR(17, 1, B); _DEFPIN_AVR(18, 128, F); _DEFPIN_AVR(19, 64, F);
+_DEFPIN_AVR(20, 32, F); _DEFPIN_AVR(21, 16, F); _DEFPIN_AVR(22, 2, F); _DEFPIN_AVR(23, 0, F);
#define SPI_DATA 16
#define SPI_CLOCK 15
@@ -196,4 +203,6 @@ _DEFPIN_AVR(20, 32, F); _DEFPIN_AVR(21, 16, F); _DEFPIN_AVR(22, 2, F); _DEFPIN_A
#endif
-#endif
+#endif // FORCE_SOFTWARE_PINS
+
+#endif // __INC_FASTPIN_AVR_H
diff --git a/fastspi_avr.h b/platforms/avr/fastspi_avr.h
index 6470f37d..6470f37d 100644
--- a/fastspi_avr.h
+++ b/platforms/avr/fastspi_avr.h
diff --git a/platforms/avr/led_sysdefs_avr.h b/platforms/avr/led_sysdefs_avr.h
new file mode 100644
index 00000000..19cfabee
--- /dev/null
+++ b/platforms/avr/led_sysdefs_avr.h
@@ -0,0 +1,21 @@
+#ifndef __INC_LED_SYSDEFS_AVR_H
+#define __INC_LED_SYSDEFS_AVR_H
+
+#define FASTLED_AVR
+#define FASTLED_ACCURATE_CLOCK
+
+#ifndef INTERRUPT_THRESHOLD
+#define INTERRUPT_THRESHOLD 2
+#endif
+
+#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
+
+
+#endif
diff --git a/preview_changes.txt b/preview_changes.txt
index 84407524..e69dd3cb 100644
--- a/preview_changes.txt
+++ b/preview_changes.txt
@@ -6,4 +6,4 @@ FastLED 3.1 preview changes:
* interrupt friendly code on teensy 3/3.1
* interrupt friendly code on AVR
* interrupt friendly code on the due
-
+* code re-org for future wider platform support
diff --git a/wiring.cpp b/wiring.cpp
index d9efc8f6..7d62e4bf 100644
--- a/wiring.cpp
+++ b/wiring.cpp
@@ -1,6 +1,7 @@
#include "FastLED.h"
-#ifdef FASTLED_AVR
+
+#if defined(FASTLED_AVR) && !defined(TEENSYDUINO) && !defined(LIB8_ATTINY)
extern "C" {
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.