3 chip VZ200 project
This page will document my efforts to build a working VZ200 in hardware
using a combination of new and old technology
What is a VZ200?
The VZ200 is an
early 1980s home computer. Out of the box it came with 8k RAM, 16K ROM,
Z80 CPU, Motorola 6847 graphics chip, rubber keyboard and a simple 2
bit piezo speaker.
It was designed as a low cost entry level computer - better than a ZX81
but not as good as a spectrum. Similar machines of the time were the
Acorn Atom and Tandy MC-10.
The VZ300 appeared
in 1985, which was fundamentally the same as a VZ200 but with more
memory and a better keyboard. The picture below is some of my
collection.
Opening the case of a VZ200 revealled a myriad of chips, resistors and
capacitors. The reason for the high chip count is due to the 1980s
technology - memory was expensive.
In the VZ the internal RAM was built up using 2k RAM chips. For a 16k
VZ300, that's 8 ICs right there. Then you have the 2k graphics memory,
an 8 bit latch, and 16k ROM. Each of these
chips requires supporting circuitry, and additional ICs for address
decoding between the Z80 and 6847.
Below is a picture
of the VZ300 internals.
This project is an attempt to build a working VZ in hardware with just 3 chips:
1. Motorola 6847 - The original graphics chip used in the VZ computers
2. 7404 hex inverter - used alongside a 3.58mhz crystal to provide the clock signal for the M6847
3. Teensy 3.5
microcontroller. This is a modern, powerful, programmable 50 pin IC.
This will simulate the Z80 CPU, provide a 64k address space, bootstrap
the VZ ROM, interface to the M6847 and handle all the address
decoding logic. It is essentially a VZ emulator on a chip that
interfaces to a real display chip. The teensy will replace all but two
of the ICs above!
How it will work
- The teensy will
contain the original VZ ROM on the internal micro sd card - the same
ROM file used by the VZEM emulator
- The teensy will contain the Z80 emulation code in its sketch memory,
with supporting functions for VZ specific hardware
- On powerup, the teensy will allocate a 64K chunk of RAM, load the VZ
ROM into low memory, and start the Z80 emulation. The clock will start
running the M6847
- The Z80 emulation code will run for 71590 T-states, which is the
number of cpu cycles for a 3.5795mhz Z80 running for 20ms
- The teensy will wait for the next FS signal from the M6847, which
signifies the end of a frame
- At the same time the Z80 emulation code is running, the teensy is
decoding the address lines of the M6847 and returning bytes of data
according to the VZ memory map
- The "VZ latch" will be internal to the emulation code, with pins from
the teensy wired to the M6847 mode control pins to set display
mode/background colour
Initial version will just use the "Y" output of the M6847 to drive a monochrome NTSC display. If I get this far, future experiments may include:
- MC1372 modulator
chip to drive a color display
- LCD display screen with some pushbuttons to map disk & cassette
images
- A real Z80, with the teensy just serving the ROM, RAM and address
decoding. This qualifies as a "real" VZ, rather than an
emulator/hardware hybrid
Progress
25th March 2017
Thanks to some help
from Gerardus I believe I have a working clock generator. The circuit
is based on the below design, taken from
http://www.andreadrian.de/Z80_blinkenlights/index.html
I then inverted the
output again and after some experimentation used a 1.2k resistor to
smooth out the edges.
This is the clock
generator circuit on a breadboard, next to the M6847.
And this is the
resulting signal captured on my scope. The pulse width is appx 150ns
with rise and fall times of appx 50ns.
What next
The next phase of
the project will be to build a test circuit interfacing the teensy to
the M6847. The two transistor circuit below will be added to the "video
card" breadboard to see if it can produce a working display.
Then the Z80/VZ200 emulation code will be loaded into the teensy.
http://devster.monkeeh.com/files/vidamp.png
Update - 29th March 2017
The below pic shows the M6847 hooked up to the teensy. The white wire
is the clock signal. The orange wire is the horizontal synch pin, the
blue wire the field synch pin
Looking at the 6847 datasheet, there are 32 lines left in the frame
until the end of the vertical retrace (26 bottom border + 6 retrace)
The following code was loaded into teensy's sketch memory, to count the number of horizontal synchs after the field synch, till the end of frame
#include
<SD.h>
#include
<SPI.h>
#define
M6847_FS 33 // Field synch pin wired to teensy pin 33
#define
M6847_HS 34 // Horizontal synch pin wired to teensy pin 34
const
int chipSelect = BUILTIN_SDCARD;
File
myFile;
void
setup()
{
if (!SD.begin(chipSelect))
{
return;
}
myFile = SD.open("3chipvz.txt", FILE_WRITE);
if (myFile)
{
myFile.println("***
3CHIPVZ
***");
myFile.println("Initialising...");
}
pinMode(M6847_FS,
INPUT);
pinMode(M6847_HS,
INPUT);
int horizontalSynchs = 0;
while (digitalRead(M6847_FS) == LOW); //
we could be starting in the retrace period, eg FS low, so wait for
start of display
while (digitalRead(M6847_FS) == HIGH); // now
in main display
// starting point - the FS has just gone low again. Start counting
horizontal synchs until start of display
while (digitalRead(M6847_FS) == LOW)
{
while
(digitalRead(M6847_HS) ==
LOW); // wait for HS to
complete
while
(digitalRead(M6847_HS) ==
HIGH); //
drawing scanline
horizontalSynchs++;
//
just
hit HS low - increment count
}
myFile.print("HS count: ");
myFile.println(horizontalSynchs);
myFile.close();
}
void
loop()
{
// nothing happens after setup
}
Once power was
applied to the circuit, this was the resulting output on the SD card
*** 3CHIPVZ ***
Initialising...
HS count: 32
Which proves the
M6847 is accepting the clock signal and producing horizontal and frame
synch pulses, which the microcontroller can read.
Update
- 2nd April 2017
Wired up the address and data bus of the M6847 to the teensy. For the
"address" lines, the data pins on the teensy were configured as
input. The "data" lines, writing data back to the M6847 were
configured as output.
Pins 0-12 are used for the address lines, which fits neatly on the
pinout diagram below. Pin 0 is the most significant bit, wired to pin
DA12 (pin 21) on the M6847
Pins 25-32 are the
8 data lines to return data back to the M6847 with pin 25 the most
significant bit.
These are the
functions defined in the teensy to decode the address lines and return
data back to the M6847.
unsigned int M6847_readAddress()
{
int addressBus = 0;
addressBus |= ((digitalRead(12)==HIGH)?1:0)<<0;
addressBus |= ((digitalRead(11)==HIGH)?1:0)<<1;
addressBus |= ((digitalRead(10)==HIGH)?1:0)<<2;
addressBus |= ((digitalRead(9)==HIGH)?1:0)<<3;
addressBus |= ((digitalRead(8)==HIGH)?1:0)<<4;
addressBus |= ((digitalRead(7)==HIGH)?1:0)<<5;
addressBus |= ((digitalRead(6)==HIGH)?1:0)<<6;
addressBus |= ((digitalRead(5)==HIGH)?1:0)<<7;
addressBus |= ((digitalRead(4)==HIGH)?1:0)<<8;
addressBus |= ((digitalRead(3)==HIGH)?1:0)<<9;
addressBus |= ((digitalRead(2)==HIGH)?1:0)<<10;
addressBus |= ((digitalRead(1)==HIGH)?1:0)<<11;
addressBus |= ((digitalRead(0)==HIGH)?1:0)<<12;
}
void M6847_writeData(byte
data)
{
digitalWrite(32, (data
& 0x01) >> 0);
digitalWrite(31, (data
& 0x02) >> 1);
digitalWrite(30, (data
& 0x04) >> 2);
digitalWrite(29, (data
& 0x08) >> 3);
digitalWrite(28, (data
& 0x10) >> 4);
digitalWrite(27, (data
& 0x20) >> 5);
digitalWrite(26, (data
& 0x40) >> 6);
digitalWrite(25, (data
& 0x80) >> 7);
}
Another test
program was loaded into the teensy to set the video memory
to 0x41 - the ascii "A" character.
for (int i=0; i < 6144;
i++)
{
M6847_MEM[i]
= 0x41;
}
The "loop" function, which loops forever while the power is on, just
reads lines from the address bus (0x0000-0x17FF) and returns data from
the byte array defined for the screen memory.
The last digitalWrite command just lights up the LED permanently, which
tells me the microcontroller is in its main loop.
void loop()
{
addr_bus =
M6847_readAddress();
data =
M6847_MEM[addr_bus];
M6847_writeData(data);
digitalWrite(led, HIGH); // turn the LED on (HIGH is the
voltage level)
}
The two-transistor
circuit was rigged up on a separate piece of breadboard.
The picture below
shows the initial state - using jumper wire it gets messy quickly, but
this was just to test the pins. The final prototype will use cut to
length wire. Note the micro sd card plugged in to the teensy. At
the moment this is used to log tests, this will eventually be used to
load the VZ rom on startup, and hold all the floppy disk and cassette
images.
This is the resulting picture displayed on a cheap polaroid lcd tv.
There is a blue tinge to the characters. Not sure if the tv can handle
an ntsc signal properly
And this is the same result displayed on my old commodore 1084 monitor.
The picture is near perfect - quite sharp to look at.
Next iteration will split the teensy onto a separate breadboard, and
the composite video out circuit will be incorporated onto the board
with the clock and M6847. I'll change the rca plug into an rca socket,
to allow use of a standard yellow video rca cable.
I might buy a single large breadboard to fit the entire prototype on
one piece