bus drivers for additional parallel I/O: since the external memory interface eats a lot of I/O lines, an I/O
expansion is necessary in some way. I could have used one of the more modern x51 variants with built-in
flash EPROM and thereby get most of the processor's pins as I/O, but as I already mentioned, I have a
strong preference for components that are not single-sourced.
The whole circuitry is built on a prototype card and wired with thin isolated copper wires, a popular
method for prototypes. Needs a bit patience and requires accuracy...the connection to the tuner's mainboard
is done via a ribbon cable with a crimped plug on one end and an IC socket on the mainboard; of course, I
had to unsolder the broken processor and replace it with a socket. The DIL connector is in my case a
simple IC socket with the cable soldered onto it wire by wire; there are however also crimpable connectors
available for this end.
Basic Layout of the Software
As you may imagine, it is by far too complex to explain the firmware on a line-by-line basis at this place;
I'm also not going to explain the basics of the 80C32's architecture at this place - there's plenty of literature
available in the Internet about that. I will therefore describe the basic building blocks and line out how they
work together:
Initialization
Of course, the first step after a power-on or a reset is the initialization. The interrupt-driven background
processes have to be initialized, and some global memory cells are resetted to meaningful defaults.
Interrupt Routines
There are two interrupt-driven background processes that run on the CPU. At least on a standard C32
without X2 mode, they consume about 70% of the CPU time, which is no miracle given the low clock
frequency. The remainder is however still fully sufficient for our purposes.
The first process runs at about 400 interrupts per second and is used to drive the flourescent display and
read the keyboard matrix. As with most consumer electronics, the RT200's display is a 'dumb' display that
does not the refresh by itself, so the processor has to do the multiplexing itself. It works in the following
way: Initially, the CPU outputs the data for the leftmost digit to the SEGMENT OUT pins and pulls the
DIGIT OUT 0 line low while DIGIT OUT 1..4 remain high; this way, the contents of the leftmost digit are
displayed at the correct place. In the next cycle (==interrupt), the first digit is turned off, the data for the
second digit outputted, and the second digit is turned on. This process continues until the last digit is done,
and we jump back to the first digit. So at any point of time, only one digit is on, but if this done fast
enough, you get the impression of a still display. Similar to a computer monitor, about 60..70 complete
cycles are needed per second for a flicker-free display, which results in the interrupt frequency mentioned
above for 6 digits.
The other regular process is an interrupt service routine triggered by the precise 250Hz delivered by the
synthesizer chip. This clock is used to run a real-time clock needed for the time display and timer
functionality. For each interrupt, a byte in memory is incremented. As soon as its value reaches 250, the
seconds value is incremented. The rest should be clear ;-)
Since the keyboard matrix and display share their row select, is is only natuaral that the process mentioned
first also scans the keyboard. If one row of the matrix is pulled low, any key that is pressed and connected
to that row will generate a low level on the keyboard scan lines. The scanned values are stored in 6
consecutive memory cells, resulting in an image of the keyboard matrix stored in memory that gets updated
regularly. The x51 family allows to assign either a low or a high priority to each interrupt source. In our
case, the keyboard/display multiplexer gets a high priority, while the clock update process works with the
standard (low) priority. This is necessary to allow the multiplexer to interrupt a running clock service
routine. Especially when one or more counter(s) roll over, the clock update consumes more time and can
significantly delay the next multiplex cycle (don't forget we have a rather slow 8032!) and result in a