Full-Duplex SPI?
K2
Posts: 693
SPI is inherently full-duplex, but this fact is rarely exploited, it seems. I was unable to find anything SPI-related in OBEX that implemented simultaneous Tx and Rx. Doesn't seem like it would be too difficult to modify one of the existing SPI engines for this - seems like it would just involve sampling MISO one half clock after asserting MOSI. Before attempting such a modification, though, I wanted to check to see if anyone knew of such a piece of code already in existence.
Comments
BTW, what a great job you did recently in discovering the bug in Clock.spin! You constantly amaze me.
(I just finished a long project at work. I'm very excited to get back to the Prop. What a great platform! The more I use IAR EWARM, the more I love PropTool and the Propeller.)
Post #9 of this thread has the driver I wrote.
I will probably revisit the driver again soon to see if I can apply the things I just learned writing a driver for 23K256 SRAM chips.
I'll post my driver for these chips later today. I also wrote a driver that uses eight of these SRAM chips in parallel (I'll also post this later today).
I'm sure there are other drivers for the 23K256 chips out there; I just wanted to see if I could write one myself. Compared with other SPI devices, these chips are very simple to communicate with.
I learned something about sharing the MOSI and MISO lines yesterday when working on this driver. It turned out to be important to release the data line as soon as possible after clocking out the last bit of data prior to reading from the chips. If I left the data lines high after the last bit for a couple of instructions, it would conflict with the chips outgoing data and I'd get erroneous reads. This wasn't a problem when using only one chip but it was a problem when using eight chips at once.
Duane
- set Counter A to NCO mode, single pin output on the Data Out line (Data In on the SPI chip)
- set Counter B to NCO mode, single pin output set to the clock line
- set the data to be written out into PHSA, and left shift it to the 1st bit out is in bit 31 (which means the NCO mode drives the data out line to the value of that bit)
- start clock line by setting PHSB to a good initial value, and setting FRQB such that the clock pin toggles at the correct period (either 8 clocks for the unrolled loop, or 12 clocks for the djnz loop)
- now do the following for however many bits you need: - stop your clock line by setting FRQB to 0 (note, you may have to do this after the final "test", but before the final "rcl" to make sure you don't send out an extra clock)
That's basically it.
Jonathan
Your code looks like an excellent place to start on FD SPI, partly because it implements just the basics. In many SPI examples, there are massive amounts of code I would have to excise before moving forward. And that's often problematic because of all the dependencies.
fwiw, I was born in Poky (but grew up elsewhere). I'm happy to see such an active prop head in the area!
@ Jonathan: Near as I can tell, you have outlined the perfect high performance FD SPI in a Prop. As my humble first attempt grows up, it will be hugely educational to follow each step you've sketched out. Other than implementing canned solutions from Phil and kuroneko, I've done little with regard to the ancillary timing hardware that the Prop provides, so I don't yet understand the full picture of what you are proposing - but it's the perfect opportunity to change that.
You sneaky son of a mother! That "rcl phsa, #1" line is inspired. (definitely going in my bag of tricks)
If you want less voodoo involved with setting up the clock on counter B, set the CTRx up the same as Lonesock suggested. Set FRQB to 1 and add "ABSNEG PHSB, #4" inside the loop whenever you want a clock pulse. (4 [clocks] long in this case) One instruction slower per bit, but better for first cut code as there are fewer things to go wrong.
Lawson
I'm starting to appreciate the brilliance of the ideas advanced by lonesock and Lawson. They are speed enhancements, for sure, but they also produce elegant and simple code, and make better use of the available hardware. It has been a great education. Many thanks to the great foruministas here!
I need to learn how to do that too.
Yes. I wrote a few lines of bit-banging code (figuring I'd complete the first version that way, and later worry about improvements) and decided instead to reread lonesock's instructions. By then, his approach seemed do-able in an incremental way, using a scope to examine what was going on with the SCLK and MOSI lines. I never would have started out that way without 1) confidence that it can be done and 2) an excellent outline of how to do it. I don't have all the kinks worked out of RX yet, not because of any show-stoppers, but simply because the top-level SPIN portion is also being fleshed out as the PASM SPI engine becomes more functional.
By any chance, did you ever publish this full duplex SPI object to the OBEX? It sounds like you went about it in the most optimal way, and I think it would give lots of people a head start with faster SPI code. I'm about to do the same thing...but how many of us should really re-invent this wheel?