Wednesday, 6 March 2013

In Which The Keyboard Reawakens


I had considerable success re-integrating and refining the cursor logic, stripping six or seven fairly ugly routines out and streamlining everything down to just four tidy bits of code to set/read the cursor screen co-ordinates, calculate the bitmap draw address based on those co-ordinates (re-using the new fast address-computation routine I wrote for the revamped glyph renderer), turn the cursor on/off, and do the actual draw/undraw. I was so pleased, in fact, that I decided to press ahead and tackle the unruly mess that the keyboard handler had evolved into right away.

The basic mechanics are of course still the same - set-up the VIA ports to strobe the keyboard lines and detect any activity, then decode whatever we found into meaningful data (either a 'displayable' character code, or a control code indicating keys like return, shift, control, and so on). The problem I'd run into last time was that I kept finding edge-conditions where the general rules didn't apply, or at least didn't apply in quite the usual way. For example, I needed to debounce the keypresses as they came in to prevent keys repeating at the IRQ frequency, but then I also needed to be able to enable key-repeat at a sensible rate - so my general rule, which eliminated accidental key-repeat due to the frequency of the keyboard scan, needed a bit of extra logic to handle the fact that we actually wanted to time the keypress duration and allow repeats after a given interval, and then only at a much slower rate than the IRQ could generate them. This turned into a series of unpalatable kludges around the basic functionality, and - in combination with some other similar issues - was the key contributor to my unhappiness with the project, and its' suspension.

The root cause was the design of the code - I'd never written a bare-metal keyboard handler before and there was a considerable amount to learn about the way the 6522 worked, how Commodore had wired things up, how XVIC catered for that hardware configuration inside its' emulation environment, and then just the general software-layer intricacies of managing a keypress-management state-machine that operates in a linear fashion but spread across successive interrupt cycles. Although things started-out quite cleanly, the evolution of the logic through the learning process meant that the routine became more and more unmanageable as the number of exceptions-to-the-rule grew. In the end I was sick of the sight of it - which is never a good frame of mind to be in about your own project!

But the payoff to a difficult learning process is that once you come out the other end of it, however nasty the result you've got, you've also got the fundamental understanding of how to do it better the second time around - and that's where I am today, slowly rebuilding the keyboard handler using the basic technique I mentioned above but now aware of, and avoiding, the glitches that cropped-up last time. So I have the VIA set-up, doing key-detection and debouncing, and an initial stub routine just spitting characters to the screen as they're registered. I changed the way keycodes are mapped to be a lot more efficient in terms of table storage, so I have to revisit the lookup table to re-arrange things a little (at the moment the character that appears on-screen bears no relation to the key you press) and then I can plug-in a neat little bit of code I've got an idea for that'll handle selective key-repeat.

I think, even though I haven't completed the to-do list for the release, I might make a demo available at the point the keyboard handler is at a stable position; better late than never. ;)

No comments:

Post a Comment