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:
Diffstat (limited to 'fastspi_avr.h')
-rw-r--r--fastspi_avr.h168
1 files changed, 77 insertions, 91 deletions
diff --git a/fastspi_avr.h b/fastspi_avr.h
index af116cab..6470f37d 100644
--- a/fastspi_avr.h
+++ b/fastspi_avr.h
@@ -13,7 +13,7 @@
#if defined(AVR_HARDWARE_SPI)
#if defined(UBRR0)
template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER>
-class AVRUSARTSPIOutput {
+class AVRUSARTSPIOutput {
Selectable *m_pSelect;
public:
@@ -21,7 +21,7 @@ public:
AVRUSARTSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; }
void setSelect(Selectable *pSelect) { m_pSelect = pSelect; }
- void init() {
+ void init() {
UBRR0 = 0;
UCSR0A = 1<<TXC0;
@@ -35,23 +35,23 @@ public:
UBRR0 = 3; // 2 Mhz clock rate
}
- static void stop() {
+ static void stop() {
// TODO: stop the uart spi output
}
static void wait() __attribute__((always_inline)) { while(!(UCSR0A & (1<<UDRE0))); }
static void waitFully() __attribute__((always_inline)) { wait(); }
-
+
static void writeByteNoWait(uint8_t b) __attribute__((always_inline)) { UDR0 = b;}
static void writeBytePostWait(uint8_t b) __attribute__((always_inline)) { UDR0 = b; wait(); }
static void writeByte(uint8_t b) __attribute__((always_inline)) { wait(); UDR0 = b; }
static void writeWord(uint16_t w) __attribute__((always_inline)) { writeByte(w>>8); writeByte(w&0xFF); }
-
- template <uint8_t BIT> inline static void writeBit(uint8_t b) {
- if(b && (1 << BIT)) {
+
+ template <uint8_t BIT> inline static void writeBit(uint8_t b) {
+ if(b && (1 << BIT)) {
FastPin<_DATA_PIN>::hi();
- } else {
+ } else {
FastPin<_DATA_PIN>::lo();
}
@@ -60,68 +60,71 @@ public:
}
void select() { if(m_pSelect != NULL) { m_pSelect->select(); } } // FastPin<_SELECT_PIN>::hi(); }
- void release() {
+ void release() {
// wait for all transmissions to finish
while ((UCSR0A & (1 <<TXC0)) == 0) {}
- if(m_pSelect != NULL) { m_pSelect->release(); } // FastPin<_SELECT_PIN>::hi();
+ if(m_pSelect != NULL) { m_pSelect->release(); } // FastPin<_SELECT_PIN>::hi();
}
static void writeBytesValueRaw(uint8_t value, int len) {
while(len--) { writeByte(value); }
}
-
- void writeBytesValue(uint8_t value, int len) {
+
+ void writeBytesValue(uint8_t value, int len) {
select();
- while(len--) {
+ while(len--) {
writeByte(value);
}
release();
}
-
- // Write a block of n uint8_ts out
- template <class D> void writeBytes(register uint8_t *data, int len) {
+
+ // Write a block of n uint8_ts out
+ template <class D> void writeBytes(register uint8_t *data, int len) {
uint8_t *end = data + len;
select();
- while(data != end) {
-#if defined(__MK20DX128__)
- writeByte(D::adjust(*data++));
-#else
+ while(data != end) {
// a slight touch of delay here helps optimize the timing of the status register check loop (not used on ARM)
writeByte(D::adjust(*data++)); delaycycles<3>();
-#endif
}
D::postBlock(len);
- release();
+ release();
}
void writeBytes(register uint8_t *data, int len) { writeBytes<DATA_NOP>(data, len); }
// 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 SKIP, class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
+ 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) {
uint8_t *end = data + len;
+ PixelController<RGB_ORDER> pixels(data, scale, true, advance, skip);
select();
- while(data != end) {
- writeByte(D::adjust(data[SPI_B0], scale));
- writeByte(D::adjust(data[SPI_B1], scale));
- writeByte(D::adjust(data[SPI_B2], scale));
- data += SPI_ADVANCE;
+ 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 <uint8_t SKIP, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
- writeBytes3<SKIP, DATA_NOP, RGB_ORDER>(data, len, scale);
+ // 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<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) {
- writeBytes3<0, D, RGB_ORDER>(data, len, scale);
+ 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) {
+ 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) {
- writeBytes3<0, DATA_NOP, RGB_ORDER>(data, len, scale);
+ template <EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t 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) {
- writeBytes3<0, DATA_NOP, RGB>(data, len, scale);
+ void writeBytes3(register uint8_t *data, int len, register uint8_t scale, bool advance=true, uint8_t skip=0) {
+ writeBytes3<0, DATA_NOP, RGB>(data, len, scale, advance, skip);
}
};
@@ -135,14 +138,14 @@ public:
// Hardware SPI support using SPDR registers and friends
//
// Technically speaking, this uses the AVR SPI registers. This will work on the Teensy 3.0 because Paul made a set of compatability
-// classes that map the AVR SPI registers to ARM's, however this caps the performance of output.
+// classes that map the AVR SPI registers to ARM's, however this caps the performance of output.
//
// TODO: implement ARMHardwareSPIOutput
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER>
-class AVRHardwareSPIOutput {
+class AVRHardwareSPIOutput {
Selectable *m_pSelect;
bool mWait;
public:
@@ -150,7 +153,7 @@ public:
AVRHardwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; }
void setSelect(Selectable *pSelect) { m_pSelect = pSelect; }
- void setSPIRate() {
+ void setSPIRate() {
SPCR &= ~ ( (1<<SPR1) | (1<<SPR0) ); // clear out the prescalar bits
bool b2x = false;
@@ -158,7 +161,7 @@ public:
if(_SPI_CLOCK_DIVIDER >= 128) { SPCR |= (1<<SPR1); SPCR |= (1<<SPR0); }
else if(_SPI_CLOCK_DIVIDER >= 64) { SPCR |= (1<<SPR1);}
else if(_SPI_CLOCK_DIVIDER >= 32) { SPCR |= (1<<SPR1); b2x = true; }
- else if(_SPI_CLOCK_DIVIDER >= 16) { SPCR |= (1<<SPR0); }
+ else if(_SPI_CLOCK_DIVIDER >= 16) { SPCR |= (1<<SPR0); }
else if(_SPI_CLOCK_DIVIDER >= 8) { SPCR |= (1<<SPR0); b2x = true; }
else if(_SPI_CLOCK_DIVIDER >= 4) { /* do nothing - default rate */ }
else { b2x = true; }
@@ -166,7 +169,7 @@ public:
if(b2x) { SPSR |= (1<<SPI2X); }
else { SPSR &= ~ (1<<SPI2X); }
}
-
+
void init() {
volatile uint8_t clr;
@@ -183,16 +186,16 @@ public:
SPCR |= ((1<<SPE) | (1<<MSTR) ); // enable SPI as master
SPCR &= ~ ( (1<<SPR1) | (1<<SPR0) ); // clear out the prescalar bits
- clr = SPSR; // clear SPI status register
+ clr = SPSR; // clear SPI status register
clr = SPDR; // clear SPI data register
- clr;
+ clr;
bool b2x = false;
if(_SPI_CLOCK_DIVIDER >= 128) { SPCR |= (1<<SPR1); SPCR |= (1<<SPR0); }
else if(_SPI_CLOCK_DIVIDER >= 64) { SPCR |= (1<<SPR1);}
else if(_SPI_CLOCK_DIVIDER >= 32) { SPCR |= (1<<SPR1); b2x = true; }
- else if(_SPI_CLOCK_DIVIDER >= 16) { SPCR |= (1<<SPR0); }
+ else if(_SPI_CLOCK_DIVIDER >= 16) { SPCR |= (1<<SPR0); }
else if(_SPI_CLOCK_DIVIDER >= 8) { SPCR |= (1<<SPR0); b2x = true; }
else if(_SPI_CLOCK_DIVIDER >= 4) { /* do nothing - default rate */ }
else { b2x = true; }
@@ -204,23 +207,25 @@ public:
shouldWait(false);
}
- static bool shouldWait(bool wait = false) __attribute__((always_inline)) {
- static bool sWait=false;
- if(sWait) { sWait = wait; return true; } else { sWait = wait; return false; }
+ static bool shouldWait(bool wait = false) __attribute__((always_inline)) {
+ static bool sWait=false;
+ if(sWait) { sWait = wait; return true; } else { sWait = wait; return false; }
// return true;
}
static void wait() __attribute__((always_inline)) { if(shouldWait()) { while(!(SPSR & (1<<SPIF))); } }
static void waitFully() __attribute__((always_inline)) { wait(); }
+ static void writeWord(uint16_t w) __attribute__((always_inline)) { writeByte(w>>8); writeByte(w&0xFF); }
+
static void writeByte(uint8_t b) __attribute__((always_inline)) { wait(); SPDR=b; shouldWait(true); }
static void writeBytePostWait(uint8_t b) __attribute__((always_inline)) { SPDR=b; shouldWait(true); wait(); }
static void writeByteNoWait(uint8_t b) __attribute__((always_inline)) { SPDR=b; shouldWait(true); }
- template <uint8_t BIT> inline static void writeBit(uint8_t b) {
+ template <uint8_t BIT> inline static void writeBit(uint8_t b) {
SPCR &= ~(1 << SPE);
- if(b & (1 << BIT)) {
+ if(b & (1 << BIT)) {
FastPin<_DATA_PIN>::hi();
- } else {
+ } else {
FastPin<_DATA_PIN>::lo();
}
@@ -237,73 +242,54 @@ public:
while(len--) { writeByte(value); }
}
- void writeBytesValue(uint8_t value, int len) {
+ void writeBytesValue(uint8_t value, int len) {
//setSPIRate();
select();
- while(len--) {
+ while(len--) {
writeByte(value);
}
release();
}
-
- // Write a block of n uint8_ts out
- template <class D> void writeBytes(register uint8_t *data, int len) {
+
+ // Write a block of n uint8_ts out
+ template <class D> void writeBytes(register uint8_t *data, int len) {
//setSPIRate();
uint8_t *end = data + len;
select();
- while(data != end) {
+ while(data != end) {
// a slight touch of delay here helps optimize the timing of the status register check loop (not used on ARM)
writeByte(D::adjust(*data++)); delaycycles<3>();
}
- release();
+ release();
}
void writeBytes(register uint8_t *data, int len) { writeBytes<DATA_NOP>(data, len); }
// 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 SKIP, class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
+ template <uint8_t FLAGS, class D, EOrder RGB_ORDER> void writePixels(PixelController<RGB_ORDER> pixels) {
//setSPIRate();
- uint8_t *end = data + len;
+ int len = pixels.mLen;
+
select();
- while(data != end) {
- if(SKIP & FLAG_START_BIT) {
+ while(pixels.has(1)) {
+ if(FLAGS & FLAG_START_BIT) {
writeBit<0>(1);
- }
- // a slight touch of delay here helps optimize the timing of the status register check loop (not used on ARM)
- if(false && _SPI_CLOCK_DIVIDER == 0) {
- writeByteNoWait(D::adjust(data[SPI_B0], scale)); delaycycles<13>();
- writeByteNoWait(D::adjust(data[SPI_B1], scale)); delaycycles<13>();
- writeByteNoWait(D::adjust(data[SPI_B2], scale)); delaycycles<9>();
- } else if(SKIP & FLAG_START_BIT) {
- writeBytePostWait(D::adjust(data[SPI_B0], scale));
- writeBytePostWait(D::adjust(data[SPI_B1], scale));
- writeBytePostWait(D::adjust(data[SPI_B2], scale));
- } else {
- writeByte(D::adjust(data[SPI_B0], scale));
- writeByte(D::adjust(data[SPI_B1], scale));
- writeByte(D::adjust(data[SPI_B2], scale));
+ writeBytePostWait(D::adjust(pixels.loadAndScale0()));
+ writeBytePostWait(D::adjust(pixels.loadAndScale1()));
+ writeBytePostWait(D::adjust(pixels.loadAndScale2()));
+ } else {
+ writeByte(D::adjust(pixels.loadAndScale0()));
+ writeByte(D::adjust(pixels.loadAndScale1()));
+ writeByte(D::adjust(pixels.loadAndScale2()));
}
- data += SPI_ADVANCE;
+ pixels.advanceData();
+ pixels.stepDithering();
}
D::postBlock(len);
release();
}
-
- template <uint8_t SKIP, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
- writeBytes3<SKIP, DATA_NOP, RGB_ORDER>(data, len, scale);
- }
- template <class D, EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
- writeBytes3<0, D, RGB_ORDER>(data, len, scale);
- }
- template <EOrder RGB_ORDER> void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
- writeBytes3<0, DATA_NOP, RGB_ORDER>(data, len, scale);
- }
- void writeBytes3(register uint8_t *data, int len, register uint8_t scale) {
- writeBytes3<0, DATA_NOP, RGB>(data, len, scale);
- }
-
};
#endif
@@ -311,4 +297,4 @@ public:
// #define FORCE_SOFTWARE_SPI
#endif
-#endif \ No newline at end of file
+#endif