Help with SPIN bidirectional SPI > 32 bits
cheezus
Posts: 298
in Propeller 1
I looked through the obex and nothing jumped out at me so I thought I'd ask for some help. What I need to do is shift synchronous serial data out, LSB first, while simultaneously shifting data in, LSB first. (I'm pretty sure the data in is LSB, the code I have now shifts in MSB but pretty sure it does the reversal in the calling method.) It needs to be variable number of bits and handle multi-long transfers. The other must have is pure spin.
One of the problems I'm having is with endian-ness.. I still need to handle how ASCII hex string is parsed into the longs and since they're both up in the air right now I just keep getting lost. I'm probably not describing the problem 100% so here's an example. The original code is able to shift variable number of bits in/out, up to 1 long.
I think this code could work, just compute how many times to loop. What I really want to do is pass a pointer to the array. Not sure how it should return the data though. This returned data needs to be optionally compared against an expected output data, with a mask. That should be farily simple once I figure out how to get data in and out. Understanding this shift problem should help with writing the parsing code.
Right now I have this written to theoretically work with 32 bit data. SIR is never more than 8 bits for this chip though.
One of the problems I'm having is with endian-ness.. I still need to handle how ASCII hex string is parsed into the longs and since they're both up in the air right now I just keep getting lost. I'm probably not describing the problem 100% so here's an example. The original code is able to shift variable number of bits in/out, up to 1 long.
PRI Shift_Array(array, num_bits) : ret_value | i { Shifts an array of bits into the TAP while reading data back out. This method is called when the TAP state machine is in the Shift_DR or Shift_IR state. } ret_value := 0 repeat i from 1 to num_bits outa[TDI] := array & 1 ' Output data to target, LSB first array >>= 1 ret_value <<= 1 ret_value |= ina[TDO] ' Receive data, shift order depends on target if (i == num_bits) ' If at final bit... outa[TMS] := 1 ' Go to Exit1 TCK_Pulse
I think this code could work, just compute how many times to loop. What I really want to do is pass a pointer to the array. Not sure how it should return the data though. This returned data needs to be optionally compared against an expected output data, with a mask. That should be farily simple once I figure out how to get data in and out. Understanding this shift problem should help with writing the parsing code.
Right now I have this written to theoretically work with 32 bit data. SIR is never more than 8 bits for this chip though.
ifnot str.stringCompareCS(c, @SIR) ' sir always 8 bits { if ck > 32 ' SIR > 32 bits not supported, only 8 bit SIR testing pst.str(string(13,10,"SIR > 32 Clocks")) return } tdi := nu.FromStr(long[p][2], nu#HEX) isTdo := false isMask := false { pst.str(String(13,10)) pst.str(@commandbuffer) pst.str(String(13,10,"parameters = ")) pst.dec(n) pst.str(String(13,10)) pst.dec(t) }{ repeat i from 1 to t pst.str(long[p][(i*2)]) pst.hex(nu.FromStr(long[p][(i*2)], nu#HEX),2) pst.str(String(" ")) } if n == 5 ifnot str.stringCompareCS(long[p][3], string("TDO")) tdo := nu.FromStr(long[p][4], nu#HEX) isTdo := true if n == 7 ifnot str.stringCompareCS(long[p][3], string("TDO")) tdo := nu.FromStr(long[p][4], nu#HEX) isTdo := true ifnot str.stringCompareCS(long[p][5], string("MASK")) mask := nu.FromStr(long[p][6], nu#HEX) isMask := true elseifnot str.stringCompareCS(long[p][5], string("TDO")) tdo := nu.FromStr(long[p][6], nu#HEX) isTdo := true if n == 9 if str.stringCompareCS(long[p][3], string("SMASK")) pst.str(string("bad data format")) return if str.stringCompareCS(long[p][5], string("TDO")) pst.str(string("bad data format")) return if str.stringCompareCS(long[p][7], string("MASK")) pst.str(string("bad data format")) return tdo := nu.FromStr(long[p][6], nu#HEX) mask := nu.FromStr(long[p][8], nu#HEX) isTdo := true isMask := true '' lets debug all this stuff above for a basic sanity check { pst.str(string(13,10,"CLOCKS ")) pst.dec(ck) pst.str(string(" TDI")) pst.str(nu.ToStr(tdi, nu#HEX)) if isTdo pst.str(string(" TDO")) pst.str(nu.ToStr(tdo, nu#HEX)) if isMask pst.str(string(" MASK")) pst.str(nu.ToStr(mask, nu#HEX)) } result := jtag.Send_Instruction(tdi ,ck) if isTdo result ^= tdo if isMask result &= mask ifnot result '' DEBUG SUCESS OR FAIL HERE!! pst.str(String("SIR COMPARE FAIL"))
Comments
*edit
Looking at that again, this doesn't seem quite right...:
I think the divide is 32, so the right shift would be 6? Not sure about the left shift...
The math is escaping me at the moment. Perhaps when the twins go to sleep.
my thought was every 32 bit I need a new long. but then I got confused with you starting at 1 not 0. And then things got out of plan.
I guess you are right with >>5
So yeah - that's what I MEANT to say...
but basically if you provide a address of an input array of size n and the address of an output array of the same size it should do it.
In fact, if you do not need the data in the send buffer again, you could even use the same array, and it will replace bit by bit the 'to send' bit with the 'received' bit
Enjoy!
Mike
It was a lot closer than where I was going. I do need the data in the send buffer again because once the TDI is sent, the receive is optionally compared against TDO (with a mask). I know I'm just overthinking things and trying to make it harder than it is. I haven't tested this method yet but it does look like it should work. I ran the edge cases through a calc and got the expected results. Basic sanity checks. I'm not sure how much overhead precomputing n saves.
I can't remember what else I was looking at but there was something that used bidirectional spi. Hopefully when I run across it again this will work for that too!
Mike