Question of Shifts in SPIN

Most likely I have missed something in the PROP manual, but my question regards shifts in SPIN and if there is a carry in/out test than can be done. Easy enough in PASM, but the spin descriptions are not as clear to me. Given an array of 12 bit words, I would like to unwind them into another array of words by shifting left or right and using the carry out of SourceVar(m) as the bit to shift into the DestVar(n) of the destination array (think rotate the array 90 degrees). Has anyone used the SPIN shift instructions to set or clear a bit in a word depending on the carry out value?

Thanks for any ideas.

FF
Ordnung ist das halbe Leben
I gave up on that half long ago.........

Comments

  • the problem is 12-bit, what you need is a 4-bitmove

    mask out 4-bit of fromarray with and
    or 4-bit into toarray

    I would use a pointer to the from byte
    and then split into 3 variations
    just first 4 bit
    just last 4 bits
    both (all) 8 bits

    and a pointer to the tobyte also 3 variations
    first 4
    last4
    both 8 bit

    You could check first if both arrays are at 0bit position in the start byte and 7bit on the end byte, special case, then you can use bytemove…

    but c out of << I don't know.

    Enjoy!

    Mike



    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • Another idea

    use bytearrays,
    if shift left check if source byte is negative -> your carry
    if shift right check if byte bit 0 is set - your carry
    the you can use << or >> on bytes

    but that still leaves the half byte problem of 12 bit

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • So it looks like it may be simpler to write a PASM routine to carry out (pun purely unintended) the rotate the array?
    Ordnung ist das halbe Leben
    I gave up on that half long ago.........
  • In Spin, you can always just test the bit that's shifted out before you do the shift.

    -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
  • Spin doesn't save the carry, so you have to test for it explicitly (as Phil said). In some cases a clever compiler can optimize the test and shift into a shift with carry. fastspin will do this in a few cases, but probably not for your particular use case. (it does work for shifting out to a pin though.)

  • I use shift in this way.
    PUB spiOut(out) : in | y
    
        out ><= 8               ' reverse byte
        repeat y from 0 to 7
            outa[clkPin]~~      ' clk pin high
            outa[mosiPin]:= out ' data bit out
            out /= 2            ' rotate right 1
            'waitcnt(cnt + 1000)
            outa[clkPin]~       ' clk pin low
            in *= 2             ' rotate left 1
            in |= ina[misoPin]  ' data bit in
    
    Yes Frida is my watchdog!
  • Also, in PASM, be aware that the carry flag contains the first bit shifted out, not the last one. The Propeller uses a "barrel shifter" wherein the bits are not shifted incrementally but all at once. And there's no logic to reach into the source register beforehand to test the "last" bit to be shifted out -- only bit 0 or bit 31, depending upon the direction of the shift.

    -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
  • frida wrote: »
    I use shift in this way.
    PUB spiOut(out) : in | y
    
        out ><= 8               ' reverse byte
        repeat y from 0 to 7
            outa[clkPin]~~      ' clk pin high
            outa[mosiPin]:= out ' data bit out
            out /= 2            ' rotate right 1
            'waitcnt(cnt + 1000)
            outa[clkPin]~       ' clk pin low
            in *= 2             ' rotate left 1
            in |= ina[misoPin]  ' data bit in
    

    I think much better to use shifts instead of multiply and divide. A simple compiler (like the default Spin compiler) will just blindly translate that code and will actually do multiply and divide, which are very slow. fastspin will try to use shifts automatically, but the "out /= 2" actually requires some tricky handling because in Spin variables are signed and a signed divide by 2 is not the same as a logical shift right, so it has to check for the "out" variable being negative (if fastspin were a bit smarter perhaps it could conclude that it cannot be negative because of the reverse at the top, but it's not that clever).

    For
        outa[mosiPin] := out
        out >>= 1
    
    fastspin does do something like:
       shr   arg01, #1 wc
       muxc  outa, #2 ' assuming mosiPin is pin 1
    
Sign In or Register to comment.