While my send UART code has been pretty solid for some time, I’ve always though my receive uart code needed doublechecked and worked on.
I spent some time today just going through the code, graphing out some timing diagrams, checking my cycle-counts and so forth. The RX uart code is actually pretty good. There is some minor jitter in detecting when the startbit actually falls, but it is on the order of a couple cycles. Depending on exactly when the start bit happens, it can either take 2 cycles or 4 cycles. This is only a difference 40ns, and I’m not horribly worried about it.
I still want to do some type of stress test on it because I don’t want this to be a source of problems if I ever decide to implement writing as a feature.
Ok, so I tested my receive UART last night.
On a small sample, I averaged 760.9ns for the first sample in the first bit.
If the start bit ends at 500ns, and the first bit ends at 1us, then 750us is the exact middle of the first bit. I was within 10ns on average which is pretty good, considering all the instructions are 20ns instructions!
The jitter comes from the fact that I continuously loop checking for a high-to-low start bit transition. Depending where in that loop the transition occurs changes how long it takes for the loop to react.
Simply put, if the lead is low during the first pass of the check, then it reacts within +/- 40ns. If it was high during the first check, and has to loop, checking again, it’s roughly 80ns + 40 ns or 120ns.
While I doubt I knew this, or accounted for this earlier, my existing delay code is pretty darn perfect. And then, of course, the samples all occur 500ns later, sampling (hopefully) in the same place on each bit.
With a nice discussion I had on news:comp.arch.embedded, I think I can easily implement false-start detection and maybe majority center sampling. Just for robustness. We’ll see.
I did some indepth digging tonight on the RX uart code. Set up a debug output pin to fine tune where the uart was sampling the received data. Got it very close to where I’d like it. Seems to be working well.
I was trying to come up with an easy way to really put it through its paces, but heck if I can come up with a way of testing it — at least within the current framework.
Someone on the usenet newsgroup brought up a good point. Since I would store the byte right after receiving it, I really have to make sure that my sending routine delays enough to give my SX a chance to receive the next byte. so who knows, maybe I’ll integrate the live-write feature where the bits are written to memory as they come in the port. or something like that. 2mbps is plenty slow enough for the memory to handle, so it should be pretty easy just to pipe the bits to my serial fram.
the false start detection is basically just to prevent noise from triggering a receive, but I probably dont have any existing noise sources now. I want to make this thing more robust, but not add unnecessary code. I’ll have to think about the next steps.
anyways, for tonight, at 4:51am local time, I’m pretty happy with the UART code as it stands. Fine tuning with the logic analyzer is the only way to go although at first I ran into Heisenberg uncertainty principle aka observer effect on this. When I added code to view what was going on, this threw the timing off and then my code didnt work anymore. once I adjusted timing for it, then it was ok. I knew it would throw off timing, but i didnt think enough to cause problems. i was wrong. 🙂
see
https://en.wikipedia.org/wiki/Uncertainty_principle
for more info. 🙂