/* Copyright (C) Magna Carta Software, Inc. 1988-1990. All Rights Reserved. Z80SIO03.C -- BISYNC reception using the Z-80 SIO */ #include #include #include #include #include #include /* MANIFEST CONSTANTS AND MACROS */ #define MENU ALT_M /* key for command summary */ #define AST 0X300 /* 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); void INTERRUPT_ uz80_bisync_rxint(void); /* GLOBAL VARIABLES */ BYTE ztxbuf[2048]; /* TRANSMIT BUFFER FOR Z-80 SIO */ BYTE zrxbuf[2048]; /* RECEIVE BUFFER FOR Z-80 SIO */ int vers = 3; #include "sioport.c" COMM_PORT * sio0 = &z80; /* ------------------------ PROGRAM BEGINS HERE --------------------------- */ int main(void) { z80.uart.uz80sio = uz80; /* Z-80 SIO INITIALIZATION */ u2.uz80sio = uz80; if (c_open(&z80) == PORT_ALREADY_OPEN) { fprintf(stderr, "\aError: Cannot open port1"); mspause(1000); return (EOF); } uz80_mod_reg(&z80, WR3, ~UZ80_RX_ENABLE, 0); uz80_set_reg(&z80, WR0, UZ80_RX_CRC_RESET); uz80_set_reg(&z80, WR2, 0); /* interrupt vector */ /* uz80_mod_reg(&z80, WR3, ~UZ80_AUTO_ENABLE, UZ80_AUTO_ENABLE); */ uz80_mod_reg(&z80, WR4, ~UZ80_STOPBITS_MASK, UZ80_STOPBITS0); uz80_mod_reg(&z80, WR4, ~UZ80_SYNC_MASK, UZ80_BISYNC); uz80_mod_reg(&z80, WR4, ~UZ80_CLOCK_MASK, X1); uz80_mod_reg(&z80, WR5, ~UZ80_CRC16_MASK, UZ80_CRC16_MASK); uz80_mod_reg(&z80, WR5, ~UZ80_DTR_MASK, UZ80_DTR_MASK); uz80_mod_reg(&z80, WR3, ~UZ80_SYNC_INHIBIT, UZ80_SYNC_INHIBIT); /* uz80_mod_reg(&z80, WR3, ~UZ80_RX_CRC_ENABLE, UZ80_RX_CRC_ENABLE); */ uz80_mod_reg(&z80, WR3, ~UZ80_HUNT_ENTER, UZ80_HUNT_ENTER); uz80_mod_reg(&z80, WR3, ~UZ80_RX_DATABITS_MASK, UZ80_RX_DATA8); uz80_set_reg(&z80, WR6, SYN); uz80_set_reg(&z80, WR7, SYN); /* STATUS EFFECTS VECTOR, EXTERNAL INT. ENABLE, RX INT. ENABLE */ uz80_mod_reg(&z80, WR1, ~0X1D, 0X1D); uz80_mod_reg(&z80, WR3, ~UZ80_RX_ENABLE, UZ80_RX_ENABLE); #if 0 uz80_mod_reg(&z80, WR3, ~UZ80_SYNC_INHIBIT, UZ80_SYNC_INHIBIT); uz80_mod_reg(&z80, WR3, ~UZ80_HUNT_ENTER, UZ80_HUNT_ENTER); uz80_mod_reg(&z80, WR3, ~UZ80_RX_DATABITS_MASK, UZ80_RX_DATA8); #endif /* INSTALL THE INTERRUPT HANDLERS */ uz80_install_ipr(&z80, UZ80_RX_ALL, NULL, zrxbuf, sizeof(zrxbuf)); uz80_install_ipr(&z80, UZ80_ES, NULL, NULL, 0); install_isr(&z80, 2, (void far *) uz80_bisync_rxint); 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); set_dtr(&z80, LOW); uz80_mod_reg(&z80, WR3, ~UZ80_RX_ENABLE, 0); 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, XLAT, TRUE); 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, XLAT, TRUE); 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 */ } char *parity_strings[] = {"NONE","ODD","EVEN","MARK","SPACE"}; /* DO_DATA_MENU -- Show a menu for setting the data format. */ void do_data_menu(COMM_PORT * p_port) { short key, DONE = FALSE; do { puts("\nSET THE DATA FORMAT"); printf("\nFormat: %d Data bits, %s Parity, %d Stopbits", p_port->rxdatabits, parity_strings[p_port->parity], p_port->stopbits ); puts("\nA. Set number of databits"); puts("B. Set number of stopbits"); puts("C. Set parity"); puts("\nAny other key exits"); key = toupper(bios_key(0) & 0XFF); switch (key) { case 'A': puts("\nEnter databits (5, 6, 7 or 8): "); key = bios_key(0) & 0XF; set_databits(p_port, key); break; case 'B': puts("\nEnter stopbits (1 or 2): "); key = bios_key(0) & 0XF; set_stopbits(p_port, key); break; case 'C': puts("\nEnter parity ('N' for none, 'E' for even, etc.): "); key = toupper(bios_key(0) & 0XFF); if (key == 'N') set_parity(p_port, PARITY_NONE); else if (key == 'E') set_parity(p_port, PARITY_EVEN); else if (key == 'O') set_parity(p_port, PARITY_ODD); else if (key == 'M') set_parity(p_port, PARITY_MARK); else if (key == 'S') set_parity(p_port, PARITY_SPACE); else puts("\nNot recognized. Use 'N', 'E', 'O', 'M' or 'S'"); break; default: DONE = TRUE; break; } } while (!DONE); printf("\nFormat now : %d Data bits, %s Parity, %d Stopbits", p_port->rxdatabits, parity_strings[p_port->parity], p_port->stopbits ); } /* DO_SPEED_MENU -- Show a menu for setting the data tranfer rate. */ long do_speed_menu(COMM_PORT *p_port) { short key; long ret; do { puts("\nSET THE DATA TRANSFER SPEED"); printf("\nSpeed: %ld bits-per-second\n", p_port->speed); puts("\nA. Data transfer rate 50 bits-per-second"); puts("B. Data transfer rate 75 bits-per-second"); puts("C. Data transfer rate 110 bits-per-second"); puts("D. Data transfer rate 134.5 bits-per-second"); puts("E. Data transfer rate 150 bits-per-second"); puts("F. Data transfer rate 300 bits-per-second"); puts("G. Data transfer rate 600 bits-per-second"); puts("H. Data transfer rate 1200 bits-per-second"); puts("I. Data transfer rate 2400 bits-per-second"); puts("J. Data transfer rate 4800 bits-per-second"); puts("K. Data transfer rate 9600 bits-per-second"); puts("L. Data transfer rate 19200 bits-per-second"); puts("M. Data transfer rate 38400 bits-per-second"); puts("N. Data transfer rate 57600 bits-per-second"); puts("O. Data transfer rate 115200 bits-per-second"); printf("\n\tNew data transfer rate: "); key = toupper(bios_key(0) & 0XFF); } while (key < 'A' || key > 'O'); switch (key) { case 'A': ret = 50; break; case 'B': ret = 75; break; case 'C': ret = 110; break; case 'D': puts("\nSorry, that data transfer rate not supported"); ret = EOF; break; case 'E': ret = 150; break; case 'F': ret = 300; break; case 'G': ret = 600; break; case 'H': ret = 1200; break; case 'I': ret = 2400; break; case 'J': ret = 4800; break; case 'K': ret = 9600; break; case 'L': ret = 19200; break; case 'M': ret = 38400L; break; case 'N': ret = 57600L; break; case 'O': ret = 115200L; break; default: ret = EOF; } if (ret != EOF) { set_speed(p_port, ret); printf("\nSpeed now set to: %ld bits-per-second\n", p_port->speed); } return ((long) ret); } /* UZ80_BYSYNC_RXINT -- Interrupt handler for the Z-80 SIO to perform BISYNC. Enables RX, TX, ES interrupts For use under the IBM architecture. */ void INTERRUPT_ uz80_bisync_rxint(void) { static BYTE c, rx_lastchar; static volatile BYTE far *b_ptr; outp(z80.ubase_addr, 2); /* toggle the reg. ptr. to RR2 */ c = (BYTE) (inp(z80.ubase_addr) & 0XE); /* EXTERNAL STATUS CHANGE (DCD, CTS, or SYNC) */ if (c & 2) { uz80_set_reg(&z80, WR0, UZ80_ES_RESET); } /* RX CHARACTER AVAILABLE */ if (c & 4) { if (inp(z80.ubase_addr) & 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 */ rx_lastchar = *z80.rxbufhead = (BYTE) inp(z80.udata_reg_addr); z80.rxbufhead = b_ptr; } } } else if (c & 6) { /* SPECIAL RECEIVE CONDITION (Parity error, RX Overrrun, CRC Error */ #if defined(CCT_TEST) outp(AST+3,1); /* read register 1 for int type */ rr1 = inp(AST+3); if (rr1 & 0X20) { c = 'o'; /* receiver overrun error */ outp(AST+3, 0X30); /* issue error reset command */ if (inp(AST+3) & 1) inp(AST+3); /* IF a char is ready get it */ } else if (rr1 & 0X40) { c = 'f'; /* receiver framing error */ outp(AST+3, 0X30); /* issue error reset command */ if (inp(AST+3) & 1) inp(AST+1); /* IF a char is ready get it */ } #endif } disable(); outp(EOINT, 0X20); /* Send EOI to 8259 */ }