Computers Overview
Commodore PET
Sinclair ZX80
Sinclair ZX81
BBC Micro
Sinclair Spectrum
Memotech MTX
    About
    Library
    Manuals
    Options
    Photos
    Projects
      CFX
      Hardware Hacks
      Legacy (1980s)
      MAGROM
      MTXPlus+
          Architecture
          Design Data
          Firmware
             CPU
               Clocks (PHI)
               Memory Map
               ROM
                   Boot
                   Err. Msgs
                   Features
                   Media
                   Timing
               Speculator+
             I/O
             Video
               Wait States
          Parts
          Software
      PAL Reader
      Programmers
      ReMemotech
      ReMemorizer
      SDX
    Repairs
    Software
    Tools
    User Groups
    Video Wall
Memotech CP/M
Atari ST
DEC 3000 AXP
OpenVMS
Raspberry Pi

 

 
 
 

"MTX Plus+" ROM - Timing

 

MTX CTC Pin-out MTXPlus+ CTC Pin-out

Background

Both the original MTX and MTXPlus+ computers include a Z80 Counter/Timer Circuit (CTC), the CTC has four independently programmable counter/timer channels that can be used to perform functions such as interrupt timing and clock rate generation. Each channel has an external Clock/Timer Trigger input (T/T0 to C/T3) and can drive one or two outputs. Channels 0 to 2 each have an individual Zero Count/Timeout output (ZC0 to ZC2) and all channels can drive the Interrupt Request (INT) pin.

The diagrams above show the connections to the Z80 CTC for the original MTX and MTXPlus+, the only differences being the connections to pins 20 and 7. Allocation of the CTC channels for the MTX and MTXPlus+ are shown in the table below :

CTC Pin-out MTX MTXPlus+
External Clock/Timer Trigger inputs, C/Tx
Channel
 
 
 
0
Pin
 
 
 
23 VDP Interrupt VDP Interrupt
1 22 CK4/13 (For DART Channel 1) CK4/13 (For SIO Channel 1)
2 21 CK4/13 (For DART Channel 2) CK4/13 (For SIO Channel 2)
3 20 Cassette Interface 125 Hz interrupt clock input
Zero Count/Timeout outputs, ZCx
Channel
 
 
0
Pin
 
 
7 Not used Raw VDPINT Interrupt clock output
1 8 Serial Clock for DART Channel 1 Serial Clock for SIO Channel 1
2 9 Serial Clock for DART Channel 2 Serial Clock for SIO Channel 2

As the device name suggests, each channel can be configured as either a counter or a timer. Each channel is programmed with two or three (if interrupts are enabled) 8 bit words - a control word and a time-constant word.

When in Timing mode, each channel has a selectable pre-scaler (set in the control word) which divides the system clock by either 16 or 256, and a time-constant word that can have values from 1 to 256, that can be used to specify the interrupt frequency. (Equation 1)

Interrupt frequency

=

 PHI
Prescaler * Time Constant

Time related functions in the MTX, such as the system clock and keyboard repeat rate, are controlled by periodic interrupts with a frequency of 125Hz which are generated by the CTC.

Channel 0 of the CTC is connected to the VDP interrupt output pin (VDPINT), the VDP generates an interrupt signal at the end of each active display scan, which, in the case of the TMS9929A, is about every 1/50 second. The MTX ROM has an interrupt routine called VDPINT that handles the internal clock, key auto repeat, cursor flash and some sound functions.

The interrupt is generated by CTC channel 0, but instead of using the VDPINT signal as a trigger, it uses the CTC timer mode to divide the CPU clock by (256 * 125) to give a 125 Hz interrupt.

Interrupt frequency

=

 4 MHz
256 * 125
 

=

 125 Hz

Using this method means that the interrupt period would be the same for the NTSC (TMS9918, 60Hz) and PAL (TMS9929, 50Hz) versions, allowing the ROM code to be common.1

 

MTXPlus+ Timing

If a copy of the MTX ROM, with interrupts generated from the CPU clock, was used in MTXPlus+ without modification, then the time related functions would only be correct when the system was operated at 4MHz, as the system speed increased, so would the rate of the timing dependent functions.

When discussing how we were going to handle the time related functions in MTXPlus+, initial thoughts were around using CTC constants appropriate for the clock frequency, at 16MHz though, constraints in the CTC were somewhat problematic.  Using the maximum pre-scaler (256) value :

Scaled frequency

=

 16 MHz
256 (pre-scaler)
 

=

 62500

 

Using the maximum time constant value (256), the minimum interrupt frequency would be almost twice that expected - doubling the clock tick rate etc.

Interrupt frequency

=

 62500
256 (counter maximum)
 

=

 ~244Hz

Although it is possible to cascade more than one counter to get values greater than 256, the problem would still be that the interrupt frequency would only be correct for a single clock speed. To keep the timing correct at all clock speeds without having to change constants in the software for each, some method of automatically controlling the interrupt frequency was required.

Tony Brewer suggested a mechanism for doing this that didn't need additional resources (on my board anyway), using the redundant CTC channels C/T3 and ZC0, as well as spare I/O in the CPU control buffer GAL2, enabling the GAL to count ZC0 pulses and generate 125Hz interrupts for any of the three defined clock speeds.

 
GAL Inputs

GAL Logic

CPU Clock speed select MHz
VDPINT frequency divide counters - internal use only - no physical outputs

/ZC0_CNT0

: =

ZC0_CNT0

/ZC0_CNT1

: =

/ZC0_CNT0

*

/ZC0_CNT1

(00 -> 01)

 

+

ZC0_CNT0

*

ZC0_CNT1

(11 -> 00)

 

* A "00" value on PS1/PS0 is a variable rate slow clock used for testing

PS1 PS0
0 0 n/a*
0 1 4
1 0 8
1 1 16
ZC0 CTC Ch.2 Output

CT/3

= /PS1

*

PS0

*

ZC0

 

 
  + PS1 * /PS0 *

ZC0_CNT0

   
  + PS1 * PS0 *

ZC0_CNT0

* ZC0_CNT1
 
  4 MHz CT/3 = ZC0
  8 MHz CT/3 = ZC0 / 2
  16 MHz CT/3 =

ZC0 / 4

GAL Outputs
ZC0_CNT0 (Internal use)
ZC0_CNT1 (Internal use)

C_T3

CTC Ch.3 Input
(125Hz clock for interrupt)

The CTC is programmed to output the interrupt signal derived from the MTX ROM, i.e., the CPU clock divided by (256 * 125), resulting in ZC0 frequencies of 500, 250 or 125 Hz for CPU clocks speeds of 16, 8 and 4 MHz respectively. Based on the configuration of the CPU clock speed select switches, the GAL divides the ZC0 frequency by 4, 2 or 1 and feeds back into the CTC C/T3 input at 125Hz, independent of CPU clock speed.

Design Development

Having the GAL22V10 divide ZC0 by 1, 2, 3 or 4 for 4, 8, 12 or 16 MHz CPU clocks was an ideal solution when the system clock speeds were multiples of 4MHz, but becomes less useful now that the system has the capability of running at clock rates that are not multiples of 4MHz.

The GAL22V10 has now ben removed and the CTC ZC0 output fed back directly to the CTC C/T3 input.

ZC0 pulses high whenever CTC channel 0 down-counter reaches zero. This will happen in two different cases, when :

(a) CPU clock is divided to generate 125 Hz interrupt or

(b) /VDPINT input used to generate interrupt, as discussed separately below.  

For a normal MTX at 4 MHz, the CPU clock is divided by a pre-scaler of 256 and a time constant of 125 to generate the 125 Hz interrupt (see Equation 1 above). The time constant value is pure coincidence as 4000000 / (256*125) = 125. A time constant of 250 for an 8 MHz clock and maximum of 256 (0 value is programmed) for 8.192 MHz clock is possible.

Anything higher ('fast') requires two cascaded CTC channels, 0 and 3, the latter, otherwise unused cassette interface, is not supported.

If 'fast' = 10 MHz, have channel 0 pre-scaler of 16 (cannot be 256), time constant of 125 and channel 3 time constant of 40.

If 'fast' = 12 MHz, have channel 0 pre-scaler of 16 (or 256), time constant of 125 and channel 3 time constant of 48 (or 3).

Channel 0 is in timer mode and channel 3 in counter mode with no pre-scaler available and external trigger ZC0. Therefore simply connect ZC0 output to C/T3 input and remove C/T3 from all other devices.  

Time constant of 1 ensures that /INT goes low every time /VDPINT goes low so that CPU is interrupted 50 times per second at the end of active display. As ZC0 will go high whenever /VDPINT and hence /INT go low, we have a choice of which of /INT or ZC0 to connect to CPLD for Speculator logic (which must know when /INT goes low) but we don't need both.

N.B. ZC0 and C/T3 changes mean must have different interrupt code for 4MHz and 'fast'. If latter is only 8 MHz now as temporary measure, only one byte would differ (time constant 125 or 250) as one CTC channel sufficient for 125 Hz (but not true for 10+ MHz).

 

Explanation of currently implemented ROM code (from Martin)

The current setup for the CTC is : 

Channel 0 is set up as follows: 

The control word is now &25 which is a bit pattern of 0010 0101
Bit 7 clear – no interrupt
Bit 6 clear – timer mode
Bit 5 set – pre-scaler 256
Bit 4 clear – falling edge detection
Bit 3 clear  – automatic trigger when time constant is loaded
Bit 2 set  – time constant follows
Bit 1 clear – continued operation
Bit 0 set  – identifies control word

 The original MTX code would have had the interrupt bit set, as this was the only counter in use   The modified hardware has the output to this pin connected to the input of channel 3   The timer constant that follows is 31 (decimal) instead of 125.   At 4mhz counting to 125, with a pre-scale of 256 results in an interrupt every 32000 cycles, giving the system its 125hz interrupt.

The MTXPlus+ however, with it’s count of 31 and a pre-scale of 31, results in the input of channel 3 being pulsed every 7936 cycles.

Channel 3 is set up as a counter and not a timer

The control word is &D5 which is bit pattern 1101 0101
Bit 7 set – Trigger an interrupt
Bit 6 set – Counter mode
Bit 5 clear – not used in count mode
 Bit 4 set – Rising edge detection
( NB  I’m not quite sure why I changed that in theory either edge should work)
Bit 3 clear – not used in count mode
Bit 2 set – time constant follows
Bit 1 clear – continued operation
Bit 0 set – identifies control word

The time constant that follows is the CPU speed in MHZ that’s detected on start up.  

So, channel 0 triggers channel 3 every 7936 cycles, If the MTXplus+ CPU is running at 4mhz, that results in the channel 3 interrupt being triggered every 31744 cycles, Which is a fraction faster than the original MTX, there are now an average 126.008 interrupts per second. So by changing the count for the software clock from 125 to 126, TIME$ is now sufficiently accurate for normal use.

 Using the CPU speed as the constant for the 2nd stage count means that whatever speed the CPU is clocked at, as long as its an exact number of MHz, the result is a 126hz tick   i.e. 10MHz CPU, the interrupt triggers every 79360 cycles, 10,000,000 / 79360 = 126.008 as above, the system clock runs as before.

At 10.5mhz, the interrupt would still trigger every 79360 cycles, however 10,500,00 / 79360 = 132.3 so the system clock will run 5% fast  

"Final" Implementation

Using CPLD or GAL logic developed by Tony, MTXPlus+ now has the ability to operate at any one of 16 clock frequencies from 4MHz to 16MHz. To support this, 16 different CTC time constants are required :

Clock /? MHz 125 Hz Error CTC Time Constants
0 8 4.00    16,125 (4,000,000)
1 7 4.57  1s in 8001s 18,127 (4,572,000)
2 4.92  1s in 4570s 23,107 (4,922,000)
3 6 5.33  1s in 8001s 21,127 (5,334,000)
4 5.82  1s in 3201s 15,194 (5,820,000)
5 5 6.40    25,128 (6,400,000)
6 7.11  1s in 8001s 28,127 (7,112,000)
7 4 8.00    32,125 (8,000,000)
8 8.53  1s in 12801s 17,251 (8,534,000)
9 9.14  1s in 8001s 36,127 (9,144,000)
10 9.85  1s in 4570s 46,107 (9,844,000)
11 3 10.67 1s in 8001s 42,127 (10,668,000)
12 11.64 1s in 7112s 23,253 (11,638,000)
13 12.80   50,128 (12,800,000)
14 14.22 1s in 80011s 56,127 (14,224,000)
15 2 16.00   64,125 (16,000,000)

For clock frequencies of  4, 6.40, 8.0, 12.80 and 16.0MHz, the clocks can generate a 125 Hz interrupt precisely, the rest have small errors as listed in the table of CTC time constants, the worst case error is at 5.82MHz, where the error is 1s in 3201, i.e., 1s in 53 minutes, or approximately 26 seconds per day.

 

 Identifying the CPU speed, in software 

The MTXPlus+ is designed to have an adjustable CPU clock. 4MHz for Compatibility with the MTX, mostly for games, and a range of faster speeds to take advantage of the enhanced hardware.

The support ROM, therefore uses the on-board RTC chip to calculate the CPU speed.   To do this it counts how many processor cycles it completes in one second of real time as determined by the DS12887. The ROM counts how many times it executes a 9874 cycle sub routine, It’s a slightly odd figure as the count routine averages 126 cycles per loop which has to be taken into account. From there it knows to within 0.01 of a MHz how fast the system clock is. Tested with an 11.0592mhz oscillator  it reported 11.06, close enough!  

The CTC only counts in integers, which for the majority of available oscillators isn’t a problem, Having the 4MHz compatibility mode really means the master clock is going to be some multiple of that anyway.

 

 

Credits :

1  Information about the CTC configuration in the original MTX ROM courtesy of Tony Brewer, January 2015

 

Notes :

2 Utilising the GAL22V10 used on Dave's CPU board to buffer the Z80 control signals

 

 

mailto: Webmaster

 Terms & Conditions