Sunday, 22 September 2019

How the VIC20 Works

The VIC20 is a great little machine, and quite a simple machine, particularly the later cost-reduced version.
Inside the earlier VIC20 machines, it looks like there is quite a lot going on, but it's mainly a load of 2114 static RAM chips.
The later machine replaced most of these with two 6116 SRAM chips, leaving only three 2114s (for old times' sake).
The simplicity of the machine did leave a few compromises when it came to address mapping, but this was meant to be an entry level machine. If you wanted 32K, you could buy a Commodore PET or CBM.

Schematics

Various schematics for the VIC20 are available on the net. The ones on zimmers.net have the pages split in half, so for reference, these are the joined up versions I put together, with a little bit of tidying up and attempts to correct the misalignment present in the original scans.
Page 1 covers the 6502, VIC, clock and bus buffers.
Page 2 covers power supply, reset, IO and address decoding.
Page 3 covers the ROM and RAM.

VIC chip

You could say the heart of the machine is the 6502 processor, but that is relegated off to the side, and the real star of the show is the VIC chip, the 6560 (for NTSC) or 6561 (for PAL). This gives the machine it's name, although it wasn't actually designed for it, having been designed several years earlier but failed to find an application. The VIC generates the video output, which is tied to the dot clock for the different video standards. The original version of the VIC20 (2 pin power connector) had different boards for PAL and NTSC versions, these had different clock crystals (14.31818 MHz for NTSC, 8.867238 MHz for PAL),
There were also differences in the supporting circuitry, the PAL version had an additional 74S74 chip to divide the clock down by two to give 4.43618 MHz. The later CR machines used the same board, and used a 4.43618MHz crystal on PAL machines to avoid the need for the extra divide by two stage. The VIC chips output the main system clock, divided by four on PAL machines to give 1.108 MHz, and divide by 14 to give a slightly slower 1.022 MHz on NTSC machines. More info on this in previous blog posts converting a PAL VIC20-CR to NTSC and vice versa.
Unusually for machines of this era, the video output was composite video. UHF TV output was only possible with an external RF modulator box supplied with the machine. The VIC chip outputs chrominance and luminance separately, so with a slight modification, it is also possible to get S-Video out of a VIC 20. That is really only beneficial if you have a suitably vintage S-Video monitor.
To do that, disconnect the C (chrominance) output from the Y (luminance) path, that leaves the previous composite video output now being luminance, and chrominance can be fed via a low value capacitor (1nF?) and an impedance matching resistor (75Ω). You could modify the 5 pin connector to have chrominance at pin 1 to match the early Commodore 64s.

Reset

The VIC20 uses the good old 555 timer to generate a clean reset pulse of 1.6 seconds. This is fed via a 7406 open collector buffer, to allow external reset via the user port, IEC port or cartridge port.
More on this (and other reset circuits) in a previous blog post on an Oric 1 repair.

Power

None of the VIC20 range used dynamic RAM, so there was no need for -5V or 12V rails required by the usual 4116 chips. The static RAM chips 2114s and 6116s are 5V only, so the VIC20 was a mostly 5V machine. The only part that needed more than 5V was the datasette port that needed 9V. The power circuitry went back to the early Commodore PETs, and had a 9V AC input, rectified to give 9V DC (ish) and then regulated down to 5V. The regulator inside the early model Commodore PET was a 7805 TO3 device which gets rather warm.
The redesign for the CR used the Commodore 64 style power supply. This still provided 9V AC for the datasette and the userport, but regulated the 5V in the external power supply (although these are not considered to be reliable these days).

Address decoding

Most of the address decoding in the VIC20 is handled by splitting the 64K address range of the 6502 microprocessor into eight 8K chunks. These are split as follows:

Block
Address Range
Use
0
0000 - 1FFF
Internal 1K RAM
Cartridge RAM1,RAM2,RAM3
Internal 4K RAM
1
2000 - 3FFF
Cartridge BLK1
2
4000 - 5FFF
Cartridge BLK2
3
6000 - 7FFF
Cartridge BLK3
4
8000 - 9FFF
Character ROM, I/O 0 and Colour RAM
Cartridge I/O2,I/O3
5
A000 - BFFF
Cartridge BLK5
6
C000 - DFFF
BASIC ROM
7
E000 - FFFF
KERNAL ROM

Four (and a half) of those blocks are not implemented within the VIC20 (shown in blue), and are assigned to the cartridge port. RAM1, RAM2 and RAM3 are 1K allocations within block 0. I/O 2 and I/O 3 are 1K blocks within block 4. BLK1, BLK2, BLK3 and BLK5 are four full 8K blocks.

Block 0

Block 0 contains the internal RAM, and important areas of RAM that are always present, and forms the  BASIC working area and screen memory as follows:

Address Range
Size
Use
0000 - 00FF
256 bytes
Zero page
0100 - 01FF
256 bytes
Stack
0200 - 03FF
512 bytes
BASIC variables
0400 - 07FF
1K
RAM1 (cartridge slot)
0800 - 0BFF
1K
RAM2 (cartridge slot)
0C00 - 0FFF
1K
RAM3 (cartridge slot)
1000 - 1DFF
3.5K
BASIC User area
1E00 - 1FFF
512 bytes
Screen Memory

The zero page and stack are important to the 6502 so there always needs to be RAM at these locations if you want to make use of the faster zero page op codes, and any subroutine jumps need a stack. There is a 3K gap within this range that can be filled via the cartridge port. This confuses things quite a bit, and you end up with three different arrangements of the memory map, expanded, 3K expansion and 8K (or more) expansion (see later)

Blocks 1,2 and 3

Blocks 1, 2 and 3 are mapped to the cartridge port. There you can install RAM and / or ROM. RAM must start in block 1, then blocks 1 and 2, then blocks 1,2 and 3 if it is to be recognised by BASIC. Other combinations can be used by your own assembly language programs, but BASIC will not count memory if there is a gap. These blocks are normally used in combination with block 5, to provide one or more additional 8K blocks of code. As far as we know, Cheese and Onion is the only game which uses all of blocks 1, 2, 3 and 5.

Block 4

Block 4 is used for IO and the screen colour RAM as follows:

Address Range
Size
Use
8000 - 8FFF
4K
Character ROM
9000 - 93FF
1K
I/O 0 (VIC and VIAs)
9400 - 97FF
1K
Colour RAM
9800 - 9BFF
1K
I/O 2 (cartridge slot)
9C00 - 9FFF
1K
I/O 3 (cartridge slot)

The 4K character ROM is generally 901460-03, but there may be regional variations for other character sets. The colour RAM is a single 2114 chip, 4 bits by 1K, so only bits 0-3 are implemented. The VIC chip uses either the top or bottom half of that depending on the amount of system RAM installed (see later). I/O 2 and 3 are assigned to the cartridge port to use for external I/O devices. I've never seen those implemented as RAM, but I suppose there is nothing stopping you adding a further 2K of RAM within this I/O range, if you wanted to squeeze the maximum out of the VIC20. BASIC wouldn't see it, but you own assembly language could. The I/O 0 range is split up further for the VIC and the two VIA chips.

Address Range
Size
Use
9000 - 900F
16 bytes
VIC
9110 - 911F
16 bytes
VIA #1 (userport)
9120 - 912F
16 bytes
VIA #2 (keyboard)

VIA#1 is used mainly for the userport, and VIA#2 for the keyboard. The other I/O functions, the joystick port, IEC port and datasette port are split between the remaining pins on both chips.The decoding is not complete here, so the VIAs are mirrored throughout the I/O 0 range. VIA#1 is enabled on all addresses in the I/O 0 range where A4 is high, and VIA#2 where A5 is high, so there are addresses where both chips are enabled. I've not seen this used in practaice, but you could save time if you were writing to both chips at the same time during initialisation using say 9130-913F, although, any read operations would cause bus conflict. Quite a lot of potential range is wasted there, as only 48 bytes of a possible 1024 are used, but it saves a number of logic chips that would have been required for tighter decoding.

Block 5

Block 5 is an 8K block assigned to the cartridge port. If a ROM chip is present which starts with the correct predefined header, BASIC execution will jump to the start address defined in the header, this allows autostart cartridges to be used. Most ROM cartridges use a ROM in block 5 to start their code, often with an additional ROM in one of the other 8K banks on the cartridge slot  It is also possible to install RAM in this address range, and if a ROM image is copied into the RAM, it will also autostart, but be aware that some cartridges will detect if they are running from RAM, and may refuse to continue.

Block 6

Block 6 is the BASIC ROM. This cannot be paged out or replaced from the cartridge port, so any routines in the BASIC ROM are always available. There appears to have only ever been one release, 901486-01.

Block 7

Block 7 is the KERNAL ROM (although it also contains various bits of the BASIC code). This is also fixed and cannot be paged or replaced. It is normally socketed, as there are different KERNAL ROMs for each region (901486-06 for NTSC, 901486-07 for PAL). They also seem to be a more common failure than many other chips.

Moving Targets

If that all seemed to make sense, then let me confuse you a little. In order to make use of the extra 3K or 8K or more RAM, some things are moved around when these are installed, to leave the largest available continuous run of RAM available to BASIC.


Unexpanded
3K
8K
16K
24K
32K
Screen Memory 
1E00-1FFF
1000-1FFF
Screen Colour
9600-97FF
9400-95FF
BASIC Memory
1000-1DFF
0400-1DFF
1200-3FFF
1200-5FFF
1200-7FFF
BASIC bytes free
3583
6655
11775
19967
28159

Quite a few things to note here:
  • The screen and colour RAM move when 8K or more is installed. 
  • The 3K space in block 0 is not used by BASIC when 8K or more is installed.
  • The BASIC start address changes each time.
  • RAM in block 5 is not counted by BASIC
  • The internal RAM is multiplexed with the VIC chip, so it can't access external RAM
The BASIC RAM space needs to be continuous, so RAM in block 5 is not available directly for BASIC storage, but can be used by assembly language programs. The same is true for the 3K in block 0 if there is also RAM in block 1. BASIC programs will generally cope with this movement, as long as there is enough RAM to load the program itself. Assembly language programs depends on the programmer. In some cases, they will use the BASIC variables stored in zero page which indicate where the various memory ranges start, so will cope with changing RAM configurations. Others hard code screen and colour RAM addresses, so will fail to work if designed for unexpanded / 3K and are run on an 8K machine, or vice versa. When I hit this issue when running programs I keep thinking they should have arranged it better so it didn't move, but if you are stuck with the 5K internal RAM and have to cope with 3K or 8K expansions I couldn't come up with anything better, other than maybe moving the video RAM up into block 4?

Decoding hardware

The address decoding is fairly simple, and uses mainly 74LS138 three to eight line decoders.
I have seen quite a few machines where these chips have failed. Possibly because some of their pins are directly connected to the cartridge port, so could have been damaged by inserting or removing a cartridge when the power was on (particularly at an angle), or just static from the carpet.
The decoding of block 0 uses another 74LS138, providing chip selects for three 1K blocks on the cartridge port and the internal RAM chips (part numbers shown for VIC20-CR).
One of the problems we occasionally hear with the VIC20 Penultimate Cartridge is 'it doesn't work, but my VIC20 works fine when it's not plugged in'. Generally we assume that the PU cartridges work because I don't think we have actually had a faulty one come back. The 74LS138 at UC5 failing is a common cause of that. This is as good a place as any to describe my normal testing plan. What usually happens is one of the external block lines is stuck high or stuck low, so it's either never enabled (so code is missing) or always enabled (yay! bus conflicts). If the user has access to any other cartridges, I suggest they try out a selection as different types use different combinations of blocks, so that might narrow down the problem.

Cartidge Type
Blocks Used
Examples
Simple 4K/8K
5
Avenger, Radar Rat Race, Omega Race
Atari 16K
1,5
Centipede, Dig Dug
Standard 16K
3,5
Defender, Robotrol, Pole Position
Text Adventure
1,2
Adventureland, Pirate's Cove, The Count

Any of those that work prove those blocks are working. Any that fail indicate one or more bad block enable lines. More on this in a previous VIC20 Repair blog post. You will see the Scott Adams' Text Adventure cartridges do not sit in block 5. This is apparently due to a shortage or space, they couldn't fit in the header and bootup code required, so the user had to type a SYS command to start the game.

Accessories

These days, I don't think a VIC20 is complete without a Penultimate+ Cartridge and an SD2IEC.
The VIC20 is also still enjoying new releases and new hardware developments. There are still many VIC20 fans out there.
This week saw the release of these two new cartridges from The Future Was 8 bit, Nibbler and Future Fighter.

If you want to support this blog, you can donate via Patreon or Paypal, or buy something from my store.