Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 46 additions & 125 deletions Adafruit_NeoPixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,138 +991,141 @@ void Adafruit_NeoPixel::show(void) {
asm volatile(
"headF:"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n2] , %[lo]"
"\n\t"
"out %[port] , %[n1]"
"sts %[port] , %[n1]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 6"
"\n\t"
"mov %[n2] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n1] , %[lo]"
"\n\t"
"out %[port] , %[n2]"
"sts %[port] , %[n2]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 5"
"\n\t"
"mov %[n1] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n2] , %[lo]"
"\n\t"
"out %[port] , %[n1]"
"sts %[port] , %[n1]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 4"
"\n\t"
"mov %[n2] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n1] , %[lo]"
"\n\t"
"out %[port] , %[n2]"
"sts %[port] , %[n2]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 3"
"\n\t"
"mov %[n1] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n2] , %[lo]"
"\n\t"
"out %[port] , %[n1]"
"sts %[port] , %[n1]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 2"
"\n\t"
"mov %[n2] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n1] , %[lo]"
"\n\t"
"out %[port] , %[n2]"
"sts %[port] , %[n2]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 1"
"\n\t"
"mov %[n1] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"rjmp .+0"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n2] , %[lo]"
"\n\t"
"out %[port] , %[n1]"
"sts %[port] , %[n1]"
"\n\t"
"rjmp .+0"
"\n\t"
"sbrc %[byte] , 0"
"\n\t"
"mov %[n2] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"sbiw %[count], 1"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"mov %[n1] , %[lo]"
"\n\t"
"out %[port] , %[n2]"
"sts %[port] , %[n2]"
"\n\t"
"ld %[byte] , %a[ptr]+"
"\n\t"
"sbrc %[byte] , 7"
"\n\t"
"mov %[n1] , %[hi]"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"brne headF"
"in __tmp_reg__, __SREG__"
"\n\t"
"sbrs __tmp_reg__, %[avr_sreg_z]"
"\n\t"
"jmp headF"
"\n"
: [byte] "+r"(b), [n1] "+r"(n1), [n2] "+r"(n2), [count] "+w"(i)
: [port] "I"(_SFR_IO_ADDR(PORTF)), [ptr] "e"(ptr), [hi] "r"(hi),
[lo] "r"(lo));

: [port] "M"(_SFR_MEM_ADDR(PORTF)), [ptr] "e"(ptr), [hi] "r"(hi),
[lo] "r"(lo), [avr_sreg_z] "I"(SREG_Z));
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
}
#endif // defined(PORTD/B/C)
Expand Down Expand Up @@ -1527,41 +1530,41 @@ void Adafruit_NeoPixel::show(void) {
// Same as above, just set for PORTF & stripped of comments
asm volatile("headF:"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port], %[hi]"
"sts %[port], %[hi]"
"\n\t"
"rcall bitTimeC"
"\n\t"
"out %[port] , %[hi]"
"sts %[port] , %[hi]"
"\n\t"
"rjmp .+0"
"\n\t"
"ld %[byte] , %a[ptr]+"
"\n\t"
"out %[port] , %[next]"
"sts %[port] , %[next]"
"\n\t"
"mov %[next] , %[lo]"
"\n\t"
Expand All @@ -1571,7 +1574,7 @@ void Adafruit_NeoPixel::show(void) {
"\n\t"
"nop"
"\n\t"
"out %[port] , %[lo]"
"sts %[port] , %[lo]"
"\n\t"
"sbiw %[count], 1"
"\n\t"
Expand All @@ -1581,7 +1584,7 @@ void Adafruit_NeoPixel::show(void) {
"\n\t"
"bitTimeC:"
"\n\t"
"out %[port], %[next]"
"sts %[port], %[next]"
"\n\t"
"mov %[next], %[lo]"
"\n\t"
Expand All @@ -1593,14 +1596,14 @@ void Adafruit_NeoPixel::show(void) {
"\n\t"
"nop"
"\n\t"
"out %[port], %[lo]"
"sts %[port], %[lo]"
"\n\t"
"ret"
"\n\t"
"doneC:"
"\n"
: [byte] "+r"(b), [next] "+r"(next), [count] "+w"(i)
: [port] "I"(_SFR_IO_ADDR(PORTF)), [ptr] "e"(ptr),
: [port] "M"(_SFR_MEM_ADDR(PORTF)), [ptr] "e"(ptr),
[hi] "r"(hi), [lo] "r"(lo));

#if defined(PORTD) || defined(PORTB) || defined(PORTC)
Expand Down Expand Up @@ -2424,7 +2427,7 @@ void Adafruit_NeoPixel::show(void) {

#elif defined(__SAMD21E17A__) || defined(__SAMD21G18A__) || \
defined(__SAMD21E18A__) || defined(__SAMD21J18A__) || \
defined(__SAMD11C14A__) || defined(__SAMD21G17A__)
defined (__SAMD11C14A__)
// Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo
// and others
// Tried this with a timer/counter, couldn't quite get adequate
Expand Down Expand Up @@ -3082,89 +3085,7 @@ if(is800KHz) {
; // Wait for last bit
TC_Stop(TC1, 0);


// RENESAS including UNO R4
#elif defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_RENESAS_UNO) || defined(ARDUINO_ARCH_RENESAS_PORTENTA)

// Definition for a single channel clockless controller for RA4M1 (Cortex M4)
// See clockless.h for detailed info on how the template parameters are used.
#define ARM_DEMCR (*(volatile uint32_t *)0xE000EDFC) // Debug Exception and Monitor Control
#define ARM_DEMCR_TRCENA (1 << 24) // Enable debugging & monitoring blocks
#define ARM_DWT_CTRL (*(volatile uint32_t *)0xE0001000) // DWT control register
#define ARM_DWT_CTRL_CYCCNTENA (1 << 0) // Enable cycle count
#define ARM_DWT_CYCCNT (*(volatile uint32_t *)0xE0001004) // Cycle count register

#define F_CPU 48000000
#define CYCLES_800_T0H (F_CPU / 4000000)
#define CYCLES_800_T1H (F_CPU / 1250000)
#define CYCLES_800 (F_CPU / 800000)
#define CYCLES_400_T0H (F_CPU / 2000000)
#define CYCLES_400_T1H (F_CPU / 833333)
#define CYCLES_400 (F_CPU / 400000)

uint8_t *p = pixels, *end = p + numBytes, pix, mask;

bsp_io_port_pin_t io_pin = g_pin_cfg[pin].pin;
#define PIN_IO_PORT_ADDR(pn) (R_PORT0 + ((uint32_t) (R_PORT1 - R_PORT0) * ((pn) >> 8u)))

volatile uint16_t *set = &(PIN_IO_PORT_ADDR(io_pin)->POSR);
volatile uint16_t *clr = &(PIN_IO_PORT_ADDR(io_pin)->PORR);
uint16_t msk = (1U << (io_pin & 0xFF));

uint32_t cyc;

ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;

#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if (is800KHz) {
#endif
cyc = ARM_DWT_CYCCNT + CYCLES_800;
while (p < end) {
pix = *p++;
for (mask = 0x80; mask; mask >>= 1) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
;
cyc = ARM_DWT_CYCCNT;
*set = msk;
if (pix & mask) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H)
;
} else {
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H)
;
}
*clr = msk;
}
}
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
;
#if defined(NEO_KHZ400)
} else { // 400 kHz bitstream
cyc = ARM_DWT_CYCCNT + CYCLES_400;
while (p < end) {
pix = *p++;
for (mask = 0x80; mask; mask >>= 1) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400)
;
cyc = ARM_DWT_CYCCNT;
*set = msk;
if (pix & mask) {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H)
;
} else {
while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H)
;
}
*clr = msk;
}
}
while (ARM_DWT_CYCCNT - cyc < CYCLES_400)
;
}
#endif // NEO_KHZ400

#endif // ARM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you remove this?!

This code works beautifully.

#endif // end Due

// END ARM ----------------------------------------------------------------

Expand Down