Welcome to my 3rd and probably last post on the Good Times timer. I want to write about the pieces of flair I put into it.
This project was for my wife, and the timing of the project happened to be late November last year, so I decided I would make it Christmas gift, and I stopped showing her progress on it.
Of course, I had to add some Easter eggs to the project :)
This last part really added no meaningful value to the final product, but added fun geek factor and also helped in debugging.
The main application already had a "mode stack" system, and adding new modes were as easy as deriving from a base mode class, and pushing an instance of it onto the mode stack from an appropriate key handler callback of another mode. (This is in general how the logic flow of the user interface worked) All of the Easter eggs were just new modes added to the system.
A secret menu is entered by cycling the time entry to 00:00 twice using the +0:15 button and hitting "play". you then could press one additional key to enter one of the easter egg modes.
I had three secret modes:
- "Piano mode". each key plays notes, and I display the note's name
- "Play song mode". usable to play any of the 8 built in songs (this was really helpful for encoding the songs, since in normal use the songs are selected randomly)
- "Dodge Game". A mini game where you must dodge obstacles.
Video of easter eggs.
Another area that worked out nicely for adding the dodge game was how the display system was setup. From a high level, I treated the display as a 32 bit number (4 * (7 segments + 1 decimal point)). I had utilities that would encode a numeric time value into a bit pattern, and I also had a set of canned words. I think just "bit banged" that pattern out to the shift registers that drove the display. I could also just manipulate individual bits in the display and that is how I did the dodge game with routines to "draw" the ship and obstacles into the bit pattern. The game tracks your score, as you can see in the video, and also has a progressive difficulty system where obstacles move faster over time. The indicator lights also reflect the difficulty level going from green->yellow->red as it gets harder.
I decided to make a product manual for it with copious tongue-in-cheek corny humor my wife knows and loves me for.
Here are a few selected pages from it. (I changed the name to "The Pedantite Foundation", for this blog. It's a running joke in our house that we run "The <our last name> foundation", I've even used that on survey forms, so I get junk mail addressed to that organization).
We've been using the timer with my kids for a few months now, and my wife has a couple feature requests. She wants a audio warning when the timer goes green->yellow, since my kids often interrupt what they're doing to "see if it's yellow yet". And, it currently always plays Beethoven's Fifth on start-up. That's gotten old, and she wants it be random, like it is when the "Times up" alarm plays. This one I have to think about, since I actually store a seed for the random routine based on timer ticks whenever a key is pressed. I could possibly store a seed in EEPROM for next boot.
Luckily, firmware updates are easy because I built-in a JTAG connector for the 644, as well as a 6 pin ISP connector for the 2313.
My trick for initializing a pseudo-random seed is to do an analog read from an unconnected pin.ReplyDelete
Ah, yes, I should post a follow up. I implemented my wife's feature requests since I posted this. I tried successive digital reads from an unconnected pin. I don't remember if I tried an analog read. I found that the digital read for whatever reason seemed "sticky", the same bit pattern seemed to come up often. I think (it's been a while) what I did was my original idea, I wait for an initial key-press, and store a new seed based in one of the timer counters.ReplyDelete
I should add that we still use this thing almost every day. I struggle to come up with a new project idea that could match the utility of this. Then again, my wife was the one who came up with the initial suggestion.ReplyDelete