diff --git a/fastspi.h b/fastspi.h index 38e8eabf07..2bf5d6d0ff 100644 --- a/fastspi.h +++ b/fastspi.h @@ -51,7 +51,12 @@ class SPIOutput : public NRF52SPIOutput<_DATA_PIN, _CLOCK_PIN, _SPI_CLOCK_DIVIDE #if defined(SPI_DATA) && defined(SPI_CLOCK) -#if defined(FASTLED_TEENSY3) && defined(ARM_HARDWARE_SPI) +#if defined(FASTLED_APOLLO3) + +template +class SPIOutput : public APOLLO3HardwareSPIOutput {}; + +#elif defined(FASTLED_TEENSY3) && defined(ARM_HARDWARE_SPI) template class SPIOutput : public ARMHardwareSPIOutput {}; diff --git a/platforms/apollo3/clockless_apollo3.h b/platforms/apollo3/clockless_apollo3.h index 5ed0e27d60..7791056434 100644 --- a/platforms/apollo3/clockless_apollo3.h +++ b/platforms/apollo3/clockless_apollo3.h @@ -5,7 +5,61 @@ FASTLED_NAMESPACE_BEGIN #if defined(FASTLED_APOLLO3) +/* +#define FASTLED_HAS_CLOCKLESS 1 + +template +class ClocklessController : public CPixelLEDController { + typedef typename FastPinBB::port_ptr_t data_ptr_t; + typedef typename FastPinBB::port_t data_t; + +// data_t mPinMask; +// data_ptr_t mPort; + CMinWait mWait; +public: + virtual void init() { + FastPinBB::setOutput(); + mPinMask = FastPinBB::mask(); + mPort = FastPinBB::port(); + } + + virtual uint16_t getMaxRefreshRate() const { return 400; } + + virtual void showPixels(PixelController & pixels) { + mWait.wait(); + cli(); + if(!showRGBInternal(pixels)) { + sei(); delayMicroseconds(WAIT_TIME); cli(); + showRGBInternal(pixels); + } + sei(); + mWait.mark(); + } + + // 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. + static uint32_t showRGBInternal(PixelController pixels) { + struct M0ClocklessData data; + data.d[0] = pixels.d[0]; + data.d[1] = pixels.d[1]; + data.d[2] = pixels.d[2]; + data.s[0] = pixels.mScale[0]; + data.s[1] = pixels.mScale[1]; + data.s[2] = pixels.mScale[2]; + data.e[0] = pixels.e[0]; + data.e[1] = pixels.e[1]; + data.e[2] = pixels.e[2]; + data.adj = pixels.mAdvance; + + typename FastPin::port_ptr_t portBase = FastPin::port(); + return showLedData<8,4,T1,T2,T3,RGB_ORDER, WAIT_TIME>(portBase, FastPin::mask(), pixels.mData, pixels.mLen, &data); + } + + +}; + +*/ #endif diff --git a/platforms/apollo3/fastled_apollo3.h b/platforms/apollo3/fastled_apollo3.h index 47f68ed459..4c727dd0c5 100644 --- a/platforms/apollo3/fastled_apollo3.h +++ b/platforms/apollo3/fastled_apollo3.h @@ -2,7 +2,7 @@ #define __INC_FASTLED_APOLLO3_H #include "fastpin_apollo3.h" -//#include "fastspi_apollo3.h" -//#include "clockless_apollo3.h" +#include "fastspi_apollo3.h" +#include "clockless_apollo3.h" #endif diff --git a/platforms/apollo3/fastpin_apollo3.h b/platforms/apollo3/fastpin_apollo3.h index e901d0e4ad..63b4b7626e 100644 --- a/platforms/apollo3/fastpin_apollo3.h +++ b/platforms/apollo3/fastpin_apollo3.h @@ -133,8 +133,8 @@ _FL_DEFPIN(35); _FL_DEFPIN(36); _FL_DEFPIN(37); _FL_DEFPIN(38); _FL_DEFPIN(39); _FL_DEFPIN(40); _FL_DEFPIN(41); _FL_DEFPIN(42); _FL_DEFPIN(43); _FL_DEFPIN(44); _FL_DEFPIN(45); _FL_DEFPIN(47); _FL_DEFPIN(48); _FL_DEFPIN(49); -//#define SPI_DATA MOSI -//#define SPI_CLOCK SCK +#define SPI_DATA MOSI +#define SPI_CLOCK SCK #define HAS_HARDWARE_PIN_SUPPORT 1 diff --git a/platforms/apollo3/fastspi_apollo3.h b/platforms/apollo3/fastspi_apollo3.h index 97b5b82536..12ca9e0680 100644 --- a/platforms/apollo3/fastspi_apollo3.h +++ b/platforms/apollo3/fastspi_apollo3.h @@ -1,18 +1,119 @@ #ifndef __INC_FASTSPI_APOLLO3_H #define __INC_FASTSPI_APOLLO3_H +//#include "FastLED.h" + FASTLED_NAMESPACE_BEGIN -#if defined(AVR_HARDWARE_SPI) +template +class APOLLO3HardwareSPIOutput { + Selectable *m_pSelect; +public: + APOLLO3HardwareSPIOutput() { m_pSelect = NULL; } + APOLLO3HArdwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; } -#else - -// #define FASTLED_FORCE_SOFTWARE_SPI + // set the object representing the selectable + void setSelect(Selectable *pSelect) { /* TODO */ } -#endif + // initialize the SPI subssytem + void init() { + pinMode(_DATA_PIN, OUTPUT); am_hal_gpio_fastgpio_enable(_DATA_PIN); + pinMode(_CLOCK_PIN, OUTPUT); am_hal_gpio_fastgpio_enable(_CLOCK_PIN); + //enableBurstMode(); //Optional. Go to 96MHz. Roughly doubles the speed of shiftOut and fastShiftOut + enableFastShift(_DATA_PIN, _CLOCK_PIN); + } + + // latch the CS select + void inline select() { /* TODO */ } + + // release the CS select + void inline release() { /* TODO */ } + + // wait until all queued up data has been written + static void waitFully() { /* TODO */ } + + // write a byte out via SPI (returns immediately on writing register) + static void writeByte(uint8_t b) { + fastShiftOut(_DATA_PIN, _CLOCK_PIN, MSBFIRST, b); + } + + // write a word out via SPI (returns immediately on writing register) + static void writeWord(uint16_t w) { + writeByte((uint8_t)((w >> 8) && 0xff)); + writeByte((uint8_t)(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--) { writeByte(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 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, len); } + + // write a single bit out, which bit from the passed in byte is determined by template parameter + template inline static void writeBit(uint8_t b) { + waitFully(); + if(b & (1 << BIT)) { + FastPin<_DATA_PIN>::hi(); + } else { + FastPin<_DATA_PIN>::lo(); + } + + FastPin<_CLOCK_PIN>::hi(); + FastPin<_CLOCK_PIN>::lo(); + } + + // 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 void writePixels(PixelController pixels) { + select(); + + int len = pixels.mLen; // unused? + + if(FLAGS & FLAG_START_BIT) { + while(pixels.has(1)) { + writeBit<0>(1); + writeByte(D::adjust(pixels.loadAndScale0())); + writeByte(D::adjust(pixels.loadAndScale1())); + writeByte(D::adjust(pixels.loadAndScale2())); + pixels.advanceData(); + pixels.stepDithering(); + } + } else { + while(pixels.has(1)) { + writeByte(D::adjust(pixels.loadAndScale0())); + writeByte(D::adjust(pixels.loadAndScale1())); + writeByte(D::adjust(pixels.loadAndScale2())); + pixels.advanceData(); + pixels.stepDithering(); + } + } + D::postBlock(len); + release(); + } -FASTLED_NAMESPACE_END; +}; +FASTLED_NAMESPACE_END #endif