diff options
Diffstat (limited to 'Библиотеки/FastLED-master/platforms/arm/nrf51/fastspi_arm_nrf51.h')
-rw-r--r-- | Библиотеки/FastLED-master/platforms/arm/nrf51/fastspi_arm_nrf51.h | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Библиотеки/FastLED-master/platforms/arm/nrf51/fastspi_arm_nrf51.h b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastspi_arm_nrf51.h new file mode 100644 index 0000000..539fd65 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastspi_arm_nrf51.h @@ -0,0 +1,150 @@ +#ifndef __INC_FASTSPI_NRF_H +#define __INC_FASTSPI_NRF_H + +#ifdef NRF51 + +#ifndef FASTLED_FORCE_SOFTWARE_SPI +#define FASTLED_ALL_PINS_HARDWARE_SPI + +// A nop/stub class, mostly to show the SPI methods that are needed/used by the various SPI chipset implementations. Should +// be used as a definition for the set of methods that the spi implementation classes should use (since C++ doesn't support the +// idea of interfaces - it's possible this could be done with virtual classes, need to decide if i want that overhead) +template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER> +class NRF51SPIOutput { + + struct saveData { + uint32_t sck; + uint32_t mosi; + uint32_t miso; + uint32_t freq; + uint32_t enable; + } mSavedData; + + void saveSPIData() { + mSavedData.sck = NRF_SPI0->PSELSCK; + mSavedData.mosi = NRF_SPI0->PSELMOSI; + mSavedData.miso = NRF_SPI0->PSELMISO; + mSavedData.freq = NRF_SPI0->FREQUENCY; + mSavedData.enable = NRF_SPI0->ENABLE; + } + + void restoreSPIData() { + NRF_SPI0->PSELSCK = mSavedData.sck; + NRF_SPI0->PSELMOSI = mSavedData.mosi; + NRF_SPI0->PSELMISO = mSavedData.miso; + NRF_SPI0->FREQUENCY = mSavedData.freq; + mSavedData.enable = NRF_SPI0->ENABLE; + } + +public: + NRF51SPIOutput() { FastPin<_DATA_PIN>::setOutput(); FastPin<_CLOCK_PIN>::setOutput(); } + NRF51SPIOutput(Selectable *pSelect) { FastPin<_DATA_PIN>::setOutput(); FastPin<_CLOCK_PIN>::setOutput(); } + + // set the object representing the selectable + void setSelect(Selectable *pSelect) { /* TODO */ } + + // initialize the SPI subssytem + void init() { + FastPin<_DATA_PIN>::setOutput(); + FastPin<_CLOCK_PIN>::setOutput(); + NRF_SPI0->PSELSCK = _CLOCK_PIN; + NRF_SPI0->PSELMOSI = _DATA_PIN; + NRF_SPI0->PSELMISO = 0xFFFFFFFF; + NRF_SPI0->FREQUENCY = 0x80000000; + NRF_SPI0->ENABLE = 1; + NRF_SPI0->EVENTS_READY = 0; + } + + // latch the CS select + void select() { saveSPIData(); init(); } + + // release the CS select + void release() { shouldWait(); restoreSPIData(); } + + static bool shouldWait(bool wait = false) __attribute__((always_inline)) __attribute__((always_inline)) { + // static bool sWait=false; + // bool oldWait = sWait; + // sWait = wait; + // never going to bother with waiting since we're always running the spi clock at max speed on the rfduino + // TODO: When we set clock rate, implement/fix waiting properly, otherwise the world hangs up + return false; + } + + // wait until all queued up data has been written + static void waitFully() __attribute__((always_inline)){ if(shouldWait()) { while(NRF_SPI0->EVENTS_READY==0); } NRF_SPI0->INTENCLR; } + static void wait() __attribute__((always_inline)){ if(shouldWait()) { while(NRF_SPI0->EVENTS_READY==0); } NRF_SPI0->INTENCLR; } + + // write a byte out via SPI (returns immediately on writing register) + static void writeByte(uint8_t b) __attribute__((always_inline)) { wait(); NRF_SPI0->TXD = b; NRF_SPI0->INTENCLR; shouldWait(true); } + + // write a word out via SPI (returns immediately on writing register) + static void writeWord(uint16_t w) __attribute__((always_inline)){ writeByte(w>>8); writeByte(w & 0xFF); } + + // A raw set of writing byte values, assumes setup/init/waiting done elsewhere (static for use by adjustment classes) + 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(); + while(len--) { + writeByte(value); + } + waitFully(); + release(); + } + + // A full cycle of writing a raw block of data out, including select, release, and waiting + template<class D> void writeBytes(uint8_t *data, int len) { + uint8_t *end = data + len; + select(); + while(data != end) { + writeByte(D::adjust(*data++)); + } + D::postBlock(len); + waitFully(); + release(); + } + + void writeBytes(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(); + NRF_SPI0->ENABLE = 0; + if(b & 1<<BIT) { + FastPin<_DATA_PIN>::hi(); + } else { + FastPin<_DATA_PIN>::lo(); + } + FastPin<_CLOCK_PIN>::toggle(); + FastPin<_CLOCK_PIN>::toggle(); + NRF_SPI0->ENABLE = 1; + } + + 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); + waitFully(); + release(); + } + +}; + +#endif +#endif + +#endif |