The timekeeping aspect of this project is going to be very simple. While the GPS clock project had granularity down to the 10th-of-a-second, which required some interpolation, this clock will only require one second granularity. There will be a need to keep a sub-second timer, but we'll get to that later. Getting time from a GPS receiver requires handling the serial I/O as well as the PPS output from the receiver. We can use the PPS as an interrupt to create the leading edge of the tick and beep sounds (so that they're as accurate as possible) as well as marking the second-start for synchronizing the software activities.
Like all of the time-talkers that have come before, we want to use sampled audio rather than attempting to use voice synthesis. The limited vocabulary of the clock makes that the path of least resistance. 8 kHz 8 bit µ-law encoding provides "telephone" quality level for the audio. The bad news is that the 32 kB of flash available is obviously insufficient for the number of samples required. Storing the audio on an SD card or SPI flash chip gives us plenty of storage, and by using FAT storage, we can configure and access the storage quite easily. This also potentially allows field replacement of the samples, so that people could customize the voice (even the language) however they like.
We use the same XMega32E5 controller we used in the v5 variant of the GPS clock. The XMega32E5 has a 2 channel DAC that we can use to play back the audio samples from the SD card or SPI flash chip. We can use one of the timers configured for 8 kHz as a clock for the DMA controller to trigger updating the current DAC value so that playback can be done largely in the background (we have to double-buffer the sample reads to insure the playback remains seamless, but that's only 1k of RAM out of the 4k available). When reading the values in from the flash, we also need to convert the µ-law samples into 12 bit (actually, 16 bit, but the hardware drops the bottom 4 bits) unsigned values. This is, however, fairly straightforward.
The actual audio format is 10 second blocks. Every second is marked by a 10 ms "tick" and every 10 seconds there will be a 3/4 second beep. The leading edges of these are synchronized to the PPS of the GPS receiver using the PPS ISR. We configure one of the timers to output a 1 kHz square wave on one of the pins of the controller, and we simply turn that output on early in the PPS ISR and in the outer loop turn it off either 10 ms or 750 ms after the second.
The audio circuitry takes the 1 kHz square wave output and runs it through an RC low-pass filter. Then it is mixed with the output of the DAC and the sum fed into an audio amplifier and speaker. The audio amp has two stages because the DAC output ranges from 0 to 3.3 volts and the power amp runs on 5 volts. If we don't provide some additional pre-amplification then the final output winds up too low. The power amp is an LM4871, which is a push-pull style amp designed to drive a small speaker from a low voltage supply.
The SD card slot or SPI flash chip is simply connected to the SPI interface. The directory layout is top level directories "ZONE" "HOUR" "MINUTE" "SECOND". Inside of each of the hour, minute and second directory are files named 0-60 (0-24 for hours, and only every 10 for seconds), each of which are an audio snippet. Inside of "ZONE" are files with two letter names, the first of which is a timezone (Pacific, Mountain, Central, Eastern, Alaskan, Hawaiian), the second of which is either S for standard or D for daylight. There will also be a "U" for UTC. Every 10 seconds, the playback consists of the appropriate ZONE file, then hour, minute and second. The intended scripting is "At the tone, Coordinated Universal time will be 23 hours, 59 minutes, 50 seconds." The first second of each 10 second block is reserved for the previous block's mark tone. Seconds 2 through...Read more »