Skip to content

Commit db41471

Browse files
authored
Merge pull request #436 from adafruit/rp2350_fixes
clean up and hand-add some of #381
2 parents 5afcd58 + c2e1046 commit db41471

File tree

3 files changed

+96
-60
lines changed

3 files changed

+96
-60
lines changed

Adafruit_NeoPixel.cpp

Lines changed: 28 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,20 +124,43 @@ 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);
139137
}
140138

141139
/*!
142140
@brief Configure NeoPixel pin for output.
141+
@returns False if we weren't able to claim resources required
143142
*/
144-
void Adafruit_NeoPixel::begin(void) {
143+
bool Adafruit_NeoPixel::begin(void) {
145144
if (pin >= 0) {
146145
pinMode(pin, OUTPUT);
147146
digitalWrite(pin, LOW);
147+
} else {
148+
begun = false;
149+
return false;
148150
}
151+
152+
#if defined(ARDUINO_ARCH_RP2040)
153+
// if we're calling begin() again, unclaim any existing PIO resc.
154+
rp2040releasePIO();
155+
if (! rp2040claimPIO()) {
156+
begun = false;
157+
return false;
158+
}
159+
160+
#endif
161+
149162
begun = true;
163+
return true;
150164
}
151165

152166
/*!
@@ -209,38 +223,8 @@ void Adafruit_NeoPixel::updateType(neoPixelType t) {
209223
}
210224
}
211225

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);
217226

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)
227+
#if defined(ARDUINO_ARCH_CH32)
244228

245229
// F_CPU is defined to SystemCoreClock (not constant number)
246230
#if SYSCLK_FREQ_144MHz_HSE == 144000000 || SYSCLK_FREQ_HSE == 144000000 || \
@@ -1908,7 +1892,7 @@ void Adafruit_NeoPixel::show(void) {
19081892

19091893
#elif defined(ARDUINO_ARCH_RP2040)
19101894
// Use PIO
1911-
rp2040Show(pin, pixels, numBytes, is800KHz);
1895+
rp2040Show(pixels, numBytes);
19121896

19131897
#elif defined(TEENSYDUINO) && \
19141898
defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
@@ -3382,8 +3366,7 @@ if(is800KHz) {
33823366
#elif defined(ARDUINO_ARCH_CH32)
33833367
ch32Show(gpioPort, gpioPin, pixels, numBytes, is800KHz);
33843368
#elif defined(ARDUINO_ARCH_RP2040) && defined(__riscv)
3385-
// Use PIO
3386-
rp2040Show(pin, pixels, numBytes, is800KHz);
3369+
rp2040Show(pixels, numBytes); // Use PIO
33873370
#else
33883371
#error Architecture not supported
33893372
#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+
uint pio_sm = -1;
392+
uint 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: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 = NULL;
8+
9+
if (! pio_claim_free_sm_and_add_program_for_gpio_range(&ws2812_program,
10+
&pio, &pio_sm, &pio_program_offset,
11+
pin, 1, true)) {
12+
pio = NULL;
13+
pio_sm = -1;
14+
pio_program_offset = 0;
15+
return false; // No PIO available
16+
}
17+
18+
// yay ok!
19+
20+
if (is800KHz) {
21+
// 800kHz, 8 bit transfers
22+
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 800000, 8);
23+
} else {
24+
// 400kHz, 8 bit transfers
25+
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 400000, 8);
26+
}
27+
28+
return true;
29+
}
30+
31+
void Adafruit_NeoPixel::rp2040releasePIO(void) {
32+
if (pio == NULL)
33+
return;
34+
35+
pio_remove_program_and_unclaim_sm(&ws2812_program, pio, pio_sm, pio_program_offset);
36+
}
37+
38+
39+
// Private, called from show()
40+
void Adafruit_NeoPixel::rp2040Show(uint8_t *pixels, uint32_t numBytes)
41+
{
42+
// verify we have a valid PIO and state machine
43+
if (! pio || (pio_sm < 0)) {
44+
return;
45+
}
46+
47+
while(numBytes--)
48+
// Bits for transmission must be shifted to top 8 bits
49+
pio_sm_put_blocking(pio, pio_sm, ((uint32_t)*pixels++)<< 24);
50+
}
51+
#endif

0 commit comments

Comments
 (0)