CHR$128 para o TK85
Por Kelly Abrantes Murta - Zeddy-Br
11 de Agosto de 2010


Jogo Aeroporto em HRN
a década de 80, no auge do boom dos microcomputadores de 8 bits, fez muito sucesso aqui no Brasil uma pequena adaptação feita nos TKs que possibilitava a redefinição dos 64 caracteres disponíveis no micro. Uma dessas adaptações, de autoria de  Bernhard Wolfgang Schön, foi publicada na revista Micro Bits em uma série de três artigos e acho que fez bastante sucesso entre aqueles usuários que tinham familiaridade com o ferro-de-solda. A alguns anos atrás, por ocasião do encontro do Canal 3 que aconteceu aqui em Belo Horizonte, eu implementei essa modificação em meu TK85  mas acabei retirando-a logo após o encontro pois, apesar de funcionar perfeitamente, a montagem ficou muito tosca, com uma montoeira de fios dentro do TK.

Pois bem, após eu ter implementado o vídeo composto by Victor Trucco e com a versatilidade e eficiência proporcionada pelo projeto O.T.L.A. no carregamento de programas via porta cassete, deu uma vontade danada de experimentar novamente a sensação de ver no TK85 os joguinhos em alta-resolução por redefinição de caracteres e foi daí que surgiu o material para este artigo e com uma funcionalidade extra, inexistente no projeto original.

A geração de caracteres no ZX81

Antes de passar à montagem, vamos rever então como são gerados os caracteres que o ZX81 envia para tela durante a geração de vídeo.

Cada caracter é formado a partir de uma matriz de 8x8 pixels armazenados na ROM a partir do endereço $1E00 (7680 em decimal). Assim, cada caracter é definido por 8 bytes sucessivos, resultando em 512 bytes o total de memória necessário para definir todos os 64 caracteres disponíveis. Tome como exemplo o caracter A:

A

O código deste caracter é 38 e sua matriz de definição está armazenada a partir do endereço 7984 (7680+38*8). Examinando os oito bytes subsequentes encontramos a seguinte sequencia:

hexadecimal   binário
   00         00000000
   3C         00111100
   42         01000010
   42         01000010
   7E         01111110
   42         01000010
   42         01000010
   00         00000000

Pois bem, se quisermos redefinir este caracter precisaremos alterar os oito valores acima, mas como estão localizados em ROM isso não é possível. Teríamos que transferir a tabela de caracteres para a RAM, redefinir os caracteres e informar ao sistema operacional onde localizar a nova tabela de caracteres, o que é feito através do registrador I do processador Z80. Durante o boot, esse registrador é carregado com o valor $1E indicando que a tabela está armazenada a partir do endereço $1E00, no final da ROM de 8Kb. Se transferirmos a tabela de caracteres para o endereço $6000 (24576) devemos alterar o registrador I para apontar para a nova tabela, o que pode ser feito com o pequeno código abaixo:

       ld a,$60
       ld i,a
       ret

Mas o que acontece quando executamos o código acima após transferir a tabela de caracteres para o endereço $6000? Você vai observar um efeito muito curioso: a tela ficará preenchida com padrões de pixels totalmente estranhos, algo parecido com a figura ao lado.

A primeira vez em que eu fiz isso em meu TK82C, ficava imaginando o que deu errado, afinal eu havia transferido a tabela para a RAM e alterado o registrador I para a nova posição, então por que a bagaça não funcionava?!

Para saber a razão, é necessário antes compreender como o TK envia para a TV as informações do arquivo de tela (DFILE), o que tentarei explicar a seguir.

O arquivo de tela do TK é armazenado em RAM e sua posição é indicada pela variável de sistema DFILE. Quando o circuito de geração de vídeo interrompe o programa do usuário para rodar a rotina de interrupção responsável pela geração da imagem na TV, em um dado momento é executado a instrução JP (HL), onde o par de registradores HL contém o valor do DFILE+$8000. Nesse momento, o TK identifica a linha A15 do Z80 em nível lógico 1 e a linha /M1 (opcode fetch) em nível lógico 0. Imediatamente o TK coloca as linhas D0 a D7 do barramento de dados do Z80 em nível lógico 0, forçando-o a executar a instrução NOP para cada código de caracter no DFILE. Paralelamente, os bits 0 a 5 do código do caracter que está sendo processado naquele momento são capturados e armazenados em um registrador de 6 bits e o bit 7 armazenado no INVERT register, tudo isso ocorrendo durante os ciclos T1 e T2 da execução do NOP pelo  Z80. Nos ciclos seguintes (T3 e T4), o Z80 ativa o sinal /RFSH e o TK passa a montar o endereço da posição de memória onde será capturado o byte que formará cada linha do caracter. Para isso existe um circuito contador de 0 a 7 (o LINECNTR), que é incrementado a cada linha do caracter e cuja saída fornece os bits A0 a A2 do endereço. Os bits A3 a A8 são fornecidos pelo seis bits do código do caracter e os bits A9 a A15 correspondem ao conteúdo do registrador I do Z80. Ou seja:

                     A15------A9  A8-----A3    A2-A0

                    <---reg I---> <--CHR--> <-LINECNTR->

Com o endereço montado, os oito pixels correspondentes à linha do caracter que está sendo processada é lido da ROM e enviado para o vídeo shift register que por sua vez envia-o para a TV à taxa de 6.5MHz. Se o bit armazenado no INVERT register for 1, o pixel é invertido antes de ir para a TV.

Pois bem, se o endereço é formado pelo reg I+cód caracter+LINECNTR, por que a rotina acima não funcionou quando o registrador I foi alterado?

A resposta é simples! Todos os eventos relatados acima ocorrem durante a execução da instrução NOP, quando o barramento de endereço do Z80 endereça o código do caracter no DFILE em RAM. Isso implica que o barramento de endereços da tabela de caracteres deve ser isolado do barramento do Z80. Isso é feito por resistores colocados entre as linhas A0 a A8 do Z80 e as saídas de um circuito multiplexador de 16 para 8 linhas, que multiplexa as linhas A0 a A8 com os bits 0 a 8 (CHR+LINECNTR) do endereço da máscara de pixel do caracter durante o ciclo de refresh gerado pela CPU. As saídas desse multiplexador são identificadas no circuito do TK/ZX81 como A0' a A8' e estão conectadas aos pinos A0 a A8 da ROM, enquanto que a RAM está ligada diretamente ao barramento A0 a A8 do Z80. Por isso não adianta apenas fazer o registrador I apontar para a RAM, pois ela sempre estará sendo endereçada pelo Z80, mesmo durante a geração de vídeo.

Diante do exposto, para possibilitar a redefinição de caracteres precisamos implementar uma RAM cujos pinos A0 a A8 estejam conectados às linhas A0' a A8' e a melhor maneira de fazer isso é conectando-os diretamente aos pinos correspondentes da ROM. E é isso o que se propõe o presente artigo, implementar um redefinidor de caracteres montado em uma pequena placa que encaixe diretamente no soquete da ROM do TK85. Isso minimizará a quantidade de fios a serem ligados dentro do TK e tornará o MOD, digamos, menos amador ;-)

O circuito do CHR$128

A figura abaixo mostra o esquema do nosso circuito, onde temos o chip da ROM do sistema operacional e os dois chips de memória 2114, que dispensam maiores explicações. O integrado 74LS138 é o responsável pelo mapeamento das memórias nos primeiros 16Kb do sistema. Quando acessamos os endereços entre 0 e 8191, a ROM do SO é selecionada; entre 8192 e 12287 seleciona-se a ROM do HISPEED e, por fim, entre 12288 e 16383 são selecionadas as memórias 2114. O sinal /ROMCS foi usado para prevenir que haja conflito caso se conecte algum periférico que também requisite essa área de memória. Neste caso, o redefinidor de caracteres ficará desabilitado.

Esquema do CRH$128

A grande novidade desse circuito em relação ao original é o uso do multiplex 74LS157 para criar a linha A9', o que possibilitará o acesso a um banco extra de 64 caracteres de tal forma que o TK85 passará a dispor de até 128 caracteres únicos em oposição aos 64 originais. Para ativar esse banco extra de 64 caracteres é necessário setar o bit 0 do registrador I, o qual normalmente é zero. Por exemplo, para ativarmos um banco de 64 caracteres no endereço 12288 carregamos o registrador I com o valor $30; se quisermos 128 caracteres, carregamos o valor $31 em I. Neste caso, os 64 caracteres extras são acessados através do bit 7 do código do caracter setado. Dito isso, vamos ver como funciona essa parte do circuito.

Quando o sinal /RFSH estiver em nível lógico 1, o 157 ligará a entrada 1B à saída 1Y e A9' = A9. Com o /RFSH ativo, ou seja em nível 0, a saída 1Y (A9') será gerada pelas duas portas NAND na entrada 1A. Neste caso, se A8 = 1 e INVERT = 1, então A9' = 1 e o acesso se dará no segundo banco de caracteres. Caso contrário, A9' = 0 e o acesso será no primeiro banco.

Vale lembrar que o código de caracter com o bit 7 setado força a inversão dos pixels do caracter na saída do sinal de vídeo, portanto, os caracteres do banco extra devem ser definidos em reverso.

Sabendo como o circuito funciona, vamos finalmente para a parte prática!

A montagem do CHR$128

A motagem, apesar de simples, é trabalhosa e requer um pouco mais de atenção e habilidade com o ferro-de-solda. Separe o seguinte material:
A minha intenção era fazer a montagem em uma pci confeccionada especialmente para o CHR$128 mas infelizmente minha impressora está uma porcaria e não foi possível, ainda, confeccionar a pci. Portanto, a seguir descrevo como fazer a montagem em uma placa universal e quando eu conseguir confeccionar a minha pci, atualizo o artigo. De qualquer modo, deixo a seguir o layout da pci para que vocês mesmo possam confeccioná-la, já que assim a montagem é bem mais fácil.

PCI do CHR$128
PCI lado dos componentes


Montagem em Placa Universal

Com o material em mãos, comecem pelo soquete da ROM e pela barra de pinos. Tome por referência a figura a seguir como uma sugestão de layout para a disposição dos componetes. Tanto no esquema do circuito como no layout abaixo a ROM está identificada como 2364 apenas como referência, pois provavelmente na maioria dos TK's ela pode ter outra identificação. O meu por exemplo usa o SCM92879P, para a qual não encontrei referência em nenhun lugar. As 3 próximas fotos são apenas para ilustrar o procedimento de montagem das barras de pino e do soquete da ROM, não é a montagem do MOD propriamente. Infelizmente eu esqueci de documentar esta parte e tive que improvisar para as fotos, I'm sorry :(

Layout da placa do CHR$128

Pegue a barra de pinos e separe dois pedaços com 12 pinos cada. Vamos começar soldando a barra de pinos 1; insira os pinos mais curtos na placa pelo lado cobreado mas não deixe os pinos vazarem do outro lado pois é necessário deixar um espaçamento entre o suporte da barra e a ilha na placa, para poder receber a solda. Para facilitar, coloque a placa sobre a mesa e insira a barra, dessa maneira os pinos não atravessarão do outro lado. Solde o primeiro ou o último pino e cuide para que a barra fique em ângulo de 90º com a placa.  O resultado deve ficar como na foto a seguir:



Solde agora o pino da outra ponta para que a barra fique firme. Pegue o soquete de 24 pinos para a ROM e posicione-o ao lado da barra, pelo outro lado da placa:



Solde os pinos 1 e 24 do soquete, fixando-o em sua posição. O próximo passo é conectar cada pino do soquete com o seu correspondente na barra de pinos, o que pode ser feito apenas com solda ou, se acharem mais fácil, com pedacinhos de fio. Esta parte é muito crítica (e chata) e deve-se tomar muito cuidado para não fechar curto com os pinos vizinhos. Comece pelo pino 13 e siga da esquerda para a direita (a não ser que você seja canhoto), solda na mão esquerda e ferro na direita, e não tenha dó de gastar solda! A cada pino ligado, verifique a continuidade com um multímetro para ter certeza da conexão e de que não há curto com os pinos laterais. Veja o exemplo abaixo com os pinos 13, 14 e 15 já interligados:



Terminando com a barra 1, repita todo o procedimento para a barra 2 e depois fixe os soquetes para os demais CIs, exceto para as memórias 2114 que deverão ser soldadas direto na placa, como explicarei adiante. Finalizada essa etapa, usando fios finos do tipo wireup ou parecidos, proceda à interligação dos componentes conforme detalhado no esquemático do circuito, imprima-o e tenha-o em mãos durante toda a montagem. Uma dica: as linhas de endereçamento e dados entre a ROM e a memória 2114 não precisam ser ligadas sequencialmente, use a sequencia que achar mais conveniente, isto não afetará o funcionamento do circuito. Os demais sinais devem ser ligados rigorosamente conforme consta no esquemático, portanto, bastante atenção nessa hora ;-)

As memórias 2114 deverão ser montadas uma sobre a outra, por isso não será possível o uso de soquete para elas pois a montagem ficaria muito alta e impediria o fechamento do TK. Oriente-se pela ilustração a seguir para montar as 2114:

Montagem das 2114

Veja como ficou a minha montagem, já com os fios para as conexões na placa do TK85:





Finalizada a montagem da placa é hora de conectar o dispositivo, então vamos identificar os pontos de conexão na placa do TK:



A linha A8 é extraída do terminal do resistor R33 e a /ROMCS do terminal do resistor R26 ou R27. /RFSH, /MREQ, A13 e A14 são extraídos dos furos na placa indicados na foto acima. O sinal /WR, que não está mostrado, deve ser extraído do barramento de expansão na sétima trilha contando da direita para a esquerda, conforme pode ser visto nas fotos seguintes. O sinal /HSROMCS deve ser ligado ao pino 18 da ROM do hispeed. Extraia o chip do soquete, levante o pino 18, coloque a ROM de volta ao soquete e ligue o fio do /HSROMCS no pino levantado. O sinal INVERT deve ser extraído do pino 5 do IC16, solde o fio neste pino (é o fio azul nas fotos abaixo).



A montagem finalizada, com o dispositivo já espetado no soquete da ROM:




Pronto, está finalizada a montagem! Primeiro vamos testar a nova RAM em 12288. Conecte o teclado e digite POKE 12288,37 / PRINT PEEK 12288. Se tudo estiver bem, será impresso 37 na tela. Caso contrário, verifique as ligações, veja se não tem nenhum CI com posição invertida e/ou defeituoso. Com tudo OK, carregue alguns programas redefinidos e curta seu novo MOD!