programmable video overlay module
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:
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.
- Ordering Assembly Kits
- Installing the firmware
- Installing and testing the device
- Configuring USB devices on the PC
- Installing the overlay64 utility
- Using the overlay64 utility
- Font file format and rendering constraints
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
configuration utility, Windows 32-bit installer package
Gerber files for pcb revision 1
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 airmail is free of charge.
You can order kits via email at firstname.lastname@example.org
To place an order, please include the word “Overlay64” in your subject. State your full name, the number of kits you want and your complete international shipping address. You will then receive an email containing payment information (bank transfer only).
Please note that you will have to pay in advance to confirm your order. Since I’m doing all of this in my spare time and on a short budget, I can’t afford to keep complete assembly kits on stock. Instead, I will keep just the PCBs in stock and buy the remaining parts when a sufficient number of orders is reached. This means that it could take a few weeks until you get your kits. However, I will inform you about the status of your order in regular intervals.
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
|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|
|-||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 email@example.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
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
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.
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.
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).
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.
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.
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:
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:
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|
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
0666, allowing access for any user. If you want to
restrict access, edit the respective udev-rules in
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
PREFIX variable can be used to install with a different prefix,
make PREFIX=/usr install to install into
DESTDIR variable can be used for a staged install.
On linux, the udev rules required for the USB devices will be
/etc/udev/rules.d as well. As root, run
# udevadm control --reload-rules
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-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
variable to the proper prefix for your toolchain. Then use
win32 to build
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 write 0 0 "THIS IS THE SECOND SCREEN" 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 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
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 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.
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.
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.
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. Usage: 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 Options: -v, --version : print version information -h, --help : print this help text Commands: 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) Files: <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
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
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
.hex, or a binary file, determined by the extension
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.
Make the device enter the bootloader by sending the corresponding command via USB.
Resets the device. Leaves the bootloader or restarts the application.
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
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.
font-update command also accepts bigger files, however only the
first 96 characters (768 bytes) are flashed to the device.
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
Copyright (C) 2016 Henning bekel <firstname.lastname@example.org>
The firmware contains the V-USB Driver (https://www.obdev.at/vusb), (C)2008 Objective Development GmbH.
In addition, this distribution contains
- a circuit diagram in PDF format, see ./hardware/overlay64-schematics.pdf
- the full source code for the host software in ./firmware
- a README file in ASCII format which describes the purpose of the project and what can be found in which directories and which files
- references to (https://www.obdev.at/vusb)
The USB Product and Vendor IDs for the Overlay64 USB device have kindly been provided by OpenMoko, Inc (http://openmoko.org).