SkillAgentSearch skills...

Monotron

A simple 8-bit home computer style application for the TI Tiva-C Launchpad

Install / Use

/learn @thejpster/Monotron
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Monotron.

A simple 1980's home computer style application for the Tiva-C Launchpad

The Monotron is no more

Monotron was fun, but it was only ever a tech demo rather than something we could build on. Check out https://github.com/neotron-compute/ for our new family of ARM-based, Rust-powered home computers.

Introduction

Monotron is powered by a Texas Instruments TM4C123 microcontroller, containing an ARM Cortex-M4 core and a number of peripherals. This processor was chosen because it is available on an inexpensive dev-kit - the Tiva-C Launchpad - and I happened to have some lying around. The challenge I set myself was, how much can you squeeze out of this tiny CPU? And can you do it all in pure-Rust?

YouTube screenshot of a video of Monotron See Monotron in Action!

The Future

Monotron has been replaced by the Neotron 32, part of the Neotron family. All future work will happen under the Neotron banner, and this repo is in archive mode.

Features

  • 800x600 8-colour VGA output
  • 32 KiB SRAM (24 KiB usable for applications)
  • 256 KiB Flash ROM
  • Choice of low-memory 48x36 text display mode or full 384x288 bitmap graphics mode
  • 8-bit mono audio output with 3 channel, 4 waveform synthesiser
  • USB Serial I/O
  • Atari 9-pin joystick interface
  • Simple command-line interface
  • I2C expansion interface
  • Loadable apps
  • Battery backed real-time clock*
  • 25-pin IBM PC style parallel printer port*
  • MIDI In, Out and Through*
  • PS/2 Keyboard and Mouse*
  • RS-232 Serial port*
  • Watch this space!

* Requires additional hardware, included on the Monotron PCB

Video

Monotron generates an 800x600 VGA video signal at 60 Hz using three SPI peripherals and a timer to generate the horizontal sync signals. It can do this because the VGA signal has a pixel clock of 40 MHz and the Tiva-C Launchpad's TM4C123 CPU runs at 80 MHz. We save on the number of pixels we have to push through the SPIs by running at half-resolution horizontally (giving 400x600), which also halves the pixel clock to 20 MHz. I did try 40 MHz mode and it didn't work.

Monotron has two 'modes' it can display on this VGA output.

Text Mode

Text Mode has a 48 character by 36 line display. Each character cell is 8 pixels wide and 16 pixels high and can take any character from the 8-bit MS- DOS Code Page 850 character set, and can have any foreground and background colour from the supported set:

  • White
  • Red
  • Yellow
  • Green
  • Cyan
  • Blue
  • Magenta
  • Black

The text buffer takes up 48 x 36 x 2 = 3,456 bytes of SRAM.

The built-in font is taken from FreeBSD. There's also a second font which implements Teletext block graphics (or 'sixels').

Any line of text can be displayed in "double height" mode, showing either the top-half or bottom-half.

Finally, the display is framed with an 8 pixel border at the sides and a 12 pixel border at the top and bottom, to make everything fit neatly and to help with any minor overscan issues if you use an actual CRT monitor.

Graphics Mode

Graphics Mode can be enabled and disabled at run-time. It's not enabled by default because bitmap graphics take up a lot of RAM!

You can attach a 1-bit-per-pixel graphics buffer that is some multiple of 384 pixels (i.e. 384 bits or 48 bytes) long. This buffer is displayed using line- doubling (i.e. every line is shown twice) so you can go up to 384x288 resolution maximum, which will fill the screen. Each bit from the bitmap is coloured according to the text cell (see above) it sits on top of, much like a ZX Spectrum. A full-screen bitmap therefore uses the 3,456 bytes of SRAM from text-mode plus an additional 384x288 / 8 = 13,824 bytes of SRAM.

Compiling

You will need to build using Rust Nightly, as we need various experimental features for Embedded development that are not yet available in Stable.

$ rustup toolchain install nightly
$ git clone https://github.com/thejpster/monotron.git
$ cd monotron
$ rustup override set nightly
$ rustup target add thumbv7em-none-eabihf
$ cargo build --release

To program the board, you can use lm4flash:

$ cargo build --release
$ arm-none-eabi-objcopy -O binary ./target/thumbv7em-none-eabihf/release/monotron ./target/thumbv7em-none-eabihf/release/monotron.bin
$ lm4flash ./target/thumbv7em-none-eabihf/release/monotron.bin

Or you can debug in GDB (which will automatically load the program first):

$ openocd
<switch to a different terminal>
$ cargo run --release

OpenOCD should read our openocd.cfg file, which directs it to use the correct configuration. You may need to run sudo openocd if your user doesn't have permission to open the USB device.

To exit GDB, you may need to press Ctrl-C multiple times, as it seems it can get a bit stuck.

Connecting

You have two options when running a Monotron.

  1. You can take a bare Tiva-C Launchpad and wire up various connectors using the pin-outs in the following sections.
  2. You can skip all that make yourself a Monotron PCB!

VGA

Your VGA connector requires five wires:

  • Pin 1: Red - connect to PF1 via a 330 Ohm resistor.
  • Pin 2: Green - connect to PB7 via a 330 Ohm resistor.
  • Pin 3: Blue - connect to PD3 via a 330 Ohm resistor.
  • Pin 5: Ground - connect to GND
  • Pin 6: Red Return - connect to GND
  • Pin 7: Green Return - connect to GND
  • Pin 8: Blue Return - connect to GND
  • Pin 13: H-Sync - connect to PB4
  • Pin 14: V-Sync - connect to PB5

I'm using this arrangement using random resistors I found on my desk, and it works for me (although the picture is a bit dim, as it actually produces about 0.6V peak rather than 0.7V):

-----+
     |     +------+ 330 Ohm        Co-ax in the VGA cable
PB7 o+-----|      |------------(o)==================)+
     |     +------+                                  |
-----+                                               |
                                                    +-+
                                                    | |
                                                    | | 75 Ohm
                                                    | | (in Monitor)
                                                    +-+
                                                     |
                                                     o
                                                    GND

The 330 Ohm resistor forms a resistive divider with the 75 Ohm resistor in the monitor. This is needed to drop the 3.3V output down to 0.7V. Some monitors are more tolerant of over voltage than others. The higher the resistor you use, the less current you pulling out of the GPIO pin (we're just over 8mA currently, which is a bit high) but the lower the voltage the monitor will see and the dimmer your picture will be. Conversely if you lower the resistor, more current will flow but it'll be a brigher picture. I'd save your chip from damage and just wind the brightness control up!

Obviously only one channel is shown above - wire up the blue and red channels in exactly the same fashion. Finally, don't forget to keep your wires short! You will have noise if you try and send a 20 MHz signal down 10cm of unshielded wire.

In a perfect world, your board would offer a 75 ohm source impendance matching the monitor's 75 ohm impedance, to reduce reflections, but at this resolution it doesn't seem to matter. If you want do do that, you'll need to make a resistive divider to drop the 3.3V to 1.4V, and then feed that through a high-bandwidth (>20 MHz) unity-gain amplifier, with a 75 ohm resistor on the output. The pair of 75 ohm resistors will then drop the 1.4V to 0.7V in the monitor.

UART

Monotron primarily uses UART0, which is converted to USB Serial by the on-board companion chip on the Tiva-C Launchpad. Connect with your favourite Serial terminal at 115,200bps, then send UTF-8 characters and they'll get converted to virtual keyboard input, allowing you to drive the Monotron.

There's also a second UART (UART1), which has RTS/CTS hardware handshaking lines connected (but not DSR, DTR or RI). On the Monotron PCB these are brought out to pin header J8. By fitting six jumpers on this header, the on-board MAX3232 level shifter is activated, driving RS-232 signals on the DE9M connector, J12. This connector is wired as Data Terminal Equipment or DTE (as opposed to Data Communications Equipment or DCE). This means that Monotron transmits data on DE9 pin 3, and it's designed to connect to Serial AT modems or other peripherals. Other computers (like an old IBM PC) and even USB to RS-232 adaptors are most likely wired DTE and so to connect one to the Monotron you'll most likely need a null-modem cable (one that swaps pins 3 + 4 and pins 7 + 8).

Bonus points to the first person to write a BBS program for Monotron that lets you dial up on a 56k modem.

Extra bonus points to the first person to write an xmodem file transfer program so you can transfer files from SD card over RS-232 to an xmodem utility on your old MS-DOS 3.3 IBM PC.

Note: The Joystick connector looks the same as the RS232 connector - don't mix them up!

On the Monotron PCB, a third UART (UART3) is routed through various opto-isolators to the MIDI In and MIDI Out ports. The MIDI Through port just repeats everything received on the MIDI In port.

Finally, also on the Monotron PCB, a fourth UART (UART7) connects to a 5V AtMega48 which is used as an I/O expander. This microcontroller drives two PS/2 ports (one for keyboard, one for the mouse) as well as a full IBM PC-style 25

Related Skills

View on GitHub
GitHub Stars194
CategoryDevelopment
Updated4mo ago
Forks9

Languages

Rust

Security Score

92/100

Audited on Nov 14, 2025

No findings