Connect with us

Two Wire Serial bit-bang Dyslexia

Discussion in 'Microcontrollers, Programming and IoT' started by Fish4Fun, Aug 14, 2020.

Scroll to continue with content
  1. Fish4Fun

    Fish4Fun So long, and Thanks for all the Fish!

    464
    105
    Aug 27, 2013
    My Dyslexia is killing me and I need some help .... I can't remember the relationship between time and left-right orientation in the timing diagram ... I know this seems ridiculous, but it is the world I live in. In an effort to make clear what I am asking here are the two most likely scenarios as I see them:

    ****************************************************************************************************
    One:

    With Respect To the diagram below, assuming I want to send the 32-bit word $F1020408 (11110001 00000010 00000100 00001000) via a bit-bang routine do I send the lowest bit in the lowest byte first like so:

    Code:
    ;Assume io Pins are Initialized
    
    Tx_F1020408:
    sbi   PORT_io, Pin_cki     ;Set Clock Line High
    call TxLSB
    call TxByte2
    call TxByte3
    call TxMSB
    ret
    
    Tx_LSB:     ;00001000
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    ret
    
    Tx_Byte2:          ;00000100
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    ret
    
    Tx_Byte3:          ;00000010
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    ret
    
    Tx_MSB:          ;11110001
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_One
    call   Tx_One
    call   Tx_One
    ret
    
    Tx_Zero:
    ;Tx 0
    cbi   PORT_io, Pin_sdi      ;Set sdi = 0
    cbi   PORT_io, Pin_cki      ;Clock = Low
    sbi   PORT_io, Pin_cki      ;Clock = High
    ret
    
    Tx_One:
    sbi   PORT_io, Pin_sdi      ;Set sdi = 0
    cbi   PORT_io, Pin_cki      ;Clock = Low
    sbi   PORT_io, Pin_cki      ;Clock = High
    ret
    
    ****************************************************************************************************
    Two:
    With Respect To the diagram below, assuming I want to send the 32-bit word $F1020408 (11110001 00000010 00000100 00001000) via a bit-bang routine do I send the Highest bit in the lowest byte first like so:


    Code:
    ;Assume io Pins are Initialized
    
    Tx_F1020408:
    sbi   PORT_io, Pin_cki     ;Set Clock Line High
    call TxLSB
    call TxByte2
    call TxByte3
    call TxMSB
    ret
    
    Tx_LSB:     ;00001000
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    ret
    
    Tx_Byte2:          ;00000100
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    ret
    
    Tx_Byte3:          ;00000010
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    ret
    
    Tx_MSB:          ;11110001
    call   Tx_One
    call   Tx_One
    call   Tx_One
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    ret
    
    Tx_Zero:
    ;Tx 0
    cbi   PORT_io, Pin_sdi      ;Set sdi = 0
    cbi   PORT_io, Pin_cki      ;Clock = Low
    sbi   PORT_io, Pin_cki      ;Clock = High
    ret
    
    Tx_One:
    sbi   PORT_io, Pin_sdi      ;Set sdi = 0
    cbi   PORT_io, Pin_cki      ;Clock = Low
    sbi   PORT_io, Pin_cki      ;Clock = High
    ret
    
    
    ****************************************************************************************************

    Of course the other two permutations (not detailed above) involve using one of the above two scenarios except sending the High Byte First, but I am 99.99% sure these are NOT the case ....

    ***AND NO, this is NOT the actual code, just didactic attempts to clarify the order of operations to comply with the protocol in the below diagram.***

    Here is the Two-Wire serial timing Diagram (taken from the SK9822 data sheet):

    TWI.jpg


    I know this seems silly, and I could certainly figure it out experimentally; however, it would be a kindness if someone could simply tell me the answer .... (The irony of asking for the answer to **Time** is not lost on me.)

    If anyone is still reading ... the bit-bang routine I am working on is going to be used to control arrays of SK9822 RGB LEDs .... The SK9822's arrays are "daisy chained" together the "Start Sequence" is 32 zeros followed by 32 bits of data for each LED in the array and then terminated by 32 ones ....

    I am **assuming** that a routine optimized for refresh rate would immediately begin sending the next "frame" of data immediately following the termination bits .... ie:

    Assuming 1024 LEDs in an array ...

    Frame.0:
    Start = $00000000
    Data = 1024 * $xxxxxxxx data bytes
    Termination = $FFFFFFFF

    Frame.1:
    Start = $00000000
    Data = 1024 * $xxxxxxxx data bytes
    Termination = $FFFFFFFF
    .
    .
    .
    .
    Frame.N
    Start = $00000000
    Data = 1024 * $xxxxxxxx data bytes
    Termination = $FFFFFFFF
    .
    .
    etc
    .
    etc

    (8256 Total Bits/Frame ... ~4.128mS/Frame (~240 Frames/Sec) @ 2mbps)


    But to send a "Static" Frame one would do the following:

    Start = $00000000
    Data = 1024 * $xxxxxxxx data bytes
    Termination = 1024 * $FFFFFFFF
    (16416 Total Bits ... ~8.2mS @ 2mbps)

    I have three of these 32x8 arrays on order: ( https://www.ebay.com/itm/WS2812B-RG...var=454012843559&_trksid=p2057872.m2749.l2649 ) to experiment with .... I will start a new thread specifically about these ... for now I just wanted to make sure I get the protocol straight in my head so I can get the bit-bang code written before the panels arrive ...

    Thanks!

    Fish
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    10,567
    2,356
    Nov 17, 2011
    First of all, this more detailed explanation may be of more help than the sparse datasheet.
    The interface used is of the SPI type which is explained e.g. in the Wikipedia.

    Understandable. That's because this may be confusing.
    Usually, time advances from left to right, showing earlier events to the left, later events to the right. As e.g. in a historical timeline. This can be interpreted as the events being static and time moving from left to right (my interpretation, at least). This is what is shown in the datasheet of the SK9822.
    BUT the diagrams shown on e.g. the Wikipedia site show a different interpretation: time being static and the signals (events) flowing from left to right.Like this:
    upload_2020-8-17_8-45-26.png
    The red line indicates the static time, the signals are marching waveforms. This interpretation matches the hardware setup also shown on the same page where Bit 7 is shifted out forst from the shift register, followed by bits 6 5, 4 etc.:
    [​IMG]

    Coming back to your code: Both codes are invalid because both codes work with this sequence:
    Code:
    call TxLSB
    call TxByte2
    call TxByte3
    call TxMSB
    So they will send the LSB first, MSB last whereas the specs require MSB first, LSB last. But here the confusion may be on my side as it is not totally clear what LSB, Byte2, Byte3 and MSB are meant to be. From my point of view it were more meaningful to name thebytes according to function, e.g. for an LED frame:
    Code:
    call TxGlobal
    call TxBlue
    call TxGreen
    call TxRed
    But the naming is totally up to you, of course.

    Within the subroutines for the bytes the code from your 2nd example is correct:
    Code:
    Tx_LSB:     ;00001000
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_One
    call   Tx_Zero
    call   Tx_Zero
    call   Tx_Zero
    ret
    as it will output the MSB first, LSB last.
     
  3. Fish4Fun

    Fish4Fun So long, and Thanks for all the Fish!

    464
    105
    Aug 27, 2013
    Thanks Harald!

    I truly appreciate you taking the time to detail this for me. I cannot begin to explain how frustrating it is to look @ "dab" and read "bad", or "21" and see "12". While I understand MSB/LSB first conceptually, translating that to a time line with no actual data was killing me.

    Again, Thank You!

    I am aware there is existing Open Source C code specifically for driving small SK9822 arrays using an Arduino, but I have a really hard time sussing out the nuances of the low-level functions from C source written to use an AVR USART. The project I am exploring will require I have a mastery of the low-level mechanics in order to determine feasibility of the overall project ... and I was failing utterly at step one.

    Your naming convention (TxGlobal, TxBlue, TxGreen, TxRed) combined with pointing out the correct sequence for sending "00001000" gives me the building blocks to get the byte oriented routines written correctly ... perhaps even in a single try!

    One final question ... **if you happen to know the answer** (please do not waste any of your time researching, a few minutes testing will provide the answer) ...

    With a Single SK9822 LED (not an array)
    To light it Blue, I would send:
    $00000000 ;Start Sequence
    [Global Byte] [Blue Byte = 80] [Green Byte = 0] [Red Byte = 0]
    $FFFFFFFF ; End Sequence


    Now, assume an array of 256 x SK9822 LEDs .... LED(0) to LED(255)
    If I want to set the LED(0) data to a static value of:
    [Global Byte] [Blue Byte = 80 ] [Green Byte = 00] [Red Byte = 00]
    And all the other LEDs <OFF>
    I would send:
    $00000000 ;Start Sequence
    LED(255) = [Global Byte] [Blue Byte = 00] [Green Byte = 00] [Red Byte = 00]
    LED(254) = [Global Byte] [Blue Byte = 00] [Green Byte = 00] [Red Byte = 00]
    LED(253) = [Global Byte] [Blue Byte = 00] [Green Byte = 00] [Red Byte = 00]
    .
    .
    .
    .
    LED(2) = [Global Byte] [Blue Byte = 00] [Green Byte = 00] [Red Byte = 00]
    LED(1) = [Global Byte] [Blue Byte = 00] [Green Byte = 00] [Red Byte = 00]
    LED(0) = [Global Byte] [Blue Byte = 80] [Green Byte = 00] [Red Byte = 00]
    $FFFFFFFF ;End Sequence (0)
    $FFFFFFFF ;End Sequence (1)
    .
    .
    .
    $FFFFFFFF ;End Sequence (254)
    $FFFFFFFF ;End Sequence (255)

    To simplify the next question ==>> If ....
    Frame Data() =
    LED(255) = [Global Byte = XX] [Blue Byte = XX] [Green Byte = XX] [Red Byte = XX]
    LED(254) = [Global Byte = XX] [Blue Byte = XX] [Green Byte = XX] [Red Byte = XX]
    .
    .
    .
    LED(1) = [Global Byte = XX] [Blue Byte = XX] [Green Byte = XX] [Red Byte = XX]
    LED(0) = [Global Byte = XX] [Blue Byte = XX] [Green Byte = XX] [Red Byte = XX]

    With XX = Associate Values of RGB for LED(0) to LED(255) ....

    I am ***assuming*** that in the more general case of "refreshing all the LEDs" that the typical refresh process would be:

    $00000000 ;Start Frame(0)
    Frame Data(0)
    $FFFFFFFF ;End Sequence
    $00000000 ;Start Frame(1)
    Frame Data(1)
    $FFFFFFFF ;End Sequence
    .
    .
    .
    $00000000 ;Start Frame(N)
    Frame Data(N)
    $FFFFFFFF ;End Sequence
    $00000000 ;Start Frame(N + 1)
    Frame Data(N + 1)
    $FFFFFFFF ;End Sequence

    Where the Start and End Sequences are propagated From LED(0) to LED(255) .... and the update of LED(255) in Frame(0) occurs after the data for LED(0) to LED(254) Frame(1) has been loaded, but just before LED(0) has Rxd the End Sequence?

    It probably took longer to write that out than it will to actually test it, LoL, and it seems logical that my assumption would be correct from a bandwidth perspective ... but if you happen to know the answer ... ;-)

    Thanks Again!

    Fish
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-