Skip to content

Pocket sized Altair 8800 clone, with blinking lights.

License

Notifications You must be signed in to change notification settings

dankar/nanoaltair8800

Repository files navigation

nanoAltair

CI status

This is a continuation and remake of my old Altair8800 project (https://github.com/dankar/altair8800)

The Intel 8080 emulation is much improved, the PCB is credit card sized and it contains all the processing power required on board. Micro USB connector provides power, serial port and firmware updates.

This is still a work in progress, and there might be both hardware and software bugs. This documentation should be accurate, but there might be changes that haven't been added to the documentation yet. If in doubt, check the code and build scripts.

Image of PCB

License

Hardware design and code is covered by the LICENSE.md file. Files under software/stm32cube are generated by STM32CubeMX and subject to their own license.

Firmware update

The current firmware build can be shown by connecting to the USB virtual com port and pressing the examine button while the stop button is being held down. The build version and timestamp will then be printed over the com port.

Firmware update can be initiated by connecting via USB and then pressing the reset button while the stop button is being held down. The device will then appear as a DFU device and firmware update can proceed. STM32 DFU driver might have to be installed on your PC.

Basic operation

The stop and run buttons will change between stopped and running modes. When in running mode the CPU will continually fetch new instructions and execute them. No buttons except for stop will have any effect.

When in stopped mode the rest of the buttons can be used. Reset will completely reset all memory, and parse the configuration file again, reopening any disk files and load any ROMs.

Examine will read the state of the DIP switches and load that address in ROM/RAM. The address LEDs will be updated to show this address and the data LEDs will show the byte stored in that address. Examine next will increment the address being examined by one.

Deposit and deposit next will put the low byte of the DIP switches into the currently examined address location, or the next address location respectively.

Step will execute one instruction and then return to stopped mode. Note that this differs from the original Altair, where the step switch executed one machine cycle.

SD card

The SD card needs to be formatted with a FAT file system. Both FAT32 and exFAT is fine. Long file names are supported, but everything probably works best if no special characters are used in filenames.

Configuration file

Upon reset the emulator will try to find "altair.cfg" in the root of the SD-card. This will then be parsed to determine the setup and optional other files to be loaded. Each line in the configuration file is one setting, except for empty lines or line beginning with #, which are for comments.

A setting consists of first a name for the setting, then an equal sign and lastly the value of the setting.

The configuration file is read top-down and if there are duplicates of any setting, the last one will apply. The default_path setting is special since it affects file loading during the parsing of the configuration file and will be active until another value is set as the default path.

Do note that it is perfectly possible to start the emulator without a valid configuration file, and even without an SD card inserted. The emulator will warn about this by flashing the front panel lights in a sequence, but after this data can be input via the front panel. Since no port I/O will be setup without a configuration, the functionality is very limited in this mode.

Settings

default_path = [path]

This can be used to set a path prefix for any subsequent file loads. It is entirely optional as the full paths to the files can be specified instead. Setting this setting to a value of "." will set the root folder as default.

disk[0-3] = [path/filename.ext]

This command is used to load a file as a virtual floppy disk. A maximum number of four disks can be mounted at the same time, using settings disk[0], disk[1], disk[2] and disk[3]. The disks will be available through the emulated 88-DCDD device.

tape = [path/filename.ext]

Used to mount a file as a tape, attached to serial port two of the emulated 88-2SIO device.

port[HEX] = [port_name]

Used to assign specific input/output functions to specific port number. The port numbers are specified in hexadecimal numbers, without any prefix or suffix.

The following port names are available:

serial1_control

Control/status for serial port one of the 88-2SIO.

serial1_data

Data in/out for serial port one of the 88-2SIO

serial2_control

Control/status for serial port two of the 88-2SIO.

serial2_data

Data in/out for serial port two of the 88-2SIO. Note that this data port is by default connected to any mounted tape file, making it possible to load program from tape by loading from serial port two.

sense_sw

Port input for the front panel sense switches. These should always be on port FF.

floppy_select_status

Select/status functions of the 88-DCDD disk drive.

floppy_function_sector

Function/sector functions of the 88-DCDD disk drive.

floppy_data

Data input/output functions of the 88-DCDD disk drive.

vic

Control function for the 88-VI/RTC, combined vectored interrupt and RTC controller.

rom[HEX] = [path/filename.ext]

Used to specify a ROM to be loaded at an offset in memory specified by a hexadecimal offset. Any loaded ROMs will be disabled as soon as any data in or out is detected on port FF. After this, all 64k of RAM are available.

start_address = [HEX]

This specifies the address that the CPU will be waiting on after a reset.

run_state = [true/false]

This specifies whether the CPU should start halted or if it should start executing directly after a reset.

rtc_divider = [number]

This specifies how to divide the 60 Hz clock running the RTC interrupt on the vectored interrupt controller. Setting this to 1 will generate an interrupt 60 times a second.

rtc_interrupt_line = [number]

This sets which interrupt line on the vectored interrupt controller to use for the RTC.

serial1_interrupt_line = [number]

This sets which interrupt line on the vectored interrupt controller to use for the first serial port.

Example configuration

# Use cpm22 as default path
default_path = cpm22

# Load bootable cpm image as disk0
disk[0] = cpm63k.dsk

# Load games as disk1
disk[1] = games.dsk

# Change default path to the folder with tapes
default_path = tapes
# Load a tape with extended basic
tape = extbasic.tap

# Load some ROMs that we want to have
#
# turmonh is the Turnkey Monitor, with the added command H, for 
# loading Intel Hex files via the monitor.
# 
# mble is the bootloader for loading programs from tape
#
# dbl is the disk bootloader.
# 
default_path = roms
rom[fd00] = turmonh.bin
rom[fe00] = mble.bin
rom[ff00] = dbl.bin

# Set some default values for the interrupt lines and RTC divider
rtc_divider = 1
rtc_interrupt_line = 6
serial1_interrupt_line = 7

# Set the port I/O to a good default configuration. This should most 
# likely be the same for any most configurations.
port[00] = serial1_control
port[01] = serial1_data
port[08] = floppy_select_status
port[09] = floppy_function_sector
port[0A] = floppy_data
port[10] = serial1_control
port[11] = serial1_data
port[12] = serial2_control
port[13] = serial2_data
port[FE] = vic
port[FF] = sense_sw

Booting from disk

Using the above example configuration, the system can be booted from disk[0] by first entering FF00 on the front switches, then pressing examine to go to that offset (the start of the DBL ROM) and then hitting run. The terminal will be on serial port one, available via the USB virtual com port.

Booting from tape

Using the above example configuration, extended basic can be loaded from tape by first entering FE00 on the front switches, and pressing examine to go to that offset. The CPU will now be halted at the beginning of the MBL bootloader. Before hitting run, make sure to set up the sense switches (A15-A8) as needed.

In this case we set the lower three switches to 110 to tell the bootloader to load tape from serial port two (001 would load tape from the USB virtual com port) and the high four switches to 0001 so that BASIC will know to use serial port one as terminal. After this we can press run and BASIC will be loaded from tape.

Building the firmware

Project is built with cmake:

apt install cmake git zip gcc gcc-arm-none-eabi make
mkdir build
cd build
cmake ..
make -j

Alternatively, you can use docker to build by simply running:

./build.sh all

And if you want a packaged release, run:

./build.sh create_release

About

Pocket sized Altair 8800 clone, with blinking lights.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages