Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/AlexGyver/Arduino_Ambilight.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Библиотеки/FastLED-master/platforms/arm/common/m0clockless.h')
-rw-r--r--Библиотеки/FastLED-master/platforms/arm/common/m0clockless.h318
1 files changed, 318 insertions, 0 deletions
diff --git a/Библиотеки/FastLED-master/platforms/arm/common/m0clockless.h b/Библиотеки/FastLED-master/platforms/arm/common/m0clockless.h
new file mode 100644
index 0000000..11512fd
--- /dev/null
+++ b/Библиотеки/FastLED-master/platforms/arm/common/m0clockless.h
@@ -0,0 +1,318 @@
+#ifndef __INC_M0_CLOCKLESS_H
+#define __INC_M0_CLOCKLESS_H
+
+struct M0ClocklessData {
+ uint8_t d[3];
+ uint8_t e[3];
+ uint8_t adj;
+ uint8_t pad;
+ uint32_t s[3];
+};
+
+
+template<int HI_OFFSET, int LO_OFFSET, int T1, int T2, int T3, EOrder RGB_ORDER, int WAIT_TIME>int
+showLedData(volatile uint32_t *_port, uint32_t _bitmask, const uint8_t *_leds, uint32_t num_leds, struct M0ClocklessData *pData) {
+ // Lo register variables
+ register uint32_t scratch=0;
+ register struct M0ClocklessData *base = pData;
+ register volatile uint32_t *port = _port;
+ register uint32_t d=0;
+ register uint32_t counter=num_leds;
+ register uint32_t bn=0;
+ register uint32_t b=0;
+ register uint32_t bitmask = _bitmask;
+
+ // high register variable
+ register const uint8_t *leds = _leds;
+#if (FASTLED_SCALE8_FIXED == 1)
+ pData->s[0]++;
+ pData->s[1]++;
+ pData->s[2]++;
+#endif
+ asm __volatile__ (
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // asm macro definitions - used to assemble the clockless output
+ //
+ ".ifnotdef fl_delay_def;"
+#ifdef FASTLED_ARM_M0_PLUS
+ " .set fl_is_m0p, 1;"
+ " .macro m0pad;"
+ " nop;"
+ " .endm;"
+#else
+ " .set fl_is_m0p, 0;"
+ " .macro m0pad;"
+ " .endm;"
+#endif
+ " .set fl_delay_def, 1;"
+ " .set fl_delay_mod, 4;"
+ " .if fl_is_m0p == 1;"
+ " .set fl_delay_mod, 3;"
+ " .endif;"
+ " .macro fl_delay dtime, reg=r0;"
+ " .if (\\dtime > 0);"
+ " .set dcycle, (\\dtime / fl_delay_mod);"
+ " .set dwork, (dcycle * fl_delay_mod);"
+ " .set drem, (\\dtime - dwork);"
+ " .rept (drem);"
+ " nop;"
+ " .endr;"
+ " .if dcycle > 0;"
+ " mov \\reg, #dcycle;"
+ " delayloop_\\@:;"
+ " sub \\reg, #1;"
+ " bne delayloop_\\@;"
+ " .if fl_is_m0p == 0;"
+ " nop;"
+ " .endif;"
+ " .endif;"
+ " .endif;"
+ " .endm;"
+
+ " .macro mod_delay dtime,b1,b2,reg;"
+ " .set adj, (\\b1 + \\b2);"
+ " .if adj < \\dtime;"
+ " .set dtime2, (\\dtime - adj);"
+ " fl_delay dtime2, \\reg;"
+ " .endif;"
+ " .endm;"
+
+ // check the bit and drop the line low if it isn't set
+ " .macro qlo4 b,bitmask,port,loff ;"
+ " lsl \\b, #1 ;"
+ " bcs skip_\\@ ;"
+ " str \\bitmask, [\\port, \\loff] ;"
+ " skip_\\@: ;"
+ " m0pad;"
+ " .endm ;"
+
+ // set the pin hi or low (determined by the offset passed in )
+ " .macro qset2 bitmask,port,loff;"
+ " str \\bitmask, [\\port, \\loff];"
+ " m0pad;"
+ " .endm;"
+
+ // Load up the next led byte to work with, put it in bn
+ " .macro loadleds3 leds, bn, rled, scratch;"
+ " mov \\scratch, \\leds;"
+ " ldrb \\bn, [\\scratch, \\rled];"
+ " .endm;"
+
+ // check whether or not we should dither
+ " .macro loaddither7 bn,d,base,rdither;"
+ " ldrb \\d, [\\base, \\rdither];"
+ " lsl \\d, #24;" //; shift high for the qadd w/bn
+ " lsl \\bn, #24;" //; shift high for the qadd w/d
+ " bne chkskip_\\@;" //; if bn==0, clear d;"
+ " eor \\d, \\d;" //; clear d;"
+ " m0pad;"
+ " chkskip_\\@:;"
+ " .endm;"
+
+ // Do the qadd8 for dithering -- there's two versions of this. The m0 version
+ // takes advantage of the 3 cycle branch to do two things after the branch,
+ // while keeping timing constant. The m0+, however, branches in 2 cycles, so
+ // we have to work around that a bit more. This is one of the few times
+ // where the m0 will actually be _more_ efficient than the m0+
+ " .macro dither5 bn,d;"
+ " .syntax unified;"
+ " .if fl_is_m0p == 0;"
+ " adds \\bn, \\d;" // do the add
+ " bcc dither5_1_\\@;"
+ " mvns \\bn, \\bn;" // set the low 24bits ot 1's
+ " lsls \\bn, \\bn, #24;" // move low 8 bits to the high bits
+ " dither5_1_\\@:;"
+ " nop;" // nop to keep timing in line
+ " .else;"
+ " adds \\bn, \\d;" // do the add"
+ " bcc dither5_2_\\@;"
+ " mvns \\bn, \\bn;" // set the low 24bits ot 1's
+ " dither5_2_\\@:;"
+ " bcc dither5_3_\\@;"
+ " lsls \\bn, \\bn, #24;" // move low 8 bits to the high bits
+ " dither5_3_\\@:;"
+ " .endif;"
+ " .syntax divided;"
+ " .endm;"
+
+ // Do our scaling
+ " .macro scale4 bn, base, scale, scratch;"
+ " ldr \\scratch, [\\base, \\scale];"
+ " lsr \\bn, \\bn, #24;" // bring bn back down to its low 8 bits
+ " mul \\bn, \\scratch;" // do the multiply
+ " .endm;"
+
+ // swap bn into b
+ " .macro swapbbn1 b,bn;"
+ " lsl \\b, \\bn, #16;" // put the 8 bits we want for output high
+ " .endm;"
+
+ // adjust the dithering value for the next time around (load e from memory
+ // to do the math)
+ " .macro adjdither7 base,d,rled,eoffset,scratch;"
+ " ldrb \\d, [\\base, \\rled];"
+ " ldrb \\scratch,[\\base,\\eoffset];" // load e
+ " .syntax unified;"
+ " subs \\d, \\scratch, \\d;" // d=e-d
+ " .syntax divided;"
+ " strb \\d, [\\base, \\rled];" // save d
+ " .endm;"
+
+ // increment the led pointer (base+6 has what we're incrementing by)
+ " .macro incleds3 leds, base, scratch;"
+ " ldrb \\scratch, [\\base, #6];" // load incremen
+ " add \\leds, \\leds, \\scratch;" // update leds pointer
+ " .endm;"
+
+ // compare and loop
+ " .macro cmploop5 counter,label;"
+ " .syntax unified;"
+ " subs \\counter, #1;"
+ " .syntax divided;"
+ " beq done_\\@;"
+ " m0pad;"
+ " b \\label;"
+ " done_\\@:;"
+ " .endm;"
+
+ " .endif;"
+ );
+
+#define M0_ASM_ARGS : \
+ [leds] "+h" (leds), \
+ [counter] "+l" (counter), \
+ [scratch] "+l" (scratch), \
+ [d] "+l" (d), \
+ [bn] "+l" (bn), \
+ [b] "+l" (b) \
+ : \
+ [port] "l" (port), \
+ [base] "l" (base), \
+ [bitmask] "l" (bitmask), \
+ [hi_off] "I" (HI_OFFSET), \
+ [lo_off] "I" (LO_OFFSET), \
+ [led0] "I" (RO(0)), \
+ [led1] "I" (RO(1)), \
+ [led2] "I" (RO(2)), \
+ [e0] "I" (3+RO(0)), \
+ [e1] "I" (3+RO(1)), \
+ [e2] "I" (3+RO(2)), \
+ [scale0] "I" (4*(2+RO(0))), \
+ [scale1] "I" (4*(2+RO(1))), \
+ [scale2] "I" (4*(2+RO(2))), \
+ [T1] "I" (T1), \
+ [T2] "I" (T2), \
+ [T3] "I" (T3) \
+ :
+
+ /////////////////////////////////////////////////////////////////////////
+ // now for some convinience macros to make building our lines a bit cleaner
+#define LOOP " loop_%=:"
+#define HI2 " qset2 %[bitmask], %[port], %[hi_off];"
+#define D1 " mod_delay %c[T1],2,0,%[scratch];"
+#define QLO4 " qlo4 %[b],%[bitmask],%[port], %[lo_off];"
+#define LOADLEDS3(X) " loadleds3 %[leds], %[bn], %[led" #X "] ,%[scratch];"
+#define D2(ADJ) " mod_delay %c[T2],4," #ADJ ",%[scratch];"
+#define LO2 " qset2 %[bitmask], %[port], %[lo_off];"
+#define D3(ADJ) " mod_delay %c[T3],2," #ADJ ",%[scratch];"
+#define LOADDITHER7(X) " loaddither7 %[bn], %[d], %[base], %[led" #X "];"
+#define DITHER5 " dither5 %[bn], %[d];"
+#define SCALE4(X) " scale4 %[bn], %[base], %[scale" #X "], %[scratch];"
+#define SWAPBBN1 " swapbbn1 %[b], %[bn];"
+#define ADJDITHER7(X) " adjdither7 %[base],%[d],%[led" #X "],%[e" #X "],%[scratch];"
+#define INCLEDS3 " incleds3 %[leds],%[base],%[scratch];"
+#define CMPLOOP5 " cmploop5 %[counter], loop_%=;"
+#define NOTHING ""
+
+#if !(defined(SEI_CHK) && (FASTLED_ALLOW_INTERRUPTS == 1))
+ // We're not allowing interrupts - run the entire loop in asm to keep things
+ // as tight as possible. In an ideal world, we should be pushing out ws281x
+ // leds (or other 3-wire leds) with zero gaps between pixels.
+ asm __volatile__ (
+ // pre-load byte 0
+ LOADLEDS3(0) LOADDITHER7(0) DITHER5 SCALE4(0) ADJDITHER7(0) SWAPBBN1
+
+ // loop over writing out the data
+ LOOP
+ // Write out byte 0, prepping byte 1
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(1) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(1) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(1) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(1) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(0)
+
+ // Write out byte 1, prepping byte 2
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(2) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(2) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(2) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(2) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 INCLEDS3 D2(3) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(0)
+
+ // Write out byte 2, prepping byte 0
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(0) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(0) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(0) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(0) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(5) CMPLOOP5
+
+ M0_ASM_ARGS
+ );
+#else
+ // We're allowing interrupts - track the loop outside the asm code, to allow
+ // inserting the interrupt overrun checks.
+ asm __volatile__ (
+ // pre-load byte 0
+ LOADLEDS3(0) LOADDITHER7(0) DITHER5 SCALE4(0) ADJDITHER7(0) SWAPBBN1
+ M0_ASM_ARGS);
+
+ do {
+ asm __volatile__ (
+ // Write out byte 0, prepping byte 1
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(1) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(1) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(1) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(1) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(0)
+
+ // Write out byte 1, prepping byte 2
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(2) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(2) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(2) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(2) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(0)
+
+ // Write out byte 2, prepping byte 0
+ HI2 D1 QLO4 INCLEDS3 D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADLEDS3(0) D2(3) LO2 D3(0)
+ HI2 D1 QLO4 LOADDITHER7(0) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 DITHER5 D2(5) LO2 D3(0)
+ HI2 D1 QLO4 SCALE4(0) D2(4) LO2 D3(0)
+ HI2 D1 QLO4 ADJDITHER7(0) D2(7) LO2 D3(0)
+ HI2 D1 QLO4 NOTHING D2(0) LO2 D3(0)
+ HI2 D1 QLO4 SWAPBBN1 D2(1) LO2 D3(5)
+
+ M0_ASM_ARGS
+ );
+ SEI_CHK; INNER_SEI; --counter; CLI_CHK;
+ } while(counter);
+#endif
+ return num_leds;
+}
+
+#endif