/***************************************************************************
These C++ classes are copyright 1990, by William Herrera.

All those who put this code or its derivatives in a commercial product MUST
mention this copyright in their documentation for users of the products in
which this code or its derivative classes are used.  Otherwise, this code
may be freely distributed and freely used for any purpose.

Enhancements: 1991 by David Orme
	*  General cleanup.
			- I/O now takes advantage of C++ overloading.
			- Serial port I/O functionality now only in Serial class.
			- Modem functionality now only in Modem class.
	*  Possible to easily implement file Xfr prots now.
	*  CCITT CRC-16 class added							-- 2-20-1991
	*  BIOS Timer class added								-- 2-22-1991
	*  Optional timeout on all input routines added	-- 2-25-1991

***************************************************************************/

// file serialpo.cpp class definitions for SerialPort.

#include <stdio.h>
#include <stdlib.h>

#include "serialpo.hpp"

SerialPort::SerialPort(int portnum, int speed, parity_t p,
						 int sbits, int dbits, boolean trans)
{
	port_number = portnum;
	switch(port_number)
	{
		case 1: 
			com = new COM1;
			break;  		
		case 2: 
			com = new COM2;
			break;		
		case 3: 
			com = new COM3;
			break;		
		case 4: 
			com = new COM4;
			break;
		default:
			fputs("SerialPort error: constructor cannot initialize"
					" port number given", stderr);
			exit(-1);
	}	
	com->SetBaudRate(speed);
	com->SetParity(p);
	com->SetStopBits(sbits);
	com->SetDataBits(dbits);
	translatenewline = trans;
	lastin_wascr = false;
}

SerialPort::~SerialPort() 
{ 
	delete com;
}

uart * SerialPort::GetUART() { return com; }

void SerialPort::SetSpeed(int s) { com->SetSpeed(s); }
int SerialPort::GetSpeed() { return com->GetSpeed(); }

void SerialPort::SetParity(parity_t p) { com->SetParity(p); }
parity_t SerialPort::GetParity() { return com->GetParity(); }

void SerialPort::SetStopBits(int s) { com->SetStopBits(s); }
int SerialPort::GetStopBits() { return com->GetStopBits(); }

void SerialPort::SetDataBits(int s) { com->SetStopBits(s); }
int SerialPort::GetDataBits() { return com->GetStopBits(); }

void SerialPort::PurgeInput() { com->PurgeInput(); }
void SerialPort::FlushOutput() { com->FlushOutput(); }
void SerialPort::PurgeOutput() { com->PurgeOutput(); }

boolean SerialPort::CarrierPresent() { return com->CarrierPresent(); }
	  
void SerialPort::RaiseDTR() { com->SetDTR(true); }
void SerialPort::DropDTR() { com->SetDTR(false); }


void SerialPort::Pause(int ms) { com->Pause(ms); }
void SerialPort::Break(int ms) { com->Break(ms); }

void SerialPort::SetDoIfNoCarrier(void (*f)()) { com->SetDoIfNoCarrier(f); }
void SerialPort::SetDoOnRing(void (*f)()) { com->SetDoOnRing(f); }

boolean SerialPort::InputEmpty() { return com->InputEmpty(); }
boolean SerialPort::OutputEmpty() { return com->OutputEmpty(); }
boolean SerialPort::OutputReady() { return com->OutputReady(); }


// These are the binary read/write functions -- they don't do
// \r\n xlation.

void SerialPort::Write(void * p,int n)
{
	// will only write up to number that can fit into queue, up to max of n.
	while(n > 0)
	{
		Send(*((char *)p)++);
		--n;		
	}
}

int SerialPort::Read(char * p, int n, float secs)
{
	// will only read up to number in queue, up to max of n chars.
	int i = 0;
	T.Set(secs);							// Set timeout timer
	while(n-- > 0 && (!T.TimeOut() || com->InputEmpty()) )
	{
		while (!T.TimeOut() && com->InputEmpty());
		if (com->InputEmpty())
			break;
		*p++ = com->GetChar();
		i++;
	}
	return i;
	// returns number actually read.
}


// The send and recieve functions below are set up to allow 
// optional carriage return/linefeed translation of '\r\n' <--> '\n'
// if translatenewline is true.

int SerialPort::Receive(char& ch, float secs)
{
	T.Set(secs);			// Set timeout timer

	while(!lastin_wascr && com->InputEmpty() && !T.TimeOut());

	if (!lastin_wascr && com->InputEmpty())
		return -1;

	if(lastin_wascr)
	{
		ch = '\n';
		lastin_wascr = false;
	}
	else
	{
		ch = char(com->GetChar());
		if(translatenewline && ch == '\r')
			lastin_wascr = true;
	}
	return 1;
}

void SerialPort::Send(char ch)
{
	com->SendChar(ch);
	if(translatenewline && ch == '\r')	
		com->SendChar('\n'); 
}

void SerialPort::Send(char * s) { while(*s) com->SendChar(*s++); }


// end of file Serialpo.cpp

