/* Copyright (C) Magna Carta Software, Inc. 1988-1990. All Rights Reserved. Z80SIO01.C -- Use interrupt-driven transmission or reception with Z80 SIO CAPABILITY: Dumb terminal program. 1) Uses interrupt driven transmission. 2) Data transfer rate can be set at run time. 3) Data format can be adjusted at run time. 4) Received data translation. 5) Transmitted data translation is used. All other options must be changed in the source code and the source recompiled to change them. */ #include #include #include #include #include /* MANIFEST CONSTANTS AND MACROS */ #define MENU ALT_M /* key for command summary */ #define AST 0X303 /* base address of AST CC-232 */ /* FUNCTION PROTOTYPES */ void do_data_menu(COMM_PORT * p_port); long do_speed_menu(COMM_PORT * p_port); short menu(COMM_PORT *p); void term(COMM_PORT *p); /* GLOBAL VARIABLES */ BYTE zrxbuf[2048]; /* RECEIVE BUFFER FOR Z-80 SIO */ BYTE ztxbuf[2048]; /* TRANSMIT BUFFER FOR Z-80 SIO */ int vers = 1; #include "menus.c" /* DEFINE SOME SPECIAL FEATURES OF THE Z80 SIO IN A STRUCTURE */ UARTZ80SIO uz80 = { AST + 6, /* offset of clock reg. from base */ 0X30F, /* offset of interrupt id. register */ X16, /* USART reference clock speed */ {0,0,0,0,0,0,0,0} /* USART virtual write register array */ }; COMM_PORT z80; /* ------------------------ PROGRAM BEGINS HERE --------------------------- */ int main(void) { /* ASSIGN THE Z80 SIO USART DEFINED ABOVE TO THE COMM_PORT STRUCTURE */ z80.uart.uz80sio = uz80; /* Z-80 SIO INITIALIZATION */ uz80_init(&z80, 0X302, AST, 19200L, 8, PARITY_NONE, 1); /* AST Z80-SIO, INSTALL THE INTERRUPT HANDLER AND ENABLE RECEIVE INTERRUPTS */ install_ipr(&z80, RECEIVE, NULL, zrxbuf, sizeof(zrxbuf)); /* install_ipr(&z80, TRANSMIT, NULL, ztxbuf, sizeof(ztxbuf)); */ install_isr(&z80, 7, (void far *) uz80_rx_int_); printf("CCT Z-80 SIO Version %d: Press Alt-M for a list of commands\n", vers); term(&z80); printf("\nEnd of CCT Z-80 SIO%d\n", vers); deinit_port(&z80); return (0); } /* TERM -- The terminal emulation routine. Simply polls the COM port and the keyboard alternately for characters. */ void term(COMM_PORT *p_port) { short c; /* must be signed to detect a -1 return */ /* THESE LINES CONTROL THE RECEIVED DATA FORMAT */ set_rx_xlat(p_port, EOL, FALSE); set_rx_xlat(p_port, LOCAL_ECHO, ON); /* THESE LINES CONTROL THE TRANSMITTED DATA FORMAT */ set_tx_xlat(p_port, ASCII_ONLY, TRUE); for (;;) { /* CHECK SERIAL PORT FOR BYTE */ while ((c = c_getc(p_port)) != EOF); /* CHECK KEYBOARD FOR A KEY PRESS */ if ( (c = inkey()) != EOF) { if (c == MENU) { if (menu(p_port) == 1) break; } else c_putc(p_port, c); } } } #define DATA_FORMAT 'D' /* key to set speed */ #define DATA_SPEED 'S' /* key to set speed */ #define EXIT 'Q' /* key to exit from main */ #define SEND_STR 'T' short menu(COMM_PORT *p_port) { short c, retval = 0, DONE = FALSE; static char *menus[] = { "\tD. Data Format", "\tS. Data Transfer Rate.", "\tT. Transmit a string", "\tQ. EXIT from COMM.", NULL }; char **p_menu; c = !EXIT; while (!DONE) { puts("\n\n"); for (p_menu = menus; *p_menu != NULL; p_menu++) printf("%s\n", *p_menu); printf("\n\t\t Enter selection (CR to quit menu) : "); if ( (c = getch()) == CR) break; /* return to term */ c = toupper(c); switch (c) { case EXIT: retval = 1; DONE = TRUE; break; case DATA_FORMAT: do_data_menu(p_port); break; case DATA_SPEED: do_speed_menu(p_port); break; case SEND_STR: c_putn(p_port, 8L, "ATS0=1X4"); DONE = TRUE; break; default: puts("Invalid choice\n\007"); DONE = TRUE; break; } } puts("\nExiting menu"); return (retval); /* will be zero except if EXIT */ } /* UZ80_RX_INT -- interrupt handler for receive data. Note: A circular buffer of char "buff1" must be declared prior to use. EOI must be defined as 0X20. BYTE is typedef unsigned char BYTE. */ void INTERRUPT_ uz80_rx_int_(void) { #if defined(CCT_TEST) static BYTE c, rr1; #endif static volatile BYTE FAR_ *b_ptr; enable(); #if defined(CCT_TEST) outp(AST,1); /* read register 1 for int type */ rr1 = inp(AST); if (rr1 & 0X20) { c = 'o'; /* receiver overrun error */ outp(AST, 0X30); /* issue error reset command */ if (inp(AST) & 1) inp(AST); /* IF a char is ready get it */ } else if (rr1 & 0X40) { c = 'f'; /* receiver framing error */ outp(AST, 0X30); /* issue error reset command */ if (inp(AST) & 1) inp(AST); /* IF a char is ready get it */ } else #endif if (inp(AST) & 1) { /* IF a char is ready get it */ b_ptr = z80.rxbufhead + 1; if (b_ptr > z80.rxbufend) b_ptr = z80.rxbuf; if (!(b_ptr == z80.rxbuftail)) { /* buffer is full */ *z80.rxbufhead = (BYTE) inp(AST-2); z80.rxbufhead = b_ptr; } } outp(z80.pic, EOINT); /* Send EOI to 8259 */ } #if XDEBUG WORD FAR_ *s = (WORD FAR_ *) 0XB8000000L; #endif /* UZ80_TX_INT -- Interrupt handler for the Z80SIO/DART transmit data interrupt. For use under the IBM architecture. Note: A circular buffer of char "txbuff1" must be declared prior to use. EOI must be defined as 0X20. The comm port number must be specified. BYTE is typedef unsigned char BYTE. */ void INTERRUPT_ uz80_tx_int_(void) { /* enable(); */ if (z80.txbuftail == z80.txbufhead) { z80.f_txbusy |= FALSE; uz80_set_reg_(&z80, WR0, UZ80_TX_RESET); } else { outp(z80.udata_reg_addr, *z80.txbuftail++); /* send byte */ if (z80.txbuftail > z80.txbufend) z80.txbuftail = z80.txbuf; #if XDEBUG **s++ = (0XF << 8) | 'o'; #endif } /* disable(); */ outp(z80.pic, EOINT); /* Send EOI to 8259 */ }