Spectravideo

Kohteesta Kasettilamerit
Loikkaa: valikkoon, hakuun

Physical interface and memory mapping

Spectravideo 3x8 uses Intel 8255 Programmable Peripheral Interface to read and write cassette data.

I/O ports used for cassette data:

Port A (0x98)
Bit 7: Cassette: Read data
Bit 6: Cassette: Ready
Port C (0x97)
Bit 5: Cassette: Write data
Bit 4: Cassette: Motor relay control (0=on, 1=off)

All ports are in mode 0 - simple I/O.

Svi ppi 8255.png

Official Spectravideo cassette players
SV-903 Data Cassette (1800 bps, stereo, microphone)
SV-904 Data Cassette (1800 bps)
Do-it-yourself interface for any cassette player
Universal Cassette Interface> by Peter Zevenhoven. Published in C.U.C. magazine #18.

Cassette data lead-in and sync

Lead-in consists of 3200 alternating short and long pulses.

Normal signal

Wave normal falling edge.svg

Time between falling edges is clearly different.

Inverted signal:

Wave inverted falling edge.svg

Time between falling edges is constant because it takes one half of both short pulse and long pulse.

Spectravideo ROM code checks the polarity of cassette signal with a routine at 0x2117. It does that by measuring 100 pulse pairs and checking whether their lengths are all far enough from each other to be normal signal or close enough to be inverted signal. If cassette signal is inverted, code sets flag at 0xFD4C to non-zero value. Read_pulse routine at 0x2164 uses this flag to use either falling or rising edge to measure pulse length.

Once the polarity has been detected, ROM code at 0x2149 waits until it finds bit pattern 01111111. Only then it returns and the actual header starts.

Wave svi 3x8 sync.svg

Stop byte

Whenever the tape is stopped, one extra zero byte (with start bit) is written, followed by a short pause before the tape player motor is actually stopped.


Data bytes

Everything except the lead-in and sync mark is stored with nine pulses - each data byte has a start bit prepended to it. That is done to give some extra time for inter-byte processing and to ensure that Spectravideo can accurately measure length of the first data bit. Start bit is always a long pulse (0) but that isn't checked in the loader code.

For example, byte 0x31 ("1") is coded as

Wave svi 3x8 byte 31.svg

The first pulse is the start bit, next eight are bits "00110001" stored the most significant bit first.

Header

Header consists of 17 bytes:

Type
Header type - repeated 10 times
File name
Name in ASCII - six chars, padded with space (0x20)
Attribute byte
Extra byte used to tell which screen mode was used when saving screen data. Otherwise unused.

Cassette is stopped after writing the header. This routine at 0x206C adds one more zero byte which isn't technically part of the header.

Different file types

Spectravideo uses the following standard file types, but nothing stops users from using their own, either by calling ROM functions or rolling their own ones. Note that the zero byte written by _CTWOFF routine called at STOP is not explicitly shown below.

=== CSAVE ... - tokenized BASIC program ===
SYNC
HEADER - type=0xD3, attribute=0xFF
STOP
SYNC
DATA[] - tokenized BASIC
7 * 0x00
STOP
=== CSAVE ...,S - screen mode 0, text only ===
SYNC
HEADER - type=0xD3, attribute=0x00
STOP
SYNC
DATA[] - 0x03C0 bytes, written to VDP[0x0000-0x03BF] (text)
STOP
=== CSAVE ...,S - screen mode 1, hi-res ===
SYNC
HEADER - type=0xD3, attribute=0x01
STOP
SYNC
DATA[] - 0x1800 bytes, written to VDP[0x0000-0x17FF] (bitmap)
DATA[] - 0x1800 bytes, written to VDP[0x2000-0x37FF] (color)
DATA[] - 0x0080 bytes, written to VDP[0x1B00-0x1B7F] (sprite attributes)
DATA[] - 0x0800 bytes, written to VDP[0x3800-0x3FFF] (sprite data)
STOP
=== CSAVE ...,S - screen mode 2, lo-res ===
SYNC
HEADER - type=0xD3, attribute=0x02
STOP
SYNC
DATA[] - 0x0600 bytes, written to VDP[0x0000-0x05FF] ()
DATA[] - 0x0080 bytes, written to VDP[0x1B00-0x1B7F] (sprite attributes)
DATA[] - 0x0800 bytes, written to VDP[0x3800-0x3FFF] (sprite data)
STOP
=== BSAVE ...,start,end,exec - binary data ===
SYNC
HEADER - type=0xD0, attribute=0x00
STOP
SYNC
start.w - 16-bit start address, low byte first
end.w - 16-bit end address
exec.w - 16-bit execution address (if not given in BSAVE command exec defaults to start)
DATA[] - from start to end, inclusive
STOP
=== OPEN "CAS..." - Sequential file ===
=== also used when BASIC program is saved in ASCII format, using command SAVE ...,A
SYNC
HEADER - type=0xEA, attribute=0x00
STOP
SYNC
DATA [256] - 256 bytes of data
STOP
SYNC + DATA[] + STOP - repeated until the last block
SYNC
DATA [256] - last block is padded with 0x1A, no other info about the data length is given
STOP






SYNC
400 * 55h (raw)
1 * 7fh (raw)
BYTE
STARTBIT : - this is not verified to be zero when reading
DATA : MSB first
STOP
1 * 00
pause
motor off
HEADER
10 * type
6 * name - padded with spaces
1 * attribute

CSAVE ...
SAVE "CAS..."
CLOAD ...
SYNC
HEADER D3,FF - CSAVE, not screen
STOP
SYNC
DATA[] - tokenized BASIC
7 * 00
STOP
CSAVE ...,S
SAVE "CAS...",S
CLOAD ...
SYNC
HEADER D3,00 - CSAVE SCREEN 0
STOP
SYNC
DATA[03C0h] - written to VDP[0000h-03BFh]
STOP


SYNC
HEADER D3,01 - CSAVE SCREEN 1
STOP
SYNC
DATA[1800h] - written to VDP[0000h-17FFh] - bitmap
DATA[1800h] - written to VDP[2000h-37FFh] - color
DATA[0080h] - written to VDP[1B00h-1B7Fh] - sprite attributes
DATA[0800h] - written to VDP[3800h-3FFFh] - sprite data
STOP


SYNC
HEADER D3,02 - CSAVE SCREEN 2
STOP
SYNC
DATA[0600h] - written to VDP[0000h-05FFh] - color
DATA[0080h] - written to VDP[1B00h-1B7Fh] - sprite attributes
DATA[0800h] - written to VDP[3800h-3FFFh] - sprite data
STOP

BSAVE ...,start,end,exec
BLOAD ...
SYNC
HEADER D0,00 - BSAVE
STOP
SYNC
start.w - lo,hi
end.w - --
exec.w - --
DATA[] - from start to end, inclusive
STOP

OPEN "CAS..." - Sequential file
SAVE ,A
SYNC
HEADER EA,00 - Sequential file
STOP
SYNC
DATA [256]
STOP
...
SYNC
DATA {256] - last block is padded with 1Ah
STOP