[Contest] RIOT Clock
Posted: Thu Jan 16, 2020 12:09 am
Project Aims:
Make a nice and useful clock to hang on the wall. It needs to keep accurate time (as good as my watch), be readable from a distance, easy to set, and have a countdown timer function for kitchen utility; perhaps an alarm function as well. Preferably incorporating more than one simultaneous timer, as many kitchen projects have overlapping processes that need timing independently.
Oh, and I'd like it to chime and strike the hours, too. That'll be the fun part.
Central Logic:
I'll probably use a modern 8Kx8 EEPROM, but only 2KB of it, and design the socket so that a correctly programmed 2716 can also be used. The RIOT contains enough RAM for the task by itself. The RIOT's timer is not really suited to running a clock with long-term accuracy, so I'll delegate that task to a DS1501 RTC, which also contains a small NVRAM and supports keeping time from a coin-cell backup battery. This means the power outages I occasionally have won't disrupt timekeeping. Instead I'll reserve the RIOT's timer for the chime function. Since I don't need a lot of computing power for this, I may divide a standard 1.8432 MHz UART crystal oscillator down to 115.2 kHz, just above the reliable minimum speed for an NMOS 650x.
Display:
For readability at a distance, I would either need a rather large LCD panel or an LED display, unless I stumble across a way to implement computer-controlled clock hands. This is likely to be the most expensive part of the system, in any case. Absolute minimum requirements would be a four-digit 7-segment block, but it'd be nice to show seconds, day and date, lunar phase, and an auxiliary display for the kitchen timer function. Fourteen or sixteen segment digits should work well for day-of-week and month-name abbreviations. Figuring out the best way to hang so many LED segments off the RIOT will be a large part of the challenge here; there are a number of LED driver ICs that can be driven serially, which will seriously help.
My family's grandfather clock had a lunar-phase dial which I never remember having been in working order, but I've worked out a way to calculate it even on as tiny a machine as this.
Input:
Hold down a button to select which item gets adjusted by a rotary encoder, the latter needing just two input pins to handle. Six buttons could cover year, month, day, hour, minute, second. Day of week and lunar phase would be calculated, not set. Two more buttons would be available from an 8-to-3 priority encoder, and could be associated with the timer function. Of course I could cascade a second button encoder if I needed more buttons. I still need to work out exactly how best to implement the timer interface here, given that it will get used much more often than the clock adjustment.
Chiming & Striking:
A striking clock is one that counts the hours on its bell; technically a cuckoo clock fits this definition. A chiming clock is one that precedes the strike with a tune, and usually also chimes the quarter-hours. Several different chimes are popularly used in clocks, generally implemented on eight bells representing a major scale, as a set of five musical phrases which end up being played twice an hour (the quarters being phrase 1, then 2-3, then 4-5-1, and finally 2-3-4-5). Characteristic of this process is that each bell reverberates for some time after the next note has been struck, and indeed after the complete chime has finished.
I've worked out a reasonably simple circuit to produce a decaying tone, crudely simulating a physical bell. Nine of these circuits ganged together can implement a major scale plus a separate striking bell, with appropriately independent reverberation; these will be followed by a pair of op-amps to implement a filter and drive a speaker. The bells can easily be driven by one of the RIOT's ports, via a '138 decoder to reduce the number of pins required.
At 115.2 kHz Phi2, the RIOT can time an interval of up to 2.267 seconds (1024*255 cycles) without special effort. This is just about perfect for timing out a chime and strike sequence.
Software:
Most of the time, the job is just noticing when the RTC registers change and updating the display to match. The RTC can be configured to produce a 1PPS signal to facilitate this. This job gets modified when the countdown timers are active, as the 1PPS signal now also needs to decrement the timer and compare it against zero. Additionally, the display still needs to be updated when a chime sequence is active, even though the chimes will take several seconds to complete (and I don't want them rigidly synchronised to the seconds). The process of setting the time may also expose some corner cases.
The 2KB ROM essentially precludes the use of any high-level languages or even VMs. Which is fine by me; I've made sure some of the RIOT's RAM is mapped for use as a stack, precisely so that I can still use subroutines sensibly. This is also one of the relatively few serious uses I expect to make of the 6502's Decimal mode, as that's what the RTC chip uses and it's convenient to not have to convert it for display.
Make a nice and useful clock to hang on the wall. It needs to keep accurate time (as good as my watch), be readable from a distance, easy to set, and have a countdown timer function for kitchen utility; perhaps an alarm function as well. Preferably incorporating more than one simultaneous timer, as many kitchen projects have overlapping processes that need timing independently.
Oh, and I'd like it to chime and strike the hours, too. That'll be the fun part.
Central Logic:
I'll probably use a modern 8Kx8 EEPROM, but only 2KB of it, and design the socket so that a correctly programmed 2716 can also be used. The RIOT contains enough RAM for the task by itself. The RIOT's timer is not really suited to running a clock with long-term accuracy, so I'll delegate that task to a DS1501 RTC, which also contains a small NVRAM and supports keeping time from a coin-cell backup battery. This means the power outages I occasionally have won't disrupt timekeeping. Instead I'll reserve the RIOT's timer for the chime function. Since I don't need a lot of computing power for this, I may divide a standard 1.8432 MHz UART crystal oscillator down to 115.2 kHz, just above the reliable minimum speed for an NMOS 650x.
Display:
For readability at a distance, I would either need a rather large LCD panel or an LED display, unless I stumble across a way to implement computer-controlled clock hands. This is likely to be the most expensive part of the system, in any case. Absolute minimum requirements would be a four-digit 7-segment block, but it'd be nice to show seconds, day and date, lunar phase, and an auxiliary display for the kitchen timer function. Fourteen or sixteen segment digits should work well for day-of-week and month-name abbreviations. Figuring out the best way to hang so many LED segments off the RIOT will be a large part of the challenge here; there are a number of LED driver ICs that can be driven serially, which will seriously help.
My family's grandfather clock had a lunar-phase dial which I never remember having been in working order, but I've worked out a way to calculate it even on as tiny a machine as this.
Input:
Hold down a button to select which item gets adjusted by a rotary encoder, the latter needing just two input pins to handle. Six buttons could cover year, month, day, hour, minute, second. Day of week and lunar phase would be calculated, not set. Two more buttons would be available from an 8-to-3 priority encoder, and could be associated with the timer function. Of course I could cascade a second button encoder if I needed more buttons. I still need to work out exactly how best to implement the timer interface here, given that it will get used much more often than the clock adjustment.
Chiming & Striking:
A striking clock is one that counts the hours on its bell; technically a cuckoo clock fits this definition. A chiming clock is one that precedes the strike with a tune, and usually also chimes the quarter-hours. Several different chimes are popularly used in clocks, generally implemented on eight bells representing a major scale, as a set of five musical phrases which end up being played twice an hour (the quarters being phrase 1, then 2-3, then 4-5-1, and finally 2-3-4-5). Characteristic of this process is that each bell reverberates for some time after the next note has been struck, and indeed after the complete chime has finished.
I've worked out a reasonably simple circuit to produce a decaying tone, crudely simulating a physical bell. Nine of these circuits ganged together can implement a major scale plus a separate striking bell, with appropriately independent reverberation; these will be followed by a pair of op-amps to implement a filter and drive a speaker. The bells can easily be driven by one of the RIOT's ports, via a '138 decoder to reduce the number of pins required.
At 115.2 kHz Phi2, the RIOT can time an interval of up to 2.267 seconds (1024*255 cycles) without special effort. This is just about perfect for timing out a chime and strike sequence.
Software:
Most of the time, the job is just noticing when the RTC registers change and updating the display to match. The RTC can be configured to produce a 1PPS signal to facilitate this. This job gets modified when the countdown timers are active, as the 1PPS signal now also needs to decrement the timer and compare it against zero. Additionally, the display still needs to be updated when a chime sequence is active, even though the chimes will take several seconds to complete (and I don't want them rigidly synchronised to the seconds). The process of setting the time may also expose some corner cases.
The 2KB ROM essentially precludes the use of any high-level languages or even VMs. Which is fine by me; I've made sure some of the RIOT's RAM is mapped for use as a stack, precisely so that I can still use subroutines sensibly. This is also one of the relatively few serious uses I expect to make of the 6502's Decimal mode, as that's what the RTC chip uses and it's convenient to not have to convert it for display.