----------------------------------------------------------------- ---August 1, 1994 ---Copyright Simeon Cran ---This information pertains to the MYZ80 package version 1.21 ---May be distributed freely as long as the file is not modified in any way. ---No responsibility for the accuracy of this document is accepted by the author. ----------------------------------------------------------------- The MYZ80 high performance virtual serial ports. ================================================ MYZ80 features access to the host computer's serial ports. This allows Z80 communications programs to be used in the MYZ80 environment. This document describes the methods and facilities which enable serial port communications. Very few CP/M communications programs are able to use interrupt driven i/o. Instead the majority "poll" the serial port, checking for characters as often as possible. If the polling isn't done often enough, characters are lost. The result is that baud rates must normally be kept relatively low in order to get reliable reception. Baud rates of 2400 or less may have been acceptable in the early 1980's, but now such baud rates are considered way too slow. Seeing as the polling method is built into the CP/M programs, the only way of achieving higher baud rates with existing CP/M software is to virtualise the serial ports. This is exactly what MYZ80 does. Put simply, the CP/M program still thinks it is polling the UART, but in reality it is polling a virtual UART (a software emulation of the UART). Meantime, MYZ80 runs its sophisticated interrupt driven UART code which easily handles the higher baud rates that IBM AT computers are capable of. Any data presented at the computer's serial port is read and held in a buffer ready for the CP/M program to read it via the virtual UART. The result is CP/M communications programs able to work reliably at more than 38400 baud. The virtual UART ~~~~~~~~~~~~~~~~ Any program running in MYZ80 will find two serial ports available to it. These appear to be 8250 UARTs located at Z80 i/o addresses 0-07h (port 1) and 08h-0Fh (port 2). Communications through these virtual UARTs correspond with real UARTs on the host computer. The actual mapping is controlled by API function 50. For programs which can switch communications ports, it is recommended to use API function 50 to switch the mapping. The main reason for having two virtual ports is to facilitate programs which need to use two serial ports at once. On startup, Z80 port 1 is mapped to the host computer's COM1 UART, and Z80 port 2 is mapped to the host computer's COM2 UART. API function 50 can be used to change this mapping, thereby enabling any standard UART connected to the host computer. The virtualisation routines are 16550AFN aware, and will work with 8250, 16450 and 16550 UART chips. Following is a description of what each register of the virtual UARTs does: Z80 i/o address Function PORT1 PORT2 00h 08h R When DLAB is 0: Transmitter holding register - holds the next character to be sent. W Receiver buffer register - holds the character received. R/W When DLAB is 1: Divisor low byte. 01h 09h R/W When DLAB is 0: Interrupt enable register. Interrupts can not be enabled under MYZ80. R/W When DLAB is 1: Divisor high byte. 02h 0Ah R Interrupt ID register. Interrupts can not be enabled under MYZ80 so this register is always set to 0. 03h 0Bh R/W Line control register: bit 7 DLAB (divisor latch access bit) bit 6 Break enable bit 5 Stick parity Bit 4 Parity enable Bit 3 Even parity enable Bit 2 Number of stop bits Bit 1-0 Word length 04h 0Ch R/W Modem control register: bit 1 Force RTS active bit 0 Force DTR active 05h 0Dh R Line status register bit 6 Transmitter shift and hold registers empty bit 5 Transmitter holding register empty bit 4 Break detected bit 3 Framing error detected bit 2 Parity error detected bit 1 Overrun error detected bit 0 Data ready 06h 0Eh R Modem status register: bit 7 Carrier detect bit 6 Ring indicator bit 5 Data set ready bit 4 Clear to send bit 3 Carrier detect delta bit 2 Ring indicator trailing edge bit 1 Data set ready delta bit 0 Clear to send delta 07h 0Fh R/W Scratch register Example code ~~~~~~~~~~~~ The following examples assume port 1 is being used. To use port 2 add 8 to the port addresses. ;---------------------------------------------------------------------- ; Receiving a character. Wait until a character is available: LABEL1: in a,(05h) ; Read line status register and 1 ; Check bit 0. If it is set then data is available jr z,LABEL1 ; Wait for a character ; Character is available. Get it in a,(00h) ;---------------------------------------------------------------------- ; Transmitting a character. LABEL1: in a,(05h) ; Read line status register and 20h ; Check bit 5. If it is set then we can transmit jr z,LABEL1 ; Wait until the port is clear ; Port is clear. Send the character ld a,(hl) ; Get the character out (00h),a ;---------------------------------------------------------------------- ; Changing the baud rate. ; Note that the divisor value is a 16 bit number equal to 115200 divided ; by the baud rate you require. in a,(03h) ; Get the line control register contents ld b,a ; Save it in B or 80h ; Set the high bit (DLAB) out (03h),a ; Set the DLAB ; DLAB is set now so we can change the divisor ld a,DIVLOW ; Get the low byte of the divisor out (00h),a ld a,DIVHI ; Get the high byte of the divisor out (01h),a ld a,b ; Get the original line control register contents out (03h),a ; Restore them (clear DLAB) End of File. ____________