// TOOLS.C
//

#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-порт

   select_port(value);

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

   save_com();

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

   install_com();


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

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

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

   current_baud = baud;

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

   dtr_on();

	port_active = TRUE;

	return( 0 );
}


/**
*.Name         sread
*
*.Title        Читает символы из COM-порта.
*
*.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 = r_count_pending();

		// если в буфере ессть необходимое количество символов

		if (pending >= wanted) {

         unsigned int i;

			// считывааем из буфера нужное число символов

         for (i = 0; i < wanted; i++)
            *buffer++ = (char) receive_com();

         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
*
*.Title        Запись символов в COM-порт.
*
*.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++)
      send_com(*data++);

   return len;
}


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

void ssendbrk(void)  {

   break_com();
}


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

void closeline(void) {

   int far *stats;

	port_active = FALSE;

	// отменяем сигнал DTR

   dtr_off();

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

   close_com();

	// восстанавливаем вектора прерываний

   restore_com();
}


