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 aproximadamente ~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, é:
A rotina da ROM, para carregar blocos de dados é:LD A,$FF ; dadosLD IX,50000 ; grava a partir de 50000LD DE,1000 ; 1000 bytesCALL $04C2 ; chama SA_BYTES
JR NC,tape_error
$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.
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.
ver tb http://www.hugi.scene.org/online/coding/hugi%2020%20-%20tadtape.htm
ResponderEliminar