// TOOLS.C
//

// (C) Фролов Г.В., 1995
// Адрес E-mail: frolov@glas.apc.org


#include <assert.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "common.h"
#include "tools.h"
#include "uart.h"
#include "timer.h"


unsigned port_active = FALSE;

static unsigned current_baud;

#define  STOPBIT  1

static unsigned hangup_needed = TRUE;


/**
*.Name         OpenLine
*
*.Title        Устанавливает текущий COM-порт.
*
*.Descr        Эта функция устанавливает текущий асинхронный
*              порт с которым в дальнейшем будет происходить обмен.
*
*.Proto        int OpenLine(char *name, unsigned baud)
*
*.Params       char *name - номер COM-порта
*              unsigned baud - скорость обмена данными
*
*.Return       не используется
*
*.Sample       comlib.c
**/

int OpenLine(char *name, unsigned baud) {

	int   value;

	// если порт уже активен, закрываем его

	if (port_active)
		CloseLine();

	if (sscanf(name, "COM%d", &value) != 1) {
		exit(-1);
	}

	// выбираем текущий COM-порт
	SelectPort(value);

	// сохраняем адрес старого обработчика прерываний COM-порта

	SaveCom();

	// устанавливаем новый обработчик прерываний COM-порта

	InstallCom();


	// программируем текущий COM-порт
	// скорость, связь через модем, не проверяем четность
	// один стоповый бит

	OpenCom(baud, 'M', 'N', STOPBIT);

	// запоминаем скорость

	current_baud = baud;

	// устанавливаем линию DTR в активное состояние
	// (компьютер готов к обмену данными)

	DtrOn();

	port_active = TRUE;

	return( 0 );
}


/**
*.Name         SRead
*
*.Descr        Функция читает заданное число символов
*              из буфера приемника асинхронного порта.
*
*.Proto        unsigned SRead(char *buffer, unsigned wanted, unsigned timeout)
*
*.Params       char *buffer - указатель на буфер в который будут записаны символы
*                             из буфера приемника
*              unsigned wanted - число символов, которое надо прочитать
*                                из буфера приемника
*              unsigned timeout - время, отведенное на чтение символов
*
*.Return       количество символов прочитанных  из буфера приемника
*
*.Sample       comlib.c
**/

unsigned  SRead(char *buffer, unsigned wanted, unsigned timeout) {

	time_t start;
	hangup_needed = TRUE;

	// определяем начальное время

	start = time(nil(time_t));

	for(;;) {

		unsigned int pending;

		// определяем число символов в буфере приемника
		pending = RCountPending();

		// если в буфере ессть необходимое количество символов
		if (pending >= wanted) {

			unsigned int i;

			// считывааем из буфера нужное число символов
			for (i = 0; i < wanted; i++)
				*buffer++ = (char) ReceiveCom();

			return pending;
		}

		// если в буфере приемника меньше символов, чем заказано
		// для чтения, проверяем не изтекло ли отведенное для чтения
		// время

		else {

			time_t   now     = time(nil(time_t));
			time_t   elapsed = now - start;

			Delay(0);

			if (elapsed >= (long) timeout)
				return pending;
		}
	}
}


/**
*.Name         SWrite
*
*.Descr        Функция записывает заданное число символов
*              в буфер передатчика асинхронного порта.
*
*.Proto        int SWrite(char *data, unsigned len)
*
*.Params       char *data - указатель на буфер данных
*              unsigned len - число символов, которое надо записать
*                                в буфер передатчика
*
*.Return       количество символов записанных в буфер передатчика
*
*.Sample       comlib.c
**/

int SWrite(char *data, unsigned int len) {

	unsigned int i;

	hangup_needed = TRUE;

	// записываем входные данные в буфер передатчика
	// асинхронного порта

	for (i = 0; i < len; i++)
		SendCom(*data++);

	return len;
}


/**
*.Name         SSendBrk
*
*.Title        Передает сигнал BREAK удаленному модему.
*
*.Proto        void SSendBrk()
*
*.Params       Не используются.
*
*.Return       Не используется.
*
*.Sample       comlib.c
**/

void SSendBrk(void)  {

	BreakCom();
}


/**
*.Name         CloseLine
*
*.Descr        Функция восстанавливает старые значение
*              векторов прерываний и запрещает прерывания
*              от COM-порта.
*
*.Proto        void CloseLine(void)
*
*.Params       Не используются.
*
*.Return       Не используется.
*
*.Sample       comlib.c
**/
void CloseLine(void) {

	int far *stats;

	port_active = FALSE;

	// отменяем сигнал DTR
	DtrOff();

	// заперщаем прерывания от COM-порта
	CloseCom();

	// восстанавливаем вектора прерываний
	RestoreCom();
}


