Find file History
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
README.md
apple2.hgr
gen3.py
sense4.s

README.md

Notes on the 23kbps prototype

See also #4 for more discussion.

Quick start

The main test environment for 23kbps receive is sense4.s, a short 6502 assembly program that receives images over the cassette port and displays them as hi-res images (8kb each image, stored from $2000 to $3fff).

cl65 -t apple2 -C apple2-asm.cfg sense4.s
../bin/c2t-96h -2 ~/garden/apple2/sense4,bf00 sense4.wav

Then on the Apple II, follow the instructions generated by ct2:

	CALL -151
	BF00.BF91R BF00G

Now generate waveforms using gen3.py and send them:

python gen3.py < apple.hgr | play -r 48000 -e unsigned -b 16 -c 1 -t raw /dev/stdin

Images should appear.

An explanation of the encoding

A cycle is a high pulse followed by a low pulse. The width of each pulse carries 2 bits of information; the width is (44 + 27 * sym) µs where sym is 0 through 3. A byte is 4 symbols (in big-endian order, the top two bits are the first symbol).

There is a bit of massaging of the signal to increase the contrast between wide and narrow pulses, to compensate for degradations in the signal path that reduce this contrast. That logic is in decidePulseWidthRaw and is a bit hard to explain; all the fudge factors were determined by experiment. Without those corrections, the encoding still kinda works but is not reliable.

The amplitude of the pulse is inversely proportional to its width, to guarantee that the generated signal has no DC offset. Any DC offset would be filtered out by the high-pass filter between the cassette port and 741 input, and would have the effect of further reducing contrast between wide and narrow pulses.

The Python waveform generating code contains an atlas of the possible pulse widths, each of which is obtained from convolving a box with an FIR filter that band-limits to the audio range. For simplicity and easy visualization of the results, internally the code generates a signal sampled at 192kHz. Downconversion to 48kHz is simple; just taking every 4th sample works because it is band-limited.

The leader is 128 3 symbols (wide pulses) followed by [0, 3, 3, 3] repeated 4 times. This pattern is designed to be easy to detect (it's only the 14 lines of code following start_sync0) and hard to trigger accidentally.

Next steps

The Python code was designed for experimentation, and is not a particularly efficient way to generate waveforms. A better approach is to use BLEP generation. This is a general technique that can generate all existing waveforms, with higher quality (which should manifest as a wider range of volumes for which decoding is reliable) and greater flexiblity of choice for sampling rate.