The Z80 CTC module (SC102) provides four programmable counter/timers with very flexible input and output connectivity, as well as support for Z80 mode 2 interrupt daisy chaining.
All four channels have an external clock/trigger input, and the first three channels have a zero count/time-out output. All of these signals are available on a connector at the back of the board.Each counter/timer channel can be started as a timer by an external trigger signal on the channel’s input.
Each counter/timer channel can count down, from a pre-set value, each time the selected edge (rising or falling) occurs on its input. When the counter reaches zero a pulse appears on the channels output, the counter is automatically reloaded and an optional interrupt is generated.
Feeding a clock signal to a channel input enables the module to generate a periodic tick signal and/or interrupt. Jumper options allow each channel to be optionally supplied with a clock signal from one of these sources:
- RC2014 bus primary clock (CLK)
- RC2014 bus secondary clock (CLK2)
- The module’s on-board oscillator output (CLKX)
- RC2014 bus USER pin (USER 5, 6, 7, 1 for CTC channels 0, 1, 2, 3)
- An external signal from a connector on the back edge of the module
The first three channels can each act as a baud rate generator by generating a periodic output at the required frequency, as described above. Any one of these can be set to output a baud rate clock to the RC2014 secondary clock (CLK2).
By pre-setting a channel’s counter to 1 the module can generate a Z80 mode 2 interrupt each time the selected edge occurs on the channel’s input. This allows the module to act as a four channel Z80 mode 2 interrupt controller for non-Z80 devices.
For full details of the Z80 CTC see the Zilog data sheet.
Printed Circuit Board
The printed circuit board is a standard footprint RC2014 board.
Version 1.0 of the schematic and PCB label resistors R1, R2, R3 and R4 as 100k, but it was found that if all four inputs were set to the RC2014 bus primary clock (CLK) the system would become unreliable. The value has therefore been changed to 470k to reduce loading of the clock signal.
Configuring the CTC Module
The following are just a few examples of how you can configure and use the CTC module. To realise its full potential it is necessary to study the Zilog Z80 CTC data sheet, which can be found on the internet by searching for “zilog UM0081”.
Most of the following examples require software support.
CTC Module as the Primary Clock
The CTC module can provide a clock source for the RC2014 bus primary clock (CLK). This means a separate clock module is not required, potentially saving one backplane slot.
The illustration below shows the jumper shunt positions required to link the output of the on-board oscillator to the RC2014 bus primary clock (CLK). The illustration uses JP4, but any of the jumpers JP3 to JP6 can be used.
Each channel’s counter/timer input can be either:
- RC2014 bus primary clock (CLK)
- RC2014 bus secondary clock (CLK2)
- The CTC’s on-board oscillator output (CLKX)
- RC2014 bus USER pin (USER 5, 6, 7, 1 for CTC channels 0 to 3)
- An external signal from connector P3
The illustration below shows the jumper shunt positions for:
- Channel 0 to use the RC2014 bus primary clock (CLK) as its input
- Channel 1 to use the RC2014 bus secondary clock (CLK2) as its input
- Channel 2 to use the on-board oscillator clock (CLKX) as its input
- Channel 3 to use the signal on RC2014 bus pin 37 (USER1) as its input
To use the signal on P3’s CT0, CT1, CT2 or CT3 input, just remove the channel’s input jumper shunt so the input is not connected to any of the above.
The outputs from channels 0 to 2 (ZT0, ZT1 and ZT2) are connected to P3, so that they can be easily accessed for any required purpose. Channel 3 does not have an accessible output signal.
In addition, the outputs are connected to jumper JP7, along with the on-board oscillator clock (CLKX). Jumper JP7 enables the RC2014 bus secondary clock (CLK2) to be supplied by any one of the CTC outputs or the on-board oscillator output (CLKX).
By using a CTC output as the secondary clock source, port B of the serial SIO module can have its baud rate controlled by software.
If your RC2014 system already has a device providing the secondary clock signal (CLK2), then do not fit a jumper shunt to JP7.
The illustration below shows the jumper shunt position required to use the output of CTC channel 1 as the source for the secondary bus clock (CLK2).
Baud Rate Generator
For users of the official RC2014 Z80 SIO/2 module, the CTC module can provide a software selectable baud rate clock for SIO port B.
In the example below, the normal clock module is removed and the CTC module provides the RC2014 bus primary and secondary clocks (CLK and CLK2). The primary clock (CLK) is 7.3827 MHz, while the secondary clock (CLK2) is 0.6144 MHz. The primary clock is used by the processor and by SIO port A (115200 baud), while the secondary clock is used by SIO port B (9600 baud).
The jumper shunt positions shown above perform the following functions:
- Red – Sets the RC2014 bus primary clock (CLK) to the CTC module’s on-board oscillator output (CLKX).
- Green – Sets CTC channel 1 clock input to the CTC module’s on-board oscillator output (CLKX).
- Yellow – Links CTC channel 1 output to the RC2014 bus secondary clock line, providing the baud rate clock for SIO port B.
The SIO/2 module’s port B jumper shunt should be removed to isolate port B’s clock from port A’s clock.
To set CTC channel 1 to generate the required 0.6144 MHz clock, issue the following Small Computer Monitor commands:
O 89 55
O 89 6
Or the BASIC commands:
OUT &H89, &H55
OUT &H89, 6
- &H89 is the address of CTC channel 1’s control register (&H88+1)
- &H55 selects:
- No interrupt
- Counter mode
- Count on rising edge
- Time constant follows
- 6 is the time constant
The time constant value 6 selects divide by 12. The doubling of the divider, or halving of the frequency, is caused by the CTC only counting the second edge.
With the CTC input at 7.3728 MHz and CTC channel 1 set to divide by 12, CTC channel 1 output is 7.3728 / 12 MHz, which is 0.6144 MHz. The 0.6144 MHz clock is output to the RC2014 secondary clock line (CLK2) and is picked up by SIO/2 port B. By default the SIO is set to divide the incoming clock by 64 to generate the baud rate. The baud rate is thus 0.6144 / 64 MHz, which is 0.0096 MHz or 9600 Hz.
Time constant value and baud rates:
SIO = divide 64
SIO = divide 16
Due to the way the CTC synchronises its counting function to the bus clock, the above only works when the bus clock (CLK) is the same signal as the CTC input.
By linking the output of one CTC channel to the input of the next, the two channels can be cascaded to give a greater range.
The illustration below shows the jumper shunt position required to link the output of channel 1 to the input of channel 2.
The CTC module can act as an interrupt controller, whereby it provides Z80 interrupt mode 2 functions for up to four devices that do not themselves support mode 2.
The illustration below shows the jumper shunt positions (in red) required to use channel 1 and channel 3 as interrupt controllers for non-mode 2 devices. The interrupt signals from the non-mode 2 devices can be connected to CT1 and CT3 on P3 (shown in yellow) with Dupont wires, or to USER pins on the RC2014 bus (shown in green).
The software will be required to:
- Set the processor to interrupt mode 2 and initialise the I register
- Set the interrupt vector table entries for the CTC’s interrupts
- Set the CTC’s interrupt vector register
- Set the CTC channel(s) to count down from 1
- Set the CTC channel(s) input edge to either rising or falling
- Set the CTC channel(s) to generate an interrupt
- Write an interrupt handler for the non-mode 2 device
Interrupt Daisy Chain
If your system has more than one device using interrupt mode 2, it will be necessary to set up an interrupt daisy chain.
This is fully described in the Z80 peripherals data sheet, but essentially it requires linking the output (IEO) of one interrupt generating device to the input (IEI) of the next, and so on. The position in the chain determines the device’s interrupt priority.
The illustration shows the connections required when using external Dupont wires on P2 (in red) and the RC2014 bus USER pins (in yellow).
Setting up a mode 2 interrupt system is not trivial so requires study of the data sheets rather than following any simple example I could write here.
The module’s address can be set to any address that is a multiple of 4, such as address 0, 4, 8, 12, 16, … , 252. This address is known as the base address, with the module occupying this address plus the next three addresses. Thus if the base address is 0, then the module occupies the address range 0 to 3.
The address is set with the 6 way DIP switch SW1.
The six address switches, 1 to 6, represent addresses 128, 64, 32, 16, 8 and 4 respectively. The base address is the sum of all the switches in the Off position. For a piano style DIP switch, as illustrated below, Up is Off and Down is On.
In the illustration below the switches are:
Up Down Down Down Up Down
This represents the address:
128 + 0 + 0 + 0 + 8 + 0
= 128 + 8
= 136 (or 0x88 in hexadecimal).
In order to provide some certainty for software it is strongly recommended you set the base address of your first CTC module to 0x88, so that the module occupies I/O addresses 0x88 to 0x8B. This is done by setting the switches as illustrated above.
If you have a second CTC module the recommended base address is 0x8C.
WARNING: The suggested addresses clash with the official RC2014 serial / ACIA module, which does not have tight address decoding. It is assumed that most people wanting a Z80 CTC module will be using a Z80 SIO as the serial device, as the ACIA can not generate Z80 mode 2 interrupts.
If everybody follows these recommendations then software written for the CTC module will know where to find the CTC hardware.
The following table shows examples of address switch settings.
Recommended 1st CTC
Base address 0x88
Range 0x88 to 0x8B
(136 to 139 decimal)
Recommended 2nd CTC
Base address 0x8C
Range 0x8C to 0x8F
(140 to 143 decimal)
Base address 0x00
Range 0x00 to 0x03
(0 to 3 decimal)
Base address 0x04
Range 0x04 to 0x07
(4 to 7 decimal)
Base address 0x08
Range 0x08 to 0x0B
(8 to 11 decimal)
Base address 0x40
Range 0x40 to 0x43
(64 to 67 decimal)
Base address 0x44
Range 0x44 to 0x47
(68 to 71 decimal)
Base address 0x48
Range 0x48 to 0x4B
(72 to 75 decimal)
Base address 0x4C
Range 0x4C to 0x4F
(76 to 79 decimal)
Base address 0x50
Range 0x50 to 0x53
(80 to 83 decimal)
Base address 0xF0
Range 0xF0 to 0xF3
(240 to 243 decimal)
Base address 0xF4
Range 0xF4 to 0xF7
(244 to 247 decimal)
Base address 0xF8
Range 0xF8 to 0xFB
(248 to 251 decimal)
Base address 0xFC
Range 0xFC to 0xFF
(252 to 255 decimal)
Thanks to all those who provided encouragement, feedback and contributed ideas to the design. Specifically: Mark T, Tom S, Jon L, Nigel K, Samster, Jay C, Colin L, Karl B, Spencer O, and anyone else I forgot! Also thanks to those who reported errors in this guide, which hopefully I’ve fixed.
See RC2014 google group for full details: