;******************************************************************************
; Prog Monitor_COSMAC.asm - programa monitor para placa COSMAC by Arne
;
;
; Desenvolvido por: Eng. Márcio José Soares
; versão 1.0: 09/05/2026
;
; Compilador: a18
; Plataforma: placa CPU COSMAC + placa extensora COSMAC by Arne (home built)
;
;******************************************************************************

;******************************************************************************

;******************************************************************************
; Define CPU
;
            CPU     1802

;******************************************************************************
; Define registradores
;
R0		    EQU	     0
R1		    EQU	     1
R2		    EQU	     2
R3		    EQU	     3
R4		    EQU	     4
R5		    EQU	     5
R6		    EQU	     6
R7		    EQU	     7
R8		    EQU	     8
R9		    EQU	     9
R10		    EQU	    10
R11		    EQU	    11
R12		    EQU	    12
R13		    EQU	    13
R14		    EQU	    14
R15         EQU	    15

;******************************************************************************
; Define endereços das PORTAS de I/O
;
SLED        EQU     7000H
DISPSEG     EQU     7005H
DISPKS      EQU     7006H
TECO        EQU     7004H
TECI        EQU     7004H

;******************************************************************************
; Define posições na RAM
;
TAMDATA     EQU     31H             ; RAM para dados internos 49 bytes máximos!
TAMBUFFER   EQU     80H             ; buffer de 128 bytes
TAMRAM      EQU     7FFFH           ; 07FFH - 6116, 1FFFH - 6264, 7FFFH - 62256
RAMTOP      EQU     0FFFFH          ; RAM TOP máximo - 64K - necessário manter o Fxxx para garantir
                                    ; o acesso a RAM 1xxx xxxx xxxx xxxx
RAMPRG      EQU     8000H           ; endereço inicial do programa do usuário
POSDATA     EQU     ((RAMPRG+TAMRAM) - (TAMDATA+TAMBUFFER+1));

;******************************************************************************
; Flags
;
HAVETEC     EQU     01H
ALTADDR     EQU     02H
ALTDATA     EQU     04H
DSPBIT0     EQU     08H
DSPBIT1     EQU     10H
DSPBIT2     EQU     20H
MYSHIFT     EQU     40H

;******************************************************************************
; Endereços na ROM
;
STACK_H     EQU     80H            ; endereço
STACK_L     EQU     64H
DISPLAY_H   EQU     00H
DISPLAY_L   EQU     2FH

;******************************************************************************
; Endereços na RAM
;
mydisp1      EQU    POSDATA         ; displays
mydisp2      EQU    POSDATA+1
mydisp3      EQU    POSDATA+2
mydisp4      EQU    POSDATA+3
mydisp5      EQU    POSDATA+4
mydisp6      EQU    POSDATA+5

myCatodos    EQU    POSDATA+6       ; controle dos catodos

myTecOut    EQU     POSDATA+7       ; valor a ser inserido nas colunas do teclado
myNrCols    EQU     POSDATA+8       ; numero da coluna utilizada
aux         EQU     POSDATA+9
myTecla     EQU     POSDATA+10      ; se houve uma tecla a mesma será colocada aqui
myFlags     EQU     POSDATA+11      ; meus flags
                                    ; 0 0 0 0  0 0 0 0
                                    ; bit 0 - Informa que tem tecla
                                    ; bit 1 - Informa que pediu para alterar Address
                                    ; bit 2 - Informa que pediu para alterar Dado
                                    ; bit 3 - Informa pos disps - 1 à 6
                                    ; bit 4 - Informa pos disps - 1 à 6
                                    ; bit 5 - Informa pos disps - 1 à 6
                                    ; bit 6 - Informa seleção Shift
                                    ; bit 7 - vago

myDispPos   EQU     POSDATA+12      ; guarda a posição do display para próxima tecla
myAddrMSB   EQU     POSDATA+13      ; guarda MSB do endereço atual
myAddrLSB   EQU     POSDATA+14      ; guarda LSB do endereço atual
myData      EQU     POSDATA+15      ; guarda o dado

aux1        EQU     POSDATA+16
aux2        EQU     POSDATA+17
aux3        EQU     POSDATA+18
aux4        EQU     POSDATA+19

;******************************************************************************
; Endereço onde tudo começa!!!
;
            ORG     #0000
            BR      STARTDISP

;******************************************************************************
; sub-rotina para iniciar displays
;
STARTDISP:  LOAD    R11,mydisp1      ; em R11, endereço da RAM para display 1
            SEX     R11
            LDI     08H             ; carrega D com 8
            STR     R11             ; guarda

            LOAD    R11,mydisp2     ; em R11, endereço da RAM para display 2
            SEX     R11
            LDI     00H             ; carrega D com 0
            STR     R11             ; guarda

            LOAD    R11,mydisp3     ; em R11, endereço da RAM para display 3
            SEX     R11
            LDI     00H             ; carrega D com 0
            STR     R11             ; guarda

            LOAD    R11,mydisp4     ; em R11, endereço da RAM para display 4
            SEX     R11
            LDI     00H             ; carrega D com 0
            STR     R11             ; guarda

            LDI     00H             ; em D 00H
            PHI     R4              ; carrega no MSB de R4 conteúdo de D
            LDI     01H
            PLO     R4              ; no LSB de R4 01H - disp1 ligado

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            SEX     R7
            GLO     R4              ; recupera LSB em D
            STR     R7              ; envia p/ catodos dos segmentos dos displays

            LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6
            GHI     R4              ; recupera MSB de R4 em D
            STR     R6              ; envia p/ segmentos dos displays

            LOAD    R5,SLED         ; R5 aponta p/ endereço 7000H
            SEX     R5
            GHI     R4              ; recupera LSB em D - LEDs desligados
            STR     R5              ; envia p/ LEDs

;******************************************************************************
; sub-rotina para iniciar teclado
;
STARTTEC:   LOAD    R11,myTecOut    ; em R11 o endereço da RAM para saída do teclado
            SEX     R11
            LDI     20H             ; b0010 0000 -> b1101 1111
            STR     R11             ; guarda

            LOAD    R11,myNrCols    ; em R11 o endereço da RAM para nr da coluna no teclado
            SEX     R11
            LDI     01H             ; carrega D com 1 - começa varredura na coluna 6, conta ao contrário
            STR     R11             ; guarda

;******************************************************************************
; sub-rotina para limpar variáveis
;
LIMPAVARS:  LOAD    R11,myTecla     ;
            SEX     R11
            LDI     00H             ; vars começam sempre com zero
            STR     R11

            LOAD    R11,myFlags
            SEX     R11
            LDI     00H             ; vars começam sempre com zero
            STR     R11

            LOAD    R11,myDispPos
            SEX     R11
            LDI     00H             ; vars começam sempre com zero
            STR     R11

            LOAD    R11,myAddrMSB    ; em R11 o endereço da RAM para MSB do ADDR
            SEX     R11
            LDI     80H             ; carrega D
            STR     R11             ; guarda

            SEX     R11             ; x=11
            LDN     R11             ; lê o que estiver lá e coloca en D
            PHI     R12

            LOAD    R11,myAddrLSB    ; em R11 o endereço da RAM para LSB do ADDR
            SEX     R11
            LDI     00H             ; carrega D
            STR     R11             ; guarda

            SEX     R11             ; x=11
            LDN     R11             ; lê o que estiver lá e coloca en D
            PLO     R12             ; endereço completo em R12

            SEX     R12             ; x=12
            LDN     R12             ; coleta dado e coloca em D
            ANI     0F0H            ; limpa LSB
            SHR
            SHR
            SHR
            SHR
            PLO     R9              ; salva em R9

            LOAD    R11,mydisp5     ; pega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera valor
            STR     R11             ; salva

            SEX     R12             ; x=12
            LDN     R12             ; coleta dado e coloca em D
            ANI     0FH             ; limpa MSB
            PLO     R9              ; salva em R9
            LOAD    R11,mydisp6     ; pega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera valor
            STR     R11             ; salva

            LOAD    R11,aux1        ; apenas para testes - remover p/ final!
            SEX     R11
            LDI     0A1H            ;
            STR     R11

            LOAD    R11,aux2        ;
            SEX     R11
            LDI     0B2H            ;
            STR     R11

            LOAD    R11,aux3        ;
            SEX     R11
            LDI     0C3H            ;
            STR     R11

            LOAD    R11,aux4        ;
            SEX     R11
            LDI     0D4H            ;
            STR     R11

;******************************************************************************
; sub-rotina principal
;
;******************************************************************************
; sub-rotina principal
;
MAIN:
CALLTEC:    LOAD    R10,TECLADO     ; aponta para subrotina teclado
            SEX     R10             ; x = 10
            SEP     R10             ; desvia

CALLTTEC:   LOAD    R11,myFlags     ; lê end de memória - var
            SEX     R11             ; x=11
            LDN     R11             ; coloca em D a var

            ANI     01H             ; testa primeiro bit
            LBZ     CALLDISP        ; sem tecla para tratar, desvia

            LOAD    R10,TRATATEC    ; aponta para subrotina de tratamento de tecla
            SEX     R10             ; x=10
            SEP     R10             ; desvia

CALLDISP:   LOAD    R10,DISPLAY     ; aponta para subrotina display
            SEX     R10             ; x = 10
            SEP     R10             ; desvia

CALLRET:    LBR     MAIN            ; volta - laço eterno!
            IDL                     ; break se chegar aqui

;******************************************************************************
; sub-rotina TECLADO - faz o tratamento do teclado
;
TECLADO:    ;*******************************************************************
            ; Lê valor para as colunas
            ;
            LOAD    R11,myTecOut    ; pega end da var
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D
            XRI     3FH             ; inverte os bits
            PLO     R7              ; guarda na parte LSB de R9

            ;*******************************************************************
            ; coloca valor nas colunas
            ;
            LOAD    R4,TECO         ; aponta para endereço 7004H - saída teclado
            GLO     R7              ; recupera valor lido na memória
            SEX     R4              ; x=4
            STR     R4              ; envia para saída byte em D

            NOP
            NOP
            NOP
            NOP

             ;*******************************************************************
            ; lê as linhas
            ;
            LOAD    R5,TECI         ; prepara para ler endereço 7004H - entrada teclado
            SEX     R5              ; x=5
            LDN     R5              ; pega dado da entrada 7004H e coloca em D
            ANI     0FH             ; limpa bits MSB
            PHI     R7

            ;*******************************************************************
            ; compara com 0FH (Sub D Immediate) - se igual desvia - sem tecla
            ; se diferente trata
            ;
            GHI     R7              ; recupera byte lido da entrada do teclado
            SDI     0FH             ; D = M(R7.1) - D -> compara R7 Hi com 0FH
            LBZ     TECCONT         ; se igual desvia

            LOAD    R11,myNrCols    ; pega nr atual da coluna
            SEX     R11
            LDN     R11             ; nr agora em D
            SHL                     ; faz shift a esquerda para ficar no MSB
            SHL
            SHL
            SHL
            PLO     R7              ; guarda em R7.0 (Low)

            GHI     R7              ; recupera High em D
            LOAD    R3,aux          ; aponta para aux
            SEX     R3              ; x=3
            GLO     R7              ; guarda o LSB de R7 em aux
            STR     R3              ; guarda
            GHI     R7              ; recupera a parte alta
            OR                      ; M(R3) or D -> resultado em D
            PHI     R7              ; guarda D no MSB de R7

            ;*******************************************************************
            ; mostra valor nos LEDSs - MSB nr da coluna - LSB tecla
            ;
            LOAD    R6,SLED         ; R6 aponta p/ endereço 7000H
            GHI     R7
            XRI     0FH             ; inverte os bits no LSB... zero vira 1 e vice-versa!
            PHI     R7              ; salvo novamente
            SEX     R6              ; x=6
            STR     R6              ; envia p/ os LEDs

            ;*******************************************************************
            ; Guarda dados na var para tratamento
            ;
            LOAD    R6,myTecla      ; R6 aponta p/ var
            SEX     R6              ; x=6
            GHI     R7
            STR     R6              ; guarda na var o valor

            LOAD    R6,myFlags      ; R6 aponta p/ var
            SEX     R6              ; x=6
            LDN     R6              ; lê dado para D

            ORI     HAVETEC         ; marca flag
            SEX     R6              ; x=6
            STR     R6              ; salva com novo valor

            ;*******************************************************************
            ; Retorna valores ao inicio quando tem tecla
            ;
            ;LOAD    R11,myTecOut    ; em R11 o endereço da RAM para saída do teclado
            ;SEX     R11
            ;LDI     20H             ; b0010 0000 -> b1101 1111
            ;STR     R11             ; guarda

            ;LOAD    R11,myNrCols    ; em R11 o endereço da RAM para nr da coluna no teclado
            ;SEX     R11
            ;LDI     01H             ; carrega D com 1 - começa varredura na coluna 6, conta ao contrário
            ;STR     R11             ; guarda

            ;*******************************************************************
            ; pequeno bounce se encontrou - 75ms
            ;
TECTIME:    LDI     10H             ; carga imediata em D
            PHI     R9              ; coloca D no MSB de R9
            LDI     88H             ; carga imediata em D
            PLO     R9              ; coloca D no LSB de R9

LOOPTIME:   DEC     R9              ; 1 ciclo
            GHI     R9              ; 2 ciclos
            BNZ     LOOPTIME        ; 2 ciclos
            GLO     R9              ; 2 ciclos
            BNZ     LOOPTIME        ; 2 ciclos -> total 9 ciclos

            LBR     ALTQ

            ;*******************************************************************
            ; avança pós coluna se não achou nada, avança nr das colunas também
            ; linhas sem comentários devem ser retiradas... colocadas aqui só para dar
            ; tempo de ver a var myTecOut nos LEDs
TECCONT:    LOAD    R11,myTecOut    ; pega novamente o valor
            SEX     R11             ; x = 11
            LDN     R11             ; pega o valor e coloca em D
            PHI     R9
            SHR                     ; faz shift a direita
            STR     R11             ; guarda valor

            LOAD    R11,myNrCols    ; pega o nr atual da coluna
            SEX     R11             ; x=11
            LDN     R11             ; pega o valor e coloca em D
            ADI     01H             ; adiciona 1
            PLO     R7              ; guarda em R7 LSB

            SDI     07H             ; passou do limite?
            LBNZ    TECSAV          ; não?! apenas desvia, se sim recarrega tudo

            LOAD    R11,myTecOut    ; em R11 o endereço da RAM para saída do teclado
            SEX     R11
            LDI     20H             ; b0010 0000 -> b1101 1111
            STR     R11             ; guarda

            LDI     01H             ; recarrega 01 para myNrCols
            PLO     R7              ; coloca em R7

TECSAV:     LOAD    R11,myNrCols    ; pega o nr atual da coluna
            SEX     R11             ; x=11
            GLO     R7              ; recupera R7
            STR     R11             ; guarda na VAR

            ;*******************************************************************
            ; pequeno bounce - 30ms
            ;
TECTIME2:   LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     40H             ; carga imediata em D
            PLO     R9              ; coloca D no LSB de R9

LOOPTIME2:  DEC     R9              ; 1 ciclo
            GHI     R9              ; 2 ciclos
            BNZ     LOOPTIME2       ; 2 ciclos
            GLO     R9              ; 2 ciclos
            BNZ     LOOPTIME2       ; 2 ciclos -> total 9 ciclos

            ;*******************************************************************
            ; altera estado de Q
            ;
ALTQ:       LSQ                     ; se Q = 1 pula as duas próximas instruções
            SEQ                     ; liga Q
            SKP                     ; pula a próxima instrução
            REQ                     ; desliga Q

            ;*******************************************************************
            ; Fim da brincadeira
TECEND:     LOAD    R3,CALLTTEC     ; retorna para main - testa tecla
            SEX     R3
            SEP     R3

            IDL                     ; break se chegar aqui

;******************************************************************************
; sub-rotina DISPLAY - mostra valores nos displays
;
DISPLAY:    LDI     00H             ; em D 00H
            PHI     R4              ; carrega no MSB de R4 conteúdo de D
            LDI     01H
            PLO     R4              ; no LSB de R4 01H - disp1 ligado

            LOAD    R11,mydisp1     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

DISP1:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            SEX     R7              ; x=7
            GLO     R4              ; recupera byte inserido no LSB
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP1:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            BNZ     LOOP1          ; desvia se não for zero

            LOAD    R11,mydisp2     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

DIPS2:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            LDI     02H             ; manda para segundo display
            SEX     R7              ; x=7
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP2:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            BNZ     LOOP2           ; desvia se não for zero

            LOAD    R11,mydisp3     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

DSIP3:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            LDI     04H             ; manda para terceiro display
            SEX     R7              ; x=7
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP3:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            LBNZ    LOOP3           ; desvia se não for zero

            LOAD    R11,mydisp4     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

            LOAD    R6,myFlags      ; lê os flags
            SEX     R6              ; x=6
            LDN     R6              ; lê conteúdo e coloca em D

            ANI     ALTADDR         ; verifica se setado
            BZ      DISP4           ; não?? desvia

            GHI     R4              ; restaura r4 em D
            ORI     80H             ; liga bit do ponto
            PHI     R4              ; salva em R4

DISP4:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            LDI     08H             ; manda para quarto display
            SEX     R7              ; x=7
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP4:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            LBNZ     LOOP4           ; desvia se não for zero

            LOAD    R11,mydisp5     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

DISP5:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            LDI     10H             ; manda para quinto display
            SEX     R7              ; x=7
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP5:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            BNZ    LOOP5           ; desvia se não for zero

            LOAD    R11,mydisp6     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; lê conteúdo do endereço em D

            LOAD    R8,_7SEGDATA    ; R8 contem agora o endereço da tabela
            GLO     R8              ; recupera conteúdo
            ADD                     ; soma
            PLO     R8              ; guarda na parte baixa de R8
            SEX     R8              ; indice agora em R8
            LDXA                    ; em D o byte presente na tabela

            PHI     R4              ; coloca D na parte alta de R4

            LOAD    R6,myFlags      ; lê os flags
            SEX     R6              ; x=6
            LDN     R6              ; lê conteúdo e coloca em D

            ANI     ALTDATA         ; verifica se setado
            LBZ     DISP6           ; não?? desvia

            GHI     R4              ; restaura r4 em D
            ORI     80H             ; liga bit do ponto
            PHI     R4              ; salva em R4

DISP6:      LOAD    R6,DISPSEG      ; R6 aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R6              ; x=6
            GHI     R4              ; recupera byte lido em _7SEGDATA
            STR     R6              ; envia p/ os segmentos

            LOAD    R7,DISPKS       ; R7 aponta p/ endereço 7006H - saída catodos dos displays
            LDI     20H             ; manda para sexto display
            SEX     R7              ; x=7
            STR     R7              ; liga disp

            LDI     00H             ; prepara para temporizar!
            PHI     R9
            LDI     96H             ; carga imediata de 100 em D
            PLO     R9              ; coloca D no LSB de R9

LOOP6:      DEC     R9              ; decrementa R9
            GLO     R9              ; colaca em D a parte MSB de R9
            BNZ     LOOP6           ; desvia se não for zero

EXIT_D:     LDI     01H
            PLO     R4

            LOAD    R3,CALLRET
            SEX     R3
            SEP     R3

            IDL                     ; break se chegar aqui

;******************************************************************************
; sub-rotina TRATATEC - subrotina para tratar a tecla capturada
; tecla em myTecla
;
TRATATEC:   SEX     R11             ; R11 apontava para myFlags
            LDN     R11             ; pega R11
            ANI     0FEH            ; limpa flag HAVETEC
            SEX     R11             ; x=11
            STR     R11             ; guarda com bit limpo

            LOAD    R11,myTecla     ; pega end da var
            SEX     R11             ; x=11
            LDN     R11             ; pega tecla

            PLO     R15             ; salva no LSB de R15

            SMI     21H             ; D = D - 21H
            LBNF    TEC_RIGHT       ; DF=0??? então é menor, então teclas de comando a direita

            GLO     R15             ; restaura D
            SMI     59H             ; D = D - 59H
            LBDF    TEC_LEFT        ; DF=1??? então é maior igual, teclas de comando a esquerda

;******************************************************************************
; Teclas 0-9 e A-F
;
EH0:        GLO     R15             ; se chegou aqui é tecla entre 0-9 ou A-F
            SMI     58H             ; é 0?
            LBNZ    EH1             ; não desvia

            LDI     00H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH1:        GLO     R15             ; restaura D
            SMI     48H             ; é 1?
            LBNZ    EH2             ; não desvia

            LDI     01H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH2:        GLO     R15             ; restaura D
            SMI     38H             ; é 2?
            LBNZ    EH3             ; não desvia

            LDI     02H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH3:        GLO     R15             ; restaura D
            SMI     54H             ; é 3?
            LBNZ    EH4             ; não desvia

            LDI     03H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH4:        GLO     R15             ; restaura D
            SMI     44H             ; é 4?
            LBNZ    EH5             ; não desvia

            LDI     04H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH5:        GLO     R15             ; restaura D
            SMI     34H             ; é 5?
            LBNZ    EH6             ; não desvia

            LDI     05H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH6:        GLO     R15             ; restaura D
            SMI     52H             ; é 6?
            LBNZ    EH7             ; não desvia

            LDI     06H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH7:        GLO     R15             ; restaura D
            SMI     42H             ; é 7?
            BNZ     EH8             ; não desvia

            LDI     07H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH8:        GLO     R15             ; restaura D
            SMI     32H             ; é 8?
            BNZ     EH9             ; não desvia

            LDI     08H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EH9:        GLO     R15             ; restaura D
            SMI     51H             ; é 9?
            BNZ     EHA             ; não desvia

            LDI     09H             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHA:        GLO     R15             ; restaura D
            SMI     41H             ; é A?
            BNZ     EHB             ; não desvia

            LDI     0AH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHB:        GLO     R15             ; restaura D
            SMI     31H             ; é b?
            BNZ     EHC             ; não desvia

            LDI     0BH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHC:        GLO     R15             ; restaura D
            SMI     21H             ; é C?
            BNZ     EHD             ; não desvia

            LDI     0CH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHD:        GLO     R15             ; restaura D
            SMI     22H             ; é D?
            BNZ     EHE             ; não desvia

            LDI     0DH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHE:        GLO     R15             ; restaura D
            SMI     24H             ; é E?
            BNZ     EHF             ; não desvia

            LDI     0EH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever


EHF:        GLO     R15             ; restaura D
            SMI     28H             ; é F?
            LBNZ    EXIT_TRT        ; não desvia

            LDI     0FH             ; achou a tecla
            PLO     R15             ; guarda para escrever
            LBR     WRITE_DISP      ; desvia para escrever

;******************************************************************************
; Teclas de comando a esquerda: ADDR, DATA, PC e Shift
;
TEC_LEFT:
EHADDR:     GLO     R15             ; restaura D
            SMI     61H             ; é ADDR?!
            LBNZ    EHDT            ; não? desvia

            LOAD    R11,myFlags     ; pega var flags
            SEX     R11             ; x=11
            LDN     R11             ; em D o valor em mydisp1
            ORI     ALTADDR         ; liga flag de ADDR
            ANI     0BBH            ; desliga flag DATA e SHIFT
            SEX     R11             ; x=11
            STR     R11             ; salva

            LOAD    R11,myDispPos   ; pega end da var
            SEX     R11             ; x=11
            LDI     01H             ; carrega D
            STR     R11             ; salva

            LOAD    R11,mydisp1     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LOAD    R11,mydisp2     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LOAD    R11,mydisp3     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LOAD    R11,mydisp4     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LBR     EXIT_TRT        ; desvia para o fim

EHDT:       GLO     R15             ; restaura D
            SMI     62H             ; é DATA?!
            LBNZ    EHPC            ; desvia

            LOAD    R11,myFlags     ; pega var flags
            SEX     R11             ; x=11
            LDN     R11             ; em D o valor em mydisp1
            ORI     ALTDATA         ; liga flag de DATA
            ANI     0BDH            ; desliga flag ADDR e SHIFT
            SEX     R11             ; x=11
            STR     R11             ; salva

            LOAD    R11,myDispPos   ; pega end da var
            SEX     R11             ; x=11
            LDI     05H             ; carrega D
            STR     R11             ; salva

            LOAD    R11,mydisp5     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LOAD    R11,mydisp6     ; pega end da var
            SEX     R11             ; x=11
            LDI     11H             ; mostra traço
            STR     R11

            LBR     EXIT_TRT        ; desvia para o fim

EHPC:       GLO     R15             ; restaura D
            SMI     64H             ; é PC?!
            LBNZ    EHSH            ; desvia
            LBR     EHFIM           ; desvia para o fim

EHSH:       GLO     R15             ; restaura D
            SMI     68H             ; é SHIFT?!
            LBNZ    EHFIM           ; desvia

            LOAD    R11,myFlags     ; pega var flags
            SEX     R11             ; x=11
            LDN     R11             ; em D o valor em mydisp1
            ORI     MYSHIFT         ; liga flag de shift
            STR     R11             ; salva!

            LOAD    R11,mydisp5     ; pega end da var
            SEX     R11             ; x=11
            LDI     12H             ; mostra traço alto
            STR     R11

            LOAD    R11,mydisp6     ; pega end da var
            SEX     R11             ; x=11
            LDI     12H             ; mostra traço alto
            STR     R11

EHFIM:      LBR     EXIT_TRT        ; desvia para o fim

;******************************************************************************
; Teclas de comandos a direita - UP, DOWN, GO e ENTER (CR)
;
TEC_RIGHT:
EHUP:       GLO     R15             ; restaura
            SMI     11H             ; compara
            LBNZ    EHDOWN          ; desvia

            LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PHI     R12             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PLO     R12             ; agora R12 contem o endereço!

            INC     R12             ; incrementa reg

            LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            GHI     R12             ; recupera R12
            STR     R11             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            GLO     R12             ; recupera R12
            STR     R11             ; salva

            LBR     ATUALADDR       ; desvia para atualizar vars do display


EHDOWN:     GLO     R15             ; restaura
            SMI     12H             ; compara
            LBNZ    EHGO            ; desvia

            LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PHI     R12             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PLO     R12             ; agora R12 contem o endereço!

            DEC     R12             ; incrementa reg

            LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            GHI     R12             ; recupera R12
            STR     R11             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            GLO     R12             ; recupera R12
            STR     R11             ; salva

ATUALADDR:  GHI     R12             ; restaura MSB do ADDR
            ANI     0F0H            ; limpa o LSB BCD
            SHR
            SHR
            SHR
            SHR
            ANI     0FH;            ; limpa
            PLO     R9

            LOAD    R11,mydisp1     ; carrega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera R9
            STR     R11             ; salva

            GHI     R12             ; restaura MSB do ADDR
            ANI     0FH             ; limpa o MSB BCD
            PLO     R9

            LOAD    R11,mydisp2     ; carrega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera R9
            STR     R11             ; salva

            GLO     R12             ; restaura LSB do ADDR
            ANI     0F0H            ; limpa o LSB BCD
            SHR
            SHR
            SHR
            SHR
            ANI     0FH;            ; limpa
            PLO     R9

            LOAD    R11,mydisp3     ; carrega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera R9
            STR     R11             ; salva

            GLO     R12             ; restaura LSB do ADDR
            ANI     0FH             ; limpa o MSB BCD
            PLO     R9

            LOAD    R11,mydisp4     ; carrega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera R9
            STR     R11             ; salva

            LBR     SHOWB           ; desvia para mostrar o byte

EHGO:       GLO     R15             ; restaura
            SMI     14H             ; compara
            LBNZ    EHCR            ; desvia


EXECPRG:    LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PHI     R13             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PLO     R13             ; agora R13 contem o endereço do programa em RAM!

            LOAD    R11,DISPKS      ; aponta p/ endereço 7006H - saída catodos dos displays
            SEX     R11
            LDI     00H
            STR     R11             ; desliga todos os catodos

            LOAD    R11,DISPSEG     ; aponta p/ endereço 7005H - saída para segmentos dos displays
            SEX     R11
            LDI     00H
            STR     R11             ; desliga todos os segmentos

            LOAD    R11,SLED        ; aponta p/ endereço 7000H
            SEX     R11
            LDI     00H
            STR     R11             ; desliga todos os LEDs

            LOAD    R11,TECO        ; aponta para endereço 7004H - saída para colunas do teclado
            SEX     R11
            LDI     00H             ;
            STR     R11             ; todas colunas desligadas

            REQ                     ; desliga Q

            SEX     R13             ; x=13
            SEP     R13             ; desvia para processar o que estiver na RAM

            LBR     EXIT_TRT        ; desvia para o fim - dummy!!!!

EHCR:       GLO     R15             ; restaura
            SMI     18H             ; compara
            LBNZ    EXIT_TRT        ; desvia

            LOAD    R11,myAddrMSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PHI     R12             ; salva

            LOAD    R11,myAddrLSB   ; carrega end da var
            SEX     R11             ; x=11
            LDN     R11             ; em D a var
            PLO     R12             ; agora R12 contem o endereço!

            LOAD    R11,myFlags     ; pega endereço
            SEX     R11             ; x=11
            LDN     R11             ; conteúdo em D
            PHI     R9              ; salva no MSB de R9
            ANI     ALTADDR         ; testa para ver se está ativado endereço
            BNZ     SHOWB           ; desvia se sim
            GHI     R9              ; restaura MSB de R9
            ANI     ALTDATA         ; testa para ver se está ativado DATA
            BZ      SHOWB           ; desvia se não

            LOAD    R11,myData      ; pega end da var
            SEX     R11             ; x=11
            LDN     R11             ; conteúdo em D
            PHI     R9              ; transfere para MSB de R9

            SEX     R12             ; aponta para endereço
            GHI     R9              ; em D MSB de R9
            STR     R12             ; salva

            LOAD    R11,myFlags     ; pega var flags - volta ponteiro para ADDR
            SEX     R11             ; x=11
            LDN     R11             ; em D
            ORI     ALTADDR         ; liga flag de ADDR
            ANI     0BBH            ; desliga flag DATA e Shift
            SEX     R11             ; x=11
            STR     R11             ; salva

SHOWB:      SEX     R12             ; x=12
            LDN     R12             ; lê o que estiver lá e coloca en D
            ANI     0F0H            ; limpa LSB
            SHR                     ; shift a direita - MSB em LSB
            SHR
            SHR
            SHR
            ANI     0FH;            ; limpa o MSB
            PLO     R9              ; salva em R9

            LOAD    R11,mydisp5     ; pega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera valor
            STR     R11             ; salva

            SEX     R12             ; x=12
            LDN     R12             ; lê o que estiver lá e coloca en D
            ANI     0FH             ; limpa MSB
            PLO     R9              ; salva em R9
            LOAD    R11,mydisp6     ; pega end da var
            SEX     R11             ; x=11
            GLO     R9              ; recupera valor
            STR     R11             ; salva

            LBR     EXIT_TRT        ; desvia para o fim


;******************************************************************************
; Escreve nos displays durante uso do teclado
;
WRITE_DISP: LOAD    R11,myDispPos   ; pega end da var
            SEX     R11             ; x=11
            LDN     R11
            PHI     R15             ; salva em R15 - high
            LBZ     EXIT_TRT        ; não pediu entrada nem de ADD nem DT

WRTDISP1:   GHI     R15             ; restaura
            SMI     01H             ; testa se primeiro do endereço
            LBNZ    WRTDISP2        ; não?! pode ser o segundo?!

            LOAD    R12,mydisp1     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 1° digito do ADDR - Xxxx
            ANI     0FH             ; limpa MSB
            SHL                     ; troca LSB pelo MSB
            SHL
            SHL
            SHL
            PLO     R15             ; grava a var

            LOAD    R12,myAddrMSB   ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0FH             ; limpa MSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

            LBR     SV_NXDIG        ; desvia para posicionar o próximo

WRTDISP2:   GHI     R15             ; restaura
            SMI     02H             ; testa se segundo do endereço
            LBNZ    WRTDISP3        ; não?! pode ser o terceiro?!

            LOAD    R12,mydisp2     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 2° digito do ADDR - xXxx
            ANI     0FH             ; limpa MSB
            PLO     R15

            LOAD    R12,myAddrMSB   ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0F0H            ; limpa LSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

            LBR     SV_NXDIG        ; desvia para posicionar o próximo

WRTDISP3:   GHI     R15             ; restaura
            SMI     03H             ; testa se terceiro do endereço
            LBNZ    WRTDISP4        ; não?! pode ser o quarto?!

            LOAD    R12,mydisp3     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 1° digito do ADDR - Xxxx
            ANI     0FH             ; limpa MSB
            SHL                     ; troca LSB pelo MSB
            SHL
            SHL
            SHL
            PLO     R15             ; grava a var

            LOAD    R12,myAddrLSB   ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0FH             ; limpa MSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

            LBR     SV_NXDIG        ; desvia para posicionar o próximo

WRTDISP4:   GHI     R15             ; restaura
            SMI     04H             ; testa se quarto do endereço
            LBNZ    WRTDISP5        ; não?! pode ser o primeiro do dado?!

            LOAD    R12,mydisp4     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 2° digito do ADDR - xXxx
            ANI     0FH             ; limpa MSB
            PLO     R15

            LOAD    R12,myAddrLSB   ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0F0H            ; limpa LSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

            LBR     SV_NXDIG        ; desvia para posicionar o próximo

WRTDISP5:   GHI     R15             ; restaura
            SMI     05H             ; testa se primeiro do dado
            LBNZ    WRTDISP6        ; não?! pode ser o segundo do dado?!

            LOAD    R12,mydisp5     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 1° digito do ADDR - Xxxx
            ANI     0FH             ; limpa MSB
            SHL                     ; troca LSB pelo MSB
            SHL
            SHL
            SHL
            PLO     R15             ; grava a var

            LOAD    R12,myData      ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0FH             ; limpa MSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

            LBR     SV_NXDIG        ; desvia para posicionar o próximo

WRTDISP6:   GHI     R15             ; restaura
            SMI     06H             ; testa se segundo do dado
            LBNZ    EXIT_TRT        ; não?! zuado!

            LOAD    R12,mydisp6     ; pega end da var
            SEX     R12             ; x=12
            GLO     R15             ; recupera valor
            STR     R12             ; carrega

            GLO     R15             ; prepara para gravar 2° digito do ADDR - xXxx
            ANI     0FH             ; limpa MSB
            PLO     R15

            LOAD    R12,myData      ; carrega end da var
            SEX     R12             ; x=12
            LDN     R12             ; carrega
            ANI     0F0H            ; limpa LSB
            STR     R12             ; salva

            GLO     R15             ; recupera
            OR                      ; or de D com endereço 12
            STR     R12             ; salva D na var

SV_NXDIG:   GHI     R15             ; recurera em R15 - High
            ADI     01H             ; soma 1
            PHI     R15             ; guarda

            LOAD    R12,myFlags     ; pega flags
            SEX     R12             ; x=12
            LDN     R12             ; carrega D
            PLO     R9              ; guarda

            GLO     R9              ; restaura
            ANI     ALTADDR         ; faz AND com flag
            BNZ     SV_ADD          ; desvia para tratar ADDR

            GLO     R9              ; restaura
            ANI     ALTDATA         ; AND com flag
            LBNZ    SV_DATA         ; desvia para tratar DADO
            LBR     EXIT_TRT

SV_ADD:     GHI     R15             ; restaura
            SMI     05H             ; chegou ao fim?!
            LBNZ    SV_CONT         ; salva
            LDI     01H             ; restaura valor
            PHI     R15             ; salva
            LBR     SV_CONT

SV_DATA:    GHI     R15             ; restaura
            SMI     07H             ; chegou ao fim?!
            BNZ     SV_CONT         ; salva
            LDI     05H             ; restaura valor
            PHI     R15             ; salva

SV_CONT:    GHI     R15             ; recupera valor da var
            SEX     R11             ; x=11
            STR     R11             ; salva

EXIT_TRT:   LOAD    R3,CALLDISP
            SEX     R3
            SEP     R3

            IDL                     ; break se chegar aqui
;******************************************************************************
; Constantes inseridas na ROM
;
_7SEGDATA:  DB      03FH,06H,5BH,4FH,66H,6DH,7DH,07H
            DB      7FH,67H,77H,7CH,39H,5EH,79H,71H,80H
            DB      40H,01H,00H

;******************************************************************************
; Fim
;
            END


