Ero sivun ”Spectravideo” versioiden välillä
Tnt (keskustelu | muokkaukset) (Ak: Uusi sivu: ; 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...) |
Tnt (keskustelu | muokkaukset) |
||
Rivi 1: | Rivi 1: | ||
+ | |||
+ | == Physical interface and memory mapping== | ||
+ | Spectravideo 3x8 uses [https://en.wikipedia.org/wiki/Intel_8255 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. | ||
+ | |||
+ | [[Tiedosto: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 === | ||
+ | |||
+ | [[Tiedosto:wave_normal_falling_edge.svg]] | ||
+ | |||
+ | Time between falling edges is clearly different. | ||
+ | |||
+ | === Inverted signal: === | ||
+ | |||
+ | [[Tiedosto: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. | ||
+ | |||
+ | [[Tiedosto: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 | ||
+ | |||
+ | [[Tiedosto: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 | ; SYNC | ||
: 400 * 55h (raw) | : 400 * 55h (raw) |
Versio 26. marraskuuta 2017 kello 13.16
Sisällysluettelo
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.
- 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
Time between falling edges is clearly different.
Inverted signal:
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.
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
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