I kept working on this project, and quite frankly struggled a bit. When I first imagined this project, I thought that I would make a sort of modal clock: it would alternate between showing:
- the name of the event ("half life day", which nicely can be rendered legibly on a 7 segment display)
- the current time and date
- the number of days remaining until the event, in days, hours minutes and seconds.
When the time went down to zero seconds, I wanted to trigger an external event (perhaps to blink some lights, or sound a beeper).
I did a couple of rounds implementing all the functionality, and ended up with a not-quite-fully-functional prototype that was close to 1500 bytes. I did battle with it in a number of different ways.
The key components of the design are the TM1640 based 16 digit 7 segment display, and the DS3231 I2C clock module. To make this work, we need drivers for both. Luckily for me, Peter Fleury did a lot of heavy lifting with respect to the I2C bus. I used his i2c library:
which uses the TWI (Atmel-speak for I2C) hardware on the atmega328. It's compact and easy, and is quite compact. Interfacing with the DS3231 only takes a couple hundred bytes.
I took some time to read the Titan Micro data sheet for the TM1640. It's pretty simple too: a couple of hours reading and tinkering resulted in the very minimal amount of code that I needed to drive the display.
Together, combined with some of the library overhead, I ended up with about 630 bytes of code for both. That left me just about 400 bytes (less than 200 instructions) to implement the rest.
The basic problem that I had was that the clock module presents its data in BCD form. That's fine if all you want to do is display, but I needed to compute the number of days until my target date, as well as the number of hours, minutes and second until that date. The Atmel doesn't support BCD arithmetic, which made all of these calculations difficult. I worked out the algorithms, but attempts to squeeze them was clearly getting me no where.
It wasn't going to happen. I went to bed frustrated.
But in the morning, with some patient urging from my wife, I rethought the project as a whole. What could I do that could be coaxed into fitting?
Basically, my clock became a calendar.
It would still read the time from the clock module, and compute the number of days until the target date.
- Before the date, it displays "XXXX daYS to", and then "haLF LiFE dAY"
- On the day, it will display "todAY is", "haLF LiFE daY"
- and after, it will display "haLF LiFE daY", "haS PaST"
On the day of the event, it will also enable an output pin to trigger some kind of remote action. I've got some 10mm blinking red LEDs, but I'm also thinking of wiring a small motor with a flag on it that will wave on the day. I'll probably avoid audio signaling, since ultimately this will sit on my desk at work, and I don't want to overtly disturb anyone.
Another hour of working, and I tweaked it down to just 387 lines of code, and 986 bytes of firmware. Over the next few days I'll work up a YouTube video to demonstrate it, and try to get it mounted into a permanent case.
I'm actually kind of pleased with the edited result. I learned a lot about trying to squish down C code for the AVR architecture, and the countdown calendar is actually pretty nice.
In the meantime, I've placed the code (which I consider reasonably complete at the moment) in my github account. I haven't actually tested the "alarm" functionality, but it's straightforward, so I have some confidence. I'll work on some documentation and hope that someone finds it useful.
A slight annoyance is that I was trying to find a link to a supplier for the LED displays. I've had a couple of these in my junk box for a while. I think I ordered them from deal extreme.com, but I failed to find a link to them, so reproducing this might be more difficult than I had imagined. I'll keep on the lookout.