Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
co2ampel
ampel-firmware
Commits
a224c1fa
Commit
a224c1fa
authored
3 years ago
by
Eric Duminil
Browse files
Options
Download
Email Patches
Plain Diff
Update NeoPixel to 1.10.3
parent
9d9f4ebf
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
+2161
-1323
...-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
+165
-121
ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
ampel-firmware/src/lib/Adafruit_NeoPixel/README.md
+4
-0
ampel-firmware/src/lib/Adafruit_NeoPixel/README.md
ampel-firmware/src/lib/Adafruit_NeoPixel/esp.c
+16
-0
ampel-firmware/src/lib/Adafruit_NeoPixel/esp.c
ampel-firmware/src/lib/Adafruit_NeoPixel/esp8266.c
+5
-5
ampel-firmware/src/lib/Adafruit_NeoPixel/esp8266.c
ampel-firmware/src/lib/Adafruit_NeoPixel/library.properties
+1
-1
ampel-firmware/src/lib/Adafruit_NeoPixel/library.properties
ampel-firmware/src/lib/Adafruit_NeoPixel/rp2040_pio.h
+63
-0
ampel-firmware/src/lib/Adafruit_NeoPixel/rp2040_pio.h
with
2415 additions
and
1450 deletions
+2415
-1450
ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
+
2161
-
1323
View file @
a224c1fa
...
@@ -46,7 +46,7 @@
...
@@ -46,7 +46,7 @@
#include
"Adafruit_NeoPixel.h"
#include
"Adafruit_NeoPixel.h"
#if defined(TARGET_LPC1768)
#if defined(TARGET_LPC1768)
#include
<time.h>
#include
<time.h>
#endif
#endif
#if defined(NRF52) || defined(NRF52_SERIES)
#if defined(NRF52) || defined(NRF52_SERIES)
...
@@ -57,6 +57,14 @@
...
@@ -57,6 +57,14 @@
//#define NRF52_DISABLE_INT
//#define NRF52_DISABLE_INT
#endif
#endif
#if defined(ARDUINO_ARCH_NRF52840)
#if defined __has_include
#if __has_include(<pinDefinitions.h>)
#include
<pinDefinitions.h>
#endif
#endif
#endif
/*!
/*!
@brief NeoPixel constructor when length, pin and pixel type are known
@brief NeoPixel constructor when length, pin and pixel type are known
at compile-time.
at compile-time.
...
@@ -69,11 +77,21 @@
...
@@ -69,11 +77,21 @@
pixel.
pixel.
@return Adafruit_NeoPixel object. Call the begin() function before use.
@return Adafruit_NeoPixel object. Call the begin() function before use.
*/
*/
Adafruit_NeoPixel
::
Adafruit_NeoPixel
(
uint16_t
n
,
u
int16_t
p
,
neoPixelType
t
)
:
Adafruit_NeoPixel
::
Adafruit_NeoPixel
(
uint16_t
n
,
int16_t
p
,
neoPixelType
t
)
begun
(
false
),
brightness
(
0
),
pixels
(
NULL
),
endTime
(
0
)
{
:
begun
(
false
),
brightness
(
0
),
pixels
(
NULL
),
endTime
(
0
)
{
updateType
(
t
);
updateType
(
t
);
updateLength
(
n
);
updateLength
(
n
);
setPin
(
p
);
setPin
(
p
);
#if defined(ARDUINO_ARCH_RP2040)
// Find a free SM on one of the PIO's
sm
=
pio_claim_unused_sm
(
pio
,
false
);
// don't panic
// Try pio1 if SM not found
if
(
sm
<
0
)
{
pio
=
pio1
;
sm
=
pio_claim_unused_sm
(
pio
,
true
);
// panic if no SM is free
}
init
=
true
;
#endif
}
}
/*!
/*!
...
@@ -86,12 +104,13 @@ Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, uint16_t p, neoPixelType t) :
...
@@ -86,12 +104,13 @@ Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, uint16_t p, neoPixelType t) :
'new' keyword with the first constructor syntax (length, pin,
'new' keyword with the first constructor syntax (length, pin,
type).
type).
*/
*/
Adafruit_NeoPixel
::
Adafruit_NeoPixel
()
:
Adafruit_NeoPixel
::
Adafruit_NeoPixel
()
:
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
is800KHz
(
true
),
is800KHz
(
true
),
#endif
#endif
begun
(
false
),
numLEDs
(
0
),
numBytes
(
0
),
pin
(
-
1
),
brightness
(
0
),
pixels
(
NULL
),
begun
(
false
),
numLEDs
(
0
),
numBytes
(
0
),
pin
(
-
1
),
brightness
(
0
),
rOffset
(
1
),
gOffset
(
0
),
bOffset
(
2
),
wOffset
(
1
),
endTime
(
0
)
{
pixels
(
NULL
),
rOffset
(
1
),
gOffset
(
0
),
bOffset
(
2
),
wOffset
(
1
),
endTime
(
0
)
{
}
}
/*!
/*!
...
@@ -99,14 +118,15 @@ Adafruit_NeoPixel::Adafruit_NeoPixel() :
...
@@ -99,14 +118,15 @@ Adafruit_NeoPixel::Adafruit_NeoPixel() :
*/
*/
Adafruit_NeoPixel
::~
Adafruit_NeoPixel
()
{
Adafruit_NeoPixel
::~
Adafruit_NeoPixel
()
{
free
(
pixels
);
free
(
pixels
);
if
(
pin
>=
0
)
pinMode
(
pin
,
INPUT
);
if
(
pin
>=
0
)
pinMode
(
pin
,
INPUT
);
}
}
/*!
/*!
@brief Configure NeoPixel pin for output.
@brief Configure NeoPixel pin for output.
*/
*/
void
Adafruit_NeoPixel
::
begin
(
void
)
{
void
Adafruit_NeoPixel
::
begin
(
void
)
{
if
(
pin
>=
0
)
{
if
(
pin
>=
0
)
{
pinMode
(
pin
,
OUTPUT
);
pinMode
(
pin
,
OUTPUT
);
digitalWrite
(
pin
,
LOW
);
digitalWrite
(
pin
,
LOW
);
}
}
...
@@ -128,7 +148,7 @@ void Adafruit_NeoPixel::updateLength(uint16_t n) {
...
@@ -128,7 +148,7 @@ void Adafruit_NeoPixel::updateLength(uint16_t n) {
// Allocate new data -- note: ALL PIXELS ARE CLEARED
// Allocate new data -- note: ALL PIXELS ARE CLEARED
numBytes
=
n
*
((
wOffset
==
rOffset
)
?
3
:
4
);
numBytes
=
n
*
((
wOffset
==
rOffset
)
?
3
:
4
);
if
((
pixels
=
(
uint8_t
*
)
malloc
(
numBytes
)))
{
if
((
pixels
=
(
uint8_t
*
)
malloc
(
numBytes
)))
{
memset
(
pixels
,
0
,
numBytes
);
memset
(
pixels
,
0
,
numBytes
);
numLEDs
=
n
;
numLEDs
=
n
;
}
else
{
}
else
{
...
@@ -159,36 +179,71 @@ void Adafruit_NeoPixel::updateType(neoPixelType t) {
...
@@ -159,36 +179,71 @@ void Adafruit_NeoPixel::updateType(neoPixelType t) {
wOffset
=
(
t
>>
6
)
&
0b11
;
// See notes in header file
wOffset
=
(
t
>>
6
)
&
0b11
;
// See notes in header file
rOffset
=
(
t
>>
4
)
&
0b11
;
// regarding R/G/B/W offsets
rOffset
=
(
t
>>
4
)
&
0b11
;
// regarding R/G/B/W offsets
gOffset
=
(
t
>>
2
)
&
0b11
;
gOffset
=
(
t
>>
2
)
&
0b11
;
bOffset
=
t
&
0b11
;
bOffset
=
t
&
0b11
;
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
is800KHz
=
(
t
<
256
);
// 400 KHz flag is 1<<8
is800KHz
=
(
t
<
256
);
// 400 KHz flag is 1<<8
#endif
#endif
// If bytes-per-pixel has changed (and pixel data was previously
// If bytes-per-pixel has changed (and pixel data was previously
// allocated), re-allocate to new size. Will clear any data.
// allocated), re-allocate to new size. Will clear any data.
if
(
pixels
)
{
if
(
pixels
)
{
bool
newThreeBytesPerPixel
=
(
wOffset
==
rOffset
);
bool
newThreeBytesPerPixel
=
(
wOffset
==
rOffset
);
if
(
newThreeBytesPerPixel
!=
oldThreeBytesPerPixel
)
updateLength
(
numLEDs
);
if
(
newThreeBytesPerPixel
!=
oldThreeBytesPerPixel
)
updateLength
(
numLEDs
);
}
}
// RP2040 specific driver
#if defined(ARDUINO_ARCH_RP2040)
void
Adafruit_NeoPixel
::
rp2040Init
(
uint8_t
pin
,
bool
is800KHz
)
{
uint
offset
=
pio_add_program
(
pio
,
&
ws2812_program
);
if
(
is800KHz
)
{
// 800kHz, 8 bit transfers
ws2812_program_init
(
pio
,
sm
,
offset
,
pin
,
800000
,
8
);
}
else
{
// 400kHz, 8 bit transfers
ws2812_program_init
(
pio
,
sm
,
offset
,
pin
,
400000
,
8
);
}
}
}
}
// Not a user API
void
Adafruit_NeoPixel
::
rp2040Show
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
bool
is800KHz
)
{
if
(
this
->
init
)
{
// On first pass through initialise the PIO
rp2040Init
(
pin
,
is800KHz
);
this
->
init
=
false
;
}
while
(
numBytes
--
)
// Bits for transmission must be shifted to top 8 bits
pio_sm_put_blocking
(
pio
,
sm
,
((
uint32_t
)
*
pixels
++
)
<<
24
);
}
#endif
#if defined(ESP8266)
#if defined(ESP8266)
// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
extern
"C"
void
ICACHE_
RAM_ATTR
espShow
(
extern
"C"
I
RAM_ATTR
void
espShow
(
uint16_t
pin
,
uint8_t
*
pixels
,
uint16_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
uint8_t
type
);
uint32_t
numBytes
,
uint8_t
type
);
#elif defined(ESP32)
#elif defined(ESP32)
extern
"C"
void
espShow
(
extern
"C"
void
espShow
(
uint16_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
uint16_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
uint8_t
type
);
uint8_t
type
);
#endif // ESP8266
#endif // ESP8266
#if defined(K210)
#if defined(K210)
#define KENDRYTE_K210 1
#define KENDRYTE_K210 1
#endif
#endif
#if defined(KENDRYTE_K210)
#if defined(KENDRYTE_K210)
extern
"C"
void
k210Show
(
extern
"C"
void
k210Show
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
boolean
is800KHz
);
boolean
is800KHz
);
#endif //KENDRYTE_K210
#endif //
KENDRYTE_K210
/*!
/*!
@brief Transmit pixel data in RAM to NeoPixels.
@brief Transmit pixel data in RAM to NeoPixels.
@note On most architectures, interrupts are temporarily disabled in
@note On most architectures, interrupts are temporarily disabled in
...
@@ -202,7 +257,8 @@ extern "C" void k210Show(
...
@@ -202,7 +257,8 @@ extern "C" void k210Show(
*/
*/
void
Adafruit_NeoPixel
::
show
(
void
)
{
void
Adafruit_NeoPixel
::
show
(
void
)
{
if
(
!
pixels
)
return
;
if
(
!
pixels
)
return
;
// Data latch = 300+ microsecond pause in the output stream. Rather than
// Data latch = 300+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// put a delay at the end of the function, the ending time is noted and
...
@@ -210,36 +266,35 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -210,36 +266,35 @@ void Adafruit_NeoPixel::show(void) {
// subsequent round of data until the latch time has elapsed. This
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
// rather than stalling for the latch.
while
(
!
canShow
());
while
(
!
canShow
())
// endTime is a private member (rather than global var) so that multiple
;
// instances on different pins can be quickly issued in succession (each
// endTime is a private member (rather than global var) so that multiple
// instance doesn't delay the next).
// instances on different pins can be quickly issued in succession (each
// instance doesn't delay the next).
// In order to make this code runtime-configurable to work with any pin,
// SBI/CBI instructions are eschewed in favor of full PORT writes via the
// In order to make this code runtime-configurable to work with any pin,
// OUT or ST instructions. It relies on two facts: that peripheral
// SBI/CBI instructions are eschewed in favor of full PORT writes via the
// functions (such as PWM) take precedence on output pins, so our PORT-
// OUT or ST instructions. It relies on two facts: that peripheral
// wide writes won't interfere, and that interrupts are globally disabled
// functions (such as PWM) take precedence on output pins, so our PORT-
// while data is being issued to the LEDs, so no other code will be
// wide writes won't interfere, and that interrupts are globally disabled
// accessing the PORT. The code takes an initial 'snapshot' of the PORT
// while data is being issued to the LEDs, so no other code will be
// state, computes 'pin high' and 'pin low' values, and writes these back
// accessing the PORT. The code takes an initial 'snapshot' of the PORT
// to the PORT register as needed.
// state, computes 'pin high' and 'pin low' values, and writes these back
// to the PORT register as needed.
// NRF52 may use PWM + DMA (if available), may not need to disable interrupt
#if !( defined(NRF52) || defined(NRF52_SERIES) )
// NRF52 may use PWM + DMA (if available), may not need to disable interrupt
#if !(defined(NRF52) || defined(NRF52_SERIES))
noInterrupts
();
// Need 100% focus on instruction timing
noInterrupts
();
// Need 100% focus on instruction timing
#endif
#endif
#if defined(__AVR__)
#if defined(__AVR__)
// AVR MCUs -- ATmega & ATtiny (no XMEGA) ---------------------------------
// AVR MCUs -- ATmega & ATtiny (no XMEGA) ---------------------------------
volatile
uint16_t
volatile
uint16_t
i
=
numBytes
;
// Loop counter
i
=
numBytes
;
// Loop counter
volatile
uint8_t
*
ptr
=
pixels
,
// Pointer to next byte
volatile
uint8_t
b
=
*
ptr
++
,
// Current byte value
*
ptr
=
pixels
,
// Pointer to next byte
hi
,
// PORT w/output bit set high
b
=
*
ptr
++
,
// Current byte value
lo
;
// PORT w/output bit set low
hi
,
// PORT w/output bit set high
lo
;
// PORT w/output bit set low
// Hand-tuned assembly code issues data to the LED drivers at a specific
// Hand-tuned assembly code issues data to the LED drivers at a specific
// rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
// rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
...
@@ -259,10 +314,10 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -259,10 +314,10 @@ void Adafruit_NeoPixel::show(void) {
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
volatile
uint8_t
n1
,
n2
=
0
;
// First, next bits out
volatile
uint8_t
n1
,
n2
=
0
;
// First, next bits out
// Squeezing an 800 KHz stream out of an 8 MHz chip requires code
// Squeezing an 800 KHz stream out of an 8 MHz chip requires code
// specific to each PORT register.
// specific to each PORT register.
...
@@ -273,14 +328,15 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -273,14 +328,15 @@ void Adafruit_NeoPixel::show(void) {
// PORTD OUTPUT ----------------------------------------------------
// PORTD OUTPUT ----------------------------------------------------
#if defined(PORTD)
#if defined(PORTD)
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
if
(
port
==
&
PORTD
)
{
if
(
port
==
&
PORTD
)
{
#endif // defined(PORTB/C/F)
#endif // defined(PORTB/C/F)
hi
=
PORTD
|
pinMask
;
hi
=
PORTD
|
pinMask
;
lo
=
PORTD
&
~
pinMask
;
lo
=
PORTD
&
~
pinMask
;
n1
=
lo
;
n1
=
lo
;
if
(
b
&
0x80
)
n1
=
hi
;
if
(
b
&
0x80
)
n1
=
hi
;
// Dirty trick: RJMPs proceeding to the next instruction are used
// Dirty trick: RJMPs proceeding to the next instruction are used
// to delay two clock cycles in one instruction word (rather than
// to delay two clock cycles in one instruction word (rather than
...
@@ -289,360 +345,618 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -289,360 +345,618 @@ void Adafruit_NeoPixel::show(void) {
// relative branch.
// relative branch.
asm
volatile
(
asm
volatile
(
"headD:"
"
\n\t
"
// Clk Pseudocode
"headD:"
// Bit 7:
"
\n\t
"
// Clk Pseudocode
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
// Bit 7:
"mov %[n2] , %[lo]"
"
\n\t
"
// 1 n2 = lo
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
// 1 PORT = n1
"
\n\t
"
// 1 PORT = hi
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"mov %[n2] , %[lo]"
"sbrc %[byte] , 6"
"
\n\t
"
// 1-2 if(b & 0x40)
"
\n\t
"
// 1 n2 = lo
"mov %[n2] , %[hi]"
"
\n\t
"
// 0-1 n2 = hi
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"
\n\t
"
// 1 PORT = n1
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"rjmp .+0"
// Bit 6:
"
\n\t
"
// 2 nop nop
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"sbrc %[byte] , 6"
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"
\n\t
"
// 1-2 if(b & 0x40)
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"mov %[n2] , %[hi]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 0-1 n2 = hi
"sbrc %[byte] , 5"
"
\n\t
"
// 1-2 if(b & 0x20)
"out %[port] , %[lo]"
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
"
\n\t
"
// 1 PORT = lo
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 2 nop nop
// Bit 5:
// Bit 6:
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"out %[port] , %[hi]"
"mov %[n2] , %[lo]"
"
\n\t
"
// 1 n2 = lo
"
\n\t
"
// 1 PORT = hi
"out %[port] , %[n1]"
"
\n\t
"
// 1 PORT = n1
"mov %[n1] , %[lo]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 1 n1 = lo
"sbrc %[byte] , 4"
"
\n\t
"
// 1-2 if(b & 0x10)
"out %[port] , %[n2]"
"mov %[n2] , %[hi]"
"
\n\t
"
// 0-1 n2 = hi
"
\n\t
"
// 1 PORT = n2
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 2 nop nop
// Bit 4:
"sbrc %[byte] , 5"
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"
\n\t
"
// 1-2 if(b & 0x20)
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"mov %[n1] , %[hi]"
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"
\n\t
"
// 0-1 n1 = hi
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"out %[port] , %[lo]"
"sbrc %[byte] , 3"
"
\n\t
"
// 1-2 if(b & 0x08)
"
\n\t
"
// 1 PORT = lo
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
"rjmp .+0"
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"
\n\t
"
// 2 nop nop
"rjmp .+0"
"
\n\t
"
// 2 nop nop
// Bit 5:
// Bit 3:
"out %[port] , %[hi]"
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"
\n\t
"
// 1 PORT = hi
"mov %[n2] , %[lo]"
"
\n\t
"
// 1 n2 = lo
"mov %[n2] , %[lo]"
"out %[port] , %[n1]"
"
\n\t
"
// 1 PORT = n1
"
\n\t
"
// 1 n2 = lo
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"out %[port] , %[n1]"
"sbrc %[byte] , 2"
"
\n\t
"
// 1-2 if(b & 0x04)
"
\n\t
"
// 1 PORT = n1
"mov %[n2] , %[hi]"
"
\n\t
"
// 0-1 n2 = hi
"rjmp .+0"
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"
\n\t
"
// 2 nop nop
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"sbrc %[byte] , 4"
// Bit 2:
"
\n\t
"
// 1-2 if(b & 0x10)
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"mov %[n2] , %[hi]"
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"
\n\t
"
// 0-1 n2 = hi
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"out %[port] , %[lo]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 1 PORT = lo
"sbrc %[byte] , 1"
"
\n\t
"
// 1-2 if(b & 0x02)
"rjmp .+0"
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
"
\n\t
"
// 2 nop nop
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
// Bit 4:
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"out %[port] , %[hi]"
// Bit 1:
"
\n\t
"
// 1 PORT = hi
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"mov %[n1] , %[lo]"
"mov %[n2] , %[lo]"
"
\n\t
"
// 1 n2 = lo
"
\n\t
"
// 1 n1 = lo
"out %[port] , %[n1]"
"
\n\t
"
// 1 PORT = n1
"out %[port] , %[n2]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"
\n\t
"
// 1 PORT = n2
"sbrc %[byte] , 0"
"
\n\t
"
// 1-2 if(b & 0x01)
"rjmp .+0"
"mov %[n2] , %[hi]"
"
\n\t
"
// 0-1 n2 = hi
"
\n\t
"
// 2 nop nop
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"sbrc %[byte] , 3"
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (don't act on Z flag yet)
"
\n\t
"
// 1-2 if(b & 0x08)
// Bit 0:
"mov %[n1] , %[hi]"
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"
\n\t
"
// 0-1 n1 = hi
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"out %[port] , %[lo]"
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"
\n\t
"
// 1 PORT = lo
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++
"rjmp .+0"
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 0x80)
"
\n\t
"
// 2 nop nop
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
// Bit 3:
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"out %[port] , %[hi]"
"brne headD"
"
\n
"
// 2 while(i) (Z flag set above)
"
\n\t
"
// 1 PORT = hi
:
[
byte
]
"+r"
(
b
),
"mov %[n2] , %[lo]"
[
n1
]
"+r"
(
n1
),
"
\n\t
"
// 1 n2 = lo
[
n2
]
"+r"
(
n2
),
"out %[port] , %[n1]"
[
count
]
"+w"
(
i
)
"
\n\t
"
// 1 PORT = n1
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTD
)),
"rjmp .+0"
[
ptr
]
"e"
(
ptr
),
"
\n\t
"
// 2 nop nop
[
hi
]
"r"
(
hi
),
"sbrc %[byte] , 2"
[
lo
]
"r"
(
lo
));
"
\n\t
"
// 1-2 if(b & 0x04)
"mov %[n2] , %[hi]"
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
"
\n\t
"
// 0-1 n2 = hi
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"rjmp .+0"
"
\n\t
"
// 2 nop nop
// Bit 2:
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"sbrc %[byte] , 1"
"
\n\t
"
// 1-2 if(b & 0x02)
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"rjmp .+0"
"
\n\t
"
// 2 nop nop
// Bit 1:
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"mov %[n2] , %[lo]"
"
\n\t
"
// 1 n2 = lo
"out %[port] , %[n1]"
"
\n\t
"
// 1 PORT = n1
"rjmp .+0"
"
\n\t
"
// 2 nop nop
"sbrc %[byte] , 0"
"
\n\t
"
// 1-2 if(b & 0x01)
"mov %[n2] , %[hi]"
"
\n\t
"
// 0-1 n2 = hi
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (don't act on Z flag yet)
// Bit 0:
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi
"mov %[n1] , %[lo]"
"
\n\t
"
// 1 n1 = lo
"out %[port] , %[n2]"
"
\n\t
"
// 1 PORT = n2
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 0x80)
"mov %[n1] , %[hi]"
"
\n\t
"
// 0-1 n1 = hi
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo
"brne headD"
"
\n
"
// 2 while(i) (Z flag set above)
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTD
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
}
else
// other PORT(s)
}
else
// other PORT(s)
#endif // defined(PORTB/C/F)
#endif // defined(PORTB/C/F)
#endif // defined(PORTD)
#endif // defined(PORTD)
// PORTB OUTPUT ----------------------------------------------------
// PORTB OUTPUT ----------------------------------------------------
#if defined(PORTB)
#if defined(PORTB)
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
if
(
port
==
&
PORTB
)
{
if
(
port
==
&
PORTB
)
{
#endif // defined(PORTD/C/F)
#endif // defined(PORTD/C/F)
// Same as above, just switched to PORTB and stripped of comments.
// Same as above, just switched to PORTB and stripped of comments.
hi
=
PORTB
|
pinMask
;
hi
=
PORTB
|
pinMask
;
lo
=
PORTB
&
~
pinMask
;
lo
=
PORTB
&
~
pinMask
;
n1
=
lo
;
n1
=
lo
;
if
(
b
&
0x80
)
n1
=
hi
;
if
(
b
&
0x80
)
n1
=
hi
;
asm
volatile
(
asm
volatile
(
"headB:"
"
\n\t
"
"headB:"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 6"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 6"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 5"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 4"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 5"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 3"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 2"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 4"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 1"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 0"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 3"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"brne headB"
"
\n
"
"rjmp .+0"
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
"
\n\t
"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTB
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"out %[port] , %[hi]"
[
lo
]
"r"
(
lo
));
"
\n\t
"
"mov %[n2] , %[lo]"
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 2"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 1"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 0"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"sbrc %[byte] , 7"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"brne headB"
"
\n
"
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTB
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
}
}
#endif
#endif
#if defined(PORTC) || defined(PORTF)
#if defined(PORTC) || defined(PORTF)
else
else
#endif // defined(PORTC/F)
#endif // defined(PORTC/F)
#endif // defined(PORTB)
#endif // defined(PORTB)
// PORTC OUTPUT ----------------------------------------------------
// PORTC OUTPUT ----------------------------------------------------
#if defined(PORTC)
#if defined(PORTC)
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
if
(
port
==
&
PORTC
)
{
if
(
port
==
&
PORTC
)
{
#endif // defined(PORTD/B/F)
#endif // defined(PORTD/B/F)
// Same as above, just switched to PORTC and stripped of comments.
// Same as above, just switched to PORTC and stripped of comments.
hi
=
PORTC
|
pinMask
;
hi
=
PORTC
|
pinMask
;
lo
=
PORTC
&
~
pinMask
;
lo
=
PORTC
&
~
pinMask
;
n1
=
lo
;
n1
=
lo
;
if
(
b
&
0x80
)
n1
=
hi
;
if
(
b
&
0x80
)
n1
=
hi
;
asm
volatile
(
asm
volatile
(
"headC:"
"
\n\t
"
"headC:"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 6"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 6"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 5"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 4"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 5"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 3"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 2"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 4"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 1"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 0"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 3"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"brne headC"
"
\n
"
"rjmp .+0"
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
"
\n\t
"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTC
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"out %[port] , %[hi]"
[
lo
]
"r"
(
lo
));
"
\n\t
"
"mov %[n2] , %[lo]"
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 2"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 1"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 0"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"sbrc %[byte] , 7"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"brne headC"
"
\n
"
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTC
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
}
}
#endif // defined(PORTD/B/F)
#endif // defined(PORTD/B/F)
#if defined(PORTF)
#if defined(PORTF)
else
else
#endif
#endif
#endif // defined(PORTC)
#endif // defined(PORTC)
// PORTF OUTPUT ----------------------------------------------------
// PORTF OUTPUT ----------------------------------------------------
#if defined(PORTF)
#if defined(PORTF)
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
if
(
port
==
&
PORTF
)
{
if
(
port
==
&
PORTF
)
{
#endif // defined(PORTD/B/C)
#endif // defined(PORTD/B/C)
hi
=
PORTF
|
pinMask
;
hi
=
PORTF
|
pinMask
;
lo
=
PORTF
&
~
pinMask
;
lo
=
PORTF
&
~
pinMask
;
n1
=
lo
;
n1
=
lo
;
if
(
b
&
0x80
)
n1
=
hi
;
if
(
b
&
0x80
)
n1
=
hi
;
asm
volatile
(
asm
volatile
(
"headF:"
"
\n\t
"
"headF:"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 6"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 6"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 5"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 4"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 5"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 3"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[lo]"
"sbrc %[byte] , 2"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n1]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 4"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n2] , %[hi]"
"sbrc %[byte] , 1"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"out %[port] , %[n1]"
"
\n\t
"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"mov %[n1] , %[lo]"
"sbrc %[byte] , 0"
"
\n\t
"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[n2]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"rjmp .+0"
"out %[port] , %[hi]"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"sbrc %[byte] , 3"
"out %[port] , %[n2]"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"mov %[n1] , %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"out %[port] , %[lo]"
"
\n\t
"
"
\n\t
"
"brne headF"
"
\n
"
"rjmp .+0"
:
[
byte
]
"+r"
(
b
),
[
n1
]
"+r"
(
n1
),
[
n2
]
"+r"
(
n2
),
[
count
]
"+w"
(
i
)
"
\n\t
"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTF
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"out %[port] , %[hi]"
[
lo
]
"r"
(
lo
));
"
\n\t
"
"mov %[n2] , %[lo]"
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 2"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 1"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n2] , %[lo]"
"
\n\t
"
"out %[port] , %[n1]"
"
\n\t
"
"rjmp .+0"
"
\n\t
"
"sbrc %[byte] , 0"
"
\n\t
"
"mov %[n2] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"mov %[n1] , %[lo]"
"
\n\t
"
"out %[port] , %[n2]"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"sbrc %[byte] , 7"
"
\n\t
"
"mov %[n1] , %[hi]"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"brne 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
));
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
}
}
#endif // defined(PORTD/B/C)
#endif // defined(PORTD/B/C)
#endif // defined(PORTF)
#endif // defined(PORTF)
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
...
@@ -660,41 +974,56 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -660,41 +974,56 @@ void Adafruit_NeoPixel::show(void) {
volatile
uint8_t
next
,
bit
;
volatile
uint8_t
next
,
bit
;
hi
=
*
port
|
pinMask
;
hi
=
*
port
|
pinMask
;
lo
=
*
port
&
~
pinMask
;
lo
=
*
port
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
bit
=
8
;
bit
=
8
;
asm
volatile
(
asm
volatile
(
"head20:"
"head20:"
"
\n\t
"
// Clk Pseudocode (T = 0)
"
\n\t
"
// Clk Pseudocode (T = 0)
"st %a[port], %[hi]"
"
\n\t
"
// 2 PORT = hi (T = 2)
"st %a[port], %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 128)
"
\n\t
"
// 2 PORT = hi (T = 2)
"mov %[next], %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 4)
"sbrc %[byte] , 7"
"st %a[port], %[next]"
"
\n\t
"
// 2 PORT = next (T = 6)
"
\n\t
"
// 1-2 if(b & 128)
"mov %[next] , %[lo]"
"
\n\t
"
// 1 next = lo (T = 7)
"mov %[next], %[hi]"
"dec %[bit]"
"
\n\t
"
// 1 bit-- (T = 8)
"
\n\t
"
// 0-1 next = hi (T = 4)
"breq nextbyte20"
"
\n\t
"
// 1-2 if(bit == 0)
"st %a[port], %[next]"
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 10)
"
\n\t
"
// 2 PORT = next (T = 6)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 12)
"mov %[next] , %[lo]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 14)
"
\n\t
"
// 1 next = lo (T = 7)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 16)
"dec %[bit]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 18)
"
\n\t
"
// 1 bit-- (T = 8)
"rjmp head20"
"
\n\t
"
// 2 -> head20 (next bit out)
"breq nextbyte20"
"nextbyte20:"
"
\n\t
"
// (T = 10)
"
\n\t
"
// 1-2 if(bit == 0)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 12)
"rol %[byte]"
"nop"
"
\n\t
"
// 1 nop (T = 13)
"
\n\t
"
// 1 b <<= 1 (T = 10)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 14)
"st %a[port], %[lo]"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 16)
"
\n\t
"
// 2 PORT = lo (T = 12)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 18)
"rjmp .+0"
"brne head20"
"
\n
"
// 2 if(i != 0) -> (next byte)
"
\n\t
"
// 2 nop nop (T = 14)
:
[
port
]
"+e"
(
port
),
"rjmp .+0"
[
byte
]
"+r"
(
b
),
"
\n\t
"
// 2 nop nop (T = 16)
[
bit
]
"+r"
(
bit
),
"rjmp .+0"
[
next
]
"+r"
(
next
),
"
\n\t
"
// 2 nop nop (T = 18)
[
count
]
"+w"
(
i
)
"rjmp head20"
:
[
hi
]
"r"
(
hi
),
"
\n\t
"
// 2 -> head20 (next bit out)
[
lo
]
"r"
(
lo
),
"nextbyte20:"
[
ptr
]
"e"
(
ptr
));
"
\n\t
"
// (T = 10)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 12)
"nop"
"
\n\t
"
// 1 nop (T = 13)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 14)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 16)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 18)
"brne head20"
"
\n
"
// 2 if(i != 0) -> (next byte)
:
[
port
]
"+e"
(
port
),
[
byte
]
"+r"
(
b
),
[
bit
]
"+r"
(
bit
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
),
[
ptr
]
"e"
(
ptr
));
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
...
@@ -702,7 +1031,7 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -702,7 +1031,7 @@ void Adafruit_NeoPixel::show(void) {
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
// In the 12 MHz case, an optimized 800 KHz datastream (no dead time
// In the 12 MHz case, an optimized 800 KHz datastream (no dead time
...
@@ -717,253 +1046,397 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -717,253 +1046,397 @@ void Adafruit_NeoPixel::show(void) {
// PORTD OUTPUT ----------------------------------------------------
// PORTD OUTPUT ----------------------------------------------------
#if defined(PORTD)
#if defined(PORTD)
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
if
(
port
==
&
PORTD
)
{
if
(
port
==
&
PORTD
)
{
#endif // defined(PORTB/C/F)
#endif // defined(PORTB/C/F)
hi
=
PORTD
|
pinMask
;
hi
=
PORTD
|
pinMask
;
lo
=
PORTD
&
~
pinMask
;
lo
=
PORTD
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
if
(
b
&
0x80
)
next
=
hi
;
if
(
b
&
0x80
)
next
=
hi
;
// Don't "optimize" the OUT calls into the bitTime subroutine;
// Don't "optimize" the OUT calls into the bitTime subroutine;
// we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
// we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
asm
volatile
(
asm
volatile
(
"headD:"
"headD:"
"
\n\t
"
// (T = 0)
"
\n\t
"
// (T = 0)
"out %[port], %[hi]"
"
\n\t
"
// (T = 1)
"out %[port], %[hi]"
"rcall bitTimeD"
"
\n\t
"
// Bit 7 (T = 15)
"
\n\t
"
// (T = 1)
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeD"
"rcall bitTimeD"
"
\n\t
"
// Bit 6
"
\n\t
"
// Bit 7 (T = 15)
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeD"
"
\n\t
"
// Bit 5
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeD"
"rcall bitTimeD"
"
\n\t
"
// Bit 4
"
\n\t
"
// Bit 6
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeD"
"
\n\t
"
// Bit 3
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeD"
"rcall bitTimeD"
"
\n\t
"
// Bit 2
"
\n\t
"
// Bit 5
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeD"
"
\n\t
"
// Bit 1
"
\n\t
"
// Bit 0:
"rcall bitTimeD"
"out %[port] , %[hi]"
"
\n\t
"
// 1 PORT = hi (T = 1)
"
\n\t
"
// Bit 4
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 3)
"out %[port], %[hi]"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 5)
"
\n\t
"
"out %[port] , %[next]"
"
\n\t
"
// 1 PORT = next (T = 6)
"rcall bitTimeD"
"mov %[next] , %[lo]"
"
\n\t
"
// 1 next = lo (T = 7)
"
\n\t
"
// Bit 3
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 0x80) (T = 8)
"out %[port], %[hi]"
"mov %[next] , %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 9)
"
\n\t
"
"nop"
"
\n\t
"
// 1 (T = 10)
"rcall bitTimeD"
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo (T = 11)
"
\n\t
"
// Bit 2
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 13)
"out %[port], %[hi]"
"brne headD"
"
\n\t
"
// 2 if(i != 0) -> (next byte)
"
\n\t
"
"rjmp doneD"
"
\n\t
"
"rcall bitTimeD"
"bitTimeD:"
"
\n\t
"
// nop nop nop (T = 4)
"
\n\t
"
// Bit 1
"out %[port], %[next]"
"
\n\t
"
// 1 PORT = next (T = 5)
// Bit 0:
"mov %[next], %[lo]"
"
\n\t
"
// 1 next = lo (T = 6)
"out %[port] , %[hi]"
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 7)
"
\n\t
"
// 1 PORT = hi (T = 1)
"sbrc %[byte], 7"
"
\n\t
"
// 1-2 if(b & 0x80) (T = 8)
"rjmp .+0"
"mov %[next], %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 9)
"
\n\t
"
// 2 nop nop (T = 3)
"nop"
"
\n\t
"
// 1 (T = 10)
"ld %[byte] , %a[ptr]+"
"out %[port], %[lo]"
"
\n\t
"
// 1 PORT = lo (T = 11)
"
\n\t
"
// 2 b = *ptr++ (T = 5)
"ret"
"
\n\t
"
// 4 nop nop nop nop (T = 15)
"out %[port] , %[next]"
"doneD:"
"
\n
"
"
\n\t
"
// 1 PORT = next (T = 6)
:
[
byte
]
"+r"
(
b
),
"mov %[next] , %[lo]"
[
next
]
"+r"
(
next
),
"
\n\t
"
// 1 next = lo (T = 7)
[
count
]
"+w"
(
i
)
"sbrc %[byte] , 7"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTD
)),
"
\n\t
"
// 1-2 if(b & 0x80) (T = 8)
[
ptr
]
"e"
(
ptr
),
"mov %[next] , %[hi]"
[
hi
]
"r"
(
hi
),
"
\n\t
"
// 0-1 next = hi (T = 9)
[
lo
]
"r"
(
lo
));
"nop"
"
\n\t
"
// 1 (T = 10)
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
"out %[port] , %[lo]"
"
\n\t
"
// 1 PORT = lo (T = 11)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 13)
"brne headD"
"
\n\t
"
// 2 if(i != 0) -> (next byte)
"rjmp doneD"
"
\n\t
"
"bitTimeD:"
"
\n\t
"
// nop nop nop (T = 4)
"out %[port], %[next]"
"
\n\t
"
// 1 PORT = next (T = 5)
"mov %[next], %[lo]"
"
\n\t
"
// 1 next = lo (T = 6)
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 7)
"sbrc %[byte], 7"
"
\n\t
"
// 1-2 if(b & 0x80) (T = 8)
"mov %[next], %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 9)
"nop"
"
\n\t
"
// 1 (T = 10)
"out %[port], %[lo]"
"
\n\t
"
// 1 PORT = lo (T = 11)
"ret"
"
\n\t
"
// 4 nop nop nop nop (T = 15)
"doneD:"
"
\n
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTD
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTB) || defined(PORTC) || defined(PORTF)
}
else
// other PORT(s)
}
else
// other PORT(s)
#endif // defined(PORTB/C/F)
#endif // defined(PORTB/C/F)
#endif // defined(PORTD)
#endif // defined(PORTD)
// PORTB OUTPUT ----------------------------------------------------
// PORTB OUTPUT ----------------------------------------------------
#if defined(PORTB)
#if defined(PORTB)
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
if
(
port
==
&
PORTB
)
{
if
(
port
==
&
PORTB
)
{
#endif // defined(PORTD/C/F)
#endif // defined(PORTD/C/F)
hi
=
PORTB
|
pinMask
;
hi
=
PORTB
|
pinMask
;
lo
=
PORTB
&
~
pinMask
;
lo
=
PORTB
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
if
(
b
&
0x80
)
next
=
hi
;
if
(
b
&
0x80
)
next
=
hi
;
// Same as above, just set for PORTB & stripped of comments
// Same as above, just set for PORTB & stripped of comments
asm
volatile
(
asm
volatile
(
"headB:"
"headB:"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeB"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeB"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeB"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeB"
"
\n\t
"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"rcall bitTimeB"
"rjmp .+0"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"out %[port], %[hi]"
"out %[port] , %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[lo]"
"
\n\t
"
"rcall bitTimeB"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"nop"
"
\n\t
"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rcall bitTimeB"
"sbiw %[count], 1"
"
\n\t
"
"
\n\t
"
"brne headB"
"
\n\t
"
"out %[port], %[hi]"
"rjmp doneB"
"
\n\t
"
"
\n\t
"
"bitTimeB:"
"
\n\t
"
"rcall bitTimeB"
"out %[port], %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"rol %[byte]"
"
\n\t
"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"rjmp .+0"
"mov %[next], %[hi]"
"
\n\t
"
"
\n\t
"
"nop"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"out %[port], %[lo]"
"
\n\t
"
"
\n\t
"
"ret"
"
\n\t
"
"out %[port] , %[next]"
"doneB:"
"
\n
"
"
\n\t
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
"mov %[next] , %[lo]"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTB
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"
\n\t
"
[
lo
]
"r"
(
lo
));
"sbrc %[byte] , 7"
"
\n\t
"
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
"mov %[next] , %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"brne headB"
"
\n\t
"
"rjmp doneB"
"
\n\t
"
"bitTimeB:"
"
\n\t
"
"out %[port], %[next]"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"rol %[byte]"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"mov %[next], %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[port], %[lo]"
"
\n\t
"
"ret"
"
\n\t
"
"doneB:"
"
\n
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTB
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTD) || defined(PORTC) || defined(PORTF)
}
}
#endif
#endif
#if defined(PORTC) || defined(PORTF)
#if defined(PORTC) || defined(PORTF)
else
else
#endif // defined(PORTC/F)
#endif // defined(PORTC/F)
#endif // defined(PORTB)
#endif // defined(PORTB)
// PORTC OUTPUT ----------------------------------------------------
// PORTC OUTPUT ----------------------------------------------------
#if defined(PORTC)
#if defined(PORTC)
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
if
(
port
==
&
PORTC
)
{
if
(
port
==
&
PORTC
)
{
#endif // defined(PORTD/B/F)
#endif // defined(PORTD/B/F)
hi
=
PORTC
|
pinMask
;
hi
=
PORTC
|
pinMask
;
lo
=
PORTC
&
~
pinMask
;
lo
=
PORTC
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
if
(
b
&
0x80
)
next
=
hi
;
if
(
b
&
0x80
)
next
=
hi
;
// Same as above, just set for PORTC & stripped of comments
// Same as above, just set for PORTC & stripped of comments
asm
volatile
(
asm
volatile
(
"headC:"
"headC:"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rjmp .+0"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"out %[port], %[hi]"
"out %[port] , %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[lo]"
"
\n\t
"
"rcall bitTimeC"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"nop"
"
\n\t
"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rcall bitTimeC"
"sbiw %[count], 1"
"
\n\t
"
"
\n\t
"
"brne headC"
"
\n\t
"
"out %[port], %[hi]"
"rjmp doneC"
"
\n\t
"
"
\n\t
"
"bitTimeC:"
"
\n\t
"
"rcall bitTimeC"
"out %[port], %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"rol %[byte]"
"
\n\t
"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"rjmp .+0"
"mov %[next], %[hi]"
"
\n\t
"
"
\n\t
"
"nop"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"out %[port], %[lo]"
"
\n\t
"
"
\n\t
"
"ret"
"
\n\t
"
"out %[port] , %[next]"
"doneC:"
"
\n
"
"
\n\t
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
"mov %[next] , %[lo]"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTC
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"
\n\t
"
[
lo
]
"r"
(
lo
));
"sbrc %[byte] , 7"
"
\n\t
"
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
"mov %[next] , %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"brne headC"
"
\n\t
"
"rjmp doneC"
"
\n\t
"
"bitTimeC:"
"
\n\t
"
"out %[port], %[next]"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"rol %[byte]"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"mov %[next], %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[port], %[lo]"
"
\n\t
"
"ret"
"
\n\t
"
"doneC:"
"
\n
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTC
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTD) || defined(PORTB) || defined(PORTF)
}
}
#endif // defined(PORTD/B/F)
#endif // defined(PORTD/B/F)
#if defined(PORTF)
#if defined(PORTF)
else
else
#endif
#endif
#endif // defined(PORTC)
#endif // defined(PORTC)
// PORTF OUTPUT ----------------------------------------------------
// PORTF OUTPUT ----------------------------------------------------
#if defined(PORTF)
#if defined(PORTF)
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
if
(
port
==
&
PORTF
)
{
if
(
port
==
&
PORTF
)
{
#endif // defined(PORTD/B/C)
#endif // defined(PORTD/B/C)
hi
=
PORTF
|
pinMask
;
hi
=
PORTF
|
pinMask
;
lo
=
PORTF
&
~
pinMask
;
lo
=
PORTF
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
if
(
b
&
0x80
)
next
=
hi
;
if
(
b
&
0x80
)
next
=
hi
;
// Same as above, just set for PORTF & stripped of comments
// Same as above, just set for PORTF & stripped of comments
asm
volatile
(
asm
volatile
(
"headF:"
"headF:"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port], %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"rcall bitTimeC"
"
\n\t
"
"
\n\t
"
"out %[port] , %[hi]"
"
\n\t
"
"rcall bitTimeC"
"rjmp .+0"
"
\n\t
"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
"out %[port], %[hi]"
"out %[port] , %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[lo]"
"
\n\t
"
"rcall bitTimeC"
"sbrc %[byte] , 7"
"
\n\t
"
"
\n\t
"
"mov %[next] , %[hi]"
"
\n\t
"
"out %[port], %[hi]"
"nop"
"
\n\t
"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"rcall bitTimeC"
"sbiw %[count], 1"
"
\n\t
"
"
\n\t
"
"brne headF"
"
\n\t
"
"out %[port], %[hi]"
"rjmp doneC"
"
\n\t
"
"
\n\t
"
"bitTimeC:"
"
\n\t
"
"rcall bitTimeC"
"out %[port], %[next]"
"
\n\t
"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"out %[port] , %[hi]"
"rol %[byte]"
"
\n\t
"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"rjmp .+0"
"mov %[next], %[hi]"
"
\n\t
"
"
\n\t
"
"nop"
"
\n\t
"
"ld %[byte] , %a[ptr]+"
"out %[port], %[lo]"
"
\n\t
"
"
\n\t
"
"ret"
"
\n\t
"
"out %[port] , %[next]"
"doneC:"
"
\n
"
"
\n\t
"
:
[
byte
]
"+r"
(
b
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
"mov %[next] , %[lo]"
:
[
port
]
"I"
(
_SFR_IO_ADDR
(
PORTF
)),
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
"
\n\t
"
[
lo
]
"r"
(
lo
));
"sbrc %[byte] , 7"
"
\n\t
"
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
"mov %[next] , %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[port] , %[lo]"
"
\n\t
"
"sbiw %[count], 1"
"
\n\t
"
"brne headF"
"
\n\t
"
"rjmp doneC"
"
\n\t
"
"bitTimeC:"
"
\n\t
"
"out %[port], %[next]"
"
\n\t
"
"mov %[next], %[lo]"
"
\n\t
"
"rol %[byte]"
"
\n\t
"
"sbrc %[byte], 7"
"
\n\t
"
"mov %[next], %[hi]"
"
\n\t
"
"nop"
"
\n\t
"
"out %[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
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(PORTD) || defined(PORTB) || defined(PORTC)
}
}
#endif // defined(PORTD/B/C)
#endif // defined(PORTD/B/C)
#endif // defined(PORTF)
#endif // defined(PORTF)
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
...
@@ -974,45 +1447,64 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -974,45 +1447,64 @@ void Adafruit_NeoPixel::show(void) {
volatile
uint8_t
next
,
bit
;
volatile
uint8_t
next
,
bit
;
hi
=
*
port
|
pinMask
;
hi
=
*
port
|
pinMask
;
lo
=
*
port
&
~
pinMask
;
lo
=
*
port
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
bit
=
8
;
bit
=
8
;
asm
volatile
(
asm
volatile
(
"head30:"
"head30:"
"
\n\t
"
// Clk Pseudocode (T = 0)
"
\n\t
"
// Clk Pseudocode (T = 0)
"st %a[port], %[hi]"
"
\n\t
"
// 2 PORT = hi (T = 2)
"st %a[port], %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 128)
"
\n\t
"
// 2 PORT = hi (T = 2)
"mov %[next], %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 4)
"sbrc %[byte] , 7"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 6)
"
\n\t
"
// 1-2 if(b & 128)
"st %a[port], %[next]"
"
\n\t
"
// 2 PORT = next (T = 8)
"mov %[next], %[hi]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 10)
"
\n\t
"
// 0-1 next = hi (T = 4)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 12)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 14)
"
\n\t
"
// 2 nop nop (T = 6)
"nop"
"
\n\t
"
// 1 nop (T = 15)
"st %a[port], %[next]"
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 17)
"
\n\t
"
// 2 PORT = next (T = 8)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 19)
"rjmp .+0"
"dec %[bit]"
"
\n\t
"
// 1 bit-- (T = 20)
"
\n\t
"
// 2 nop nop (T = 10)
"breq nextbyte30"
"
\n\t
"
// 1-2 if(bit == 0)
"rjmp .+0"
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 22)
"
\n\t
"
// 2 nop nop (T = 12)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 24)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 26)
"
\n\t
"
// 2 nop nop (T = 14)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 28)
"nop"
"rjmp head30"
"
\n\t
"
// 2 -> head30 (next bit out)
"
\n\t
"
// 1 nop (T = 15)
"nextbyte30:"
"
\n\t
"
// (T = 22)
"st %a[port], %[lo]"
"nop"
"
\n\t
"
// 1 nop (T = 23)
"
\n\t
"
// 2 PORT = lo (T = 17)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 24)
"rjmp .+0"
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 26)
"
\n\t
"
// 2 nop nop (T = 19)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 28)
"dec %[bit]"
"brne head30"
"
\n
"
// 1-2 if(i != 0) -> (next byte)
"
\n\t
"
// 1 bit-- (T = 20)
:
[
port
]
"+e"
(
port
),
"breq nextbyte30"
[
byte
]
"+r"
(
b
),
"
\n\t
"
// 1-2 if(bit == 0)
[
bit
]
"+r"
(
bit
),
"rol %[byte]"
[
next
]
"+r"
(
next
),
"
\n\t
"
// 1 b <<= 1 (T = 22)
[
count
]
"+w"
(
i
)
"rjmp .+0"
:
[
hi
]
"r"
(
hi
),
"
\n\t
"
// 2 nop nop (T = 24)
[
lo
]
"r"
(
lo
),
"rjmp .+0"
[
ptr
]
"e"
(
ptr
));
"
\n\t
"
// 2 nop nop (T = 26)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 28)
"rjmp head30"
"
\n\t
"
// 2 -> head30 (next bit out)
"nextbyte30:"
"
\n\t
"
// (T = 22)
"nop"
"
\n\t
"
// 1 nop (T = 23)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 24)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 26)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 28)
"brne head30"
"
\n
"
// 1-2 if(i != 0) -> (next byte)
:
[
port
]
"+e"
(
port
),
[
byte
]
"+r"
(
b
),
[
bit
]
"+r"
(
bit
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
),
[
ptr
]
"e"
(
ptr
));
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
...
@@ -1020,7 +1512,7 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1020,7 +1512,7 @@ void Adafruit_NeoPixel::show(void) {
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
// WS2811 and WS2812 have different hi/lo duty cycles; this is
// WS2811 and WS2812 have different hi/lo duty cycles; this is
...
@@ -1031,42 +1523,58 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1031,42 +1523,58 @@ void Adafruit_NeoPixel::show(void) {
volatile
uint8_t
next
,
bit
;
volatile
uint8_t
next
,
bit
;
hi
=
*
port
|
pinMask
;
hi
=
*
port
|
pinMask
;
lo
=
*
port
&
~
pinMask
;
lo
=
*
port
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
bit
=
8
;
bit
=
8
;
asm
volatile
(
asm
volatile
(
"head20:"
"head20:"
"
\n\t
"
// Clk Pseudocode (T = 0)
"
\n\t
"
// Clk Pseudocode (T = 0)
"st %a[port], %[hi]"
"
\n\t
"
// 2 PORT = hi (T = 2)
"st %a[port], %[hi]"
"sbrc %[byte], 7"
"
\n\t
"
// 1-2 if(b & 128)
"
\n\t
"
// 2 PORT = hi (T = 2)
"mov %[next], %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 4)
"sbrc %[byte], 7"
"dec %[bit]"
"
\n\t
"
// 1 bit-- (T = 5)
"
\n\t
"
// 1-2 if(b & 128)
"st %a[port], %[next]"
"
\n\t
"
// 2 PORT = next (T = 7)
"mov %[next], %[hi]"
"mov %[next] , %[lo]"
"
\n\t
"
// 1 next = lo (T = 8)
"
\n\t
"
// 0-1 next = hi (T = 4)
"breq nextbyte20"
"
\n\t
"
// 1-2 if(bit == 0) (from dec above)
"dec %[bit]"
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 10)
"
\n\t
"
// 1 bit-- (T = 5)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 12)
"st %a[port], %[next]"
"nop"
"
\n\t
"
// 1 nop (T = 13)
"
\n\t
"
// 2 PORT = next (T = 7)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 15)
"mov %[next] , %[lo]"
"nop"
"
\n\t
"
// 1 nop (T = 16)
"
\n\t
"
// 1 next = lo (T = 8)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 18)
"breq nextbyte20"
"rjmp head20"
"
\n\t
"
// 2 -> head20 (next bit out)
"
\n\t
"
// 1-2 if(bit == 0) (from dec above)
"nextbyte20:"
"
\n\t
"
// (T = 10)
"rol %[byte]"
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 11)
"
\n\t
"
// 1 b <<= 1 (T = 10)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 13)
"rjmp .+0"
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 15)
"
\n\t
"
// 2 nop nop (T = 12)
"nop"
"
\n\t
"
// 1 nop (T = 16)
"nop"
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 18)
"
\n\t
"
// 1 nop (T = 13)
"brne head20"
"
\n
"
// 2 if(i != 0) -> (next byte)
"st %a[port], %[lo]"
:
[
port
]
"+e"
(
port
),
"
\n\t
"
// 2 PORT = lo (T = 15)
[
byte
]
"+r"
(
b
),
"nop"
[
bit
]
"+r"
(
bit
),
"
\n\t
"
// 1 nop (T = 16)
[
next
]
"+r"
(
next
),
"rjmp .+0"
[
count
]
"+w"
(
i
)
"
\n\t
"
// 2 nop nop (T = 18)
:
[
ptr
]
"e"
(
ptr
),
"rjmp head20"
[
hi
]
"r"
(
hi
),
"
\n\t
"
// 2 -> head20 (next bit out)
[
lo
]
"r"
(
lo
));
"nextbyte20:"
"
\n\t
"
// (T = 10)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 11)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 13)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 15)
"nop"
"
\n\t
"
// 1 nop (T = 16)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 18)
"brne head20"
"
\n
"
// 2 if(i != 0) -> (next byte)
:
[
port
]
"+e"
(
port
),
[
byte
]
"+r"
(
b
),
[
bit
]
"+r"
(
bit
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 KHz
}
else
{
// 400 KHz
...
@@ -1078,269 +1586,368 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1078,269 +1586,368 @@ void Adafruit_NeoPixel::show(void) {
volatile
uint8_t
next
,
bit
;
volatile
uint8_t
next
,
bit
;
hi
=
*
port
|
pinMask
;
hi
=
*
port
|
pinMask
;
lo
=
*
port
&
~
pinMask
;
lo
=
*
port
&
~
pinMask
;
next
=
lo
;
next
=
lo
;
bit
=
8
;
bit
=
8
;
asm
volatile
(
asm
volatile
(
"head40:"
"head40:"
"
\n\t
"
// Clk Pseudocode (T = 0)
"
\n\t
"
// Clk Pseudocode (T = 0)
"st %a[port], %[hi]"
"
\n\t
"
// 2 PORT = hi (T = 2)
"st %a[port], %[hi]"
"sbrc %[byte] , 7"
"
\n\t
"
// 1-2 if(b & 128)
"
\n\t
"
// 2 PORT = hi (T = 2)
"mov %[next] , %[hi]"
"
\n\t
"
// 0-1 next = hi (T = 4)
"sbrc %[byte] , 7"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 6)
"
\n\t
"
// 1-2 if(b & 128)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 8)
"mov %[next] , %[hi]"
"st %a[port], %[next]"
"
\n\t
"
// 2 PORT = next (T = 10)
"
\n\t
"
// 0-1 next = hi (T = 4)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 12)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 14)
"
\n\t
"
// 2 nop nop (T = 6)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 16)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 18)
"
\n\t
"
// 2 nop nop (T = 8)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 20)
"st %a[port], %[next]"
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 22)
"
\n\t
"
// 2 PORT = next (T = 10)
"nop"
"
\n\t
"
// 1 nop (T = 23)
"rjmp .+0"
"mov %[next] , %[lo]"
"
\n\t
"
// 1 next = lo (T = 24)
"
\n\t
"
// 2 nop nop (T = 12)
"dec %[bit]"
"
\n\t
"
// 1 bit-- (T = 25)
"rjmp .+0"
"breq nextbyte40"
"
\n\t
"
// 1-2 if(bit == 0)
"
\n\t
"
// 2 nop nop (T = 14)
"rol %[byte]"
"
\n\t
"
// 1 b <<= 1 (T = 27)
"rjmp .+0"
"nop"
"
\n\t
"
// 1 nop (T = 28)
"
\n\t
"
// 2 nop nop (T = 16)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 30)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 32)
"
\n\t
"
// 2 nop nop (T = 18)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 34)
"rjmp .+0"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 36)
"
\n\t
"
// 2 nop nop (T = 20)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 38)
"st %a[port], %[lo]"
"rjmp head40"
"
\n\t
"
// 2 -> head40 (next bit out)
"
\n\t
"
// 2 PORT = lo (T = 22)
"nextbyte40:"
"
\n\t
"
// (T = 27)
"nop"
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 28)
"
\n\t
"
// 1 nop (T = 23)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 30)
"mov %[next] , %[lo]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 32)
"
\n\t
"
// 1 next = lo (T = 24)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 34)
"dec %[bit]"
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 36)
"
\n\t
"
// 1 bit-- (T = 25)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 38)
"breq nextbyte40"
"brne head40"
"
\n
"
// 1-2 if(i != 0) -> (next byte)
"
\n\t
"
// 1-2 if(bit == 0)
:
[
port
]
"+e"
(
port
),
"rol %[byte]"
[
byte
]
"+r"
(
b
),
"
\n\t
"
// 1 b <<= 1 (T = 27)
[
bit
]
"+r"
(
bit
),
"nop"
[
next
]
"+r"
(
next
),
"
\n\t
"
// 1 nop (T = 28)
[
count
]
"+w"
(
i
)
"rjmp .+0"
:
[
ptr
]
"e"
(
ptr
),
"
\n\t
"
// 2 nop nop (T = 30)
[
hi
]
"r"
(
hi
),
"rjmp .+0"
[
lo
]
"r"
(
lo
));
"
\n\t
"
// 2 nop nop (T = 32)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 34)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 36)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 38)
"rjmp head40"
"
\n\t
"
// 2 -> head40 (next bit out)
"nextbyte40:"
"
\n\t
"
// (T = 27)
"ldi %[bit] , 8"
"
\n\t
"
// 1 bit = 8 (T = 28)
"ld %[byte] , %a[ptr]+"
"
\n\t
"
// 2 b = *ptr++ (T = 30)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 32)
"st %a[port], %[lo]"
"
\n\t
"
// 2 PORT = lo (T = 34)
"rjmp .+0"
"
\n\t
"
// 2 nop nop (T = 36)
"sbiw %[count], 1"
"
\n\t
"
// 2 i-- (T = 38)
"brne head40"
"
\n
"
// 1-2 if(i != 0) -> (next byte)
:
[
port
]
"+e"
(
port
),
[
byte
]
"+r"
(
b
),
[
bit
]
"+r"
(
bit
),
[
next
]
"+r"
(
next
),
[
count
]
"+w"
(
i
)
:
[
ptr
]
"e"
(
ptr
),
[
hi
]
"r"
(
hi
),
[
lo
]
"r"
(
lo
));
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
#else
#else
#error "CPU SPEED NOT SUPPORTED"
#error "CPU SPEED NOT SUPPORTED"
#endif // end F_CPU ifdefs on __AVR__
#endif // end F_CPU ifdefs on __AVR__
// END AVR ----------------------------------------------------------------
// END AVR ----------------------------------------------------------------
#elif defined(__arm__)
#elif defined(__arm__)
// ARM MCUs -- Teensy 3.0, 3.1, LC, Arduino Due ---------------------------
// ARM MCUs -- Teensy 3.0, 3.1, LC, Arduino Due, RP2040 -------------------
#if defined(ARDUINO_ARCH_RP2040)
// Use PIO
rp2040Show
(
pin
,
pixels
,
numBytes
,
is800KHz
);
#if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
#elif defined(TEENSYDUINO) && \
#define CYCLES_800_T0H (F_CPU / 4000000)
defined
(
KINETISK
)
// Teensy 3.0, 3.1, 3.2, 3.5, 3.6
#define CYCLES_800_T1H (F_CPU / 1250000)
#define CYCLES_800_T0H (F_CPU / 4000000)
#define CYCLES_800 (F_CPU / 800000)
#define CYCLES_800_T1H (F_CPU / 1250000)
#define CYCLES_400_T0H (F_CPU / 2000000)
#define CYCLES_800 (F_CPU / 800000)
#define CYCLES_400_T1H (F_CPU / 833333)
#define CYCLES_400_T0H (F_CPU / 2000000)
#define CYCLES_400 (F_CPU / 400000)
#define CYCLES_400_T1H (F_CPU / 833333)
#define CYCLES_400 (F_CPU / 400000)
uint8_t
*
p
=
pixels
,
uint8_t
*
p
=
pixels
,
*
end
=
p
+
numBytes
,
pix
,
mask
;
*
end
=
p
+
numBytes
,
pix
,
mask
;
volatile
uint8_t
*
set
=
portSetRegister
(
pin
),
*
clr
=
portClearRegister
(
pin
);
volatile
uint8_t
*
set
=
portSetRegister
(
pin
),
uint32_t
cyc
;
*
clr
=
portClearRegister
(
pin
);
uint32_t
cyc
;
ARM_DEMCR
|=
ARM_DEMCR_TRCENA
;
ARM_DEMCR
|=
ARM_DEMCR_TRCENA
;
ARM_DWT_CTRL
|=
ARM_DWT_CTRL_CYCCNTENA
;
ARM_DWT_CTRL
|=
ARM_DWT_CTRL_CYCCNTENA
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_800
;
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_800
;
while
(
p
<
end
)
{
while
(
p
<
end
)
{
pix
=
*
p
++
;
pix
=
*
p
++
;
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
)
cyc
=
ARM_DWT_CYCCNT
;
;
cyc
=
ARM_DWT_CYCCNT
;
*
set
=
1
;
*
set
=
1
;
if
(
pix
&
mask
)
{
if
(
pix
&
mask
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T1H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T1H
)
;
}
else
{
}
else
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T0H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T0H
)
;
}
}
*
clr
=
1
;
*
clr
=
1
;
}
}
}
}
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
)
;
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 kHz bitstream
}
else
{
// 400 kHz bitstream
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_400
;
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_400
;
while
(
p
<
end
)
{
while
(
p
<
end
)
{
pix
=
*
p
++
;
pix
=
*
p
++
;
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
)
cyc
=
ARM_DWT_CYCCNT
;
;
cyc
=
ARM_DWT_CYCCNT
;
*
set
=
1
;
*
set
=
1
;
if
(
pix
&
mask
)
{
if
(
pix
&
mask
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T1H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T1H
)
;
}
else
{
}
else
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T0H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T0H
)
;
}
}
*
clr
=
1
;
*
clr
=
1
;
}
}
}
}
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
)
;
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
#elif defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
#elif defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))
#define CYCLES_800_T0H (F_CPU_ACTUAL / 4000000)
#define CYCLES_800_T0H (F_CPU_ACTUAL / 4000000)
#define CYCLES_800_T1H (F_CPU_ACTUAL / 1250000)
#define CYCLES_800_T1H (F_CPU_ACTUAL / 1250000)
#define CYCLES_800 (F_CPU_ACTUAL / 800000)
#define CYCLES_800 (F_CPU_ACTUAL / 800000)
#define CYCLES_400_T0H (F_CPU_ACTUAL / 2000000)
#define CYCLES_400_T0H (F_CPU_ACTUAL / 2000000)
#define CYCLES_400_T1H (F_CPU_ACTUAL / 833333)
#define CYCLES_400_T1H (F_CPU_ACTUAL / 833333)
#define CYCLES_400 (F_CPU_ACTUAL / 400000)
#define CYCLES_400 (F_CPU_ACTUAL / 400000)
uint8_t
*
p
=
pixels
,
uint8_t
*
p
=
pixels
,
*
end
=
p
+
numBytes
,
pix
,
mask
;
*
end
=
p
+
numBytes
,
pix
,
mask
;
volatile
uint32_t
*
set
=
portSetRegister
(
pin
),
*
clr
=
portClearRegister
(
pin
);
volatile
uint32_t
*
set
=
portSetRegister
(
pin
),
uint32_t
cyc
,
msk
=
digitalPinToBitMask
(
pin
);
*
clr
=
portClearRegister
(
pin
);
uint32_t
cyc
,
ARM_DEMCR
|=
ARM_DEMCR_TRCENA
;
msk
=
digitalPinToBitMask
(
pin
);
ARM_DEMCR
|=
ARM_DEMCR_TRCENA
;
ARM_DWT_CTRL
|=
ARM_DWT_CTRL_CYCCNTENA
;
ARM_DWT_CTRL
|=
ARM_DWT_CTRL_CYCCNTENA
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_800
;
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_800
;
while
(
p
<
end
)
{
while
(
p
<
end
)
{
pix
=
*
p
++
;
pix
=
*
p
++
;
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
)
cyc
=
ARM_DWT_CYCCNT
;
;
cyc
=
ARM_DWT_CYCCNT
;
*
set
=
msk
;
*
set
=
msk
;
if
(
pix
&
mask
)
{
if
(
pix
&
mask
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T1H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T1H
)
;
}
else
{
}
else
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T0H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800_T0H
)
;
}
}
*
clr
=
msk
;
*
clr
=
msk
;
}
}
}
}
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_800
)
;
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 kHz bitstream
}
else
{
// 400 kHz bitstream
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_400
;
cyc
=
ARM_DWT_CYCCNT
+
CYCLES_400
;
while
(
p
<
end
)
{
while
(
p
<
end
)
{
pix
=
*
p
++
;
pix
=
*
p
++
;
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
for
(
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
)
cyc
=
ARM_DWT_CYCCNT
;
;
cyc
=
ARM_DWT_CYCCNT
;
*
set
=
msk
;
*
set
=
msk
;
if
(
pix
&
mask
)
{
if
(
pix
&
mask
)
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T1H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T1H
)
;
}
else
{
}
else
{
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T0H
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400_T0H
)
;
}
}
*
clr
=
msk
;
*
clr
=
msk
;
}
}
}
}
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
);
while
(
ARM_DWT_CYCCNT
-
cyc
<
CYCLES_400
)
;
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
#elif defined(TEENSYDUINO) && defined(__MKL26Z64__) // Teensy-LC
#elif defined(TEENSYDUINO) && defined(__MKL26Z64__) // Teensy-LC
#if F_CPU == 48000000
#if F_CPU == 48000000
uint8_t
*
p
=
pixels
,
uint8_t
*
p
=
pixels
,
pix
,
count
,
dly
,
bitmask
=
digitalPinToBitMask
(
pin
);
pix
,
count
,
dly
,
bitmask
=
digitalPinToBitMask
(
pin
);
volatile
uint8_t
*
reg
=
portSetRegister
(
pin
);
volatile
uint8_t
*
reg
=
portSetRegister
(
pin
);
uint32_t
num
=
numBytes
;
uint32_t
num
=
numBytes
;
asm
volatile
(
asm
volatile
(
"L%=_begin:"
"L%=_begin:"
"
\n\t
"
"
\n\t
"
"ldrb %[pix], [%[p], #0]"
"
\n\t
"
"ldrb %[pix], [%[p], #0]"
"lsl %[pix], #24"
"
\n\t
"
"
\n\t
"
"movs %[count], #7"
"
\n\t
"
"lsl %[pix], #24"
"L%=_loop:"
"
\n\t
"
"
\n\t
"
"lsl %[pix], #1"
"
\n\t
"
"movs %[count], #7"
"bcs L%=_loop_one"
"
\n\t
"
"
\n\t
"
"L%=_loop_zero:"
"
\n\t
"
"L%=_loop:"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"
\n\t
"
"movs %[dly], #4"
"
\n\t
"
"lsl %[pix], #1"
"L%=_loop_delay_T0H:"
"
\n\t
"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bcs L%=_loop_one"
"bne L%=_loop_delay_T0H"
"
\n\t
"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"L%=_loop_zero:"
"movs %[dly], #13"
"
\n\t
"
"
\n\t
"
"L%=_loop_delay_T0L:"
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"sub %[dly], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_loop_delay_T0L"
"
\n\t
"
"movs %[dly], #4"
"b L%=_next"
"
\n\t
"
"
\n\t
"
"L%=_loop_one:"
"
\n\t
"
"L%=_loop_delay_T0H:"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"
\n\t
"
"movs %[dly], #13"
"
\n\t
"
"sub %[dly], #1"
"L%=_loop_delay_T1H:"
"
\n\t
"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_loop_delay_T0H"
"bne L%=_loop_delay_T1H"
"
\n\t
"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"movs %[dly], #4"
"
\n\t
"
"
\n\t
"
"L%=_loop_delay_T1L:"
"
\n\t
"
"movs %[dly], #13"
"sub %[dly], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_loop_delay_T1L"
"
\n\t
"
"L%=_loop_delay_T0L:"
"nop"
"
\n\t
"
"
\n\t
"
"L%=_next:"
"
\n\t
"
"sub %[dly], #1"
"sub %[count], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_loop"
"
\n\t
"
"bne L%=_loop_delay_T0L"
"lsl %[pix], #1"
"
\n\t
"
"
\n\t
"
"bcs L%=_last_one"
"
\n\t
"
"b L%=_next"
"L%=_last_zero:"
"
\n\t
"
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"L%=_loop_one:"
"movs %[dly], #4"
"
\n\t
"
"
\n\t
"
"L%=_last_delay_T0H:"
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"sub %[dly], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_last_delay_T0H"
"
\n\t
"
"movs %[dly], #13"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"
\n\t
"
"movs %[dly], #10"
"
\n\t
"
"L%=_loop_delay_T1H:"
"L%=_last_delay_T0L:"
"
\n\t
"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"sub %[dly], #1"
"bne L%=_last_delay_T0L"
"
\n\t
"
"
\n\t
"
"b L%=_repeat"
"
\n\t
"
"bne L%=_loop_delay_T1H"
"L%=_last_one:"
"
\n\t
"
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"movs %[dly], #13"
"
\n\t
"
"
\n\t
"
"L%=_last_delay_T1H:"
"
\n\t
"
"movs %[dly], #4"
"sub %[dly], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_last_delay_T1H"
"
\n\t
"
"L%=_loop_delay_T1L:"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"
\n\t
"
"movs %[dly], #1"
"
\n\t
"
"sub %[dly], #1"
"L%=_last_delay_T1L:"
"
\n\t
"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_loop_delay_T1L"
"bne L%=_last_delay_T1L"
"
\n\t
"
"
\n\t
"
"nop"
"
\n\t
"
"nop"
"L%=_repeat:"
"
\n\t
"
"
\n\t
"
"add %[p], #1"
"
\n\t
"
"L%=_next:"
"sub %[num], #1"
"
\n\t
"
"
\n\t
"
"bne L%=_begin"
"
\n\t
"
"sub %[count], #1"
"L%=_done:"
"
\n\t
"
"
\n\t
"
:
[
p
]
"+r"
(
p
),
"bne L%=_loop"
[
pix
]
"=&r"
(
pix
),
"
\n\t
"
[
count
]
"=&r"
(
count
),
"lsl %[pix], #1"
[
dly
]
"=&r"
(
dly
),
"
\n\t
"
[
num
]
"+r"
(
num
)
"bcs L%=_last_one"
:
[
bitmask
]
"r"
(
bitmask
),
"
\n\t
"
[
reg
]
"r"
(
reg
)
"L%=_last_zero:"
);
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"movs %[dly], #4"
"
\n\t
"
"L%=_last_delay_T0H:"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_last_delay_T0H"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"movs %[dly], #10"
"
\n\t
"
"L%=_last_delay_T0L:"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_last_delay_T0L"
"
\n\t
"
"b L%=_repeat"
"
\n\t
"
"L%=_last_one:"
"
\n\t
"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
"movs %[dly], #13"
"
\n\t
"
"L%=_last_delay_T1H:"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_last_delay_T1H"
"
\n\t
"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
"movs %[dly], #1"
"
\n\t
"
"L%=_last_delay_T1L:"
"
\n\t
"
"sub %[dly], #1"
"
\n\t
"
"bne L%=_last_delay_T1L"
"
\n\t
"
"nop"
"
\n\t
"
"L%=_repeat:"
"
\n\t
"
"add %[p], #1"
"
\n\t
"
"sub %[num], #1"
"
\n\t
"
"bne L%=_begin"
"
\n\t
"
"L%=_done:"
"
\n\t
"
:
[
p
]
"+r"
(
p
),
[
pix
]
"=&r"
(
pix
),
[
count
]
"=&r"
(
count
),
[
dly
]
"=&r"
(
dly
),
[
num
]
"+r"
(
num
)
:
[
bitmask
]
"r"
(
bitmask
),
[
reg
]
"r"
(
reg
));
#else
#else
#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
#endif // F_CPU == 48000000
#endif // F_CPU == 48000000
// Begin of support for nRF52 based boards -------------------------
// Begin of support for nRF52 based boards -------------------------
#elif defined(NRF52) || defined(NRF52_SERIES)
#elif defined(NRF52) || defined(NRF52_SERIES)
// [[[Begin of the Neopixel NRF52 EasyDMA implementation
// [[[Begin of the Neopixel NRF52 EasyDMA implementation
...
@@ -1369,16 +1976,16 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1369,16 +1976,16 @@ void Adafruit_NeoPixel::show(void) {
//#define MAGIC_T1H 12UL | (0x8000) // 0.75us
//#define MAGIC_T1H 12UL | (0x8000) // 0.75us
// WS2812B (rev B) timing is 0.4 and 0.8 us
// WS2812B (rev B) timing is 0.4 and 0.8 us
#define MAGIC_T0H
6UL | (0x8000) // 0.375us
#define MAGIC_T0H 6UL | (0x8000) // 0.375us
#define MAGIC_T1H
13UL | (0x8000) // 0.8125us
#define MAGIC_T1H 13UL | (0x8000) // 0.8125us
// WS2811 (400 khz) timing is 0.5 and 1.2
// WS2811 (400 khz) timing is 0.5 and 1.2
#define MAGIC_T0H_400KHz
8UL
| (0x8000) // 0.5us
#define MAGIC_T0H_400KHz 8UL | (0x8000) // 0.5us
#define MAGIC_T1H_400KHz
19UL | (0x8000) // 1.1875us
#define MAGIC_T1H_400KHz 19UL | (0x8000) // 1.1875us
// For 400Khz, we double value of CTOPVAL
// For 400Khz, we double value of CTOPVAL
#define CTOPVAL
20UL
// 1.25us
#define CTOPVAL
20UL
// 1.25us
#define CTOPVAL_400KHz
40UL
// 2.5us
#define CTOPVAL_400KHz
40UL
// 2.5us
// ---------- END Constants for the EasyDMA implementation -------------
// ---------- END Constants for the EasyDMA implementation -------------
//
//
...
@@ -1390,14 +1997,14 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1390,14 +1997,14 @@ void Adafruit_NeoPixel::show(void) {
// The number of cycles was hand picked and is guaranteed to be 100%
// The number of cycles was hand picked and is guaranteed to be 100%
// organic to preserve freshness and high accuracy.
// organic to preserve freshness and high accuracy.
// ---------- BEGIN Constants for cycle counter implementation ---------
// ---------- BEGIN Constants for cycle counter implementation ---------
#define CYCLES_800_T0H
18
// ~0.36 uS
#define CYCLES_800_T0H 18 // ~0.36 uS
#define CYCLES_800_T1H
41
// ~0.76 uS
#define CYCLES_800_T1H 41 // ~0.76 uS
#define CYCLES_800
71
// ~1.25 uS
#define CYCLES_800 71 // ~1.25 uS
#define CYCLES_400_T0H
26
// ~0.50 uS
#define CYCLES_400_T0H 26 // ~0.50 uS
#define CYCLES_400_T1H
70
// ~1.26 uS
#define CYCLES_400_T1H 70 // ~1.26 uS
#define CYCLES_400
156 // ~2.50 uS
#define CYCLES_400 156 // ~2.50 uS
// ---------- END of Constants for cycle counter implementation --------
// ---------- END of Constants for cycle counter implementation --------
// To support both the SoftDevice + Neopixels we use the EasyDMA
// To support both the SoftDevice + Neopixels we use the EasyDMA
// feature from the NRF25. However this technique implies to
// feature from the NRF25. However this technique implies to
...
@@ -1409,55 +2016,60 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1409,55 +2016,60 @@ void Adafruit_NeoPixel::show(void) {
//
//
// If there is not enough memory, we will fall back to cycle counter
// If there is not enough memory, we will fall back to cycle counter
// using DWT
// using DWT
uint32_t
pattern_size
=
numBytes
*
8
*
sizeof
(
uint16_t
)
+
2
*
sizeof
(
uint16_t
);
uint32_t
pattern_size
=
uint16_t
*
pixels_pattern
=
NULL
;
numBytes
*
8
*
sizeof
(
uint16_t
)
+
2
*
sizeof
(
uint16_t
);
uint16_t
*
pixels_pattern
=
NULL
;
NRF_PWM_Type
*
pwm
=
NULL
;
NRF_PWM_Type
*
pwm
=
NULL
;
// Try to find a free PWM device, which is not enabled
// Try to find a free PWM device, which is not enabled
// and has no connected pins
// and has no connected pins
NRF_PWM_Type
*
PWM
[]
=
{
NRF_PWM_Type
*
PWM
[]
=
{
NRF_PWM0
,
NRF_PWM1
,
NRF_PWM2
NRF_PWM0
,
NRF_PWM1
,
NRF_PWM2
#if defined(NRF_PWM3)
#if defined(NRF_PWM3)
,
NRF_PWM3
,
NRF_PWM3
#endif
#endif
};
};
for
(
unsigned
int
device
=
0
;
device
<
(
sizeof
(
PWM
)
/
sizeof
(
PWM
[
0
]));
device
++
)
{
for
(
unsigned
int
device
=
0
;
device
<
(
sizeof
(
PWM
)
/
sizeof
(
PWM
[
0
]));
if
(
(
PWM
[
device
]
->
ENABLE
==
0
)
&&
device
++
)
{
if
((
PWM
[
device
]
->
ENABLE
==
0
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
0
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
0
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
1
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
1
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
2
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
2
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
&&
(
PWM
[
device
]
->
PSEL
.
OUT
[
3
]
&
PWM_PSEL_OUT_CONNECT_Msk
)
(
PWM
[
device
]
->
PSEL
.
OUT
[
3
]
&
PWM_PSEL_OUT_CONNECT_Msk
))
{
)
{
pwm
=
PWM
[
device
];
pwm
=
PWM
[
device
];
break
;
break
;
}
}
}
}
// only malloc if there is PWM device available
// only malloc if there is PWM device available
if
(
pwm
!=
NULL
)
{
if
(
pwm
!=
NULL
)
{
#if defined(ARDUINO_NRF52_ADAFRUIT) // use thread-safe malloc
#if defined(ARDUINO_NRF52_ADAFRUIT) // use thread-safe malloc
pixels_pattern
=
(
uint16_t
*
)
rtos_malloc
(
pattern_size
);
pixels_pattern
=
(
uint16_t
*
)
rtos_malloc
(
pattern_size
);
#else
#else
pixels_pattern
=
(
uint16_t
*
)
malloc
(
pattern_size
);
pixels_pattern
=
(
uint16_t
*
)
malloc
(
pattern_size
);
#endif
#endif
}
}
// Use the identified device to choose the implementation
// Use the identified device to choose the implementation
// If a PWM device is available use DMA
// If a PWM device is available use DMA
if
(
(
pixels_pattern
!=
NULL
)
&&
(
pwm
!=
NULL
)
)
{
if
(
(
pixels_pattern
!=
NULL
)
&&
(
pwm
!=
NULL
))
{
uint16_t
pos
=
0
;
// bit position
uint16_t
pos
=
0
;
// bit position
for
(
uint16_t
n
=
0
;
n
<
numBytes
;
n
++
)
{
for
(
uint16_t
n
=
0
;
n
<
numBytes
;
n
++
)
{
uint8_t
pix
=
pixels
[
n
];
uint8_t
pix
=
pixels
[
n
];
for
(
uint8_t
mask
=
0x80
;
mask
>
0
;
mask
>>=
1
)
{
for
(
uint8_t
mask
=
0x80
;
mask
>
0
;
mask
>>=
1
)
{
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
if
(
!
is800KHz
)
{
if
(
!
is800KHz
)
{
pixels_pattern
[
pos
]
=
(
pix
&
mask
)
?
MAGIC_T1H_400KHz
:
MAGIC_T0H_400KHz
;
pixels_pattern
[
pos
]
=
}
else
(
pix
&
mask
)
?
MAGIC_T1H_400KHz
:
MAGIC_T0H_400KHz
;
#endif
}
else
#endif
{
{
pixels_pattern
[
pos
]
=
(
pix
&
mask
)
?
MAGIC_T1H
:
MAGIC_T0H
;
pixels_pattern
[
pos
]
=
(
pix
&
mask
)
?
MAGIC_T1H
:
MAGIC_T0H
;
}
}
...
@@ -1474,15 +2086,16 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1474,15 +2086,16 @@ void Adafruit_NeoPixel::show(void) {
pwm
->
MODE
=
(
PWM_MODE_UPDOWN_Up
<<
PWM_MODE_UPDOWN_Pos
);
pwm
->
MODE
=
(
PWM_MODE_UPDOWN_Up
<<
PWM_MODE_UPDOWN_Pos
);
// Set the PWM to use the 16MHz clock
// Set the PWM to use the 16MHz clock
pwm
->
PRESCALER
=
(
PWM_PRESCALER_PRESCALER_DIV_1
<<
PWM_PRESCALER_PRESCALER_Pos
);
pwm
->
PRESCALER
=
(
PWM_PRESCALER_PRESCALER_DIV_1
<<
PWM_PRESCALER_PRESCALER_Pos
);
// Setting of the maximum count
// Setting of the maximum count
// but keeping it on 16Mhz allows for more granularity just
// but keeping it on 16Mhz allows for more granularity just
// in case someone wants to do more fine-tuning of the timing.
// in case someone wants to do more fine-tuning of the timing.
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
if
(
!
is800KHz
)
{
if
(
!
is800KHz
)
{
pwm
->
COUNTERTOP
=
(
CTOPVAL_400KHz
<<
PWM_COUNTERTOP_COUNTERTOP_Pos
);
pwm
->
COUNTERTOP
=
(
CTOPVAL_400KHz
<<
PWM_COUNTERTOP_COUNTERTOP_Pos
);
}
else
}
else
#endif
#endif
{
{
pwm
->
COUNTERTOP
=
(
CTOPVAL
<<
PWM_COUNTERTOP_COUNTERTOP_Pos
);
pwm
->
COUNTERTOP
=
(
CTOPVAL
<<
PWM_COUNTERTOP_COUNTERTOP_Pos
);
...
@@ -1501,10 +2114,10 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1501,10 +2114,10 @@ void Adafruit_NeoPixel::show(void) {
pwm
->
SEQ
[
0
].
PTR
=
(
uint32_t
)(
pixels_pattern
)
<<
PWM_SEQ_PTR_PTR_Pos
;
pwm
->
SEQ
[
0
].
PTR
=
(
uint32_t
)(
pixels_pattern
)
<<
PWM_SEQ_PTR_PTR_Pos
;
// Calculation of the number of steps loaded from memory.
// Calculation of the number of steps loaded from memory.
pwm
->
SEQ
[
0
].
CNT
=
(
pattern_size
/
sizeof
(
uint16_t
))
<<
PWM_SEQ_CNT_CNT_Pos
;
pwm
->
SEQ
[
0
].
CNT
=
(
pattern_size
/
sizeof
(
uint16_t
))
<<
PWM_SEQ_CNT_CNT_Pos
;
// The following settings are ignored with the current config.
// The following settings are ignored with the current config.
pwm
->
SEQ
[
0
].
REFRESH
=
0
;
pwm
->
SEQ
[
0
].
REFRESH
=
0
;
pwm
->
SEQ
[
0
].
ENDDELAY
=
0
;
pwm
->
SEQ
[
0
].
ENDDELAY
=
0
;
// The Neopixel implementation is a blocking algorithm. DMA
// The Neopixel implementation is a blocking algorithm. DMA
...
@@ -1512,29 +2125,28 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1512,29 +2125,28 @@ void Adafruit_NeoPixel::show(void) {
// operation we enable the interruption for the end of sequence
// operation we enable the interruption for the end of sequence
// and block the execution thread until the event flag is set by
// and block the execution thread until the event flag is set by
// the peripheral.
// the peripheral.
// pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos);
// pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos);
// PSEL must be configured before enabling PWM
// PSEL must be configured before enabling PWM
#if defined(ARDUINO_ARCH_NRF52840)
#if defined(ARDUINO_ARCH_NRF52840)
pwm
->
PSEL
.
OUT
[
0
]
=
g_APinDescription
[
pin
].
name
;
pwm
->
PSEL
.
OUT
[
0
]
=
g_APinDescription
[
pin
].
name
;
#else
#else
pwm
->
PSEL
.
OUT
[
0
]
=
g_ADigitalPinMap
[
pin
];
pwm
->
PSEL
.
OUT
[
0
]
=
g_ADigitalPinMap
[
pin
];
#endif
#endif
// Enable the PWM
// Enable the PWM
pwm
->
ENABLE
=
1
;
pwm
->
ENABLE
=
1
;
// After all of this and many hours of reading the documentation
// After all of this and many hours of reading the documentation
// we are ready to start the sequence...
// we are ready to start the sequence...
pwm
->
EVENTS_SEQEND
[
0
]
=
0
;
pwm
->
EVENTS_SEQEND
[
0
]
=
0
;
pwm
->
TASKS_SEQSTART
[
0
]
=
1
;
pwm
->
TASKS_SEQSTART
[
0
]
=
1
;
// But we have to wait for the flag to be set.
// But we have to wait for the flag to be set.
while
(
!
pwm
->
EVENTS_SEQEND
[
0
])
while
(
!
pwm
->
EVENTS_SEQEND
[
0
])
{
{
#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_NRF52840)
#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_NRF52840)
yield
();
yield
();
#endif
#endif
}
}
// Before leave we clear the flag for the event.
// Before leave we clear the flag for the event.
...
@@ -1548,40 +2160,39 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1548,40 +2160,39 @@ void Adafruit_NeoPixel::show(void) {
pwm
->
PSEL
.
OUT
[
0
]
=
0xFFFFFFFFUL
;
pwm
->
PSEL
.
OUT
[
0
]
=
0xFFFFFFFFUL
;
#if defined(ARDUINO_NRF52_ADAFRUIT)
// use thread-safe free
#if defined(ARDUINO_NRF52_ADAFRUIT) // use thread-safe free
rtos_free
(
pixels_pattern
);
rtos_free
(
pixels_pattern
);
#else
#else
free
(
pixels_pattern
);
free
(
pixels_pattern
);
#endif
#endif
}
// End of DMA implementation
}
// End of DMA implementation
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
else
{
else
{
#ifndef ARDUINO_ARCH_NRF52840
#ifndef ARDUINO_ARCH_NRF52840
// Fall back to DWT
// Fall back to DWT
#if defined(ARDUINO_NRF52_ADAFRUIT)
#if defined(ARDUINO_NRF52_ADAFRUIT)
// Bluefruit Feather 52 uses freeRTOS
// Bluefruit Feather 52 uses freeRTOS
// Critical Section is used since it does not block SoftDevice execution
// Critical Section is used since it does not block SoftDevice execution
taskENTER_CRITICAL
();
taskENTER_CRITICAL
();
#elif defined(NRF52_DISABLE_INT)
#elif defined(NRF52_DISABLE_INT)
// If you are using the Bluetooth SoftDevice we advise you to not disable
// If you are using the Bluetooth SoftDevice we advise you to not disable
// the interrupts. Disabling the interrupts even for short periods of time
// the interrupts. Disabling the interrupts even for short periods of time
// causes the SoftDevice to stop working.
// causes the SoftDevice to stop working.
// Disable the interrupts only in cases where you need high performance for
// Disable the interrupts only in cases where you need high performance for
// the LEDs and if you are not using the EasyDMA feature.
// the LEDs and if you are not using the EasyDMA feature.
__disable_irq
();
__disable_irq
();
#endif
#endif
NRF_GPIO_Type
*
nrf_port
=
(
NRF_GPIO_Type
*
)
digitalPinToPort
(
pin
);
NRF_GPIO_Type
*
nrf_port
=
(
NRF_GPIO_Type
*
)
digitalPinToPort
(
pin
);
uint32_t
pinMask
=
digitalPinToBitMask
(
pin
);
uint32_t
pinMask
=
digitalPinToBitMask
(
pin
);
uint32_t
CYCLES_X00
=
CYCLES_800
;
uint32_t
CYCLES_X00
=
CYCLES_800
;
uint32_t
CYCLES_X00_T1H
=
CYCLES_800_T1H
;
uint32_t
CYCLES_X00_T1H
=
CYCLES_800_T1H
;
uint32_t
CYCLES_X00_T0H
=
CYCLES_800_T0H
;
uint32_t
CYCLES_X00_T0H
=
CYCLES_800_T0H
;
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
if
(
!
is800KHz
)
if
(
!
is800KHz
)
{
{
CYCLES_X00
=
CYCLES_400
;
CYCLES_X00
=
CYCLES_400
;
CYCLES_X00_T1H
=
CYCLES_400_T1H
;
CYCLES_X00_T1H
=
CYCLES_400_T1H
;
CYCLES_X00_T0H
=
CYCLES_400_T0H
;
CYCLES_X00_T0H
=
CYCLES_400_T0H
;
}
}
...
@@ -1592,36 +2203,39 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1592,36 +2203,39 @@ void Adafruit_NeoPixel::show(void) {
DWT
->
CTRL
|=
DWT_CTRL_CYCCNTENA_Msk
;
DWT
->
CTRL
|=
DWT_CTRL_CYCCNTENA_Msk
;
// Tries to re-send the frame if is interrupted by the SoftDevice.
// Tries to re-send the frame if is interrupted by the SoftDevice.
while
(
1
)
{
while
(
1
)
{
uint8_t
*
p
=
pixels
;
uint8_t
*
p
=
pixels
;
uint32_t
cycStart
=
DWT
->
CYCCNT
;
uint32_t
cycStart
=
DWT
->
CYCCNT
;
uint32_t
cyc
=
0
;
uint32_t
cyc
=
0
;
for
(
uint16_t
n
=
0
;
n
<
numBytes
;
n
++
)
{
for
(
uint16_t
n
=
0
;
n
<
numBytes
;
n
++
)
{
uint8_t
pix
=
*
p
++
;
uint8_t
pix
=
*
p
++
;
for
(
uint8_t
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
for
(
uint8_t
mask
=
0x80
;
mask
;
mask
>>=
1
)
{
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00
);
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00
)
cyc
=
DWT
->
CYCCNT
;
;
cyc
=
DWT
->
CYCCNT
;
nrf_port
->
OUTSET
|=
pinMask
;
nrf_port
->
OUTSET
|=
pinMask
;
if
(
pix
&
mask
)
{
if
(
pix
&
mask
)
{
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00_T1H
);
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00_T1H
)
;
}
else
{
}
else
{
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00_T0H
);
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00_T0H
)
;
}
}
nrf_port
->
OUTCLR
|=
pinMask
;
nrf_port
->
OUTCLR
|=
pinMask
;
}
}
}
}
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00
)
;
while
(
DWT
->
CYCCNT
-
cyc
<
CYCLES_X00
)
;
// If total time longer than 25%, resend the whole data.
// If total time longer than 25%, resend the whole data.
// Since we are likely to be interrupted by SoftDevice
// Since we are likely to be interrupted by SoftDevice
if
(
(
DWT
->
CYCCNT
-
cycStart
)
<
(
8
*
numBytes
*
((
CYCLES_X00
*
5
)
/
4
)
)
)
{
if
((
DWT
->
CYCCNT
-
cycStart
)
<
(
8
*
numBytes
*
((
CYCLES_X00
*
5
)
/
4
))
)
{
break
;
break
;
}
}
...
@@ -1629,40 +2243,43 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1629,40 +2243,43 @@ void Adafruit_NeoPixel::show(void) {
delayMicroseconds
(
300
);
delayMicroseconds
(
300
);
}
}
// Enable interrupts again
// Enable interrupts again
#if defined(ARDUINO_NRF52_ADAFRUIT)
#if defined(ARDUINO_NRF52_ADAFRUIT)
taskEXIT_CRITICAL
();
taskEXIT_CRITICAL
();
#elif defined(NRF52_DISABLE_INT)
#elif defined(NRF52_DISABLE_INT)
__enable_irq
();
__enable_irq
();
#endif
#endif
#endif
#endif
}
}
// END of NRF52 implementation
// END of NRF52 implementation
#elif defined (__SAMD21E17A__) || defined(__SAMD21G18A__) || defined(__SAMD21E18A__) || defined(__SAMD21J18A__) // Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo and others
#elif defined(__SAMD21E17A__) || defined(__SAMD21G18A__) || \
defined
(
__SAMD21E18A__
)
||
\
defined
(
__SAMD21J18A__
)
// Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo
// and others
// Tried this with a timer/counter, couldn't quite get adequate
// Tried this with a timer/counter, couldn't quite get adequate
// resolution. So yay, you get a load of goofball NOPs...
// resolution. So yay, you get a load of goofball NOPs...
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
;
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
;
uint32_t
pinMask
;
uint32_t
pinMask
;
portNum
=
g_APinDescription
[
pin
].
ulPort
;
portNum
=
g_APinDescription
[
pin
].
ulPort
;
pinMask
=
1ul
<<
g_APinDescription
[
pin
].
ulPin
;
pinMask
=
1ul
<<
g_APinDescription
[
pin
].
ulPin
;
ptr
=
pixels
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
volatile
uint32_t
*
set
=
&
(
PORT
->
Group
[
portNum
].
OUTSET
.
reg
),
volatile
uint32_t
*
set
=
&
(
PORT
->
Group
[
portNum
].
OUTSET
.
reg
),
*
clr
=
&
(
PORT
->
Group
[
portNum
].
OUTCLR
.
reg
);
*
clr
=
&
(
PORT
->
Group
[
portNum
].
OUTCLR
.
reg
);
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
for
(;;)
{
for
(;;)
{
*
set
=
pinMask
;
*
set
=
pinMask
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
if
(
p
&
bitMask
)
{
if
(
p
&
bitMask
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop;"
);
"nop; nop; nop; nop;"
);
...
@@ -1673,20 +2290,21 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1673,20 +2290,21 @@ void Adafruit_NeoPixel::show(void) {
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop;"
);
"nop; nop; nop; nop;"
);
}
}
if
(
bitMask
>>=
1
)
{
if
(
bitMask
>>=
1
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop; nop;"
);
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop; nop;"
);
}
else
{
}
else
{
if
(
ptr
>=
end
)
break
;
if
(
ptr
>=
end
)
p
=
*
ptr
++
;
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
}
}
}
}
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 KHz bitstream
}
else
{
// 400 KHz bitstream
for
(;;)
{
for
(;;)
{
*
set
=
pinMask
;
*
set
=
pinMask
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
);
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
);
if
(
p
&
bitMask
)
{
if
(
p
&
bitMask
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
...
@@ -1703,29 +2321,195 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1703,29 +2321,195 @@ void Adafruit_NeoPixel::show(void) {
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
if
(
bitMask
>>=
1
)
{
if
(
bitMask
>>=
1
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop;"
);
asm
(
"nop; nop; nop; nop; nop; nop; nop;"
);
}
else
{
}
else
{
if
(
ptr
>=
end
)
break
;
if
(
ptr
>=
end
)
p
=
*
ptr
++
;
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
}
}
}
}
}
}
#endif
#endif
#elif defined (__SAMD51__) // M4
//----
#elif defined(XMC1100_XMC2GO) || defined(XMC1100_H_BRIDGE2GO) || defined(XMC1100_Boot_Kit) || defined(XMC1300_Boot_Kit)
// XMC1100/1200/1300 with ARM Cortex M0 are running with 32MHz, XMC1400 runs with 48MHz so may not work
// Tried this with a timer/counter, couldn't quite get adequate
// resolution. So yay, you get a load of goofball NOPs...
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
,
bit
;
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
;
uint32_t
pinMask
;
uint32_t
pinMask
;
portNum
=
g_APinDescription
[
pin
].
ulPort
;
pinMask
=
1ul
<<
g_APinDescription
[
pin
].
ulPin
;
ptr
=
pixels
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
XMC_GPIO_PORT_t
*
XMC_port
=
mapping_port_pin
[
pin
].
port
;
uint8_t
XMC_pin
=
mapping_port_pin
[
pin
].
pin
;
uint32_t
omrhigh
=
(
uint32_t
)
XMC_GPIO_OUTPUT_LEVEL_HIGH
<<
XMC_pin
;
uint32_t
omrlow
=
(
uint32_t
)
XMC_GPIO_OUTPUT_LEVEL_LOW
<<
XMC_pin
;
#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
#endif
for
(;;)
{
XMC_port
->
OMR
=
omrhigh
;
asm
(
"nop; nop; nop; nop;"
);
if
(
p
&
bitMask
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop;"
);
XMC_port
->
OMR
=
omrlow
;
}
else
{
XMC_port
->
OMR
=
omrlow
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop;"
);
}
if
(
bitMask
>>=
1
)
{
asm
(
"nop; nop; nop; nop; nop;"
);
}
else
{
if
(
ptr
>=
end
)
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
}
}
#ifdef NEO_KHZ400 // untested code
}
else
{
// 400 KHz bitstream
for
(;;)
{
XMC_port
->
OMR
=
omrhigh
;
asm
(
"nop; nop; nop; nop; nop;"
);
if
(
p
&
bitMask
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop;"
);
XMC_port
->
OMR
=
omrlow
;
}
else
{
XMC_port
->
OMR
=
omrlow
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop;"
);
}
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
if
(
bitMask
>>=
1
)
{
asm
(
"nop; nop; nop;"
);
}
else
{
if
(
ptr
>=
end
)
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
}
}
}
#endif
//----
//----
#elif defined(XMC4700_Relax_Kit) || defined(XMC4800_Relax_Kit)
// XMC4700 and XMC4800 with ARM Cortex M4 are running with 144MHz
// Tried this with a timer/counter, couldn't quite get adequate
// resolution. So yay, you get a load of goofball NOPs...
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
;
uint32_t
pinMask
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
XMC_GPIO_PORT_t
*
XMC_port
=
mapping_port_pin
[
pin
].
port
;
uint8_t
XMC_pin
=
mapping_port_pin
[
pin
].
pin
;
uint32_t
omrhigh
=
(
uint32_t
)
XMC_GPIO_OUTPUT_LEVEL_HIGH
<<
XMC_pin
;
uint32_t
omrlow
=
(
uint32_t
)
XMC_GPIO_OUTPUT_LEVEL_LOW
<<
XMC_pin
;
#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
#endif
for
(;;)
{
XMC_port
->
OMR
=
omrhigh
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop;"
);
if
(
p
&
bitMask
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
XMC_port
->
OMR
=
omrlow
;
}
else
{
XMC_port
->
OMR
=
omrlow
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
}
if
(
bitMask
>>=
1
)
{
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
);
}
else
{
if
(
ptr
>=
end
)
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
}
}
#ifdef NEO_KHZ400
}
else
{
// 400 KHz bitstream
// ToDo!
}
#endif
//----
#elif defined(__SAMD51__) // M4
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
,
portNum
,
bit
;
uint32_t
pinMask
;
portNum
=
g_APinDescription
[
pin
].
ulPort
;
pinMask
=
1ul
<<
g_APinDescription
[
pin
].
ulPin
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
volatile
uint32_t
*
set
=
&
(
PORT
->
Group
[
portNum
].
OUTSET
.
reg
),
volatile
uint32_t
*
set
=
&
(
PORT
->
Group
[
portNum
].
OUTSET
.
reg
),
*
clr
=
&
(
PORT
->
Group
[
portNum
].
OUTCLR
.
reg
);
*
clr
=
&
(
PORT
->
Group
[
portNum
].
OUTCLR
.
reg
);
...
@@ -1745,65 +2529,67 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1745,65 +2529,67 @@ void Adafruit_NeoPixel::show(void) {
// seems to work just well enough. When finished, the SysTick
// seems to work just well enough. When finished, the SysTick
// peripheral is set back to its original state.
// peripheral is set back to its original state.
uint32_t
t0
,
t1
,
top
,
ticks
,
uint32_t
t0
,
t1
,
top
,
ticks
,
saveLoad
=
SysTick
->
LOAD
,
saveVal
=
SysTick
->
VAL
;
saveLoad
=
SysTick
->
LOAD
,
saveVal
=
SysTick
->
VAL
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
top
=
(
uint32_t
)(
F_CPU
*
0.00000125
);
// Bit hi + lo = 1.25 uS
top
=
(
uint32_t
)(
F_CPU
*
0.00000125
);
// Bit hi + lo = 1.25 uS
t0
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000040
);
// 0 = 0.4 uS hi
t0
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000040
);
// 0 = 0.4 uS hi
t1
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000080
);
// 1 = 0.8 uS hi
t1
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000080
);
// 1 = 0.8 uS hi
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 KHz bitstream
}
else
{
// 400 KHz bitstream
top
=
(
uint32_t
)(
F_CPU
*
0.00000250
);
// Bit hi + lo = 2.5 uS
top
=
(
uint32_t
)(
F_CPU
*
0.00000250
);
// Bit hi + lo = 2.5 uS
t0
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000050
);
// 0 = 0.5 uS hi
t0
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000050
);
// 0 = 0.5 uS hi
t1
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000120
);
// 1 = 1.2 uS hi
t1
=
top
-
(
uint32_t
)(
F_CPU
*
0.00000120
);
// 1 = 1.2 uS hi
}
}
#endif
#endif
SysTick
->
LOAD
=
top
;
// Config SysTick for NeoPixel bit freq
SysTick
->
LOAD
=
top
;
// Config SysTick for NeoPixel bit freq
SysTick
->
VAL
=
top
;
// Set to start value (counts down)
SysTick
->
VAL
=
top
;
// Set to start value (counts down)
(
void
)
SysTick
->
VAL
;
// Dummy read helps sync up 1st bit
(
void
)
SysTick
->
VAL
;
// Dummy read helps sync up 1st bit
for
(;;)
{
for
(;;)
{
*
set
=
pinMask
;
// Set output high
*
set
=
pinMask
;
// Set output high
ticks
=
(
p
&
bitMask
)
?
t1
:
t0
;
// SysTick threshold,
ticks
=
(
p
&
bitMask
)
?
t1
:
t0
;
// SysTick threshold,
while
(
SysTick
->
VAL
>
ticks
);
// wait for it
while
(
SysTick
->
VAL
>
ticks
)
*
clr
=
pinMask
;
// Set output low
;
// wait for it
if
(
!
(
bitMask
>>=
1
))
{
// Next bit for this byte...done?
*
clr
=
pinMask
;
// Set output low
if
(
ptr
>=
end
)
break
;
// If last byte sent, exit loop
if
(
!
(
bitMask
>>=
1
))
{
// Next bit for this byte...done?
p
=
*
ptr
++
;
// Fetch next byte
if
(
ptr
>=
end
)
bitMask
=
0x80
;
// Reset bitmask
break
;
// If last byte sent, exit loop
p
=
*
ptr
++
;
// Fetch next byte
bitMask
=
0x80
;
// Reset bitmask
}
}
while
(
SysTick
->
VAL
<=
ticks
);
// Wait for rollover to 'top'
while
(
SysTick
->
VAL
<=
ticks
)
;
// Wait for rollover to 'top'
}
}
SysTick
->
LOAD
=
saveLoad
;
// Restore SysTick rollover to 1 ms
SysTick
->
LOAD
=
saveLoad
;
// Restore SysTick rollover to 1 ms
SysTick
->
VAL
=
saveVal
;
// Restore SysTick value
SysTick
->
VAL
=
saveVal
;
// Restore SysTick value
#elif defined
(ARDUINO_STM32_FEATHER) // FEATHER WICED (120MHz)
#elif defined(ARDUINO_STM32_FEATHER) // FEATHER WICED (120MHz)
// Tried this with a timer/counter, couldn't quite get adequate
// Tried this with a timer/counter, couldn't quite get adequate
// resolution. So yay, you get a load of goofball NOPs...
// resolution. So yay, you get a load of goofball NOPs...
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
;
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
;
uint32_t
pinMask
;
uint32_t
pinMask
;
pinMask
=
BIT
(
PIN_MAP
[
pin
].
gpio_bit
);
pinMask
=
BIT
(
PIN_MAP
[
pin
].
gpio_bit
);
ptr
=
pixels
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
volatile
uint16_t
*
set
=
&
(
PIN_MAP
[
pin
].
gpio_device
->
regs
->
BSRRL
);
volatile
uint16_t
*
set
=
&
(
PIN_MAP
[
pin
].
gpio_device
->
regs
->
BSRRL
);
volatile
uint16_t
*
clr
=
&
(
PIN_MAP
[
pin
].
gpio_device
->
regs
->
BSRRH
);
volatile
uint16_t
*
clr
=
&
(
PIN_MAP
[
pin
].
gpio_device
->
regs
->
BSRRH
);
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
for
(;;)
{
for
(;;)
{
if
(
p
&
bitMask
)
{
// ONE
if
(
p
&
bitMask
)
{
// ONE
// High 800ns
// High 800ns
*
set
=
pinMask
;
*
set
=
pinMask
;
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
asm
(
"nop; nop; nop; nop; nop; nop; nop; nop;"
...
@@ -1849,12 +2635,13 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1849,12 +2635,13 @@ void Adafruit_NeoPixel::show(void) {
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop;"
);
"nop; nop; nop; nop;"
);
}
}
if
(
bitMask
>>=
1
)
{
if
(
bitMask
>>=
1
)
{
// Move on to the next pixel
// Move on to the next pixel
asm
(
"nop;"
);
asm
(
"nop;"
);
}
else
{
}
else
{
if
(
ptr
>=
end
)
break
;
if
(
ptr
>=
end
)
p
=
*
ptr
++
;
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
}
}
}
}
...
@@ -1865,17 +2652,17 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1865,17 +2652,17 @@ void Adafruit_NeoPixel::show(void) {
#endif
#endif
#elif defined(TARGET_LPC1768)
#elif defined(TARGET_LPC1768)
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
;
uint8_t
*
ptr
,
*
end
,
p
,
bitMask
;
ptr
=
pixels
;
ptr
=
pixels
;
end
=
ptr
+
numBytes
;
end
=
ptr
+
numBytes
;
p
=
*
ptr
++
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
for
(;;)
{
for
(;;)
{
if
(
p
&
bitMask
)
{
if
(
p
&
bitMask
)
{
// data ONE high
// data ONE high
// min: 550 typ: 700 max: 5,500
// min: 550 typ: 700 max: 5,500
gpio_set
(
pin
);
gpio_set
(
pin
);
...
@@ -1893,12 +2680,13 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1893,12 +2680,13 @@ void Adafruit_NeoPixel::show(void) {
gpio_clear
(
pin
);
gpio_clear
(
pin
);
time
::
delay_ns
(
450
);
time
::
delay_ns
(
450
);
}
}
if
(
bitMask
>>=
1
)
{
if
(
bitMask
>>=
1
)
{
// Move on to the next pixel
// Move on to the next pixel
asm
(
"nop;"
);
asm
(
"nop;"
);
}
else
{
}
else
{
if
(
ptr
>=
end
)
break
;
if
(
ptr
>=
end
)
p
=
*
ptr
++
;
break
;
p
=
*
ptr
++
;
bitMask
=
0x80
;
bitMask
=
0x80
;
}
}
}
}
...
@@ -1908,204 +2696,229 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -1908,204 +2696,229 @@ void Adafruit_NeoPixel::show(void) {
}
}
#endif
#endif
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
uint8_t
*
p
=
pixels
,
*
end
=
p
+
numBytes
,
uint8_t
*
p
=
pixels
,
*
end
=
p
+
numBytes
,
pix
=
*
p
++
,
mask
=
0x80
;
pix
=
*
p
++
,
mask
=
0x80
;
uint32_t
cyc
;
uint32_t
cyc
;
uint32_t
saveLoad
=
SysTick
->
LOAD
,
saveVal
=
SysTick
->
VAL
;
uint32_t
saveLoad
=
SysTick
->
LOAD
,
saveVal
=
SysTick
->
VAL
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
uint32_t
top
=
(
F_CPU
/
800000
);
// 1.25µs
uint32_t
top
=
(
F_CPU
/
800000
);
// 1.25µs
uint32_t
t0
=
top
-
(
F_CPU
/
2500000
);
// 0.4µs
uint32_t
t0
=
top
-
(
F_CPU
/
2500000
);
// 0.4µs
uint32_t
t1
=
top
-
(
F_CPU
/
1250000
);
// 0.8µs
uint32_t
t1
=
top
-
(
F_CPU
/
1250000
);
// 0.8µs
SysTick
->
LOAD
=
top
-
1
;
// Config SysTick for NeoPixel bit freq
SysTick
->
LOAD
=
top
-
1
;
// Config SysTick for NeoPixel bit freq
SysTick
->
VAL
=
0
;
// Set to start value
SysTick
->
VAL
=
0
;
// Set to start value
for
(;;)
{
for
(;;)
{
LL_GPIO_SetOutputPin
(
gpioPort
,
gpioPin
);
LL_GPIO_SetOutputPin
(
gpioPort
,
gpioPin
);
cyc
=
(
pix
&
mask
)
?
t1
:
t0
;
cyc
=
(
pix
&
mask
)
?
t1
:
t0
;
while
(
SysTick
->
VAL
>
cyc
);
while
(
SysTick
->
VAL
>
cyc
)
;
LL_GPIO_ResetOutputPin
(
gpioPort
,
gpioPin
);
LL_GPIO_ResetOutputPin
(
gpioPort
,
gpioPin
);
if
(
!
(
mask
>>=
1
))
{
if
(
!
(
mask
>>=
1
))
{
if
(
p
>=
end
)
break
;
if
(
p
>=
end
)
pix
=
*
p
++
;
break
;
pix
=
*
p
++
;
mask
=
0x80
;
mask
=
0x80
;
}
}
while
(
SysTick
->
VAL
<=
cyc
);
while
(
SysTick
->
VAL
<=
cyc
)
;
}
}
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 kHz bitstream
}
else
{
// 400 kHz bitstream
uint32_t
top
=
(
F_CPU
/
400000
);
// 2.5µs
uint32_t
top
=
(
F_CPU
/
400000
);
// 2.5µs
uint32_t
t0
=
top
-
(
F_CPU
/
2000000
);
// 0.5µs
uint32_t
t0
=
top
-
(
F_CPU
/
2000000
);
// 0.5µs
uint32_t
t1
=
top
-
(
F_CPU
/
833333
);
// 1.2µs
uint32_t
t1
=
top
-
(
F_CPU
/
833333
);
// 1.2µs
SysTick
->
LOAD
=
top
-
1
;
// Config SysTick for NeoPixel bit freq
SysTick
->
LOAD
=
top
-
1
;
// Config SysTick for NeoPixel bit freq
SysTick
->
VAL
=
0
;
// Set to start value
SysTick
->
VAL
=
0
;
// Set to start value
for
(;;)
{
for
(;;)
{
LL_GPIO_SetOutputPin
(
gpioPort
,
gpioPin
);
LL_GPIO_SetOutputPin
(
gpioPort
,
gpioPin
);
cyc
=
(
pix
&
mask
)
?
t1
:
t0
;
cyc
=
(
pix
&
mask
)
?
t1
:
t0
;
while
(
SysTick
->
VAL
>
cyc
);
while
(
SysTick
->
VAL
>
cyc
)
;
LL_GPIO_ResetOutputPin
(
gpioPort
,
gpioPin
);
LL_GPIO_ResetOutputPin
(
gpioPort
,
gpioPin
);
if
(
!
(
mask
>>=
1
))
{
if
(
!
(
mask
>>=
1
))
{
if
(
p
>=
end
)
break
;
if
(
p
>=
end
)
pix
=
*
p
++
;
break
;
pix
=
*
p
++
;
mask
=
0x80
;
mask
=
0x80
;
}
}
while
(
SysTick
->
VAL
<=
cyc
);
while
(
SysTick
->
VAL
<=
cyc
)
;
}
}
}
}
#endif // NEO_KHZ400
#endif // NEO_KHZ400
SysTick
->
LOAD
=
saveLoad
;
// Restore SysTick rollover to 1 ms
SysTick
->
LOAD
=
saveLoad
;
// Restore SysTick rollover to 1 ms
SysTick
->
VAL
=
saveVal
;
// Restore SysTick value
SysTick
->
VAL
=
saveVal
;
// Restore SysTick value
#elif defined (NRF51)
#elif defined(NRF51)
uint8_t
*
p
=
pixels
,
uint8_t
*
p
=
pixels
,
pix
,
count
,
mask
;
pix
,
count
,
mask
;
int32_t
num
=
numBytes
;
int32_t
num
=
numBytes
;
unsigned
int
bitmask
=
(
1
<<
g_ADigitalPinMap
[
pin
]);
unsigned
int
bitmask
=
(
1
<<
g_ADigitalPinMap
[
pin
]
);
// https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/variants/BBCmicrobit/variant.cpp
// https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/variants/BBCmicrobit/variant.cpp
volatile
unsigned
int
*
reg
=
(
unsigned
int
*
)
(
0x50000000UL
+
0x508
);
volatile
unsigned
int
*
reg
=
(
unsigned
int
*
)(
0x50000000UL
+
0x508
);
// https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/cores/nRF5/SDK/components/device/nrf51.h
// https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/cores/nRF5/SDK/components/device/nrf51.h
// http://www.iot-programmer.com/index.php/books/27-micro-bit-iot-in-c/chapters-micro-bit-iot-in-c/47-micro-bit-iot-in-c-fast-memory-mapped-gpio?showall=1
// http://www.iot-programmer.com/index.php/books/27-micro-bit-iot-in-c/chapters-micro-bit-iot-in-c/47-micro-bit-iot-in-c-fast-memory-mapped-gpio?showall=1
// https://github.com/Microsoft/pxt-neopixel/blob/master/sendbuffer.asm
// https://github.com/Microsoft/pxt-neopixel/blob/master/sendbuffer.asm
asm
volatile
(
asm
volatile
(
// "cpsid i" ; disable irq
// "cpsid i" ; disable irq
// b .start
// b .start
"b L%=_start"
"
\n\t
"
"b L%=_start"
// .nextbit: ; C0
"
\n\t
"
"L%=_nextbit:"
"
\n\t
"
//; C0
// .nextbit: ; C0
// str r1, [r3, #0] ; pin := hi C2
"L%=_nextbit:"
"strb %[bitmask], [%[reg], #0]"
"
\n\t
"
//; pin := hi C2
"
\n\t
"
//; C0
// tst r6, r0 ; C3
// str r1, [r3, #0] ; pin := hi C2
"tst %[mask], %[pix]"
"
\n\t
"
// ; C3
"strb %[bitmask], [%[reg], #0]"
// bne .islate ; C4
"
\n\t
"
//; pin := hi C2
"bne L%=_islate"
"
\n\t
"
//; C4
// tst r6, r0 ; C3
// str r1, [r2, #0] ; pin := lo C6
"tst %[mask], %[pix]"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
//; pin := lo C6
"
\n\t
"
// ; C3
// .islate:
// bne .islate ; C4
"L%=_islate:"
"
\n\t
"
"bne L%=_islate"
// lsrs r6, r6, #1 ; r6 >>= 1 C7
"
\n\t
"
//; C4
"lsr %[mask], %[mask], #1"
"
\n\t
"
//; r6 >>= 1 C7
// str r1, [r2, #0] ; pin := lo C6
// bne .justbit ; C8
"strb %[bitmask], [%[reg], #4]"
"bne L%=_justbit"
"
\n\t
"
//; C8
"
\n\t
"
//; pin := lo C6
// .islate:
// ; not just a bit - need new byte
"L%=_islate:"
// adds r4, #1 ; r4++ C9
"
\n\t
"
"add %[p], #1"
"
\n\t
"
//; r4++ C9
// lsrs r6, r6, #1 ; r6 >>= 1 C7
// subs r5, #1 ; r5-- C10
"lsr %[mask], %[mask], #1"
"sub %[num], #1"
"
\n\t
"
//; r5-- C10
"
\n\t
"
//; r6 >>= 1 C7
// bcc .stop ; if (r5<0) goto .stop C11
// bne .justbit ; C8
"bcc L%=_stop"
"
\n\t
"
//; if (r5<0) goto .stop C11
"bne L%=_justbit"
// .start:
"
\n\t
"
//; C8
"L%=_start:"
// movs r6, #0x80 ; reset mask C12
// ; not just a bit - need new byte
"movs %[mask], #0x80"
"
\n\t
"
//; reset mask C12
// adds r4, #1 ; r4++ C9
// nop ; C13
"add %[p], #1"
"nop"
"
\n\t
"
//; C13
"
\n\t
"
//; r4++ C9
// subs r5, #1 ; r5-- C10
// .common: ; C13
"sub %[num], #1"
"L%=_common:"
"
\n\t
"
//; C13
"
\n\t
"
//; r5-- C10
// str r1, [r2, #0] ; pin := lo C15
// bcc .stop ; if (r5<0) goto .stop C11
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
//; pin := lo C15
"bcc L%=_stop"
// ; always re-load byte - it just fits with the cycles better this way
"
\n\t
"
//; if (r5<0) goto .stop C11
// ldrb r0, [r4, #0] ; r0 := *r4 C17
// .start:
"ldrb %[pix], [%[p], #0]"
"
\n\t
"
//; r0 := *r4 C17
"L%=_start:"
// b .nextbit ; C20
// movs r6, #0x80 ; reset mask C12
"b L%=_nextbit"
"
\n\t
"
//; C20
"movs %[mask], #0x80"
"
\n\t
"
//; reset mask C12
// .justbit: ; C10
// nop ; C13
"L%=_justbit:"
"
\n\t
"
//; C10
"nop"
// ; no nops, branch taken is already 3 cycles
"
\n\t
"
//; C13
// b .common ; C13
"b L%=_common"
"
\n\t
"
//; C13
// .common: ; C13
"L%=_common:"
// .stop:
"
\n\t
"
//; C13
"L%=_stop:"
"
\n\t
"
// str r1, [r2, #0] ; pin := lo C15
// str r1, [r2, #0] ; pin := lo
"strb %[bitmask], [%[reg], #4]"
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
//; pin := lo
"
\n\t
"
//; pin := lo C15
// cpsie i ; enable irq
// ; always re-load byte - it just fits with the cycles better this way
// ldrb r0, [r4, #0] ; r0 := *r4 C17
:
[
p
]
"+r"
(
p
),
"ldrb %[pix], [%[p], #0]"
[
pix
]
"=&r"
(
pix
),
"
\n\t
"
//; r0 := *r4 C17
[
count
]
"=&r"
(
count
),
// b .nextbit ; C20
[
mask
]
"=&r"
(
mask
),
"b L%=_nextbit"
[
num
]
"+r"
(
num
)
"
\n\t
"
//; C20
:
[
bitmask
]
"r"
(
bitmask
),
[
reg
]
"r"
(
reg
)
// .justbit: ; C10
);
"L%=_justbit:"
"
\n\t
"
//; C10
// ; no nops, branch taken is already 3 cycles
// b .common ; C13
"b L%=_common"
"
\n\t
"
//; C13
// .stop:
"L%=_stop:"
"
\n\t
"
// str r1, [r2, #0] ; pin := lo
"strb %[bitmask], [%[reg], #4]"
"
\n\t
"
//; pin := lo
// cpsie i ; enable irq
:
[
p
]
"+r"
(
p
),
[
pix
]
"=&r"
(
pix
),
[
count
]
"=&r"
(
count
),
[
mask
]
"=&r"
(
mask
),
[
num
]
"+r"
(
num
)
:
[
bitmask
]
"r"
(
bitmask
),
[
reg
]
"r"
(
reg
));
#elif defined(__SAM3X8E__) // Arduino Due
#elif defined(__SAM3X8E__) // Arduino Due
#define SCALE
VARIANT_MCK / 2UL / 1000000UL
#define SCALE VARIANT_MCK / 2UL / 1000000UL
#define INST
(2UL * F_CPU / VARIANT_MCK)
#define INST (2UL * F_CPU / VARIANT_MCK)
#define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
#define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
#define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
#define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
#define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
#define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
#define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
#define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
#define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
#define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
#define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))
#define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))
int
pinMask
,
time0
,
time1
,
period
,
t
;
int
pinMask
,
time0
,
time1
,
period
,
t
;
Pio
*
port
;
Pio
*
port
;
volatile
WoReg
*
portSet
,
*
portClear
,
*
timeValue
,
*
timeReset
;
volatile
WoReg
*
portSet
,
*
portClear
,
*
timeValue
,
*
timeReset
;
uint8_t
*
p
,
*
end
,
pix
,
mask
;
uint8_t
*
p
,
*
end
,
pix
,
mask
;
pmc_set_writeprotect
(
false
);
pmc_set_writeprotect
(
false
);
pmc_enable_periph_clk
((
uint32_t
)
TC3_IRQn
);
pmc_enable_periph_clk
((
uint32_t
)
TC3_IRQn
);
TC_Configure
(
TC1
,
0
,
TC_Configure
(
TC1
,
0
,
TC_CMR_WAVE
|
TC_CMR_WAVSEL_UP
|
TC_CMR_TCCLKS_TIMER_CLOCK1
);
TC_CMR_WAVE
|
TC_CMR_WAVSEL_UP
|
TC_CMR_TCCLKS_TIMER_CLOCK1
);
TC_Start
(
TC1
,
0
);
TC_Start
(
TC1
,
0
);
pinMask
=
g_APinDescription
[
pin
].
ulPin
;
// Don't 'optimize' these into
pinMask
=
g_APinDescription
[
pin
].
ulPin
;
// Don't 'optimize' these into
port
=
g_APinDescription
[
pin
].
pPort
;
// declarations above. Want to
port
=
g_APinDescription
[
pin
].
pPort
;
// declarations above. Want to
portSet
=
&
(
port
->
PIO_SODR
);
// burn a few cycles after
portSet
=
&
(
port
->
PIO_SODR
);
// burn a few cycles after
portClear
=
&
(
port
->
PIO_CODR
);
// starting timer to minimize
portClear
=
&
(
port
->
PIO_CODR
);
// starting timer to minimize
timeValue
=
&
(
TC1
->
TC_CHANNEL
[
0
].
TC_CV
);
// the initial 'while'.
timeValue
=
&
(
TC1
->
TC_CHANNEL
[
0
].
TC_CV
);
// the initial 'while'.
timeReset
=
&
(
TC1
->
TC_CHANNEL
[
0
].
TC_CCR
);
timeReset
=
&
(
TC1
->
TC_CHANNEL
[
0
].
TC_CCR
);
p
=
pixels
;
p
=
pixels
;
end
=
p
+
numBytes
;
end
=
p
+
numBytes
;
pix
=
*
p
++
;
pix
=
*
p
++
;
mask
=
0x80
;
mask
=
0x80
;
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
if
(
is800KHz
)
{
if
(
is800KHz
)
{
#endif
#endif
time0
=
TIME_800_0
;
time0
=
TIME_800_0
;
time1
=
TIME_800_1
;
time1
=
TIME_800_1
;
period
=
PERIOD_800
;
period
=
PERIOD_800
;
#if defined(NEO_KHZ400)
#if defined(NEO_KHZ400)
}
else
{
// 400 KHz bitstream
}
else
{
// 400 KHz bitstream
time0
=
TIME_400_0
;
time0
=
TIME_400_0
;
time1
=
TIME_400_1
;
time1
=
TIME_400_1
;
period
=
PERIOD_400
;
period
=
PERIOD_400
;
}
}
#endif
#endif
for
(
t
=
time0
;;
t
=
time0
)
{
for
(
t
=
time0
;;
t
=
time0
)
{
if
(
pix
&
mask
)
t
=
time1
;
if
(
pix
&
mask
)
while
(
*
timeValue
<
(
unsigned
)
period
);
t
=
time1
;
*
portSet
=
pinMask
;
while
(
*
timeValue
<
(
unsigned
)
period
)
;
*
portSet
=
pinMask
;
*
timeReset
=
TC_CCR_CLKEN
|
TC_CCR_SWTRG
;
*
timeReset
=
TC_CCR_CLKEN
|
TC_CCR_SWTRG
;
while
(
*
timeValue
<
(
unsigned
)
t
);
while
(
*
timeValue
<
(
unsigned
)
t
)
;
*
portClear
=
pinMask
;
*
portClear
=
pinMask
;
if
(
!
(
mask
>>=
1
))
{
// This 'inside-out' loop logic utilizes
if
(
!
(
mask
>>=
1
))
{
// This 'inside-out' loop logic utilizes
if
(
p
>=
end
)
break
;
// idle time to minimize inter-byte delays.
if
(
p
>=
end
)
break
;
// idle time to minimize inter-byte delays.
pix
=
*
p
++
;
pix
=
*
p
++
;
mask
=
0x80
;
mask
=
0x80
;
}
}
}
}
while
(
*
timeValue
<
(
unsigned
)
period
);
// Wait for last bit
while
(
*
timeValue
<
(
unsigned
)
period
)
;
// Wait for last bit
TC_Stop
(
TC1
,
0
);
TC_Stop
(
TC1
,
0
);
#endif // end Due
#endif // end Due
// END ARM ----------------------------------------------------------------
// END ARM ----------------------------------------------------------------
#elif defined(ESP8266) || defined(ESP32)
#elif defined(ESP8266) || defined(ESP32)
// ESP8266 ----------------------------------------------------------------
// ESP8266 ----------------------------------------------------------------
// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
espShow
(
pin
,
pixels
,
numBytes
,
is800KHz
);
espShow
(
pin
,
pixels
,
numBytes
,
is800KHz
);
...
@@ -2113,94 +2926,97 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -2113,94 +2926,97 @@ void Adafruit_NeoPixel::show(void) {
#elif defined(KENDRYTE_K210)
#elif defined(KENDRYTE_K210)
k210Show
(
pin
,
pixels
,
numBytes
,
is800KHz
);
k210Show
(
pin
,
pixels
,
numBytes
,
is800KHz
);
#elif defined(__ARDUINO_ARC__)
// Arduino 101 -----------------------------------------------------------
#elif defined(__ARDUINO_ARC__)
#define NOPx7 { __builtin_arc_nop(); \
// Arduino 101 -----------------------------------------------------------
__builtin_arc_nop
();
__builtin_arc_nop
();
\
__builtin_arc_nop
();
__builtin_arc_nop
();
\
#define NOPx7 \
__builtin_arc_nop
();
__builtin_arc_nop
();
}
{
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
__builtin_arc_nop
();
\
}
PinDescription
*
pindesc
=
&
g_APinDescription
[
pin
];
PinDescription
*
pindesc
=
&
g_APinDescription
[
pin
];
register
uint32_t
loop
=
8
*
numBytes
;
// one loop to handle all bytes and all bits
register
uint32_t
loop
=
8
*
numBytes
;
// one loop to handle all bytes and all bits
register
uint8_t
*
p
=
pixels
;
register
uint8_t
*
p
=
pixels
;
register
uint32_t
currByte
=
(
uint32_t
)
(
*
p
);
register
uint32_t
currByte
=
(
uint32_t
)(
*
p
);
register
uint32_t
currBit
=
0x80
&
currByte
;
register
uint32_t
currBit
=
0x80
&
currByte
;
register
uint32_t
bitCounter
=
0
;
register
uint32_t
bitCounter
=
0
;
register
uint32_t
first
=
1
;
register
uint32_t
first
=
1
;
// The loop is unusual. Very first iteration puts all the way LOW to the wire -
// The loop is unusual. Very first iteration puts all the way LOW to the wire
// constant LOW does not affect NEOPIXEL, so there is no visible effect displayed.
// - constant LOW does not affect NEOPIXEL, so there is no visible effect
// During that very first iteration CPU caches instructions in the loop.
// displayed. During that very first iteration CPU caches instructions in the
// Because of the caching process, "CPU slows down". NEOPIXEL pulse is very time sensitive
// loop. Because of the caching process, "CPU slows down". NEOPIXEL pulse is
// that's why we let the CPU cache first and we start regular pulse from 2nd iteration
// very time sensitive that's why we let the CPU cache first and we start
// regular pulse from 2nd iteration
if
(
pindesc
->
ulGPIOType
==
SS_GPIO
)
{
if
(
pindesc
->
ulGPIOType
==
SS_GPIO
)
{
register
uint32_t
reg
=
pindesc
->
ulGPIOBase
+
SS_GPIO_SWPORTA_DR
;
register
uint32_t
reg
=
pindesc
->
ulGPIOBase
+
SS_GPIO_SWPORTA_DR
;
uint32_t
reg_val
=
__builtin_arc_lr
((
volatile
uint32_t
)
reg
);
uint32_t
reg_val
=
__builtin_arc_lr
((
volatile
uint32_t
)
reg
);
register
uint32_t
reg_bit_high
=
reg_val
|
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_high
=
reg_val
|
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_low
=
reg_val
&
~
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_low
=
reg_val
&
~
(
1
<<
pindesc
->
ulGPIOId
);
loop
+=
1
;
// include first, special iteration
loop
+=
1
;
// include first, special iteration
while
(
loop
--
)
{
while
(
loop
--
)
{
if
(
!
first
)
{
if
(
!
first
)
{
currByte
<<=
1
;
currByte
<<=
1
;
bitCounter
++
;
bitCounter
++
;
}
}
// 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
// 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
__builtin_arc_sr
(
first
?
reg_bit_low
:
reg_bit_high
,
(
volatile
uint32_t
)
reg
);
__builtin_arc_sr
(
first
?
reg_bit_low
:
reg_bit_high
,
if
(
currBit
)
{
// ~400ns HIGH (740ns overall)
(
volatile
uint32_t
)
reg
);
NOPx7
if
(
currBit
)
{
// ~400ns HIGH (740ns overall)
NOPx7
NOPx7
NOPx7
}
}
// ~340ns HIGH
// ~340ns HIGH
NOPx7
NOPx7
__builtin_arc_nop
();
__builtin_arc_nop
();
// 820ns LOW; per spec, max allowed low here is 5000ns */
// 820ns LOW; per spec, max allowed low here is 5000ns */
__builtin_arc_sr
(
reg_bit_low
,
(
volatile
uint32_t
)
reg
);
__builtin_arc_sr
(
reg_bit_low
,
(
volatile
uint32_t
)
reg
);
NOPx7
NOPx7
NOPx7
NOPx7
if
(
bitCounter
>=
8
)
{
if
(
bitCounter
>=
8
)
{
bitCounter
=
0
;
bitCounter
=
0
;
currByte
=
(
uint32_t
)
(
*++
p
);
currByte
=
(
uint32_t
)(
*++
p
);
}
}
currBit
=
0x80
&
currByte
;
currBit
=
0x80
&
currByte
;
first
=
0
;
first
=
0
;
}
}
}
else
if
(
pindesc
->
ulGPIOType
==
SOC_GPIO
)
{
}
else
if
(
pindesc
->
ulGPIOType
==
SOC_GPIO
)
{
register
uint32_t
reg
=
pindesc
->
ulGPIOBase
+
SOC_GPIO_SWPORTA_DR
;
register
uint32_t
reg
=
pindesc
->
ulGPIOBase
+
SOC_GPIO_SWPORTA_DR
;
uint32_t
reg_val
=
MMIO_REG_VAL
(
reg
);
uint32_t
reg_val
=
MMIO_REG_VAL
(
reg
);
register
uint32_t
reg_bit_high
=
reg_val
|
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_high
=
reg_val
|
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_low
=
reg_val
&
~
(
1
<<
pindesc
->
ulGPIOId
);
register
uint32_t
reg_bit_low
=
reg_val
&
~
(
1
<<
pindesc
->
ulGPIOId
);
loop
+=
1
;
// include first, special iteration
loop
+=
1
;
// include first, special iteration
while
(
loop
--
)
{
while
(
loop
--
)
{
if
(
!
first
)
{
if
(
!
first
)
{
currByte
<<=
1
;
currByte
<<=
1
;
bitCounter
++
;
bitCounter
++
;
}
}
MMIO_REG_VAL
(
reg
)
=
first
?
reg_bit_low
:
reg_bit_high
;
MMIO_REG_VAL
(
reg
)
=
first
?
reg_bit_low
:
reg_bit_high
;
if
(
currBit
)
{
// ~430ns HIGH (740ns overall)
if
(
currBit
)
{
// ~430ns HIGH (740ns overall)
NOPx7
NOPx7
NOPx7
__builtin_arc_nop
();
NOPx7
__builtin_arc_nop
();
}
}
// ~310ns HIGH
// ~310ns HIGH
NOPx7
NOPx7
// 850ns LOW; per spec, max allowed low here is 5000ns */
// 850ns LOW; per spec, max allowed low here is 5000ns */
MMIO_REG_VAL
(
reg
)
=
reg_bit_low
;
MMIO_REG_VAL
(
reg
)
=
reg_bit_low
;
NOPx7
NOPx7
NOPx7
NOPx7
if
(
bitCounter
>=
8
)
{
if
(
bitCounter
>=
8
)
{
bitCounter
=
0
;
bitCounter
=
0
;
currByte
=
(
uint32_t
)
(
*++
p
);
currByte
=
(
uint32_t
)(
*++
p
);
}
}
currBit
=
0x80
&
currByte
;
currBit
=
0x80
&
currByte
;
...
@@ -2212,10 +3028,9 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -2212,10 +3028,9 @@ void Adafruit_NeoPixel::show(void) {
#error Architecture not supported
#error Architecture not supported
#endif
#endif
// END ARCHITECTURE SELECT ------------------------------------------------
// END ARCHITECTURE SELECT ------------------------------------------------
#if !(defined(NRF52) || defined(NRF52_SERIES))
#if !( defined(NRF52) || defined(NRF52_SERIES) )
interrupts
();
interrupts
();
#endif
#endif
...
@@ -2227,15 +3042,16 @@ void Adafruit_NeoPixel::show(void) {
...
@@ -2227,15 +3042,16 @@ void Adafruit_NeoPixel::show(void) {
if any, is set to INPUT and the new pin is set to OUTPUT.
if any, is set to INPUT and the new pin is set to OUTPUT.
@param p Arduino pin number (-1 = no pin).
@param p Arduino pin number (-1 = no pin).
*/
*/
void
Adafruit_NeoPixel
::
setPin
(
uint16_t
p
)
{
void
Adafruit_NeoPixel
::
setPin
(
int16_t
p
)
{
if
(
begun
&&
(
pin
>=
0
))
pinMode
(
pin
,
INPUT
);
if
(
begun
&&
(
pin
>=
0
))
pinMode
(
pin
,
INPUT
);
// Disable existing out pin
pin
=
p
;
pin
=
p
;
if
(
begun
)
{
if
(
begun
)
{
pinMode
(
p
,
OUTPUT
);
pinMode
(
p
,
OUTPUT
);
digitalWrite
(
p
,
LOW
);
digitalWrite
(
p
,
LOW
);
}
}
#if defined(__AVR__)
#if defined(__AVR__)
port
=
portOutputRegister
(
digitalPinToPort
(
p
));
port
=
portOutputRegister
(
digitalPinToPort
(
p
));
pinMask
=
digitalPinToBitMask
(
p
);
pinMask
=
digitalPinToBitMask
(
p
);
#endif
#endif
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
...
@@ -2252,23 +3068,23 @@ void Adafruit_NeoPixel::setPin(uint16_t p) {
...
@@ -2252,23 +3068,23 @@ void Adafruit_NeoPixel::setPin(uint16_t p) {
@param g Green brightness, 0 = minimum (off), 255 = maximum.
@param g Green brightness, 0 = minimum (off), 255 = maximum.
@param b Blue brightness, 0 = minimum (off), 255 = maximum.
@param b Blue brightness, 0 = minimum (off), 255 = maximum.
*/
*/
void
Adafruit_NeoPixel
::
setPixelColor
(
void
Adafruit_NeoPixel
::
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
)
{
uint8_t
b
)
{
if
(
n
<
numLEDs
)
{
if
(
n
<
numLEDs
)
{
if
(
brightness
)
{
// See notes in setBrightness()
if
(
brightness
)
{
// See notes in setBrightness()
r
=
(
r
*
brightness
)
>>
8
;
r
=
(
r
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
}
}
uint8_t
*
p
;
uint8_t
*
p
;
if
(
wOffset
==
rOffset
)
{
// Is an RGB-type strip
if
(
wOffset
==
rOffset
)
{
// Is an RGB-type strip
p
=
&
pixels
[
n
*
3
];
// 3 bytes per pixel
p
=
&
pixels
[
n
*
3
];
// 3 bytes per pixel
}
else
{
// Is a WRGB-type strip
}
else
{
// Is a WRGB-type strip
p
=
&
pixels
[
n
*
4
];
// 4 bytes per pixel
p
=
&
pixels
[
n
*
4
];
// 4 bytes per pixel
p
[
wOffset
]
=
0
;
// But only R,G,B passed -- set W to 0
p
[
wOffset
]
=
0
;
// But only R,G,B passed -- set W to 0
}
}
p
[
rOffset
]
=
r
;
// R,G,B always stored
p
[
rOffset
]
=
r
;
// R,G,B always stored
p
[
gOffset
]
=
g
;
p
[
gOffset
]
=
g
;
p
[
bOffset
]
=
b
;
p
[
bOffset
]
=
b
;
}
}
...
@@ -2284,24 +3100,24 @@ void Adafruit_NeoPixel::setPixelColor(
...
@@ -2284,24 +3100,24 @@ void Adafruit_NeoPixel::setPixelColor(
@param w White brightness, 0 = minimum (off), 255 = maximum, ignored
@param w White brightness, 0 = minimum (off), 255 = maximum, ignored
if using RGB pixels.
if using RGB pixels.
*/
*/
void
Adafruit_NeoPixel
::
setPixelColor
(
void
Adafruit_NeoPixel
::
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
,
uint8_t
w
)
{
uint8_t
b
,
uint8_t
w
)
{
if
(
n
<
numLEDs
)
{
if
(
n
<
numLEDs
)
{
if
(
brightness
)
{
// See notes in setBrightness()
if
(
brightness
)
{
// See notes in setBrightness()
r
=
(
r
*
brightness
)
>>
8
;
r
=
(
r
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
w
=
(
w
*
brightness
)
>>
8
;
w
=
(
w
*
brightness
)
>>
8
;
}
}
uint8_t
*
p
;
uint8_t
*
p
;
if
(
wOffset
==
rOffset
)
{
// Is an RGB-type strip
if
(
wOffset
==
rOffset
)
{
// Is an RGB-type strip
p
=
&
pixels
[
n
*
3
];
// 3 bytes per pixel (ignore W)
p
=
&
pixels
[
n
*
3
];
// 3 bytes per pixel (ignore W)
}
else
{
// Is a WRGB-type strip
}
else
{
// Is a WRGB-type strip
p
=
&
pixels
[
n
*
4
];
// 4 bytes per pixel
p
=
&
pixels
[
n
*
4
];
// 4 bytes per pixel
p
[
wOffset
]
=
w
;
// Store W
p
[
wOffset
]
=
w
;
// Store W
}
}
p
[
rOffset
]
=
r
;
// Store R,G,B
p
[
rOffset
]
=
r
;
// Store R,G,B
p
[
gOffset
]
=
g
;
p
[
gOffset
]
=
g
;
p
[
bOffset
]
=
b
;
p
[
bOffset
]
=
b
;
}
}
...
@@ -2315,17 +3131,14 @@ void Adafruit_NeoPixel::setPixelColor(
...
@@ -2315,17 +3131,14 @@ void Adafruit_NeoPixel::setPixelColor(
and least significant byte is blue.
and least significant byte is blue.
*/
*/
void
Adafruit_NeoPixel
::
setPixelColor
(
uint16_t
n
,
uint32_t
c
)
{
void
Adafruit_NeoPixel
::
setPixelColor
(
uint16_t
n
,
uint32_t
c
)
{
if
(
n
<
numLEDs
)
{
if
(
n
<
numLEDs
)
{
uint8_t
*
p
,
uint8_t
*
p
,
r
=
(
uint8_t
)(
c
>>
16
),
g
=
(
uint8_t
)(
c
>>
8
),
b
=
(
uint8_t
)
c
;
r
=
(
uint8_t
)(
c
>>
16
),
if
(
brightness
)
{
// See notes in setBrightness()
g
=
(
uint8_t
)(
c
>>
8
),
b
=
(
uint8_t
)
c
;
if
(
brightness
)
{
// See notes in setBrightness()
r
=
(
r
*
brightness
)
>>
8
;
r
=
(
r
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
g
=
(
g
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
b
=
(
b
*
brightness
)
>>
8
;
}
}
if
(
wOffset
==
rOffset
)
{
if
(
wOffset
==
rOffset
)
{
p
=
&
pixels
[
n
*
3
];
p
=
&
pixels
[
n
*
3
];
}
else
{
}
else
{
p
=
&
pixels
[
n
*
4
];
p
=
&
pixels
[
n
*
4
];
...
@@ -2352,21 +3165,22 @@ void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
...
@@ -2352,21 +3165,22 @@ void Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
void
Adafruit_NeoPixel
::
fill
(
uint32_t
c
,
uint16_t
first
,
uint16_t
count
)
{
void
Adafruit_NeoPixel
::
fill
(
uint32_t
c
,
uint16_t
first
,
uint16_t
count
)
{
uint16_t
i
,
end
;
uint16_t
i
,
end
;
if
(
first
>=
numLEDs
)
{
if
(
first
>=
numLEDs
)
{
return
;
// If first LED is past end of strip, nothing to do
return
;
// If first LED is past end of strip, nothing to do
}
}
// Calculate the index ONE AFTER the last pixel to fill
// Calculate the index ONE AFTER the last pixel to fill
if
(
count
==
0
)
{
if
(
count
==
0
)
{
// Fill to end of strip
// Fill to end of strip
end
=
numLEDs
;
end
=
numLEDs
;
}
else
{
}
else
{
// Ensure that the loop won't go past the last pixel
// Ensure that the loop won't go past the last pixel
end
=
first
+
count
;
end
=
first
+
count
;
if
(
end
>
numLEDs
)
end
=
numLEDs
;
if
(
end
>
numLEDs
)
end
=
numLEDs
;
}
}
for
(
i
=
first
;
i
<
end
;
i
++
)
{
for
(
i
=
first
;
i
<
end
;
i
++
)
{
this
->
setPixelColor
(
i
,
c
);
this
->
setPixelColor
(
i
,
c
);
}
}
}
}
...
@@ -2429,45 +3243,45 @@ uint32_t Adafruit_NeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
...
@@ -2429,45 +3243,45 @@ uint32_t Adafruit_NeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
// the constants below are not the multiples of 256 you might expect.
// the constants below are not the multiples of 256 you might expect.
// Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
// Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
if
(
hue
<
510
)
{
// Red to Green-1
if
(
hue
<
510
)
{
// Red to Green-1
b
=
0
;
b
=
0
;
if
(
hue
<
255
)
{
// Red to Yellow-1
if
(
hue
<
255
)
{
// Red to Yellow-1
r
=
255
;
r
=
255
;
g
=
hue
;
// g = 0 to 254
g
=
hue
;
// g = 0 to 254
}
else
{
// Yellow to Green-1
}
else
{
// Yellow to Green-1
r
=
510
-
hue
;
// r = 255 to 1
r
=
510
-
hue
;
// r = 255 to 1
g
=
255
;
g
=
255
;
}
}
}
else
if
(
hue
<
1020
)
{
// Green to Blue-1
}
else
if
(
hue
<
1020
)
{
// Green to Blue-1
r
=
0
;
r
=
0
;
if
(
hue
<
765
)
{
// Green to Cyan-1
if
(
hue
<
765
)
{
// Green to Cyan-1
g
=
255
;
g
=
255
;
b
=
hue
-
510
;
// b = 0 to 254
b
=
hue
-
510
;
// b = 0 to 254
}
else
{
// Cyan to Blue-1
}
else
{
// Cyan to Blue-1
g
=
1020
-
hue
;
// g = 255 to 1
g
=
1020
-
hue
;
// g = 255 to 1
b
=
255
;
b
=
255
;
}
}
}
else
if
(
hue
<
1530
)
{
// Blue to Red-1
}
else
if
(
hue
<
1530
)
{
// Blue to Red-1
g
=
0
;
g
=
0
;
if
(
hue
<
1275
)
{
// Blue to Magenta-1
if
(
hue
<
1275
)
{
// Blue to Magenta-1
r
=
hue
-
1020
;
// r = 0 to 254
r
=
hue
-
1020
;
// r = 0 to 254
b
=
255
;
b
=
255
;
}
else
{
// Magenta to Red-1
}
else
{
// Magenta to Red-1
r
=
255
;
r
=
255
;
b
=
1530
-
hue
;
// b = 255 to 1
b
=
1530
-
hue
;
// b = 255 to 1
}
}
}
else
{
// Last 0.5 Red (quicker than % operator)
}
else
{
// Last 0.5 Red (quicker than % operator)
r
=
255
;
r
=
255
;
g
=
b
=
0
;
g
=
b
=
0
;
}
}
// Apply saturation and value to R,G,B, pack into 32-bit result:
// Apply saturation and value to R,G,B, pack into 32-bit result:
uint32_t
v1
=
1
+
val
;
// 1 to 256; allows >>8 instead of /255
uint32_t
v1
=
1
+
val
;
// 1 to 256; allows >>8 instead of /255
uint16_t
s1
=
1
+
sat
;
// 1 to 256; same reason
uint16_t
s1
=
1
+
sat
;
// 1 to 256; same reason
uint8_t
s2
=
255
-
sat
;
// 255 to 0
uint8_t
s2
=
255
-
sat
;
// 255 to 0
return
((((((
r
*
s1
)
>>
8
)
+
s2
)
*
v1
)
&
0xff00
)
<<
8
)
|
return
((((((
r
*
s1
)
>>
8
)
+
s2
)
*
v1
)
&
0xff00
)
<<
8
)
|
(((((
g
*
s1
)
>>
8
)
+
s2
)
*
v1
)
&
0xff00
)
|
(((((
g
*
s1
)
>>
8
)
+
s2
)
*
v1
)
&
0xff00
)
|
(
((((
b
*
s1
)
>>
8
)
+
s2
)
*
v1
)
>>
8
);
(((((
b
*
s1
)
>>
8
)
+
s2
)
*
v1
)
>>
8
);
}
}
/*!
/*!
...
@@ -2482,44 +3296,41 @@ uint32_t Adafruit_NeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
...
@@ -2482,44 +3296,41 @@ uint32_t Adafruit_NeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
This gets more pronounced at lower brightness levels.
This gets more pronounced at lower brightness levels.
*/
*/
uint32_t
Adafruit_NeoPixel
::
getPixelColor
(
uint16_t
n
)
const
{
uint32_t
Adafruit_NeoPixel
::
getPixelColor
(
uint16_t
n
)
const
{
if
(
n
>=
numLEDs
)
return
0
;
// Out of bounds, return no color.
if
(
n
>=
numLEDs
)
return
0
;
// Out of bounds, return no color.
uint8_t
*
p
;
uint8_t
*
p
;
if
(
wOffset
==
rOffset
)
{
// Is RGB-type device
if
(
wOffset
==
rOffset
)
{
// Is RGB-type device
p
=
&
pixels
[
n
*
3
];
p
=
&
pixels
[
n
*
3
];
if
(
brightness
)
{
if
(
brightness
)
{
// Stored color was decimated by setBrightness(). Returned value
// Stored color was decimated by setBrightness(). Returned value
// attempts to scale back to an approximation of the original 24-bit
// attempts to scale back to an approximation of the original 24-bit
// value used when setting the pixel color, but there will always be
// value used when setting the pixel color, but there will always be
// some error -- those bits are simply gone. Issue is most
// some error -- those bits are simply gone. Issue is most
// pronounced at low brightness levels.
// pronounced at low brightness levels.
return
(((
uint32_t
)(
p
[
rOffset
]
<<
8
)
/
brightness
)
<<
16
)
|
return
(((
uint32_t
)(
p
[
rOffset
]
<<
8
)
/
brightness
)
<<
16
)
|
(((
uint32_t
)(
p
[
gOffset
]
<<
8
)
/
brightness
)
<<
8
)
|
(((
uint32_t
)(
p
[
gOffset
]
<<
8
)
/
brightness
)
<<
8
)
|
(
(
uint32_t
)(
p
[
bOffset
]
<<
8
)
/
brightness
);
((
uint32_t
)(
p
[
bOffset
]
<<
8
)
/
brightness
);
}
else
{
}
else
{
// No brightness adjustment has been made -- return 'raw' color
// No brightness adjustment has been made -- return 'raw' color
return
((
uint32_t
)
p
[
rOffset
]
<<
16
)
|
return
((
uint32_t
)
p
[
rOffset
]
<<
16
)
|
((
uint32_t
)
p
[
gOffset
]
<<
8
)
|
((
uint32_t
)
p
[
gOffset
]
<<
8
)
|
(
uint32_t
)
p
[
bOffset
];
(
uint32_t
)
p
[
bOffset
];
}
}
}
else
{
// Is RGBW-type device
}
else
{
// Is RGBW-type device
p
=
&
pixels
[
n
*
4
];
p
=
&
pixels
[
n
*
4
];
if
(
brightness
)
{
// Return scaled color
if
(
brightness
)
{
// Return scaled color
return
(((
uint32_t
)(
p
[
wOffset
]
<<
8
)
/
brightness
)
<<
24
)
|
return
(((
uint32_t
)(
p
[
wOffset
]
<<
8
)
/
brightness
)
<<
24
)
|
(((
uint32_t
)(
p
[
rOffset
]
<<
8
)
/
brightness
)
<<
16
)
|
(((
uint32_t
)(
p
[
rOffset
]
<<
8
)
/
brightness
)
<<
16
)
|
(((
uint32_t
)(
p
[
gOffset
]
<<
8
)
/
brightness
)
<<
8
)
|
(((
uint32_t
)(
p
[
gOffset
]
<<
8
)
/
brightness
)
<<
8
)
|
(
(
uint32_t
)(
p
[
bOffset
]
<<
8
)
/
brightness
);
((
uint32_t
)(
p
[
bOffset
]
<<
8
)
/
brightness
);
}
else
{
// Return raw color
}
else
{
// Return raw color
return
((
uint32_t
)
p
[
wOffset
]
<<
24
)
|
return
((
uint32_t
)
p
[
wOffset
]
<<
24
)
|
((
uint32_t
)
p
[
rOffset
]
<<
16
)
|
((
uint32_t
)
p
[
rOffset
]
<<
16
)
|
((
uint32_t
)
p
[
gOffset
]
<<
8
)
|
(
uint32_t
)
p
[
bOffset
];
((
uint32_t
)
p
[
gOffset
]
<<
8
)
|
(
uint32_t
)
p
[
bOffset
];
}
}
}
}
}
}
/*!
/*!
@brief Adjust output brightness. Does not immediately affect what's
@brief Adjust output brightness. Does not immediately affect what's
currently displayed on the LEDs. The next call to show() will
currently displayed on the LEDs. The next call to show() will
...
@@ -2543,7 +3354,7 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
...
@@ -2543,7 +3354,7 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
// (color values are interpreted literally; no scaling), 1 = min
// (color values are interpreted literally; no scaling), 1 = min
// brightness (off), 255 = just below max brightness.
// brightness (off), 255 = just below max brightness.
uint8_t
newBrightness
=
b
+
1
;
uint8_t
newBrightness
=
b
+
1
;
if
(
newBrightness
!=
brightness
)
{
// Compare against prior value
if
(
newBrightness
!=
brightness
)
{
// Compare against prior value
// Brightness has changed -- re-scale existing data in RAM,
// Brightness has changed -- re-scale existing data in RAM,
// This process is potentially "lossy," especially when increasing
// This process is potentially "lossy," especially when increasing
// brightness. The tight timing in the WS2811/WS2812 code means there
// brightness. The tight timing in the WS2811/WS2812 code means there
...
@@ -2554,15 +3365,17 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
...
@@ -2554,15 +3365,17 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
// the limited number of steps (quantization) in the old data will be
// the limited number of steps (quantization) in the old data will be
// quite visible in the re-scaled version. For a non-destructive
// quite visible in the re-scaled version. For a non-destructive
// change, you'll need to re-render the full strip data. C'est la vie.
// change, you'll need to re-render the full strip data. C'est la vie.
uint8_t
c
,
uint8_t
c
,
*
ptr
=
pixels
,
*
ptr
=
pixels
,
oldBrightness
=
brightness
-
1
;
// De-wrap old brightness value
oldBrightness
=
brightness
-
1
;
// De-wrap old brightness value
uint16_t
scale
;
uint16_t
scale
;
if
(
oldBrightness
==
0
)
scale
=
0
;
// Avoid /0
if
(
oldBrightness
==
0
)
else
if
(
b
==
255
)
scale
=
65535
/
oldBrightness
;
scale
=
0
;
// Avoid /0
else
scale
=
(((
uint16_t
)
newBrightness
<<
8
)
-
1
)
/
oldBrightness
;
else
if
(
b
==
255
)
for
(
uint16_t
i
=
0
;
i
<
numBytes
;
i
++
)
{
scale
=
65535
/
oldBrightness
;
c
=
*
ptr
;
else
scale
=
(((
uint16_t
)
newBrightness
<<
8
)
-
1
)
/
oldBrightness
;
for
(
uint16_t
i
=
0
;
i
<
numBytes
;
i
++
)
{
c
=
*
ptr
;
*
ptr
++
=
(
c
*
scale
)
>>
8
;
*
ptr
++
=
(
c
*
scale
)
>>
8
;
}
}
brightness
=
newBrightness
;
brightness
=
newBrightness
;
...
@@ -2573,16 +3386,12 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
...
@@ -2573,16 +3386,12 @@ void Adafruit_NeoPixel::setBrightness(uint8_t b) {
@brief Retrieve the last-set brightness value for the strip.
@brief Retrieve the last-set brightness value for the strip.
@return Brightness value: 0 = minimum (off), 255 = maximum.
@return Brightness value: 0 = minimum (off), 255 = maximum.
*/
*/
uint8_t
Adafruit_NeoPixel
::
getBrightness
(
void
)
const
{
uint8_t
Adafruit_NeoPixel
::
getBrightness
(
void
)
const
{
return
brightness
-
1
;
}
return
brightness
-
1
;
}
/*!
/*!
@brief Fill the whole NeoPixel strip with 0 / black / off.
@brief Fill the whole NeoPixel strip with 0 / black / off.
*/
*/
void
Adafruit_NeoPixel
::
clear
(
void
)
{
void
Adafruit_NeoPixel
::
clear
(
void
)
{
memset
(
pixels
,
0
,
numBytes
);
}
memset
(
pixels
,
0
,
numBytes
);
}
// A 32-bit variant of gamma8() that applies the same function
// A 32-bit variant of gamma8() that applies the same function
// to all components of a packed RGB or WRGB value.
// to all components of a packed RGB or WRGB value.
...
@@ -2596,6 +3405,35 @@ uint32_t Adafruit_NeoPixel::gamma32(uint32_t x) {
...
@@ -2596,6 +3405,35 @@ uint32_t Adafruit_NeoPixel::gamma32(uint32_t x) {
// someone's storing information in the unused most significant byte
// someone's storing information in the unused most significant byte
// of an RGB value, but this seems exceedingly rare and if it's
// of an RGB value, but this seems exceedingly rare and if it's
// encountered in reality they can mask values going in or coming out.
// encountered in reality they can mask values going in or coming out.
for
(
uint8_t
i
=
0
;
i
<
4
;
i
++
)
y
[
i
]
=
gamma8
(
y
[
i
]);
for
(
uint8_t
i
=
0
;
i
<
4
;
i
++
)
y
[
i
]
=
gamma8
(
y
[
i
]);
return
x
;
// Packed 32-bit return
return
x
;
// Packed 32-bit return
}
}
/*!
@brief Fill NeoPixel strip with one or more cycles of hues.
Everyone loves the rainbow swirl so much, now it's canon!
@param first_hue Hue of first pixel, 0-65535, representing one full
cycle of the color wheel. Each subsequent pixel will
be offset to complete one or more cycles over the
length of the strip.
@param reps Number of cycles of the color wheel over the length
of the strip. Default is 1. Negative values can be
used to reverse the hue order.
@param saturation Saturation (optional), 0-255 = gray to pure hue,
default = 255.
@param brightness Brightness/value (optional), 0-255 = off to max,
default = 255. This is distinct and in combination
with any configured global strip brightness.
@param gammify If true (default), apply gamma correction to colors
for better appearance.
*/
void
Adafruit_NeoPixel
::
rainbow
(
uint16_t
first_hue
,
int8_t
reps
,
uint8_t
saturation
,
uint8_t
brightness
,
bool
gammify
)
{
for
(
uint16_t
i
=
0
;
i
<
numLEDs
;
i
++
)
{
uint16_t
hue
=
first_hue
+
(
i
*
reps
*
65536
)
/
numLEDs
;
uint32_t
color
=
ColorHSV
(
hue
,
saturation
,
brightness
);
if
(
gammify
)
color
=
gamma32
(
color
);
setPixelColor
(
i
,
color
);
}
}
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
+
165
-
121
View file @
a224c1fa
...
@@ -37,16 +37,28 @@
...
@@ -37,16 +37,28 @@
#define ADAFRUIT_NEOPIXEL_H
#define ADAFRUIT_NEOPIXEL_H
#ifdef ARDUINO
#ifdef ARDUINO
#if (ARDUINO >= 100)
#if (ARDUINO >= 100)
#include
<Arduino.h>
#include
<Arduino.h>
#else
#else
#include
<WProgram.h>
#include
<WProgram.h>
#include
<pins_arduino.h>
#include
<pins_arduino.h>
#endif
#endif
#ifdef USE_TINYUSB // For Serial when selecting TinyUSB
#include
<Adafruit_TinyUSB.h>
#endif
#endif
#endif
#ifdef TARGET_LPC1768
#ifdef TARGET_LPC1768
#include
<Arduino.h>
#include
<Arduino.h>
#endif
#if defined(ARDUINO_ARCH_RP2040)
#include
<stdlib.h>
#include
"hardware/pio.h"
#include
"hardware/clocks.h"
#include
"rp2040_pio.h"
#endif
#endif
// The order of primary colors in the NeoPixel data stream can vary among
// The order of primary colors in the NeoPixel data stream can vary among
...
@@ -76,42 +88,42 @@
...
@@ -76,42 +88,42 @@
// RGB NeoPixel permutations; white and red offsets are always same
// RGB NeoPixel permutations; white and red offsets are always same
// Offset: W R G B
// Offset: W R G B
#define NEO_RGB
((0<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B
#define NEO_RGB ((0
<<
6) | (0
<<
4) | (1
<<
2) | (2)) ///< Transmit as R,G,B
#define NEO_RBG
((0<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G
#define NEO_RBG ((0
<<
6) | (0
<<
4) | (2
<<
2) | (1)) ///< Transmit as R,B,G
#define NEO_GRB
((1<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B
#define NEO_GRB ((1
<<
6) | (1
<<
4) | (0
<<
2) | (2)) ///< Transmit as G,R,B
#define NEO_GBR
((2<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R
#define NEO_GBR ((2
<<
6) | (2
<<
4) | (0
<<
2) | (1)) ///< Transmit as G,B,R
#define NEO_BRG
((1<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G
#define NEO_BRG ((1
<<
6) | (1
<<
4) | (2
<<
2) | (0)) ///< Transmit as B,R,G
#define NEO_BGR
((2<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R
#define NEO_BGR ((2
<<
6) | (2
<<
4) | (1
<<
2) | (0)) ///< Transmit as B,G,R
// RGBW NeoPixel permutations; all 4 offsets are distinct
// RGBW NeoPixel permutations; all 4 offsets are distinct
// Offset: W R G B
// Offset: W R G B
#define NEO_WRGB ((0<<6) | (1<<4) | (2<<2) | (3)) ///< Transmit as W,R,G,B
#define NEO_WRGB ((0
<<
6) | (1
<<
4) | (2
<<
2) | (3)) ///< Transmit as W,R,G,B
#define NEO_WRBG ((0<<6) | (1<<4) | (3<<2) | (2)) ///< Transmit as W,R,B,G
#define NEO_WRBG ((0
<<
6) | (1
<<
4) | (3
<<
2) | (2)) ///< Transmit as W,R,B,G
#define NEO_WGRB ((0<<6) | (2<<4) | (1<<2) | (3)) ///< Transmit as W,G,R,B
#define NEO_WGRB ((0
<<
6) | (2
<<
4) | (1
<<
2) | (3)) ///< Transmit as W,G,R,B
#define NEO_WGBR ((0<<6) | (3<<4) | (1<<2) | (2)) ///< Transmit as W,G,B,R
#define NEO_WGBR ((0
<<
6) | (3
<<
4) | (1
<<
2) | (2)) ///< Transmit as W,G,B,R
#define NEO_WBRG ((0<<6) | (2<<4) | (3<<2) | (1)) ///< Transmit as W,B,R,G
#define NEO_WBRG ((0
<<
6) | (2
<<
4) | (3
<<
2) | (1)) ///< Transmit as W,B,R,G
#define NEO_WBGR ((0<<6) | (3<<4) | (2<<2) | (1)) ///< Transmit as W,B,G,R
#define NEO_WBGR ((0
<<
6) | (3
<<
4) | (2
<<
2) | (1)) ///< Transmit as W,B,G,R
#define NEO_RWGB ((1<<6) | (0<<4) | (2<<2) | (3)) ///< Transmit as R,W,G,B
#define NEO_RWGB ((1
<<
6) | (0
<<
4) | (2
<<
2) | (3)) ///< Transmit as R,W,G,B
#define NEO_RWBG ((1<<6) | (0<<4) | (3<<2) | (2)) ///< Transmit as R,W,B,G
#define NEO_RWBG ((1
<<
6) | (0
<<
4) | (3
<<
2) | (2)) ///< Transmit as R,W,B,G
#define NEO_RGWB ((2<<6) | (0<<4) | (1<<2) | (3)) ///< Transmit as R,G,W,B
#define NEO_RGWB ((2
<<
6) | (0
<<
4) | (1
<<
2) | (3)) ///< Transmit as R,G,W,B
#define NEO_RGBW ((3<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B,W
#define NEO_RGBW ((3
<<
6) | (0
<<
4) | (1
<<
2) | (2)) ///< Transmit as R,G,B,W
#define NEO_RBWG ((2<<6) | (0<<4) | (3<<2) | (1)) ///< Transmit as R,B,W,G
#define NEO_RBWG ((2
<<
6) | (0
<<
4) | (3
<<
2) | (1)) ///< Transmit as R,B,W,G
#define NEO_RBGW ((3<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G,W
#define NEO_RBGW ((3
<<
6) | (0
<<
4) | (2
<<
2) | (1)) ///< Transmit as R,B,G,W
#define NEO_GWRB ((1<<6) | (2<<4) | (0<<2) | (3)) ///< Transmit as G,W,R,B
#define NEO_GWRB ((1
<<
6) | (2
<<
4) | (0
<<
2) | (3)) ///< Transmit as G,W,R,B
#define NEO_GWBR ((1<<6) | (3<<4) | (0<<2) | (2)) ///< Transmit as G,W,B,R
#define NEO_GWBR ((1
<<
6) | (3
<<
4) | (0
<<
2) | (2)) ///< Transmit as G,W,B,R
#define NEO_GRWB ((2<<6) | (1<<4) | (0<<2) | (3)) ///< Transmit as G,R,W,B
#define NEO_GRWB ((2
<<
6) | (1
<<
4) | (0
<<
2) | (3)) ///< Transmit as G,R,W,B
#define NEO_GRBW ((3<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B,W
#define NEO_GRBW ((3
<<
6) | (1
<<
4) | (0
<<
2) | (2)) ///< Transmit as G,R,B,W
#define NEO_GBWR ((2<<6) | (3<<4) | (0<<2) | (1)) ///< Transmit as G,B,W,R
#define NEO_GBWR ((2
<<
6) | (3
<<
4) | (0
<<
2) | (1)) ///< Transmit as G,B,W,R
#define NEO_GBRW ((3<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R,W
#define NEO_GBRW ((3
<<
6) | (2
<<
4) | (0
<<
2) | (1)) ///< Transmit as G,B,R,W
#define NEO_BWRG ((1<<6) | (2<<4) | (3<<2) | (0)) ///< Transmit as B,W,R,G
#define NEO_BWRG ((1
<<
6) | (2
<<
4) | (3
<<
2) | (0)) ///< Transmit as B,W,R,G
#define NEO_BWGR ((1<<6) | (3<<4) | (2<<2) | (0)) ///< Transmit as B,W,G,R
#define NEO_BWGR ((1
<<
6) | (3
<<
4) | (2
<<
2) | (0)) ///< Transmit as B,W,G,R
#define NEO_BRWG ((2<<6) | (1<<4) | (3<<2) | (0)) ///< Transmit as B,R,W,G
#define NEO_BRWG ((2
<<
6) | (1
<<
4) | (3
<<
2) | (0)) ///< Transmit as B,R,W,G
#define NEO_BRGW ((3<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G,W
#define NEO_BRGW ((3
<<
6) | (1
<<
4) | (2
<<
2) | (0)) ///< Transmit as B,R,G,W
#define NEO_BGWR ((2<<6) | (3<<4) | (1<<2) | (0)) ///< Transmit as B,G,W,R
#define NEO_BGWR ((2
<<
6) | (3
<<
4) | (1
<<
2) | (0)) ///< Transmit as B,G,W,R
#define NEO_BGRW ((3<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R,W
#define NEO_BGRW ((3
<<
6) | (2
<<
4) | (1
<<
2) | (0)) ///< Transmit as B,G,R,W
// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
...
@@ -134,7 +146,7 @@
...
@@ -134,7 +146,7 @@
#ifdef NEO_KHZ400
#ifdef NEO_KHZ400
typedef
uint16_t
neoPixelType
;
///< 3rd arg to Adafruit_NeoPixel constructor
typedef
uint16_t
neoPixelType
;
///< 3rd arg to Adafruit_NeoPixel constructor
#else
#else
typedef
uint8_t
neoPixelType
;
///< 3rd arg to Adafruit_NeoPixel constructor
typedef
uint8_t
neoPixelType
;
///< 3rd arg to Adafruit_NeoPixel constructor
#endif
#endif
// These two tables are declared outside the Adafruit_NeoPixel class
// These two tables are declared outside the Adafruit_NeoPixel class
...
@@ -149,22 +161,24 @@ for x in range(256):
...
@@ -149,22 +161,24 @@ for x in range(256):
if x&15 == 15: print
if x&15 == 15: print
*/
*/
static
const
uint8_t
PROGMEM
_NeoPixelSineTable
[
256
]
=
{
static
const
uint8_t
PROGMEM
_NeoPixelSineTable
[
256
]
=
{
128
,
131
,
134
,
137
,
140
,
143
,
146
,
149
,
152
,
155
,
158
,
162
,
165
,
167
,
170
,
173
,
128
,
131
,
134
,
137
,
140
,
143
,
146
,
149
,
152
,
155
,
158
,
162
,
165
,
167
,
170
,
176
,
179
,
182
,
185
,
188
,
190
,
193
,
196
,
198
,
201
,
203
,
206
,
208
,
211
,
213
,
215
,
173
,
176
,
179
,
182
,
185
,
188
,
190
,
193
,
196
,
198
,
201
,
203
,
206
,
208
,
211
,
218
,
220
,
222
,
224
,
226
,
228
,
230
,
232
,
234
,
235
,
237
,
238
,
240
,
241
,
243
,
244
,
213
,
215
,
218
,
220
,
222
,
224
,
226
,
228
,
230
,
232
,
234
,
235
,
237
,
238
,
240
,
245
,
246
,
248
,
249
,
250
,
250
,
251
,
252
,
253
,
253
,
254
,
254
,
254
,
255
,
255
,
255
,
241
,
243
,
244
,
245
,
246
,
248
,
249
,
250
,
250
,
251
,
252
,
253
,
253
,
254
,
254
,
255
,
255
,
255
,
255
,
254
,
254
,
254
,
253
,
253
,
252
,
251
,
250
,
250
,
249
,
248
,
246
,
254
,
255
,
255
,
255
,
255
,
255
,
255
,
255
,
254
,
254
,
254
,
253
,
253
,
252
,
251
,
245
,
244
,
243
,
241
,
240
,
238
,
237
,
235
,
234
,
232
,
230
,
228
,
226
,
224
,
222
,
220
,
250
,
250
,
249
,
248
,
246
,
245
,
244
,
243
,
241
,
240
,
238
,
237
,
235
,
234
,
232
,
218
,
215
,
213
,
211
,
208
,
206
,
203
,
201
,
198
,
196
,
193
,
190
,
188
,
185
,
182
,
179
,
230
,
228
,
226
,
224
,
222
,
220
,
218
,
215
,
213
,
211
,
208
,
206
,
203
,
201
,
198
,
176
,
173
,
170
,
167
,
165
,
162
,
158
,
155
,
152
,
149
,
146
,
143
,
140
,
137
,
134
,
131
,
196
,
193
,
190
,
188
,
185
,
182
,
179
,
176
,
173
,
170
,
167
,
165
,
162
,
158
,
155
,
128
,
124
,
121
,
118
,
115
,
112
,
109
,
106
,
103
,
100
,
97
,
93
,
90
,
88
,
85
,
82
,
152
,
149
,
146
,
143
,
140
,
137
,
134
,
131
,
128
,
124
,
121
,
118
,
115
,
112
,
109
,
79
,
76
,
73
,
70
,
67
,
65
,
62
,
59
,
57
,
54
,
52
,
49
,
47
,
44
,
42
,
40
,
106
,
103
,
100
,
97
,
93
,
90
,
88
,
85
,
82
,
79
,
76
,
73
,
70
,
67
,
65
,
37
,
35
,
33
,
31
,
29
,
27
,
25
,
23
,
21
,
20
,
18
,
17
,
15
,
14
,
12
,
11
,
62
,
59
,
57
,
54
,
52
,
49
,
47
,
44
,
42
,
40
,
37
,
35
,
33
,
31
,
29
,
10
,
9
,
7
,
6
,
5
,
5
,
4
,
3
,
2
,
2
,
1
,
1
,
1
,
0
,
0
,
0
,
27
,
25
,
23
,
21
,
20
,
18
,
17
,
15
,
14
,
12
,
11
,
10
,
9
,
7
,
6
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
2
,
2
,
3
,
4
,
5
,
5
,
6
,
7
,
9
,
5
,
5
,
4
,
3
,
2
,
2
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
10
,
11
,
12
,
14
,
15
,
17
,
18
,
20
,
21
,
23
,
25
,
27
,
29
,
31
,
33
,
35
,
0
,
1
,
1
,
1
,
2
,
2
,
3
,
4
,
5
,
5
,
6
,
7
,
9
,
10
,
11
,
37
,
40
,
42
,
44
,
47
,
49
,
52
,
54
,
57
,
59
,
62
,
65
,
67
,
70
,
73
,
76
,
12
,
14
,
15
,
17
,
18
,
20
,
21
,
23
,
25
,
27
,
29
,
31
,
33
,
35
,
37
,
79
,
82
,
85
,
88
,
90
,
93
,
97
,
100
,
103
,
106
,
109
,
112
,
115
,
118
,
121
,
124
};
40
,
42
,
44
,
47
,
49
,
52
,
54
,
57
,
59
,
62
,
65
,
67
,
70
,
73
,
76
,
79
,
82
,
85
,
88
,
90
,
93
,
97
,
100
,
103
,
106
,
109
,
112
,
115
,
118
,
121
,
124
};
/* Similar to above, but for an 8-bit gamma-correction table.
/* Similar to above, but for an 8-bit gamma-correction table.
Copy & paste this snippet into a Python REPL to regenerate:
Copy & paste this snippet into a Python REPL to regenerate:
...
@@ -175,49 +189,49 @@ for x in range(256):
...
@@ -175,49 +189,49 @@ for x in range(256):
if x&15 == 15: print
if x&15 == 15: print
*/
*/
static
const
uint8_t
PROGMEM
_NeoPixelGammaTable
[
256
]
=
{
static
const
uint8_t
PROGMEM
_NeoPixelGammaTable
[
256
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
3
,
3
,
3
,
3
,
1
,
1
,
1
,
1
,
1
,
1
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
5
,
5
,
5
,
5
,
5
,
6
,
6
,
6
,
6
,
7
,
3
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
5
,
5
,
5
,
5
,
5
,
6
,
7
,
7
,
8
,
8
,
8
,
9
,
9
,
9
,
10
,
10
,
10
,
11
,
11
,
11
,
12
,
12
,
6
,
6
,
6
,
7
,
7
,
7
,
8
,
8
,
8
,
9
,
9
,
9
,
10
,
10
,
10
,
13
,
13
,
13
,
14
,
14
,
15
,
15
,
16
,
16
,
17
,
17
,
18
,
18
,
19
,
19
,
20
,
11
,
11
,
11
,
12
,
12
,
13
,
13
,
13
,
14
,
14
,
15
,
15
,
16
,
16
,
17
,
20
,
21
,
21
,
22
,
22
,
23
,
24
,
24
,
25
,
25
,
26
,
27
,
27
,
28
,
29
,
29
,
17
,
18
,
18
,
19
,
19
,
20
,
20
,
21
,
21
,
22
,
22
,
23
,
24
,
24
,
25
,
30
,
31
,
31
,
32
,
33
,
34
,
34
,
35
,
36
,
37
,
38
,
38
,
39
,
40
,
41
,
42
,
25
,
26
,
27
,
27
,
28
,
29
,
29
,
30
,
31
,
31
,
32
,
33
,
34
,
34
,
35
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
52
,
53
,
54
,
55
,
56
,
57
,
36
,
37
,
38
,
38
,
39
,
40
,
41
,
42
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
58
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
68
,
69
,
70
,
71
,
72
,
73
,
75
,
49
,
50
,
51
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
62
,
63
,
76
,
77
,
78
,
80
,
81
,
82
,
84
,
85
,
86
,
88
,
89
,
90
,
92
,
93
,
94
,
96
,
64
,
65
,
66
,
68
,
69
,
70
,
71
,
72
,
73
,
75
,
76
,
77
,
78
,
80
,
81
,
97
,
99
,
100
,
102
,
103
,
105
,
106
,
108
,
109
,
111
,
112
,
114
,
115
,
117
,
119
,
120
,
82
,
84
,
85
,
86
,
88
,
89
,
90
,
92
,
93
,
94
,
96
,
97
,
99
,
100
,
102
,
122
,
124
,
125
,
127
,
129
,
130
,
132
,
134
,
136
,
137
,
139
,
141
,
143
,
145
,
146
,
148
,
103
,
105
,
106
,
108
,
109
,
111
,
112
,
114
,
115
,
117
,
119
,
120
,
122
,
124
,
125
,
150
,
152
,
154
,
156
,
158
,
160
,
162
,
164
,
166
,
168
,
170
,
172
,
174
,
176
,
178
,
180
,
127
,
129
,
130
,
132
,
134
,
136
,
137
,
139
,
141
,
143
,
145
,
146
,
148
,
150
,
152
,
182
,
184
,
186
,
188
,
191
,
193
,
195
,
197
,
199
,
202
,
204
,
206
,
209
,
211
,
213
,
215
,
154
,
156
,
158
,
160
,
162
,
164
,
166
,
168
,
170
,
172
,
174
,
176
,
178
,
180
,
182
,
218
,
220
,
223
,
225
,
227
,
230
,
232
,
235
,
237
,
240
,
242
,
245
,
247
,
250
,
252
,
255
};
184
,
186
,
188
,
191
,
193
,
195
,
197
,
199
,
202
,
204
,
206
,
209
,
211
,
213
,
215
,
218
,
220
,
223
,
225
,
227
,
230
,
232
,
235
,
237
,
240
,
242
,
245
,
247
,
250
,
252
,
255
};
/*!
/*!
@brief Class that stores state and functions for interacting with
@brief Class that stores state and functions for interacting with
Adafruit NeoPixels and compatible devices.
Adafruit NeoPixels and compatible devices.
*/
*/
class
Adafruit_NeoPixel
{
class
Adafruit_NeoPixel
{
public:
public:
// Constructor: number of LEDs, pin number, LED type
// Constructor: number of LEDs, pin number, LED type
Adafruit_NeoPixel
(
uint16_t
n
,
u
int16_t
pin
=
6
,
Adafruit_NeoPixel
(
uint16_t
n
,
int16_t
pin
=
6
,
neoPixelType
type
=
NEO_GRB
+
NEO_KHZ800
);
neoPixelType
type
=
NEO_GRB
+
NEO_KHZ800
);
Adafruit_NeoPixel
(
void
);
Adafruit_NeoPixel
(
void
);
~
Adafruit_NeoPixel
();
~
Adafruit_NeoPixel
();
void
begin
(
void
);
void
begin
(
void
);
void
show
(
void
);
void
show
(
void
);
void
setPin
(
uint16_t
p
);
void
setPin
(
int16_t
p
);
void
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
);
void
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
);
void
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
,
void
setPixelColor
(
uint16_t
n
,
uint8_t
r
,
uint8_t
g
,
uint8_t
b
,
uint8_t
w
);
uint8_t
w
);
void
setPixelColor
(
uint16_t
n
,
uint32_t
c
);
void
setPixelColor
(
uint16_t
n
,
uint32_t
c
);
void
fill
(
uint32_t
c
=
0
,
uint16_t
first
=
0
,
uint16_t
count
=
0
);
void
fill
(
uint32_t
c
=
0
,
uint16_t
first
=
0
,
uint16_t
count
=
0
);
void
setBrightness
(
uint8_t
);
void
setBrightness
(
uint8_t
);
void
clear
(
void
);
void
clear
(
void
);
void
updateLength
(
uint16_t
n
);
void
updateLength
(
uint16_t
n
);
void
updateType
(
neoPixelType
t
);
void
updateType
(
neoPixelType
t
);
/*!
/*!
@brief Check whether a call to show() will start sending data
@brief Check whether a call to show() will start sending data
immediately or will 'block' for a required interval. NeoPixels
immediately or will 'block' for a required interval. NeoPixels
...
@@ -232,10 +246,26 @@ class Adafruit_NeoPixel {
...
@@ -232,10 +246,26 @@ class Adafruit_NeoPixel {
if show() would block (meaning some idle time is available).
if show() would block (meaning some idle time is available).
*/
*/
bool
canShow
(
void
)
{
bool
canShow
(
void
)
{
if
(
endTime
>
micros
())
{
// It's normal and possible for endTime to exceed micros() if the
endTime
=
micros
();
// 32-bit clock counter has rolled over (about every 70 minutes).
// Since both are uint32_t, a negative delta correctly maps back to
// positive space, and it would seem like the subtraction below would
// suffice. But a problem arises if code invokes show() very
// infrequently...the micros() counter may roll over MULTIPLE times in
// that interval, the delta calculation is no longer correct and the
// next update may stall for a very long time. The check below resets
// the latch counter if a rollover has occurred. This can cause an
// extra delay of up to 300 microseconds in the rare case where a
// show() call happens precisely around the rollover, but that's
// neither likely nor especially harmful, vs. other code that might
// stall for 30+ minutes, or having to document and frequently remind
// and/or provide tech support explaining an unintuitive need for
// show() calls at least once an hour.
uint32_t
now
=
micros
();
if
(
endTime
>
now
)
{
endTime
=
now
;
}
}
return
(
micros
()
-
endTime
)
>=
300L
;
return
(
now
-
endTime
)
>=
300L
;
}
}
/*!
/*!
@brief Get a pointer directly to the NeoPixel data buffer in RAM.
@brief Get a pointer directly to the NeoPixel data buffer in RAM.
...
@@ -251,19 +281,19 @@ class Adafruit_NeoPixel {
...
@@ -251,19 +281,19 @@ class Adafruit_NeoPixel {
writes past the ends of the buffer. Great power, great
writes past the ends of the buffer. Great power, great
responsibility and all that.
responsibility and all that.
*/
*/
uint8_t
*
getPixels
(
void
)
const
{
return
pixels
;
};
uint8_t
*
getPixels
(
void
)
const
{
return
pixels
;
};
uint8_t
getBrightness
(
void
)
const
;
uint8_t
getBrightness
(
void
)
const
;
/*!
/*!
@brief Retrieve the pin number used for NeoPixel data output.
@brief Retrieve the pin number used for NeoPixel data output.
@return Arduino pin number (-1 if not set).
@return Arduino pin number (-1 if not set).
*/
*/
int16_t
getPin
(
void
)
const
{
return
pin
;
};
int16_t
getPin
(
void
)
const
{
return
pin
;
};
/*!
/*!
@brief Return the number of pixels in an Adafruit_NeoPixel strip object.
@brief Return the number of pixels in an Adafruit_NeoPixel strip object.
@return Pixel count (0 if not set).
@return Pixel count (0 if not set).
*/
*/
uint16_t
numPixels
(
void
)
const
{
return
numLEDs
;
}
uint16_t
numPixels
(
void
)
const
{
return
numLEDs
;
}
uint32_t
getPixelColor
(
uint16_t
n
)
const
;
uint32_t
getPixelColor
(
uint16_t
n
)
const
;
/*!
/*!
@brief An 8-bit integer sine wave function, not directly compatible
@brief An 8-bit integer sine wave function, not directly compatible
with standard trigonometric units like radians or degrees.
with standard trigonometric units like radians or degrees.
...
@@ -276,7 +306,7 @@ class Adafruit_NeoPixel {
...
@@ -276,7 +306,7 @@ class Adafruit_NeoPixel {
a signed int8_t, but you'll most likely want unsigned as this
a signed int8_t, but you'll most likely want unsigned as this
output is often used for pixel brightness in animation effects.
output is often used for pixel brightness in animation effects.
*/
*/
static
uint8_t
sine8
(
uint8_t
x
)
{
static
uint8_t
sine8
(
uint8_t
x
)
{
return
pgm_read_byte
(
&
_NeoPixelSineTable
[
x
]);
// 0-255 in, 0-255 out
return
pgm_read_byte
(
&
_NeoPixelSineTable
[
x
]);
// 0-255 in, 0-255 out
}
}
/*!
/*!
...
@@ -290,7 +320,7 @@ class Adafruit_NeoPixel {
...
@@ -290,7 +320,7 @@ class Adafruit_NeoPixel {
NeoPixels in average tasks. If you need finer control you'll
NeoPixels in average tasks. If you need finer control you'll
need to provide your own gamma-correction function instead.
need to provide your own gamma-correction function instead.
*/
*/
static
uint8_t
gamma8
(
uint8_t
x
)
{
static
uint8_t
gamma8
(
uint8_t
x
)
{
return
pgm_read_byte
(
&
_NeoPixelGammaTable
[
x
]);
// 0-255 in, 0-255 out
return
pgm_read_byte
(
&
_NeoPixelGammaTable
[
x
]);
// 0-255 in, 0-255 out
}
}
/*!
/*!
...
@@ -304,8 +334,8 @@ class Adafruit_NeoPixel {
...
@@ -304,8 +334,8 @@ class Adafruit_NeoPixel {
function. Packed RGB format is predictable, regardless of
function. Packed RGB format is predictable, regardless of
LED strand color order.
LED strand color order.
*/
*/
static
uint32_t
Color
(
uint8_t
r
,
uint8_t
g
,
uint8_t
b
)
{
static
uint32_t
Color
(
uint8_t
r
,
uint8_t
g
,
uint8_t
b
)
{
return
((
uint32_t
)
r
<<
16
)
|
((
uint32_t
)
g
<<
8
)
|
b
;
return
((
uint32_t
)
r
<<
16
)
|
((
uint32_t
)
g
<<
8
)
|
b
;
}
}
/*!
/*!
@brief Convert separate red, green, blue and white values into a
@brief Convert separate red, green, blue and white values into a
...
@@ -319,10 +349,10 @@ class Adafruit_NeoPixel {
...
@@ -319,10 +349,10 @@ class Adafruit_NeoPixel {
function. Packed WRGB format is predictable, regardless of
function. Packed WRGB format is predictable, regardless of
LED strand color order.
LED strand color order.
*/
*/
static
uint32_t
Color
(
uint8_t
r
,
uint8_t
g
,
uint8_t
b
,
uint8_t
w
)
{
static
uint32_t
Color
(
uint8_t
r
,
uint8_t
g
,
uint8_t
b
,
uint8_t
w
)
{
return
((
uint32_t
)
w
<<
24
)
|
((
uint32_t
)
r
<<
16
)
|
((
uint32_t
)
g
<<
8
)
|
b
;
return
((
uint32_t
)
w
<<
24
)
|
((
uint32_t
)
r
<<
16
)
|
((
uint32_t
)
g
<<
8
)
|
b
;
}
}
static
uint32_t
ColorHSV
(
uint16_t
hue
,
uint8_t
sat
=
255
,
uint8_t
val
=
255
);
static
uint32_t
ColorHSV
(
uint16_t
hue
,
uint8_t
sat
=
255
,
uint8_t
val
=
255
);
/*!
/*!
@brief A gamma-correction function for 32-bit packed RGB or WRGB
@brief A gamma-correction function for 32-bit packed RGB or WRGB
colors. Makes color transitions appear more perceptially
colors. Makes color transitions appear more perceptially
...
@@ -335,31 +365,45 @@ class Adafruit_NeoPixel {
...
@@ -335,31 +365,45 @@ class Adafruit_NeoPixel {
control you'll need to provide your own gamma-correction
control you'll need to provide your own gamma-correction
function instead.
function instead.
*/
*/
static
uint32_t
gamma32
(
uint32_t
x
);
static
uint32_t
gamma32
(
uint32_t
x
);
protected:
void
rainbow
(
uint16_t
first_hue
=
0
,
int8_t
reps
=
1
,
uint8_t
saturation
=
255
,
uint8_t
brightness
=
255
,
bool
gammify
=
true
);
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
private:
bool
is800KHz
;
///< true if 800 KHz pixels
#if defined(ARDUINO_ARCH_RP2040)
void
rp2040Init
(
uint8_t
pin
,
bool
is800KHz
);
void
rp2040Show
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
bool
is800KHz
);
#endif
#endif
bool
begun
;
///< true if begin() previously called
uint16_t
numLEDs
;
///< Number of RGB LEDs in strip
protected:
uint16_t
numBytes
;
///< Size of 'pixels' buffer below
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
int16_t
pin
;
///< Output pin number (-1 if not yet set)
bool
is800KHz
;
///< true if 800 KHz pixels
uint8_t
brightness
;
///< Strip brightness 0-255 (stored as +1)
#endif
uint8_t
*
pixels
;
///< Holds LED color values (3 or 4 bytes each)
bool
begun
;
///< true if begin() previously called
uint8_t
rOffset
;
///< Red index within each 3- or 4-byte pixel
uint16_t
numLEDs
;
///< Number of RGB LEDs in strip
uint8_t
gOffset
;
///< Index of green byte
uint16_t
numBytes
;
///< Size of 'pixels' buffer below
uint8_t
bOffset
;
///< Index of blue byte
int16_t
pin
;
///< Output pin number (-1 if not yet set)
uint8_t
wOffset
;
///< Index of white (==rOffset if no white)
uint8_t
brightness
;
///< Strip brightness 0-255 (stored as +1)
uint32_t
endTime
;
///< Latch timing reference
uint8_t
*
pixels
;
///< Holds LED color values (3 or 4 bytes each)
uint8_t
rOffset
;
///< Red index within each 3- or 4-byte pixel
uint8_t
gOffset
;
///< Index of green byte
uint8_t
bOffset
;
///< Index of blue byte
uint8_t
wOffset
;
///< Index of white (==rOffset if no white)
uint32_t
endTime
;
///< Latch timing reference
#ifdef __AVR__
#ifdef __AVR__
volatile
uint8_t
*
port
;
///< Output PORT register
volatile
uint8_t
*
port
;
///< Output PORT register
uint8_t
pinMask
;
///< Output PORT bitmask
uint8_t
pinMask
;
///< Output PORT bitmask
#endif
#endif
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
GPIO_TypeDef
*
gpioPort
;
///< Output GPIO PORT
GPIO_TypeDef
*
gpioPort
;
///< Output GPIO PORT
uint32_t
gpioPin
;
///< Output GPIO PIN
uint32_t
gpioPin
;
///< Output GPIO PIN
#endif
#if defined(ARDUINO_ARCH_RP2040)
PIO
pio
=
pio0
;
int
sm
=
0
;
bool
init
=
true
;
#endif
#endif
};
};
...
...
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/README.md
+
4
-
0
View file @
a224c1fa
...
@@ -56,6 +56,10 @@ Compatibility notes: Port A is not supported on any AVR processors at this time
...
@@ -56,6 +56,10 @@ Compatibility notes: Port A is not supported on any AVR processors at this time
-
ESP8266 any speed
-
ESP8266 any speed
-
ESP32 any speed
-
ESP32 any speed
-
Nordic nRF52 (Adafruit Feather nRF52), nRF51 (micro:bit)
-
Nordic nRF52 (Adafruit Feather nRF52), nRF51 (micro:bit)
-
Infineon XMC1100 BootKit @ 32 MHz
-
Infineon XMC1100 2Go @ 32 MHz
-
Infineon XMC1300 BootKit @ 32 MHz
-
Infineon XMC4700 RelaxKit, XMC4800 RelaxKit, XMC4800 IoT Amazon FreeRTOS Kit @ 144 MHz
Check forks for other architectures not listed here!
Check forks for other architectures not listed here!
...
...
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/esp.c
+
16
-
0
View file @
a224c1fa
...
@@ -22,6 +22,12 @@
...
@@ -22,6 +22,12 @@
#include
<Arduino.h>
#include
<Arduino.h>
#include
"driver/rmt.h"
#include
"driver/rmt.h"
#if defined(ESP_IDF_VERSION)
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
#define HAS_ESP_IDF_4
#endif
#endif
// This code is adapted from the ESP-IDF v3.4 RMT "led_strip" example, altered
// This code is adapted from the ESP-IDF v3.4 RMT "led_strip" example, altered
// to work with the Arduino version of the ESP-IDF (3.2)
// to work with the Arduino version of the ESP-IDF (3.2)
...
@@ -89,6 +95,7 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
...
@@ -89,6 +95,7 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
if
(
!
rmt_reserved_channels
[
i
])
{
if
(
!
rmt_reserved_channels
[
i
])
{
rmt_reserved_channels
[
i
]
=
true
;
rmt_reserved_channels
[
i
]
=
true
;
channel
=
i
;
channel
=
i
;
break
;
}
}
}
}
if
(
channel
==
ADAFRUIT_RMT_CHANNEL_MAX
)
{
if
(
channel
==
ADAFRUIT_RMT_CHANNEL_MAX
)
{
...
@@ -96,6 +103,10 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
...
@@ -96,6 +103,10 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
return
;
return
;
}
}
#if defined(HAS_ESP_IDF_4)
rmt_config_t
config
=
RMT_DEFAULT_CONFIG_TX
(
pin
,
channel
);
config
.
clk_div
=
2
;
#else
// Match default TX config from ESP-IDF version 3.4
// Match default TX config from ESP-IDF version 3.4
rmt_config_t
config
=
{
rmt_config_t
config
=
{
.
rmt_mode
=
RMT_MODE_TX
,
.
rmt_mode
=
RMT_MODE_TX
,
...
@@ -113,12 +124,16 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
...
@@ -113,12 +124,16 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
.
idle_output_en
=
true
,
.
idle_output_en
=
true
,
}
}
};
};
#endif
rmt_config
(
&
config
);
rmt_config
(
&
config
);
rmt_driver_install
(
config
.
channel
,
0
,
0
);
rmt_driver_install
(
config
.
channel
,
0
,
0
);
// Convert NS timings to ticks
// Convert NS timings to ticks
uint32_t
counter_clk_hz
=
0
;
uint32_t
counter_clk_hz
=
0
;
#if defined(HAS_ESP_IDF_4)
rmt_get_counter_clock
(
channel
,
&
counter_clk_hz
);
#else
// this emulates the rmt_get_counter_clock() function from ESP-IDF 3.4
// this emulates the rmt_get_counter_clock() function from ESP-IDF 3.4
if
(
RMT_LL_HW_BASE
->
conf_ch
[
config
.
channel
].
conf1
.
ref_always_on
==
RMT_BASECLK_REF
)
{
if
(
RMT_LL_HW_BASE
->
conf_ch
[
config
.
channel
].
conf1
.
ref_always_on
==
RMT_BASECLK_REF
)
{
uint32_t
div_cnt
=
RMT_LL_HW_BASE
->
conf_ch
[
config
.
channel
].
conf0
.
div_cnt
;
uint32_t
div_cnt
=
RMT_LL_HW_BASE
->
conf_ch
[
config
.
channel
].
conf0
.
div_cnt
;
...
@@ -129,6 +144,7 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
...
@@ -129,6 +144,7 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
uint32_t
div
=
div_cnt
==
0
?
256
:
div_cnt
;
uint32_t
div
=
div_cnt
==
0
?
256
:
div_cnt
;
counter_clk_hz
=
APB_CLK_FREQ
/
(
div
);
counter_clk_hz
=
APB_CLK_FREQ
/
(
div
);
}
}
#endif
// NS to tick converter
// NS to tick converter
float
ratio
=
(
float
)
counter_clk_hz
/
1e9
;
float
ratio
=
(
float
)
counter_clk_hz
/
1e9
;
...
...
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/esp8266.c
+
5
-
5
View file @
a224c1fa
...
@@ -17,16 +17,16 @@ static inline uint32_t _getCycleCount(void) {
...
@@ -17,16 +17,16 @@ static inline uint32_t _getCycleCount(void) {
}
}
#ifdef ESP8266
#ifdef ESP8266
void
ICACHE_
RAM_ATTR
espShow
(
I
RAM_ATTR
void
espShow
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
boolean
is800KHz
)
{
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
__attribute__
((
unused
))
boolean
is800KHz
)
{
#else
#else
void
espShow
(
void
espShow
(
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
boolean
is800KHz
)
{
uint8_t
pin
,
uint8_t
*
pixels
,
uint32_t
numBytes
,
boolean
is800KHz
)
{
#endif
#endif
#define CYCLES_800_T0H (F_CPU / 250000
0
) // 0.4us
#define CYCLES_800_T0H (F_CPU / 250000
1
) // 0.4us
#define CYCLES_800_T1H (F_CPU / 125000
0
) // 0.8us
#define CYCLES_800_T1H (F_CPU / 125000
1
) // 0.8us
#define CYCLES_800 (F_CPU / 80000
0
) // 1.25us per bit
#define CYCLES_800 (F_CPU / 80000
1
) // 1.25us per bit
#define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
#define CYCLES_400_T0H (F_CPU / 2000000) // 0.5uS
#define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
#define CYCLES_400_T1H (F_CPU / 833333) // 1.2us
#define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
#define CYCLES_400 (F_CPU / 400000) // 2.5us per bit
...
...
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/library.properties
+
1
-
1
View file @
a224c1fa
name
=
Adafruit NeoPixel
name
=
Adafruit NeoPixel
version
=
1.
7.0
version
=
1.
10.3
author
=
Adafruit
author
=
Adafruit
maintainer
=
Adafruit <info@adafruit.com>
maintainer
=
Adafruit <info@adafruit.com>
sentence
=
Arduino library for controlling single-wire-based LED pixels and strip.
sentence
=
Arduino library for controlling single-wire-based LED pixels and strip.
...
...
This diff is collapsed.
Click to expand it.
ampel-firmware/src/lib/Adafruit_NeoPixel/rp2040_pio.h
0 → 100644
+
63
-
0
View file @
a224c1fa
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
// Unless you know what you are doing...
// Lines 47 and 52 have been edited to set transmit bit count
#if !PICO_NO_HARDWARE
#include
"hardware/pio.h"
#endif
// ------ //
// ws2812 //
// ------ //
#define ws2812_wrap_target 0
#define ws2812_wrap 3
#define ws2812_T1 2
#define ws2812_T2 5
#define ws2812_T3 3
static
const
uint16_t
ws2812_program_instructions
[]
=
{
// .wrap_target
0x6221
,
// 0: out x, 1 side 0 [2]
0x1123
,
// 1: jmp !x, 3 side 1 [1]
0x1400
,
// 2: jmp 0 side 1 [4]
0xa442
,
// 3: nop side 0 [4]
// .wrap
};
#if !PICO_NO_HARDWARE
static
const
struct
pio_program
ws2812_program
=
{
.
instructions
=
ws2812_program_instructions
,
.
length
=
4
,
.
origin
=
-
1
,
};
static
inline
pio_sm_config
ws2812_program_get_default_config
(
uint
offset
)
{
pio_sm_config
c
=
pio_get_default_sm_config
();
sm_config_set_wrap
(
&
c
,
offset
+
ws2812_wrap_target
,
offset
+
ws2812_wrap
);
sm_config_set_sideset
(
&
c
,
1
,
false
,
false
);
return
c
;
}
#include
"hardware/clocks.h"
static
inline
void
ws2812_program_init
(
PIO
pio
,
uint
sm
,
uint
offset
,
uint
pin
,
float
freq
,
uint
bits
)
{
pio_gpio_init
(
pio
,
pin
);
pio_sm_set_consecutive_pindirs
(
pio
,
sm
,
pin
,
1
,
true
);
pio_sm_config
c
=
ws2812_program_get_default_config
(
offset
);
sm_config_set_sideset_pins
(
&
c
,
pin
);
sm_config_set_out_shift
(
&
c
,
false
,
true
,
bits
);
// <----<<< Length changed to "bits"
sm_config_set_fifo_join
(
&
c
,
PIO_FIFO_JOIN_TX
);
int
cycles_per_bit
=
ws2812_T1
+
ws2812_T2
+
ws2812_T3
;
float
div
=
clock_get_hz
(
clk_sys
)
/
(
freq
*
cycles_per_bit
);
sm_config_set_clkdiv
(
&
c
,
div
);
pio_sm_init
(
pio
,
sm
,
offset
,
&
c
);
pio_sm_set_enabled
(
pio
,
sm
,
true
);
}
#endif
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment