programmable video overlay module

Overlay64 Rev.1

The Overlay64 module allows superimposing predefined texts onto an existing analog video signal, depending on the states of up to 24 digital input lines.

Among other possible applications the overlay64 can be used to display the state of various hardware extensions build into a classic home computer directly on the screen:

Installed in a C64 to display the state of a stereo SID board and a Multirom adapter

The user writes a simple configuration file that determines which texts are to be displayed for which input line states as well as which lines control the display. The configuration file is converted to a binary format and flashed to the eeprom memory of the microcontroller using the supplied commandline utility, supported under Linux, MacOSX and Windows.

The device has been primarily designed for use in a Commodore 64 home computer in order to display the state of control lines for additional hardware such as the MixSID or the Reprom64. Nevertheless it should be suitable for use in any context where textual display of digital state superimposed on an analog video signal is required.

Documentation is available in both english and german.




The source distribution includes the sources for the firmware and the configuration utility as well as schematics and pcb layouts in KiCad format.

Latest stable is overlay64-1.2.tar.gz.

All releases can be found under /download/overlay64

Latest developments are available via github:

git clone https://github.com/hbekel/overlay64



Ordering Assembly Kits

I’m offering assembly kits including the Overlay64 pcb, a preprogrammed Atmega and all other required components (except connection cables) for 25€ each. Worldwide shipping via regular mail is free of charge.

You can order kits via email at henning.liebenau@protonmail.com

To place an order, please include the word “overlay64” in the subject. State your full name, your complete international shipping address and the number of kits you wish to buy. Note that orders are limited to a maximum of two kits per person. You will receive an email containing payment information (bank transfer only). You will have to pay in advance to confirm your order.

Notes on availability

I try to keep a sufficent number of kits on stock, but please note that I’m doing all of this in my spare time, on a short budget and a minimal profit margin. My primary motivation is to serve the community, not to run a profitable business.

This means that in case I am currently out of stock, it may take a few weeks until I can put together a new batch of kits to fullfill your order. I may even need to collect a sufficient number of prepaid orders before I can afford to order the necessary parts myself. In these cases I will regularily inform you about the status of your order. Thus some patience and trust may be required on your part.


Assembly should be straightforward, please refer to the list of parts and the placement on board below.

If you prefer a flat build, you might want to consider to omit IC sockets. Note though that the Atmega needs to contain a working bootloader, as there is no JTAG header present on the board.

List of parts

Reference Type Value Package/RM
IC1 Atmega1284(P) - DIP40 15.24mm
U1 LM1881 - DIP8 7.62mm
C2 Ceramic capacitor 18pF 2.5mm
C3 Ceramic capacitor 18pF 2.5mm
C1 Ceramic/film capacitor 100nF 2.5mm
C4 Ceramic/film capacitor 100nF 2.5mm
C5 Ceramic/film capacitor 100nF 2.5mm
C6 Ceramic/film capacitor 100nF 2.5mm
D1 Low Power Zener Diode 3.6V 500mW DO-204
D2 Low Power Zener Diode 3.6V 500mW DO-204
R1 Precision Resistor 68 6.5mm, ∅ 2.5mm
R2 Precision Resistor 68 6.5mm, ∅ 2.5mm
R3 Precision Resistor 1k5 6.5mm, ∅ 2.5mm
R5 Precision Resistor 680k 6.5mm, ∅ 2.5mm
RV1 Trimpot 1k T7YA or 3339P
∅ 7mm, height 6mm, RM 2.54mm
P1 USB Mini-B Socket - Through-Hole
P2 Pin header angled 1x16 2.54mm
P9 Pin header angled 1x16 2.54mm
P3 Pin header angled 1x8 2.54mm
P4 Pin header angled 1x3 2.54mm
SW1 Push Button - 6x6mm print
Y1 Quartz Crystal 20Mhz HC49/U-S
- DIP socket 40pin - DIP40 15.24mm
- DIP socket 8pin - DIP8 7.62mm

Placement on board

Installing the firmware

If you bought an assembly kit from me, the Atmega is already programmed with the latest firmware and bootloader versions and is ready to use. Proceed directly to installing and testing the device

Otherwise, if you have no means of initially programming the Atmega yourself then you can send it to me and I will prepare it for you. Just drop me a line at henning.liebenau@protonmail.com.

Installing the combined firmware image

The easiest way to bootstrap the Atmega is to install the combined firmware image. The image contains both the bootloader and the application part of the firmware. If you have a programming device capable of programming the complete PROGMEM area from a single binary image or intel hex file (e.g. the TL866), use this method.

Note that you also have to check and eventually program the fuses of the Atmega as well. The required fuse values are:

    Low:      0xd7
    High:     0xd0
    Extended: 0xfc

This corresponds to the following fuses programmed: SUT1, CKSEL3, SPIEN, EESAVE, BOOTSZ0, BOOTSZ1, BOOTRST, BODLEVEL0, BODLEVEL1. All other fuses must remain unprogrammed.

Installing the bootloader manually

The Atmega1284p must contain the USBaspLoader, which must be uploaded to the Atmega via ISP prior to installing it on the board.

There is a preconfigured version of the bootloader in the source tarball.

Change to the bootloader directory and edit the Makefile.inc and adjust the PROGRAMMER settings to according to your setup. Then you can compile the bootloader, flash it to the Atmega and set the fuses:

 $ make flash fuse

The Atmega can now be inserted into its socket on the device. When entering the bootloader, it identifies itself to the host like this:

16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb

It can be accessed using avrdude -p m1284p -c usbasp <commands...>

Note that you will have to configure the USB devices on your system beforehand.

Entering the bootloader

The bootloader can be entered by sending the appropriate command to the device via USB:

$ overlay64 boot

To manually enter the bootloader, hold down the BOOT button while powering on the device, then release the BOOT button.

Installing and updating the firmware

Once a working firmware and bootloader are installed, the firmware can be updated using the overlay64 utility:

$ overlay64 update overlay64-firmware-1.2.hex

This will automatically enter the bootloader, update the firmware and reset the device.

Note that in case the above command should not work (e.g. in case of a corrupted firmware), you can always enter the bootloader manually and then use avrdude directly:

$ avrdude -p m1284p -c usbasp -U flash:w:overlay64-firmware-1.2.hex

If you have build the firmware from source you can use the program target of the toplevel Makefile as well.

Note that firmware version 1.1 contains a bug that may prevent device detection to work properly under certain flavors of Windows. Windows will report the devices as unknown or not working properly. In this case, temporarily remove the LM1881 IC as a workaround. Without the LM1881, the overlay64 will not display anything, but device detection should work properly so that the firmware can be updated using the above commands.

Installing and testing the device

The pin header at the lower left corner needs to be connected to the power supply and to the host video signal.

Power Supply

VCC must be connected to +5VDC. GND should be connected as close as possible to the video signal. Significantly longer ground return paths will result in loss of video synchronization, especially when overlaying text on dark contents.

VCC and GND and must come from the same source that is used to power the circuit generating the video signal the and the input lines being sampled. Do not use different power sources.

Video Signal

The pin labeled VIDEO needs to be connected to the host video signal.

This can either be the luminance portion of an S-Video signal or a composite video signal (FBAS/CVBS).

Commodore C64

The C64 outputs both an S-Video signal (chrominance/luminance) and a composite signal (FBAS/CVBS) at the Audio/Video connector.

The overlay64 video signal can be added to the S-Video output, the composite output, or both.

S-Video only

To add the signal to the S-Video output only, Connect the overlay64 VIDEO pin to the luminance signal available at Pin 1 of the A/V connector.

If you don’t want to connect the luminance signal directly at the A/V jack but prefer to connect it somewhere else on the board, make sure that you only connect to the signal after it has been amplified by the HF-Modulator circuit.

Do not connect the non-amplified luminance signal directly from the VIC.

Composite only

To add the signal to the composite output only, connect the VIDEO pin to the composite signal available at Pin 4 of the A/V connector. Note though that the signal is weaker in general and will also vary with the brightness of the overlayed video signal.

Both S-Video and Composite (experts only)

If you want the signal to appear at both the S-Video and composite outputs you will have to connect the overlay64’s VIDEO pin to the emitter of the luminance transistor on the HF-Modulator daughter board.

This solution not optimal since the display will be dimmer overall and will be susceptible to disturb video synchronization, especially when the host signal already displays bright content. Use this option only if you really need it.

Here are the schematics for the modulator variants found in the C64. The red dot marks the point where the signal can be connected:

Note that there are more than two layouts of the modulator board in existence, so make sure you pick the right spot.

Testing the device

Once the powersource and and the video signal is connected, set the brightness potentiometer to the middle position first.

Now power on the host device.

Since there is no user configuration yet, the device will display a few lines of default text at the top and bottom of the screen:

Adjusting brightness

Use the brightness pot to adjust the brightness to a level suitable for your needs. Turning the knob to the right will increase the strength of the signal added to the host video signal, and thus increase the text brightness.

Note that at the end of the scale the signal will begin to disturb the synchronization of the video up to the point where video synchronization is completely lost.

Configuring USB devices on the PC

The overlay64 implements two separate USB devices, a remote control device and a bootloader device.

During normal operation, the remote control device will be active and accessible from the PC using the overlay64 utility. This device will identify itself to the host using the following properties:

Vendor OpenMoko, Inc.
Manufacturer Henning Bekel
Device Overlay64
Vendor ID 1d50
Product ID 6100

The device emulates the USBasp programmer while in bootloader mode. This device will identify itself to the host using the following properties:

Vendor Van Ooijen Technische Informatica shared ID for use with libusb
Manufacturer www.fischl.de
Device USBasp
Vendor ID 16c0
Product ID 05dc


On Linux, the required udev rules are installed alongside the overlay64 utility. In order to use the usb devices directly after installation, issue

# udevadm control --reload-rules

When in bootloader mode, the bootloader device will be symlinked to /dev/usbasp. During normal operation, the overlay64 control device will be symlinked to /dev/overlay64. These symlinks are created with file permissions 0666, allowing access for any user. If you want to restrict access, edit the respective udev-rules in /etc/udev/rules.d/10-overlay64.rules.


Once you connect one of the usb devices for the first time, Windows will insist on trying to download and install a driver for these devices. Since both devices are general purpose USB devices, this is futile, since there simply are no drivers for windows to install. You must abort the windows driver installation dialog to prevent windows from permanently marking the device as unusable due to its perceived lack of “proper” drivers.

Instead, use the Zadig tool to generate and install minimal drivers that simply associate the devices with the subsystems required for general purpose access.

Run Zadig, connect the usb cable to the overlay64 and power up the device. Zadig should now detect the Overlay64 device. Install the WinUSB driver for this device.

Now enter the bootloader. The Zadig tool should now detect the USBasp device. Install the WinUSB driver for this device, too.

Note though that in case you wish to use avrdude instead of the overlay64 client for updating the firmware, you may need to install the libusb-win32 driver instead of WinUSB for the USBasp device. The versions of avrdude available for windows may still be linked against the obsolte libusb-0.1, which is the libusb version that is only supported by Zadigs libusb-win32 driver.

Installing the overlay64 utility


For the windows version, use the binary installer package. This will also install the required libusb-1.0.dll. The installation directory will be added to your PATH environment variable and can thus be called from from any directory on the command prompt.


Linux & MacOSX

libusb-1.0 and corresponding development packages (if any) need to be installed on your system.

$ tar vxzf overlay64-1.2.tar.gz
$ cd overlay64-1.2
$ make
$ make install

This installs the overlay64 binary into /usr/local/bin. The PREFIX variable can be used to install with a different prefix, e.g. use make PREFIX=/usr install to install into /usr/bin instead. The DESTDIR variable can be used for a staged install.

On linux, the udev rules required for the USB devices will be installed to /etc/udev/rules.d as well. As root, run

# udevadm control --reload-rules

after installation.


If you’re using cygwin you can build a windows binary in the same way as under Linux or MacOSX. The required cygwin-packages are libusb-1.0 and libusb-1.0-devel. Note that the resulting binary will still need cygwin dlls to be present.

A native win32 binary can be build using mingw32 under Linux or Cygwin. If necessary, edit the Makefile and adjust the MINGW32 variable to the proper prefix for your toolchain. Then use make win32 to build overlay64.exe.


The configuration file is a plain text file in human readable format. Using the overlay64 utility, this file is converted to a binary format and flashed into the EEPROM memory of the Microcontroller. See the configure command.


In general, the configuration determines what text to display where, depending on specific input lines and their states, as well as when to display text at all, either automatically (when the input lines change), or manually (depending on the state of user defined control lines). Here is an example:

screen manual

  sample 0
    when 0
      write 0 10 "INPUT LINE 0 IS LOW "
    when 1
      write 0 10 "INPUT LINE 0 IS HIGH"

screen notify


  sample 1 2
    when 00 write 1 10 "BOTH LINES ARE LOW           "
    when 01 write 1 10 "LINE 1 IS LOW, LINE 2 IS HIGH"
    when 10 write 1 10 "LINE 1 IS HIGH, LINE 2 IS LOW"
    when 11 write 1 10 "BOTH LINES ARE HIGH          "

control 16 manual 0
timeout 100

The first directive denotes the beginning of a screen section, which in this case is set to manual control mode. A screen is a unit of configuration which can be displayed and controlled independently other screen units. manual mode means that the screen will only be displayed when another line defined as a control line for this screen is activated.

The first screen contains one sample section, which is configured to sample the first control line (line 0). Sample sections must define at least one write command for one ore more possible input line states, where the respective state is specified using the appropriate when clause.

A write command finally defines the location (row and column) and the actual text to display.

Thus if the first screen is active, line 0 will be permanently monitored. If it is found to be high, the text “INPUT LINE 0 IS HIGH” appears on row 0, column 10 on the screen. If it is found to be low, the text “INPUT LINE 0 IS LOW “ will be written at the same location.

The second screen directive marks the start of the next screen section. This section is set to notify mode, which means that this screen will only be shown for a certain time after being activated. The timeout is defined in number of frames by the global timeout directive. The screen is activated whenever the state of the lines sampled in this section changes, thus the screen will automatically notify the user of changes.

The sample section in this screen samples control lines 1 and 2 simultaneously. The state of these lines is combined to a two bit value. Likewise, the when cases are defined for all possible two bit values, so there are four cases in total.

The control directive defines line 16 as an active-low manual control line for the first screen (screen 0). This means that as long as this line is driven low, the screen is active, all samples are performed and text is displayed accordingly.

Control lines can also be configured in notify mode, which means that a rising edge on the line will cause the associated screens to be activated for timeout frames.

The timeout directive sets the global timeout value for notifications. It is given in total number of frames. Thus for a PAL signal at 50Hz, a timeout value of 50 will set a timeout of one second.

Note that screens can contain write commands outside of sample sections, which will be performed independently of input line states as long as the screen is activated.

In general, active screens are rendered in the order in which they are defined in the configuration file. In case two or more active screens write to the same physical line, only the result of the write commands from the screen defined earlier in the configuration file will become visible.

There is another screen mode called always which causes the screen to be displayed regardless of current input or control line states.

Note that as a general rule, screens are only activated if doing so would result in at least one write operation to be performed, regardless of whether the above rules have already caused the screen to be activated.

Also note that control lines can be configured to control one or more screens at the same time.

The overall syntax and the individual directives will be explained in detail in the next sections.


Whitespace and comments

Empty lines as well as leading and trailing whitespace characters are ignored. Whitespace is only significant to separate individual tokens and keywords.

Comments begin with a hash character # and continue for the remainder of the current line.


Custom symbols can improve flexibility and readability of the configuration file. They are defined using simple name/value pairs.

<name> = <value>

Symbol names must consist of alphanumeric characters, digits and underscores only. If a symbol name equals one of the reserved command names, a corresponding error message will be issued.

Once a symbol has been defined, any subsequent occurence is replaced by its literal value. If a symbol is used before it is defined, an error message will be generated.

String literals

String literals must be enclosed by double quote characters. Both the opening and closing double quote must appear on the same line. The following escape sequences are recognized:

\" inserts a literal double quote character

\\ inserts a literal backslash character



screen [<mode>]

Denotes the start of a new screen section and sets the screen mode. Screens can be referenced by other commands using their index, where the first screen defined in the configuration file is indexed by zero.

Mode is either “manual”, “notify” or “always”. If no mode is given, manual mode is used by default.

Screens configured in manual mode can only be activated explicitly by a user defined control line.

Screens configured in notify mode will be automatically activated for timeout frames if the state of any input lines sampled in this screen changes.

Screens configured in mode “always” are always activated, regardless of current input or control line states, but only if the following rule also applies:

Regardless of screen mode, screens are only activated if doing so will cause at least one effective write operation to be carried out after the above rules have been applied.


control <line> <mode> <screen...>

Defines an input line as an external digital control line activating one or more screens and operating in the given control mode.

Mode must either be “manual” or “notify”.

In manual mode, the line becomes an active-low control line which causes the associated screens to be activated as long as the line is driven low.

In notify mode, a rising edge will cause the associated screens to be activated for timeout frames.


sample <line...>

Causes one or more lines to be sampled an their states combined to a binary value, where the first line given will be used as the most significant bit. Sample directives are followed by when statements covering some or all of the possible combinations of line states.


when <value>

Commands immediately following this statement will be executed only if the the given value corresponds to the state of the control lines currently sampled.

The value is given as a binary string consisting of 0 (low) and 1 (high) and must contain a value for each input line currently sampled.


write <row> <col> "<text>"

Writes the specified string to the display, starting at the specified position.

There are 30 rows indexed from 0 to 29, and 53 columns indexed from 0 to 52 available.

Strings must contain only 7-Bit printable ASCII characters (ASCII codes 32-127). Results for characters greater than 127 are undefined.

See String literals for additional contstraints.


timeout <frames>

The timeout directive specifies the duration for displaying notifications triggered by a screen or control using “notify” mode.

The duration is given in number of video frames. For a PAL signal at 50Hz, a value of 50 corresponds to one second. For an NTSC signal at 60hz, a value of 60 corresponds to one second.

Using the overlay64 utility

The overlay64 is a command line utility. When called without arguments, the following synopsis is displayed:

overlay64 v1.1
Copyright (C) 2016 Henning Bekel.
License GPLv3: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

      overlay64 <options>
      overlay64 [configure] <infile|->
      overlay64 convert [<infile>|-] [<outfile>|-]
      overlay64 update <firmware>
      overlay64 font-convert <infile> <outfile>
      overlay64 font-update <infile>
      overlay64 identify
      overlay64 boot
      overlay64 reset

      -v, --version : print version information
      -h, --help    : print this help text

      configure    : read/parse configuration and flash to eeprom
      convert      : convert configuration to/from binary/text format
      update       : update firmware from Intel HEX file
      font-convert : convert C64 charset to overlay64 font file
      font-update  : install font from overlay64 font file
      identify     : report firmware version and build date
      boot         : make device enter bootloader mode
      reset        : reset device (leave bootloader/restart application)

      <infile>   : input file, format is autodetected
      <outfile>  : output file, format determined by extension
      <firmware> : firmware in binary or Intel HEX format (.bin or .hex)

      *.conf : plain text config file format
      *.bin  : binary file format (default)
      *.hex  : Intel HEX file format
      -      : standard input/output


--help displays the above synopsis of options and commands.

--version displays version, copyright and license information.


Single file argument

overlay64 <filename>

If the sole argument is found to be a filename, the configure command is implied.


overlay64 configure <filename|->

Transfers the given configuration to the device.

Parses a configuration file denoted by the <filename> argument and converts it to the internal binary configuration format, then transfers the configuration to the device, where it is stored in EEPROM memory. Finally, the device is reset and the new configuration becomes effective.

The configuration file may either be a textual configuration file or a binary configuration file previously converted using the convert command.


overlay64 convert <infile|-> <outfile|->

Converts configuration files to/from binary/textual format. When <infile> is found to be a textual configuration file, it is converted to binary format and vice versa.


overlay64 update <firmware>

Enters the bootloader, updates the firmware and resets the device.

<firmware> must be a file in either Intel HEX format, determined by the extension .hex, or a binary file, determined by the extension .bin.


overlay64 font-convert <infile> <outfile>

Converts a C64 character rom image to an overlay64 font. Copies only those characters which are present in both ASCII and PETSCII. The remaining characters like backtick, tilde, circumflex etc. are copied from the default overlay64 font.

The resulting file can be edited with any program suitable for editing 8x8 bitmap fonts, e.g. a C64 font editor.


overlay64 font-update <infile>

Uploads the given overlay64 font image to the device and resets it. Uses only the first 768 bytes (96 characters) from the given file.


overlay64 boot

Make the device enter the bootloader by sending the corresponding command via USB.


overlay64 reset

Resets the device. Leaves the bootloader or restarts the application.


overlay64 identify

Identifies the device. If the application is running, the firmware version and build date are reported. If the device is in bootloader mode, the bootloader version is reported.

Standard input and output

The filename argument - denotes standard input or output if indicated by the command synopsis.

Font file format and rendering constraints

File format

Font files are binary files containing 96 8x8 bitmapped characters corresponding to the ASCII codes 32-127 (e.g. all printable 7-bit ASCII characters). As such it can be edited with any editor suitable for 8x8 bitmapped fonts.

The font-update command also accepts bigger files, however only the first 96 characters (768 bytes) are flashed to the device.

Rendering constraints

During rendering, a small, about one pixel wide horizontal gap remains between the rightmost pixel of the preceding character and the leftmost pixel of the succeeding character. The output line does not change state during this gap, which means that if the rightmost pixel is set, it remains set until the leftmost pixel of the next character is rendered. In other words, the rightmost column is actually rendered two pixels wide. Therefore the rightmost column should usually remain empty.

The fonts provided with the overlay64 source distribution have all been designed with an empty rightmost column for this reason.

Keep this constraint in mind when converting C64 fonts using the font-convert command.


Copyright (C) 2016 Henning bekel <h.bekel@googlemail.com>

Hardware licensed under CERN OHL v.1.2, see ./hardware/LICENSE.txt
Software and firmware licensed under GNU GPLv3, see ./LICENSE

The software contains MIT licensed code from https://github.com/arkku/ihex for reading Intel HEX files, copyright (C) 2013-2015 Kimmo Kulovesi, see ./intelhex/LICENSE

The firmware contains the V-USB Driver (https://www.obdev.at/vusb), (C)2008 Objective Development GmbH.

Distributed in the ./bootloader directory is the USBasp bootloader, (C)2013 Stephan Baerwolf (matrixstorm@gmx.de) and (C)2008 Objective Development GmbH (https://www.obdev.at/vusb).

In compliance with the terms of the (identical) V-USB driver and USBasp bootloader licenses (./firmware/usbdrv/License.txt and ./bootloader/License.txt, the entire project is published under


In addition, this distribution contains

The USB Product and Vendor IDs for the Overlay64 USB device have kindly been provided by OpenMoko, Inc (http://openmoko.org).