#ifndef __INC_BLOCK_CLOCKLESS_H #define __INC_BLOCK_CLOCKLESS_H FASTLED_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Base template for clockless controllers. These controllers have 3 control points in their cycle for each bit. The first point // is where the line is raised hi. The second pointsnt is where the line is dropped low for a zero. The third point is where the // line is dropped low for a one. T1, T2, and T3 correspond to the timings for those three in clock cycles. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if defined(__SAM3X8E__) #define PORT_MASK (((1< class InlineBlockClocklessController : public CPixelLEDController { typedef typename FastPin::port_ptr_t data_ptr_t; typedef typename FastPin::port_t data_t; data_t mPinMask; data_ptr_t mPort; CMinWait mWait; public: virtual int size() { return CLEDController::size() * LANES; } virtual void init() { static_assert(LANES <= 8, "Maximum of 8 lanes for Due parallel controllers!"); if(FIRST_PIN == PORTA_FIRST_PIN) { switch(LANES) { case 8: FastPin<31>::setOutput(); case 7: FastPin<58>::setOutput(); case 6: FastPin<100>::setOutput(); case 5: FastPin<59>::setOutput(); case 4: FastPin<60>::setOutput(); case 3: FastPin<61>::setOutput(); case 2: FastPin<68>::setOutput(); case 1: FastPin<69>::setOutput(); } } else if(FIRST_PIN == PORTD_FIRST_PIN) { switch(LANES) { case 8: FastPin<11>::setOutput(); case 7: FastPin<29>::setOutput(); case 6: FastPin<15>::setOutput(); case 5: FastPin<14>::setOutput(); case 4: FastPin<28>::setOutput(); case 3: FastPin<27>::setOutput(); case 2: FastPin<26>::setOutput(); case 1: FastPin<25>::setOutput(); } } else if(FIRST_PIN == PORTB_FIRST_PIN) { switch(LANES) { case 8: FastPin<97>::setOutput(); case 7: FastPin<96>::setOutput(); case 6: FastPin<95>::setOutput(); case 5: FastPin<94>::setOutput(); case 4: FastPin<93>::setOutput(); case 3: FastPin<92>::setOutput(); case 2: FastPin<91>::setOutput(); case 1: FastPin<90>::setOutput(); } } mPinMask = FastPin::mask(); mPort = FastPin::port(); } virtual uint16_t getMaxRefreshRate() const { return 400; } virtual void showPixels(PixelController & pixels) { mWait.wait(); showRGBInternal(pixels); sei(); mWait.mark(); } static uint32_t showRGBInternal(PixelController &allpixels) { // Serial.println("Entering show"); int nLeds = allpixels.mLen; // Setup the pixel controller and load/scale the first byte Lines b0,b1,b2; allpixels.preStepFirstByteDithering(); for(uint8_t i = 0; i < LANES; i++) { b0.bytes[i] = allpixels.loadAndScale0(i); } // Setup and start the clock TC_Configure(DUE_TIMER,DUE_TIMER_CHANNEL,TC_CMR_TCCLKS_TIMER_CLOCK1); pmc_enable_periph_clk(DUE_TIMER_ID); TC_Start(DUE_TIMER,DUE_TIMER_CHANNEL); #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); #endif uint32_t next_mark = (DUE_TIMER_VAL + (TOTAL)); while(nLeds--) { allpixels.stepDithering(); #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); if(DUE_TIMER_VAL > next_mark) { if((DUE_TIMER_VAL - next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); return DUE_TIMER_VAL; } } #endif // Write first byte, read next byte writeBits<8+XTRA0,1>(next_mark, b0, b1, allpixels); // Write second byte, read 3rd byte writeBits<8+XTRA0,2>(next_mark, b1, b2, allpixels); allpixels.advanceData(); // Write third byte writeBits<8+XTRA0,0>(next_mark, b2, b0, allpixels); #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); #endif } return DUE_TIMER_VAL; } template __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, Lines & b3, PixelController &pixels) { // , register uint32_t & b2) { Lines b2; transpose8x1(b.bytes,b2.bytes); register uint8_t d = pixels.template getd(pixels); register uint8_t scale = pixels.template getscale(pixels); for(uint32_t i = 0; (i < LANES) && (i<8); i++) { while(DUE_TIMER_VAL < next_mark); next_mark = (DUE_TIMER_VAL+TOTAL); *FastPin::sport() = PORT_MASK; while((next_mark - DUE_TIMER_VAL) > (T2+T3+6)); *FastPin::cport() = (~b2.bytes[7-i]) & PORT_MASK; while((next_mark - (DUE_TIMER_VAL)) > T3); *FastPin::cport() = PORT_MASK; b3.bytes[i] = pixels.template loadAndScale(pixels,i,d,scale); } for(uint32_t i = LANES; i < 8; i++) { while(DUE_TIMER_VAL < next_mark); next_mark = (DUE_TIMER_VAL+TOTAL); *FastPin::sport() = PORT_MASK; while((next_mark - DUE_TIMER_VAL) > (T2+T3+6)); *FastPin::cport() = (~b2.bytes[7-i]) & PORT_MASK; while((next_mark - DUE_TIMER_VAL) > T3); *FastPin::cport() = PORT_MASK; } } }; #endif FASTLED_NAMESPACE_END #endif