MSX


Que tal realizar algumas experiências com a porta paralela do seu MSX? O que eu proponho nesse artigo é justamente isso. Você só vai precisar de um cabo e uma plaquinha montada com poucos componentes (LEDs e resistores).


Construíndo um cabo para a porta paralela do MSX

Acredito que quem conhece o MSX sabe que aqui no Brasil o Hotbit da Sharp seguiu o padrão estabelecido lá fora, mas o Expert da Gradiente não (estou falando da parte física da porta paralela ok). De qualquer maneira, prevendo que alguns podem não conhecer, coloquei algumas informações importantes logo abaixo:

Porta presente no Hotbit
Conector Centronics fêmea 14 vias


Pin Name Type Description
1 PSTB O Strobe
2 PDB0 O Data 0
3 PDB1 O Data 1
4 PDB2 O Data 2
5 PDB3 O Data 3
6 PDB4 O Data 4
7 PDB5 O Data 5
8 PFB6 O Data 6
9 PDB7 O Data 7
10 NC
Reserved
11 BUSY I Printer is busy
12 NC
Reserved
13 NC
Reserved
14 GND
Signal Ground

Porta presente nos Expert's
Conector IDC macho 26 vias


Pin Name Type Description
1 PSTB O Strobe
2 GND
Signal Ground
3 PDB0 O Data 0
4 GND
Signal Ground
5 PDB1 O Data 1
6 GND
Signal Ground
7 PDB2 O Data 2
8 GND
Signal Ground
9 PDB3 O Data 3
10 GND
Signal Ground
11 PDB4 O Data 4
12 GND
Signal Ground
13 PDB5 O Data 5
14 GND
Signal Ground
15 PDB6 O Data 6
16 GND
Signal Ground
17 PDB7 O Data 7
18 GND
Signal Ground
19 NC

20 GND
Signal Ground
21 BUSY I Printer is busy
22 GND
Signal Ground
23 NC

24 GND
Signal Ground
25 NC

26 NC



Note que os conectores na saída de cada máquina é diferente, e sendo assim você precisará de um cabo especifico para cada uma delas. E hoje eles são raros e bem caros. Por isso optei por montar o meu. Precisei apenas de um pedaço de cabo flat com 15 vias, um conector Centronics 14 vias macho e outro Centronic 36 vias macho.

Se o seu MSX é um Expert Gradiente você vai precisar de um cabo flat com um número maior de vias. O ideal é que ele tenha o mesmo número de vias do conector IDC presente na traseira do seu Expert.

Ai é só montar o cabo respeitando a "tabela" com a pinagem da porta LPT do seu MSX (acima) e a tabela mais abaixo:


Pinagem na para o conector Centronics 36 vias macho
Pin No (36 pin) Signal name Direction Register - bit
1 Strobe In/Out Control-0
2 Data0 Out Data-0
3 Data1 Out Data-1
4 Data2 Out Data-2
5 Data3 Out Data-3
6 Data4 Out Data-4
7 Data5 Out Data-5
8 Data6 Out Data-6
9 Data7 Out Data-7
10 Ack In Status-6
11 Busy In Status-7
12 Paper-Out In Status-5
13 Select In Status-4
14 Linefeed In/Out Control-1
32 Error In Status-3
31 Reset In/Out Control-2
36 Select-Printer In/Out Control-3
19-30,33,17,16 Ground - -

As minhas máquinas atuais são um Hotbit Sharp Branco (MSX1) e também um Panasonic A1-WSX (MSX2+). E para ambos os casos o conector é o mesmo. Abaixo uma imagem do meu cabo junto com uma das revistas Clube MSX! Revista fantática! Clique aqui para saber mais a respeito!


Obs.: O conector Centronics 14 vias macho é bastante díficil de ser encontrado. Eu comprei o mesmo via eBay. Tenha cuidado para não confundir esse conector com o "mini Centronics" utilizado no padrão SCSI(esse último não serve!!!)

Preparando uma pequena placa de testes

A placa que você pode usar nessa experiência é bem fácil de se montar e eu sequer desenhei um circuito para a mesma no Eagle CAD. Simplesmente desenhei a mesma em meu caderno de anotações (sim eu uso isso, afinal sou velho!!! rsrsrsr) e em seguida a montei. Veja a imagem abaixo e se precisar clique na mesma para ampliar e obter as informações necessárias.



Eu fiz a minha montagem usando uma placa padrão. Os resistores são de 390R e os LEDs redondos de 5mm difusos. Não use aqui LEDs de alto-brilho, LEDs azuis ou outros. Como não existe um "buffer" a corrente sobre cada LED aceso é retirada diretamente da porta LPT do MSX. Os "números" presentes no lado esquerdo da imagem são do conector Centronics 36 vias fêmea que foi montado na placa.

Claro que você pode, se quiser, montar um cabo que vai da saída do seu MSX direto para a placa (para quem possui um Expert Gradiente essa parece ser a solução mais barata e simples). Tudo é possível. Apenas tenha cuidado para não ligar nada invertido, evitando queimar seu lindo e raro MSX (é em 2020 eles agora são exatamente isso, raros!!!)


Antes de seguir em frente, que tal um pouco de teoria?!?!

A prática sem a teoria fica sem base! Então vamos entender um pouco sobre a lógica envolvida na porta LPT do MSX.

A primeira coisa a "aprender" é que tudo no MSX é endereçado, assim como em qualquer outro computador. Sem um endereço, você não se comunica!!!

A porta paralela do MSX está nos endereços de I/O 90H e 91H. Em 90H temos no bit 1 a leitura do Busy ou Printer Read e no bit 0 temos a escrita do Strobe. Veja abaixo:

Endereço de I/O 90H
(bits)
7
6
5
4
3
2
1
0
0
0
0
0
0
0
R
W






BUSY
STROBE

Já no endereço de I/O 91H temos os dados que podem ser acessados individualmente. Veja abaixo:

Endereço de I/O 91H
(bits)
7
6
5
4
3
2
1
0
D7
D6
D5
D4
D3
D2
D1
D0

Assim, usando uma simples lógica podemos controlar através de um programa escrito em BASIC, por exemplo, os bits da porta LPT do MSX.


Um programa de exemplo - controle das "saídas"

Abaixo mostro um pequeno programa que fiz em BASIC e que usei em meus primeiros testes. Esse programa testa apenas as "saídas" ok.

5 REM ********************************
10 CLS:PRINT "PROGRAMA DE TESTE PARA LPT"
20 PRINT "MARCIO JOSE SOARES"
30 PRINT "14/06/2019"
35 REM *******************************
40 PRINT "ENVIANDO DADOS:"
50 I=&H1:J=&H2:OUT &H91,0: OUT &H90,0
55 M=0
60 GOSUB 170
70 GOSUB 220
80 I=I*J
90 IF I<=&H80 THEN GOTO 60
100 I=I/2:REM APENAS PARA EVITAR 2 128
110 I=I/J
120 GOSUB 170
130 GOSUB 220
140 IF I=1 THEN GOTO 270 ELSE 110
150 REM ******************************
160 REM SUBROTINA DE TEMPORIZACAO
170 FOR K=0 TO 10:FOR L=0 TO 30
180 NEXT L: NEXT K
190 RETURN
200 REM ******************************
210 REM SUBROTINA PARA ENVIO DE DADOS
220 PRINT HEX$(I);"H"
230 M=M XOR 1:OUT &H90,M:OUT &H91,I
240 RETURN
250 REM ******************************
260 REM FIM DO PROGRAMA
270 PRINT "FIM"
280 GOSUB 170:OUT &H90,0:OUT &H91,0


Um outro exemplo - controle da "entrada"

Abaixo segue um outro programa que usei para testar o pino Busy (entrada da LPT do MSX).

10 '**********************************
20 'TESTE ENTRADA BUSY DA LPT
30 'BY MARCIO JOSE SOARES - ARNE
40 '20/11/2019
50 '**********************************
55 KEY OFF: CLS
60 A=INP(&H90)
70 A$="00000000"+BIN$(A AND &B00000010)
80 PRINT RIGHT$(A$,8)
90 GOTO 60


Um exemplo em Assembly

Abaixo um pequeno programa em Assembly que permite testar também as saídas, usando a mesma plaquinha descrita neste artigo:

;-------------------------------------------------------------------------------
; Project: lpt_t1.zdsp
; Main File: lpt_t1.asm
; Date: 12/07/2019 16:09:46
;
; Created with zDevStudio - Z80 Development Studio.
; Eng. Marcio Jose Soares
; Faz um vai e vem via LPT usando linguagem ASM - compilador PASMO v0.53
;-------------------------------------------------------------------------------
                org     0C100H          ;endereco inicial para o programa
;-------------------------------------------------------------------------------
; Declara enderecos das rotinas do MSX
CHPUT:          equ     00A2H           ;rotina que permite escrever na tela
LPTOUT:         equ     00A5H           ;rotina que permite enviar um char para LPT
LPTDT:          equ     0091H           ;endereco para out na linha de dados para LPT
LPTST:          equ     0090H           ;endereco do strob na linha de dados para LPT
STROBE:         equ     0001H           ;bit para ativar o STROB - bit0

;-------------------------------------------------------------------------------
; Declara constantes
CR:             equ     0DH             ;ENTER
LF:             equ     0AH             ;Line Feed
valinit:        equ     01H             ;valor inicial a ser inserido na LPT
valend:         equ     80H             ;valor de retorno
asciizero       equ     30H             ;valor ASCII para zero
ascii7          equ     37H             ;valor ASCII para 7

;-------------------------------------------------------------------------------
; Declara espaco para vars
valor           DB      0                ;vars
myout           DB      0
myxor           DB      0

;-------------------------------------------------------------------------------
; Subrotina principal
                ld      hl,myxor        ;carrega endereço em hl
                ld      a, 00H
                ld      (hl),a          ;guarda zero em myxor

                ld      hl,msgini       ;carrega mensagem /inicial
                call    wrmsg           ;escreve mensagem inicial
                ld      hl,msgCRLF      ;carrega CR/LF
                call    wrmsg           ;escreve

                ld      hl,valor        ;carrega HL com endereco da pos valor
                ld      a, asciizero    ;carrega valor em a
                ld      (hl),a          ;carrega posicao HL com a

                ld      hl,myout        ;carrega HL com endereco myout
                ld      a, valinit      ;carrega valor
                ld      (hl),a          ;carrega posicao de memoria com a

                ld      hl,msgsend      ;carrega msg enviando
                call    wrmsg           ;escreve
                call    giraEsq         ;gira valores a esquerda e envia para LPT

                ld      hl,valor        ;carrega HL com endereco da pos valor
                ld      a, ascii7       ;carrega valor em a
                ld      (hl),a          ;carrega posicao HL com a

                ld      hl,myout        ;carrega HL com endereco myout
                ld      a, valend       ;carrega valor
                ld      (hl),a          ;carrega posicao de memoria com a

                ld      hl,msgCRLF      ;carrega CR/LF
                call    wrmsg           ;escreve

                ld      hl,msgsend      ;carrega msg enviando
                call    wrmsg           ;escreve
                call    giraDir         ;gira valores a direita e envia para LPT

                ret                     ;retorna para o BASIC

;-------------------------------------------------------------------------------
; Subrotina Gira valores a esquerda e envia para LPT
giraEsq:        call    sndVDLPT        ;envia dados para vídeo e LPT
                ld      hl,valor        ;carrega endereco da var
                ld      a,(hl)          ;pega conteudo
                inc     a               ;incrementa
                ld      (hl),a          ;guarda

                ld      hl,myout        ;carrega endereco da var
                ld      a,(hl)          ;pega conteudo
                rla                     ;gira acumulador a esquerda
                ld      (hl),a          ;guarda
                cp      00H             ;compara com zero
                jr nz,  giraEsq         ;desvia se resultado nao for zero
                ret                     ;retorna para subrotina inicial

;-------------------------------------------------------------------------------
; Subrotina Gira valores a direita e envia para LPT
giraDir:        call    sndVDLPT        ;envia dados para vídeo e LPT
                ld      hl,valor        ;carrega endereco da var
                ld      a,(hl)          ;pega conteudo
                dec     a               ;incrementa
                ld      (hl),a          ;guarda

                ld      hl,myout        ;carrega endereco da var
                ld      a,(hl)          ;pega conteudo
                rra                     ;gira acumulador a direita
                ld      (hl),a          ;guarda
                cp      00H             ;compara com zero
                jr nz,  giraDir         ;desvia se resultado nao for zero
                ret                     ;retorna para subrotina inicial

;-------------------------------------------------------------------------------
; Subrotina para enviar dados para tela e impressora
sndVDLPT:       ld      hl,valor        ;carrega endereco da var em hl
                ld      a,(hl)          ;pega o conteudo
                call    CHPUT           ;envia char

                ld      hl,myout        ;carrega endereco da var
                ld      a,(hl)          ;pega o conteudo
                out     (LPTDT),a       ;envia dados para LPT via OUT direto

                ld      hl,myxor        ;carrega endereço
                ld      a,(hl)          ;pega o conteúdo de myxor
                xor     STROBE          ;faz xor com valor guardado
                out     (LPTST),a       ;envia dado para pino de STROBE

                ld      hl,myxor        ;guarda resultado para próximo xor
                ld      (hl),a          ;valor agora está salvo

                call    _500ms          ;aguarda
                ret

;-------------------------------------------------------------------------------
; Subrotina para aguardar aproximadamente 50ms
;
; T = 1/F => T = 1/3,57MHz => T = 0,280us
; DEC consome 4 ciclos
; JRNZ consome 12 ciclos
; DEC + JRNZ consomente juntos 16 ciclos
;
; 175 x 16 x 0,280us = 784us (DEC L + JR NZ loop1_1)
; 50 x 16 x 0,280us = 224us (DEC H + JR NZ loop1)
;
; (784us + 224us) x 50 = 50.4ms
;
_50ms:          ld      h,032H          ;carrega H com 50
loop1:          ld      l,0AFH          ;carrega L com 175
loop1_1:        dec     l               ;decrementa L
                jr nz,  loop1_1         ;continua ate ser zero
                dec     h               ;decrementa h
                jr nz,  loop1           ;continua ate H ser zero
                ret                     ;retorna para subrotina de chamada

;-------------------------------------------------------------------------------
; Subrotina para aguardar aproximadamente 500ms
;
; T = 1/F => T = 1/3,57MHz => T = 0,280us
; DEC consome 4 ciclos
; JRNZ consome 12 ciclos
; DEC + JRNZ consomente juntos 16 ciclos
;
; 165 x 16 x 0,280us = 739,20us (DEC L + JR NZ loop2_3)
; 50 x 16 x 0,280us = 224us (DEC H + JR NZ loop_2_2)
; 10 x 16 x 0,280us = 44,8us (DEC E + JR NZ loop2)
;
; (739,2us + 224us + 44,8us) x 500 ~= 504ms
;
_500ms:         ld      e,0AH           ;carregqa e com 10
loop2:          ld      h,032H          ;carrega h com 50
loop2_2:        ld      l,0A5H          ;carrega l com 165
loop2_3:        dec     l               ;decrementa l
                jr nz,  loop2_3         ;continua ate ser zero
                dec     h               ;decrementa h
                jr nz,  loop2_2         ;recarrega l e faz até h ser zero
                dec     e               ;decrementa e
                jr nz,  loop2
                ret                     ;retorna para subrotina de chamada

;-------------------------------------------------------------------------------
; Subrotina para escrever na tela
wrmsg:          ld      a,(hl)          ;carrega no acumulador o conteudo
                and     a               ;faz um AND
                ret     z               ;retorna se flag z estiver setado, senao pula
                call    CHPUT           ;chama rotina para escrever char
                inc     hl              ;incrementa HL (ponteiro)
                jr      wrmsg           ;continua ate o final da string

;-------------------------------------------------------------------------------
; Mensagens a serem escritas na tela
msgini:         db      'TESTE CONTROLE PORTA PARALELA EM ASM!'    ;texto para primeira linha
                db      CR, LF                                     ;muda linha
                db      'by ARNE ;) - compilador PASMO v0.53'      ;texto para segunda linha
                db      0               ;fim da string!

msgsend:        db      'ENVIANDO -> '
                db      0

msgCRLF:        db      CR
                db      LF
                db      0

;-------------------------------------------------------------------------------
; Fim do programa
                end


Conclusão

Muitas são as possibilidades para o uso da porta paralela do MSX com a adição de circuitos relativamente simples. É possível, por exemplo, controlar diversos tipos de cargas desde que tomadas as devidas providências para que os pinos sejam "protegidos" e recebam "drivers" de corrente adequados. Espero, de alguma forma, ter contribuído com o seu aprendizado sobre o MSX! Até a proxima!!!




Copyright deste conteúdo reservado para Márcio José Soares e protegido pela Lei de Direitos Autorais LEI N° 9.610, de 19 de Fevereiro de 1998. É estritamente proibida a reprodução total ou parcial do conteúdo desta página em outros pontos da internet, livros ou outros tipos de publicações comerciais ou não, sem a prévia autorização por escrito do autor.