1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-26 09:29:45 +00:00
4 The ZX80 and ZX81
Thomas Harte edited this page 2017-06-22 21:39:41 -04:00

The unexpanded ZX80 and ZX81 combine a Z80 microprocessor, 1kb of static RAM, 4 or 8kb of ROM and various bits of support logic. In the ZX81 the support logic is provided in a single ULA.

The Z80 is clocked at 3.25Mhz and its display is generated programmatically.

Memory map

The ZX80 has a 4kb ROM. That ROM is mapped from address 0x0000. It has 1kb RAM which appears at 0x4000. The RAM is mirrored to 0x8000.

The ZX81 has an 8kb ROM, which also is mapped from address 0x0000. The ZX81 ROM is intentionally also compatible with the ZX80, but the ZX80 ROM will fail 50% of the time when used in a ZX81 as whether the NMI generator (see below) is enabled at startup is undefined.

Video Generation on the ZX80

Programmatic sync is used for vertical synchronisation. Reading from any port which had an address with the low bit clear causes the synchronisation signal to begin. Writing to any port causes it to end.

A combination of the Z80's program counter and refresh counter, and an external 3-bit counter — the line counter — is used to generate lines of video.

When:

  • M1 is set; and
  • bit 15 of the address bus is set; and
  • the HALT line is not set: the support circuitry will intercept the value being read from memory before the CPU has sampled it.

If bit 6 of the value intercepted is clear then a video value will be output, which means that:

  • the value being supplied to the Z80 will be forced to 0x00;
  • having received the refresh address R, a ROM access to the address (R & 0xff00) | (((intercepted value) & 0x3f) << 3) | (line counter) is attempted;
  • the value on the bus will then be output as pixels. If the top bit of the intercepted value was set, it will be inverted.

If the address formed from the refresh address, intercepted value and line counter is located in RAM and the RAM in use loads the data bus during refresh cycles, the value output will actually be that directly addressed by the refresh counter rather than one from ROM.

If bit 6 of the refresh address is clear during a refresh cycle then an interrupt is signalled.

If the bus signals an interrupt acknowledge then:

  • the line counter is incremented; and
  • a 20-cycle period of video sync will be signalled 13 cycles later.

The line counter is reset on any port output.

Net Effect

As designed, lines of text are assembled in memory, terminated by a HALT instruction. At an appropriate moment during display, the CPU is sent to execute those lines from the 0x8000 mirror of RAM. The video circuit captures the opcodes it would have performed and outputs them as video, feeding NOPs to the CPU. If it hits a HALT instruction, that instruction is let through and the CPU enters a halted state. It is next awoken when the incrementing refresh address triggers an interrupt.

Unintentionally, the refresh counter can be used as a direct video address with compatible RAM.

It's also possible to reset the line counter repeatedly by triggering programmatic sync at the same time as the automatic sync would occur anyway, as the two things are ORd.

The ROM is written such that the total number of cycles per line is 207.

Video Generation on the ZX81

The ZX81 adds an additional 207-cycle counter, along with NMI and WAIT logic; it slightly adjusts horizontal sync timing.

Interrupt acknowledge now resets the 207-cycle counter. [Horizontal] sync is signalled when that counter reaches 16 and until it reaches 32. The counter automatically resets itself upon reaching 207.

NMI generation is optional. It is enabled by outputting to any port with the lowest address line clear. It is disabled by outputting to any port with bit 1 of the address line clear.

When NMI generation is enabled, the NMI line will be asserted at the same time as horizontal sync is generated.

If the HALT output of the Z80 is not active and the NMI line is active then the WAIT line will also be held active.

Net Effect

Because the 207-cycle counter is capable of triggering a regular horizontal sync without any additional intervention, the ZX81 no longer needs to cycle count during blank lines. It can be doing other work mostly without any regard to the display.

NMI generation allows the Z80 to count lines so that it knows where the display is vertically, and therefore when to resume active painting.

WAIT generation provides a means of horizontal resynchronisation between the processor and the raster beam — intended use is that the ROM hits a HALT and sits there. An NMI is triggered. The CPU exits the halt state. At that point WAIT is asserted. The CPU gets through the second cycle of its NMI sequence, to where it will next honour a wait request, and starts performing wait cycles. Eventually the ULA stops asserting NMI. So it also stops asserting WAIT. The NMI is then permitted to finish its sequence and nine cycles after the end of horizontal sync, execution begins at 0x66.

Additional discussion: Wilf Rigter has observed that WAIT logic would work equally well for synchronisation if applied only if it detects a transition of HALT from active to inactive, which would free up around 10% of additional processing time for non-display processing because the NMI + not HALT condition also applies when the CPU isn't trying to synchronise at all; he speculates that Sinclair declined to do so for a slight cost reduction.