I’ve been getting lots of good ideas from the smart guys over at Parallax. They are throwing out a variety of methods and ways I can get this job done. I will say that I’m a little overwhelmed at the pure number of ways to attack the problem. I’m glad there are multiple ways, but this allows me to instill doubt in the current method, and leave an easy way out. It’s easy to say, “oh this isn’t working, forget about debugging it, and just switch methods”
I now have at least 5 different versions of code written by different people, but which none of them currently work. I then, of course, have my own version of code which is the only version to have yet produced any valid data whatsoever. And so I’m partial to my own code. It’s easy, simply, straight forward……..and its not in assembly. Which I will say, however, that I’m getting much better at reading it since all these versions of code are in assembly.
Some of the different methods presented are:
Two interrupt sources:
mine (in SX/B): the ISR handles both the edge detection (via wkpnd_b) and the timeout condition. The main code handles PC communication solely. All shifting happens in the ISR. Edge triggers the ISR.
I actually have several different versions that handle it all sorts of ways, but the only version to produce any results is this one.
Peter’s: the ISR handles both edge detection (via RTCC values) and the timeout condition. All shifting done in the ISR. Main handles PC communications only. Edge triggers the ISR.
His version is very similar to mine in overall layout, although I’m sure his is much better done. This is reassuring though, because this was the method I ended up choosing — he determines an edge differently from mine, but the overall idea is the same.
Michael’s: the ISR is triggered both by timeout and by edge detection. ISR handles the shifter. Main handles the PC communication only.
One Interrupt source:
Guenther’s: ISR triggered only by RTCC rollover. The ISR keeps track of the number of interrupts that have occurred between edges. ISR handles PC comm. Main polls wkpnd_b for an edge and does the shifting. Similar method suggested by Jim P.
Brainstorming indeed. I just have to figure out what’s going to be the best method.
I’d be thrilled to debug my code and get it working. I have to sit down and list the possible things that could be going wrong, and design tests for them to rule them out. Since other’s code is similar to mine, and the fact that it is producing some data is encouraging. It tells me I’m not entirely on the wrong track.
Some questions on my code might be:
1. Are we missing edges because we spend too much time processing a high, which is a very common and regular task. Edges are less frequent, but more important. Losing an edge causes us to lose at least one ‘0’, and potentially up to three ‘0’s — because the SX will think we’re idle when we are not.
2. Is our rollover not happening at the right time? For instance, is a rollover happening too close to an edge, which further complicates problem one? It complicates it because if it samples too close to the edge, then we’re in the ISR during an edge event, and so the interrupt doesn’t re-fire. And then, we only detect the edge has occurred as result of entering the interrupt from a rollover which is BAD BAD BAD because we should be storing a ‘0’ at that point, not an edge. We should never sample an edge or a low during a “0”-cell.
3. Does the PC perchance get overwhelmed with the flow of data, and because of multitasking, etc start dropping bytes? My code currently wouldn’t notice this —- and this wouldn’t effect new data…
I guess what I really need to do is start writing more checks into my code that will generate a breakpoint if one of these bad things happen. Run the real-time debugger, and see if it breaks someplace.
It all comes down to timing, and this is why I have pjv really reviewing my code for timing issues, etc.
If your traditional (and most pregnant :)) approach used two interrupt sources, have you thought of disabling other interrupts while in the interrupt handling routine?
I mean, if you’re processing one interrupt, e.g. edge, there probably won’t be much sense in reacting to/processing the other (RTC rollover), and vice versa.
Well the SX automatically disables interrupts while you are in the ISR. and the SX doesn’t support interrupt queueing. If you are in the ISR, and another reason for an interrupt occurs, absolutely nothing happens.
The reason why this is bad, of course, is that in the event of edges, if I’m in the ISR during an edge event I “miss” that edge event, unless I have a check for it someplace else. Or perhaps the next time an RTCC rollover happened, it would sense an edge.. As you read above this is bad.
The general approach,I think, is just to prevent that from happening(via getting your timing perfect), or turn off edge-detection-isr-triggers, and check the edge register from the main program, etc.
I wanted to answer a couple of the questions that I put to myself earlier.
1. Because of the SX/B overhead in ISR processing, plus the time it takes the SX to react, it takes roughly 400ns before I sample the pin. What this tells me is that the input signal could already be up again, and I missed sampling the edge. I still know an edge happened because of wkpnd_b, but I can’t double check this easily. If I can sample right at the interrupt that might be much better.
2. Our rollover is happening at the right time. I actually sample the pin (instead of just realizing its a rollover event), and then if it’s zero here (it should be a one) I BREAK. I ran tons of data through it and it didn’t break once. This tells me our rollover’s are happening at the right time. Now there is a delay between the rollover, and sampling the pin — it’s about 280ns or so, but this should be good enough. If I can find a way to modify the assembly to have it sample immediately and stuff it in a variable, I’d like to check this further. Also, I’m going to through another sample at the end of the ISR processing and double check it!
3. I’ve completed trimmed the PC side down to the absolute bare minimum. I think this is as fast as I’m going to get it without having to rewrite DLL’s on the PC side which I don’t want to do.