5

EDIT: I realize from reading the comments that I was bit loose in my use of the word "speed" as a property of the tape drive. What I had in mind was the speed of the data transfer, not the speed of the tape across the tape head.

My recollection is super fuzzy at this point, but I seem to remember having a 3rd party gizmo which plugged into the expansion port of the VIC-20 which would dramatically increase the speed of the tape drive. I think it was called the "VIC-rabbit", and that the tape drive plugged into the VIC-20 as it normally would. I was always puzzled how such a device could work. How did this device boost the tape drive's speed and why this wasn't used by the VIC-20 to begin with?

  • 1
    It’s not hard to outdo Commodore’s built-in encoding. Tip of the iceberg: Commodore’s mechanism for error detection is to write the data part of every file twice. If the two don’t match when reloaded, an error is reported and the loading is considered failed. No error correction, no recovery, no advantage whatsoever over the CRC or checksum used by everybody else. – Tommy Sep 7 at 20:07
  • 1
    @LeoB.: The Commodore's tape encoding uses two pulses per bit, which are either long-short or short-long, and includes both a start-of-byte marker before each byte and a parity bit after. The drive unfortunately cannot support Manchester encoding since it only detects flux reversals in one direction, but using tighter pulse spacing and leaving off the extra markers allows for a pretty huge improvement. It's possible to push things even further and encode two bits per pulse by using four pulses widths, but that may cause difficulties on drives with two much flutter. – supercat Sep 7 at 20:53
  • 1
    @LeoB. yeah, 'tip of the iceberg' was meant to clarify that it's just one illustrative example. Full format for a program file is: leader, [header + copy], [program + copy], [end block + copy]. Leader is just 50 cycles of 182 microsecond (2.75 kHz) tone. Bytes are a marker, then the bits, then a parity. The marker is 2x342 µs levels plus 2x262µs; a 0 is 2x182µs + 2x262µs; a 1 is the same as a 0 but reverse the order of long and short. So e.g. drop the marker, the parity and the copies, use 2x182µs for a 0 and 2x262µs for a long, and you're down to 3,552µs/byte average from 18,400µs fixed. – Tommy Sep 7 at 21:16
  • 1
    ... which is ~5.18 times as fast, though it would go down once you introduce a CRC or checksum to replace the copies, especially if you put one e.g. every 256 bytes rather than once per file. I have no idea exactly what the Rabbit does, however, but clearly 5 times is easily within the hardware range. – Tommy Sep 7 at 21:18
  • 1
    @Tommy: Depending upon the lengths of long and short pulses, performance may be improved by writing nine bits per byte, the first of which is used to invert the other eight if 5 or more of them would be set, so that each byte would contain nine bits, but at most four of them would be of the longer duration. – supercat Sep 8 at 1:29
3

As to how such a device might work, look at the standard Commodore tape encoding, common to the PET, Vic-20, C64 and more. The timings actually vary very slightly between those computers when writing, but I'm going to use the archetypal timings given by The Complete Commodore Inner Space Anthology, page 97.

A program file on tape consists of:

  • a leader — a block of high-pitched tone;
  • the program header, then a second copy of the program header;
  • the program data, then a second copy of the program data; and
  • an end marker, followed by a second copy of the end marker.

Those things are encoded through three lengths of square wave:

  • a short wave consists of both a high and low portion, each lasting 182 µs;
  • a long wave consists of both a high and low portion, each lasting 262 µs; and
  • a mark wave consists of both a high and low portion, each lasting 342 µs.

So a complete short wave is 364 µs, a complete long is 524 µs and a complete mark is 684 µs.

The leader is just 50 cycles of 'short' waves. That's fairly straightforward.

The other three parts are built up from bytes, and each byte is formed as:

  • a byte marker;
  • the eight bits from the byte; and
  • a parity bit.

The byte marker is a complete mark wave plus a complete long wave. So it is 342+262 = 604 µs long. Each bit is then either: (i) a long wave followed by a short wave, to signal a '1'; or (ii) a short wave followed by a long wave, to signal a '0'. Therefore each bit is 182+262 = 444 µs long.

There are nine bits plus the marker per byte = 4,600 µs. But every byte is repeated twice, so it actually occupies 9,200 µs.

The machine is sensitive enough to detect the wave lengths as per above, so suppose you instead said that bytes don't have a marker, each one implicitly starts directly after the other. Also there's no parity, and each byte appears once. Instead a 16-bit CRC will be included after every 256 bytes. Also, we can simplify the encoding of each bit — e.g. just use one long wave for a '1' and one short wave for a '0'.

Then the average bit length will be (262 + 182) / 2 = 222 µs. And each byte is just eight bits, so an average of 1776 µs long. Even if you include the new CRC bytes of two per 256, that adds only an average of (2/256)*1776 ~= 13.8 µs per byte. So call the new scheme 1790 µs per byte.

9,200 / 1,790 ~= 5.14.

So just by doing those things, you've increased the data rate to around 5.14 times as much as it was.

I don't know whether that's close to what the Rabbit does or not, but this is how such a device could work.

| improve this answer | |
  • If one wanted to add error correction and didn't mind requiring that all data be written as 128-byte blocks (if loading a file that isn't a multiple of 128 bytes, load the last block into the tape buffer and then copy it to the destination), one could divide storage into even and odd blocks, each guarded by a CRC, and at the end of the file write a block with all the even blocks xor'ed together, and then a block all the odd blocks exor'ed together [compute the xor's while writing out the data]. When reading, if one even and/or one odd block CRC was invalid, replace the loaded block... – supercat Sep 8 at 16:06
  • ...with the "xor-of-everything" block, and then xor that block in memory with the contents of all the other even or odd blocks. That would allow recovery from any action that corrupts at most one even and one odd block, for the cost of adding two more blocks to the tape. – supercat Sep 8 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.