First commit.

This commit is contained in:
2020-07-17 18:55:06 +02:00
commit b47a0ab935
247 changed files with 30192 additions and 0 deletions

View File

@ -0,0 +1,214 @@
#ifndef __INC_BLOCK_CLOCKLESS_ARM_MXRT1062_H
#define __INC_BLOCK_CLOCKLESS_ARM_MXRT1062_H
FASTLED_NAMESPACE_BEGIN
// Definition for a single channel clockless controller for the teensy4
// See clockless.h for detailed info on how the template parameters are used.
#if defined(FASTLED_TEENSY4)
#define __FL_T4_MASK ((1<<(LANES))-1)
template <uint8_t LANES, int FIRST_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50>
class FlexibleInlineBlockClocklessController : public CPixelLEDController<RGB_ORDER, LANES, __FL_T4_MASK> {
uint8_t m_bitOffsets[16];
uint8_t m_nActualLanes;
uint8_t m_nLowBit;
uint8_t m_nHighBit;
uint32_t m_nWriteMask;
uint8_t m_nOutBlocks;
uint32_t m_offsets[3];
CMinWait<WAIT_TIME> mWait;
public:
virtual int size() { return CLEDController::size() * m_nActualLanes; }
// For each pin, if we've hit our lane count, break, otherwise set the pin to output,
// store the bit offset in our offset array, add this pin to the write mask, and if this
// pin ends a block sequence, then break out of the switch as well
#define _BLOCK_PIN(P) case P: { \
if(m_nActualLanes == LANES) break; \
FastPin<P>::setOutput(); \
m_bitOffsets[m_nActualLanes++] = FastPin<P>::pinbit(); \
m_nWriteMask |= FastPin<P>::mask(); \
if( P == 27 || P == 7 || P == 30) break; \
}
virtual void init() {
// pre-initialize
memset(m_bitOffsets,0,16);
m_nActualLanes = 0;
m_nLowBit = 33;
m_nHighBit = 0;
m_nWriteMask = 0;
// setup the bits and data tracking for parallel output
switch(FIRST_PIN) {
// GPIO6 block output
_BLOCK_PIN( 1);
_BLOCK_PIN( 0);
_BLOCK_PIN(24);
_BLOCK_PIN(25);
_BLOCK_PIN(19);
_BLOCK_PIN(18);
_BLOCK_PIN(14);
_BLOCK_PIN(15);
_BLOCK_PIN(17);
_BLOCK_PIN(16);
_BLOCK_PIN(22);
_BLOCK_PIN(23);
_BLOCK_PIN(20);
_BLOCK_PIN(21);
_BLOCK_PIN(26);
_BLOCK_PIN(27);
// GPIO7 block output
_BLOCK_PIN(10);
_BLOCK_PIN(12);
_BLOCK_PIN(11);
_BLOCK_PIN(13);
_BLOCK_PIN( 6);
_BLOCK_PIN( 9);
_BLOCK_PIN(32);
_BLOCK_PIN( 8);
_BLOCK_PIN( 7);
// GPIO 37 block output
_BLOCK_PIN(37);
_BLOCK_PIN(36);
_BLOCK_PIN(35);
_BLOCK_PIN(34);
_BLOCK_PIN(39);
_BLOCK_PIN(38);
_BLOCK_PIN(28);
_BLOCK_PIN(31);
_BLOCK_PIN(30);
}
for(int i = 0; i < m_nActualLanes; i++) {
if(m_bitOffsets[i] < m_nLowBit) { m_nLowBit = m_bitOffsets[i]; }
if(m_bitOffsets[i] > m_nHighBit) { m_nHighBit = m_bitOffsets[i]; }
}
m_nOutBlocks = (m_nHighBit + 8)/8;
}
virtual void showPixels(PixelController<RGB_ORDER, LANES, __FL_T4_MASK> & pixels) {
mWait.wait();
#if FASTLED_ALLOW_INTERRUPTS == 0
uint32_t clocks = showRGBInternal(pixels);
// Adjust the timer
long microsTaken = CLKS_TO_MICROS(clocks);
MS_COUNTER += (1 + (microsTaken / 1000));
#else
showRGBInternal(pixels);
#endif
mWait.mark();
}
typedef union {
uint8_t bytes[32];
uint8_t bg[4][8];
uint16_t shorts[16];
uint32_t raw[8];
} _outlines;
template<int BITS,int PX> __attribute__ ((always_inline)) inline void writeBits(register uint32_t & next_mark, register _outlines & b, PixelController<RGB_ORDER, LANES, __FL_T4_MASK> &pixels) {
_outlines b2;
transpose8x1(b.bg[3], b2.bg[3]);
transpose8x1(b.bg[2], b2.bg[2]);
transpose8x1(b.bg[1], b2.bg[1]);
transpose8x1(b.bg[0], b2.bg[0]);
register uint8_t d = pixels.template getd<PX>(pixels);
register uint8_t scale = pixels.template getscale<PX>(pixels);
int x = 0;
for(uint32_t i = 8; i > 0;) {
i--;
while(ARM_DWT_CYCCNT < next_mark);
*FastPin<FIRST_PIN>::sport() = m_nWriteMask;
next_mark = ARM_DWT_CYCCNT + m_offsets[0];
uint32_t out = (b2.bg[3][i] << 24) | (b2.bg[2][i] << 16) | (b2.bg[1][i] << 8) | b2.bg[0][i];
out = ((~out) & m_nWriteMask);
while((next_mark - ARM_DWT_CYCCNT) > m_offsets[1]);
*FastPin<FIRST_PIN>::cport() = out;
out = m_nWriteMask;
while((next_mark - ARM_DWT_CYCCNT) > m_offsets[2]);
*FastPin<FIRST_PIN>::cport() = out;
// Read and store up to two bytes
if (x < m_nActualLanes) {
b.bytes[m_bitOffsets[x]] = pixels.template loadAndScale<PX>(pixels,x,d,scale);
x++;
if (x < m_nActualLanes) {
b.bytes[m_bitOffsets[x]] = pixels.template loadAndScale<PX>(pixels,x,d,scale);
x++;
}
}
}
}
uint32_t showRGBInternal(PixelController<RGB_ORDER,LANES, __FL_T4_MASK> &allpixels) {
allpixels.preStepFirstByteDithering();
_outlines b0;
uint32_t start = ARM_DWT_CYCCNT;
for(int i = 0; i < m_nActualLanes; i++) {
b0.bytes[m_bitOffsets[i]] = allpixels.loadAndScale0(i);
}
cli();
m_offsets[0] = _FASTLED_NS_TO_DWT(T1+T2+T3);
m_offsets[1] = _FASTLED_NS_TO_DWT(T2+T3);
m_offsets[2] = _FASTLED_NS_TO_DWT(T3);
uint32_t wait_off = _FASTLED_NS_TO_DWT((WAIT_TIME-INTERRUPT_THRESHOLD));
uint32_t next_mark = ARM_DWT_CYCCNT + m_offsets[0];
while(allpixels.has(1)) {
allpixels.stepDithering();
#if (FASTLED_ALLOW_INTERRUPTS == 1)
cli();
// if interrupts took longer than 45µs, punt on the current frame
if(ARM_DWT_CYCCNT > next_mark) {
if((ARM_DWT_CYCCNT-next_mark) > wait_off) { sei(); return ARM_DWT_CYCCNT - start; }
}
#endif
// Write first byte, read next byte
writeBits<8+XTRA0,1>(next_mark, b0, allpixels);
// Write second byte, read 3rd byte
writeBits<8+XTRA0,2>(next_mark, b0, allpixels);
allpixels.advanceData();
// Write third byte
writeBits<8+XTRA0,0>(next_mark, b0, allpixels);
#if (FASTLED_ALLOW_INTERRUPTS == 1)
sei();
#endif
}
sei();
return ARM_DWT_CYCCNT - start;
}
};
template<template<uint8_t DATA_PIN, EOrder RGB_ORDER> class CHIPSET, uint8_t DATA_PIN, int NUM_LANES, EOrder RGB_ORDER=GRB>
class __FIBCC : public FlexibleInlineBlockClocklessController<NUM_LANES,DATA_PIN,CHIPSET<DATA_PIN,RGB_ORDER>::__T1(),CHIPSET<DATA_PIN,RGB_ORDER>::__T2(),CHIPSET<DATA_PIN,RGB_ORDER>::__T3(),RGB_ORDER,CHIPSET<DATA_PIN,RGB_ORDER>::__XTRA0(),CHIPSET<DATA_PIN,RGB_ORDER>::__FLIP(),CHIPSET<DATA_PIN,RGB_ORDER>::__WAIT_TIME()> {};
#define __FASTLED_HAS_FIBCC 1
#endif //defined(FASTLED_TEENSY4)
FASTLED_NAMESPACE_END
#endif

View File

@ -0,0 +1,128 @@
#ifndef __INC_CLOCKLESS_ARM_MXRT1062_H
#define __INC_CLOCKLESS_ARM_MXRT1062_H
FASTLED_NAMESPACE_BEGIN
// Definition for a single channel clockless controller for the teensy4
// See clockless.h for detailed info on how the template parameters are used.
#if defined(FASTLED_TEENSY4)
#define FASTLED_HAS_CLOCKLESS 1
#define _FASTLED_NS_TO_DWT(_NS) (((F_CPU_ACTUAL>>16)*(_NS)) / (1000000000UL>>16))
template <int DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50>
class ClocklessController : public CPixelLEDController<RGB_ORDER> {
typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
typedef typename FastPin<DATA_PIN>::port_t data_t;
data_t mPinMask;
data_ptr_t mPort;
CMinWait<WAIT_TIME> mWait;
uint32_t off[3];
public:
static constexpr int __DATA_PIN() { return DATA_PIN; }
static constexpr int __T1() { return T1; }
static constexpr int __T2() { return T2; }
static constexpr int __T3() { return T3; }
static constexpr EOrder __RGB_ORDER() { return RGB_ORDER; }
static constexpr int __XTRA0() { return XTRA0; }
static constexpr bool __FLIP() { return FLIP; }
static constexpr int __WAIT_TIME() { return WAIT_TIME; }
virtual void init() {
FastPin<DATA_PIN>::setOutput();
mPinMask = FastPin<DATA_PIN>::mask();
mPort = FastPin<DATA_PIN>::port();
FastPin<DATA_PIN>::lo();
}
protected:
virtual void showPixels(PixelController<RGB_ORDER> & pixels) {
mWait.wait();
if(!showRGBInternal(pixels)) {
sei(); delayMicroseconds(WAIT_TIME); cli();
showRGBInternal(pixels);
}
mWait.mark();
}
template<int BITS> __attribute__ ((always_inline)) inline void writeBits(register uint32_t & next_mark, register uint32_t & b) {
for(register uint32_t i = BITS-1; i > 0; i--) {
while(ARM_DWT_CYCCNT < next_mark);
next_mark = ARM_DWT_CYCCNT + off[0];
FastPin<DATA_PIN>::hi();
if(b&0x80) {
while((next_mark - ARM_DWT_CYCCNT) > off[1]);
FastPin<DATA_PIN>::lo();
} else {
while((next_mark - ARM_DWT_CYCCNT) > off[2]);
FastPin<DATA_PIN>::lo();
}
b <<= 1;
}
while(ARM_DWT_CYCCNT < next_mark);
next_mark = ARM_DWT_CYCCNT + off[1];
FastPin<DATA_PIN>::hi();
if(b&0x80) {
while((next_mark - ARM_DWT_CYCCNT) > off[2]);
FastPin<DATA_PIN>::lo();
} else {
while((next_mark - ARM_DWT_CYCCNT) > off[2]);
FastPin<DATA_PIN>::lo();
}
}
uint32_t showRGBInternal(PixelController<RGB_ORDER> pixels) {
uint32_t start = ARM_DWT_CYCCNT;
// Setup the pixel controller and load/scale the first byte
pixels.preStepFirstByteDithering();
register uint32_t b = pixels.loadAndScale0();
cli();
off[0] = _FASTLED_NS_TO_DWT(T1+T2+T3);
off[1] = _FASTLED_NS_TO_DWT(T2+T3);
off[2] = _FASTLED_NS_TO_DWT(T3);
uint32_t wait_off = _FASTLED_NS_TO_DWT((WAIT_TIME-INTERRUPT_THRESHOLD));
uint32_t next_mark = ARM_DWT_CYCCNT + off[0];
while(pixels.has(1)) {
pixels.stepDithering();
#if (FASTLED_ALLOW_INTERRUPTS == 1)
cli();
// if interrupts took longer than 45µs, punt on the current frame
if(ARM_DWT_CYCCNT > next_mark) {
if((ARM_DWT_CYCCNT-next_mark) > wait_off) { sei(); return ARM_DWT_CYCCNT - start; }
}
#endif
// Write first byte, read next byte
writeBits<8+XTRA0>(next_mark, b);
b = pixels.loadAndScale1();
// Write second byte, read 3rd byte
writeBits<8+XTRA0>(next_mark, b);
b = pixels.loadAndScale2();
// Write third byte, read 1st byte of next pixel
writeBits<8+XTRA0>(next_mark, b);
b = pixels.advanceAndLoadAndScale0();
#if (FASTLED_ALLOW_INTERRUPTS == 1)
sei();
#endif
};
sei();
return ARM_DWT_CYCCNT - start;
}
};
#endif
FASTLED_NAMESPACE_END
#endif

View File

@ -0,0 +1,12 @@
#ifndef __INC_FASTLED_ARM_MXRT1062_H
#define __INC_FASTLED_ARM_MXRT1062_H
#include "fastpin_arm_mxrt1062.h"
#include "fastspi_arm_mxrt1062.h"
#include "../k20/octows2811_controller.h"
#include "../k20/ws2812serial_controller.h"
#include "../k20/smartmatrix_t3.h"
#include "clockless_arm_mxrt1062.h"
#include "block_clockless_arm_mxrt1062.h"
#endif

View File

@ -0,0 +1,91 @@
#ifndef __FASTPIN_ARM_MXRT1062_H
#define __FASTPIN_ARM_MXRT1062_H
FASTLED_NAMESPACE_BEGIN
#if defined(FASTLED_FORCE_SOFTWARE_PINS)
#warning "Software pin support forced, pin access will be slightly slower."
#define NO_HARDWARE_PIN_SUPPORT
#undef HAS_HARDWARE_PIN_SUPPORT
#else
/// Template definition for teensy 4.0 style ARM pins, providing direct access to the various GPIO registers. Note that this
/// uses the full port GPIO registers. It calls through to pinMode for setting input/output on pins
/// The registers are data output, set output, clear output, toggle output, input, and direction
template<uint8_t PIN, uint32_t _BIT, uint32_t _MASK, typename _GPIO_DR, typename _GPIO_DR_SET, typename _GPIO_DR_CLEAR, typename _GPIO_DR_TOGGLE> class _ARMPIN {
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)) { _GPIO_DR_SET::r() = _MASK; }
inline static void lo() __attribute__ ((always_inline)) { _GPIO_DR_CLEAR::r() = _MASK; }
inline static void set(register port_t val) __attribute__ ((always_inline)) { _GPIO_DR::r() = val; }
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
inline static void toggle() __attribute__ ((always_inline)) { _GPIO_DR_TOGGLE::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 _GPIO_DR::r() | _MASK; }
inline static port_t loval() __attribute__ ((always_inline)) { return _GPIO_DR::r() & ~_MASK; }
inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_GPIO_DR::r(); }
inline static port_ptr_t sport() __attribute__ ((always_inline)) { return &_GPIO_DR_SET::r(); }
inline static port_ptr_t cport() __attribute__ ((always_inline)) { return &_GPIO_DR_CLEAR::r(); }
inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; }
inline static uint32_t pinbit() __attribute__ ((always_inline)) { return _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; } };
#define _FL_IO(L) _RD32(GPIO ## L ## _DR); _RD32(GPIO ## L ## _DR_SET); _RD32(GPIO ## L ## _DR_CLEAR); _RD32(GPIO ## L ## _DR_TOGGLE); _FL_DEFINE_PORT(L, _R(GPIO ## L ## _DR));
// From the teensy core - it looks like there's the "default set" of port registers at GPIO1-5 - but then there
// are a mirrored set for GPIO1-4 at GPIO6-9, which in the teensy core is referred to as "fast" - while the pin definitiosn
// at https://forum.pjrc.com/threads/54711-Teensy-4-0-First-Beta-Test?p=193716&viewfull=1#post193716
// refer to GPIO1-4, we're going to use GPIO6-9 in the definitions below because the fast registers are what
// the teensy core is using internally
#define _FL_DEFPIN(PIN, BIT, L) template<> class FastPin<PIN> : public _ARMPIN<PIN, BIT, 1 << BIT, _R(GPIO ## L ## _DR), _R(GPIO ## L ## _DR_SET), _R(GPIO ## L ## _DR_CLEAR), _R(GPIO ## L ## _DR_TOGGLE)> {};
#if defined(FASTLED_TEENSY4) && defined(CORE_TEENSY)
_FL_IO(1); _FL_IO(2); _FL_IO(3); _FL_IO(4); _FL_IO(5);
_FL_IO(6); _FL_IO(7); _FL_IO(8); _FL_IO(9);
#define MAX_PIN 39
_FL_DEFPIN( 0, 3,6); _FL_DEFPIN( 1, 2,6); _FL_DEFPIN( 2, 4,9); _FL_DEFPIN( 3, 5,9);
_FL_DEFPIN( 4, 6,9); _FL_DEFPIN( 5, 8,9); _FL_DEFPIN( 6,10,7); _FL_DEFPIN( 7,17,7);
_FL_DEFPIN( 8,16,7); _FL_DEFPIN( 9,11,7); _FL_DEFPIN(10, 0,7); _FL_DEFPIN(11, 2,7);
_FL_DEFPIN(12, 1,7); _FL_DEFPIN(13, 3,7); _FL_DEFPIN(14,18,6); _FL_DEFPIN(15,19,6);
_FL_DEFPIN(16,23,6); _FL_DEFPIN(17,22,6); _FL_DEFPIN(18,17,6); _FL_DEFPIN(19,16,6);
_FL_DEFPIN(20,26,6); _FL_DEFPIN(21,27,6); _FL_DEFPIN(22,24,6); _FL_DEFPIN(23,25,6);
_FL_DEFPIN(24,12,6); _FL_DEFPIN(25,13,6); _FL_DEFPIN(26,30,6); _FL_DEFPIN(27,31,6);
_FL_DEFPIN(28,18,8); _FL_DEFPIN(29,31,9); _FL_DEFPIN(30,23,8); _FL_DEFPIN(31,22,8);
_FL_DEFPIN(32,12,7); _FL_DEFPIN(33, 7,9); _FL_DEFPIN(34,15,8); _FL_DEFPIN(35,14,8);
_FL_DEFPIN(36,13,8); _FL_DEFPIN(37,12,8); _FL_DEFPIN(38,17,8); _FL_DEFPIN(39,16,8);
#define HAS_HARDWARE_PIN_SUPPORT
#define ARM_HARDWARE_SPI
#define SPI_DATA 11
#define SPI_CLOCK 13
#define SPI1_DATA 26
#define SPI1_CLOCK 27
#define SPI2_DATA 35
#define SPI2_CLOCK 37
#endif // defined FASTLED_TEENSY4
#endif // FASTLED_FORCE_SOFTWARE_PINSs
FASTLED_NAMESPACE_END
#endif

View File

@ -0,0 +1,140 @@
#ifndef __INC_FASTSPI_ARM_MXRT1062_H
#define __INC_FASTSPI_ARM_MXRT1062_H
FASTLED_NAMESPACE_BEGIN
#if defined (FASTLED_TEENSY4) && defined(ARM_HARDWARE_SPI)
#include <SPI.h>
template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint32_t _SPI_CLOCK_RATE, SPIClass & _SPIObject, int _SPI_INDEX>
class Teesy4HardwareSPIOutput {
Selectable *m_pSelect;
uint32_t m_bitCount;
uint32_t m_bitData;
inline IMXRT_LPSPI_t & port() __attribute__((always_inline)) {
switch(_SPI_INDEX) {
case 0:
return IMXRT_LPSPI4_S;
case 1:
return IMXRT_LPSPI3_S;
case 2:
return IMXRT_LPSPI1_S;
}
}
public:
Teesy4HardwareSPIOutput() { m_pSelect = NULL; m_bitCount = 0;}
Teesy4HardwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; m_bitCount = 0;}
// set the object representing the selectable -- ignore for now
void setSelect(Selectable *pSelect) { /* TODO */ }
// initialize the SPI subssytem
void init() { _SPIObject.begin(); }
// latch the CS select
void inline select() __attribute__((always_inline)) {
// begin the SPI transaction
_SPIObject.beginTransaction(SPISettings(_SPI_CLOCK_RATE, MSBFIRST, SPI_MODE0));
if(m_pSelect != NULL) { m_pSelect->select(); }
}
// release the CS select
void inline release() __attribute__((always_inline)) {
if(m_pSelect != NULL) { m_pSelect->release(); }
_SPIObject.endTransaction();
}
// wait until all queued up data has been written
static void waitFully() { /* TODO */ }
// write a byte out via SPI (returns immediately on writing register) -
void inline writeByte(uint8_t b) __attribute__((always_inline)) {
if(m_bitCount == 0) {
_SPIObject.transfer(b);
} else {
// There's been a bit of data written, add that to the output as well
uint32_t outData = (m_bitData << 8) | b;
uint32_t tcr = port().TCR;
port().TCR = (tcr & 0xfffff000) | LPSPI_TCR_FRAMESZ((8+m_bitCount) - 1); // turn on 9 bit mode
port().TDR = outData; // output 9 bit data.
while ((port().RSR & LPSPI_RSR_RXEMPTY)) ; // wait while the RSR fifo is empty...
port().TCR = (tcr & 0xfffff000) | LPSPI_TCR_FRAMESZ((8) - 1); // turn back on 8 bit mode
port().RDR;
m_bitCount = 0;
}
}
// write a word out via SPI (returns immediately on writing register)
void inline writeWord(uint16_t w) __attribute__((always_inline)) {
writeByte(((w>>8) & 0xFF));
_SPIObject.transfer(w & 0xFF);
}
// A raw set of writing byte values, assumes setup/init/waiting done elsewhere
static void writeBytesValueRaw(uint8_t value, int len) {
while(len--) { _SPIObject.transfer(value); }
}
// A full cycle of writing a value for len bytes, including select, release, and waiting
void writeBytesValue(uint8_t value, int len) {
select(); writeBytesValueRaw(value, len); release();
}
// A full cycle of writing a value for len bytes, including select, release, and waiting
template <class D> void writeBytes(register uint8_t *data, int len) {
uint8_t *end = data + len;
select();
// could be optimized to write 16bit words out instead of 8bit bytes
while(data != end) {
writeByte(D::adjust(*data++));
}
D::postBlock(len);
waitFully();
release();
}
// A full cycle of writing a value for len bytes, including select, release, and waiting
void writeBytes(register uint8_t *data, int len) { writeBytes<DATA_NOP>(data, len); }
// write a single bit out, which bit from the passed in byte is determined by template parameter
template <uint8_t BIT> inline void writeBit(uint8_t b) {
m_bitData = (m_bitData<<1) | ((b&(1<<BIT)) != 0);
// If this is the 8th bit we've collected, just write it out raw
register uint32_t bc = m_bitCount;
bc = (bc + 1) & 0x07;
if (!bc) {
m_bitCount = 0;
_SPIObject.transfer(m_bitData);
}
m_bitCount = bc;
}
// write a block of uint8_ts out in groups of three. len is the total number of uint8_ts to write out. The template
// parameters indicate how many uint8_ts to skip at the beginning and/or end of each grouping
template <uint8_t FLAGS, class D, EOrder RGB_ORDER> void writePixels(PixelController<RGB_ORDER> pixels) {
select();
int len = pixels.mLen;
while(pixels.has(1)) {
if(FLAGS & FLAG_START_BIT) {
writeBit<0>(1);
}
writeByte(D::adjust(pixels.loadAndScale0()));
writeByte(D::adjust(pixels.loadAndScale1()));
writeByte(D::adjust(pixels.loadAndScale2()));
pixels.advanceData();
pixels.stepDithering();
}
D::postBlock(len);
release();
}
};
#endif
FASTLED_NAMESPACE_END
#endif

View File

@ -0,0 +1,43 @@
#ifndef __INC_LED_SYSDEFS_ARM_MXRT1062_H
#define __INC_LED_SYSDEFS_ARM_MXRT1062_H
#define FASTLED_TEENSY4
#define FASTLED_ARM
#ifndef INTERRUPT_THRESHOLD
#define INTERRUPT_THRESHOLD 1
#endif
// Default to allowing interrupts
#ifndef FASTLED_ALLOW_INTERRUPTS
#define FASTLED_ALLOW_INTERRUPTS 1
#endif
#if FASTLED_ALLOW_INTERRUPTS == 1
#define FASTLED_ACCURATE_CLOCK
#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 register types
#if defined(ARDUINO) // && ARDUINO < 150
typedef volatile uint32_t RoReg; /**< Read only 8-bit register (volatile const unsigned int) */
typedef volatile uint32_t RwReg; /**< Read-Write 8-bit register (volatile unsigned int) */
#endif
// extern volatile uint32_t systick_millis_count;
// # define MS_COUNTER systick_millis_count
// Teensy4 provides progmem
#ifndef FASTLED_USE_PROGMEM
#define FASTLED_USE_PROGMEM 1
#endif
#endif