Oliv4945 / wipy-WS2812

Wipy driver for WS2812 RGB LEDs (WS2812B, AdaFruit NeoPixels, ...).
MIT License
17 stars 11 forks source link

bytearray() doesn't allow multi-byte writes #5

Open Gadgetoid opened 6 years ago

Gadgetoid commented 6 years ago

I don't know if I'm missing something, but the way bytearray is used in the code is, as far as I can tell, not how bytearray actually works.

In C I would expect this paradigm because a strongly typed uint16_t being written to an array pointer of type uint8_t would set two bytes. But for a bytearray in Python, the high-byte is simply ignored. Example:

>>> b = bytearray(10)
>>> b[0] = 0xE0E0
>>> b
bytearray(b'\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00')

In order to fix this, I rewrote the buffer preparation code to the following:

            buf[index:index+2] = buf_bytes[green >> 6 & 0b11]
            buf[index+2:index+4] = buf_bytes[green >> 4 & 0b11]
            buf[index+4:index+6] = buf_bytes[green >> 2 & 0b11]
            buf[index+6:index+8] = buf_bytes[green & 0b11]

            buf[index+8:index+10] = buf_bytes[red >> 6 & 0b11]
            buf[index+10:index+12] = buf_bytes[red >> 4 & 0b11]
            buf[index+12:index+14] = buf_bytes[red >> 2 & 0b11]
            buf[index+14:index+16] = buf_bytes[red & 0b11]

            buf[index+16:index+18] = buf_bytes[blue >> 6 & 0b11]
            buf[index+18:index+20] = buf_bytes[blue >> 4 & 0b11]
            buf[index+20:index+22] = buf_bytes[blue >> 2 & 0b11]
            buf[index+22:index+24] = buf_bytes[blue & 0b11]

Where buf_bytes is:

    buf_bytes = (b'\xE0\xE0', # 0  0b00
                 b'\xE0\xFC', # 1  0b01
                 b'\xFC\xE0', # 2  0b10
                 b'\xFC\xFC') # 3  0b11

For WiPy 2.0 I also used G22/P11 and removed the pull-up setting.

Gadgetoid commented 6 years ago

Note, I think I've seen what might have happened here- I found a generic "pyb" MicroPython board based example and modified it into the following: https://github.com/Gadgetoid/wipy-WS2812/blob/master/ws2812alt.py

This packs two bits per byte correctly, whereas the code in this repository (at time of writing) discards one bit, and packs the other ones 1 bit per byte, with an empty spacing byte between each one.