Boards
An Altair is a backplane, and everything in it is a board. The memory, the serial ports, the disk controller, the front panel and the processor are all boards. Without the boards, only the bus is left.
altairsim works in the same way. For this reason, the crystal is a property of the processor
board, and the sense switches are a property of the front panel. You can remove a board, add
a different one, and see what the software does.
This chapter starts with the commands that add, remove and show boards. After that, it tells you what each board is: what the real hardware was, what it is for, and what can go wrong. It does not list the properties of each board. The board reference at the back of this manual lists every property of every board, from the program's own tables.
Add, remove and look at boards
You can do everything by hand that a machine file does to a board.
| Command | |
|---|---|
BOARDS |
what is in the backplane |
SHOW BOARDS |
the board types that you can add, one line each |
SHOW BOARD <type> |
the description and settings of one type (add UNITS for only the units) |
BOARDS ADD <type> <id> |
add a board |
BOARDS REMOVE <id> |
remove a board |
SHOW <id> |
the settings of one board in the machine, with the values that it accepts |
SET <id> <key>=<value> |
change one setting |
altairsim> BOARDS ADD virtc vi0
altairsim> SET vi0 rtc_source=line
altairsim> SHOW vi0
The keys at the prompt are the keys in a machine file. SET cpu0 clock_hz=2000000 at the
prompt and clock_hz = 2000000 in a machine file set the same property.
When you have the machine that you want, type:
altairsim> CONFIG SAVE mine.toml
This writes the machine to a file, and the file loads back as the same machine.
Look at a board type before you add it
SHOW BOARD <type> reads the catalog. It makes one board of that type, describes it, lists
its settings, and removes it again. Nothing is added to the backplane. For a disk controller,
the last lines name its units:
altairsim> SHOW BOARD dcdd
dcdd MITS 88-DCDD: 8" hard-sector floppy, up to 16 drives...
...
This board has units: drive
SHOW BOARD dcdd UNITS for their properties.
Under the legal values of each setting, SHOW BOARD gives a default: line. It is the value
that the setting has when a machine file does not set it. A setting that only shows live state
has no default, and has no line:
altairsim> SHOW BOARD 2sio
PROPERTY HELP
-------- ------------------------------------------------------------------
port Base address. The board decodes four ports: BASE+0 .. BASE+3
values: 0x0 .. 0xFC
default: 0x10
Add UNITS to see only the units. Each unit has a heading with its kind, and after the
kind, the command that fills it:
altairsim> SHOW BOARD sol units
Unit 'serial' (serial, CONNECT)
PROPERTY HELP
--------- -----------------------------------------------------------------
connect The endpoint on the other end of this line (CONNECT sets this)
...
Unit 'tape1' (tape, MOUNT)
mode Which way the bytes go: play loads from the file, record saves to it
...
- A serial unit is an endpoint, so you
CONNECTit, toconsole, a socket or a real port. - A disk, rom or tape unit holds an image, so you
MOUNTa file in it. - A cpu unit is fixed on the board. It takes neither command, and the heading shows only its kind.
The heading tells you which command a unit takes, before you add the board.
When a machine file fills a unit, UNITS shows the TOML table and its keys instead. For a
disk controller, this is [[board.drive]] with its mount, readonly and media keys. You
can find the file form as easily as the prompt form.
Contention
When two boards decode the same port, that is contention, and it happened on real backplanes too. Both boards answer and both drive the data bus, so the processor reads the wrong value.
The simulator does not stop you from doing this. It tells you about it. For example, add an
mds to a machine that already has a dcdd:
altairsim> BOARDS ADD mds mds0
mds0: mds added
altairsim> SHOW BUS CONTENTION
port 08 OUT driven by dsk0 mds0
port 09 OUT driven by dsk0 mds0
port 0A OUT driven by dsk0 mds0
The output names each port and both boards. You can build a machine that does not work, on purpose, because a wrong setup is part of developing hardware. The program shows you what is wrong.
The boards
The boards are in groups, in the same order as the sections below.
The whole machine
| Type | What it is |
|---|---|
fp |
the front panel |
turnkey |
MITS 8800b Turnkey Module: the Altair with no front panel, on one board |
Memory
| Type | What it is |
|---|---|
memory |
RAM and ROM, as a list of regions |
bankmem |
bank-switched RAM: Vector Graphic, Cromemco 64KZ, North Star HRAM, ExpandoRAM II |
v2z80rom |
the onboard MASTER monitor ROM of the S100Computers V2 Z80 processor board. A paged EEPROM, not a processor |
Processors
| Type | What it is |
|---|---|
8080 |
the MITS 88-CPU |
8085 |
an 8085 processor board. It runs all 8080 code, and adds RIM, SIM and the TRAP and RST interrupts |
z80 |
a Z80 processor board. The same bus, with a different instruction set |
Serial ports and consoles
| Type | What it is |
|---|---|
2sio |
MITS 88-2SIO: two serial ports. The usual console |
sio |
MITS 88-SIO: one serial port. The first MITS serial board |
sbc |
SD Systems SBC-100/200: the serial console, timer and parallel port of a Z80 single-board computer |
gsio |
a generic serial board with two channels, set up with straps |
io4 |
SSM IO-4: two serial ports and four parallel ports |
propio |
S100Computers Console I/O: a serial console built on a Propeller chip |
pmmi |
PMMI MM-103: a Bell 103 telephone modem on one board |
Cassette
| Type | What it is |
|---|---|
acr |
MITS 88-ACR: the cassette interface |
uio |
MITS 88-UIO: a serial port and a cassette interface on one board |
Printers
| Type | What it is |
|---|---|
c700 |
MITS 88-C700: the line-printer controller. Capture to a file |
lpc |
MITS 88-LPC: the other line-printer controller, with a line buffer |
Parallel and analog I/O
| Type | What it is |
|---|---|
pio |
MITS 88-PIO: an 8-bit parallel port, in and out |
4pio |
MITS 88-4PIO: up to four programmable parallel ports |
d7a |
Cromemco D+7A: analog and parallel I/O. Reads joysticks and plays their speakers |
music6 |
Newtech Model 6 Music Board: a 6-bit D/A converter and a speaker |
Floppy and disk controllers
| Type | What it is |
|---|---|
dcdd |
MITS 88-DCDD: the 8″ floppy controller |
mds |
MITS 88-MDS: the 5¼″ minidisk controller |
fdcplus |
FarmTek FDC+: the 1.5 MB floppy, or the serial drive, where the disk images are on a drive server on a serial line |
hdsk |
MITS 88-HDSK: the Datakeeper hard-disk controller |
versafloppy |
SD Systems VersaFloppy I/II: a soft-sector floppy controller. Boots SDOS |
tarbell |
Tarbell #1011: a single-density floppy controller with its own boot PROM. Boots CP/M by itself |
tarbelldd |
Tarbell #2022: the double-density version, for mixed-density disks |
icom |
iCOM FD3712/FD3812: an 8″ floppy controller with its own boot PROM. Boots CP/M and FDOS |
disk1 |
CompuPro Disk 1: an 8″ floppy controller with DMA, its own boot EPROM and a bit-banged serial line. Boots CompuPro CP/M 2.2N |
disk1a |
CompuPro Disk 1A: an 8″ floppy controller with DMA and its own boot EPROM. Boots CompuPro CP/M |
mdsa |
North Star MDS-A: a single-density 5¼″ floppy controller in memory, with its own boot PROM. Boots CP/M and North Star DOS |
mdsad |
North Star MDS-A-D: the double-density version, for one-sided and two-sided disks |
16fdc |
Cromemco 16FDC: a floppy controller with a console UART and the RDOS 2.52 boot PROM. Boots CDOS |
64fdc |
Cromemco 64FDC: a floppy controller with a console UART and the RDOS 3.12 boot PROM. Boots CDOS |
dualsd |
S100Computers Dual SD: two microSD cards as CP/M drives. Boots CP/M 3 |
dualide |
S100Computers IDE-AB: two CompactFlash cards as CP/M drives. Boots CP/M 3 |
Video and display
| Type | What it is |
|---|---|
vdm1 |
Processor Technology VDM-1: memory-mapped video. Needs a display |
dazzler |
Cromemco Dazzler: color graphics. Needs a display |
dazzler2 |
Cromemco Dazzler II: the Dazzler with its picture in RAM on the board. Needs a display |
vdb8024 |
SD Systems VDB-8024: an 80×24 video terminal on one board. Needs a display |
cadzilla |
CADzilla: an HD63484 ACRTC graphics board with a Bt453 color table. Needs a display |
sol |
Processor Technology Sol-PC: the onboard I/O of the Sol-20, on one board |
Interrupts and the clock
| Type | What it is |
|---|---|
virtc |
MITS 88-VI/RTC: vectored interrupts and a clock |
ss1 |
CompuPro System Support 1: a real-time clock, a serial channel, an interval timer and two interrupt controllers |
rtc100 |
SciTronics RTC-100: a battery-backed real-time clock, with an optional interrupt each second |
Host integration
| Type | What it is |
|---|---|
hostbridge |
file transfer to your computer. Our own board, not a period board |
PROM programmers
| Type | What it is |
|---|---|
pb1 |
SSM PB1: program a 2708 or 2716 EPROM, and save it as a hex file |
The whole machine
The front panel, and the turnkey board that replaces it.
fp: the front panel
The front panel is a board, because it was one on a real Altair. It plugged into the bus
like the other boards. On a real Altair, the panel was how you toggled a bootstrap into memory.
Here, the monitor's DEPOSIT does that, and the board gives the machine its sense switches.
The SENSE switches, at port FF
The sense switches are the eight switches on the left of the address switches, SA8 to SA15.
IN FFH reads them. They are read-only. An OUT FF does nothing on this board.
SA15 is the top bit of the byte, and SA8 is the bottom bit. The bits are in the same
order, left to right, as the switches on the panel:
switch SA15 SA14 SA13 SA12 SA11 SA10 SA9 SA8
bit 7 6 5 4 3 2 1 0
value 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01
This makes a period boot procedure easy to follow. "Raise A15 and A11" is 0x80 plus 0x08, or
%10001000 when you write it to look like the panel.
The switches are important. Period bootstraps read the sense switches to decide what to boot from: which device, at which port, and at which speed. For this reason, every tape machine in this package sets them:
sense = 0x80 # basic4k: load from the cassette
sense = %10000000 # the same eight switches, drawn
sense = 0x8E # ps2: the 2SIO, and interrupts off
sense = %10001110 # again, one digit per switch
% is not special to this board. It works for any number, at the prompt and in a machine file.
Do not write 0b here: the switches are a hex setting, and in a hex number B is a digit.
The Monitor gives the full list of prefixes. Binary is easier to read for eight switches.
However you write the value, SHOW fp0 shows it in hex.
If you set the switches wrong, the loader reads a device that is not there, and it gives no error.
sense is a board property, because the switches are on the panel. There is no sense for
the machine, and the program gives an error if you try to set one.
turnkey: the MITS 8800bt, on one board
The 8800b "turnkey" system had no front panel. One board, the Systems Turnkey Module, did
the work of the panel and more. It had the boot PROM, the serial port for the terminal, the
sense switches, and a circuit that booted the machine when you turned it on. This board is that
board, so a turnkey machine has no fp and no separate 2sio. All three are on this
board. altairsim turnkey is the plain machine. Give it a disk and one of the two boot loaders
below (start = "FF00" for the floppy disk, FC00 for the hard disk), and CP/M starts when the
machine turns on.
It boots itself
There is no front panel to toggle in a bootstrap, so the board has an Auto-Start circuit.
RUN 0000 starts the processor at address 0, and the board puts a JMP on the bus, so that the
boot PROM runs first. This is what the START switch on the panel did. The start property is
the START ADDR switches: FF00 runs the floppy loader, and FC00 runs the hard-disk loader.
With startup = ["RUN 0000"] in the machine file, this happens when the program starts.
The boot PROM gets out of the way
The PROM is at FC00–FFFF. A read there gets the PROM, not the RAM under it, until the
first IN from port FE or FF. The PROM then switches itself off, and the machine has the
full 64 KB of RAM. For this reason, this machine has 64K, and a front-panel Altair has 56K.
The PROM does not use the top of memory all the time. It is a boot device that gets out of the
way. The same IN FF that reads the sense switches switches it off. Period software, such as
Altair BASIC and the CP/M loaders, gets the full 64K in this way without knowing about it.
The console and the sense switches
The serial console is the tty unit, at port 10h. It works like channel A of a 2sio, so the
same software drives it. The sense switches are at port FF, as on the front panel. This board
uses FF, so do not put an fp in a turnkey machine. Both boards would answer the port.
The PROM sockets are a list, like the regions of a memory board:
[[board.socket]]
at = 0xFC00 # socket L1: the hard-disk loader
mount = "builtin:hdbl"
Memory
RAM, ROM, and the boards that switch banks of RAM.
memory: RAM and ROM
A memory board is a list of regions. A real S-100 memory board was the same. It had banks of
chips, and each bank decoded the addresses that its jumpers set. A board with 56K of RAM at the
bottom and a 256-byte boot PROM at FF00 was an ordinary board.
For this reason, default has one memory board, and that board holds both the 56K and the PROM.
PHANTOM*: how a boot PROM gets out of the way
The bus has a line called PHANTOM*. A board pulls this line to switch another board off.
When the processor reads the PROM at FF00, the PROM asserts PHANTOM*. The RAM board under it
stops answering, if its jumper tells it to obey PHANTOM*. Two boards decode FF00, and only
one answers.
This is how an Altair with disks boots. The PROM covers the RAM at the top of memory, and the loader runs from the PROM. After that, the loader switches the PROM off, and the RAM under it can be used again. CP/M needs that memory.
Whether a board obeys PHANTOM*, and whether it asserts it, are jumpers on the board. You
set them. If you set them wrong, the machine does not boot, and it does not tell you why. The
bus view in the monitor shows you both boards on the same page.
A plain memory board has no bank switching. Bank switching is a different board, bankmem.
bankmem: bank-switched RAM
When 64K was not enough, S-100 makers put several planes of RAM at the same addresses. A
write-only select port chose which plane the processor saw. Each maker did this in a
different way, so bankmem is one board with four decoders. Its card property selects the
decoder:
card |
Real board | Select port | What a write does |
|---|---|---|---|
vector |
Vector Graphic 64K | 40 |
one bit for each bank: 01→bank 0, 02→1, 04→2 … 80→7 |
cromemco64kz |
Cromemco 64KZ / 64KZ-II | 40 |
8-bit mask: bit N turns bank N on. Several banks can be on (28→banks 3 and 5) |
northstar |
North Star HRAM | C0 |
bit 0 = on or off, bits 1–7 = which bank. Banks change one at a time |
expandoram2 |
SD Systems ExpandoRAM II | FF |
the byte is a page number (see the note below) |
banks sets the number of planes on the board: up to 8 for vector and cromemco64kz, 6 for
northstar, and 10 for expandoram2. fill and seed work as they do on memory. The guest
writes the select port. At the monitor, you can write it yourself with OUT, and SHOW lists
every plane and which plane is on.
The package has no operating system that uses banks. The quickest way to see the board work is from the monitor:
$ altairsim bankmem
altairsim> OUT 40 01
port 40 <- 01
altairsim> DEPOSIT 1000 A0
altairsim> OUT 40 08
port 40 <- 08
altairsim> DEPOSIT 1000 B3
altairsim> OUT 40 01
port 40 <- 01
altairsim> DUMP 1000-1000
1000 A0 .
altairsim> OUT 40 08
port 40 <- 08
altairsim> DUMP 1000-1000
1000 B3 .
OUT 40 08 selects bank 3, because bit 3 is on. It does not select bank 8. The two DUMP
commands read different bytes at the same address, because the plane changed.
The
expandoram2page decode is an approximation. The real board sends the page number through a PROM on the board, and that PROM map is not published in a form that we can copy. For this reason,bankmemselects a plain page. The two stock partitions of the PROM are real:partition = "ex48"gives 48K of banked RAM and 16K of common RAM atC000, andpartition = "ex32"gives 32K of banked RAM and 32K of common RAM at8000.ramsets the RAM on the board, and the program calculates the number of banks from it. The other three cards are exact.
v2z80rom: the S100Computers V2 Z80 processor board's onboard monitor ROM
This board is not a processor. It is the monitor ROM on a real S100Computers V2 Z80
processor board. That ROM is an 8K EEPROM that holds John Monahan's MASTER V6.6 ROM monitor.
A machine that uses this board also needs a z80 board (below) for the processor. The real
board has the Z80 and its own firmware on one board, and here they are two boards.
The EEPROM has two 4K pages, and both pages use the addresses F000–FFFF. A write to port
D3 selects the page. The same write can also switch the EEPROM off, so that the RAM under it
can be used. CP/M does this after it boots, to get a flat 64K of RAM. While the EEPROM is on, a
read in its window gets the EEPROM, not the RAM.
There is no BOOT command. The monitor boots the machine. startup = ["RUN F000"] starts
the monitor. At its -> prompt, the I command boots CP/M 3 from a Dual SD card (below).
The dualsd machine uses this board.
The processor boards
altairsim has three S-100 processor boards: 8080, 8085 and z80. This section applies to
all three. The sections after it describe each one.
The processor is a board like the other boards. It plugs into the backplane, and you can
remove it. With -n, you can build a machine with no processor. The processor board decodes no
ports and no addresses. It runs the program, and it drives the bus to do that. You can put a
z80 where an 8080 was, and the bus, the other boards and the debugger all work the same.
Every processor board has the same three properties:
clock_hz, the crystalidle, which lets the processor rest at a promptachieved_hz, a read-only value: the speed that the processor reached
The crystal is on the board: clock_hz
The crystal is on the processor board, so clock_hz is a property of the board, not of the
machine. clock_hz = 0 is the default, and it means "run as fast as possible". On a modern
computer, that is more than a hundred times as fast as a real Altair.
To run at the speed of a real 2 MHz Altair, type:
SET cpu0 clock_hz=2000000
To use that speed for one run of a machine file, and leave the file as it is, give the setting
on the command line: altairsim mine.toml --set "cpu0 clock_hz=2000000". The machines chapter
describes --set.
The guest sees the same result at either speed. Each instruction takes the same number of
T-states. The crystal changes how the machine feels to you, not what it does. A cassette has its
own speed setting, rate, which the tapes chapter describes.
There is one exception, at the edge of the machine. A guest counts instructions to measure time. At full speed, a guest's "three-second" timeout passes in a few milliseconds of your time. For this reason, a guest that times something outside the machine, such as XMODEM through a serial port, needs the real crystal. The troubleshooting chapter tells you more.
To see how much time has passed for the guest, type SHOW CLOCK:
altairsim> SHOW CLOCK
clock (emulated time -- T-states since POWER, and what they are worth)
elapsed 0.102953 s (205905 T-states)
crystal 2000000 Hz SET cpu0 clock_hz=N
pacing paced -- emulated seconds keep step with real ones
The program counts the T-states since power on, and divides them by the crystal. The result is the guest's time, not your time. A CP/M boot takes the same guest time at full speed and at 2 MHz. Use this number to measure a guest's own timeout.
The pacing line tells you if a run keeps real time. It reads paced when a crystal is
set, and free when clock_hz is 0. A crystal is always kept, also when you start the program
from a script with no terminal. If a script must be fast, leave clock_hz at 0, or put
SET cpu0 clock_hz=0 at the start of the script.
idle: the processor rests at a prompt
At a prompt, a guest only reads the serial status register again and again, and waits for a key.
At full speed, that keeps one core of your computer busy. idle lets the processor rest while
the guest reads an empty keyboard. It is on by default. The busy core then uses a few percent.
The guest cannot see the difference, because the processor starts again as soon as a byte
arrives, before the next read. An XMODEM transfer is correct with idle on.
idle has an effect only at full speed. When you set a crystal with clock_hz, the program
already rests to keep the crystal's time, and the guest's time at a prompt stays correct.
8080: the MITS 88-CPU
The original processor board. The Altair shipped with it, and the other two processor boards replace it. It has all the properties in the section above, and nothing more.
8085: an 8085 processor
The 8085 came after the 8080, and it runs every 8080 program without a change. Of the three processors, it is the nearest to the 88-CPU. Everything in The processor boards above applies. This section gives only what the 8085 adds.
The 8085 adds RIM and SIM, which read and set the interrupt mask and the SID and SOD serial
pins. It also adds its own interrupts, TRAP, RST 5.5, RST 6.5 and RST 7.5, as well as
the 8080's INTR line. The documented instructions are correct. This includes the one
instruction that is different from the 8080: ANA and ANI always set the auxiliary carry. The
undocumented instructions run too, and set the extra V and K flag bits. DISASM marks each
undocumented byte, as DDT does. The built-in 8085 machine has an 8085, 64K of RAM and a
2SIO console.
No board drives the 8085's own pins: the SID and SOD serial lines, and the TRAP,
RST 5.5, RST 6.5 and RST 7.5 interrupt inputs. The S-100 bus does not carry them. Ordinary
interrupts on the INTR line work as they do on the 8080.
z80: a Z80 processor
The other processor that you can put in the machine. It uses the same backplane, with a
different instruction set. Everything in The processor boards above applies. The built-in
z80 machine has a z80, 64K of RAM and a 2SIO console, so that you can try the processor.
Serial ports and consoles
The boards that have a serial port, for a console, a modem or both.
2sio: MITS 88-2SIO
Two 6850 ACIAs, units a and b, with four ports at BASE+0 to BASE+3. The base is 10 hex
by default, which is where every listing of the period expects it.
This is the usual console board, and default has one. CP/M and Microsoft BASIC use this
board.
The two halves are independent
The two units are two separate chips on the same board. Each unit has its own baud rate, its
own connection and its own interrupt setting. For example, unit a can be a console at 9600
baud, and unit b a modem at 1200 baud. One can use interrupts while the other is polled.
The serial chapter tells you what you can connect a unit to: your terminal, a TCP socket, or a real serial port on your computer, with the modem control lines.
sio: MITS 88-SIO
One COM2502 UART, unit tty, with two ports. This was the first MITS serial board. It
came before the 2SIO, and the earliest Altair software uses it. The basic4k machine uses it.
The port must be even. Control is at BASE, and data is at BASE+1.
On the default Rev 1 board, the status bits are inverted
A clear bit means "ready". This is correct for the board, and it is not a bug in the
simulator. MITS changed the board at the factory, and on the changed board, "ready" is bit 7 for
output and bit 0 for input, both inverted. Every program for the 88-SIO expects this. The I/O
routine of basic4k tests for zero, and that is correct.
The rev property selects the board. rev = 1 is the changed board, and it is the default.
rev = 0 is the board as it first shipped, which also shows the two signals, not inverted, on
bits 5 and 1.
in_int and out_int set where the receive and transmit interrupts go, as the pads on the real
board did.
sbc: SD Systems SBC-100/200
SD Systems made S-100 boards for people who wanted a whole computer on as few boards as
possible. The SBC-100 and SBC-200 are Z80 single-board computers, with the
processor, memory, a serial console and more on one board. The sbc board models the parts that
the software uses. They are all in one block of eight ports, 78–7F:
- an Intel 8251 USART console, unit
tty, with data at7Cand status and command at7D - a Z80-CTC at
78–7B, which gives a keyboard interrupt when a byte arrives - a parallel port at
7E–7F. A write to7Fwith bit 1 set switches the onboard memory off - four sockets for onboard PROMs, and 1K of onboard RAM
The 8251 is not the 6850 that the MITS boards use. Software for a 2SIO cannot use it. The SBC's
own SD monitor can. The processor is a separate z80 board, and its clock_hz sets the
speed. variant selects the board: sbc200 or sbc100.
It measures the speed of your terminal
The board has auto-baud. Run altairsim sbc200, and the SD monitor waits for you to press
Return. It times the bits of that one character, and sets its own baud rate to match. A
terminal at any common speed works. Nothing happens until you press Return. The program is not
stopped. It is waiting for that key.
The onboard memory
The jumpers of the real board set where its PROM sockets and its RAM are. The sbc board has
them as properties:
| Property | What it sets | Default |
|---|---|---|
rom_size |
the size of each PROM: 1K, 2K, 4K or 8K |
2K |
bank |
the bank that holds the eight slots. A bank is eight times rom_size |
3, which is C000–FFFF |
ram |
true puts the 1K RAM in the last slot of the bank |
true |
start |
the auto-start address, a multiple of 1000 |
0000, which is off |
With the defaults, the sockets are at C000, C800, D000, D800, E000, E800 and F000,
and the RAM is at F800–FFFF. Put a PROM in a socket with a [[board.socket]] table. The
board refuses an address that is not a socket.
In a machine file:
[[board]]
type = "sbc"
id = "sbc0"
start = E000
[[board.socket]]
at = E000
mount = "builtin:msmonr21"
The machine needs a memory board with RAM under the onboard memory, and that board must have
honors_phantom = "read". The onboard memory answers a read. A write also goes to the memory
board.
Auto-start. A Z80 starts at 0000 after a reset. With start = E000, the board makes the
Z80 read the PROM at E000 after a reset, until the PROM reads port 7F. Then memory is
normal again. Thus RUN starts the monitor, and RESET then RUN starts it again.
The sbc200 machine boots the SD monitor. With the DDBIOS disk BIOS in a PROM socket
and a versafloppy controller, the monitor's C command boots SDOS. See the VersaFloppy
section below.
gsio: the generic serial board, set up with straps
Most serial boards in this chapter model one specific chip, such as the 2SIO's 6850, the
SBC's 8251 or the 88-SIO's COM2502. Software must be written for that chip. gsio is
different. It models no specific chip. You describe the port with straps:
- which port is status and control, and which port is data
- which status bit means that a byte is waiting (
dav) - which status bit means that the transmitter is ready (
tbmt) - whether the shared
inverter_gateinverts both bits
Use it for any polled interface that reads a status bit and then a data byte.
The board has two independent serial channels, units a and b. Each channel has
its own straps, baud and connect, in its own [board.unit.a] or [board.unit.b] table. By
default, a uses ports 0 and 1, and b uses ports 2 and 3.
You seldom set the straps one at a time. A profile sets them to match a known board:
sior1: MITS SIO Rev 1. This is the default, and the SSM 8080 monitor expects itsior0: MITS SIO Rev 0tuart: Cromemco TU-ARTimsai-sio2: IMSAI SIO-2compupro-if2: CompuPro Interfacer IIcompupro-ss1: CompuPro System Support 1
Select a profile for each channel, and then change any strap, as you would move a jumper. The board is polled, with no interrupts. It only sends and receives bytes. It does not model word length, parity or stop bits. A board that needs those is a separate board with a full model.
io4: SSM IO-4 (2P + 2S)
gsio describes a serial port with straps. io4 is a specific board, the SSM IO-4. It
has two full-duplex serial channels and four latched parallel ports. Each serial channel
is a real UART with programmable word length (5 to 8 bits), parity, stop bits and baud. The
status byte can be strapped in many ways, as on the real board.
The two serial channels are units a (Serial A) and b (Serial B). Each has its
own [board.unit.a] or [board.unit.b] table, its own baud and its own connect. The serial
half uses a block of four ports, which must start at a multiple of four (default 0–3). a
uses ports 0 and 1, and b uses ports 2 and 3.
Set the straps, or select a profile
The IO-4 had many jumpers, and each jumper is a property here:
- which data bit means that a byte is waiting (
stat_dav) - which data bit means that the transmitter is ready (
stat_tbmt) - four more status signals:
stat_teoc,stat_ror,stat_rpeandstat_rfe - whether the whole status byte is inverted (
invert_status) - whether the status port and the data port change places (
port_reversal)
You seldom set these one at a time. A profile sets them to match a known host:
altair-rev1 (the default, the MITS SIO Rev 1 console that the SSM 8080 monitor expects),
altair-rev0, i8251, proctech, imsai, and custom (all straps free for you to set).
Select a profile, and then change any strap, as you would move a jumper.
You can strap the three UART error flags (parity, framing and overrun) to the status byte, but they always read as inactive. The serial line carries exact bytes and has no line noise. The current-loop and RS-232 options of the real board are electrical, not programmable, so they are not modeled.
The parallel half
The other half is four 8212 latched ports, two for input and two for output, as units
pa and pb (Parallel A and B). They use their own block of two ports (default 4 and
5), which must start at an even port. An input port latches a byte on its strobe and sets a
service-request flip-flop. A read gets the byte and clears the request. CONNECT io40:pa …
connects a port to a source or a sink of bytes, like a serial line. The dav_bit, dav_source
and dav_active_low straps set up a console with its status byte on one port and its data byte
on the other.
If the two blocks of ports overlap, neither half answers on the shared ports. The real board was designed this way. It is not two boards on the same address.
Interrupts, if you strap them
The W4 header of the board sets the interrupts, and io4 follows it. Each serial channel's
receive (rx_int) and transmit (tx_int), and each parallel input (int), can go to a
vectored interrupt line, to the plain interrupt pin, or to none. There is no software
enable. The strap is the enable, as on the real board. With no straps, the default, the board
is polled. A strapped transmit interrupt stays on while the transmitter is idle. A parallel
input sets its interrupt on the strobe, also when nothing reads the port. Connect these to a
virtc, and a received character or a parallel strobe goes to the RST that you strapped.
SHOW io40 shows every unit, its ports and the live state of its lines.
propio: S100Computers Console I/O
A serial console from the modern reproduction boards: the S100Computers Console I/O board.
It uses a Parallax Propeller chip, not a 6850 or an 8251, with status at 00 and data at 01.
It is a polled console, unit serial. You CONNECT it to a terminal, a file, a socket or a
serial port, like other serial boards. The Dual SD machine uses it as its console.
propio is a preset of the serial model that gsio uses (above). The preset sets the ports
of this board, and which status bits mean "receive ready" and "transmit ready". The real board
has jumpers, so you can still change each strap. A Console I/O board with different jumpers
needs only a property or two, not a new board type.
pmmi: PMMI MM-103 modem
A Bell 103 telephone modem on one S-100 board. It was the first S-100 modem that was
approved for a direct connection to the telephone line. In a real machine, it dialed, answered
and carried a serial link at up to 600 baud. It has unit line, and four ports from a base that
must be a multiple of four. The default base is C0. The DIP switch on the real board set it,
and the North Star software of PMMI used E0.
A read and a write at the same port are different registers:
| Port | Write | Read |
|---|---|---|
| BASE+0 | character format and modem control | UART status |
| BASE+1 | transmit | receive |
| BASE+2 | baud-rate divisor | modem status |
| BASE+3 | the modem chip's control word | nothing that the board drives |
The three control registers are write-only. The program must keep its own copy of what it wrote, as it did on the real board.
The telephone line
The board does not model the tones of a Bell 103. The line carries exact bytes. You choose what is at the other end of the line:
dial = "host:port"is the number that the modem calls. When the guest takes the line off the hook and raises DTR, the board opens a TCP connection tohost:port.answer = portmakes the board answer calls. A TCP connection to that port rings the guest, and the guest answers it as it would answer a telephone call. When the guest drops DTR, the call ends, and the board waits for the next caller.- On a
dialoranswerline,telnet(on by default) uses the Telnet protocol. A person with atelnetclient then gets no double echo, and sends one key at a time. Settelnet = offfor a raw connection, for example to another simulator. CONNECTconnects the line to something else, as for other serial boards. With a real serial port, the guest's DTR goes to the port, and the port's CTS, DCD and RI come back in the modem status.rtsdtr = onmakes RTS follow DTR, for a cable that needs it. With a file or a socket, the modem status always reads "connected and ready".
The board does not decode the dial pulses of the guest into a telephone number. The dial
property gives the number. The board also raises no interrupts.
SHOW pmmi0 shows the live character format, baud rate, UART flags and modem lines, with the
base address. To try the board, add it to default. BOARDS ADD pmmi pmmi0 adds it at C0.
Cassette
Boards that read and write cassette tape.
acr: MITS 88-ACR
The cassette interface. It is an 88-SIO channel B with an FSK modem, so a byte on the bus
becomes a tone on a tape, and a tone becomes a byte again. It has unit tape and default port
06. It runs at 300 baud, because that is what an audio cassette could carry.
With this board, an Altair needs no disk and no PROM. You enter a bootstrap by hand and load the
program from a cassette. The tapes chapter describes this board: how to load Altair 4K BASIC
3.1, and the WIND, REWIND and EXTRACT commands.
uio: MITS 88-UIO
A serial port and a cassette interface on one board. The Universal I/O board is almost a
2SIO channel and an 88-ACR on the same board, with some parts shared. It has the same addresses
as the two boards that it replaces: a 6850 serial port at 10 (unit serial) and a
cassette section at 06 (unit tape). Software that expects a 2SIO console and an ACR tape
finds both.
It adds motor control and a modulation switch. SW-1 selects one of the two encodings
of the period: the MITS 300-baud format or the Kansas City standard. The tape section has the
same WIND, REWIND and EXTRACT commands and the same tape counter as the 88-ACR.
Printers
Line-printer controllers. Each one sends its output to a file or to a print queue.
c700: MITS 88-C700
The line-printer controller, an output-only board for an Altair C700 printer. It has unit
prn and default port 02, which is the MITS default: control and status at 02, data at
03.
The package has no printer, so CONNECT the prn line to where you want the output:
- a file:
CONNECT lpt0:prn out:printout.txt - the
console, to see it print while it runs - a
socket: - a real
serial:printer - a real print queue on your computer:
CONNECT lpt0:prn printer:linewriter. This works when your build found a print system. The serial chapter gives the options.
The output is the exact bytes that the program sent, with the control codes. It is not a formatted page.
You can use the board polled or with interrupts:
- Polled: write a character to the data port (
03). Before the next character, read the status port (02) until bit 0, ACKNOWLEDGE, is set. - Interrupts: set control bit 1 to turn on its single-level interrupt. The printer then interrupts the processor each time it takes a byte, and the handler sends the next byte.
The interrupt strap selects the line: pin 73 (int, the default), a vectored interrupt level
(vi0 to vi7), or none. interrupt_after is switch SW2 #4 of the board. It sets whether
the interrupt comes after every character, or only after a CR or LF.
The lineprinter machine is default with one of these boards added. Its output starts on
null. To capture it, type CONNECT lpt0:prn out:printout.txt. To see it, connect it to
console, which takes the console from the terminal.
lpc: MITS 88-LPC
The other line-printer controller, for the 88-LP printer. The c700 drives the C700
printer. The lpc has the same two ports: control at an even base and data above it, with the
MITS default 02. It drives the printer as the real one worked, and the output shows the
difference.
The C700 passes every byte through. The LPC prints a line at a time. The guest loads a 6-bit character code at a time into an 80-character line buffer. Nothing prints until the guest sends a PRINT command, or the buffer is full. LINE FEED and CLEAR are also commands. For this reason, the output is the printed page: the codes changed to characters, one text line for each printed line. On this board, the line breaks are commands, not data.
CONNECT its prn line to an out: file, the console, a socket: or a real printer:
queue. The lineprinter-lpc machine has one at 02, with its output on null until you
CONNECT it. The board is polled. The interrupt of the real board is not modeled.
Parallel and analog I/O
Parallel ports, one board that also reads analog inputs, and a music board.
pio: MITS 88-PIO
An 8-bit parallel port, in and out. It is the simplest way to move a byte that is not a
serial character. It has two lines that you connect separately: out for an output device
(a printer or a socket), and in for an input device (a keyboard or another socket). For
example, one board can write to an out: file and read a keyboard from the console at the
same time. The default ports are 04 and 05. The board is polled. A byte moves when a
driver reads the status port for it.
4pio: MITS 88-4PIO
The programmable version of the pio. It has up to four Motorola 6820 PIAs on one board,
and the guest sets the direction of each port in software. Each port is a section (ja,
jb and so on), and each section is a line that you can connect. It uses sixteen ports from a
default base of 20. It is polled, like the pio.
The pio has a fixed eight bits each way. The 4pio can be set up as the software needs. The
parallel machine has both boards, and the pio sends its output to a file.
d7a: Cromemco D+7A
An analog and parallel I/O board. It has one parallel port and seven analog channels, in
a block of eight ports (default base 18). Each analog channel is an A/D converter when you
read it and a D/A converter when you write it, in 8-bit two's complement: 00 is 0 V, 7F is
about +2.5 V, and 80 is about −2.5 V. On a real bench, it read sensors and drove instruments.
Here, it is the input and the sound of a game console. It reads one or two JS-1 joysticks. The X and Y controls go to analog channels. The four buttons of each stick are active-low bits in the parallel byte: the low four bits for one stick, and the high four bits for the other. The sticks come from a USB gamepad on your computer, or from the keyboard (the arrow keys and a few other keys) when there is no gamepad.
joystick1 and joystick2 select the device on your computer for each stick. Both are auto
by default, which gives each stick a different gamepad: stick 1 gets gamepad 0, and stick 2
gets gamepad 1. Two controllers work with no setup, and each stick uses the keyboard when its
gamepad is not there. SHOW <id> shows what each stick uses now (a named controller, the
keyboard, or nothing). SHOW JOYSTICKS lists the controllers that your computer has.
A machine that uses the sticks can set its video window to be a display, not a keyboard
([display] keyboard = none). Your keys then move the stick and do not go to a prompt.
The board also plays the speaker of each JS-1. A JS-1 has no sound chip. The guest writes a waveform to an analog channel, and the speaker plays the voltage. You hear it on the sound output of your computer.
speaker1 and speaker2 give the analog channel of each speaker. The value is none or a
channel from 1 to 7, and channel n is port base + n. The defaults are channel 1 (port
19) for stick 1 and channel 3 (port 1B) for stick 2. Some software writes the second
speaker to port 1A. For that software, set the channel to 2:
altairsim> SET d7a0 speaker2=2
In a machine file:
[[board]]
type = "d7a"
id = "d7a0"
speaker2 = 2
Sound needs a crystal. At full speed (clock_hz = 0, the default), the guest does not keep
real time, and the board plays nothing. With a crystal the machine keeps real time, also when
you start it from a script with no terminal. Set the speed of the machine to hear the
sound:
altairsim> SET cpu0 clock_hz=4000000
The dazzler machine sets 4 MHz already.
SHOW <id> has one line for each speaker. The end of the line tells you the state:
| The line ends with | Meaning |
|---|---|
-> playing |
The guest changed the speaker output in the last half second of machine time. |
-> silent |
The guest does not drive the speaker now. |
-> silent: the machine has no crystal (clock_hz = 0) |
The machine runs at full speed. Set clock_hz. |
-> no sound device |
The program cannot open a sound output on your computer, or this build has no sound. |
-> unwired |
The setting is none. |
The timing of the board is not complete. A real D+7A holds the processor for a short time on each analog read and write, and the simulated board does not. A guest that makes a tone with a tight loop plays it at a higher pitch than on a real board.
music6: Newtech Model 6 Music Board
A music board: one output port, a 6-bit D/A converter, an amplifier and a speaker. The board has no sound chip and no timer. A program makes the sound. It writes a value to the port, waits, writes the next value, and the speaker plays the voltage. The time of the loop is the pitch. You hear it on the sound output of your computer.
The default port is 24. The board answers at four addresses, the port and the next three
(24 to 27), because the real board does not decode the low two address lines. The port
setting takes the sixteen addresses that the jumpers of the board can select: 04, 14, 24
and so on to F4.
altairsim> BOARDS ADD music6 music0
altairsim> SET music0 port=44
In a machine file:
[[board]]
type = "music6"
id = "music0"
port = 0x44
The board uses the top six bits of the byte. The low two bits do nothing, so a program that changes only bit 0 or bit 1 is silent. The board has no input port: you cannot read the value back. A reset does not clear the value. Only the power switch does.
Sound needs a crystal. At full speed (clock_hz = 0, the default), the guest does not keep
real time, and the board plays nothing. With a crystal the machine keeps real time, also when
you start it from a script with no terminal. The programs that Newtech supplied with
the board are timed for an 8080 at 2 MHz:
altairsim> SET cpu0 clock_hz=2000000
This short program is the test routine from the manual of the board. It plays a steady tone of about 1009 Hz:
altairsim> DEPOSIT 0 97 06 40 05 C2 03 00 2F D3 24 C3 01 00
altairsim> RUN 0
SHOW <id> gives the value in the latch and a line for the speaker. The end of the speaker line
tells you the state:
| The line ends with | Meaning |
|---|---|
-> playing |
The guest changed the output in the last half second of machine time. |
-> silent |
The guest does not drive the board now. |
-> silent: the machine has no crystal (clock_hz = 0) |
The machine runs at full speed. Set clock_hz. |
-> no sound device |
The program cannot open a sound output on your computer, or this build has no sound. |
The amplifier and the volume control of the real board are not modeled. Set the volume on your computer.
Floppy and disk controllers
The disk controllers, from 8-inch floppy disks to CompactFlash. Several of them boot an operating system by themselves.
For most of these controllers, the package has a built-in machine but no disk image. The machine starts with empty drives, and you supply the image. The disks chapter tells you how to mount one.
Disk timing: timing
Some of these controllers stop the processor with wait states until the disk has the next
byte. They are the tarbell, tarbelldd, versafloppy, 16fdc, 64fdc, mdsa and mdsad.
The timing setting of the board sets how long the wait takes:
full(the default): the byte is ready at once, and the wait takes no time. A seek also takes no time. Disk access is as fast as possible.real: the wait takes as long as on the real machine. A seek takes the step time of each track, and each byte comes at the speed of the disk. The processor loses that time, as it did on the real machine.
The bytes on the disk are the same with both settings. Use real for a guest that measures
time with the disk, or to see how fast the machine really was:
altairsim> SET fdc0 timing=real
In a machine file:
[[board]]
type = "tarbell"
id = "fdc0"
timing = "real"
With real, the processor must be fast enough for the disk, as on the real machine. On the
tarbelldd, a double-density disk without DMA needs a 4 MHz processor (clock_hz = 4000000). At
2 MHz, the guest loses data and reports a disk error.
dcdd: MITS 88-DCDD
The 8″ hard-sector floppy controller. It has up to sixteen drives, and three ports at 08,
09 and 0A. CP/M booted from this board, and default has one.
It can also use the 8 MB medium, a large format that the same controller can address. You supply the image. The package has no 8 MB disk.
Its status bits are inverted, as on the 88-SIO. A clear bit means "ready". The interrupt
strap sets where the board's interrupt goes.
The machine must run at 2 MHz, or at full speed. The software for 8″ disks (Disk BASIC,
Altair DOS, CP/M) reads and writes two bytes each time through its loop, and it times the second
byte for a 2 MHz processor. At full speed, the board keeps the same 2 MHz time as the processor,
so the disk works. With a faster clock_hz, the software reads each byte before it arrives, as on
a real Altair with a fast processor, and the disk does not work. The boot PROM then prints C
again and again.
The disks chapter describes this board: the formats, how to mount a disk, write protection, and
the track buffer, which is why you go back to the A> prompt before you stop the machine.
mds: MITS 88-MDS
The 5¼″ minidisk controller, with four drives. It has the same registers as the DCDD, so a program for one board drives the other. The drives are different:
dcdd |
mds |
|
|---|---|---|
| Spindle | 360 RPM | 300 RPM |
| Byte time | 32 µs | 64 µs |
| Motor | always turning | stops after 6.4 seconds |
The minidisk motor does not turn all the time. It starts, and if nothing uses the drive, it
stops again. The software must handle this. To see it do that, set motor to real. The
default is free: the motor is always at speed, with no wait. The DCDD has no such setting,
because its motor never stopped.
You supply the minidisk image. The minidisk machine boots its PROM, but the package has no
5¼″ image, so the drives start empty.
It cannot be in the same machine as a dcdd
The two boards use the same three ports. This is the MITS address map. A real Altair with both boards would have them both on the data bus at the same time. If you add both here, the bus view names the conflict. Use one or the other.
fdcplus: FarmTek FDC+ serial drive and 1.5 MB floppy
The FDC+ is a modern board that replaces the 88-DCDD and the 88-MDS. Its drive type switches select what it does. This board does three drive types: 5, the 1.5 MB floppy (see The 1.5 MB floppy below), and 6 and 7, the serial drive.
In its serial drive mode it has no disk drive. A drive server on another computer keeps the disk images, and the board gets a whole track at a time over a serial line. To the software, the board is an 88-DCDD or an 88-MDS, so CP/M and the boot PROM work as they are.
Use it to use the images on a drive server, to share one set of images between the simulator and a real FDC+ Altair, or to test a drive server.
| Property | What it sets |
|---|---|
drivetype |
7: the server's disks are 8″ disks, including the 8 MB disk. 6: they are minidisks. 5: the 1.5 MB floppy, below. The board reads this at power-on, as the real switches are read. |
connect |
The drive server. CONNECT fdc0:line sets it too. |
baud |
The speed of the serial line: 9600, 19200, 38400, 57600, 76800, 230400, 403200 or 460800. Set the same speed on the server. The default is 403200, the fastest reliable speed. |
port |
08, or 80. The board uses four ports. |
The server mounts the images, not the simulator. MOUNT on fdc0:line gives an error. A
drive that has no image on the server is not ready, as an empty drive is.
Do not run the machine at full speed. A guest counts instructions to measure time, and CP/M stops looking for a sector after 1.4 seconds of its time at 2 MHz. At full speed, that is a few milliseconds, and a track takes longer than that to arrive. A faster crystal is possible if the line is fast too: 10 MHz with 230400 baud works, and 38400 baud needs 2 MHz.
To use a server on /dev/cu.usbserial-AL009KFH at 38400 baud in the default machine:
altairsim> BOARDS REMOVE dsk0
altairsim> BOARDS ADD fdcplus fdc0
altairsim> SET cpu0 clock_hz=2000000
altairsim> SET fdc0 baud=38400
altairsim> CONNECT fdc0:line serial:/dev/cu.usbserial-AL009KFH
altairsim> RUN FF00
The default machine's dcdd uses the same ports, so remove it first. On Windows, the device is
a name such as serial:COM3. CONFIG SAVE saves the machine to a file, so that you do the
setup only once.
A slower line makes a slower disk. At 38400 baud, a track takes about one second. When the machine
is not using the disk, the board writes changed tracks back to the server after about one second.
It also writes them back before a DISCONNECT, a POWER, or when you quit.
If nothing comes after RUN FF00, the server did not answer. The boot PROM has no time
limit: it waits until the drive is ready, and the drive is ready only when the server answers.
A real FDC+ does the same. To see what the line does, turn on the board's error debug flag:
altairsim> SET fdc0 DEBUG=error
It reports a server that does not answer (one time, and again when it answers), a track with a
bad checksum, a track that did not arrive in full, and each write that the server did not take.
The link flag shows the same, and also each request and each track. The debugging guide
tells you where the reports go.
The 1.5 MB floppy (drive type 5)
With drivetype = 5, the FDC+ runs a high-density floppy drive in a format of its own: each
track is one sector of 10,240 bytes, on both sides of the disk. A disk holds 1,525,760
bytes, five times an Altair floppy. The board has four drives, drive0 to drive3, and you
put a disk image in one with MOUNT. The serial line is not used.
A stock Altair boot PROM boots this disk. The PROM cannot read a 1.5 MB disk. But when the
PROM asks for a sector, the FDC+ gives it a sector of its own. That sector holds a short loader,
and the loader reads the real disk. So RUN FF00 works with the DBL PROM of the default
machine.
The machine must run at 2 MHz, or at full speed. The CP/M for this disk moves a track with no
handshake: it reads a byte every 17 µs, slightly slower than the disk, and writes one every 14
µs, slightly faster. Those are 2 MHz loops. At full speed, the board keeps the same 2 MHz time as
the processor, so the disk works. With a faster clock_hz, CP/M reads bytes before the disk has
sent them, as on a real Altair with a fast processor, and the disk does not work.
To boot a CP/M disk image for this drive in the default machine:
altairsim> BOARDS REMOVE dsk0
altairsim> BOARDS ADD fdcplus fdc0
altairsim> SET fdc0 drivetype=5
altairsim> POWER
altairsim> MOUNT fdc0:drive0 CPM22-48K-HDF.dsk
altairsim> RUN FF00
The board reads drivetype at power-on, so POWER comes after it. A disk that is mounted
read-only is write-protected. The CP/M for this disk refuses to write to it, and CP/M then
shows Bdos Err On A: Bad Sector.
hdsk: MITS 88-HDSK Datakeeper
A hard-disk controller, the "Datakeeper". CP/M boots from it when it does not boot from a
floppy disk. It is a separate controller with a command and handshake protocol and four
256-byte page buffers. Unlike the floppy disk boards, it moves whole sectors for you. It
does not shift bits in real time. It has eight ports, default A0–A7.
The HDBL boot PROM at FC00 reads the descriptor page of the disk and starts the system.
With a CP/M 2.2 disk image mounted, you get an A0> prompt. The disk is read/write, and
CP/M saves to it.
versafloppy: SD Systems VersaFloppy I & II
The soft-sector floppy controller of SD Systems, built on a Western Digital FD177x. It is the board that boots SDOS, a CP/M-compatible system, on an SBC-200.
One board type covers both versions. variant selects the version:
vfii(the default): the double-density VersaFloppy II, with an FD1791vfi: the single-density VersaFloppy I, with an FD1771
The two versions differ only in the controller chip and a few control bits. They have the same
eight ports (default 60) and the same drivers. Neither version has a boot PROM. The boot BIOS
is in a separate PROM, which is the onboard socket on an SBC-100/200.
Add a vfii, mount an 8″ double-density SDOS disk, and use the DDBIOS of the SBC-200. The
disk commands of the monitor then work: C boots SDOS, and R and W read and
write sectors.
It checks the density
The density bit of port 63 must agree with the density of the track, as on the hardware. A
read at the wrong density ends in Record Not Found, and a seek with verify ends in Seek
Error. The DDBIOS finds the type of a disk this way: it reads an address at double density
first, then at single density. A single-density disk boots, and a double-density disk boots as
before.
It cannot format a blank disk
The Z command formats a disk. On this board, it cannot make a disk from nothing. A disk
image holds only the data. It has none of the gaps and address marks that a real format writes
between the sectors, so a low-level format has nothing to write. The controller reports a WRITE
FAULT. Mount a disk that already has a format, and reads and writes work. For a new SDOS disk,
copy a disk that is already formatted. The iCOM board has the same limit. The Cromemco boards
(below) can format a blank disk.
tarbell: Tarbell #1011 single-density floppy
The Tarbell Electronics #1011 (July 1977) was the S-100 floppy interface that booted CP/M on
many Altair and IMSAI machines. It is a Western Digital FD1771 soft-sector controller with
eight ports, default F8. Unlike the VersaFloppy, it has its own 32-byte boot PROM, so you
do not type a boot command.
Turn the machine on with a disk in drive 0, and the machine boots itself. RESET puts the PROM at
address 0000, over the bottom of memory. The PROM reads the first sector from the disk. When
the loaded code runs, the PROM switches off, and CP/M starts. The tarbell machine has this
board. Mount a CP/M disk in drive 0, and you get the A> prompt with no monitor first. With no
disk in the drive, the PROM has nothing to load, and it stops. Put a disk in and reset.
The bootstrap switch turns the PROM off. The board is then a plain disk controller, for a
machine that boots in a different way. It has four drives, which the software selects. The disks
are 8″ single density, with 128-byte sectors. The board recognizes a disk by the size of its
image.
tarbelldd: Tarbell #2022 double-density floppy
The #2022 (1979–80) is the #1011 with a Western Digital FD1791, which reads double
density as well as single density. It boots in the same way, with the same boot PROM and the
same F8 ports. It boots from a mixed-density disk: the first track is single density, so
that the boot PROM can read it, and the other tracks are double density. The tarbelldd machine
boots CP/M 2.2 from a disk of this kind.
This board does everything that the tarbell does. It adds double density, and a DMA
register at port FD. With DMA, the board moves data to memory itself, without the processor.
Use this board for a double-density Tarbell image, and the tarbell for a single-density image.
The board recognizes the two kinds by the size of the image.
The board checks the density. The density bit of OUT FC must agree with the density of the
track, as on the hardware, and a read or a write at the wrong density gives Record Not Found.
A mixed-density disk needs a boot loader that sets the bit for the double-density tracks. The
two double-density CP/M disks of the Tarbell example have one. A disk of your own with an older
loader, one that reads track 1 with the bit clear, does not boot: write its boot sector again
with a loader that sets the bit.
icom: iCOM FD3712 / FD3812 8″ floppy
An 8″ floppy controller of a different kind. Like the Datakeeper, it uses commands and a
handshake. It does not shift bits. It holds a whole sector, and the processor moves the bytes
through two ports (default C0–C1). The disk driver of the operating system is in a boot
PROM in high memory. One board covers both iCOM versions: the single-density FD3712, and
the double-density FD3812. The FD3812 disk is mixed density, with a single-density track 0
and double-density tracks after it. The board recognizes the two by the size of the image.
The rom property selects the PROM, and the PROM selects the system that boots:
builtin:icom-fd3712-cpm(the default) boots CP/M 2.2, single density, from the PROM atF000.builtin:icom-fd3812-cpmboots CP/M 2.23, double density, also atF000.builtin:icom-fd3712-fdosboots iCOM's own FDOS from the PROM atC000. FDOS is not CP/M. It has a!prompt, and its ownLIST,EDIT,ASMBand other commands.
The icom machine boots CP/M 2.2 as soon as you mount a disk. Reads and writes of a formatted
disk work. Like the other controllers here, it cannot format a blank disk from nothing.
disk1a: CompuPro Disk 1A
The CompuPro Disk 1A (1984) is a floppy controller with an NEC µPD765A chip, a DMA
engine and a boot EPROM. It has four ports at C0–C3, and up to four drives. The board
moves each byte between the disk and memory itself, without the processor.
The boot EPROM holds sixteen 512-byte routines. The routine switch picks one, and RESET puts
it at address 0000. Routine 0, the default, reads track 0 of drive 0 into memory at 0100.
It then switches the EPROM off and starts the loader that it read. The boot switch turns the
EPROM off, for a machine that boots in a different way.
The disk1a machine has this board, a Z80 processor, 64K of RAM and a System Support 1.
The console is the serial port of the System Support 1. The machine starts the EPROM at once.
With no disk in drive 0, routine 0 tries again and again. To boot a CompuPro CP/M disk:
- Press
Ctrl-Eto get the monitor. - Mount the disk in drive 0.
- Run from
0000.
altairsim> MOUNT fd0:drive0 "CCPM22.DSK"
altairsim> RUN 0
The board recognizes a disk by the size of its image. An 8″ CompuPro disk has a single-density
track 0, which the EPROM reads, and its other tracks can be double density. A disk can have one
side or two. A smaller image that has no known size is a blank disk. CompuPro's FORMAT.COM
formats it.
A blank disk needs media, which gives the diskette its size and sides. 8ds is an 8″ disk with
two sides, and 5ss is a 5.25″ disk with one side. Without media, the board refuses a blank,
and the error names the values to set. This command puts a blank 8″ two-sided disk in drive 1:
altairsim> MOUNT fd0:drive1 BLANK.DSK CREATE media=8ds
In a machine file:
[[board]]
id = "fd0"
[[board.drive]]
unit = 1
mount = "BLANK.DSK"
media = "8ds"
create = true
create makes the empty file BLANK.DSK if it is not there. The drive keeps its media when
MOUNT puts a different disk in it.
Three 5.25″ formats have 327,680 bytes, and two have 655,360 bytes. The board refuses an image
of these sizes, because the size does not tell it the format. Set media to the whole format,
such as 5ds-dd512 for two sides of 8 × 512-byte sectors. The error message names the values
that fit the image.
These things are not part of the board:
- A 5.25″ disk boots from unit 2. Routines 2 and 3 of the EPROM read it.
- Only routines 0–3 run. The other routines are for the 8086, 68000 and 32016 processors.
- CompuPro CP/M 2.2Q does not run. Its BIOS needs the 8088 of the CompuPro CPU 8085/88 board.
disk1: CompuPro Disk 1
The CompuPro Disk 1 (1981) is the board that came before the Disk 1A. It has the same
NEC µPD765A chip, DMA engine and four ports at C0–C3, and up to four drives. Port 3
is different. On the Disk 1, bit 7 of port 3 is a serial line with no UART. A guest program
sends and receives each bit itself, with a delay loop for the timing.
The boot EPROM holds eight 256-byte routines. The routine switch picks one, and RESET puts it
at address 0000. The built-in EPROM is a copy of a factory EPROM. Routines 4–7 are for the
8080, 8085 and Z80, and routine 4 is the default. Each reads the start of track 0 of an 8″ disk
in drive 0 into memory at 0100, switches the EPROM off, and starts the loader. Each routine
passes a different console code to the loaded system:
| Routine | Console of CompuPro CP/M 2.2N |
|---|---|
| 4 | The Interfacer at 00/01 |
| 5 | An Interfacer at 10/11 |
| 6 | The serial channel of the System Support 1 |
| 7 | An Interfacer 3 or 4 at 10 |
Routines 0–3 are for the 8086 and do not run here.
The disk1 machine has this board, a Z80 processor, 64K of RAM, a System Support 1 and an
Interfacer I console. The console is the first serial port of the Interfacer I, at ports 00
and 01, as the CompuPro CP/M 2.2N BIOS expects. To boot a CompuPro CP/M 2.2N disk:
- Press
Ctrl-Eto get the monitor. - Mount the disk in drive 0.
- Run from
0000.
altairsim> MOUNT fd0:drive0 "CPM22N.DSK"
altairsim> RUN 0
To use the System Support 1 as the console, set routine 6 and move the console:
altairsim> SET fd0 routine=6
altairsim> CONNECT if1:a null
altairsim> CONNECT ss1:serial console
Each boot logs one line, fd0: serial: a break on the line (no stop bit); nothing sent. The
CP/M 2.2N BIOS sets bit 7 of port 3 to 1, and 1 holds the serial line at SPACING. Nothing is
connected to the line, so nothing is lost. To use the line, connect its serial unit:
altairsim> CONNECT fd0:serial telnet:2323
altairsim> SET fd0:serial baud=1200
Set baud to the rate of the guest's delay loop.
To format a blank disk, give its drive media = "8ds", an 8″ disk with two sides. Without
media, the board refuses a blank, and the error names 8ss and 8ds. This command puts a
blank 8″ two-sided disk in drive 1:
altairsim> MOUNT fd0:drive1 BLANK.DSK CREATE media=8ds
In a machine file:
[[board]]
id = "fd0"
[[board.drive]]
unit = 1
mount = "BLANK.DSK"
media = "8ds"
create = true
create makes the empty file BLANK.DSK if it is not there. FORMAT.COM formats drive B
with two sides, and STAT B: reports a 1200K drive.
These things are not part of the board:
- The board runs 8″ drives only. A Disk 1 ran 5.25″ drives only after a change to the board's parts and wiring. The board refuses a 5.25″ disk image.
- The M-Drive/H RAM disk is not part of the machine. The 2.2N BIOS reports
0 M-Drive/Hand continues.
mdsa and mdsad: North Star MDS-A and MDS-A-D
The North Star Micro-Disk System was a 5¼″ hard-sector floppy system for 8080 and Z80
machines. The mdsa is the single-density controller of 1977. The mdsad is the
double-density controller of 1978, which also reads and writes single density.
These boards have no ports. Each one decodes a 1 K block of memory, from E800 to EBFF.
A program gives a command when it reads an address in the block. The low byte of the address is
the command, or the data byte to write. A read of EB90 on the mdsa starts the drive motors
and returns a status byte.
A DUMP of the block gives commands to the board. DUMP and EXAMINE read memory as the
processor does, and on this board a read is a command. DISASM and the debugger look at
memory without a read. They show the boot PROM, and FF for the other addresses.
Each board has its own 256-byte boot PROM in the block. The northstar machine has an
mdsa, and the northstardd machine has an mdsad. The drives start empty, and you supply
the image. To boot a disk:
- Start the
northstarmachine. - Mount the image in the first drive:
MOUNT fd0:drive0 <file>. - Start the boot PROM:
RUN E900.
mdsa |
mdsad |
|
|---|---|---|
| Start the boot PROM | RUN E900 |
RUN E800 |
| Drives | 3 | 4 |
| Density | single | single and double |
| Sides | 1 | 1 or 2 |
The motors stop after (motor = real) |
3.2 seconds | 9.6 seconds |
drive0 is the drive that North Star software calls drive 1. The units of a board start at
0, as on every controller. North Star DOS and the boot PROM start at 1.
The board recognizes a disk by the size of its image. An image holds only the data of each sector:
| Format | Sectors | Bytes/sector | Sides | File size | Board |
|---|---|---|---|---|---|
sd |
35 × 10 | 256 | 1 | 89,600 | mdsa, mdsad |
dd |
35 × 10 | 512 | 1 | 179,200 | mdsad |
quad |
35 × 10 | 512 | 2 | 358,400 | mdsad |
The boot PROM of the mdsad boots a double-density disk. To boot a single-density disk, use
the mdsa. The mdsad reads and writes a single-density disk in a drive that it does not
boot from.
An empty file is a blank disk. On the mdsa, a blank disk is single density. On the mdsad,
a blank disk gets its density from the first sector that the guest writes, which is what the
format command of the guest decides. On the mdsad, a file of any other size does not mount.
Set media on the drive to give the format.
One image has one density. The mdsad does not write a single-density sector to a
double-density image, and the monitor tells you when the guest tries. A write-protected disk
shows in the status byte of the board, so the guest knows before it writes.
motor works as it does on the mds. With free, the default, the motors run until the guest
stops them. With real, they stop after the time in the table, and the guest starts them again.
interrupt sets where the interrupt of the board goes. The board makes an interrupt at each
sector, 50 times a second, only when the guest arms it. North Star DOS and CP/M do not arm it.
base moves the block, but the boot PROM in the board is the standard part, which runs only at
E800.
Double-density North Star DOS and the memory at 2000
Double-density North Star DOS keeps the track of drive 1 in the byte at 2000. It reads that
byte before it writes it, and the boot PROM does not write it. If the byte is 80 or more, the
DOS moves the head to a wrong track, and the boot fails. A second RUN E800 then boots,
because the DOS wrote the byte during the first boot.
The northstardd machine starts with all its memory at zero, so the first boot works. If you
add an mdsad to a different machine, set fill = "zero" on the memory board, or start the
boot two times. CP/M and single-density North Star DOS do not have this problem.
16fdc and 64fdc: Cromemco 16FDC and 64FDC
Cromemco's double-density floppy controllers. Each board has three things on it:
- a Western Digital FD1793 floppy controller, for single and double density, with up to four
drives. Its registers are at
30–34. - a TMS 5501 console UART, unit
tty, at00–09 - an RDOS boot PROM at
C000. The 16FDC has 4K of RDOS 2.52. The 64FDC, from 1983, has 8K of RDOS 3.12, atC000–DFFF.
OUT 40H switches the PROM off, and RESET switches it on again. With the bootstrap strap on
(the default), RDOS boots the disk. With it off, RDOS gives its monitor prompt.
Both boards boot Cromemco CDOS. The package has no CDOS disk and no built-in machine for these boards, so you add the board and supply the disk. These boards can format a blank disk. Mount a blank image, and the guest's own format program writes the tracks.
RDOS boots drive A. To boot a different drive, set boot_drive to B, C or D. This sets the
boot-drive switches of the board. RDOS reads them for the automatic boot, and for its B command
when you give no drive letter:
altairsim> SET fdc0 boot_drive=B
In a machine file:
[[board]]
type = "64fdc"
id = "fdc0"
boot_drive = "B"
The boards check the density. Bit D6 of port 34 must agree with the density of the track, as
on the hardware, and a read or a write at the wrong density gives Record Not Found. A
5.25-inch double-density track that a program formats is recorded as double density. Both boards
use the same density bit at the same 250 kbit/s for 5.25-inch single and double density, so the
bit is the only thing that tells the two apart.
Port 04 bit D6 reads 0 on the 16FDC. On the 64FDC it always reads 1. CDOS reads this bit
for each 8-inch drive: a 0 marks a PerSci drive, which CDOS homes with the ¬RESTORE line of
port 04 (D3). The 64FDC has no such line, so CDOS homes its drive with the disk chip.
The boards are polled. They deliver no interrupts. The other switches of the boards are fixed: the console has a preset baud rate, and RDOS boots from a floppy disk.
dualsd: S100Computers Dual SD
A modern disk controller among the period boards. The S100Computers Dual SD board puts two
microSD cards on the S-100 bus as drives with 512-byte sectors, and a Z80 machine runs CP/M
3 from them. Like the iCOM and the Datakeeper, it uses commands and a handshake. It has
two ports (default 80–81), and a microcontroller on the board does the card I/O. Each SD
card is one CP/M drive. The socket of the card gives the drive letter: socket 1 is A:, and
socket 2 is B:.
It has no boot PROM. The monitor on the processor board boots it. For this reason, the
dualsd machine has three boards: a z80 for the processor, the v2z80rom monitor EEPROM,
whose I command reads CP/M 3 from the card, and this controller. Start the machine, type I
at the -> monitor prompt, and CP/M 3 starts at A>.
Mount a card in both sockets. The CP/M 3 boot ROM checks that each socket has a card before it starts. With a card in socket 1 only, the loader boots and then stops. Put the bootable system card in socket 1, and a blank card in socket 2.
A card is a raw .img file, with a .geo file beside it that gives the true size of the
card. The .img can be shorter than the card, with only the live file system in it. Every
sector after its end reads as an erased card does, as all FF. For this reason, a card that is
hundreds of megabytes on real flash can be a few megabytes here. MOUNT … CREATE makes a
blank data card, an empty .img and its .geo, for the guest to format. A bootable card
must come from a real image, because nothing can make its system tracks. You supply the images.
dualide: S100Computers IDE-AB (CompactFlash)
The other half of the same S100Computers board. The Dual SD part drives microSD cards. The
IDE-AB part drives two CompactFlash cards, through an 8255 parallel port that connects
to the IDE bus of a CF card (default ports 30–34). Its two cards are CP/M drives A: and B:,
and it boots the same CP/M 3. It stores data on a card in the same layout as the SD part, so
a card image works on both boards.
It has no boot PROM either. The dualide machine has the z80, the v2z80rom monitor
EEPROM and this controller. At the -> monitor prompt, the P command (not the I of the
Dual SD) reads CP/M 3 from CompactFlash drive 0, and CP/M starts at A>.
The cards are the same as on the Dual SD board: a raw .img with a .geo file beside it.
The image can stop after the live file system, with FF after its end. MOUNT … CREATE makes a
blank data card, and a bootable card must come from a real image. The dualidesd machine
has the whole board at once: CompactFlash as A: and B:, and microSD as C: and D:, with one
CP/M 3 system on all four drives.
Video and display
Boards that show a picture in a window.
Each video board opens its own window. [display] in the configuring chapter sets which window
gets the keyboard, and how the picture looks.
Closing a video window stops the machine. It does not quit the program. The close box does
what STOP does. The guest stops at an instruction boundary, and you get the monitor prompt,
with the machine where it was. RUN continues in the same window. QUIT leaves the program.
The window size: the width property
Every video board (the VDM-1, the Dazzler and the VDB-8024) has a width property. It sets
the width of the window in pixels. auto, the default, makes the window about half as wide as
the screen. A number such as width = 1024 asks for that many pixels. The height follows
from the shape of the board's picture. With the default look, the program draws each pixel of
the board as a whole number of screen pixels, so that the picture stays sharp. A thin dark
border fills the rest. With the period look ([display] crt = true), the picture fills the
width that you asked for, because a soft picture has no square pixels to keep sharp. A width
that is too big for the screen is made smaller.
The built-in terminal window (see the serial chapter) sets its size in the same way, with a
width= option in its connect string, not a board property.
width is a property of the board, not of [display]. On real hardware, each board had its own
video output and could drive its own monitor. The same is true here. Add a VDM-1 and a Dazzler
to one machine, and you get two pictures in two windows. The keyboard is still shared. Whichever
window you type in, the keys go to the machine.
A stopped machine's window does not redraw
The window stays live when the machine is stopped. You can move it, and you can close it. If you
close it at the monitor prompt, RUN opens a new one the next time a program draws. A stopped
machine does not redraw the picture, because the running machine draws it. This has two
results:
- A change such as
SET vdm0 video=reversedoes not show until you typeRUNagain. The program keeps the setting, but nothing redraws the screen until the machine runs. - The cursor does not blink while the machine is stopped. To see it blink, use
sol20, where SOLOS runs in a loop and does not halt.
The vdm1 demo halts after it draws its banner, so its window belongs to a stopped machine.
vdm1: Processor Technology VDM-1
Memory-mapped video. A 1K screen of 16 rows by 64 columns is in the machine's own
address space, at CC00 by default. A program puts a character on the screen when it stores a
byte. It needs no port and no driver. For this reason, the board is fast, and it needs no
CONNECT, because the screen is memory.
One port (default CC) does the rest. A write to it sets which row is at the top of the screen.
This is how the VDM-1 scrolls: the text does not move, but the window on it does. A read of the
port gives two timing bits. The software uses them to avoid writing while the beam draws.
Bit 7 of each byte is the cursor and blink flag, not part of the character. For this reason, the board draws 128 characters from a real character ROM, not 256.
Two machines use it:
vdm1: an Altair with a VDM-1, and a demo that draws on itcuter: the period CUTER monitor, with its own VDM-1 driver
dazzler: Cromemco Dazzler
The first color graphics board for the S-100 bus. The VDM-1 shows text, and the Dazzler shows a picture. It does this in the same way, from a frame buffer in the machine's own RAM. You point the board at a block of 512 bytes or 2 KB, at any 512-byte boundary, and it shows that memory on the screen. A program draws when it stores bytes, with no port in the inner loop.
Two ports (default 0E and 0F) set the rest. The first turns the board on or off, and sets
where the frame buffer is. The second sets the format: the resolution, the size and the color.
This gives four modes: 32×32 or 64×64 elements in color or grey, and 64×64 or 128×128
on/off elements, in 16 colors or 16 greys.
The dazzler machine is the plain board, for you to build on. A 64×64 picture is very small, so
the board's width property (above) makes the window about the size of a VDM-1 window.
dazzler2: Cromemco Dazzler II
The Dazzler II is a modern board, not a period product. It works like the Dazzler: the same two
ports (0E and 0F), the same four modes and the same picture. The difference is where the
picture is kept. The Dazzler reads its picture out of the machine's RAM. The Dazzler II keeps the
picture in 4 KB of RAM on the board. It watches the processor's writes to memory, and it keeps
a copy of each one that is in its 4 KB window. The window starts at the address you set with
OUT 0E.
Use dazzler2 to test a program for a real Dazzler II. The board shows what the real board
shows, and the Dazzler hides these things:
- The board RAM has no defined contents until the program sets the base. A program that draws its
picture before
OUT 0Eshows random data. Theseedproperty sets the data, so the same seed gives the same picture each time. - The picture can be at an address that has no RAM in the machine, such as a ROM or an empty slot. The Dazzler shows nothing there.
- The board shows 2 KB of its 4 KB. The
pageproperty is0for the first half, or800for the second half. On the board, this is jumper P18 pins 31 and 32. - A read of the status port (
IN 0E) gives0in bits 0 to 5. The Dazzler gives1. A program that waits for the value3Fcan wait for ever.
The board does not model the second color map, the page bit set by the program, or the
joystick circuit that is also on the real board. The d7a board serves the joystick. For the
Cromemco games, use dazzler.
cadzilla: an HD63484 ACRTC graphics board
This board is a new custom product based on period components, not a period product. It uses two real chips from the middle of the 1980s. The Hitachi HD63484 ACRTC is a CRT controller with a drawing processor and up to 2 MB of its own frame memory. The Brooktree Bt453 is a RAMDAC: a color table of 256 entries, with three video DACs on one chip.
The VDM-1 and the Dazzler show a picture from the machine's RAM. The CADzilla board keeps its picture in its own memory, and the processor never addresses a pixel. The guest draws with commands, for example "move here", "draw a line to there" and "clear this block". The guest writes each command into the FIFO of the ACRTC, one word at a time, and the chip draws.
The board decodes one block of 8 I/O ports from port (default 70):
| Port | What it is |
|---|---|
port |
The ACRTC address register (write) and status register (read). |
port+1 |
The board's own MODE register, write only. It holds the sync polarity and the access mode of the board's fetch logic. |
port+2 |
The ACRTC control register that the address names, one byte at a time. The high byte is at an even address, and the low byte is at the odd address. |
port+3 |
Not decoded. On the real board, it is the high byte of a 16-bit transfer. An 8080 or Z80 does only 8-bit transfers. |
port+4 to port+7 |
The Bt453: the address register, the color table (red, green, then blue), the address again, and the overlay colors. |
The timing and display registers of the ACRTC increment the address after each byte. For this reason, one address write loads a whole block of these registers.
The ACRTC sends out an 8-bit value for each pixel. The Bt453 changes that value into a color from its table. A guest sets its colors when it loads the table. A new table changes the colors of the picture with no redraw.
The monitor is part of the board. The mode property sets a fixed-frequency VESA display:
640x480, 800x600 or 1024x768 (the default). Set it in the machine file or with SET. The
window always has the size of the mode, as the frame of a real monitor does. The timing
registers of the ACRTC set where the picture is in that frame. A picture that starts where the
back porch of the mode ends fills the frame. A picture that starts one cycle early or late moves,
and its edge is cut off.
The shift register of the board is wired for 8 bits per pixel and 8 words for each fetch. A
guest must set the ACRTC to 8 bits per pixel and an address increment of +8. SHOW <id> has a
wiring line. The line shows ok, or it names the setting that is wrong.
The board needs a display. An SDL3 build opens a window with the board's id as its title. A build with no display runs in the same way and shows nothing. The frame memory is 2 MB, and you cannot change it.
SHOW <id> gives these straps and live values:
| Name | What it is |
|---|---|
port, mode, draw_rate, width |
Straps. You set them in the machine file or with SET. |
interrupt |
A strap. It sets the S-100 line for the IRQ* output of the board: none (the default), int, or vi0 to vi7. On the real board, it is switch 8 of SW1. |
video |
Live. on when the ACRTC shows a picture. |
picture |
Live. The size of the picture, and its position in the frame. |
wiring |
Live. ok, or the ACRTC setting that does not agree with the board. |
hspol, vspol, amode, olen |
Live. The bits of the MODE register. |
status |
Live. The ACRTC status register. |
irq |
Live. Whether the board asserts an interrupt now. |
The draw_rate strap sets the drawing speed. With full (the default), the ACRTC completes
each command immediately. The write FIFO is always empty, and the guest never waits for the
chip. This is the fastest setting when you develop a program. With real, each command takes
the time that the Hitachi data sheet gives for it. The ACRTC draws only in the memory cycles
that the display does not use. These depend on the access mode and on the priority bit of the
operation mode register. While the chip draws, the next command words stay in the write FIFO.
The FIFO status bits and the command-end bit (CED) change at the times that the real chip
changes them. Use real for a guest that is sensitive to time, for example a game:
SET cad0 draw_rate=real
The ACRTC clock comes from the pixel clock of the mode. It is the pixel clock divided by 8 in
single access mode, or by 4 in interleaved access mode. The processor's clock_hz does not
change the drawing time that the guest sees. At each clock_hz, a drawing command takes the
same number of processor instructions. With clock_hz = 0, the host does not wait, and the
guest sees no change.
The cadzilla machine is the board alone, with a console for you to type at. The board does
every drawing command of the ACRTC: lines, rectangles, circles, ellipses, arcs, area paint,
patterns, and block and area copies.
vdb8024: SD Systems VDB-8024
An 80-column by 24-line video terminal on one board. The sbc board gives an SBC-100/200 a
serial port for a terminal. The VDB-8024 gives it the terminal itself: a complete display with
a keyboard, on the backplane.
It is not memory-mapped. None of its screen is in the machine's address space. To the
computer, it is two I/O ports, a status port and a data port at 00 and 01, that work
like a terminal on a line. The program reads the status to see whether a key is waiting or the
display is ready. It writes a character or a control code to the data port, and it reads a typed
key from the same port. The screen, its memory and its own processor are all behind those two
ports, as on the real board. The real board had its ports fixed at 00. The board here has a
port property so that you can move them, as the sol does below.
The board is polled by default. The interrupt strap (vi0 to vi7) sends a keyboard
interrupt to a vectored interrupt line, for the SBC-200's CTC. The SD video CBIOS needs this.
It runs sdmonv21, the video version of the SD monitor. It is the same monitor as in the
serial sbc200 machine, with the same commands and the same . prompt. You do not press
Return first, because the VDB has no serial speed to measure. The prompt is on the screen as
soon as the machine starts:
$ altairsim sbc200v
This gives the monitor's . prompt in the video window.
Like a Sol-20, the window is the console. The machine sets focus=on, so the window keeps
the keyboard while the guest runs. Keys typed in the window and at the terminal go to the
monitor together. The characters come from the board's own character font, with true descenders
on g, j, p, q and y, as the font PROM of the hardware drew them.
The board obeys the same control codes as its firmware: carriage return, line feed, backspace,
tab, cursor up and right, clear screen and home, and the ESC sequences that move the cursor
and erase to the end of a line or of the screen. A full line wraps, and a line feed on the
bottom line scrolls the page up.
sol: Processor Technology Sol-PC
The onboard I/O of the Sol-20, as one board, because it was one board on a real Sol-20. The
Sol was not an Altair with boards in it. It was one machine, with the serial port, keyboard,
parallel port and cassette interface all on the processor board, at F8–FE. On the real
hardware, those addresses were fixed. Here, the board has a base property so that you can move
it. This is the one change from the hardware, and the reference records it.
You reach the parts of the board as units. serial, printer and keyboard are lines that you
CONNECT. tape1 and tape2 are cassette decks that you MOUNT. The keyboard is connected to
the console by default. It takes what you type, from the video window when there is one, or from
your terminal.
The special keys of the keyboard
The Sol keyboard has eight keys that send codes with no ASCII equal. You use them to control SOLOS and the screen:
| Key | Sends | What it does | Press | Or type |
|---|---|---|---|---|
← |
81 |
Cursor left one | ← | Ctrl-A |
→ |
93 |
Cursor right one | → | Ctrl-S |
↑ |
97 |
Cursor up one | ↑ | Ctrl-W |
↓ |
9A |
Cursor down one | ↓ | Ctrl-Z |
HOME CURSOR |
8E |
Cursor to the top left, screen untouched | Home | Ctrl-N |
MODE SELECT |
80 |
Return to the command mode, restarting the command line | F1 | Ctrl-@ |
CLEAR |
8B |
Erase the screen, cursor home | F2 | Ctrl-K |
LOAD |
8C |
Nothing. Neither SOLOS nor CONSOL uses it | F3 | none |
The Press column works only in the video window. When the window has focus, your arrow
keys, Home, and F1 to F3 send these codes. They cannot work from a terminal. There, an arrow key
or a function key sends an escape sequence, not one byte, and the guest needs ESC as a
character, so the program cannot safely read those sequences. From a terminal, use the last
column.
A PC keyboard has no MODE SELECT, CLEAR or LOAD key, so F1 is MODE SELECT, F2 is
CLEAR, and F3 is LOAD. On a Mac, the function keys reach the window only if the system
sends F1, F2 and so on as plain function keys. If not, hold fn.
The last column is how the hardware worked. The code of each special key is 80 plus the
control code for the same action, because the display driver of SOLOS clears the top bit of each
character before it uses it. For example, CLEAR and Ctrl-K go to the same routine. The command
reader clears the top bit too. For this reason, a NUL byte is MODE SELECT. Type Ctrl-@
(Ctrl-Space on many keyboards), and SOLOS drops the line that you were typing and gives a new
prompt.
The console is 8-bit clean. If you can send the byte itself, for example with a paste, a script or a terminal macro, the real code works too.
One register (FA) gives the state of all of these parts at once, with mixed polarity.
The keyboard and parallel bits are active-low, and the tape bits are active-high. This is what
the hardware did, and the period software inverts the bits that it needs.
The cassette decks
The Sol's cassette interface is on the main board, and it has two decks, tape1 and
tape2. The 88-ACR has one. Everything in the tapes chapter applies to them, with a different
unit name. Always give the name of the deck. The program refuses a plain WIND sol0, because it
does not know which tape to move.
altairsim> MOUNT sol0:tape1 "mytape.tap"
altairsim> SET sol0:tape1 mode=record
altairsim> REW sol0:tape1
There are three differences from the ACR, and each one comes from the hardware:
- The Sol controls the motors.
OUT 0FAhstarts and stops each deck, and SOLOS does this for you.SAVEstarts the deck, writes, and stops it. For this reason, a Sol tape plays only while the guest runs it, and a deck with its motor off gives nothing. When the motor stops, the board writes the recording out. The 88-ACR cannot see the deck, so it cannot do this. The Sol still cannot wind the tape by itself, because a motor line says only "turn", not which way. You useWINDandREWINDfor that. - The guest sets the speed. The ACR's 300 baud is fixed. The Sol's cassette runs at 300 or
1200 baud, and bit D5 of
OUT 0FAhselects the speed while the machine runs. The SOLOS commandSE TAsets that bit. - The modulation is CUTS, not the ACR's FSK. A Sol tape is
cuts1200(1200 and 600 Hz) at 1200 baud, one octave below the ACR's 2400 and 1850 Hz. It can also read Kansas City (kcs300, 2400 and 1200 Hz). For this reason, the 88-ACR refuses a Sol tape. The tapes chapter tells you more.
When a tape is mounted, the SOLOS commands work:
>SA MYPROG 0100 01FF (save memory to the tape)
>GE MYPROG (find it again and load it)
>CA (catalog what is on the tape)
To write audio that a real Sol can load, you need the right tones, and also the right
shape and level. A real Sol CUTS modem is a flip-flop that divides a master clock into a
square wave. An RC network rounds the wave, and the tape records it at a moderate level. Three
properties copy this when the board writes a .WAV file. Their defaults come from measurements
of a real archived tape:
| Property | Default | What it does |
|---|---|---|
leader |
3 |
Seconds of steady tone before the data. The real tape has 3.05 s. The ACR's leader is longer, 15 s |
trailer |
2 |
Seconds of tone after the data. The real tape has 1.93 s |
rc |
4000 |
The corner of the low-pass filter that rounds the edges, in Hz. It rounds the edges of the square wave as the modem's RC network and the cassette do. CUTS only |
level (percent of full scale, default 36) applies to both boards, and the tapes chapter
describes it. With these defaults, a CUTS tape from the simulator has its tones on the same
clock grid as a real Sol expects, at the level of a real tape. It is made to load on the
hardware, not only to read back here.
Add a vdm1 to this board, and you have the sol20 machine, which starts the real SOLOS
operating system.
Interrupts and the clock
Vectored interrupts and real-time clocks.
virtc: MITS 88-VI/RTC
Two things on one board.
Vectored interrupts. The board has eight lines, VI0 to VI7. You strap a device to a
line. When the device interrupts, level n becomes RST n. The processor jumps to 8×n,
and the correct handler runs, with no polling. VI0 has the highest priority, and the board
enforces it: a lower level cannot interrupt a higher level while the higher level is being
handled.
With interrupts, the machine can do other work and does not have to wait in a loop. Every board
with an interrupt strap in its properties, such as the serial boards and the floppy controllers,
is strapped to one of these lines, to int, or to nothing.
A real-time clock, on the same board. It gives a periodic interrupt from the 60 Hz power
line, or from the system clock divided down. The rtc_source jumper selects which.
The board has one port, at FE, and it is write-only. You cannot read anything back.
Interrupt boards are easy to set up wrong, so read the reference for this board before you strap
anything to it.
The ps2int machine shows the board in use, with a MITS Programming System II tape that you
supply. The package has no such tape, so its cassette deck starts empty.
ss1: CompuPro System Support 1
A multifunction board. On the real board, one block of 16 ports holds a serial channel, an interval timer, two interrupt controllers, a battery-backed real-time clock and calendar, and a socket for a math coprocessor. This board models the clock, the serial channel, the interval timer and the two interrupt controllers. The math socket is empty.
The clock is an OKI MSM5832. It starts with the date and time of your computer, so a guest
program that reads it gets the real time. A guest can also set it. After that, the clock
keeps the setting, and the time is kept through a RESET, as the battery on the real chip did.
The block is at base 50H by default, the CompuPro convention. The base property moves
it.
The serial channel is a 2651 UART at 5C–5F. It is a spare serial port. A guest sets its
rate, its frame and its RS-232 handshake through the mode and command registers. You connect it
with CONNECT ss1:serial <endpoint>. Its baud, interrupt and connect are unit settings,
which SHOW ss1 shows.
The interval timer is an Intel 8253 at 54–57. It has three independent 16-bit counters,
which a guest can use as timers or as square-wave and rate generators. The counters count at 2
MHz, and their outputs go to the interrupt controllers. SHOW ss1 prints a live timer line
with the mode, count and output of each counter.
The interrupt system is two Intel 8259A controllers at 50–53, cascaded as master and
slave:
- The master watches the eight vectored interrupt lines of the bus, and drives the processor's interrupt pin.
- The slave collects the sources on the board, which are the three timer outputs and the UART's transmit-ready and receive-ready signals. It sends them to the master.
A guest sets them up in the usual 8259A way, with the ICW and OCW words, and unmasks the sources
that it wants. On an interrupt, the controller gives the processor a CALL to the vector of the
source with the highest priority. SHOW ss1 prints a live pic line with the request,
in-service and mask registers of each controller. The master is the interrupt priority encoder
of the machine, so do not also add a virtc. The two boards would both answer the interrupt
acknowledge.
The compupro machine has one: a stock Altair with the System Support 1 added, and its console
still on the 2SIO. The clock is at 5A (command) and 5B (data). The board reference gives the
digit map, the read and set sequences and the register layouts.
rtc100: SciTronics RTC-100
A battery-backed calendar clock, and nothing else. SciTronics sold it in 1980 for machines that did not know the date. It has an OKI MSM5832 clock chip, the same chip as on the System Support 1, behind a 6821 parallel interface, on four ports in a row.
It starts with the date and time of your computer, so a guest gets the real time. When a
guest sets it, the clock keeps that setting through a RESET and a power cycle, as the lithium
cell of the real board did. SHOW <id> prints a live time line with the time on the clock and
how far it is from the time of your computer.
The base address is the PORT switch of the board, and it must be a multiple of 4. The switch
decodes only the top six address bits, and the bottom two bits select one of the four ports. The
default is F0. A guest reads the clock one BCD digit at a time. It writes the number of the
digit to the first port, and reads the digit back in the top half of the byte. For this
reason, the period drivers for this board all mask and rotate the byte at the end.
It can also interrupt once a second, to drive a clock display in the background. Set
interrupt to int, and the board pulls the interrupt line of the machine. restart selects
the RST that it gives the processor (0 to 7, the INT switch of the board). The manual of the
board says that 0 and 7 are often used by other things. With interrupt set to none, the
board never interrupts, and it still keeps the correct time.
Host integration
A board that connects the machine to your computer. It is not period hardware.
hostbridge: our own board, not a period board
This board never existed. It is the one part of the machine that is not history, and this manual says so.
It moves files between the guest and your computer, in both directions. It is sandboxed.
The guest sees one folder that you choose, and it cannot leave that folder. It cannot use
.. or an absolute path to leave it. This is a fixed rule, not a setting.
The default port is B0. The utilities are not in the board. R, W and HDIR are
ordinary CP/M .COM programs. They are on a disk, they run at the A> prompt, and they use the
two ports of the board, as any other CP/M program could. They were assembled in the machine,
with the machine's own assembler, from 8080 source that ships with the package. You can read
their code.
The file-transfer chapter describes this board. It is the fastest way to get your own code into CP/M. XMODEM also works, over an ordinary serial line, as it did on real machines.
PROM programmers
A board that does not run software, but programs it into a chip. You load a period EPROM programmer routine and run it. The bytes that it programs go into a socket, and you can save the socket to a file.
pb1: SSM PB1
The SSM PB1 (Solid State Music) is a 2708 and 2716 EPROM programmer. It has a 4K window
in memory (default D000) for its two sockets: U22 holds a 2708 (1K), and U23 holds a
2716 (2K). It has one control port (default 10). The default machine has its 2SIO at
10 too, so move one of the two boards when you add a pb1.
Software programs the chip:
- An
OUTto the control port arms the board and selects the chip. Write01for the 2708, or02for the 2716. - After that, every byte that the guest writes into the window is programmed into the chip.
- A read of the window disarms the board again. The period routines end in this way, and it turns the LED off.
"Programming is a write, and disarming is a read" has two results:
- A socket starts erased, with every byte
FF. Programming can only clear bits to 0. It cannot set them, as on a real EPROM. Program a blank chip. A second program over the first gives the AND of the two. - The program is in the board, not on your computer. To keep it,
SAVEit to a file (below). A power cycle reads the sockets again from their mounts, so a program that you did not save is lost.
Programming an EPROM, and making a hex file
You need this board, not only a write to memory, because you want to run the period software.
The PB1 manual has SSM's programmer routines, one for the 2708 and one for the 2716. Each
routine copies bytes from 4000 into the socket. The 2708 routine starts at 0100. The package
does not include these routines. Enter one from the manual, or LOAD it from a hex file of your
own. After that, put the data at 4000, run the routine, and save the result:
altairsim> FILL 4000-43FF E5
altairsim> LOAD PROG2708.HEX
altairsim> BREAK F021
altairsim> RUN 100
altairsim> SAVE eprom.hex D000-D3FF
FILLputs the 1K that you want to program at4000. You can alsoLOADyour own data there.LOAD PROG2708.HEXloads the 2708 routine.BREAK F021is needed because SSM's routine ends with a jump to SSM's own system monitor, atF021. A machine without that monitor has nothing atF021. The breakpoint stops the machine at that jump, after the chip is programmed. The next section shows a machine that has the monitor, and needs no breakpoint.RUN 100runs the routine. It arms the board and programs the 2708.SAVEreads the socket window from the bus and writes it to a file. After it is programmed, the socket reads like other memory.eprom.hexis an ordinary Intel HEX image of the chip. You can give it to another tool, orLOADit again later.
Your own routine works in the same way. It writes 01 to port 10 (or 02 for a 2716), and
then writes the data into the window. After it runs, SAVE the window.
With the SSM monitor
SSM wrote the routines for the SSM 8080 System Monitor. Each routine ends with a jump to
the monitor at F021. The manual also has two check routines, which print P (pass) or F
(fail) through the monitor's console-output routine at F009. The package has that monitor as
the built-in ROM ssm-8080mon. Put it in the machine, and the routines run as SSM wrote them.
The monitor has its console on a serial port at 00 and 01, as an io4 has by default. Thus
this machine has an io4 as its console, RAM below the window of the pb1, and the monitor at
F000:
[machine]
name = "pb1"
[[board]]
type = "8080"
id = "cpu0"
[[board]]
type = "io4"
id = "io40"
[board.unit.a]
connect = "console"
[[board]]
type = "pb1"
id = "pb1"
port = 10
window = D000
[[board]]
type = "memory"
id = "mem0"
[[board.region]]
type = "ram"
at = 0000
size = "52K"
[[board.region]]
type = "rom"
at = F000
mount = "builtin:ssm-8080mon"
Put the data and the routine in memory as before, and then start the monitor:
altairsim> FILL 4000-43FF E5
altairsim> LOAD PROG2708.HEX
altairsim> RUN F000
The monitor prints its name and its prompt, which is a period:
MONITOR V1.0
.
Type G100 and press Enter. G is the monitor's command to run a program. The routine programs
the chip and then jumps to F021, and the monitor prints its name and its prompt again:
.G100
MONITOR V1.0
.
Press Ctrl-E to go back to the altairsim> prompt, and SAVE the window as before.
A check routine runs in the same way, with G and its start address. It prints its result
before the monitor prints its name. This is the manual's copy-verify routine, which starts at
0180, after a good burn:
.G180
P
MONITOR V1.0
.
The board also has an optional EPROM area on the board (U11 to U14 on the real board). These
are read-only chips that you mount above 8000 with [[board.prom]] (at and mount). Use
them as the source when you copy one EPROM to another.