ACIA 6551A on Z80

Como usar o IC 6551A (ACIA) como interface serie no z80.

Alguma informação sobre o calculo das resistencias pull up e pull down a usar na serie 74LSxxx, os calculos também se aplicam para outras series 74YYxxx, adequando a corrente e os níveis lógicos de tensão.

https://www.electronics-tutorials.ws/logic/pull-up-resistor.html

Datasheet do IC UM6551A

Circuito da placa serial IO (6551A) para o Z80 com o bus RC2014

Esquema de ligação

Ligações dos pinos do IC6551A

GND – GND

CS0 < not(IOREQ_L) and M1 and A3

CS1_L < A2

RST_L < RESET_L

RxC – not connected

XTAL1 < 1.8432MHz clock signal

XTAL2 < not connected

RTS_L > not connected

CTS_L < GND

TxD > TX out

DTR_L > not connected

RxD < RX in

RS0 < A0

RS1 < A1

VCC – VCC

DCD_L < GND

DSR_L < GND

DB0, DB7 – D0, D7

IRQ_L > INT_L

PHI2 < not(RD_L) or not(WR_L) ) and not(IOREQ_L)

R/W_L < WR_L

Algumas notas sobre a ligação do PHI2. Inicialmente, v1 do circuito, tinha ligado o PHI2 directamente ao clock do Z80. O sistema funcionava mas tinha sempre a transmissão de 3 caracteres em vez de 1.

O problema é que como é visível na imagem Z80 – IO timing, existem 3 ciclos de relógio, enquanto que na imagem UM6551 – Timing, é visível que o 6551 espera um único pulso. Por isso passei a usar os sinais RD_L e WR_L, em conjunto com o IOREQ_L, para formar o sinal de entrada em PHI2.

not(RD_L) or not(WR_L) ) and not(IOREQ_L)

Z80 – IO timing

UM6551 – Timing

O circuito de teste foi implementado numa breadboard

Breadboard acia 6551A for z80 circuit test

Programa em z80 assembly que faz uso do circuito como porta serie e que implementa um echo do receive no transmit

            .ORG    0000 

STACKS      EQU     0xFFFF 
ACIA_DATA   EQU     0x08 
ACIA_STAT   EQU     0x09 
ACIA_CMD    EQU     0x0A 
ACIA_CTL    EQU     0x0B 



MAIN:                

; set stack pointer
            LD      SP,STACKS 


; test io ports
            LD      a,0x01 
            OUT     (0x00),a 
            IN      a,(0x00) 
            OUT     (0x00),a 
            LD      a,0xFF 
            OUT     (0x00),a 
            LD      a,0x00 
            OUT     (0x00),a 
            NOP      

; acia 6551 init

            LD      a,%00000000 ;software reset
            OUT     (ACIA_CMD),a 
            LD      a,%00001011 ;no parity, no echo, no interrupt
            OUT     (ACIA_CMD),a 
            LD      a,%00011111 ;1 stop bit, 8 data bits, 19200 baud
            OUT     (ACIA_CTL),a 

;JP      OLDTEST
HELLO:               
            LD      a,$68 
            CALL    OUTCHAR 
            LD      a,$65 
            CALL    OUTCHAR 
            LD      a,$6C 
            CALL    OUTCHAR 
            LD      a,$6C 
            CALL    OUTCHAR 
            LD      a,$6F 
            CALL    OUTCHAR 
            LD      a,$0A 
            CALL    OUTCHAR 
            LD      a,$0D 
            CALL    OUTCHAR 
            
            ;JP      HELLO

LOOP:                

            CALL    INCHAR
            ;a char is received
            LD      c, b
            LD      b,%00001000 
            AND     b 
            JP      nz,INC_IDLE
            ; yes get received char
            LD      a, c
            CALL    OUTCHAR 
            
INC_IDLE:
            ; no received char

            JP      LOOP 


;
; OUTCHAR 
; arguments
; a = char to output
;
OUTCHAR:             
            LD      c,a
OUTCHART:
            ; check transmit flag is set
            LD      b,%00010000 ; 
            IN      a,(ACIA_STAT) 
            ;OUT     ($00),a         ;show stat on leds
            AND     b 
            JP      z,OUTCHART 
            ; send char
            LD      a,c 
            OUT     (ACIA_DATA),a 
            RET      
;
; OUTCHAR 
; arguments
; a = char to output
;
INCHAR:              
            LD      c,$00 
            ; check receiv flag is set
            LD      b,%00001000
            IN      a,(ACIA_STAT) 
            ;OUT     ($00),a         ;show stat on leds
            AND     b 
            JP      z,INCHAR_ 
            ; read receive register
            IN      a,(ACIA_DATA) 
            LD      c,a 
            LD      b,$00 
INCHAR_:    
            ; no received char
            LD      a,b 
            LD      b,c 
            RET      


ACIA6551_STATUS:             
; led show FF
            LD      a,$FF 
            OUT     ($00),a 

; show cmd reg
            IN      a,(ACIA_CMD) 
            OUT     ($00),a 

; show ctl reg
            IN      a,(ACIA_CTL) 
            OUT     ($00),a 

; show stat reg
            IN      a,(ACIA_STAT) 
            OUT     ($00),a 
      
            JP      loop 

Alguns recursos consultados para desenvolver o port do acia 6551 serial IO para o z80.

UM6551A

https://www.grappendorf.net/projects/6502-home-computer/acia-serial-interface-hello-world.html

ACIA 6551

https://www.atarimagazines.com/compute/issue10/075_1_EXPERIMENTING_WITH_THE_6551_ACIA.php

Homebrew 6502 : 6551 UART issues

https://github.com/ancientcomputing/rc2014/tree/master/source/6502/monitor

https://github.com/transitorykris/krisos/tree/master/io