#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 class ClocklessController : public CLEDController { typedef typename FastPinBB::port_ptr_t data_ptr_t; typedef typename FastPinBB::port_t data_t; data_t mPinMask; data_ptr_t mPort; CMinWait mWait; public: virtual void init() { FastPinBB::setOutput(); mPinMask = FastPinBB::mask(); mPort = FastPinBB::port(); } virtual uint16_t getMaxRefreshRate() const { return 400; } virtual void clearLeds(int nLeds) { showColor(CRGB(0, 0, 0), nLeds, 0); } // set all the leds on the controller to a given color virtual void showColor(const struct CRGB & rgbdata, int nLeds, CRGB scale) { PixelController pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); cli(); // attempt to re-show a frame if we exit early because of interrupts. if(!showRGBInternal(pixels)) { sei(); delayMicroseconds(WAIT_TIME); cli(); showRGBInternal(pixels); } sei(); mWait.mark(); } virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { PixelController pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); cli(); if(!showRGBInternal(pixels)) { sei(); delayMicroseconds(WAIT_TIME); cli(); showRGBInternal(pixels); } sei(); mWait.mark(); } #ifdef SUPPORT_ARGB virtual void show(const struct CARGB *rgbdata, int nLeds, CRGB scale) { PixelController pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); cli(); showRGBInternal(pixels); sei(); mWait.mark(); } #endif // 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 & 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::port_ptr_t portBase = FastPin::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::mask(), pixels.mData, pixels.mLen, &data); LED_TIMER->TASKS_STOP = 1; return ret; // 0x00FFFFFF - _VAL; } }; #endif // NRF51 #endif // __INC_CLOCKLESS_ARM_NRF51