• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

WS2812B Protocol Idea

Status
Not open for further replies.

Suraj143

Active Member
Hi guys,

I have written an assembly subroutine called "Load_Pixel".When I call it, it will load the 3bytes (24bit) represent colour to a single pixel led.This works fine.

The doubt is Let say I have 12 nos neo pixel bulbs & need to load 12 colors from a table read.

The problem is after feeding the 1st LED colour, the code must get ready for the next colour to be load. For this task it will waste long time. Will it conflict with the protocol?

The datasheet says the data will load after 50uS of idle time.Does this means I have enough time to do code stuff until I reach 50uS?
 

Pommie

Well-Known Member
Most Helpful Member
I pretty sure that you can't have a delay of more than 50μS between sets of 24 bits and would keep it to less than 40 to be safe. I think you would have to load a ram buffer with your data in order to get it out fast enough. For 12 LEDs this would be a 36 byte buffer which most pics can handle.

If you have access to the newer chips then Microchip have an app note on using the Configurable Logic Cell to generate the protocol in hardware. See here.

They also discuss ram buffering in another note.

Mike.
 

Suraj143

Active Member
Hi thanks for the details.

I read the application note & it says it will take care of all the protocol timing. So after setting it up the CLC I have to load the RGB data to the SSP1BUF.Am I correct?

Code:
;Load the 1st LED in the strip
    movlw     b'00000000'      ; Load Green
    movwf     SSP1BUF
    movlw     b'11111111'      ; Load Red
    movwf     SSP1BUF
    movlw     b'00000000'      ; Load Blue
    movwf     SSP1BUF  
;Load the 2nd LED in the strip
    movlw     b'00000000'      ; Load Green
    movwf     SSP1BUF
    movlw     b'00000000'      ; Load Red
    movwf     SSP1BUF
    movlw     b'11111111'      ; Load Blue
    movwf     SSP1BUF
 

Pommie

Well-Known Member
Most Helpful Member
After any write to SSP1BUF you should wait for BF to be set then read SSP1BUF.
Something like,
Code:
Write
        MOVWF     SSP1BUF
LOOP     BTFSS     SSP1STAT, BF ;Has the byte been sent
        GOTO     LOOP         ;No
        MOVF     SSP1BUF, W     ;Read buff to clear flag
        RET
Mike.
Edit, untested. Banking may be completely wrong.
 

Suraj143

Active Member
Hi Mike,
Even though if I use the CLC I have to consider the 50uS time between bytes :(

Here is my structure.
You see that "Next_Pixel" subriutine takes lots of cycles :(

Code:
        clrf    Index_L            ; reset the pattern index
            clrf    Index_H            ; //
            movlw    .32
            movwf    LED_Count
            clrf    Pixel_Byte
            call    Next_Pixel_1    ; load the 1st pixel colour
            call    Load_Pixel
            ;
Send_Loop    call    Next_Pixel
            call    Load_Pixel
            decfsz    LED_Count,F
            goto    Send_Loop
            return
;============================================================================
Load_Pixel    movf    Green,W         ; Load Green
            call    Send_2812B
            movf    Red             ; Load Red
            call    Send_2812B
            movf    Blue,W             ; Load Blue
            call    Send_2812B
            return  

;============================================================================
;Load the next Pixel
Next_Pixel    movlw    .1
            addwf    Index_L,F
            btfsc    STATUS,Z
            incf    Index_H,F
            call    Pixel_Table    ; call the coresponding pixel byte
            movwf    Pixel_Byte
        ;
Next_Pixel_1  
            movf    Pixel_Byte,W
            call    Pixel_Colour    ; call the pixel byte represent colour
            movwf    Green
            incf    Pixel_Byte,F
            movf    Pixel_Byte,W
            call    Pixel_Colour
            movwf    Red
            incf    Pixel_Byte,F
            movf    Pixel_Byte,W
            call    Pixel_Colour
            movwf    Blue          
            Return
        ;
 
Last edited:

Mike - K8LH

Well-Known Member
how about...

Code:
putfx01
        movlw   fx01%256        ; fx table 1 address lo           |B0
        movwf   ptrl            ;                                 |B0
        movlw   fx01/256        ; fx table 1 address hi           |B0
        movwf   ptrh            ;                                 |B0
        movlw   fx01cnt         ; fx table 1 length               |B0
        movwf   count           ;                                 |B0
sendrgb
        call    getdata         ; get RGB pattern byte            |B0
        movwf   pattern         ; b0 = GRN, b1 = RED, b2 = BLU    |B0
        movlw   0x00            ;                                 |B0
        btfsc   pattern,0       ;                                 |B0
        movlw   0xFF            ;                                 |B0
        btfsc   SSP1STAT,BF     ; busy? no, skip, else            |B0
        goto    $-1             ; loop (wait)                     |B0
        movwf   SSP1BUF         ; send GRN byte                   |B0

        incf    ptrl,F          ; bump pattern index              |B0
        skpnz                   ;  "                              |B0
        incf    ptrh,F          ;  "                              |B0

        movlw   0x00            ;                                 |B0
        btfsc   pattern,1       ;                                 |B0
        movlw   0xFF            ;                                 |B0
        btfsc   SSP1STAT,BF     ; busy? no, skip, else            |B0
        goto    $-1             ; loop (wait)                     |B0
        movwf   SSP1BUF         ; send RED byte                   |B0
        movlw   0x00            ;                                 |B0
        btfsc   pattern,2       ;                                 |B0
        movlw   0xFF            ;                                 |B0
        btfsc   SSP1STAT,BF     ; busy? no, skip, else            |B0
        goto    $-1             ; loop (wait)                     |B0
        movwf   SSP1BUF         ; send BLU byte                   |B0
        decfsz  count,F         ; last byte? yes, skip, else      |B0
        goto    sendrgb         ; branch (send next fx data)      |B0
        return                  ; done                            |B0

getdata
        movf    ptrh,W          ;                                 |B0
        movwf   PCLATH          ;                                 |B0
        movf    ptrl,W          ;                                 |B0
        movwf   PCL             ; jump                            |B0

fx01
        dt      0,3,7,7,3,0,6,1,2,3,6,1,1,2,4,5
fx01cnt equ     $-fx01          ; length fx01 table
 

Suraj143

Active Member
Hi K8LH
I have two tables.One is Pixel table & other one is pixel colour table.

Pixel table contains which pixel you want to light up in the strip.but it represent the colour index.
Pixel colour table contains the colour of the pixel each 3 bytes.

Ex:-
Pixel_Table dt 00,01,02,08.........; 32 bytes strip

In the above first pixel is off.
4th pixel is 08, that means it should light up as orange colour.so I have to call pixel colour table 8*3= orange colour 3bytes.

That is what Iam implementing.
 

Mike - K8LH

Well-Known Member
If I understand correctly, your "color table" contains three byte duty cycle values for each color. For example, you're sending 0x00 (grn), 0xFF (red), and 0x00 (blu) duty cycle values to the WS2812 chain to light one of the WS2812's the color Red. If those values are always going to be 0 (0x00) or 255 (0xFF), why do you need a "pixel table" that contains color table indexes when each byte in the "pixel table" can represent those three byte color values directly? That is, each byte contains three bits that determine which value, 0x00 or 0xFF, to use for the 'grn', 'red', and 'blu' duty cycle values. This eliminates the need for a "color table" (see example post #6).
 

Suraj143

Active Member
Hi, I need plenty of colours not only green red and blue.
Ex: sea blue, orange, pink, violet etc...thats
If I understand correctly, your "color table" contains three byte duty cycle values for each color. For example, you're sending 0x00 (grn), 0xFF (red), and 0x00 (blu) duty cycle values to the WS2812 chain to light one of the WS2812's the color Red. If those values are always going to be 0 (0x00) or 255 (0xFF), why do you need a "pixel table" that contains color table indexes when each byte in the "pixel table" can represent those three byte color values directly? That is, each byte contains three bits that determine which value, 0x00 or 0xFF, to use for the 'grn', 'red', and 'blu' duty cycle values. This eliminates the need for a "color table" (see example post #6).
Hi, I need plenty of colours not only green red and blue.
Ex: sea blue, orange, pink, violet etc...thats why I need a colour table.
 

Mosaic

Well-Known Member
One can always learn from the efficiency of K8LH's code. :)

I am in the process of writing ASM code for this application based on a 48Mhz 18F26J50. :nailbiting:
The plan, so far, is to use the DMA SPI at a 333nS bit clock which allows me to aggregate 2 bits out of the 24 bits per LED into 1 SPI byte.
So a data stream of 12 SPI bytes deliver the colour and luminance data to a single LED. :cool:

As my application just requires 504 SPI bytes to do the 7 'large' LED refresh (6x the data as I am joining 6 LEDS into one large one) (I will run @ 64Hz refresh rate) , I am using Flash code space as a large buffer (55K of it actually) to provide about 10.5 seconds of a looping pattern.

The code will stuff the 504 bytes into GPR from Flash code space and then the DMA SPI will pump it out to the LEDs to refresh them, after 14mS another set of 504 bytes are sent to keep up the refresh rate, probably run by an interrupt timer.

The 14mS of 12MIPS time between LED refreshes allow the uC to handle all the other interfacing chores, such as LCD display, check for button presses, beep tasks, etc.

I have developed a compressed protocol to cram the 55Kbytes of RGB data into 1Kbyte of instructional data created on the Vixxen 2.0 sequencer via serial/USB over RS232 to the USART in the 18F chip. This allows me to design different compressed patterns on a PC and download them to the uC static GPR and transfer to flash RAM. So I am allocating 2 to 4KB of actual code space and 4 to 6KB of compressed pattern space (4 to 6 d'loadable patterns) , with the remaining 55KB of flash RAM for the expanded RGB data amounting to 10.5 secs of an uncompressed looping pattern selected from the compressed patterns to be displayed.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top