diff options
Diffstat (limited to 'Библиотеки/FastLED-master/platforms/arm/sam')
6 files changed, 654 insertions, 0 deletions
diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/clockless_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/clockless_arm_sam.h new file mode 100644 index 0000000..0fc621d --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/clockless_arm_sam.h @@ -0,0 +1,120 @@ +#ifndef __INC_CLOCKLESS_ARM_SAM_H +#define __INC_CLOCKLESS_ARM_SAM_H + +FASTLED_NAMESPACE_BEGIN + +// Definition for a single channel clockless controller for the sam family of arm chips, like that used in the due and rfduino +// See clockless.h for detailed info on how the template parameters are used. + +#if defined(__SAM3X8E__) + + +#define TADJUST 0 +#define TOTAL ( (T1+TADJUST) + (T2+TADJUST) + (T3+TADJUST) ) + +#define FASTLED_HAS_CLOCKLESS 1 + +template <uint8_t DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50> +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; } + +protected: + + virtual void showPixels(PixelController<RGB_ORDER> & pixels) { + mWait.wait(); + if(!showRGBInternal(pixels)) { + sei(); delayMicroseconds(WAIT_TIME); cli(); + showRGBInternal(pixels); + } + mWait.mark(); + } + + template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register data_ptr_t port, register uint8_t & b) { + // Make sure we don't slot into a wrapping spot, this will delay up to 12.5µs for WS2812 + // bool bShift=0; + // while(VAL < (TOTAL*10)) { bShift=true; } + // if(bShift) { next_mark = (VAL-TOTAL); }; + + for(register uint32_t i = BITS; i > 0; i--) { + // wait to start the bit, then set the pin high + while(DUE_TIMER_VAL < next_mark); + next_mark = (DUE_TIMER_VAL+TOTAL); + *port = 1; + + // how long we want to wait next depends on whether or not our bit is set to 1 or 0 + if(b&0x80) { + // we're a 1, wait until there's less than T3 clocks left + while((next_mark - DUE_TIMER_VAL) > (T3)); + } else { + // we're a 0, wait until there's less than (T2+T3+slop) clocks left in this bit + while((next_mark - DUE_TIMER_VAL) > (T2+T3+6+TADJUST+TADJUST)); + } + *port=0; + b <<= 1; + } + } + +#define FORCE_REFERENCE(var) asm volatile( "" : : "r" (var) ) + // 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) { + // 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); + + register data_ptr_t port asm("r7") = FastPinBB<DATA_PIN>::port(); FORCE_REFERENCE(port); + *port = 0; + + // Setup the pixel controller and load/scale the first byte + pixels.preStepFirstByteDithering(); + uint8_t b = pixels.loadAndScale0(); + + uint32_t next_mark = (DUE_TIMER_VAL + (TOTAL)); + while(pixels.has(1)) { + pixels.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 0; } + } + #endif + + writeBits<8+XTRA0>(next_mark, port, b); + + b = pixels.loadAndScale1(); + writeBits<8+XTRA0>(next_mark, port,b); + + b = pixels.loadAndScale2(); + writeBits<8+XTRA0>(next_mark, port,b); + + b = pixels.advanceAndLoadAndScale0(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) + sei(); + #endif + }; + + TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); + return DUE_TIMER_VAL; + } +}; + +#endif + +FASTLED_NAMESPACE_END + +#endif diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/clockless_block_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/clockless_block_arm_sam.h new file mode 100644 index 0000000..355f945 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/clockless_block_arm_sam.h @@ -0,0 +1,184 @@ + #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<<LANES)-1) & ((FIRST_PIN==2) ? 0xFF : 0xFF)) + +#define FASTLED_HAS_BLOCKLESS 1 + +#define PORTD_FIRST_PIN 25 +#define PORTA_FIRST_PIN 69 +#define PORTB_FIRST_PIN 90 + +typedef union { + uint8_t bytes[8]; + uint32_t raw[2]; +} Lines; + +#define TADJUST 0 +#define TOTAL ( (T1+TADJUST) + (T2+TADJUST) + (T3+TADJUST) ) +#define T1_MARK (TOTAL - (T1+TADJUST)) +#define T2_MARK (T1_MARK - (T2+TADJUST)) +template <uint8_t LANES, int FIRST_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50> +class InlineBlockClocklessController : public CPixelLEDController<RGB_ORDER, LANES, PORT_MASK> { + typedef typename FastPin<FIRST_PIN>::port_ptr_t data_ptr_t; + typedef typename FastPin<FIRST_PIN>::port_t data_t; + + data_t mPinMask; + data_ptr_t mPort; + CMinWait<WAIT_TIME> 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<FIRST_PIN>::mask(); + mPort = FastPin<FIRST_PIN>::port(); + } + + virtual uint16_t getMaxRefreshRate() const { return 400; } + + virtual void showPixels(PixelController<RGB_ORDER, LANES, PORT_MASK> & pixels) { + mWait.wait(); + showRGBInternal(pixels); + sei(); + mWait.mark(); + } + + static uint32_t showRGBInternal(PixelController<RGB_ORDER, LANES, PORT_MASK> &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<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, Lines & b3, PixelController<RGB_ORDER,LANES, PORT_MASK> &pixels) { // , register uint32_t & b2) { + Lines b2; + transpose8x1(b.bytes,b2.bytes); + + register uint8_t d = pixels.template getd<PX>(pixels); + register uint8_t scale = pixels.template getscale<PX>(pixels); + + for(uint32_t i = 0; (i < LANES) && (i<8); i++) { + while(DUE_TIMER_VAL < next_mark); + next_mark = (DUE_TIMER_VAL+TOTAL); + + *FastPin<FIRST_PIN>::sport() = PORT_MASK; + + while((next_mark - DUE_TIMER_VAL) > (T2+T3+6)); + *FastPin<FIRST_PIN>::cport() = (~b2.bytes[7-i]) & PORT_MASK; + + while((next_mark - (DUE_TIMER_VAL)) > T3); + *FastPin<FIRST_PIN>::cport() = PORT_MASK; + + b3.bytes[i] = pixels.template loadAndScale<PX>(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<FIRST_PIN>::sport() = PORT_MASK; + + while((next_mark - DUE_TIMER_VAL) > (T2+T3+6)); + *FastPin<FIRST_PIN>::cport() = (~b2.bytes[7-i]) & PORT_MASK; + + while((next_mark - DUE_TIMER_VAL) > T3); + *FastPin<FIRST_PIN>::cport() = PORT_MASK; + } + } + + +}; + +#endif + +FASTLED_NAMESPACE_END + +#endif diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/fastled_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/fastled_arm_sam.h new file mode 100644 index 0000000..fd61c14 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/fastled_arm_sam.h @@ -0,0 +1,11 @@ +#ifndef __INC_FASTLED_ARM_SAM_H +#define __INC_FASTLED_ARM_SAM_H + +// Include the sam headers +#include "fastled_delay.h" +#include "fastpin_arm_sam.h" +#include "fastspi_arm_sam.h" +#include "clockless_arm_sam.h" +#include "clockless_block_arm_sam.h" + +#endif diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/fastpin_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/fastpin_arm_sam.h new file mode 100644 index 0000000..2bb7804 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/fastpin_arm_sam.h @@ -0,0 +1,137 @@ +#ifndef __INC_FASTPIN_ARM_SAM_H +#define __INC_FASTPIN_ARM_SAM_H + +FASTLED_NAMESPACE_BEGIN + +#if defined(FASTLED_FORCE_SOFTWARE_PINS) +#warning "Software pin support forced, pin access will be sloightly slower." +#define NO_HARDWARE_PIN_SUPPORT +#undef HAS_HARDWARE_PIN_SUPPORT + +#else + + +/// Template definition for arduino due 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 register, set output register, clear output register, set data direction register +template<uint8_t PIN, uint32_t _MASK, typename _PDOR, typename _PSOR, typename _PCOR, typename _PDDR> class _DUEPIN { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { pinMode(PIN, OUTPUT); } // TODO: perform MUX config { _PDDR::r() |= _MASK; } + inline static void setInput() { pinMode(PIN, INPUT); } // TODO: preform MUX config { _PDDR::r() &= ~_MASK; } + + inline static void hi() __attribute__ ((always_inline)) { _PSOR::r() = _MASK; } + inline static void lo() __attribute__ ((always_inline)) { _PCOR::r() = _MASK; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { _PDOR::r() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { _PDOR::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 _PDOR::r() | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return _PDOR::r() & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PDOR::r(); } + inline static port_ptr_t sport() __attribute__ ((always_inline)) { return &_PSOR::r(); } + inline static port_ptr_t cport() __attribute__ ((always_inline)) { return &_PCOR::r(); } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } +}; + + +/// Template definition for DUE style ARM pins using bit banding, providing direct access to the various GPIO registers. GCC +/// does a poor job of optimizing around these accesses so they are not being used just yet. +template<uint8_t PIN, uint32_t _BIT, typename _PDOR, typename _PSOR, typename _PCOR, typename _PDDR> class _DUEPIN_BITBAND { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { pinMode(PIN, OUTPUT); } // TODO: perform MUX config { _PDDR::r() |= _MASK; } + inline static void setInput() { pinMode(PIN, INPUT); } // TODO: preform MUX config { _PDDR::r() &= ~_MASK; } + + inline static void hi() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = 1; } + inline static void lo() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = 0; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() ^= 1; } + + 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 1; } + inline static port_t loval() __attribute__ ((always_inline)) { return 0; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return _PDOR::template rx<_BIT>(); } + inline static port_t mask() __attribute__ ((always_inline)) { return 1; } +}; + +#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) +#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) + +#define _R(T) struct __gen_struct_ ## T +#define _RD32(T) struct __gen_struct_ ## T { static __attribute__((always_inline)) inline reg32_t r() { return T; } \ + template<int BIT> static __attribute__((always_inline)) inline ptr_reg32_t rx() { return GPIO_BITBAND_PTR(T, BIT); } }; +#define DUE_IO32(L) _RD32(REG_PIO ## L ## _ODSR); _RD32(REG_PIO ## L ## _SODR); _RD32(REG_PIO ## L ## _CODR); _RD32(REG_PIO ## L ## _OER); + +#define _DEFPIN_DUE(PIN, BIT, L) template<> class FastPin<PIN> : public _DUEPIN<PIN, 1 << BIT, _R(REG_PIO ## L ## _ODSR), _R(REG_PIO ## L ## _SODR), _R(REG_PIO ## L ## _CODR), \ + _R(GPIO ## L ## _OER)> {}; \ + template<> class FastPinBB<PIN> : public _DUEPIN_BITBAND<PIN, BIT, _R(REG_PIO ## L ## _ODSR), _R(REG_PIO ## L ## _SODR), _R(REG_PIO ## L ## _CODR), \ + _R(GPIO ## L ## _OER)> {}; + +#if defined(__SAM3X8E__) + +DUE_IO32(A); +DUE_IO32(B); +DUE_IO32(C); +DUE_IO32(D); + +#define MAX_PIN 78 +_DEFPIN_DUE(0, 8, A); _DEFPIN_DUE(1, 9, A); _DEFPIN_DUE(2, 25, B); _DEFPIN_DUE(3, 28, C); +_DEFPIN_DUE(4, 26, C); _DEFPIN_DUE(5, 25, C); _DEFPIN_DUE(6, 24, C); _DEFPIN_DUE(7, 23, C); +_DEFPIN_DUE(8, 22, C); _DEFPIN_DUE(9, 21, C); _DEFPIN_DUE(10, 29, C); _DEFPIN_DUE(11, 7, D); +_DEFPIN_DUE(12, 8, D); _DEFPIN_DUE(13, 27, B); _DEFPIN_DUE(14, 4, D); _DEFPIN_DUE(15, 5, D); +_DEFPIN_DUE(16, 13, A); _DEFPIN_DUE(17, 12, A); _DEFPIN_DUE(18, 11, A); _DEFPIN_DUE(19, 10, A); +_DEFPIN_DUE(20, 12, B); _DEFPIN_DUE(21, 13, B); _DEFPIN_DUE(22, 26, B); _DEFPIN_DUE(23, 14, A); +_DEFPIN_DUE(24, 15, A); _DEFPIN_DUE(25, 0, D); _DEFPIN_DUE(26, 1, D); _DEFPIN_DUE(27, 2, D); +_DEFPIN_DUE(28, 3, D); _DEFPIN_DUE(29, 6, D); _DEFPIN_DUE(30, 9, D); _DEFPIN_DUE(31, 7, A); +_DEFPIN_DUE(32, 10, D); _DEFPIN_DUE(33, 1, C); _DEFPIN_DUE(34, 2, C); _DEFPIN_DUE(35, 3, C); +_DEFPIN_DUE(36, 4, C); _DEFPIN_DUE(37, 5, C); _DEFPIN_DUE(38, 6, C); _DEFPIN_DUE(39, 7, C); +_DEFPIN_DUE(40, 8, C); _DEFPIN_DUE(41, 9, C); _DEFPIN_DUE(42, 19, A); _DEFPIN_DUE(43, 20, A); +_DEFPIN_DUE(44, 19, C); _DEFPIN_DUE(45, 18, C); _DEFPIN_DUE(46, 17, C); _DEFPIN_DUE(47, 16, C); +_DEFPIN_DUE(48, 15, C); _DEFPIN_DUE(49, 14, C); _DEFPIN_DUE(50, 13, C); _DEFPIN_DUE(51, 12, C); +_DEFPIN_DUE(52, 21, B); _DEFPIN_DUE(53, 14, B); _DEFPIN_DUE(54, 16, A); _DEFPIN_DUE(55, 24, A); +_DEFPIN_DUE(56, 23, A); _DEFPIN_DUE(57, 22, A); _DEFPIN_DUE(58, 6, A); _DEFPIN_DUE(59, 4, A); +_DEFPIN_DUE(60, 3, A); _DEFPIN_DUE(61, 2, A); _DEFPIN_DUE(62, 17, B); _DEFPIN_DUE(63, 18, B); +_DEFPIN_DUE(64, 19, B); _DEFPIN_DUE(65, 20, B); _DEFPIN_DUE(66, 15, B); _DEFPIN_DUE(67, 16, B); +_DEFPIN_DUE(68, 1, A); _DEFPIN_DUE(69, 0, A); _DEFPIN_DUE(70, 17, A); _DEFPIN_DUE(71, 18, A); +_DEFPIN_DUE(72, 30, C); _DEFPIN_DUE(73, 21, A); _DEFPIN_DUE(74, 25, A); _DEFPIN_DUE(75, 26, A); +_DEFPIN_DUE(76, 27, A); _DEFPIN_DUE(77, 28, A); _DEFPIN_DUE(78, 23, B); + +// digix pins +_DEFPIN_DUE(90, 0, B); _DEFPIN_DUE(91, 1, B); _DEFPIN_DUE(92, 2, B); _DEFPIN_DUE(93, 3, B); +_DEFPIN_DUE(94, 4, B); _DEFPIN_DUE(95, 5, B); _DEFPIN_DUE(96, 6, B); _DEFPIN_DUE(97, 7, B); +_DEFPIN_DUE(98, 8, B); _DEFPIN_DUE(99, 9, B); _DEFPIN_DUE(100, 5, A); _DEFPIN_DUE(101, 22, B); +_DEFPIN_DUE(102, 23, B); _DEFPIN_DUE(103, 24, B); _DEFPIN_DUE(104, 27, C); _DEFPIN_DUE(105, 20, C); +_DEFPIN_DUE(106, 11, C); _DEFPIN_DUE(107, 10, C); _DEFPIN_DUE(108, 21, A); _DEFPIN_DUE(109, 30, C); +_DEFPIN_DUE(110, 29, B); _DEFPIN_DUE(111, 30, B); _DEFPIN_DUE(112, 31, B); _DEFPIN_DUE(113, 28, B); + +#define SPI_DATA 75 +#define SPI_CLOCK 76 +#define ARM_HARDWARE_SPI +#define HAS_HARDWARE_PIN_SUPPORT + +#endif + +#endif // FASTLED_FORCE_SOFTWARE_PINS + +FASTLED_NAMESPACE_END + + +#endif // __INC_FASTPIN_ARM_SAM_H diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/fastspi_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/fastspi_arm_sam.h new file mode 100644 index 0000000..eb9abe4 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/fastspi_arm_sam.h @@ -0,0 +1,163 @@ +#ifndef __INC_FASTSPI_ARM_SAM_H +#define __INC_FASTSPI_ARM_SAM_H + +FASTLED_NAMESPACE_BEGIN + +#if defined(__SAM3X8E__) +#define m_SPI ((Spi*)SPI0) + +template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint8_t _SPI_CLOCK_DIVIDER> +class SAMHardwareSPIOutput { + Selectable *m_pSelect; + + static inline void waitForEmpty() { while ((m_SPI->SPI_SR & SPI_SR_TDRE) == 0); } + + void enableConfig() { m_SPI->SPI_WPMR &= ~SPI_WPMR_WPEN; } + void disableConfig() { m_SPI->SPI_WPMR |= SPI_WPMR_WPEN; } + + void enableSPI() { m_SPI->SPI_CR = SPI_CR_SPIEN; } + void disableSPI() { m_SPI->SPI_CR = SPI_CR_SPIDIS; } + void resetSPI() { m_SPI->SPI_CR = SPI_CR_SWRST; } + + static inline void readyTransferBits(register uint32_t bits) { + bits -= 8; + // don't change the number of transfer bits while data is still being transferred from TDR to the shift register + waitForEmpty(); + m_SPI->SPI_CSR[0] = SPI_CSR_NCPHA | SPI_CSR_CSAAT | (bits << SPI_CSR_BITS_Pos) | SPI_CSR_DLYBCT(1) | SPI_CSR_SCBR(_SPI_CLOCK_DIVIDER); + } + + template<int BITS> static inline void writeBits(uint16_t w) { + waitForEmpty(); + m_SPI->SPI_TDR = (uint32_t)w | SPI_PCS(0); + } + +public: + SAMHardwareSPIOutput() { m_pSelect = NULL; } + SAMHardwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; } + + // set the object representing the selectable + void setSelect(Selectable *pSelect) { /* TODO */ } + + // initialize the SPI subssytem + void init() { + // m_SPI = SPI0; + + // set the output pins master out, master in, clock. Note doing this here because I still don't + // know how I want to expose this type of functionality in FastPin. + PIO_Configure(PIOA, PIO_PERIPH_A, FastPin<_DATA_PIN>::mask(), PIO_DEFAULT); + PIO_Configure(PIOA, PIO_PERIPH_A, FastPin<_DATA_PIN-1>::mask(), PIO_DEFAULT); + PIO_Configure(PIOA, PIO_PERIPH_A, FastPin<_CLOCK_PIN>::mask(), PIO_DEFAULT); + + release(); + + // Configure the SPI clock, divider between 1-255 + // SCBR = _SPI_CLOCK_DIVIDER + pmc_enable_periph_clk(ID_SPI0); + disableSPI(); + + // reset twice (what the sam code does, not sure why?) + resetSPI(); + resetSPI(); + + // Configure SPI as master, enable + // Bits we want in MR: master, disable mode fault detection, variable peripheral select + m_SPI->SPI_MR = SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS; + + enableSPI(); + + // Send everything out in 8 bit chunks, other sizes appear to work, poorly... + readyTransferBits(8); + } + + // latch the CS select + void inline select() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->select(); } } + + // release the CS select + void inline release() __attribute__((always_inline)) { if(m_pSelect != NULL) { m_pSelect->release(); } } + + // wait until all queued up data has been written + void waitFully() { while((m_SPI->SPI_SR & SPI_SR_TXEMPTY) == 0); } + + // write a byte out via SPI (returns immediately on writing register) + static void writeByte(uint8_t b) { + writeBits<8>(b); + } + + // write a word out via SPI (returns immediately on writing register) + static void writeWord(uint16_t w) { + writeBits<16>(w); + } + + // A raw set of writing byte values, assumes setup/init/waiting done elsewhere + 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(); writeBytesValueRaw(value, len); release(); + } + + template <class D> void writeBytes(register uint8_t *data, int len) { + uint8_t *end = data + len; + select(); + // could be optimized to write 16bit words out instead of 8bit bytes + while(data != end) { + writeByte(D::adjust(*data++)); + } + D::postBlock(len); + waitFully(); + release(); + } + + void writeBytes(register 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 + // not the most efficient mechanism in the world - but should be enough for sm16716 and friends + template <uint8_t BIT> inline void writeBit(uint8_t b) { + // need to wait for all exisiting data to go out the door, first + waitFully(); + disableSPI(); + if(b & (1 << BIT)) { + FastPin<_DATA_PIN>::hi(); + } else { + FastPin<_DATA_PIN>::lo(); + } + + FastPin<_CLOCK_PIN>::hi(); + FastPin<_CLOCK_PIN>::lo(); + enableSPI(); + } + + // 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 FLAGS, class D, EOrder RGB_ORDER> void writePixels(PixelController<RGB_ORDER> pixels) { + select(); + int len = pixels.mLen; + + if(FLAGS & FLAG_START_BIT) { + while(pixels.has(1)) { + writeBits<9>((1<<8) | D::adjust(pixels.loadAndScale0())); + writeByte(D::adjust(pixels.loadAndScale1())); + writeByte(D::adjust(pixels.loadAndScale2())); + pixels.advanceData(); + pixels.stepDithering(); + } + } else { + while(pixels.has(1)) { + writeByte(D::adjust(pixels.loadAndScale0())); + writeByte(D::adjust(pixels.loadAndScale1())); + writeByte(D::adjust(pixels.loadAndScale2())); + pixels.advanceData(); + pixels.stepDithering(); + } + } + D::postBlock(len); + release(); + } +}; + +#endif + +FASTLED_NAMESPACE_END +#endif diff --git a/Библиотеки/FastLED-master/platforms/arm/sam/led_sysdefs_arm_sam.h b/Библиотеки/FastLED-master/platforms/arm/sam/led_sysdefs_arm_sam.h new file mode 100644 index 0000000..a482864 --- /dev/null +++ b/Библиотеки/FastLED-master/platforms/arm/sam/led_sysdefs_arm_sam.h @@ -0,0 +1,39 @@ +#ifndef __INC_LED_SYSDEFS_ARM_SAM_H +#define __INC_LED_SYSDEFS_ARM_SAM_H + + +#define FASTLED_ARM + +// Setup DUE timer defines/channels/etc... +#ifndef DUE_TIMER_CHANNEL +#define DUE_TIMER_GROUP 0 +#endif + +#ifndef DUE_TIMER_CHANNEL +#define DUE_TIMER_CHANNEL 0 +#endif + +#define DUE_TIMER ((DUE_TIMER_GROUP==0) ? TC0 : ((DUE_TIMER_GROUP==1) ? TC1 : TC2)) +#define DUE_TIMER_ID (ID_TC0 + (DUE_TIMER_GROUP*3) + DUE_TIMER_CHANNEL) +#define DUE_TIMER_VAL (DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_CV << 1) +#define DUE_TIMER_RUNNING ((DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_SR & TC_SR_CLKSTA) != 0) + +#ifndef INTERRUPT_THRESHOLD +#define INTERRUPT_THRESHOLD 1 +#endif + +// Default to allowing interrupts +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 1 +#endif + +#if FASTLED_ALLOW_INTERRUPTS == 1 +#define FASTLED_ACCURATE_CLOCK +#endif + +// reusing/abusing cli/sei defs for due +#define cli() __disable_irq(); __disable_fault_irq(); +#define sei() __enable_irq(); __enable_fault_irq(); + + +#endif |