Skip to content

Commit

Permalink
FastGPIO SPI : work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulZC committed Apr 7, 2020
1 parent 7972c88 commit 02e3091
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 11 deletions.
7 changes: 6 additions & 1 deletion fastspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint32_t SPI_SPEED>
class SPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> : public APOLLO3HardwareSPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> {};

#elif defined(FASTLED_TEENSY3) && defined(ARM_HARDWARE_SPI)

template<uint32_t SPI_SPEED>
class SPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> : public ARMHardwareSPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED, 0x4002C000> {};
Expand Down
54 changes: 54 additions & 0 deletions platforms/apollo3/clockless_apollo3.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,61 @@ FASTLED_NAMESPACE_BEGIN

#if defined(FASTLED_APOLLO3)

/*
#define FASTLED_HAS_CLOCKLESS 1
template <uint8_t 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 FastPinBB<DATA_PIN>::port_ptr_t data_ptr_t;
typedef typename FastPinBB<DATA_PIN>::port_t data_t;
// data_t mPinMask;
// data_ptr_t mPort;
CMinWait<WAIT_TIME> mWait;
public:
virtual void init() {
FastPinBB<DATA_PIN>::setOutput();
mPinMask = FastPinBB<DATA_PIN>::mask();
mPort = FastPinBB<DATA_PIN>::port();
}
virtual uint16_t getMaxRefreshRate() const { return 400; }
virtual void showPixels(PixelController<RGB_ORDER> & 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<RGB_ORDER> 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<DATA_PIN>::port_ptr_t portBase = FastPin<DATA_PIN>::port();
return showLedData<8,4,T1,T2,T3,RGB_ORDER, WAIT_TIME>(portBase, FastPin<DATA_PIN>::mask(), pixels.mData, pixels.mLen, &data);
}
};
*/

#endif

Expand Down
4 changes: 2 additions & 2 deletions platforms/apollo3/fastled_apollo3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions platforms/apollo3/fastpin_apollo3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
113 changes: 107 additions & 6 deletions platforms/apollo3/fastspi_apollo3.h
Original file line number Diff line number Diff line change
@@ -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 <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint32_t SPI_CLOCK_DIVIDER>
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 <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 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 <uint8_t FLAGS, class D, EOrder RGB_ORDER> void writePixels(PixelController<RGB_ORDER> 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

0 comments on commit 02e3091

Please sign in to comment.