#include <18f4550.h>
#fuses NOPROTECT,NOCPD,NOLVP,WDT64,XT,NOMCLR
#use fast_io (A)
#use fast_io (B)
#use fast_io (C)
#use fast_io (D)
#use delay(clock=4000000)
#byte IPR1= 0xF9F                                       // Registro de control de interrupiones
#bit RCIP=IPR1.5                                        // Bit de prioridad de interrupción por Recepción Serial en el EUSART.
#byte PIR1=0xF9E                                        // Registro de control de interrupciones
#bit RCIF=PIR1.5                                        // Bandera de interrupción por recepción de datos en el bus serial
#byte RCON=0xFD0                                        // Registro que controla la prioridad de las interrupciones
#bit IPEN=RCON.7                                        // Habilita la prioridad de las interrupciones
#byte INTCON=0xFF2                                      // Registro de control de interrupciones
#bit  PEIE=INTCON.6                                     // Bit de Habilitación de Interrupciones de Periféricos.
#byte PIE1=0xF9D                                        // Registro de control de interrupciones por EUSART
#bit RCIE=PIE1.5                                        // Bit de habilitación de interrupción por Recepción Serial en el EUSART.
#byte TXSTA=0xFAC                                       // Registro de control del modulo EUSART
#bit  TXEN=TXSTA.5                                      // Bit de habilitación de transmisión.
#byte BAUDCON=0xFB8                                     // Registro de control e la rata de baudios
#bit  ABDEN=BAUDCON.0                                   // Bit de habilitación de detección de Auto-Baud rate
#include "lcd.c"                                        // Libreria de la LCD por el puerto B
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)          // Habilita las funciones RS232, velocidad a 9600 baudios
#byte portd= 0xF83
#byte portb= 0xF81
#byte portc= 0xF82
#define TX_485_ENABLE PIN_A5                            // Pin que habilita la transmisión por el canal RS485
#define RX_485_ENABLE PIN_A4                            // Pin que habilita la Recepción por el canal RS485

//::::::::::::::::::::::::::Declaración de variables:::::::::::::::::::::::::::::::::::::
float dato,value,valord,valorc;
int x=0,puntero=0,index;
int8 i;

//:::::::::::::::::::::::::::::Declaración de funciones::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void USART_activa_tx(void);                  // Función que habilita la transmisión
void USART_activa_rx(void);                  // Función que habilita de recepción

//::::::::::::::::::::::::::::Interrupción por el puerto serial:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

#int_rda
void isr_rda(void)
{
    ABDEN=0;                                         // Deshabilita la detección de Auto-Baud rate
    USART_activa_tx();                                                 // Llamo a la función que me habilita la transmisión
    output_high(PIN_A2);                                               // Enciendo un led de prueba
    delay_ms(1000);
    printf("               \n\r ");
    //printf("Puntero= %d V",puntero);
    //delay_ms(3);                                                     // Una demorita por si acaso
    index=0;
    //while(index<=puntero)
       //{
          output_high(PIN_A3);                                               // Enciendo un led de prueba
          delay_ms(1000);
          for(i = 0; i < 4; ++i)
             {
                *((int8 *)(&dato) + i) = read_eeprom(index + i);
             }
          index=index+4;
          for(i = 0; i < 4; ++i)
             {
                *((int8 *)(&valorc) + i) = read_eeprom(index + i);
             }
          index=index+4;
          printf("     Voltaje=  %2.2g V",dato);                       // Mando a mostrar el valor del conversor
          printf("     Corriente=  %2.2g mA",valorc);                  // Mando a mostrar el valor del conversor
          delay_ms(3);                                                 // Una demorita por si acaso
          output_low(PIN_A3);                                             // Enciendo un led de prueba
       //}
       output_low(PIN_A2);                                             // Enciendo un led de prueba
       RCIF=0;
}


//:::::::::::::::::::::::::::Programa Principal:::::::::::::::::::::::::::::::::::::::::::
void main (void)
{
         set_tris_a(0x03);                                // Puerto A, como b'01111111
         set_tris_b(0x00);                                // Puerto B, como b'00000000 (salida)
         set_tris_d(0x00);                                // Puerto D, como b'11111111 (salida)
         RCIP=1;                                          // Interrupción EUSART alta prioridad
         TXEN=1;                                          // Habilita Transmisión
         RCIE=1;                                          // Habilita la interrupción por recepción serial.
         IPEN=0;                                          // Habilito todas las interrupciones
         PEIE=1;                                          // Habilita todas las interrupciones de periféricos
         ABDEN=0;                                         // Deshabilita la detección de Auto-Baud rate
         output_a(0);                                     // Limpio el puerto A
         output_c(0);                                     // Limpio el puerto C
         output_b(0);                                     // Limpio el puerto B
         setup_wdt(WDT_ON);                               // Watchdog Encedido
         setup_port_a(AN0_ANALOG );                       // RA0 son analógicos y los demás son digitales
         lcd_init();                                      // Para inicializar el LCD
         USART_activa_rx();                               // Llamo a la función que me habilita la recepción
         enable_interrupts(global);                       // Habilita máscara global de interrupción.
         enable_interrupts(int_rda);                      // Habilita la interrupcion por dato en eusart
         ;USART_activa_tx();                               // Llamo a la función que me habilita la transmisión
         restart_wdt();                                   // Inicio el perro Guardian


//*********************************************************************************//
//*                                                                               *//
//*                      PROGRAMA PRINCIPAL                                       *//
//*                                                                               *//
//*********************************************************************************//
while(true)
         {
            restart_wdt();                                       // Inicio el perro Guardian
            SLEEP();                                             // Modo sleep
                                                                 // Se desborda Watchdog y sale del modo Sleep
            if (restart_cause()==WDT_FROM_SLEEP)                 // Si el pic despierta por watchdog, entonces...
                {
                         if(x==0)                                // Pregunto por bandera
                            {
                               USART_activa_rx();                 // Llamo a la función que me habilita la recepción
                               setup_adc(ADC_CLOCK_INTERNAL );    // Tomará el dato contando el tiempo con el reloj interno
                               set_adc_channel(0);                // El canal de adquisición del dato es el RA0
                               delay_ms(10);                      // Un retardo para capturar bien el dato
                               value=read_adc();                  // Leo el dato
                               valord=(value*0.4);                // Multiplico el valor por 0.4 para hacer la equivalencia a 2V
                               portd=valord;                      // Lo mando al puerto D
                               setup_adc (ADC_OFF);               // Apago el conversor A/D
                               output_c(0);                                     // Limpio el puerto C
                               x=1;                               // Seteo la bandera
                            }
                        else if (x==1)                            // Si x es igual a 1
                            {
                                       USART_activa_rx();                           // Llamo a la función que me habilita la recepción
                                       dato=(value*5)/255;                          // Convierto el valor a decimal y lo guardo
                                       valorc=(4*dato)+4;                           // Para convertir a corriente
                                       //valorc=((dato/100)*1000);                  // Para convertir a corriente
                                       printf(lcd_putc,"\f");                       // Borro la pantalla LCD
                                       printf(lcd_putc,"Voltaje= %2.2g",dato);      // Mando a mostrar el valor del conversor en la LCD
                                       printf(lcd_putc,"\n");
                                       printf(lcd_putc,"Corriente= %2.2g",valorc);  // Mando a mostrar el valor del conversor en la LCD
                                       //printf("Puntero= V");
                                       delay_ms(10);
                                       if(puntero>250)                              // Si el puntero (indicador) pasa de 24 posiciones de memoria, no sigo escribiendo (reescribo)
                                          {
                                              puntero=0;                            // Si llega a 200 pues reseteo al puntero y reescribo la memoria
                                          }

                                                for(i = 0; i < 4; ++i)
                                                      {
                                                         write_eeprom(puntero + i, *((int8 *)(&dato) + i));
                                                      }
                                                puntero=puntero+4;
                                                for(i = 0; i < 4; ++i)
                                                      {
                                                         write_eeprom(puntero + i, *((int8 *)(&valorc) + i));
                                                      }
                                                 puntero=puntero+4;
                                                 delay_ms(3);                                          // Una demorita por si acaso
                                                 ;USART_activa_rx();                                                // Llamo a la función que me habilita la recepción
                                                 x=0;                                                         // Reseteo la bandera
                            }
                }
          }
}
//::::::::::::::::::::::::::::::::::::::::::::Dfinición de funciones:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

//::::::::::::::::::Función que abre el canal RS485 para transmitir::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

void USART_activa_tx(void)
{
  output_high(TX_485_ENABLE);                                 // Habilito la transmisión por el puerto (A5 en alto)
  output_low(RX_485_ENABLE);                                  // Habilito la recepción por el puerto   (A6 en bajo)
  delay_ms(5);                                                // Hago una demora
}

//::::::::::::::::::Función que abre el canal RS485 para recibir:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

void USART_activa_rx(void)
{
  delay_ms(5);                                                // Hago una demora
  output_high(RX_485_ENABLE);                                 // Habilito la transmisión por el puerto (A6 en alto)
  output_low(TX_485_ENABLE);                                  // Habilito la recepción por el puerto   (A5 en bajo)
  delay_ms(1);                                  // Hago otra demora
}