Hunting for an already invented wheel - Slave Sync Serial
photomankc
Posts: 943
in Propeller 1
Looking to see if anyone has already developed a serial shift library that *is clocked by the other end*. In developing something using the Raspberry I had made the faulty assumption that the shiftin function on that end would have the clock line driven by the device sending data. That is not correct. It expects to drive the clock when shifting data in as well. Given that it clocks at 2.3MHz that's not an insignificant data rate to keep up with.
I was hoping to not have to chisel my own wheel here so I thought serial shift-in and out would be easy to implement since each side had a library, but each side also expects to drive the clock so I have a problem. Is there any library on the Propeller side that can shiftin and out using an external clock? I guess acting as something of a slave device?
Is there an IC that lets one side shift in data with it's own clock, latch it and then the other side can shift it out with it's own clock? That kind of sucks though since it cuts the data rate in half at least. Most shift registers I see go from serial to parallel. I was hoping to avoid chewing up the only hardware UART on the Pi for this or some USB -> Serial floppy cable and pin header. If I'm going to have to roll my own anyway I guess I'll just burn 5 lines and make it a 4 bit bus so I can move the same data rate at 4x slower clock rate and it only uses 2 more pins than I am now.
I was hoping to not have to chisel my own wheel here so I thought serial shift-in and out would be easy to implement since each side had a library, but each side also expects to drive the clock so I have a problem. Is there any library on the Propeller side that can shiftin and out using an external clock? I guess acting as something of a slave device?
Is there an IC that lets one side shift in data with it's own clock, latch it and then the other side can shift it out with it's own clock? That kind of sucks though since it cuts the data rate in half at least. Most shift registers I see go from serial to parallel. I was hoping to avoid chewing up the only hardware UART on the Pi for this or some USB -> Serial floppy cable and pin header. If I'm going to have to roll my own anyway I guess I'll just burn 5 lines and make it a 4 bit bus so I can move the same data rate at 4x slower clock rate and it only uses 2 more pins than I am now.
Comments
Alright.... well that was a fun exercise anyway.
Edit: I guess it does come across whinny. Wasn't really my intent. I don't really have the assembly skill to do this well. Took me months to write and debug a 400Khz I2C implementation back before C took over. It worked but was never really ready for prime-time before others got it done better. Maybe someday when I'm not trying to wrestle with a stalled out robot project.
The FDS object is not designed for this though and even at 115.2k it is jittery.
My acting teacher used to say, "Don't whine, win!" I'll paraphrase with, "Stop complaining; start coding!"
and this is true too, to take things into context if the application only involves <10,000 bytes/sec etc.
I'm pretty sure it can be done in 9 instructions:
So close and yet so far. How about with a 6 MHz crystal?
Ummmm, Ok. Yeah I get what you are saying. I could, but I likely wont. There are a lot of competing projects, so I won't be scratch-writing a synchronous serial slave. I was looking to see if one was ever written. It's not so that answers that. I'm going to go on with some other aspects of the bigger project and use what's already developed. Probably how this goes down when other people consider doing it too I guess.
Last time I tested the FDS serial in C, 115,200 was the limit I could get reliable communication at 230400 worked sometimes, but sometimes not. 115K is probably enough. The main issue was finding a USB serial adapter that did not involve a USB A to Mini connection. I found one that is mounted to the USB A plug and then I can solder a pig-tail and connector to connect it up to a Propeller board. Should be a more reliable mechanical arrangement.
That's kind of where I was landing too. Possible but really close to the line and maybe just over it. Then if something changes and the Raspberry manages to go a little faster it's broken.
Wow, that's.....
forget I asked.
That should work just fine for up to 32 bits at a time.
That's slick! I could write in words or dwords and then take a break and send again. Really neat way to go using the table to OR in the value.
I'm not sure how fast, but probably 10's of MHz.
P.S. Oops. I see this is with an external clock. That won't work...
Bean
If you want some PASM code isolated I can give you a nice simple Ultra-FDS if you like. But I'm still wondering as we have been hinting as to what are your actual requirements in regards to payload and response etc? This then determines what is the best way which in my opinion would be this fast and reliable asynch serial.
The actual data to move is not much, but there needs to be a lot of conversations reading sensors and sending control values. I used to have a spreadsheet that outlined all the commands and the data back and forth but I've lost that.
Thinking back I believe that my real concern over bit-rate had to do with the maximum time the receiver could spend waiting on all the data. On the multi processor prop it may be less of a problem to have one of them tied up in long 1 or 2ms data transactions where getting the data over fast was more critical on single processor systems so they could get the deed done in time.
I really think 115K will be fast enough for what I need to do.
sps.start: Starts a PASM cog which then waits for an arming command
sps.stop: Kills the PASM cog
sps.arm: Tells the PASM cog which pins to look at (clock and data) and how many bits to accumulate (up to 32)
psp.wait: Waits until the PASM cog has accumulated n bits and returns them
The receive loop is "unwound". As written, it is four instructions per bit. I believe it will run at 4 MHz and will not run at 5 MHz (80 MHz clock).
If you can guarantee the clock is about 100 nsec or less, you could remove the fourth instruction for each bit and it ought to run at about 6 MHz.
A demo program is included.
Very cool . Does it do 4 MHz with sequential words, or does it require a pause between each word for the HUB write? If it requires a pause, do you know how fast of a clock you can run such that no extra pause is required between words?
And we'll assume n > 16, or else obviously this short example could be combined into a single call where n is doubled.
Thanks for sharing.
Maybe I missed it, but what mechanism do you have in mind for detecting frame errors? Assuming the peer (the SPI master) reboots for some reason in the middle of a transfer, how would master and slave ever synchronize again?