terça-feira, 26 de novembro de 2019

A cassete do ZX Spectrum (I)

O Sinclair ZX Spectrum foi lançado para gravar dados em cassetes de áudio, dado ser barato na época. Os dados são armazenados em cassete através de sons de áudio modulados.

Saliente-se que por corte de custos, não existe nenhum chip dedicado para controle de tempo / DMA / interrupts na carga de dados de cassette. Todo o sampling, contagem de tempo, armazenamento de dados e comunicação com o EAR e MIC, tem de ser realizado com exclusiva dedicação do processador Z80.

O MIC/EAR são controlados pela ULA, na porta 254.


Como se pode ver no mapa da porta 254 da ULA, o input do EAR é no bit 6, e o output pelo MIC, é no bit 3. Mais uma vez 0 significa activo, e 1 não activo. Por defeito, está em 1.


Na cassete, usando a(s) rotina(s) da ROM, SA_BYTES e LD_BYTES, são gravados ou carregados bits, sendo que um registo de CPU armazena os bits (para gravar ou para ler). Quando os oito bits são consumidos, o próximo byte é escrito / lido na RAM. A verificação de erros é feita por um XOR dos bytes carregados.

Basicamente, os sons na cassete são uns e zeros.  Necessita-se de dois impulsos (on/off), para fazer um ciclo. (square wave).

A média de transferência de dados na rotina da ROM da cassete são 1500 bauds.

O tempo de alternância entre estes é que define a frequência que está a ser usada. Na rotina da ROM o 1 tem aproximadament~1000us de duração, ou seja 1000Hz e o 0 ~509us, ou seja 1964Hz.   

No sampling, importa mais a transição e Hz / ciclos para determinar se estamos a lidar com um 1 ou 0, do que propriamente os sinais serem 1 ou 0.  A polaridade do sinal não interessa -  a rotina de carregamento da ROM apenas detecta transições entre os sinais.

Existem diversos tipos de categorias de sinais na rotina da ROM:

- som de piloto/guia: antes de cada bloco, uma sequência de 8063 (header) ou 3223 (dados) impulsos, cada com um comprimento de 2168 estados T.
- impulsos de sincronismo: o piloto é seguido por dois impulsos de sincronismo, de 667 e 735T, respectivamente.
- código de cabeçalho/bytes/checksum (dados/bytes) - bytes codificados em 8 bits. Um bit 0 é  codificado com 2 impulsos, cada um de 855T. O bit 1 é codificado com 2 impulsos com o dobro do tempo, de 1710T.
- 941T silencio.


WAV de uma tape. Sendo 8 bits zeros a seguir ao SYNC2, isto é um bloco de cabeçalho. Note-se que os 8 zeros são os 8 bits de cabeçalho. Um bit 1, é do dobro do tamanho/tempo de um bit 0. O leader, é para exemplificar o tipo de onda, o leader é bastante mais comprido.

As linhas de cores do border são apenas indicadores visuais para o utilizador, e não têm influência no processo de passagem de / para a cassete.

Como já mencionado no artigo do beeper, quanto a ouvir-se o som dos dados a serem transferidos de cassete, isto tem a ver com o desenho do ZX Spectrum. O som não é gerado por software, mas sim uma consequência do desenho do hardware.

Uso de rotinas da ROM para transferência de dados em cassette


Normalmente usam-se rotinas da ROM para ler e gravar dados, e não se controla directamente o EAR e MIC; aliás, o mais comum é usar as directivas BASIC LOAD "" CODE e SAVE "" CODE.

Por exemplo para gravar um programa C/M a partir de 50000, de 1000 bytes:

SAVE "programa" CODE 50000,1000

e para o carregar:

LOAD "" CODE

Para gravar e ler dados de cassette, as principais rotinas da ROM são a $04C2 SA_BYTES e $0556 LD_BYTES. Estas rotinas são pontos de entrada directos na ROM na rotina de cassettes, e não esperam por uma tecla i.e. sendo invocadas, são executadas de imediato.

A rotina da ROM para gravar blocos de dados é:

$04C2 - SA_BYTES - Save bytes to tape
------------------------------------
On entry:
  A:  00=header, FF=data
  IX= start address to save from
  DE= number of bytes to save
 
 


Portanto, o equivalente ao anterior BASIC,  para gravar um bloco de dados, sem headers, é:

LD  A,$FF   ; dados
LD  IX,50000 ; grava a partir de 50000
LD  DE,1000  ; 1000 bytes
CALL $04C2  ; chama SA_BYTES
JR NC,tape_error
A rotina da ROM, para carregar blocos de dados é:

$0556 - LD_BYTES - Load Bytes From Tape
--------------------------------------
On entry:
  A:  00=header, FF=data
  Cy: 1=load, 0=verify
  IX= start address to load/verify to
  DE= number of bytes to load/verify
On exit:
  C : bytes loaded or verified
  NC: nothing done, or load or verify error

Para carregar um bloco de dados, sem headers:

SCF            ; load
LD A,$FF ; dados
LD IX,50000
LD DE,1000
CALL $0556 ; chama LD_BYTES
JR NC,tape_error

Como a rotina LD_BYTES lida directamente com dados, e não com headers, irá também carregar o primeiro *header*  que apareça a seguir. Normalmente esta rotina era usada em loaders de software, tipo carregar um bloco em BASIC, e depois carregar blocos de dados sem headers, que era esperado que viesse a seguir na fita de cassete.

Exemplo ASM como gravar e carregar blocos sem headers





Para mais informações, fica o link:

Data storage on cassette tape

Notas:

Nunca é demais salientar a importância de gravar blocos sem headers imediatamente a seguir (na tape), a blocos que os carreguem. De outra forma, sem headers, torna-se bastante dificil de organizar/classificar qual a sua função.

Os valores de A de $00 para headers e $FF são arbitrários da ROM. A usar  rotinas de LOAD e SAVE em C/M, que não pretendam ser compatíveis com a ROM, podem ter qualquer valor.

Note-se que embora a definição das rotinas SA-BYTES e LD-BYTES mencionem que DE é o número de bytes, são o número de bytes transferidos de e para memória - na realidade na tape são gravados DE+2 bytes, sendo os bytes  - tipo de bloco (1 byte) + DE bytes + XOR checksum (1 byte)

O desenho do ZX Spectrum tenta minizar ruído a forçar o utilizador a usar o volume a cerca de 70-75%.

(a continuar na parte II (carregamento com headers) e III (turbo loaders) )

Ver  https://retrocomputing.stackexchange.com/questions/8442/copying-tapes-back-in-the-day/8478#8478  e  http://www.worldofspectrum.org/ldbytes.html

O autor deste artigo, também é o autor do TAPE2TAP em 1996, um programa para MS-DOS, para digitalizar cassetes de Spectrum. Sources aqui. O TAPE2TAP foi o utilitário de companhia do WSpecem do mesmo autor, o primeiro emulador de ZX Spectrum para Windows, e a base das rotinas de cassete do famoso emulador de ZX Spectrum para MS-DOS Warajevo.

1 comentário:

  1. ver tb http://www.hugi.scene.org/online/coding/hugi%2020%20-%20tadtape.htm

    ResponderEliminar