Editor Version ×

1.Easy to use and quick to get started

2.The process supports design scales of 300 devices or 1000 pads

3.Supports simple circuit simulation

4.For students, teachers, creators


1.Brand new interactions and interfaces

2.Smooth support for design sizes of over 30,000 devices or 100,000 pads

3.More rigorous design constraints, more standardized processes

4.For enterprises, more professional users

Std EditionC64 TapeDump64

Profile:Dump your old Commodore Datasette Tapes

License: CC-BY-SA 3.0

Published Time:2021-12-03 03:18:59
  • 317
  • 0
  • 1


TapeDump64 is a simple and inexpensive adapter that can interface a Commodore Datasette to your PC via USB in order to dump your old software saved on tapes as TAP files. It is inspired by TrueTape64, a similar project by Francesco Vannini. The integrated USB to serial converter can also be used as a SerialUPDI programmer for the on-board ATtiny microcontroller, so that no additional hardware is required to flash the firmware.



The schematic is shown below:



I finally wanted to use one of the (not quite so) new 8-pin tinyAVRs for a project. Here it fits really well. It has enough pins, hardware UART and a timer/counter B (TCB), which is specially designed for CPU-independent frequency and pulse length measurements. Since the firmware requires less than 800 bytes of flash, any of these MCUs can be used: ATtiny202, ATtiny212, ATtiny402 or ATtiny412. Don't buy them in China, they are much cheaper e.g. at Digikey (€0.45).

USB to Serial Converter

The CH340N (or CH330N) is now in use everywhere with me. At around €0.45 (if you buy 10 pieces) it is very cheap, fast, small, uncomplicated, reliable and hardly requires any external components (not even a crystal). It's probably the best choice for this small project too. And it is also used as a SerialUPDI programmer for the ATtiny.

Boost Converter

In order to provide the approximately 6.1V for the motor of the Datasette, a boost converter based on the inexpensive MT3608 is installed on the board. Controlling the motor with 5V would certainly also be possible, but the reduced speed would then have to be compensated by software later. It is difficult to estimate what this would mean for the accuracy of the sampled data.

Cassette Port

The cassette port is a 12-pin edge connector as part of the printed circuit board (PCB) with a spacing of 3.96mm, where 6 pins are on each sides (top and down) of the PCB. The opponent contacts are connected with each other, A with 1, B with 2, and so on. The connector of the datasette is pushed directly onto this port. A notch between B/2 and C/3 prevents accidental polarity reversal.

Pin Signal Description
A / 1 GND Ground
B / 2 +5V 5 Volt DC
C / 3 MOTOR Motor Control, approx. 6.1 Volt power supply of the motor
D / 4 READ Data Input, read data from Datasette
E / 5 WRITE Data Output, write data to Datasette (not used here)
F / 6 SENSE Detection, if one of the keys PLAY, RECORD, F.FWD or REW is pressed



Working Principle

The data is stored on the tape as a frequency modulated waveform. This signal is read from the Datasette, amplified and converted into a TTL-level square wave with the same pulse lengths and then output to the READ pin of the cassette port. TapeDump64 reads this square wave and measures the pulse durations between the falling edges of the signal. The associated TAP data bytes are calculated from the pulse lengths, which are then sent to the PC via USB and written there into the TAP file.


Interpretation of the Pulse Lengths

The actual data is coded using a sequence of pulses of different lengths. The standard Commodore system uses patterns of three different pulse lengths: short (390µs), medium (536µs) and long (698µs). Each byte of data is preceded by a marker consisting of a long pulse followed by a medium one. A "0" bit is represented by a short pulse followed by a medium one, while a "1" bit is a medium pulse followed by a short one. Each byte on the tape ends with a parity bit.

However, fast loaders are often used, each of which uses different pulse lengths and patterns, which complicates matters overall. Fortunately, TapeDump64 doesn't have to decode the data. This is because only the raw data is saved in the TAP file in the form of the individual pulse lengths. The actual interpretation of these pulses is done later by the C64 or a corresponding emulator.

Timing Accuracy

The accuracy of the measurement of the pulse lengths depends on various factors. For example, not all motors in the Datasettes run at exactly the same speed. In addition, the C64 measures the pulse length via the timer of the CIA as the number of passed system clock cycles, but the PAL versions of the C64 have a different clock frequency (985248 Hz) than the NTSC versions (1022730 Hz). Badly aligned read heads of the Datasette as well as old tapes with weakened signals contribute to the rest.

That's why the difference between the individual pulse lengths used for the encoding of the data is large enough to be able to reliably differentiate between them even under the circumstances mentioned. In fact, it is not the measured pulse length itself that is relevant, but whether it is above or below a defined threshold value. Furthermore, turbo loaders often use a mechanism to synchronize with the data stream from the datasette.

TAP File Format

The TAP file format attempts to duplicate the data stored on a C64 cassette tape, bit for bit. It was designed by Per Håkan Sundell (author of the CCS64 C64 emulator) in 1997. Since it is simply a representation of the raw serial data from a tape, it should handle any custom tape loaders that exist. The layout is fairly simple, with a small 20-byte header followed by the file data:


Bytes (hex) Description
0000-000B File signature "C64-TAPE-RAW"
000C TAP version (0 - original, 1 - updated, 2 - halfwave extension)
000D Computer platform (0 - C64, 1 - VIC-20, 2 - C16, Plus/4, 3 - PET)
000E Video standard (0 - PAL, 1 - NTSC, 2 - OLD NTSC, 3 - PALN)
000F Future expansion
0010-0013 File data size (little endian; not including the header)
0014-xxxx File data

In TAP version 0, each data byte in the file data area represents the length of a single pulse determined by the following formula:

data byte = pulse length (in seconds) * C64 clock frequency (in Hertz) / 8

Therefore, a data value for a pulse length of 390µs would be:

0.000390s * 985248Hz / 8 = 48 (0x30 in hex)

A data value of 0x00 represents an "overflow" condition, any pulse length which is more than 255 * 8 clock cycles or 2078µs in length. Such a pulse length does not encode any data and normally only occurs in the pauses between a program and the following one on the same tape. However, the lengths of these pauses can be relevant for some fast loaders.

In TAP version 1, the data value of 0x00 has been re-coded to represent values greater than 255 * 8 clock cycles or values with a greater resolution (one clock cycle instead of eight). When a 0x00 is encountered, three bytes will follow which are the actual pulse length in C64 clock cycles. The three bytes are stored in little endian format (least significant byte first). For example, a data value for a pulse length of 2875µs would look like this:

0.002875s * 985248Hz = 2832 (data bytes: 0x00, 0x10, 0x0B, 0x00)

TAP Version 2 is an extension made by Markus Brenner for C16 tapes. It is version 1, but each value represents a halfwave, starting with a '0' to '1' transition. The time encoding doesn't change.

However, in practice, neither the storage of longer pulse lengths nor the higher resolution are relevant in most cases. That's why TAP version 0 is used for TapeDump64.


Without going too much into detail, the ATtiny measures the pulse lengths with its timer/counter B (TCB) in frequency measurement mode. The TCB continuously counts upwards at 8MHz until a falling edge is detected at the READ output of the Datasette. The current value of the counter is automatically saved, the counter is then reset to zero and restarted. In addition, an interrupt is triggered, in whose service routine the stored value is read out, divided by 64 and pushed into the output buffer for transmission to the PC.

As you can see, the calculation of the TAP values is based on a resulting clock frequency of 1MHz instead of 0.985248MHz for PAL or 1.022730MHz for NTSC. However, due to the resolution and the valid measuring range of the TAP format, this does not lead to any noteworthy deviations in the end result.

The tapedump Python script controls the device via three simple serial commands:

Command Function Response
"i" transmit indentification string "TapeDump64\n"
"v" transmit firmware version number e.g. "v1.0\n"
"r" read file from tape raw data stream

The raw datastream starts with a 0x00 as soon as PLAY on tape was pressed. Each valid pulse the device reads from the tape will be converted into a single non-zero byte which represents the pulse length according to TAP file format version 0 and immediately transmitted via UART. Invalid pulse lengths that would lead to TAP values of less than 16 are ignored. TAP values that would be greater than 255 are limited to 255 and later marked as a pulse overflow (byte 0x00) by the Python script. If STOP on tape was pressed or a timeout waiting for valid pulses occurs, the end of the stream is shown with a 0x00 byte. Afterwards, the 16-bit checksum, which is formed from the addition of all data bytes, is transmitted least significant byte first (little endian). Finally, the tape buffer overflow flag is transmitted as a single byte (0x00 means no overflow occured).

If PLAY was not pressed within the defined period of time at the beginning, a 0x01 is sent instead of a 0x00 and the procedure is ended.

The Python script itself writes the TAP file header and the received data bytes into the output file.

Compiling and Uploading the Firmware

  • Set the serial mode switch on the device to "UPDI".
  • Connect the device to a USB port of your PC.
  • Use one of the following methods:

If using the Arduino IDE

  • Open your Arduino IDE.
  • Make sure you have installed megaTinyCore.
  • Go to Tools -> Board -> megaTinyCore and select ATtiny412/402/212/202.
  • Go to Tools and choose the following board options:
    • Chip: Select the chip you have installed on your device
    • Clock: 16 MHz internal
    • Programmer: SerialUPDI
    • Leave the rest at the default settings.
  • Go to Tools -> Burn Bootloader to burn the fuses.
  • Open the TapeDump64 sketch and click Upload.

If using the makefile (Linux/Mac)

  • Download AVR 8-bit Toolchain and extract the sub-folders (avr, bin, include, ...) to /software/tools/avr-gcc. To do this, you have to register for free with Microchip on the download site.
  • Open a terminal.
  • Navigate to the folder with the makefile and the Arduino sketch.
  • Run DEVICE=attiny412 PORT=/dev/ttyUSB0 make install to compile, burn the fuses and upload the firmware (change DEVICE and PORT accordingly).

Operating Instructions

  • Set the serial mode switch on your TapeDump64 to "UART"
  • Connect your TapeDump64 to your Commodore Datasette
  • Connect your TapeDump64 to a USB port of your PC
  • Execute the tapedump python script on your PC: python tapedump.py outputfile.tap
  • Press PLAY on your Datasette
  • The dumping is done fully automatically. It stops when the end of the cassette is reached, when there are no more signals on the tape for a certain time or when the STOP button on the Datasette is pressed.

TapeDump64_pic2.jpg TapeDump64_cli.jpg

Checking, Cleaning and Converting TAP Files

The TAP file generated by TapeDump64 can be used directly in your favorite emulator or with the Tapuino, but perhaps you want to check it beforehand, optimize it or convert it into another format. This works perfectly with the command line tool TAPClean. To check the quality of the generated TAP image, use the following command: tapclean -t outputfile.tap Remember, a TAP file is almost never 100% clean, as pauses in particular are not always correctly recognized. You can optimize the quality of the file with the following command: tapclean -o outputfile.tap Slight deviations in the pulse lengths are compensated for and everything is adapted to the exact timing specifications. TAPClean not only knows the required pulse lengths of the standard Commodore coding, but also those of all common fast loaders. If you want to convert the TAP file into a WAV audio file, then use the following command: tapclean -wav outputfile.tap There is also a graphical front end for TAPClean.

References, Links and Notes

  1. TrueTape64 Project
  2. Tapuino Project
  3. How Commodore Tapes Work
  4. How TurboTape Works
  5. Analyzing C64 Tape Loaders
  6. Archiving C64 Tapes Correctly
  7. TAP File Format
  8. VICE Emulator File Formats
  9. TAPClean
  10. TAPClean Front End
  11. Datasette Service Manual
  12. ATtiny Datasheet
  13. CH340N Datasheet
  14. MT3608 Datasheet

TapeDump64_pic3.jpg TapeDump64_pic4.jpg TapeDump64_pic5.jpg



This work is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License. (http://creativecommons.org/licenses/by-sa/3.0/)



Open in editor


Open in editor
Project Attachments
Project Members


周一至周五 9:00~18:00
  • 0755 - 2382 4495
  • 153 6159 2675


周一至周五 9:00~18:00
  • 立创EDA微信号


  • QQ交流群


  • 立创EDA公众号