/*
Copyright (C) Magna Carta Software, Inc. 1988-1990. All Rights Reserved.
Z80SIO03.C -- BISYNC reception using the Z-80 SIO
*/
#include <comm.h>
#include <z80sio.h>
#include <cursor.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
/* 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 */
}