diff options
Diffstat (limited to 'Библиотеки/FastLED-master/platforms/arm/nrf51')
5 files changed, 409 insertions, 0 deletions
diff --git a/Библиотеки/FastLED-master/platforms/arm/nrf51/clockless_arm_nrf51.h b/Библиотеки/FastLED-master/platforms/arm/nrf51/clockless_arm_nrf51.h new file mode 100644 index 0000000..da81e9f --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/nrf51/clockless_arm_nrf51.h @@ -0,0 +1,83 @@ +#ifndef __INC_CLOCKLESS_ARM_NRF51 +#define __INC_CLOCKLESS_ARM_NRF51 + +#if defined(NRF51) + +#include "nrf51_bitfields.h" +#define FASTLED_HAS_CLOCKLESS 1 + +#if (FASTLED_ALLOW_INTERRUPTS==1) +#define SEI_CHK LED_TIMER->CC[0] = (WAIT_TIME * (F_CPU/1000000)); LED_TIMER->TASKS_CLEAR; LED_TIMER->EVENTS_COMPARE[0] = 0; +#define CLI_CHK cli(); if(LED_TIMER->EVENTS_COMPARE[0]) { LED_TIMER->TASKS_STOP = 1; return 0; } +#define INNER_SEI sei(); +#else +#define SEI_CHK +#define CLI_CHK +#define INNER_SEI delaycycles<1>(); +#endif + + +#include "platforms/arm/common/m0clockless.h" +template <uint8_t DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 75> +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(); + + // timer mode w/prescaler of 0 + LED_TIMER->MODE = TIMER_MODE_MODE_Timer; + LED_TIMER->PRESCALER = 0; + LED_TIMER->EVENTS_COMPARE[0] = 0; + LED_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit; + LED_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk; + LED_TIMER->TASKS_START = 1; + + int ret = showLedData<4,8,T1,T2,T3,RGB_ORDER,WAIT_TIME>(portBase, FastPin<DATA_PIN>::mask(), pixels.mData, pixels.mLen, &data); + + LED_TIMER->TASKS_STOP = 1; + return ret; // 0x00FFFFFF - _VAL; + } +}; + + +#endif // NRF51 +#endif // __INC_CLOCKLESS_ARM_NRF51 diff --git a/Библиотеки/FastLED-master/platforms/arm/nrf51/fastled_arm_nrf51.h b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastled_arm_nrf51.h new file mode 100644 index 0000000..bfdefc3 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastled_arm_nrf51.h @@ -0,0 +1,11 @@ +#ifndef __INC_FASTLED_ARM_NRF51_H +#define __INC_FASTLED_ARM_NRF51_H + +// Include the k20 headers +#include "bitswap.h" +#include "fastled_delay.h" +#include "fastpin_arm_nrf51.h" +#include "fastspi_arm_nrf51.h" +#include "clockless_arm_nrf51.h" + +#endif diff --git a/Библиотеки/FastLED-master/platforms/arm/nrf51/fastpin_arm_nrf51.h b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastpin_arm_nrf51.h new file mode 100644 index 0000000..4125f9a --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/nrf51/fastpin_arm_nrf51.h @@ -0,0 +1,119 @@ +#ifndef __FASTPIN_ARM_NRF51_H +#define __FASTPIN_ARM_NRF51_H + +#if defined(NRF51) +/// Template definition for teensy 3.0 style ARM pins, providing direct access to the various GPIO registers. Note that this +/// uses the full port GPIO registers. In theory, in some way, bit-band register access -should- be faster, however I have found +/// that something about the way gcc does register allocation results in the bit-band code being slower. It will need more fine tuning. +/// The registers are data output, set output, clear output, toggle output, input, and direction +#if 0 +template<uint8_t PIN, uint32_t _MASK, typename _DIRSET, typename _DIRCLR, typename _OUTSET, typename _OUTCLR, typename _OUT> class _ARMPIN { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { _DIRSET::r() = _MASK; } + inline static void setInput() { _DIRCLR::r() = _MASK; } + + inline static void hi() __attribute__ ((always_inline)) { _OUTSET::r() = _MASK; } + inline static void lo() __attribute__ ((always_inline)) { _OUTCLR::r() = _MASK; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { _OUT::r() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { _OUT::r() ^= _MASK; } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); } + inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + inline static port_t hival() __attribute__ ((always_inline)) { return _OUT::r() | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return _OUT::r() & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_OUT::r(); } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } +}; + +#define ADDR(X) *(volatile uint32_t*)X +#define NR_GPIO_ADDR(base,offset) (*(volatile uint32_t *))((uint32_t)(base + offset)) +#define NR_DIRSET ADDR(0x50000518UL) // NR_GPIO_ADDR(NRF_GPIO_BASE, 0x518) +#define NR_DIRCLR ADDR(0x5000051CUL) // NR_GPIO_ADDR(NRF_GPIO_BASE, 0x51C) +#define NR_OUTSET ADDR(0x50000508UL) // NR_GPIO_ADDR(NRF_GPIO_BASE, 0x508) +#define NR_OUTCLR ADDR(0x5000050CUL) // NR_GPIO_ADDR(NRF_GPIO_BASE, 0x50C) +#define NR_OUT ADDR(0x50000504UL) // NR_GPIO_ADDR(NRF_GPIO_BASE, 0x504) + +#define _RD32_NRF(T) struct __gen_struct_ ## T { static __attribute__((always_inline)) inline reg32_t r() { return T; }}; + +_RD32_NRF(NR_DIRSET); +_RD32_NRF(NR_DIRCLR); +_RD32_NRF(NR_OUTSET); +_RD32_NRF(NR_OUTCLR); +_RD32_NRF(NR_OUT); + +#define _DEFPIN_ARM(PIN) template<> class FastPin<PIN> : public _ARMPIN<PIN, 1 << PIN, \ + _R(NR_DIRSET), _R(NR_DIRCLR), _R(NR_OUTSET), _R(NR_OUTCLR), _R(NR_OUT)> {}; +#else + +typedef struct { /*!< GPIO Structure */ + // __I uint32_t RESERVED0[321]; + __IO uint32_t OUT; /*!< Write GPIO port. */ + __IO uint32_t OUTSET; /*!< Set individual bits in GPIO port. */ + __IO uint32_t OUTCLR; /*!< Clear individual bits in GPIO port. */ + __I uint32_t IN; /*!< Read GPIO port. */ + __IO uint32_t DIR; /*!< Direction of GPIO pins. */ + __IO uint32_t DIRSET; /*!< DIR set register. */ + __IO uint32_t DIRCLR; /*!< DIR clear register. */ + __I uint32_t RESERVED1[120]; + __IO uint32_t PIN_CNF[32]; /*!< Configuration of GPIO pins. */ +} FL_NRF_GPIO_Type; + +#define FL_NRF_GPIO_BASE 0x50000504UL +#define FL_NRF_GPIO ((FL_NRF_GPIO_Type *) FL_NRF_GPIO_BASE) + +template<uint8_t PIN, uint32_t _MASK> class _ARMPIN { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { FL_NRF_GPIO->DIRSET = _MASK; } + inline static void setInput() { FL_NRF_GPIO->DIRCLR = _MASK; } + + inline static void hi() __attribute__ ((always_inline)) { FL_NRF_GPIO->OUTSET = _MASK; } + inline static void lo() __attribute__ ((always_inline)) { FL_NRF_GPIO->OUTCLR= _MASK; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { FL_NRF_GPIO->OUT = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { FL_NRF_GPIO->OUT ^= _MASK; } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); } + inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + inline static port_t hival() __attribute__ ((always_inline)) { return FL_NRF_GPIO->OUT | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return FL_NRF_GPIO->OUT & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &FL_NRF_GPIO->OUT; } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } + + inline static bool isset() __attribute__ ((always_inline)) { return (FL_NRF_GPIO->IN & _MASK) != 0; } +}; + + +#define _DEFPIN_ARM(PIN) template<> class FastPin<PIN> : public _ARMPIN<PIN, 1 << PIN> {}; +#endif + +// Actual pin definitions +#define MAX_PIN 31 +_DEFPIN_ARM(0); _DEFPIN_ARM(1); _DEFPIN_ARM(2); _DEFPIN_ARM(3); +_DEFPIN_ARM(4); _DEFPIN_ARM(5); _DEFPIN_ARM(6); _DEFPIN_ARM(7); +_DEFPIN_ARM(8); _DEFPIN_ARM(9); _DEFPIN_ARM(10); _DEFPIN_ARM(11); +_DEFPIN_ARM(12); _DEFPIN_ARM(13); _DEFPIN_ARM(14); _DEFPIN_ARM(15); +_DEFPIN_ARM(16); _DEFPIN_ARM(17); _DEFPIN_ARM(18); _DEFPIN_ARM(19); +_DEFPIN_ARM(20); _DEFPIN_ARM(21); _DEFPIN_ARM(22); _DEFPIN_ARM(23); +_DEFPIN_ARM(24); _DEFPIN_ARM(25); _DEFPIN_ARM(26); _DEFPIN_ARM(27); +_DEFPIN_ARM(28); _DEFPIN_ARM(29); _DEFPIN_ARM(30); _DEFPIN_ARM(31); + +#define HAS_HARDWARE_PIN_SUPPORT + +#endif + +#endif 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 diff --git a/Библиотеки/FastLED-master/platforms/arm/nrf51/led_sysdefs_arm_nrf51.h b/Библиотеки/FastLED-master/platforms/arm/nrf51/led_sysdefs_arm_nrf51.h new file mode 100644 index 0000000..7a83d11 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/nrf51/led_sysdefs_arm_nrf51.h @@ -0,0 +1,46 @@ +#ifndef __LED_SYSDEFS_ARM_NRF51 +#define __LED_SYSDEFS_ARM_NRF51 + +#ifndef NRF51 +#define NRF51 +#endif + +#define LED_TIMER NRF_TIMER1 +#define FASTLED_NO_PINMAP +#define FASTLED_HAS_CLOCKLESS + +#define FASTLED_SPI_BYTE_ONLY + +#define FASTLED_ARM +#define FASTLED_ARM_M0 + +#ifndef F_CPU +#define F_CPU 16000000 +#endif + +#include <stdint.h> +#include "nrf51.h" +#include "core_cm0.h" + +typedef volatile uint32_t RoReg; +typedef volatile uint32_t RwReg; +typedef uint32_t prog_uint32_t; +typedef uint8_t boolean; + +#define PROGMEM +#define NO_PROGMEM +#define NEED_CXX_BITS + +// Default to NOT using PROGMEM here +#ifndef FASTLED_USE_PROGMEM +#define FASTLED_USE_PROGMEM 0 +#endif + +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 1 +#endif + +#define cli() __disable_irq(); +#define sei() __enable_irq(); + +#endif |