segunda-feira, 30 de abril de 2012

Temporização de vídeo do TK90X (parte 1)

Programas como Rotatrix, que dependem fortemente de sincronização com o vídeo, são extremamente sensíveis às diferenças de temporizações entre o TK90X e os diferentes modelos de ZX Spectrum. Enquanto o computador britânico tem as suas temporizações documentadas (vide comp.sys.sinclair FAQ ou o livro The ZX Spectrum ULA: how to design a microcomputer de C. Smith), a documentação do clone brasileiro parece ter se perdido irremediavelmente. Sendo assim, é necessário haver uma investigação sobre o comportamento do nosso ULA.

ULA "MC16845" do TK90X. Fonte: Cantinho do TK90X.

Como eu não possuo osciloscópio nem analisador lógico, resolvi começar as investigações com base em software mesmo. Estou ciente de que há limitações nessa abordagem, porém encaro como um ponto de partida para futuros refinamentos. Espero que os colegas fãs do TK90X contribuam e ajudem para este trabalho. Nesta primeira parte pretendo apresentar os fundamentos da metodologia e o programa que elaborei para os testes.

Um pouco de teoria

O ULA do TK90X produz um sinal de 60 Hz para o pino /INT (interrupt) do Z80. Cada vez que /INT é ativado, a CPU interrompe o processamento e desvia para uma sub-rotina que se inicia no endereço 56 (#38). A escolha desta frequência não é por acaso, pois é igual à frequência com que se forma um quadro de imagem na TV padrão PAL-M (na Europa usa-se 50 Hz, razão pela qual esta é a frequência de interrupção do Spectrum). O recíproco de 60 Hz é o período de tempo disponível para a geração de um quadro de imagem, correspondente a 16,67 ms (milissegundo ou milésimo de segundo).

O assembly Z80 possui uma instrução especial HALT que interrompe o processamento, até que ocorra uma interrupção. Um candidato natural para iniciar a contagem de tempo é logo após uma instrução HALT, pois haveria uma sincronização com o ULA. Existem desvantagens nessa abordagem que discutirei futuramente.

Sem um instrumento, a forma mais fácil de acompanhar a geração de vídeo é através da cor da borda da tela. Ao contrário da parte principal da tela, cujo conteúdo é armazenado em RAM, a cor da borda pode ser definido apenas por uma simples instrução OUT para a porta 254. A ideia então é fazer um OUT logo após HALT, para depois aguardar um período de tempo bem definido e, ao fim, fazer outro OUT para mudar a cor da borda. Definindo de forma precisa o tempo entre as duas instruções OUT, torna-se possível acompanhar seu efeito na borda da tela.

A rotina de espera deve ser bem elaborada, para que o período de tempo seja realmente bem definido. A forma mais fácil é utilizar uma sequência de instruções NOP que nada faz além de gastar tempo. O tempo no Z80 é medido em número de estados-T, sendo que cada T equivale ao recíproco da frequência do clock (0,2797 µs - microssegundos ou milionésimos de segundos - para um clock de 3,575611 MHz). Cada NOP irá gastar tempo de 4T (1,119µs para o TK90X).

Resumindo, o programa deve ter um começo que prepara o Z80 para aguardar uma interrupção e define uma cor da borda inicial (vermelha), uma sequência de NOP para consumir tempo e, no final, instrução para mudar a cor da borda (ciano) e repetir o ciclo. O resultado que se espera é a mudança da cor da borda a partir de certa linha do vídeo, como exemplificado na figura abaixo.


Listagens

A listagem assembly que contém a rotina principal deste programa segue abaixo:

        ORG 30000
VTMain:
        LD BC,10            ; Number of NOP opcodes.
        PUSH BC             ; Store onto stack.
        LD HL,VTStart       ; Copy initial part of machine code starting from
        LD DE,32768         ;address 32768.
        LD BC,VTEnd-VTStart
        LDIR
        POP BC              ; BC=number of NOP opcodes to be inserted.
        PUSH HL             ; Save VTEnd value.
        LD L,E
        LD H,D
        DEC HL
        LDIR                ; Copy BC NOP opcodes.
        POP HL              ; Recall VTEnd value.
        DEC DE              ; Copy final part of code after the sequence of
        LD BC,VTMark-VTEnd  ;NOP instructions.
        LDIR
        LD HL,32768         ; HL contains address to jump instructions.
        JP (HL)             ; Start the video timing routine.
;
; The following routine starts from address 32768. After HALT instruction, there
;is a delay of 19 T-states plus 4 T-states for each NOP opcode between two OUT
;instructions.
VTStart:
        LD BC,254           ; B signals to read all keys, C is port address.
        IN A,(C)            ; Read keyboard.
        CPL                 ; If some key was pressed,
        AND 011111
        RET NZ              ;return.
        LD A,2              ; Value for red border.
        HALT                ; Wait for the maskable interrupt.
        OUT (C),A           ; Change border to red (12T).
        LD A,5              ; Put cyan border color value in accumulator (7T).
        NOP                 ; 4T delay for each NOP.
; The following routine must be after NOPs.
VTEnd:
        OUT (C),A           ; Change border color. (12T)
        JP (HL)             ; Jump to 32768.
VTMark: NOP


O programa BASIC a seguir providencia a interface com o usuário:

   10 LET bc=1000: INPUT "Z80 clock freq. (MHz)? ";ck
   15 CLS : FOR n=0 TO 21: PRINT AT n,0; BRIGHT n=2*INT (n/2),,: NEXT n: PRINT #0;AT 1,0; BRIGHT 1,,
   20 POKE 30002,INT (bc/256): POKE 30001,bc-256*PEEK 30002
   30 PRINT AT 10,2;"Counter=";bc,'"  Delay=";19+bc*4;" T-states","  Delay=";(19+bc*4)/ck;" microseconds",
   40 RANDOMIZE USR 3e4
   50 LET u$="q": LET d$="a": LET inc=1: GO SUB 100
   60 LET u$="w": LET d$="s": LET inc=25: GO SUB 100
   70 LET u$="e": LET d$="d": LET inc=500: GO SUB 100
   80 GO TO 20
  100 REM Read keyboard
  110 IF INKEY$=u$ THEN LET bc=bc+inc: IF bc>65525 THEN LET bc=65525
  120 IF INKEY$=d$ THEN LET bc=bc-inc: IF bc<1 THEN LET bc=1
  130 RETURN
  800 REM Start
  810 BORDER 6: PAPER 1: INK 9: BRIGHT 8: CLEAR 29999
  820 LOAD ""CODE
  830 CLS : PRINT AT 3,10;"Video Timing"
  840 PRINT ''" This program waits until a "'"maskable interrupt occurs, then"'"changes border color just after"'"a specified amount of time."''" Press keys Q W E to increase"'"time or A S D to decrease."
  850 PRINT #0;" Press any key to start.": PAUSE 0
  860 RUN
  900 REM Save files
  910 SAVE "VideoTime" LINE 800
  920 SAVE "VTCode"CODE 3e4,99


O programa pode ser baixado no 4 Shared (é necessário ter conta). O arquivo ZIP contém imagem de fita TZX e imagem de disco TRDOS para Beta 48 (CAS, CBI-95, IDS, Arcade, etc.).

Na próxima postagem...

Pretendo apresentar as instruções de uso do programa e alguns resultados obtidos.

Nenhum comentário:

Postar um comentário

Seu comentário é bem vindo, mas peço que use este espaço adequadamente.