Lab Notes: Yet Another PETI Display Refactor
Last Updated: 2022-03-03 09:30:00 -0600
Was there a firmware update to PETI? I must have done a refactor of the Display driver code. It’s sort of a tradition at this point, but to be fair it’s not the totality of the 0.1.0 firmware update. Let’s see what’s new.
Display Refactor: Introducing Multi-Font Support, Kinda.
Last time, I posted about a potential display refactor for PETI, and I’m happy to say that for the most part it went extremely well. To be brief about it, it involved changing the way directives are handled.
The old method used directives of a fixed value to specify a particular modification (or lack of modification) to each character’s data in a given line of text; color inversion, a horizontal mirror, or both. The new method retains that functionality, but adds additional capability by having the directive also specify which of 16 hypothetical fonts available to each print function will be used to get that specific character’s information.
For developer convenience, instead of memorizing a directives table, the directives have also been split into summable nibbles - instead of needing to remember that
0x10 would be FONT_0 with no modifications, you can actually specify the directive as
FONTADDR_0 + DIRECTIVE_NORMAL. Extremely convenient in my view.
At the time of writing this is only explicitly checked for in the case of the large-text print function, since that’s the only place the character table has become constrained. However, directives are always specified for all rows of text, and while not supported/interpreted in the small print function (which is only used in two places), the medium text function has been updated to parse the new directive types as well, and all scenes have been refactored to use the new logic. Which brings me to…
Introducing - then killing - our first Bricking Bug
Software bugs are nothing new. It has been said that the process of programming is introducing bugs into a blank text file until you get the results you want. However, in the process of running the refactor into all the different scenes which use it, I created a new type of bug I’ve never run into before, which bricked the firmware whenever it was triggered by going from the debug menu into the stage-of-life selector menu (more on that later).
I have to tell you, too, squashing this bug wasn’t easy at the time. Stepping through execution with the debugger made everything appear to work fine until it simply suddenly didn’t. The Debug menu correctly set the scene value, breakpoints in the scene that controls the stage selector were never reached, and all code execution seemed fine until we reached the call at the end of the main loop that puts the device to sleep, whereupon the debugger showed we spiral off into the bootloader, and nothing short of flashing would get us out of it.
I pulled my hair out on this for an hour or so the day I broke it, and then on and off again a couple other times, until some inspiration struck and I drew the main program loop (and some branches) out on a whiteboard and made a point to color-code the steps I knew to be good, came from third-party code that hadn’t changed, and hadn’t fully validated.
That was enough to let me set up two simple tests based around my two hypothoses:
- Was there some kind of overflow or stack corruption happening in the debug menu? To disprove this, let’s set the same menu option to go to a different scene instead of the scene selector.
- Was the scene selector doing something illegal? Let’s set it as the boot scene and see what happens. (Reader: The device seems to never boot).
These two experiments took less than 10 minutes to run, and pretty clearly indicated that the Scene Selector itself was at fault, contrary to what the debugger otherwise seemed to indicate previously (because we were never hitting our breakpoints inside that scene)
The issue turned out to be in a chunk of code I had dismissed as “validated” because it worked in the code I’d taken it from - the menu generator scene. Since that chunk of code was already “validated” in my mind, I had placed my earliest breakpoints after it, which was why they were never hit. One function call had to be tweaked slightly in terms of its name and on the next compile everything worked fine.
There’s a lesson here about walking away from problems you’re stuck on for a bit of fresh perspective and a recharge, but instead of cribbing it badly, I’m just going to recommend that you read Zen and the Art of Motorcycle Maintainance by Robert Pirsig. If you can’t sit through the whole thing, do yourself a favour and read at least Chapter 26.
Dev Quality of Life Perks
Speaking of the debug menu, I’ve made a few small improvements to debugging in general on PETI. In addition to a debug menu full of features and the stage selector (I know, I know, we’re going to get there), I went ahead and added support for using one of the hardware switches on the Rear Expansion Board to take the device in and out of debug mode, which:
- Makes the debug menu available, and;
- Skips the “egg” stage at the beginning of the game.
As time goes on I’m going to use the debug mode flag judiciously for other improvements, and probably hide other utilities in the debug menu that tickle my brain as useful during testing. We haven’t had a big focus on gameplay testing yet, but after the 0.1.0 firmware comes out, a big focus is going to be on QC for gameplay itself.
Improved Replacement to the Demo Mode
Previously to 0.1.0, there was a whole extra set of print functions held around for the purposes of a single scene called
demo_mode.c, which existed for no reason other than to tab through it and view characters in different stages and different active animations.
The display code for that scene was so idiosyncratic that I skipped refactoring it in 0.0.6, which required me to keep both the enhanced and unenhanced print functions around. Instead, I’ve replaced it with a special menu, which presents the user with a localized list of all available pet stages and then simply overrides the game state to think that it’s in that stage! It’s rather brilliant, actually, and I’m very happy with the way it works.
There’s actually a fair jag left, both in the project and, arguably, before the release of the 0.1.0 firmware and the accompanying release of the PETI dev kit:
- The power management bug remains to be solved. As it’s a hardware bug, I don’t have a lot of ability to simply fix it in code. I’ve identified a few candidate parts but I’m stuck waiting to order them, at which point I’d have to break everything out onto breadboard, test it, then order revised rear expansion boards and assemble them. On the whole, this process will likely take several weeks, assuming cost itself isn’t an issue, which could go either way. That said, a fix here is essential and will offer up some new functionality.
- The deprecated print functions and display code have to all be pulled out of the display driver to save space.
- The metanimations data in the evolutionary stages structure needs to be updated. Right now, many stages of life do not have working animations. This needs to be corrected at some point, and now is as good a point as any to do so.
- Technically, all structures that hold graphical data should probably have a member added to them to specify a font address. Since no second font is currently implemented, I’m on the fence as to whether or not to break that out for 0.1.0 or save it for a future update.
- The service manuals for the development kits need to be completed. While most of the copy is written, it was written for two firmware versions of functionality ago and need to be updated. The source code printouts need to be updated, and several sets of images need to be either created or updated to match the new reality, including the schematics.
- Packaging decisions need to be made and solved. Obviously PETI is a physical good and the dev kits are no exception. I need to come to terms with the best ways to assemble, box, and ship these kits since several of the people who expressed interest in having them wanted them in an assembled condition, which also means;
- Logistics decisions in ordering components and fabricated boards need to be made. I have four spare, valid boards for the front. I need to figure out how large the initial order of dev kits should be an order an appropriate number of controller and rear expansion boards, along with all the components needed to assemble them - at least, all those which I don’t already have in bulk.
PETI is a major project intended to design and construct a virtual pet from Open Source Hardware and Software, and to encourage others to modify and tinker with similar projects. If you would like to support the development of this, or any of the other projects I’m working on for Arcana Labs, and you wanted to show your support financially, your best avenue is via my Github Sponsors account or by making a one-time donation to Arcana Labs via Ko-Fi.com or through other avenues detailed here. Github Sponsors also get access to a special patrons-only section of the Arcana Labs Discord Server, where we talk about the ongoing super-secret project.