Propeller Serial with Tight Byte Spacing
SRLM
Posts: 5,045
I'll start with my problem: the new version of the RN-42 Bluetooth (firmware v6.15) seems to have a different serial driver where it spaces the bytes very close to one another. In the old version, if I sent a byte every few milliseconds I'd get a nice empty space between bytes:
(it's the middle channel that is of interest)
Now, with the same transmission the new RN-42 Bluetooth outputs the bytes very close together. In fact, it appears to be at full baud saturation:
(it's the top channel that is of interest)
Notice how there is almost no gap between bytes from the new RN-42. I'm using FDS1 as my Propeller serial driver and it can't handle the bytes being so close together. My question is:
Is there a serial driver that can handle the full saturation of the RX channel?
Preferably it's a duplex serial driver, and can run at 460800 baud. I know there are other options (transmit the bytes with a delay, change to 8N2, etc.) but that's just masking the problem (slow serial driver).
(it's the middle channel that is of interest)
Now, with the same transmission the new RN-42 Bluetooth outputs the bytes very close together. In fact, it appears to be at full baud saturation:
(it's the top channel that is of interest)
Notice how there is almost no gap between bytes from the new RN-42. I'm using FDS1 as my Propeller serial driver and it can't handle the bytes being so close together. My question is:
Is there a serial driver that can handle the full saturation of the RX channel?
Preferably it's a duplex serial driver, and can run at 460800 baud. I know there are other options (transmit the bytes with a delay, change to 8N2, etc.) but that's just masking the problem (slow serial driver).
Comments
thanks,
Jonathan
Hmmm. I was afraid of this answer. Any suggestions on a half duplex driver that I can use?
Yep, I'm actually using that version right now (at least the assembly portion. I have a C++ portion sitting on top). And I'd like to say thank you! It works great for nearly everything, and I like the code. There aren't any corrupted bytes, just missing bytes.
I have my serial driver running at over 3M baud in Tachyon. I could extract that and turn it into a Spin object and add in a transmit section to complete a high-speed half-duplex driver. Would that do?
Does it do RX? That's mostly what I'm interested in here. If yes, then that would be useful. Thanks!
thanks,
Jonathan
The critical step is not the bit to bit timing, but the time from the detection of the last data bit to the leading edge of the next start bit. Time for housekeeping and a couple of hub writes.
I'll attach my rx object (HSLP=HighSpeedLowPower). It is similar to Jon's, but the buffer size is unrestricted, up to available memory, and two hub writes instead of 3 in the wrapup. I'm curious how Peter gets 3Mbaud with writes into a hub buffer.
Hi Tracy, I just scoped my 3M operation and it looks like it has a lot of gaps there when I paste into Minicom, however when I do an ASCII file transfer it really packs it together tight with only one stop bit and I definitely lose stuff. I'm not too worried about this at 3M baud because I get the serial cog to also process the data a bit before it writes it to the hub. Testing this at 230400 baud there is no problem of course.
Repeating this at 460800 I have dropouts but then again I am doing this additional processing by filtering out whitespaces etc and recognizing command sequences and break detection etc.
Again at 460800 with 2 stop bits and leaving in the preprocessor it works fine. Removing this will mean that it should work find at 460800, I can't see any problem with that.
Cheers,
Peter (pjv)
You should post the link then. I know if I skip reading and writing the buffer write index and simply write the data to the buffer then this speeds things up to. However software that needs to access the buffer needs to know where it's been written to. I take it you are referring to asynchronous reception where you need to wait for a start bit that can start anytime asynchronously as this is the part that can also cause timing problems at high speed vs synchronized (even with a "start" bit) bit-rate specific such as 5MHz being derived from the Prop's cycle time and especially if you are just handling a fixed block before updating hub variables etc.
-Phil
Yes, but skipping the stop bit altogether can prove a disaster as async streams can get out of sync with glitches for whatever reason plus they all need at least one character gap to help resync to the real start bit. So typically the stop bit is checked half-way through to confirm it's right otherwise I take that as a framing error or wrong baud rate or part of a break if the data was also zero. Certain protocols allow you to store the data much faster in cog RAM as the packet is of specified size so all the slow hub stuff can be done afterwards.
As far as I recall, Phil has the right idea. I store the data when the stop bit is sampled, and then immediately start searching for the falling edge of the next start bit.
The next character can start at any time, not necessarily on "even" bit times. It is fully asynchronous.
Just now I can't recall what happens at speeds just below 5 Mb/s as it has been optimized to hit the hub access sweet spot.
To avoid these link issues in the future, perhaps I should find a place in the OBEX to put it. I have never done that before.
My apologies.
Cheers,
Peter, (pjv)
Here's the snippet:
Detecting the stop bit means that the decision to put the char in the buffer (or not) has to wait until halfway through the stop bit. That leaves less than 1/2 bit time to take care of all the housekeeping, writing the data and head pointer back to the hub. On the other hand, by skipping stop bit detection that leaves more, something between 1 and ~<1.5 bit times to take care of business.
Two hub writes with two intervening operations to hit the sweet spot are going to take 23 to 38 clock ticks. Add a 4 more instructions for shifting or muxing in the final data bit, updating the head pointer and for jumping to start bit detection and you have to allow at least 54 clock ticks. (I allowed 66 ticks in mine for a couple of instructions that could be cut if I borrow from Jon's driver and did more patching in the init code). Give it 60 clock ticks for leeway, baud mismatch etc, at 80MHz clock it adds up to 0.75 µs. If that is 1.5 bit, you have 0.5µs per bit, or a baud rate of 2 MBaud. No doubt that could be faster if it can use a cog buffer instead of a hub buffer.
But i notice that another situation creeps up were another "save" is made in software.
I wonder if there was just a couple of simple, well though out shift registers in hardware, how much better serial protocols might be handled and the standby UART would not have to be modified every three months.
If the shifter was thought out it could be used for UART, SPI, I2C, NRZI, USB, Ethernet, Manchester, Group codes, etc. with just a small amount of software like the video shift register is used for TV, VGA, Sprites and others.
Just wondering.
cheers,
Rich
Your wondering is not unprecedented in this forum. The subject has come up from time to time, particularly in regards to the dev efforts surrounding the Prop II. There is a segment who believes that universal hardware shift registers are as fundamental as universal counters. Another segment believes that such hardware is unnecessary, since the software can do everything adequately. If you're interested in perusing the opinions of these various factions, go to the Propeller 2 forum and read some of the dev threads. I'm sure you will be entertained!
-Phil
There is another method I could use and that is to only write once to the hub for every character but that would either mean using two bytes as a WRWORD with one as flag or else encoding the 8th bit of the character so that a buffer read could work out if it's an unread character etc. So this means that the general-purpose routine could be used up to 3M baud at full throughput but it's either limited to 7-bit ASCII or uses double the receive buffer memory.
For the moment I can handle 3M baud with only a single stop bit between characters but the 3M receive is a separate routine using instruction timing (hack).
Because this is Rx only, and there is very good lock to the start edge (much better than a /16 or /8 Uart), there is scope tosqueeze a little more out of the rate, by using that better start precision as skew at the end.
ie you sample deliberately a little fast, so you buy more time between the critical stages at the end.
It is also not vital to sample Stop at exactly 50%, it could start sample from 60~75%, to still avoid clock creep issues.
The FT232H has a virtual Baud clock of 96MHz, so if this fast link is talking to a PC, there will be some better matching Baud choices. FT232H clock precision, is very good, as they use crystals, and so too usually does the Prop.
I looked at different methods including sampling early but none these help as it's the time between the last data bit and also the stop bit that's critical which is why I even have used a different bit time for start and stop bits (applied at last data). Writing the data before the stop bit is okay as it's not accepted as a new byte in the buffer until the write index is updated. The single write method could wait until the stop bit is sampled early but still takes up to 23 additional cycles and at 26 cycles at 3M there's only 13 cycles for a stop bit verified at half bit time until another start bit. I think that it's more than good enough to handle 2M rates with one stop bit between characters and allow 3M with 2 stops bits. The end result is that we are assured that the receiver will capture all data up to 2M whereas most forum members rarely venture beyond 115.2K if that.
http://forums.parallax.com/showthread.php/120125-5Mbit-sec-ASCII-streaming-from-to-Hub-RAM
which seems to be the critical point,
could be delayed to in between receiving of the next char?
Unfortunately we don't have the wait with timeout yet, that is coming with the prop2.
For some communication like lines ended with CRLF it might be ok to get the last char only at the next burst ...
As I suspected like Beau's 14.5M baud serial object this one too is not adjustable or general-purpose and is in fact very specialized for same frequency Prop to Prop coms. An asynch serial object needs to be able to be programmed for any usable baud rate and receive characters at any time in a continuous fashion. I have used a variation of Beau's serial driver for fibre-optic communications which is DC balanced and runs at a continuous 10Mbit data rate but that is all I can use it for.
I think the nops you are seeing are simply part of the 3 Mbaud only hack (receive3) and not the general-purpose code (receive) which is limited to around 2 Mbaud max. At this speed trying to test for special end conditions etc would make the code unreliable however the code works reliably up to 2M baud without a hitch.
The code I posted three years ago was not intended to be a universal speed programmable model. It was a response to a need of "fastest serial ASCII link" that I had for an industrial application, and I just thought I would post it in case there was interest in the subject. There seemed to be none. Regrettably it also appears not to meet your requirements....... but luckily there are many others to choose from.
Cheers,
Peter (pjv)