The most elegant MSB LSB swap?

Is there a more elegant/efficient/legible way to do a swap of MSB and LSB. In this case I need it to communicate with a chip that reads and writes in the "reverse" order. (please do not start an 'endian war in this thread).
value.BYTE[0]<< 8 + value>> 8

Erlend
21st century - when everything changes
"Better with a DAT and a COG than with a CAT and a DOG"

Comments

  • 23 Comments sorted by Date Added Votes
  • That looks pretty good. The following might be a hair better:
    value.BYTE[0] << 8 + value.BYTE[1]
    

    ... or not. Dunno.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • Peter JakackiPeter Jakacki Posts: 6,689
    edited March 16 Vote Up0Vote Down
    Isn't this what we use the REV instruction for in PASM and bitwise reverse operator >< or ><= for in Spin? However your code is about swapping bytes not "Most Significant Bit" with "Least Significant Bit". Some chips require this MSB to be sent first, some require LSB, regardless of the number of bits, but (with chips) it's about bits , not bytes. Besides, why swap bytes if you can just as easily send one or the other first?
    Tachyon Forth - compact, fast, forthwright and interactive
    useforthlogo-s.png
    Tachyon Forth News Blog
    TACHYON DEMONSTRATOR
    Brisbane, Australia
  • Isn't this what we use the REV instruction for in PASM and bitwise reverse operator >< or ><= for in Spin?
    Actually, no. Anyway, if he's sending one byte at a time or the data in serial, none of this would be necessary. I think we have to assume the communication is 16-bit parallel, or he wouldn't be asking.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • It does very much depend on what the transmission format actually is. If it's serial Big-Endian then the bit order, rather than the byte order, is where he needs to be focusing.
    The Prisoner's Dilemma, in english - "Selfishness beats altruism within groups. Altruistic groups beat selfish groups." - Quoted part from 2007, D.S Wilson/E.O Wilson.
  • ErlendErlend Posts: 554
    edited March 18 Vote Up0Vote Down
    The chip expects to receive a word, so I'd like to send a word. Spin puts an (16 bit) integer in a word (actually long) with the MSB in bits 8-15, and the LSB in bits 0-7. My standard (serial) routine transmits the 8-15 first, then the 0-7. The chip wants to receive the LSB first. That is why I need to swap them so that the LSB goes into 8-15, and the MSB goes into 0-7.

    Erlend
    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • So, as I understand it, you already have a serial routine that works with words instead of bytes?

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • If your serial routine has a method for counted strings, you might be able to use,
    serial.Nstring(@wordValue,2)
    That would point to the low byte and send it first.
  • So much unnecessary mystery in some of these posts. Why say "the chip" when you can say which chip it is. Is this an issue with the order that bytes are read rather actually having to swap bytes? However when talking about communicating with chips and swapping MSB and LSB I naturally think of reversing bits.
    Tachyon Forth - compact, fast, forthwright and interactive
    useforthlogo-s.png
    Tachyon Forth News Blog
    TACHYON DEMONSTRATOR
    Brisbane, Australia
  • Tracy AllenTracy Allen Posts: 6,115
    edited March 19 Vote Up0Vote Down
    The following method to swap bytes is maybe elegant but more suited to a pasm implementation.
    x and y are bytes, ^ is the bitwise XOR operator.
    x := x ^ y
    y := y ^ x
    x := x ^ y
    now the bytes are swapped.

  • ErlendErlend Posts: 554
    edited March 19 Vote Up0Vote Down
    So much unnecessary mystery in some of these posts. ...

    No mystery intended. I was just curious to learn if there were a simpler way. The 'chip' is the IR sensor MLX90614. My curiousity was with regards to Spin and swapping byte order in general - interfacing to this chip just triggered me to ask the question.
    value.BYTE[0] << 8 | value.BYTE[1]
    
    appears to be the best answer.

    Erlend

    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • Tracy AllenTracy Allen Posts: 6,115
    edited March 19 Vote Up0Vote Down
    The MLX60915 sends and receives its words least significant byte first, which is the same as the natural order in the Propeller. It is the order used by common i2c objects such as Basic_I2C_Driver:
    ReadPage(SCL, devSel, addrReg, @data, 2) . ' to read a word
    WritePage(SCL, devSel, addrReg, @data, 2) . ' to write a word
    Isn't that what you want, no byte swap required?

    That said, the order of bytes presented by different i2c devices is all over the place. Many do send most significant first, or have data like time strings in an order opposite of what you'd like. I posit that the order should be handled as an option within any full-featured i2c object, a choice of most or least significant byte first. I'd write it to interpret a negative byte count as an endedness swap.

    p.s. I'm not trying to start an endedness war -- we have to work with it however it is.
  • Erlend wrote: »
    So much unnecessary mystery in some of these posts. ...

    No mystery intended. I was just curious to learn if there were a simpler way. The 'chip' is the IR sensor MLX90614. My curiousity was with regards to Spin and swapping byte order in general - interfacing to this chip just triggered me to ask the question.
    value.BYTE[0] << 8 | value.BYTE[1]
    
    appears to be the best answer.

    Erlend

    Thanks for that info. As Tracy mentioned that chip send its words in the same order as the Propeller handles it in memory so there isn't any need for byte swapping in this and most cases, although not all cases.

    Tachyon Forth - compact, fast, forthwright and interactive
    useforthlogo-s.png
    Tachyon Forth News Blog
    TACHYON DEMONSTRATOR
    Brisbane, Australia
  • Erlend wrote: »
    Is there a more elegant/efficient/legible way to do a swap of MSB and LSB. ...

    More legible:
       txword.byte[0] := value.byte[1]
       txword.byte[1] := value.byte[0]
    
    compiles to the same amount of bytes as your code

    More efficient:
       txword := value>>8 | value<<8
    
    Is 2 bytes shorter

    Elegance is a matter of taste, so no proposal for that...

    Andy
  • Ariba wrote: »
    Erlend wrote: »
    Is there a more elegant/efficient/legible way to do a swap of MSB and LSB. ...

       txword := value>>8 | value<<8
    

    I like this one. Elegant, compact, and efficient.

    Erlend
    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • -but I have to make sure there are no bits set in byte three of a long holding this value, right - because they would be shifted right, into byte two, and then be or'ed with the result of 'value<<8' - am I right?
    (this is just for my curiosity and learning, I can easily do a &FF first to clean it)

    Erlend
    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • I would use:
     txword := (value>>8) | (value<<8)
    

    It's probably not necessary, but it ensures the order of operations.

    As for making sure that the upper-word bits are set / not set, it depends on how the values are used. Ultimately some code somewhere is sending bits out to a device. If that code only deals with the lower 16 bits then no, you don't need to worry.
  • I think the name of the assigned variable, txword, is a hint that only 16 bits will be stored.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • I think the name of the assigned variable, txword, is a hint that only 16 bits will be stored.

    -Phil

    Yes, the result only needs the 16 bits, but when I tested in my particular code, as I feared, the 'value' variable had 'trash' in it's upper word bits, so I had to do a & $FF on it, so that that trash did not get shifted into the lower word - which I guess is only good coding practise anyway.

    Erlend
    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • evanhevanh Posts: 4,438
    edited March 28 Vote Up0Vote Down
    It's unlikely you'll need to swap bytes for serial data.

    Transmitting LittleEndian serial data is a simple case of transmitting from the lsb and shifting right, then repeat until the word is all shifted out. As opposed to BigEndian where you transmit the msb and shift left instead.

    To receive, input bits at the opposite end to transmitting: LE receives at msb and shifts right, while BE receives at lsb and shifts left.

    If not doing the above then you'll be up for bit swapping the whole word, but that's still not a byte swap.
    The Prisoner's Dilemma, in english - "Selfishness beats altruism within groups. Altruistic groups beat selfish groups." - Quoted part from 2007, D.S Wilson/E.O Wilson.
  • I read this stuff because I'm still trying to learn as much as I can. Is this more than a bitwise byte reversal?
    CON
      _clkmode = xtal1 + pll16x                           
      _xinfreq = 5_000_000
    
    OBJ   
    
      Debug : "FullDuplexSerialPlus"
       
    PUB Main  | value
    
        Debug.start(31, 30, 0, 57600)
        waitcnt(clkfreq * 2 + cnt)
        
        value := 85
    
        Debug.tx(13)
        Debug.bin(value, 8)
        Debug.tx(13)
        Debug.dec(value)
    
        value := value  >< 8
        
        Debug.tx(13)
        Debug.bin(value, 8)
        Debug.tx(13)
        Debug.dec(value)
    
        waitcnt(clkfreq + cnt)
    

    I got "85" and "170"
    Larry

    If the grass is greener on the other side...it's time to water your lawn.
  • Yep, that's it. And good use of debug there.
    The Prisoner's Dilemma, in english - "Selfishness beats altruism within groups. Altruistic groups beat selfish groups." - Quoted part from 2007, D.S Wilson/E.O Wilson.
  • evanh wrote: »
    It's unlikely you'll need to swap bytes for serial data.
    ...

    The situation is pretty simple; I have a (library) method that puts out MSB first, then LSB. The receiver wants LSB first, then MSB. How to fix this? Either write a new method that does LSB-MSB - or - swap the bytes before transmitting. I chose the latter, and I have asked for advice on how to do that in the best way. I did not expect to get so much good answers, and I still think
    txword := value>>8 | value<<8
    
    is the best answer. A valuable side effect is all the stuff I learn from this thread.

    Erlend
    21st century - when everything changes
    "Better with a DAT and a COG than with a CAT and a DOG"
  • Maybe fix the library. It must be going out of it's way to swap things itself. The library author had some hardware that used mixed Endianess or just assumed that was the normal way.
    The Prisoner's Dilemma, in english - "Selfishness beats altruism within groups. Altruistic groups beat selfish groups." - Quoted part from 2007, D.S Wilson/E.O Wilson.
Sign In or Register to comment.