The Kansas City Standard

I was pondering my laser transmitter the other day, and began to think of how I might transmit digital information from the Arduino to the remote receiver. Since I am old, I remember the old days where programs used to be stored on an obsolete audio storage medium called cassette tape. Indeed, the first storage device I ever used was the Atari 410 tape drive pictured on the right.

The Atari stored data at 600 baud, using FSK (data is stored as short bursts of two different tones, in the case of the Atari 3995 and 5327 hz), using a variant of the so-called Kansas City Standard. KCS was a standard for storing data on cassettes that was developed at a Byte magazine sponsored symposium in 1975.

Data is converted to short bursts of 1200Hz and 2400hz tones to represent zeroes and ones, respectively. Each burst is 1/300 of a second long, meaning that it sends 300 bits per second. Each 8 bit character is framed by a 0 start bit, and a pair of 1 stop bits so that character frames can be identified. It was designed to be a reliable if slow format, and succeeded on both counts. It transmits about 27 characters per second. An 8K download would take about five minutes.

It’s amazing we ever lived through the stone age.

Anyway, I thought it would be fun to make an Arduino library to send this information over my laser link, but first I decided that it would be good to test to make sure I understood how the format worked. So, I coded up a small program to generate some test .WAV files from an input data file. I made the problem simpler by generating the output at the somewhat non-standard sample rate of 9600 samples per second. This considerably simplifies the generation of samples, since they only would have amplitudes of zero, plus or minus one, and plus or minus sqrt(2)/2. I coded up the following C code, and generated this WAV file.

A WAV file that contains an ASCII test message, encoded in Kansas City Standard

The encoder is simple, the decoder, somewhat less so. So, to test that I was generating the proper bits, I used Martin Ward’s decoder written in Perl which did a good job of decoding the sample WAV files. I haven’t tested the robustness of this format with respect to noise yet, but it does appear to work reasonably well.

It wouldn’t be that hard to modify the simple sound generation code I used before to send data in this format. I think I will try to get to that next week.

[sourcecode lang=”c”]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sndfile.h>

/*
* kc.c
* A program which takes a file as input, and encodes it via the old
* Kansas City Standard – a 300 baud format that was used by old
* microcomputers to store data onto cassette tape.
*
* http://en.wikipedia.org/wiki/Kansas_City_standard
*
* We are going to produce a 9600 sample per second output file…
*
* Each "baud" is 32 samples long.
*
* A ‘0’ is 4 cycles @ 1200 Hz.
* A ‘1’ is 8 cycles @ 2400 Hz.
*
* 0 – 0 R2 1 R2 0 -R2 -1 -R2
* 1 – 0 1 0 -1
*
*/

#define R2 (.70710678118654752440f)

SNDFILE *sf ;
SF_INFO sfinfo ;

void
output(float f)
{
sf_write_float(sf, &f, 1) ;
}

void
send(int bit)
{
int c ;

switch (bit) {
case 0:
for (c=0; c<4; c++) {
output(0.f) ;
output(R2) ;
output(1.f) ;
output(R2) ;
output(0.f) ;
output(-R2) ;
output(-1.f) ;
output(-R2) ;
}
break ;
case 1:
for (c=0; c<8; c++) {
output(0.f) ;
output(1.f) ;
output(0.f) ;
output(-1.f) ;
}
break ;
default:
abort() ;
}
}

void
encode(int ch)
{
int i ;
send(0) ; /* start bit… */
for (i=0; i<8; i++) {
send(ch & 1) ;
ch = ch >> 1 ;
}
send(1) ; /* two stop bits */
send(1) ;
}

main()
{
int i, ch ;

sfinfo.channels = 1 ;
sfinfo.samplerate = 9600 ;
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;

sf = sf_open("test.wav", SFM_WRITE, &sfinfo) ;

for (i=0; i<9600/4; i++)
output(0.) ;
while ((ch = getchar()) != EOF)
encode(ch) ;
for (i=0; i<9600/4; i++)
output(0.) ;

sf_close(sf) ;
}
[/sourcecode]

6 thoughts on “The Kansas City Standard

  1. Chris Johnson

    Great stuff. I was interested to see in your previous video that the response time of the solar cell was quick enough to enable voice transmission (for some reason I had assumed that solar cells, like LDRs, would be very slow). Do you have any idea what bandwidth is actually possible?

  2. Mark

    I was surprised too. I have been unable to find details on the AC performance of photovoltaic cells, at least in a way that makes sense. I suspect they are limited by some capacitance which probably increases with cell area. I can imagine using the Arduino to generate some test signals and see what happens.

  3. Eric Smith

    That 27 characters per second was a huge improvement from the 10 cps paper tape reader on the ASR33. Then I used an Apple II, which had a variable speed cassette interface with an average of about 187 cps. We live in an era of amazing speed!

  4. Eric Baker

    Mark,

    I wrote some code for the Arduino to transmit PSK31 and RTTY50 using a software DDS.

    You could probably hook up the laser the arduino, have your little Radio Shack amplified speaker reproduce the signal and feed it into you favorite amateur radio digital mode software through a microphone. (Or figure out how to connect the solar cell to the sound card)

    Anyhow, here is the link: http://satilla.com/wy/arduino-digi-wy7a.zip

    The audio it produces has a lot of sidebands and thus clicky, probably due to lack of raised cosine pulse shaping.

    Enjoy!

    73

    Eric (WY7A, formerly WY7USA)

  5. Matt

    Mark,

    I’m often surprised at the timeliness of some of your posts. Just this past week, I was pondering how to archive some cassette based software I have for my Tandy Model 100/200 computers. Naturally, recording them on my desktop seems to be the way to go.

    Your discussion of encoder and decoder above is right up my alley at the moment. Thanks for sharing!

  6. PP5VX (Bone)

    Nice post !

    Loved to make some great “buzzy sounds”
    like do my past ZX-81, and a STANDARD
    PACKET (1200b) and PSK31, on my Arduino
    2009 Board.

    Changing times… heeee ? (hi)

    TNX for the best sharing of it !

    73/DX from,
    PP5VX (Bone)
    So. Brazil
    http://www.qrz.com/db/pp5vx

Comments are closed.