{
"metadata": {
"name": "coco"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Light Runner, an exercise in digital preservation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In my teens, I wrote a [Tron][] work-alike called _Light Runner_ in\n",
"assembly for the Color Computer; I even got Prickly Pear Software to\n",
"release it commercially. I can't find my source code (_Grrr!_), but I have a\n",
"copy of the product on cassette tape. I didn't quite get it restored\n",
"to working order, but I had some fun trying.\n",
"\n",
"[Tron]: http://en.wikipedia.org/wiki/Tron_(video_game)\n",
"\n",
"\n",
" \n",
" Audio cassette data in Audacity\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"**Processing the digital signal** involved a steep learning curve. As\n",
"explained on pg. 10 of The FACTS:\n",
"\n",
"> G. Cassette Interface - Cassette data is stored onto the tape\n",
"> using a format called Frequency Shift Keying (FSK). This means that\n",
"> two sine waves of differing frequency are used to zeroes and ones\n",
"> on the tape. A sine wave of 2400 hz is used to store a one, and a\n",
"> sine wave of 1200 Hertz is used to store a zero.\n",
"\n",
"I surfed around, wondering whether to make this an R project or a numpy project.\n",
"The clincher was a StackOverflow clue on [detecting zero crossings][1] by Jim Brissom Oct 1 2010:\n",
"\n",
"[1]: http://stackoverflow.com/a/3843124"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def zero_crossings(signal):\n",
" return numpy.where(numpy.diff(numpy.sign(signal)))[0]\n",
"a = [1, 2, 1, 1, -3, -4, 7, 8, 9, 10, -2, 1, -3, 5, 6, 7, -10]\n",
"zero_crossings(a)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 2,
"text": [
"array([ 3, 5, 9, 10, 11, 12, 15])"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Making a numpy array out of a `.wav` file is a piece of cake.\n",
"Scaling the amplitude to fit in an 8 bit DAC like the CoCo's\n",
"helps eliminate some high frequency noise:\n",
"(@@see `cloadm.py`)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import wave\n",
"import cloadm as c\n",
"tape_fn = 'lr-cut.wav'\n",
"dest_fn = 'light-runner'\n",
"tape = wave.open(tape_fn, 'r')\n",
"dest = open(dest_fn, 'w')\n",
"framerate, signal = c.wavLoadMono(tape)\n",
"amp_max = 128 # 8 bit signed\n",
"signal = signal * amp_max / max(signal)\n",
"framerate, len(signal), signal[:5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 3,
"text": [
"(44100, 1223945, array([16, 17, 17, 17, 17]))"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next step is to find the long sequence of\n",
"alternating 0s and 1s that mark the beginning of a sequence of bytes.\n",
"In Audacity, I could hear the tone right around 2 seconds in.\n",
"The signal at this point looks about right:"
]
},
{
"cell_type": "code",
"collapsed": true,
"input": [
"%pylab inline"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].\n",
"For more information, type 'help(pylab)'.\n"
]
}
],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"t = arange(2.0, 2.01, 1.0/framerate)\n",
"_ = plot(t,\n",
" signal[t[0] * framerate:t[0] * framerate + len(t)])\n",
"grid()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "display_data",
"png": "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\nxf8Hfi3Ai3Y1rDkAAAAASUVORK5CYII=\n",
"text": [
""
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The pattern of bits was close, but not quite there, no matter how I played with the threshold:"
]
},
{
"cell_type": "code",
"collapsed": true,
"input": [
"freqs, wave_ix = c.waves(zero_crossings(signal), framerate)\n",
"threshold = 1400 # experimental; cf. (CoCo.rate0 + CoCo.rate1) / 2\n",
"bits = (freqs > threshold) + 0\n",
"bits[wave_ix > 2.0 * framerate][:40]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 5,
"text": [
"array([1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0,\n",
" 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0])"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I pored over the disassembly from _The FACTS_, wondering what I'd missed:"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"*** LOOK FOR THE SYNC BYTES - RETURN WITH ACCA = 0 IF SYNC\u2019ED\n",
"*** ON HI - LO TRANSITION, ACCA = $A0 IF SYNC\u2019ED ON THE\n",
"*** LO - HI TRANSITION OF THE INPUT SIGNAL FROM THE CASSETTE.\n",
"CASON ORCC #$50 DISABLE IRQ,FIRQ\n",
" BSR LA7CA TURN ON TAPE DECK MOTOR\n",
" CLR CPULWD RESET UP TO SPEED COUNTER\n",
"LA782 BSR LA763 WAIT FOR LO-HI TRANSITION\n",
"LA784 BSR LA7AD WAIT FOR HI-LO TRANSITION\n",
" BHI LA797 CASSETTE SPEED IN RANGE FOR 1200 HZ\n",
"LA788 BSR LA7A7 WAIT FOR LO-HI TRANSITION\n",
" BCS LA79B CASSETTE SPEED IN RANGE FOR 2400 HZ\n",
" DEC CPULWD DECREMENT UP TO SPEED COUNTER IF SYNC\u2019ED ON LO-HI\n",
" LDA CPULWD GET IT\n",
" CMPA #-96 HAVE THERE BEEN 96 CONSECUTIVE 1-0-1-0 PATTERNS\n",
"LA792 BNE LA782 NO\n",
" STA CBTPHA SAVE WHICH TRANSITION (HI-LO OR LO-HI)\n",
" RTS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Aside_: I haven't found _The FACTS_ online, but the disassemblies\n",
"are also available in [Color-Basic-Unravelled.pdf][cbu], also\n",
"by Spectral Associates, digitally restored by [Aaron Wolfe][aw].\n",
"\n",
"[cbu]: https://sites.google.com/a/aaronwolfe.com/cococoding/home/docs/color-basic-unravelled.pdf?attredirects=0&d=1 \n",
"[aw]: https://sites.google.com/a/aaronwolfe.com/ \n",
"\n",
"I finally found the bug by\n",
"\n",
" - focussing on an even smaller section of the signal,\n",
" - together with the calculated frequencies and the derived bits: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lo = int(framerate * 0.560)\n",
"hi = int(framerate * 0.580)\n",
"lo, hi\n",
"\n",
"ix = intersect1d(where(wave_ix > lo)[0], where(wave_ix < hi)[0])\n",
"\n",
"ones = ix[bits[ix] == 1]\n",
"zeros = ix[bits[ix] == 0]\n",
"_ = plot(arange(lo, hi), signal[lo:hi], 'b-',\n",
" wave_ix[ix], (freqs/20)[ix], 'g*',\n",
" wave_ix[ones], bits[ones], 'r+',\n",
" wave_ix[zeros], bits[zeros], 'ro')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "display_data",
"png": "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\n",
"text": [
""
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Do you see it?\n",
"\n",
"The crossings start lo-hi for the first five bits, but somehow\n",
"the next bit is marked at a hi-lo transition.\n",
"\n",
"I added a line of code to say that they should all go the same direction:\n",
"\n",
" assert((numpy.sign(signal[z[::2]]) == numpy.sign(z[0])).all())\n",
"\n",
"When the signal crossed zero by actually hitting zero, it threw things off.\n",
"So I tweaked `zero_crossings` algorithm to use `sign() > 0` so that we\n",
"have just +/-, rather than +1/0/-1:"
]
},
{
"cell_type": "code",
"collapsed": true,
"input": [
"def zero_crossings(signal):\n",
" return numpy.where(numpy.diff(numpy.sign(signal) > 0))[0]\n",
" \n",
"zero_crossings([2, 1, 0, -1, -2, 1, 4, -4])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 7,
"text": [
"array([1, 4, 6])"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now the 1's and 0's alternate nicely:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"freqs, wave_ix = c.waves(zero_crossings(signal), framerate)\n",
"threshold = 1400 # experimental; cf. (CoCo.rate0 + CoCo.rate1) / 2\n",
"bits = (freqs > threshold) + 0\n",
"bits[wave_ix > 2.0 * framerate][:40]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 8,
"text": [
"array([1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n",
" 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0])"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This allows us to find the sync pattern:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"c.find_sync(bits)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 9,
"text": [
"1145"
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Putting it all together, we see that we get a certain distance before falling out of sync:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import logging\n",
"logging.basicConfig(level=logging.INFO)\n",
"import StringIO\n",
"tape = wave.open(tape_fn, 'r')\n",
"dest = StringIO.StringIO()\n",
"try:\n",
" c.decode(tape, dest)\n",
"except ValueError:\n",
" print \"oops!\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 0 length: 15\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected check $88 does not match found $8\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected check $6d does not match found $ed\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected check $f0 does not match found $70\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 1 length: 255\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected check $6 does not match found $86\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected block start $55 does not match found $ab\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"WARNING:cloadm:expected block start $3c does not match found $78\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"INFO:cloadm:block type: 2 length: 254\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"oops!\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The filename and copyright statement confirm that we're on the right track:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"content = dest.getvalue()\n",
"print \"filename:\", content[:8]\n",
"print\n",
"print content[229:298].replace('\\x00', '\\n')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"filename: RUNNER \n",
"\n",
"LIGHT RUNNER\n",
"COPR(C) 1983 BY CO&CO SOFTWARE\n",
"WRITTEN BY: DAN CONNOLLY\n",
"\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Related Work\n",
"\n",
"@@@move this bit up; end with copyright statement\n",
"\n",
"Browsing around the [coco mailing list][ml]\n",
"I found a `CASIN.EXE` program by Jeff Vavasour circa 1994;\n",
"I got it running under dosbox; the first thing it said was:\n",
"\n",
" This .WAV file is not a 11025Hz/mono/8-bit sample.\n",
"\n",
"So sox to the rescue:\n",
"\n",
" $ `sox ../../lr-cut.wav -r 11025 -b 8 lr8.wav`\n",
"\n",
"Then `CASIN` made some progress, but didn't get very far.\n",
"It decoded even less data than my code did. I might have felt\n",
"a little silly poring over all the low-level details if\n",
"there was a well-known solution that worked out of the box.\n",
"But data analysis and signal processing is a growing part\n",
"of my day job, and learning the scientific python toolset\n",
"has been on my todo list for quite some time, so I'm glad I did.\n",
"\n",
"[ml]: http://five.pairlist.net/pipermail/coco/\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Colophon\n",
"\n",
"I'm trying out [IPython] as an authoring tool.\n",
"I'm fond of the interactive notebook idea.\n",
"The 0.12 version that comes with Ubuntu didn't support\n",
"inline plotting, and cell selection was glitchy.\n",
"But I'm using 0.14dev, and while it doesn't quite feel as\n",
"mature as RStudio, it's getting pretty close.\n",
"\n",
"[IPython]: http://ipython.org/"
]
}
],
"metadata": {}
}
]
}