/*                                                      */
/*                       SETBAUD Utility                */
/*                        main program                  */

#define ver 2
#define rev 1
#define mod 'A'
#define asm ' '

#define PORTS 4
#define BAUD 9
#define USELOC 0X47

#include "setbaud.os"
#include "c:switch.os"

CHAR *em1 = "***  SYNTAX ERROR  ***\n";
/*page*/
main(argc, argv)
int	argc;
CHAR	*argv[];
{
	int p,b;
	CHAR *userloc;

	userloc = USELOC;
	printf ("Setbaud utility version %d.%d%c%c\n\
Set the serial port baud rate.\n\n", ver, rev, mod, asm);

	if (argc == 2)
		printf ("%sThere is not sufficient information \
to set a baud rate.\n\n", em1);
	else if (argc >= 3) {
		if ((p = getport (argv[1])) == -1) {
			printf ("%sThis port cannot be set.\n\n", em1);
		}
#ifdef cpm86
		else if (p == 1)
			printf ("%sPort 1's baud rate may not\
be modified, as it is the HiNet Port.\n\n", em1);
#endif
#ifdef cpm80
		else if (p == 1 && *userloc != 255) {
#ifdef dbg
			printf("user number = *userloc\n");
#endif
			printf ("%sWhen connected to HiNet, \n\
Port 1 baud rate cannot be modified.\n\n", em1);
		}
#endif
		else if ((b = getbaud (argv[2])) == -1) {
			printf ("%sThis baud rate cannot be set.\n\n", em1);
		}
		else {
			doset (p, b);	/*go set the baud rate*/
			return;
		}
	}
	printf ("The general form of the SETBAUD command is:   ");
	printf ("SETBAUD portnumber baudrate\n");
#ifdef cpm80
	printf ("where portnumber = 0, 1, 2, or 3\n");
#endif
#ifdef cpm86
	printf ("where portnumber = 0, 2, or 3\n");
#endif
	printf ("and where possible baudrates are:\n");
	printf ("9600,  4800,   2400,   1800,\n");
	printf ("1200,   600,    300,    110,\n\n");
	printf ("For example, the command SETBAUD 3 300 will\n");
	printf ("assign port number 3 a baud rate of 300.\n\n");
#ifdef cpm80
	printf ("NOTE: Ports 2 and 3 have interlocked baud rates.\n\
Port 1's baud rate may not be modified while connected to HiNet.\n");
#endif
}
/*page*/
#ifdef cpm86
/*programs for initializing the SIO and CTC for the 8086*/

/*initialize console serial port for 19200-300 baud*/
static unsigned char sp32c[] = {
	0X18,	/*Channel reset*/
	0X03,	/*Point to WR3*/
	0XC1,	/*Rx 8 bits, RX enable*/
	0X14,	/*Reset external status, point to WR4*/
	0X84,	/*X32 clock, 1 stop bit, no parity*/
	0X35,	/*Error reset, point to WR5*/
	0XEA,	/*Tx 8 bits, Tx enable, RTS, DTR*/
	0X11,	/*Point to WR1, reset interrupts*/
	0X18,	/*int. on each char*/
	0X00	/*terminator*/
};
/*initialize console serial port for 110 baud*/
static unsigned char sp64c[] = {
	0X18,	/*Channel reset*/
	0X03,	/*Point to WR3*/
	0XC1,	/*Rx 8 bits, RX enable*/
	0X14,	/*Reset external status, point to WR4*/
	0XC4,	/*X64 clock, 1 stop bit, no parity*/
	0X35,	/*Error reset, point to WR5*/
	0XEA,	/*Tx 8 bits, Tx enable, RTS, DTR*/
	0X11,	/*Point to WR1, reset interrupts*/
	0X18,	/*int. on each char*/
	0X00	/*terminator*/
};
/*initialize modem or auxilliary port for 19200-300baud*/
static unsigned char sp32[] = {
	0X18,	/*Channel reset*/
	0X14,	/*Reset external status, point to WR4*/
	0X84,	/*X32 clock, 1 stop bit, no parity*/
	0X03,	/*Point to WR3*/
	0XE1,	/*Rx 8 bits, RX enable, auto enables*/
	0X35,	/*Error reset, point to WR5*/
	0XEA,	/*Tx 8 bits, Tx enable, RTS, DTR*/
	0X11,	/*point to WR1*/
	0X04,	/*no interupts*/
	0X00	/*terminator*/
};
/*initialize modem or auxilliary port for 110 baud*/
static unsigned char sp64[] = {
	0X18,	/*Channel reset*/
	0X14,	/*Reset external status, point to WR4*/
	0XC4,	/*X64 clock, 1 stop bit, no parity*/
	0X03,	/*Point to WR3*/
	0XE1,	/*Rx 8 bits, RX enable, auto enables*/
	0X35,	/*Error reset, point to WR5*/
	0XEA,	/*Tx 8 bits, Tx enable, RTS, DTR*/
	0X11,	/*point to WR1*/
	0X04,	/*no interupts*/
	0X00	/*terminator*/
};
/*page*/
static unsigned char spnull[] = {0X00};
/*CTC programs for 19200-110baud*/
/* 1st byte is control word: clock trigger mode, time constant follows,*/
/*software reset, no interrupts*/
/*clock trigger input is 1.23Mhz.  2d byte is time constant*/
static unsigned char ctcprg[BAUD][2] = {{0X47,0X02}, {0X47,0X04}, {0X47,0X08}, {0X47,0X10},
	{0X47,0X15},{0X47,0X20}, {0X47,0X40}, {0X47,0X80}, {0X47,0XAE}};

/*array used to choose an sio program*/
static CHAR *siopprog[PORTS][BAUD] = {
	{sp32c, sp32c, sp32c, sp32c, sp32c, sp32c, sp32c, sp32c, sp64c},
	{spnull,spnull, spnull, spnull, spnull, spnull, spnull, spnull, spnull},
	{sp32, sp32, sp32, sp32, sp32, sp32, sp32, sp32, sp64},
	{sp32, sp32, sp32, sp32, sp32, sp32, sp32, sp32, sp64}
};
/*arrays used to choose port address*/
static unsigned int ctcport[PORTS] = {0X008C, 0X0000, 0X0088, 0X008A};
static unsigned int sioport[PORTS] = {0X0086, 0X0000, 0X0096, 0X0092};
/*page*/
doset (p, b)
int	p;
int	b;
{
	int	enableints();
	int	disableints();
	unsigned char outportb();
	unsigned int cp = ctcport[p];
	unsigned int sp = sioport[p];
	CHAR *s = siopprog[p][b];
#ifdef dbg
	printf ("Have reached doset.\n");
	printf ("portindex      = %d      baudindex   = %d\n", p, b);
	printf("CTCport address = %xh  SIOport address = %xh\n", cp, sp);
#endif
#ifdef dbg
	printf("1st CTC byte = %xh  ", outportb(cp,ctcprg[b][0]));
	printf("2d CTC byte = %xh\n", outportb(cp,ctcprg[b][1]));
#else
	outportb(cp,ctcprg[b][0]);	/*program CTC*/ 
	outportb(cp,ctcprg[b][1]);
#endif
	
	/*program SIO*/ 
	disableints;	/*disable interrupts*/
	while(*s)
#ifdef dbg
		printf("byte out = %xh\n", outportb(sp,*s++));
#else
		outportb(sp,*s++);
#endif
	enableints;	/*enable interrupts*/
}
#endif
/*page*/
#ifdef cpm80
/*CTC programs for Z80 19200-110baud*/
/*1st byte is control word, 2d is time constant*/
static  char ctcprg[BAUD][2] = {
{0X45, 06},	/*counter mode, time constant follows*/
{0X45, 13}, {0X45,26}, {0X45,52}, {0X45,69}, {0X45,104}, {0X45,208},
{0X05, 52},	/*timer  mode, prescale = 16, time constant follows*/
{0X05, 142}
};
/*array for selecting CTC port*/
static  char ctcport[PORTS] = {0X30, 0X31, 0X32, 0X32};
doset (p, b)
int	p;
int	b;
{
	char outb();
	char cp;
	cp  = ctcport[p];
#ifdef dbg
	printf ("Have reached doset.\n");
	printf ("portindex      = %d  ", p);
	printf("CTCport address = %xh  ", cp);
	printf("1st CTC byte = %xh  ", ctcprg[b][0]);
	printf("2d CTC byte = %d\n", ctcprg[b][1]);
	printf("outb(ctcprg[%d][0]) = %xh  ", b, outb(cp, ctcprg[b][0]));
	printf("outb(ctcprg[%d][1]) = %d\n", b, outb(cp, ctcprg[b][1]));
#else
	outb(cp, ctcprg[b][0]);	/*program CTC*/ 
	outb(cp, ctcprg[b][1]);
#endif
}
#endif
/*page*/
getport (s)
CHAR *s;	/*string to be matched*/
{
	static	CHAR *port[] = {"0" ,"1", "2", "3"};
	int i = 0;

	while (i <= PORTS)
		if (!strncmp (s, port[i++], 2))
			return (--i);
		return (-1);
}


getbaud (s)
CHAR *s;
{
	static	CHAR *baudr[] = {"19200", "9600", "4800", "2400",
				"1800",  "1200", "600", "300", "110"};
	int i = 0;

	while (i <= BAUD)
		if (!strncmp (s, baudr[i++], 6))
			return (--i);
		return (-1);
}


#ifdef aztec
#asm
#define OUTPA db 0edh, 79h
/*sends arg2, which is a byte, to port arg1*/
/*returns the byte sent*/
outb_:
	lxi	h,2
	dad	sp	/*points to port number*/
	mov	c,m
	inx	h	/*points to byte to send*/
	inx	h
	mov	a,m
	OUTPA
	mvi	h,0
	mov	l,a	/*return byte sent*/
	ora	l	/*appropriate zero flag*/
	ret
#endasm
#endif
