Skip to content

Commit

Permalink
rp2040 check for available pio instruction memory
Browse files Browse the repository at this point in the history
  • Loading branch information
bbacskay committed Feb 24, 2024
1 parent 15bfa17 commit fe0e693
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 14 deletions.
42 changes: 29 additions & 13 deletions Adafruit_NeoPixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,11 @@ Adafruit_NeoPixel::Adafruit_NeoPixel(uint16_t n, int16_t p, neoPixelType t)
updateLength(n);
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;
#ifdef NEO_KHZ400
rp2040Init(p, is800KHz);
#else
rp2040Init(p, true);
#endif
#endif
}

Expand All @@ -117,6 +114,13 @@ Adafruit_NeoPixel::Adafruit_NeoPixel()
@brief Deallocate Adafruit_NeoPixel object, set data pin back to INPUT.
*/
Adafruit_NeoPixel::~Adafruit_NeoPixel() {
#if defined(ARDUINO_ARCH_RP2040)
if (!init) {
pio_sm_set_enabled(pio, pio_sm, false);
pio_sm_unclaim(pio, pio_sm);
pio_remove_program(pio, &ws2812_program, pio_program_offset);
}
#endif
free(pixels);
if (pin >= 0)
pinMode(pin, INPUT);
Expand Down Expand Up @@ -197,32 +201,44 @@ void Adafruit_NeoPixel::updateType(neoPixelType t) {
#if defined(ARDUINO_ARCH_RP2040)
void Adafruit_NeoPixel::rp2040Init(uint8_t pin, bool is800KHz)
{
uint offset = pio_add_program(pio, &ws2812_program);
// Find a PIO with enough available space in its instruction memory
pio = pio0;
if (!pio_can_add_program(this->pio, &ws2812_program)) {
pio = pio1;
}

// Will PANIC if not enough space in either PIO's instruction memory
pio_program_offset = pio_add_program(pio, &ws2812_program);

// Find a free SM on one of the PIO's
pio_sm = pio_claim_unused_sm(pio, true); // panic if no SM is free

if (is800KHz)
{
// 800kHz, 8 bit transfers
ws2812_program_init(pio, sm, offset, pin, 800000, 8);
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 800000, 8);
}
else
{
// 400kHz, 8 bit transfers
ws2812_program_init(pio, sm, offset, pin, 400000, 8);
ws2812_program_init(pio, pio_sm, pio_program_offset, pin, 400000, 8);
}

this->init = false;
}

// 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);
pio_sm_put_blocking(pio, pio_sm, ((uint32_t)*pixels++)<< 24);
}

#endif
Expand Down
3 changes: 2 additions & 1 deletion Adafruit_NeoPixel.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ class Adafruit_NeoPixel {
#endif
#if defined(ARDUINO_ARCH_RP2040)
PIO pio = pio0;
int sm = 0;
int pio_sm = -1;
uint pio_program_offset = 0;
bool init = true;
#endif
};
Expand Down

0 comments on commit fe0e693

Please sign in to comment.