/*
 * *************************************************************************
 *
 * Trimble Navigation, Ltd.
 * OEM Products Development Group
 * P.O. Box 3642
 * 645 North Mary Avenue
 * Sunnyvale, California 94088-3642
 *
 * Corporate Headquarter:
 *    Telephone:  (408) 481-8000
 *    Fax:        (408) 481-6005
 *
 * Technical Support Center:
 *    Telephone:  (800) 767-4822	(U.S. and Canada)
 *                (408) 481-6940    (outside U.S. and Canada)
 *    Fax:        (408) 481-6020
 *    BBS:        (408) 481-7800
 *    e-mail:     trimble_support@trimble.com
 *
 * *************************************************************************
 *
 * Vers	Date		   Changes										         Author
 * ----	---------   ----------------------------------------	   ----------
 * 1.10	21 Jun 93	Initial version								   pvwl
 * 1.20  14 Jun 95   Revisions                                     ahl
 *       26 Jul 95   Communications at rates above 9600 bps
 *        7 Aug 95   Revisions: port settings
 * *************************************************************************
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include "tsip_ifc.h"
#include "tsipincl.h"

#define FLOW_OFF 0
#define FLOW_ON  1

#include <math.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>

#define NUM_PORTS 3

static short  			tsip_port;
static short				port_initialized[NUM_PORTS];
static short  			io_code[NUM_PORTS];

void toggle_TSR_flow_control (short cntrl)
{
	union REGS
		regs;

	switch (cntrl) {
	case FLOW_ON:        /* enable receive flow control */
		regs.h.ah = 9;
		regs.h.dh = 0;
		regs.h.dl = 1;    /* 0=flow control */
		break;

	case FLOW_OFF:       /* disable flow control */
		regs.h.ah = 9;
		regs.h.dh = 0;
		regs.h.dl = 0;
		break;
	}
	int86 (0x14, &regs, &regs);
}

void set_serial_port (void)
{
	if (tsip_port == 0)
	{
		union REGS
			regs;

		regs.h.al = io_code[tsip_port];
		regs.h.ah = 4;
		regs.h.dl = 1;
		int86 (0x14, &regs, &regs);
		toggle_TSR_flow_control (FLOW_ON);
	}
	else
	{
		unsigned short
			baud, databits, parity, stopbits;

		baud     = (io_code[tsip_port] >> 5) & 0x0F;
		databits = (io_code[tsip_port]     ) & 3;
		parity   = (io_code[tsip_port] >> 3) & 3;
		stopbits = (io_code[tsip_port] >> 2) & 1;
		initsio (tsip_port, (75 << baud), databits + 5, stopbits + 1, (parity << 3));
	}
}

void set_buf_serial_port (void)
{
	short port_param_set;
   /* first time through - set to COM1 and initialize to 9600 8-odd-1 */
	if (port_initialized[tsip_port]) {
	  xprintf ("Current port is COM%d", tsip_port);
	  clreol (); show_crlf ();
		if (tsip_port != 0)
		{
			xprintf ("Change port?");
			if (ask_verify ()) {
				tsip_port = 3 - tsip_port;
				xprintf ("Port selected is COM%d\r\n", tsip_port);
			}
		}
	}

	if (port_initialized[tsip_port]) {
		port_param_set = FALSE;
		xprintf ("Change port parameters?");
		clreol ();
		if (!ask_verify ()) {
			port_param_set = TRUE;
		}
		if (!port_param_set	&& io_code[tsip_port] != 0xC3)
		{
			xprintf ("Set to 4800 8-none-1?");
			if (ask_verify ())
			{
				io_code[tsip_port] = 0xC3;
				port_param_set = TRUE;
			}
		}
		if (!port_param_set	&& io_code[tsip_port] != 0xEB)
		{
			xprintf ("Set to 9600 8-odd-1?");
			if (ask_verify ())
			{
				io_code[tsip_port] = 0xEB;
				port_param_set = TRUE;
			}
		}
		if (!port_param_set)
		{
			if (!serial_port_select (&io_code[tsip_port])) {
				show_crlf ();
				xprintf ("-- aborted --");
			}
		}
	}
	else
	{
		port_initialized[tsip_port] = TRUE;
	}
	set_serial_port ();
	/* clear serial link */
	send_byte (DLE);
	send_byte (ETX);
}

/* functions to wrap around the non-SPDRIVE functions to provide a   */
/* common interface for the near_term                                */

/* serial port functions related to SPDRIVE */
short initialize_serial_port (short comport)
{
	union REGS
		regs;

	short iport;

	if (comport < 0 || comport > 2) return TRUE;
	for (iport = 0; iport < NUM_PORTS; iport++) {
		port_initialized[iport] = FALSE;
		io_code[iport] = 0xEB;
	}
	tsip_port = comport;
	if (tsip_port == 0)
	{
		tsip_port = 0;
		tsip_port = 1;
		regs.h.ah = 5;
		regs.h.al = 0;
		regs.x.dx = 0;
		int86 (0x14, &regs, &regs);
		if (regs.h.ah != 1) return TRUE;
	}
	set_buf_serial_port ();
	return FALSE;
}

void reset_serial_port ()
{
	short iport;

	show_crlf ();
	for (iport = 0; iport < NUM_PORTS; iport++) {
		if (port_initialized[iport] && (io_code[iport] != 0xEB)) {
			xprintf ("Reset COM%d to 9600 baud, 8-odd-1?", iport + 1);
			if (ask_verify ()) {
				io_code[iport] = 0xEB;
				tsip_port = iport + 1;
				set_serial_port ();
			}
		}
	}
	if (tsip_port == 0) {
		toggle_TSR_flow_control (FLOW_OFF);
	} else {
		closeserial ();
	}
}

short get_byte (void)
{
	if (tsip_port == 0) {
		union REGS
			regs;
		regs.h.ah = 6;
		int86 (0x14, &regs, &regs);
		if (regs.h.ah == 1) return regs.h.al;
		return -1;
	} else {
		return get_char (tsip_port);
	}
}

short send_byte (unsigned char db)
/* send a unsigned char, if able */
{
	if (tsip_port == 0) {
		union REGS
			regs;
		regs.h.ah = 7;		/*  send unsigned char  */
		regs.h.al = db;
		int86 (0x14, &regs, &regs);
		return TRUE;
	} else {
		return put_char(tsip_port, db) ? -1 : 0;
	}
}

