Miscellaneous > 16 bit DOS Programming

Reading the Status Register of the Parallel Port (solved)

(1/4) > >>

popcalent:
Hello everybody,

I'm trying to code a program to read the status register of the parallel port, but I can't get it to work.

I made an adapter to connect an NES controller to the parallel port using a PIC16F84A microcontroller. The adapter works fine, when I press a button on the NES controller, the right output of the microcontroller goes high. So, I know the adapter is not the problem. Here's a simple schematic of the adapter:

The outputs of the microcontroller go straight into the LPT pins as shown in the picture.

I wrote a quick asm program to read the status of the LPT, but I always read the same status no matter what buttons I press on the NES controller.
This is what I'm using to read the status register (I'm attaching the whole code at the end of this post):
CALL LPT_IN
PUT_CHAR AL, 15
...
LPT_IN  PROC
        PUSH DX
        MOV  DX, 0379H
        IN   AL, DX
        POP  DX
        RET
LPT_IN  ENDP

I'm trying this on real hardware: A 286 with MSDOS 3.31. I can output any byte on the LPT output register (0x378), that's not a problem, but I can't read the status register (0x379).


What am I doing wrong? Thanks!

Edit: I found the mistake. It's in bold printing in the code below.

;#################################################
;#
;# LPTTEST.ASM
;#
;#################################################

;#################################################
;# DEFINITIONS
;#################################################

;#################################################
;# MACROS
;#################################################
PUT_CHAR MACRO C,A  ; C=CHAR, A=COLOR
        PUSH AX
        PUSH BX
        PUSH CX
        MOV AH,09H
        MOV BL,A      ;COLOR
        MOV CX,1      ;NUMBER OF CHARS
        MOV AL,C      ;CHARACTER
        INT 10H
        POP CX
        POP BX
        POP AX
        ENDM
;#################################################
;# DATA
;#################################################
DATASG SEGMENT PARA 'Data'

DATASG ENDS
;#################################################
;# PROGRAM STARTS HERE
;#################################################
CODESG SEGMENT PARA 'Code'
READ_LPT PROC FAR
        ASSUME CS:CODESG, DS:DATASG
        MOV AX, DATASG
        MOV DS, AX

        MOV AL, 10000000B       ;BIT7=1  BECAUSE WE TAKE OUR Vcc FROM HERE
        CALL LPT_OUT

MAIN_LOOP:
        CALL LPT_IN
        PUT_CHAR AL, 15

      ;SOLUTION
        MOV  AH, 0      ;THIS BLOCKS THE PROGRAM BEFORE I CAN CHANGE THE PORT STATUS
        INT  16H           ;IF I CHANGE THE PORT STATUS AND PRESS A KEY OTHER THAN ESC, THE CHANGE
                                 ;WILL BE REFLECTED ON SCREEN IN THE NEXT ITERATION

EXIT_PROGRAM:
        CMP AH, 1
        JE EXIT_P
        JMP MAIN_LOOP
EXIT_P:
        MOV AH, 00H
        MOV AL, 3h
        MOV AH, 4CH      ; GO TO MSDOS
        INT 21H
READ_LPT ENDP

;#################################################
;# SUBROUTINE: LPT_OUT
;#################################################
LPT_OUT PROC
        PUSH DX
        MOV  DX, 0378H
        OUT  DX, AL
        POP  DX
        RET
LPT_OUT ENDP
;#################################################
;# SUBROUTINE: LPT_IN
;#################################################
LPT_IN  PROC
        PUSH DX
        MOV  DX, 0379H
        IN   AL, DX
        POP  DX
        RET
LPT_IN  ENDP
CODESG ENDS
END READ_LPT

mineiro:
I can't try this, so, maybe I can't help you the way I like.
In ms-dos we have 3 ways to get these informations:
1- in and out instructions
2- direct access to memory area
3- interruptions

Sometimes bus is locked and we need wait in a loop until it changes and give to us access.
You can try to use bios interruption 17.

mov ah,2        ;service 2, read status
mov dx,0        ;0 = LPT1
int 17h         ;printer interruption
;check returned value, I suppose ah register.

Link below was writen in portuguese, can be useful if you translate it.
http://arquivo.ufv.br/dea/ambiagro/arquivos/ParallelPort/PortaParalela/

FORTRANS:
Hi,

   I don't see anything obviously wrong.  So, for debug
purposes, try the BIOS Printer Functions.

INT 17      Printer Services

INPUT  AH = 0 = Print Character, AL = character
       AH = 1 = Initialize Printer
       AH = 2 = Get Printer Status
       DX = Printer number (0 = LPT1)

OUTPUT AH = Status

   Write a small program, or just use DEBUG.

Regards,

Steve N.

P.S.
   Beaten by mineiro, hope this helps.
SRN

popcalent:
Thank you for your response, mineiro and FORTRANS.  :thumbsup:

I had used INT17h before, but it didn't work. I think I forgot to move the LPT number to DX. Anyway, I tried now, and it still doesn't work.

The only thing that changes from using IN/OUT to using INT17h is the character that the program prints at the beginning. Before it printed รง (ASCII 0x87 10000111), and now it prints a dot with a concentric hole (ASCII 0x09 00001001). This is very strange. The first code makes sense to me because bit 7 is inverted, and bits 2, 1, and 0 are not physical pins and for whatever reason are high. The second code doesn't make any sense. Nevertheless, when I externally change the status register inputs, the program does nothing.

By the way, I tested the status register pins with a tester, and the logic ones and zeroes that I enter are there, but the program can't read them.

FORTRANS:
Hi,

   Use DEBUG to display the BIOS memory that indicates
the LPTx ports that the BIOS finds on boot up.

40:08H LPT1
40:0AH LPT2
40:0CH LPT3

  You should see 378H (in little endian) in one of these
words.

   Otherwise look at the returned status when you try to
initialize the port.

Regards,

Steve N.

Actually the standard ports are 3BCH, 378H, or 278H.

Navigation

[0] Message Index

[#] Next page

Go to full version