48k Spectrum
Technical Information
Video Display

A UK TV comprises 625 scan lines displayed every fiftieth of a second. To produce a stable picture, the ULA must generate the synchronising signals that mark the beginning of every line and frame and it must retrieve the video RAM in time for it to be displayed. This means instant access to video RAM. Unfortunately the CPU also needs access to the video RAM in order for it to be changed. This is achieved by sharing buses. Making the ULA wait would result in 'snow' (which is what happens to other machines of this era).

The Spectrum uses a system of parallel attributes to obtain an eight-colour display using not much more memory than is required for a black and white display. The display is maintained by the ULA which displays the information stored in a fixed area of memory - the video memory - to produce a fixed format (256 dots by 192 dots - or 32 characters per line for 24 rows). Unfortunately the ULA is not programmable to display different display modes, which could have been handy nowadays :)

The video RAM is always the first 6912 bytes in the lower 16K of RAM. While a TV picture is being displayed this area is accessed by the ULA to display the next frame.

However, if the CPU were not allowed to use the video RAM when in use by the ULA, it would not be allowed to use any other RAM or ROM in the system because the address and data buses would be in use by the ULA. Resulting in a very slow machine.

This means that the ULA can use the lower 16K of RAM while the CPU can simultaneously use all other memory above this.

If the CPU wants access to the lower 16K the ULA stops the CPU until it is ready to yield control. For this reason code requiring exact timing should be placed above the first 16K of RAM.

An interesting fact of the genius of the Spectrum design is that this video access is not controlled by a simple set of resisters rather than multiplexing chips. When the CPU is using memory above 16K the two buses work independently, with the signals on one bus appearing at a much reduced level on the other because of the voltage dropping action of the resisters. However, when the ULA allows the CPU to access its address space it stops 'driving' the buses and the voltage drop is less, so the CPU's signals gain control.

Video Output Circuit

The ULA is responsible for taking data from the video RAM and constructing the colour information as three video signals - Y (luminance and synchronisation), U (blue-green), V (red-yellow).
The task of taking these three video signals and producing a single PAL (UK) colour signal is the responsibility of a LMI889N PAL encoder chip.

The PAL encoder takes the U and V signals and generates a chroma (colour) signal that is mixed with the Y signal by a two-transistor mixer to produce the final PAL video signal, which is fed to the UHF modulator.

Colour and quality of the display can be adjusted by changing the variable capacitor and resistors positioned in a line on the left hand side of the printed circuit board. Adjusting TC1 (video clock) improves sharpness by removing interference patterns; Adjusting VR1 (colour balance red-yellow) and VR2 (colour balance blue-yellow) adjust the colour balance of the display. TC2 (CPU clock) adjusts the frequency of the CPU and should not be altered. The U, V and Y and the composite colour video signals are available at the rear edge connector and can be used to drive a colour monitor.

Video Display

The video display is colour but takes little more memory than a black and white display. This is achieved because of the use of parallel attributes to control pixels and colour.
Normally a display encodes each pixel with a colour and stores is at one memory location. For example, if this was the case for the Spectrum, each pixel would require one bit for the pixel and 4 bits for the colour, requiring about 30k. The spectrum does not encode the colour with the pixel and so the display requires 6k for the black and white pixels. The video memory for the pixels are stored at the beginning of RAM in locations 16384 to 22527. The colour attributes are stored in locations 22528 to 23295. Each location represents one whole character, rather than a pixel. This means that the storage requirements for the colour display are 6192 bytes plus 768 bytes (about 7k).

The drawback of this, as can be seen when playing games, is that only two colours are allowed per 8x8 pixel block (1 character) - the foreground and the background.

Display Map

The most obvious way of storing the pixel display would be for the first 256 locations to represent the 256 pixels that represent the first row, the next 256 locations to represent the 256 pixels of the second row, and so on.
This is not the case for the spectrum. Each row of 256 pixels is stored like this in contiguous memory locations but the order of storage reflects the 24 lines of characters, i.e. after the top row of pixels comes the top row pixels for the second line of characters (i.e. 8 rows down) and so on for the first eight rows. This means that the first third of video memory represents the top third of the display, the middle third of video memory represents the middle third of the display and the last third of video memory represents the bottom third of the display - with each block of 256 locations/pixels representing alternate rows. This is the reason why a screen for a loading game is displayed the way it is. The following program shows this:

10 FOR I=16384 TO 22527
20 POKE I,255

If L and C represented a character location (line and column), and R represented a particular row within this character (1 to 8), the following code would return its starting address within memory:

DEF FNm(L,C,R)=16384+2048*INT(L/8)+32*(L-8*INT(L/8))+256*R+C

Thus POKE FNm(10,12,3),255 would set row 3 of location 10,12.

Attribute Map

The attributes are stored contiguously, i.e. 22527 is the first character, 22528 is the second and 23295 is the last character of the last row, thus DEF Fna(C,L)=22528+32*L+C returns the location of location L,C.
Each attribute requires 1 byte of information that contains the following bit-pattern:


Bits 0,1,2 represent ink (pixel) and the colours 0 to 7.
Bits 3,4,5 represent paper (the background - where there are no pixels) and the colours 0 to 7
Bit 6 represents whether it is bright (1)
Bit 7 represents whether it is flashing (1)

Thus 128*f+64*b+8*paper+ink is the formula to set the attribute correctly.

Character Set

The Spectrum contains two character tables that are used to hold the dot patterns of the various printable characters and are held mostly in ROM. However, the system variable CHARS holds the address of the start of the character table and so it is possible to change this by poking it with a new address. The system variable UDG holds the start address of the alternate character set which can be used to display a new character set.

The system variables are:

23606: CHARS
23675: UDG
23677: CO ORDS (2 bytes) - represents the x/y co-ordinates of the last plotted point. Can be used to draw lines, etc.
23688: S POSN (2 bytes) - represents the current text cursor location
23684: DF CC (2 bytes) - represents the location within the video display of S POSN
23692: SCR CT - holds a countdown to the next "Scroll?" display message. Poking repeatedly with 255 will stop the message from appearing.
23693: ATTR P - holds the value of the permanent attribute code - i.e. the default paper colour
23695: ATTR T - as ATTR T for temporary attribute code - i.e. for the duration of the current PRINT statement.
23694/23696: MASK P and MASK T hold the permanent/temporary (as above) mask codes for transparency.
23624: BORDCR - sets the attribute code of the lower half of the screen.

Video Applications

In ZX BASIC, the parameter of the USR function is normally the address of a machine code program, however when the parameter is a string, it is used to define the memory location of the value within the character table, thus PRINT USR "A" returns the address in memory address of 'A' (CHARS + n), and POKE USR "A"+n,bitpattern with change row n of character "A" to bit-pattern.
The following code will move the character table to memory and invert it:

10 CLEAR 65536-1024 ;reserve 1k of memory
20 LET A=256+PEEK 23606+256*PEEK 23607 ;start of character table
30 LET B=65536-1024+1 ;start of reserved memory
40 FOR I=0 TO 95 ;the printable characters
50 FOR J=0 TO 7 ;8 rows of each letter
60 LET D=PEEK(A+I*8+J) ;bit-pattern of row of character
70 POKE B+I*8+7-J,D ;set opposite row
95 POKE 23608,INT((B-256)/256) ;sets the new start address
99 POKE 23606,(B-256)-INT((B-256)/256)*256

To produce smooth scrolling messages within ZX BASIC, simply store the message to the UDG area and moving the start address of the table.

Expansion Connector
Built in I/O
ULA Output
ULA Input
System Variables
ZX Basic
I/O Streams
Video Display
Tape, Sound, Printer
Interface 1
©2002 ZeDeX82