Machine Timing
Frame geometry, where the interrupt falls, and when the ULA holds the bus. The figures here matter to cycle-exact work: raster splits, multiplexed sprites, and anything that has to land on a particular scanline.
Counters
The ULA runs two counters off a 7 MHz pixel clock: hc across a scanline and vc down the frame. One CPU T-state is two pixel clocks. A line is hc_max + 1 pixel clocks; a frame is vc_max + 1 lines.
| Timing | Line (T) | Lines | Frame (T) | /INT at |
|---|---|---|---|---|
| 48K | 224 | 312 | 69888 | vc 0, hc 116 |
| 128K / +2 grey | 228 | 311 | 70908 | vc 1, hc 128 |
| +2A / +3 | 228 | 311 | 70908 | vc 1, hc 126 |
| Pentagon | 224 | 320 | 71680 | vc 319, hc 439 |
On the Next, /INT is held for 32 CPU cycles under 48K and +3 timing and 36 under 128K and Pentagon timing. The count is in CPU cycles, so it is 32 or 36 T-states at every CPU speed and shorter in real time as the speed rises. An instruction still running when the pulse ends misses the interrupt.
The +2A and +3 differ from the 128K in where the interrupt falls, two pixel clocks earlier, and in how long it is held.
A 48K frame is 224 × 312 = 69888 T-states, so at 3.5 MHz it lasts 69888 ÷ 3 500 000 = 19.97 ms.
Next timing selection
The Next takes its ULA timing from two registers:
- Nextreg
$03bits[6:4], the machine timing:000and001select 48K,010128K,011+3,100Pentagon, and101to111+3. A write sets the timing only with bit 7 set, bit 3 clear and the timing unlocked. - Nextreg
$05, the 50/60 Hz bit. 60 Hz shortens the frame to 264 lines and moves/INTtovc0. The line length does not change, so a 60 Hz 48K frame is 224 × 264 = 59136 T-states and a 60 Hz 128K frame is 228 × 264 = 60192.
Pentagon has no 60 Hz variant.
Changing either selects a new timing profile as a whole: frame length, interrupt position, contention pattern and the raster counter’s origin move together. A change takes effect from the next frame boundary.
Frame rate
Nextreg $11 sets the system clock, and with it the T-state rate, without changing any frame’s length in T-states. The frame rate in hertz for each profile:
$11 | 48K 50 Hz | 128K, +3 50 Hz | 48K 60 Hz | 128K, +3 60 Hz | Pentagon |
|---|---|---|---|---|---|
| 0 | 50.08 | 49.36 | 59.19 | 58.15 | 48.83 |
| 1 | 51.12 | 50.39 | 60.42 | 59.36 | 49.85 |
| 2 | 52.65 | 51.89 | 62.22 | 61.13 | 51.33 |
| 3 | 53.66 | 52.89 | 63.41 | 62.30 | 52.32 |
| 4 | 55.45 | 54.65 | 65.53 | 64.38 | 54.06 |
| 5 | 57.23 | 56.41 | 67.64 | 66.45 | 55.80 |
| 6 | 59.02 | 58.17 | 69.75 | 68.53 | 57.55 |
The +3’s frame is the 128K’s length. A frame of F T-states under profile p lasts F ÷ the T-state rate Next Registers gives for p.
First active line
The 256 × 192 display does not start on the same scanline in every profile. The origin for the raster counter and the line interrupt is scanline 64 at 50 Hz, 40 at 60 Hz, and 80 on Pentagon.
Visible area
Layer 2, the tilemap and the sprites cover a 320 × 256 area: the 256 × 192 display with 32 pixels of border on each side and 32 lines above and below. A monitor shows a window of the frame that is not that area, and the window depends on the output. Outside the 320 × 256 area the picture is the border, or black inside the frame’s blanking.
| Output | 48K timing | 128K, +3 timing | Pentagon timing |
|---|---|---|---|
| HDMI, 50 Hz | 360 × 288: 16 black columns left, 24 border right, 16 lines above and below | 360 × 288: 8 black and 8 border left, 24 right, 16 above and below | 360 × 288: 20 border left and right, 24 above, 8 below |
| HDMI, 60 Hz | 360 × 240: 8 lines of the area cut at the top and the bottom | as 48K | – |
| VGA, 50 Hz | 352 × 297: 9½ black columns left, 22½ border right, 17 lines above, 24 below | 352 × 296: 9½ black and 8 border left, 14½ border right, 17 above, 23 below | 352 × 305: 9½ border left, 22½ right, 1 black and 32 border lines above, 16 below |
| VGA, 60 Hz | 352 × 249: the first 7 lines of the area are not shown | as 48K | – |
| VGA with the scandoubler off (15 kHz RGB), 50 Hz | 352 × 304, the whole unblanked frame | 360 × 303 | 384 × 304 |
| VGA with the scandoubler off, 60 Hz | 352 × 256 | 360 × 256 | – |
Each output shows its window in every $11 profile. HDMI exists in profiles 0 and 1 only.
The line interrupt fires late in the scanline, at hc 380 on the 128K family and 372 on the 48K and Pentagon, counted as the /INT positions above are. Its source is a single 7 MHz tick, which starts the same /INT pulse as the frame interrupt, held for 32 or 36 CPU cycles. A program comparing the raster position with it tests for the beam having passed it, not for equality: at two pixel clocks per T-state, a test for equality can step over it.
Memory contention
While the ULA fetches display data it holds the bus, and a CPU access to contended memory in that time is delayed.
The delay repeats every 8 T-states:
| Machine | Delay at each T-state of the 8 |
|---|---|
| 48K, 128K, +2 | 6, 5, 4, 3, 2, 1, 0, 0 |
| +2A, +3 | 1, 0, 7, 6, 5, 4, 3, 2 |
On the 48K an access arriving at the first T-state of the 8 waits 6 T-states, and one arriving at the seventh waits none. On the +3 an access at the third T-state waits 7.
On the 48K, 128K and +2 the T-states an instruction spends with a contended address on the bus, between its reads and writes, are contended too. The +2A and +3 contend only the reads and writes.
Contention applies only:
- on lines 64 to 255 at 50 Hz and 40 to 231 at 60 Hz, the 192 lines of the display,
- for the 128 T-states of each line in which the ULA reads RAM,
- starting 60 T-states into the line on the 48K and Pentagon, and 64 on the 128K family.
The rest of the line, and the top and bottom border and the vertical blank, are uncontended.
On the 48K the contended range is $4000–$7FFF. On the 128K and +2, banks 1, 3, 5 and 7 are contended, wherever they are paged. On the +2A and +3, banks 4 to 7 are contended.
On the Next, contention follows the machine timing nextreg $03 selects: the 48K or 128K pattern under 48K or 128K timing, the +2A/+3 pattern under +3 timing, and none under Pentagon timing. The Next resets into +3 timing, and the boot ROM sets it.
Nextreg $08 bit 6 disables contention. With it set the machine runs without ULA delays.
I/O contention
On the 48K, 128K and +2, a port access is contended when A0 = 0: the ULA port. The +2A and +3 contend no port access.
On the Next under 48K or 128K timing, the contended ports are the ULA port, $7FFD, and the ULA+ ports $BF3B and $FF3B. $1FFD is not contended. Under +3 or Pentagon timing no port access is contended.
CPU speed
Nextreg $07 selects 3.5, 7, 14 or 28 MHz. The CPU’s clock multiplies and the ULA’s does not, so the number of instructions between two raster positions changes and the raster positions do not.
At 7 MHz a 48K-timed line holds 2 × 224 = 448 CPU T-states.
At 28 MHz the memory inserts one wait state per read, as the hardware does, so 28 MHz is slower than four times 7 MHz. The zxnDMA’s reads take the same wait.
Reading $07 back returns two values in one byte: bits[5:4] are the actual speed and bits[1:0] the programmed one. The actual speed resets to 3.5 MHz whatever the programmed one holds, so a read straight after a reset does not return what was written. Enabling the expansion bus also holds the actual speed at 3.5 MHz, whatever is programmed, and the CPU is contended at that speed.
Known differences
- I/O contention on the classic machines ignores the high byte of the port. Hardware contends an
A0 = 1access when the port address itself falls in contended memory; Bizmuth’s 48K and 128K treat every odd port as uncontended. The Next follows the hardware.
See also
- Z80N Instructions: the extended opcodes’ cycle counts.
- Next Registers:
$03,$05,$07and$08in context.