/**************************************************************************
*    Libreria para emular puerto serie asincronico (UART) para HiTech     *
***************************************************************************

***************************************************************************
* Con clock de 4MHz la velocidad maxima de transmision es de 38400 Baud   *
* Con clock de 8MHz en adelante la velocidad minima de transmision es de  *
* 2400 Baud                                                               *
***************************************************************************

***************************************************************************
*                                                                         *
* Antes de incluir este archivo en nuestro programa hay que definir       *
* algunos parametros. Estos son                                           *
*                                                                         *
* PIC_CLK   (es necesario para los delay usados internamente)             *     
*                                                                         *
* TxPin     (puerto de salida)                                            *
* RxPin     (puerto de entrada)                                           *
* BaudRate  (velocidad de transferencia)                                  *
*                                                                         *
***************************************************************************

***************************************************************************
*                                                                         *
* Las rutinas de delay se encuentran en el archivo "delayhd.h"            *
* El nombre original del archivo es:                                      * 
* "delay_alternative_enchanced_precision.h" y esta incluido dentro de     *
* "PIC_Hi-Tech_C_delay_and_timeout_routines_for_PIC16xxxx_v7-1.zip"       *
* Bajado de www.microchipc.com                                            *
*                                                                         *
* Hay que tener este archivo dentro de la carpeta de trabajo.             *
*                                                                         *
*  Si se quiere transmitir, el pin que se utilice como TX tiene que       *
* configurarse como salida.                                               *
*  Si se quiere recibir, el pin que se utilice como RX tiene que          *
* configurarse como entrada.                                              *
*                                                                         *
***************************************************************************

***************************************************************************
*                                                                         *
* En esta libreria se encuentran las siguientes funciones                 *
*                                                                         *
* InitSoftUart()                (inicializa el puerto serie)              *
* char getch_s()                (lee un byte del puerto serie)            *
* putch_s(char)                 (envia un byte al puerto serie)           *
* putst_s(char*)                (envia un string al puerto serie)         *
* char * getst_s(char*)         (lee una cadena que termine con '\r')     *
*                                                                         *
*  El parametro de la funcion anterior puede ser un puntero a un String   *
* o el propio String                                                      *
*                                                                         *
***************************************************************************

* Ejemplo de configuracion y utilizacion

  #define PIC_CLK 10000000
  #define TxPin	RA0
  #define RxPin	RB1
  #define BaudRate 9600

  #include "SoftUart.c"

  void main (void)
  {
    const char * pantalla = "Mundo";

    .....
    .....
    .....
    TRISA0 = 0;
    TRISB1 = 1;
    InitSoftUart();
    Putst_s ("Hola");   // envia el string "Hola" al puerto serie
    Putst_s ("\n");     // envia el salto de linea al puerto serie
    Putst_s (pantalla)  // envia el string apuntado por pantalla al puerto serie

  }

*/


#include "delayhd.h"	

#if defined (PIC_CLK) && defined (BaudRate) && defined (TxPin) && defined (RxPin)

  #if (PIC_CLK < 16000000)
    #define BitDelay (1000000/BaudRate)
    #define HalfBitDelay (500000/BaudRate)
  #else
    #define BitDelay (500000/BaudRate)
    #define HalfBitDelay (250000/BaudRate)
  #endif

  #if (PIC_CLK == 4000000)
    #define DelayReceivebit DelayUs(BitDelay-7)\
							DelayUs(HalfBitDelay-7)
    #if (BaudRate <= 19200)
      #define DelayStartBit DelayUs(BitDelay-7)
      #define DelaySendBit NDelayUs(BitDelay-18)
    #elif (BaudRate == 28800)
      #define DelayStartBit DelayUs(BitDelay-6)
      #define DelaySendBit NDelayUs(BitDelay-18)
    #elif (BaudRate == 38400)
      #define DelayStartBit DelayUs(BitDelay-7)\
							dly2u
      #define DelaySendBit DelayUs(BitDelay-19)\
						   dly1u
    #endif

  #elif (PIC_CLK == 8000000)
    #define DelayReceivebit DelayUs(BitDelay-7)\
							DelayUs(HalfBitDelay-2)
    #define DelayStartBit DelayUs(BitDelay-4)
    #if (BaudRate <= 38400)
      #define DelaySendBit NDelayUs(BitDelay-10)
    #else	  //(BaudRate == 57600)
      #define DelaySendBit NDelayUs(BitDelay-9)
	#endif

  #elif (PIC_CLK == 10000000)
    #define DelayReceivebit DelayUs(BitDelay-7)\
		  					DelayUs(HalfBitDelay)
    #if (BaudRate <= 38400)
      #define DelayStartBit DelayUs(BitDelay-4)
      #define DelaySendBit NDelayUs(BitDelay-8)
    #else //(BaudRate == 57600)
      #define DelayStartBit DelayUs(BitDelay-3)
      #define DelaySendBit NDelayUs(BitDelay-7)
	#endif

  #elif (PIC_CLK == 16000000) || (PIC_CLK == 20000000)
    #if (PIC_CLK == 16000000)
      #define DelayReceivebit DelayUs(BitDelay)\
							  DelayUs(BitDelay)\
							  DelayUs(BitDelay-5)
    #else //(PIC_CLK == 20000000)
      #define DelayReceivebit DelayUs(BitDelay)\
							  DelayUs(BitDelay)\
							  DelayUs(BitDelay-4)								
    #endif
		
	#if (BaudRate <= 38400)
      #define DelayStartBit DelayUs(BitDelay)\
							DelayUs(BitDelay-2)
      #define DelaySendBit NDelayUs(BitDelay)\
						   NDelayUs(BitDelay-4)
    #else //(BaudRate == 57600)
      #define DelayStartBit DelayUs(BitDelay)\
							DelayUs(BitDelay-1)
      #define DelaySendBit NDelayUs(BitDelay)\
						   NDelayUs(BitDelay-3)
    #endif
  #endif

/*
void InitSoftUart(void)
{
  TxPin = 1;
}
*/

  #define InitSoftUart TxPin = 1

  unsigned char getch_s(void)
  {
    unsigned char contador = 7;
    unsigned char letra = 0;

    DelayReceivebit;
    do
    {
      if (RxPin == 1) letra += 128;
      letra = letra >> 1;
      contador--;
      DelaySendBit;
    }
    while (contador > 0);
    DelaySendBit;
    return letra;
  }

  void putch_s (unsigned char data)
  {
    unsigned char contador = 8;

    TxPin = 0;
    DelayStartBit;
    do
    {
      TxPin = data;
      DelaySendBit;
      data = data >> 1;
      contador--;
    }
    while (contador > 0);
    TxPin = 1;
    DelayStartBit;   //tiempo de espera del bit de stop
  }

  void putst_s (const char *word)
  {
    while (*word != 0)
    {
      putch_s(*word);
      word++;
    }
  }
  
  char * getst_s (char * st)
  {
    char * st1;
    char caracter;
    
    st1 = st;
    do
    {
      caracter = getch_s();
      if (caracter != '\r')
      {
        *st1 = caracter;
        st1++;
      }
      *st1 = '\0';
    }
    while (caracter != '\r');
    return st;
  }  
  
#else
 #error Faltan definir parametros
#endif