Trouble shifting bits
lardom
Posts: 1,659
in Propeller 1
I've been trying to write a method for SPI and what I thought would work doesn't. The code I've written will read the bits right to left but I had to add another zero to the right. I'm testing it with leds. The line I commented out works the same as the binary line.
PUB READ_BYTE | idx
dira[1]~~
dira[2]~~
Test_Byte := %1110010110
repeat idx from 1 to 9
outa[2] := %1110010110 >> (idx)
'outa[2] := Test_Byte >> (idx)
waitcnt(clkfreq/4 + cnt)
outa[2]~
waitcnt(clkfreq/4 + cnt)

Comments
Only Shift right worked though and I'm hoping someone can tell me why.
PUB READ_BYTE | idx dira[1]~~ dira[2]~~ Test_Byte := %1110010110 repeat idx from 1 to 9 outa[2] := (%1110010110 >> idx) 'outa[2] := (Test_Byte >> idx) waitcnt(clkfreq/4 + cnt) outa[2]~ waitcnt(clkfreq/4 + cnt)Enjoy!
Mike
pub shift_out(value, bits, mode) '' Shift value out via DPIN using SCLK '' -- bits is # of bits to shift out '' -- mode is 0 for LSBFIRST, !0 for MSBFIRST if (mode == 0) value ><= bits ' reverse bits for LSBFIRST output value <<= 32 - bits ' move first bit to bit31 repeat bits outa[DPIN] := (value <-= 1) ' rotate output bit to bit0 outa[SCLK] := 1 ' clock it outa[SCLK] := 0IMHO, using numbers for pins and the post ~ and ~~ is a recipe for bug generation. I've used the code above in a number of apps. It's flexible, which makes it easy to use, and readable, which makes it easy to debug. "Quick and dirty" is never quick, but always dirty.Thanks JonnyMac, I'll run this on the PST. I did want to make 'sure' the bits were shifting before started thinking about clocking data.
pub shift_out(value, bits, mode) '' Shift value out via DPIN using SCLK '' -- bits is # of bits to shift out '' -- mode is 0 for LSBFIRST, !0 for MSBFIRST if (mode == 0) value ><= bits ' reverse bits for LSBFIRST output value <<= 32 - bits ' move first bit to bit31 repeat bits outa[DPIN] := (value <-= 1) ' rotate output bit to bit0 term.tx("0" + outa[DPIN]) ' verification only (remove) outa[SCLK] := 1 ' clock it outa[SCLK] := 0Counting from 1 to 9 means that you're not getting the lowest bit value, because the smallest shift you use is 1, not 0.
PUB READ_BYTE | idx, bit dira[1]~~ dira[2]~~ Test_Byte := %1110010110 repeat idx from 0 to 8 bit := (%1110010110 >> idx) & 1 'the & 1 is used to mask off all bits but the lowest one, just for terminal output outa[2] := bit term.tx( "0" + bit ) 'stolen from JonnyMac to help you debug it waitcnt(clkfreq/4 + cnt) outa[2]~ waitcnt(clkfreq/4 + cnt)I think you missed this from lardom's post:
I looked at his code and didn't see any major issues, which made me wonder if he had his LED wired correctly.
-Phil
110100111
110100111
Mine is the first one, iterating the bits from 0 to 8, without the extra zero on the value. His is the 2nd one, with the extra zero, iterating the bits from 1 to 9.
PUB READ_BYTE | idx, bit, Test_byte Test_Byte := %111001011 repeat idx from 0 to 8 bit := (Test_Byte >> idx) & 1 'the & 1 is used to mask off all bits but the lowest one, just for terminal output dbg.tx( "0" + bit ) 'stolen from JonnyMac to help you debug it dbg.tx( 13 ) Test_Byte := %1110010110 repeat idx from 1 to 9 bit := (Test_Byte >> idx) & 1 'the & 1 is used to mask off all bits but the lowest one, just for terminal output dbg.tx( "0" + bit ) 'stolen from JonnyMac to help you debug itI also learned the purpose of 'rotate bits' 'reverse bits' and 'shift bits'. BTW, thanks for the tips on hexadecimal and binary numbers. I'm using both in building the code for my current project.
One of my questions is does a 32-bit-shift move those bits to a different register?
In Spin, unless you use an assignment operator (e.g. "x := 2" or "x += 2" or "x >>= 2", as opposed to "x >> 2", which is not an assignment operation), it will never overwrite a value. Shifting a value with the normal ">>" right shift will not overwrite the old value but will only return the shifted result, while the ">>=" right shift will overwrite your value.
I'm sorry if I misunderstood your question or if I confused you even more with my answer.
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 inBefore you freak out - bits/2 has the same effect as bits >>1 because we are in the binary system. To compare, in decimal system say 200>>1 has the same effect as 200/10, 10 being the base of decimal, while 2 is being the base of binary.
Erlend
Yes /2 and >>1 are the same, only that a division takes about thousand clock cycles, while the shift takes 4 clock cycles.
So never do shifts with multiply and division in Spin. C may optimize that to a shift, but Spin does not.
Andy
Edit: As I rethink it: /2 and >>1 is not exactly the same, one works with signed numbers the other with unsigned, so /2 and ~>1 is the same.
frida, I'll copy and paste. Thanks.
>> can be used in place of division when divisor is power of 2 (2, 4, 8 16...).
<< can be used in place of multiplication when multiplier is power of 2.
Instead of
you can use:
because 8 is 2^3. Same rules apply for dividing by right shifting.
Additional tip: If you're dividing a signed number that can be negative, there is an operator called SAR that looks like this ~>. This operator will preserve the sign of the value value being divided (>> pads the sign bit end with zeroes for each bit shifted). As Andy pointed out, using shifts for multiplication and division where possible are faster than * and / operators.
1 / 2 = 0 (in integer math)
-1 / 2 = 0
1 ~> 1 = 0
BUT
-1 ~> 1 = -1
So, in very specific cases, signed right shift is not the same as divide by two.
I do now have a working SPI method, mode 0, msb 1st. Thanks to everybody.
My apologies in advance if that seems nitpicky ...
-Phil
'Apologies' from the guy who used Goertzel's algorithm to program the Propeller to respond to spoken words???