Makuna / NeoPixelBus

An Arduino NeoPixel support library supporting a large variety of individually addressable LEDs. Please refer to the Wiki for more details. Please use the GitHub Discussions to ask questions as the GitHub Issues feature is used for bug tracking.
GNU Lesser General Public License v3.0
1.18k stars 264 forks source link

NeoEspBitBangMethod does not work for pin numbers greater than 31 #820

Closed rubillos closed 2 months ago

rubillos commented 3 months ago

Describe the bug Using NeoEspBitBangMethods with PIN numbers greater than 31 does not work.

In NeoEspBitBangMethod.cpp the method neoEspBitBangWriteSpacingPixels has two issues:

At lines 104 and 105 should be:

uint32_t setValue = _BV(pin % 32);
uint32_t clearValue = _BV(pin % 32);

and at line 119 should be something like:

volatile uint32_t* setRegister;
volatile uint32_t* clearRegister;

if (pin < 32) {
    setRegister = &GPIO.out_w1ts;
    clearRegister = &GPIO.out_w1tc;
}
else {
    setRegister = &GPIO.out1_w1ts.val;
    clearRegister = &GPIO.out1_w1tc.val;
}

This will generate the correct bit masks and choose the correct registers for pins greater than 31.

(I ran into this on an Adafruit Esp32 QT Py where the internal NeoPixel is on pin 39).

Makuna commented 3 months ago

It's documented that it only works on 32 and below. https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#bit-bang

If you need this, you can always submit a change request.

rubillos commented 3 months ago

No worries, I have it patched for my own use. Was just passing along a possible fix.

Makuna commented 3 months ago

Does this actually work for you? I tried it and it does not.

Looking deeper, there is a compiler bug causing this to not work due to the format of the union they used on this field.

https://github.com/Makuna/NeoPixelBus/tree/Esp32BitBangPins contains the changes

rubillos commented 3 months ago

Working great for me. I'm using it on a project with an Adafruit Qt Py S3 for driving the onboard NeoPixel which is on pin 39. (I'm using FastLED for driving the main LED strip for the project; wanted a way to drive the onboard LED without adding a second controller to FastLED as the power management methods there don't allow individual control of multiple strips). Since it's just a single pixel, bit-banging seems to work fine.

I did simplify my code suggestion above for line 119 to:

    volatile uint32_t* setRegister = (pin < 32) ? &GPIO.out_w1ts : &GPIO.out1_w1ts.val;
    volatile uint32_t* clearRegister = (pin < 32) ? &GPIO.out_w1tc : &GPIO.out1_w1tc.val;
Makuna commented 2 months ago

https://github.com/Makuna/NeoPixelBus/pull/829

Makuna commented 2 months ago

https://github.com/Makuna/NeoPixelBus/releases/tag/2.8.1