Skip to content

Commit 903703b

Browse files
committed
clean up and hand-add some of #381
1 parent ef5ce25 commit 903703b

File tree

3 files changed

+116
-60
lines changed

3 files changed

+116
-60
lines changed

Adafruit_NeoPixel.cpp

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,7 @@ Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, int16_t p, neoPixelType t)
8686
updateType(t);
8787
updateLength(n);
8888
setPin(p);
89-
#if defined(ARDUINO_ARCH_RP2040)
90-
// Find a free SM on one of the PIO's
91-
sm = pio_claim_unused_sm(pio, false); // don't panic
92-
// Try pio1 if SM not found
93-
if (sm < 0) {
94-
pio = pio1;
95-
sm = pio_claim_unused_sm(pio, true); // panic if no SM is free
96-
}
97-
init = true;
98-
#endif
89+
9990
#if defined(ESP32)
10091
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
10192
espInit();
@@ -133,6 +124,13 @@ Adafruit_NeoPixel::~Adafruit_NeoPixel() {
133124
numLEDs = numBytes = 0;
134125
show();
135126
#endif
127+
128+
129+
#if defined(ARDUINO_ARCH_RP2040)
130+
// Release any PIO
131+
rp2040releasePIO();
132+
#endif
133+
136134
free(pixels);
137135
if (pin >= 0)
138136
pinMode(pin, INPUT);
@@ -141,12 +139,27 @@ Adafruit_NeoPixel::~Adafruit_NeoPixel() {
141139
/*!
142140
@brief Configure NeoPixel pin for output.
143141
*/
144-
void Adafruit_NeoPixel::begin(void) {
142+
bool Adafruit_NeoPixel::begin(void) {
145143
if (pin >= 0) {
146144
pinMode(pin, OUTPUT);
147145
digitalWrite(pin, LOW);
146+
} else {
147+
begun = false;
148+
return false;
148149
}
150+
151+
#if defined(ARDUINO_ARCH_RP2040)
152+
// if we're calling begin() again, unclaim any existing PIO resc.
153+
rp2040releasePIO();
154+
if (! rp2040claimPIO()) {
155+
begun = false;
156+
return false;
157+
}
158+
159+
#endif
160+
149161
begun = true;
162+
return true;
150163
}
151164

152165
/*!
@@ -209,38 +222,8 @@ void Adafruit_NeoPixel::updateType(neoPixelType t) {
209222
}
210223
}
211224

212-
// RP2040 specific driver
213-
#if defined(ARDUINO_ARCH_RP2040)
214-
void Adafruit_NeoPixel::rp2040Init(uint8_t pin, bool is800KHz)
215-
{
216-
uint offset = pio_add_program(pio, &ws2812_program);
217225

218-
if (is800KHz)
219-
{
220-
// 800kHz, 8 bit transfers
221-
ws2812_program_init(pio, sm, offset, pin, 800000, 8);
222-
}
223-
else
224-
{
225-
// 400kHz, 8 bit transfers
226-
ws2812_program_init(pio, sm, offset, pin, 400000, 8);
227-
}
228-
}
229-
// Not a user API
230-
void Adafruit_NeoPixel::rp2040Show(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz)
231-
{
232-
if (this->init)
233-
{
234-
// On first pass through initialise the PIO
235-
rp2040Init(pin, is800KHz);
236-
this->init = false;
237-
}
238-
239-
while(numBytes--)
240-
// Bits for transmission must be shifted to top 8 bits
241-
pio_sm_put_blocking(pio, sm, ((uint32_t)*pixels++)<< 24);
242-
}
243-
#elif defined(ARDUINO_ARCH_CH32)
226+
#if defined(ARDUINO_ARCH_CH32)
244227

245228
// F_CPU is defined to SystemCoreClock (not constant number)
246229
#if SYSCLK_FREQ_144MHz_HSE == 144000000 || SYSCLK_FREQ_HSE == 144000000 || \
@@ -1908,7 +1891,7 @@ void Adafruit_NeoPixel::show(void) {
19081891

19091892
#elif defined(ARDUINO_ARCH_RP2040)
19101893
// Use PIO
1911-
rp2040Show(pin, pixels, numBytes, is800KHz);
1894+
rp2040Show(pixels, numBytes);
19121895

19131896
#elif defined(TEENSYDUINO) && \
19141897
defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
@@ -3382,8 +3365,7 @@ if(is800KHz) {
33823365
#elif defined(ARDUINO_ARCH_CH32)
33833366
ch32Show(gpioPort, gpioPin, pixels, numBytes, is800KHz);
33843367
#elif defined(ARDUINO_ARCH_RP2040) && defined(__riscv)
3385-
// Use PIO
3386-
rp2040Show(pin, pixels, numBytes, is800KHz);
3368+
rp2040Show(pixels, numBytes); // Use PIO
33873369
#else
33883370
#error Architecture not supported
33893371
#endif

Adafruit_NeoPixel.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@
3737
#define ADAFRUIT_NEOPIXEL_H
3838

3939
#ifdef ARDUINO
40-
#if (ARDUINO >= 100)
4140
#include <Arduino.h>
42-
#else
43-
#include <WProgram.h>
44-
#include <pins_arduino.h>
45-
#endif
4641

4742
#ifdef USE_TINYUSB // For Serial when selecting TinyUSB
4843
#include <Adafruit_TinyUSB.h>
@@ -235,7 +230,7 @@ class Adafruit_NeoPixel {
235230
Adafruit_NeoPixel(void);
236231
~Adafruit_NeoPixel();
237232

238-
void begin(void);
233+
bool begin(void);
239234
void show(void);
240235
void setPin(int16_t p);
241236
void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
@@ -389,15 +384,20 @@ class Adafruit_NeoPixel {
389384

390385
private:
391386
#if defined(ARDUINO_ARCH_RP2040)
392-
void rp2040Init(uint8_t pin, bool is800KHz);
393-
void rp2040Show(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz);
387+
bool rp2040claimPIO(void);
388+
void rp2040releasePIO(void);
389+
void rp2040Show(uint8_t *pixels, uint32_t numBytes);
390+
PIO pio = NULL;
391+
int8_t pio_sm = -1;
392+
uint32_t pio_program_offset = 0;
394393
#endif
395394

396395
protected:
397396
#ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled...
398397
bool is800KHz; ///< true if 800 KHz pixels
399398
#endif
400-
bool begun; ///< true if begin() previously called
399+
400+
bool begun; ///< true if begin() previously called successfully
401401
uint16_t numLEDs; ///< Number of RGB LEDs in strip
402402
uint16_t numBytes; ///< Size of 'pixels' buffer below
403403
int16_t pin; ///< Output pin number (-1 if not yet set)
@@ -408,22 +408,24 @@ class Adafruit_NeoPixel {
408408
uint8_t bOffset; ///< Index of blue byte
409409
uint8_t wOffset; ///< Index of white (==rOffset if no white)
410410
uint32_t endTime; ///< Latch timing reference
411+
411412
#ifdef __AVR__
412413
volatile uint8_t *port; ///< Output PORT register
413414
uint8_t pinMask; ///< Output PORT bitmask
414415
#endif
415-
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_CH32) || defined(_PY32_DEF_)
416+
417+
#if defined(ARDUINO_ARCH_STM32) || \
418+
defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || \
419+
defined(ARDUINO_ARCH_CH32) || \
420+
defined(_PY32_DEF_)
416421
GPIO_TypeDef *gpioPort; ///< Output GPIO PORT
417422
uint32_t gpioPin; ///< Output GPIO PIN
418423
#endif
424+
419425
#if defined(TARGET_GIGA) || defined(TARGET_M4)
420426
mbed::DigitalInOut *gpio;
421427
#endif
422-
#if defined(ARDUINO_ARCH_RP2040)
423-
PIO pio = pio0;
424-
int sm = 0;
425-
bool init = true;
426-
#endif
428+
427429
};
428430

429431
#endif // ADAFRUIT_NEOPIXEL_H

Adafruit_Neopixel_RP2.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#if defined(ARDUINO_ARCH_RP2040)// RP2040 specific driver
2+
3+
#include "Adafruit_NeoPixel.h"
4+
5+
bool Adafruit_NeoPixel::rp2040claimPIO(void) {
6+
// Find a PIO with enough available space in its instruction memory
7+
pio = pio0;
8+
if (pio_can_add_program(pio, &ws2812_program)) {
9+
pio_program_offset = pio_add_program(pio, &ws2812_program);
10+
} else {
11+
// ok try pio1
12+
pio = pio1;
13+
if (pio_can_add_program(pio, &ws2812_program)) {
14+
pio_program_offset = pio_add_program(pio, &ws2812_program);
15+
} else {
16+
// ok try pio2 (RP2350)
17+
pio = pio2;
18+
if (pio_can_add_program(pio, &ws2812_program)) {
19+
pio_program_offset = pio_add_program(pio, &ws2812_program);
20+
} else {
21+
pio = NULL;
22+
return false;
23+
}
24+
}
25+
}
26+
27+
// Find a free SM on one of the PIO's
28+
pio_sm = pio_claim_unused_sm(pio, false); // don't panic
29+
if (pio_sm < 0) {
30+
return false;
31+
}
32+
33+
// yay ok!
34+
35+
if (is800KHz) {
36+
// 800kHz, 8 bit transfers
37+
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 800000, 8);
38+
} else {
39+
// 400kHz, 8 bit transfers
40+
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 400000, 8);
41+
}
42+
43+
return true;
44+
}
45+
46+
void Adafruit_NeoPixel::rp2040releasePIO(void) {
47+
if (pio == NULL)
48+
return;
49+
50+
pio_remove_program(pio, &ws2812_program, pio_program_offset);
51+
52+
if (pio_sm < 0)
53+
return;
54+
55+
pio_sm_set_enabled(pio, pio_sm, false);
56+
pio_sm_unclaim(pio, pio_sm);
57+
}
58+
59+
60+
// Private, called from show()
61+
void Adafruit_NeoPixel::rp2040Show(uint8_t *pixels, uint32_t numBytes)
62+
{
63+
// verify we have a valid PIO and state machine
64+
if (! pio || (pio_sm < 0)) {
65+
return;
66+
}
67+
68+
while(numBytes--)
69+
// Bits for transmission must be shifted to top 8 bits
70+
pio_sm_put_blocking(pio, pio_sm, ((uint32_t)*pixels++)<< 24);
71+
}
72+
#endif

0 commit comments

Comments
 (0)