Direct communication with the 8251 chip on the PX-8 computer by Earl Evans and Chris Rhodes The PX-8 lap computer is equipped with an 8251 serial interface chip. BIOS subroutines are available to use the features of this chip; however, at times it may be desirable to communicate directly with the chip through the Z80 I/O ports. Before doing this, there are a few problems that must be recognized and solved. First, we recognize that the BIOS functions are performing a considerable amount of functions transparent to the user. When speaking directly to the 8251, you must perform some of these functions yourself. These include turning on the RS232 port power, initialing the baud rate, and setting the RS232 parameters. Second, the 8251 is normally interrupt driven, and the interrupts are serviced by the BIOS routines. If these interrupts are left enabled, they will maliciously swipe the characters from the I/O port. Disabling the interrupts is a must. Third, we must make the system think that the port is open, so that it will not inadvertently attempt to open it during our conversation with the 8251. This will cause the interrupts to become enabled again. Fourth, the memory map of the PX-8 CP/M maintains mirror images of the values currently in use in the 8251 chip. The BIOS routines update these automatically; however, we must update them ourselves, since we are circumventing the BIOS routines. The following is a portion of the source code for DIOMODEM, a version of the MODEM program. This particular version of MODEM implements direct communication with the 8251 based on the principles we previously discussed. MAPLEWB EQU 0EC03H ; PX-8 CP/M warm boot location CTRL1 EQU 0F0B0H ;\ CTRL2 EQU 0F0B2H ; \ IER EQU 0F0B3H ; | system storage locations RS232MODE EQU 0F6D0H ; / RS232CMND EQU 0F6D1H ;/ RSOPFLG EQU 0F2C8H ;************************************************************** ; ; Handles in/out ports for data and status ;IN$MODCTL1 places the current control status in the A register. IN$MODCTL1: IN A,(0DH) RET ;OUT$MODDATP sends the contents of the A register out the data ;port OUT$MODDATP: OUT (0CH),A RET ;IN$MODDATP places the incoming character into the A register IN$MODDATP: IN A,(0CH) RET ;Calling ANI$MODRCVB and CPI$MODRCVR in sequence will set the Z ;flag if there is an incoming byte from the modem and reset the Z ;flag if not. ANI$MODRCVB: AND 2 ;test this bit for receive ready RET CPI$MODRCVR: CP 2 RET ;Calling ANI$MODSNDB and CPI$MODSNDR in sequence will set the Z ;flag if it is all right to send out a character, and will reset ;the Z flag if not. ANI$MODSNDB: ;bit to test for send ready AND 1 RET CPI$MODSNDR: CP 1 RET ; INITIALIZE THE PX-8 RS232 PORT INITMOD: ; INITIALIZE THE PX-8 RS232 PORT ; let's close the port first CALL MAPLEWB+3CH ; close RS232 port LD A,00H ; LD (RSOPFLG),A ; Store 0 in RSOPFLG (makes the ; system think the RS232 is open) ; Disable any 8251 interrupts LD A,(IER) ; get current interrupt enable state RES 1,A ; clear RX interrupt RES 2,A ; clear CD interrupt OUT (4),A LD (IER),A ; Turn power on with inhibit LD A,(CTRL2) ; get current value - lights, etc. SET 4,A ; inhibit TX OUT (2),A ; send it out CALL ST1ML ; delay, says the BIOS SET 3,A ; power on OUT (2),A ; send it out CALL ST100ML RES 4,A ; enable TX SET 5,A ; enable internal RX OUT (2),A ; send it out LD (CTRL2),A ; save new values ; insure baud rate clock set LD A,(CTRL1) ; get current value baud rate OUT (0),A ; force reset of 8251 LD A,0 OUT (0DH),A LD A,0 OUT (0DH),A LD A,0 OUT (0DH),A LD A,40H ; reset command OUT (0DH),A CALL ST100ML ; delay, says the BIOS ; Set up 8251 LD A,(RS232MODE) ; get current mode value OUT (0DH),A LD A,(RS232CMND) ; get current command value OUT (0DH),A RET ST10US: ; delays about 10 uS PUSH AF ST10US1: DEC BC LD A,B OR C JR NZ,ST10US1 POP AF RET ST1ML: ; 1 millisecond PUSH BC LD BC,100 CALL ST10US POP BC RET ST100ML: ; 100 milliseconds PUSH BC LD BC,10000 CALL ST10US POP BC RET * * *