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:
-rw-r--r--fastpin_arm_sam.h3
-rw-r--r--fastspi.h6
-rw-r--r--fastspi_arm_k20.h3
-rw-r--r--fastspi_arm_sam.h162
-rw-r--r--fastspi_ref.h98
-rw-r--r--preview_changes.txt8
6 files changed, 257 insertions, 23 deletions
diff --git a/fastpin_arm_sam.h b/fastpin_arm_sam.h
index 9aad9425..164754c8 100644
--- a/fastpin_arm_sam.h
+++ b/fastpin_arm_sam.h
@@ -96,6 +96,9 @@ _DEFPIN_DUE(68, 1, A); _DEFPIN_DUE(69, 0, A); _DEFPIN_DUE(70, 17, A); _DEFPIN_DU
_DEFPIN_DUE(72, 30, C); _DEFPIN_DUE(73, 21, A); _DEFPIN_DUE(74, 25, A); _DEFPIN_DUE(75, 26, A);
_DEFPIN_DUE(76, 27, A); _DEFPIN_DUE(77, 28, A); _DEFPIN_DUE(78, 23, B);
+#define SPI_DATA 75
+#define SPI_CLOCK 76
+#define ARM_HARDWARE_SPI
#define HAS_HARDWARE_PIN_SUPPORT
#endif
diff --git a/fastspi.h b/fastspi.h
index 831bae34..68d74a99 100644
--- a/fastspi.h
+++ b/fastspi.h
@@ -43,6 +43,7 @@ public:
// 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"
@@ -67,6 +68,11 @@ class SoftwareSPIOutput : public AVRSoftwareSPIOutput<_DATA_PIN, _CLOCK_PIN, _SP
template<uint8_t SPI_SPEED>
class SPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> : public ARMHardwareSPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> {};
+#elif defined(__SAM3X8E__)
+
+template<uint8_t SPI_SPEED>
+class SPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> : public SAMHardwareSPIOutput<SPI_DATA, SPI_CLOCK, SPI_SPEED> {};
+
#else
template<uint8_t SPI_SPEED>
diff --git a/fastspi_arm_k20.h b/fastspi_arm_k20.h
index 706755d2..906e1a27 100644
--- a/fastspi_arm_k20.h
+++ b/fastspi_arm_k20.h
@@ -247,7 +247,7 @@ public:
template <uint8_t BIT> inline static void writeBit(uint8_t b) {
uint32_t ctar1_save = SPI0_CTAR1;
- // Clear out the FMSZ bits, reset them for 9 bits transferd for the start bit
+ // Clear out the FMSZ bits, reset them for 1 bit transferd for the start bit
uint32_t ctar1 = (ctar1_save & (~SPI_CTAR_FMSZ(15))) | SPI_CTAR_FMSZ(0);
update_ctar1(ctar1);
@@ -278,6 +278,7 @@ public:
setSPIRate();
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++));
}
diff --git a/fastspi_arm_sam.h b/fastspi_arm_sam.h
index 9b58049d..e9d822c1 100644
--- a/fastspi_arm_sam.h
+++ b/fastspi_arm_sam.h
@@ -1,60 +1,184 @@
#ifndef __INC_FASTSPI_ARM_SAM_H
#define __INC_FASTSPI_ARM_SAM_H
+#if defined(__SAM3X8E__)
+#define m_SPI ((Spi*)SPI0)
+
template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER>
class SAMHardwareSPIOutput {
+ Selectable *m_pSelect;
+
+ static inline void waitForEmpty() { while ((m_SPI->SPI_SR & SPI_SR_TDRE) == 0); }
+
+ void enableConfig() { m_SPI->SPI_WPMR &= ~SPI_WPMR_WPEN; }
+ void disableConfig() { m_SPI->SPI_WPMR |= SPI_WPMR_WPEN; }
+
+ void enableSPI() { m_SPI->SPI_CR |= SPI_CR_SPIEN; }
+ void disableSPI() { m_SPI->SPI_CR &= ~SPI_CR_SPIEN; }
+
+ void readyTransferBits(register byte bits) {
+ bits -= 8;
+ // don't change the number of transfer bits while data is still being transferred from TDR to the shift register
+ waitForEmpty();
+ m_SPI->SPI_CSR[0] = (bits << SPI_CSR_BITS_Pos) | SPI_CSR_SCBR(_SPI_CLOCK_DIVIDER);
+ }
+
+ template<int BITS> static inline void writeBits(uint16_t w) {
+ waitForEmpty();
+ m_SPI->SPI_CSR[0] = (BITS << SPI_CSR_BITS_Pos) | SPI_CSR_SCBR(_SPI_CLOCK_DIVIDER);
+ m_SPI->SPI_TDR = w;
+ }
public:
- SAMHardwareSPIOutput() { /* TODO */ }
- SAMHArdwareSPIOutput(Selectable *pSelect) { /* TODO */ }
+ SAMHardwareSPIOutput() { m_pSelect = NULL; }
+ SAMHardwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; }
// set the object representing the selectable
void setSelect(Selectable *pSelect) { /* TODO */ }
// initialize the SPI subssytem
- void init() { /* TODO */ }
+ void init() {
+ // m_SPI = SPI0;
+
+ // set the output pins
+ FastPin<_DATA_PIN>::setOutput();
+ FastPin<_CLOCK_PIN>::setOutput();
+ release();
+
+ // Configure the SPI clock, divider between 1-255
+ // SCBR = _SPI_CLOCK_DIVIDER
+
+ // Enable writes
+ enableConfig();
+
+ // Configure SPI as master, enable
+ enableSPI();
+
+ // Only bit in MR we want on is master, everything is left to 0, see commented out psuedocode
+ m_SPI->SPI_MR = SPI_MR_MSTR;
+ // SPI_MR.MSTR = 1; set master
+ // SPI_MR.PS = 0 fixed peripheral select
+ // SPI_MR.PCSDEC = 0 direct connect CS decode
+ // SPI_MR.PCS = 0 device 0
+ // SPI_MR.DLYBCS = 0; 0 delay between chip selects
+
+ // set inter-transfer delay to 0
+ // DLYBCT = 0;
+ // DLYBS = 0;
+
+ // CSR items
+ // SPI_CSR0 = 0;
+ // SPI_CSR0.BITS = 0 (8bit), 1 (9bit), 8 (16bit)
+ // SPI_CSR0.SCBR = _SPI_CLOCK_DIVIDER
+ // SPI_CSR0.DLYBS = 0, SPI_CSR0.DLYBCT = 0
+
+ }
// latch the CS select
- void select() { /* TODO */ }
+ void inline select() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->select(); } }
// release the CS select
- void release() { /* TODO */ }
+ void inline release() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->release(); } }
// wait until all queued up data has been written
- void waitFully();
+ void waitFully() { while((m_SPI->SPI_SR & SPI_SR_TXEMPTY) == 0); }
// write a byte out via SPI (returns immediately on writing register)
- void writeByte(uint8_t b) { /* TODO */ }
+ static void writeByte(uint8_t b) {
+ writeBits<8>(b);
+ }
+
// write a word out via SPI (returns immediately on writing register)
- void writeWord(uint16_t w) { /* TODO */ }
+ static void writeWord(uint16_t w) {
+ writeBits<16>(w);
+ }
// A raw set of writing byte values, assumes setup/init/waiting done elsewhere
- void writeBytesValueRaw(uint8_t value, int len) { /* TODO */ }
+ 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) { /* TODO */ }
+ void writeBytesValue(uint8_t value, int len) {
+ select(); writeBytesValueRaw(value, len); release();
+ }
+
+ 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 raw block of data out, including select, release, and waiting
- void writeBytes(uint8_t *data, int len) { /* TODO */ }
+ 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) { /* TODO */ }
+ // not the most efficient mechanism in the world - but should be enough for sm16716 and friends
+ template <uint8_t BIT> inline void writeBit(uint8_t b) {
+ // need to wait for all exisiting data to go out the door, first
+ waitFully();
+ disableSPI();
+ if(b & (1 << BIT)) {
+ FastPin<_DATA_PIN>::hi();
+ } else {
+ FastPin<_DATA_PIN>::lo();
+ }
- template <uint8_t FLAGS, class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) { /* TODO*/ }
+ FastPin<_CLOCK_PIN>::hi();
+ FastPin<_CLOCK_PIN>::lo();
+ enableSPI();
+ }
+
+ // 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 writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ select();
+ uint8_t *end = data + len;
+
+ // Setup the pixel controller
+ PixelController<RGB_ORDER> pixels(data, scale, true, advance, skip);
+
+ while(data != end) {
+ if(FLAGS & FLAG_START_BIT) {
+ writeBit<0>(1);
+ writeByte(D::adjust(pixels.loadAndScale0()));
+ writeByte(D::adjust(pixels.loadAndScale1()));
+ writeByte(D::adjust(pixels.loadAndScale2()));
+ } else {
+ writeByte(D::adjust(pixels.loadAndScale0()));
+ writeByte(D::adjust(pixels.loadAndScale1()));
+ writeByte(D::adjust(pixels.loadAndScale2()));
+ }
+
+ pixels.advanceData();
+ pixels.stepDithering();
+ data += (3+skip);
+ }
+ D::postBlock(len);
+ release();
+ }
// template instantiations for writeBytes 3
- template <uint8_t FLAGS, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) {
- writeBytes3<SKIP, DATA_NOP, RGB_ORDER>(data, len, scale, advance, skip);
+ template <uint8_t FLAGS, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<FLAGS, DATA_NOP, RGB_ORDER>(data, len, scale, advance, skip);
}
- template <class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) {
+ template <class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
writeBytes3<0, D, RGB_ORDER>(data, len, scale, advance, skip);
}
- template <EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) {
+ template <EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
writeBytes3<0, DATA_NOP, RGB_ORDER>(data, len, scale, advance, skip);
}
- void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) {
+ void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
writeBytes3<0, DATA_NOP, RGB>(data, len, scale, advance, skip);
+ }
};
+#endif
+
#endif \ No newline at end of file
diff --git a/fastspi_ref.h b/fastspi_ref.h
new file mode 100644
index 00000000..709bec34
--- /dev/null
+++ b/fastspi_ref.h
@@ -0,0 +1,98 @@
+#ifndef __INC_FASTSPI_ARM_SAM_H
+#define __INC_FASTSPI_ARM_SAM_H
+
+// A skeletal implementation of hardware SPI support. Fill in the necessary code for init, waiting, and writing. The rest of
+// the method implementations should provide a starting point, even if not hte most efficient to start with
+template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER>
+class REFHardwareSPIOutput {
+ Selectable *m_pSelect;
+public:
+ SAMHardwareSPIOutput() { m_pSelect = NULL; }
+ SAMHArdwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; }
+
+ // set the object representing the selectable
+ void setSelect(Selectable *pSelect) { /* TODO */ }
+
+ // initialize the SPI subssytem
+ void init() { /* TODO */ }
+
+ // latch the CS select
+ void inline select() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->select(); } }
+
+ // release the CS select
+ void inline release() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->release(); } }
+
+ // 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) { /* TODO */ }
+
+ // write a word out via SPI (returns immediately on writing register)
+ static void writeWord(uint16_t w) { /* TODO */ }
+
+ // 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) { /* TODO */ }
+
+ // 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 writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ select();
+ while(data != end) {
+ 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();
+ data += (3+skip);
+ }
+ D::postBlock(len);
+ release();
+ }
+
+ // template instantiations for writeBytes 3
+ template <uint8_t FLAGS, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<FLAGS, DATA_NOP, RGB_ORDER>(data, len, scale, advance, skip);
+ }
+ template <class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<0, D, RGB_ORDER>(data, len, scale, advance, skip);
+ }
+ template <EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<0, DATA_NOP, RGB_ORDER>(data, len, scale, advance, skip);
+ }
+ void writeBytes3(register uint8_t *data, int len, register CRGB scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<0, DATA_NOP, RGB>(data, len, scale, advance, skip);
+
+};
+
+#endif \ No newline at end of file
diff --git a/preview_changes.txt b/preview_changes.txt
index 60562fef..2866abbd 100644
--- a/preview_changes.txt
+++ b/preview_changes.txt
@@ -1,7 +1,9 @@
* ALL UNTESTED, USE AT YOUR OWN RISK!
-* Preliminary teensy 3.1 support
-* Preliminary due support (no hardware SPI, yet)
-* Preliminary P9813 (aka Cool Neon Total Control Lighting support)
+* RGB based scaling, allow for color balancing
+* (The moon) dithering support
+* Teensy 3.1 support
+* Due support
+* P9813 (aka Cool Neon Total Control Lighting support)
* Preliminary 2-way ws2812 support
* Preliminary n-way clockless support on due
* Preliminary TM1829 support (broken, don't use!)