#include <18f4550.h>
#PRIORITY TIMER0,rda
#fuses NOPROTECT,NOCPD,NOLVP,NOWDT,XT,NOMCLR
#use fast_io (C)
#use fast_io (D)
#use fast_io (B)
#use delay(clock=4000000)
#byte RCON=0xFD0
#bit POR=RCON.1                                         // Bit de la bandera del Power On Reset
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)          // Habilita las funciones RS232, velocidad a 9600 baudios
#use I2C(master, sda=PIN_B0, scl=PIN_B1)                // Definicion I2C
#include <_ds1307.c>                                    // Libreria pcw de DS1307
#byte cmcon=0xfb4

//::::::::::::::::::::::::::::::DECLARACIÓN DE VARIABLES:::::::::::::::::::::::::::::
 int dato,periodo,resul=0,x=0,var1=0,var2=0,cont,resul2=0,resto=0,resul1=0,var_h,var_l,dia_H,dia_L,DIAS,r,i,
 mesH,mesL,MES,A_H,A_L,YEAR,hora_a,hora_b,hora,min_h,min_l,minutos,segundos=0,date,aux1=0,aux2=0,ban=0,indicador=0,puntero=1;

//::::::::::::::::::::::::::::::DECLARACIÓN DE FUNCIONES::::::::::::::::::::::::::::::
void pantalla_p(void);
void guardaeeprom(void);
void modiciut(void);
void prograreloj(void);
void verdatosmot(void);
void verdatoseeprom(void);
void menu (void);
void calcuciclo_u(void);
void tamaciclo_u(void);
void cambiarvelo(void);
void reloj(void);

//::::::::::::::::::::::DECLARACION DE LOS REGISTROS DS1307  EN EL PROGRAMA PRINCIPAL:::::::::::
byte day;                               // DIA
byte month;                             // MES
byte yr;                                // AÑO
byte hrs;                               // HORAS
byte min;                               // MINUTOS
byte sec;                               // SEGUNDOS
byte dow;                               // CONTROL dias de la semanas

//:::::::::::::::::::::::::::::::PROGRAMA PRINCIPAL:::::::::::::::::::::::::::::::::::
void main(void)
   {

      setup_adc(ADC_OFF);                             // Deshabilito el conversor A/D
      setup_adc_ports(NO_ANALOGS);                    // Deshabilito las entradas análogicas
      set_tris_d (0x00);                              // Configura puerto d como salida
      set_tris_c(0xFC);                               // Puerto C entradas
      output_d (0x00);                                // Limpio el puerto D
      port_b_pullups(TRUE);                           // Activo las pullups

       if(POR==0)                                     // Reset por POR
         {
            output_high(PIN_D1);                      // Enciendo un led de prueba
            delay_ms(1000);                           // Una demora para que se estabilicen los voltajes
            POR=1;                                    // Limpio la bandera del POR
            output_low(PIN_D1);                       // Enciendo un led de prueba
         }

//:::::::::::::::::::::::Configuracion del CCP1 para PWM mejorado:::::::::::::::::::::::::::::::::::::::

         setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_PWM_H_H); // Modo PWM para el CCP1
         setup_timer_2(T2_DIV_BY_16,periodo-1,4);     // Carga el periodo y TMR2
         set_pwm1_duty(resul);                        // Ciclo útil del PWM
         pantalla_p();                                // Muestro mensaje principal

while(true)
       {

       dato=getc();                    // Recojo el dato
       //printf("%c",dato);            // Muestro el dato
        if(dato=='n' || dato=='N')
        {
           menu();                   // Muestro el menú principal
        }
         if(dato=='A'|| dato=='a')
       {
         prograreloj();              // Rutina para programar el RTC
       }
         if(dato=='B'|| dato=='b')
       {
         modiciut();                 // Rutina para modificar el ciclo útil del motor
       }
         if(dato=='C'|| dato=='c')
       {
         guardaeeprom();             // Rutina que guarda los datos en la EEPROM
       }
         if(dato=='D'|| dato=='d')
       {
         verdatoseeprom();           // Rutina que muestra los datos guardados en la EEPROM
       }
          if(dato=='E'|| dato=='e')
       {
         verdatosmot();              // Rutina que muestra los datos del motor
       }
       }
   }
//:::::::::::::::::::::::::::::::FUNCIONES:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

//::::::::::::::::::::::::::::Función que permite ver el menú principal::::::::::::::::::::::::::::::
void pantalla_p(void)
{printf("\f");
 printf("**********************************************************************\n\r ");
 printf("*                        MICROPROCESADORES II                        *\n\r ");
 printf("*                           LABORATORIO 3                            *\n\r ");
 printf("*                                                                    *\n\r ");
 printf("*                                                                    *\n\r ");
 printf("*                                                                    *\n\r ");
 printf("*                                                 INTEGRANTES:       *\n\r ");
 printf("*                                                 PANICCIA MANUEL    *\n\r ");
 printf("*                                                 VARGAS MARLIN      *\n\r ");
 printf("*                                                                    *\n\r ");
 printf("----------------------------------------------------------------------\n\r ");
 printf("**********************************************************************\n\r ");
 printf("                                                                      \n\r ");
 printf("                                                                      \n\r ");
 printf("                                                                      \n\r ");
 printf("                                                                      \n\r ");
 printf("*                    PRESIONE (N) O (n) PARA CONTINUAR               *\n\r ");
 printf("*                                                                    *\n\r ");
 printf("*                                                                    *\n\r ");
}

//::::::::::::::::::::::::::::Función que permite ver el memú de opciones::::::::::::::::::::::::::::::
void menu (void)
{
       printf("\f");                                                                    // Limpio pantalla
       printf("****************************************** \n\r");
       printf("             ESCOJA UNA OPCION             \n\r");
       printf("(A)PROGRAMAR RELOJ                         \n\r");
       printf("(B)MODIFICAR CICLO UTIL                    \n\r");
       printf("(C)GRABAR DATOS EN LA EEPROM               \n\r");
       printf("(D)VER DATOS DE LA EEPROM                  \n\r");
       printf("(E)VER DATOS DEL MOTOR                     \n\r");
       printf("****************************************** \n\r");
}

//::::::::::::::::::::::::::::Función que permite guardar los datos ee la EEPROM::::::::::::::::::::::::::
void guardaeeprom(void)
{
      printf("\f");
      printf("* ----------->(u_u) GUARDAR DATOS EN LA EEPROM (u_u)<-----------* \n\r");
      if(ban==0)
         {
            i2c_start();                                                // Inicializo la memoria
            i2c_write(0xA0);                                            // Coloco la memoria en modo escritura
            i2c_write(0x00);                                            // Mando la parte alta de la memoria
            i2c_write(0x00);                                            // Escribo a partir de la dirección 00 de la memoria
            i2c_write(1);                                               // Escribo un 1 para inicializar al contador que está en la posición 0 de la memoria
            i2c_stop();                                                 // Detengo la operación de escritura
            ban=1;                                                      // Bandera que me inicializa a la memoria en la posición 00 de la memoria
            delay_ms(2);                                                // Una demorita por si acaso
         }

            i2c_start();                                                // Inicializo la memoria
            i2c_write(0xA0);                                            // Coloco la memoria en modo escritura
            i2c_write(0x00);                                            // Mando la parte alta de la memoria
            i2c_write(0x00);                                            // Escribo a partir de la dirección 00 de la memoria
            i2c_start();                                                // Inicializo la memoria
            i2c_write(0xA1);                                            // Coloco la memoria en modo lectura
            indicador=i2c_read(0);                                      // Le mando a indicador el valor de puntero (puntero está en la dirección 00 de la memoria)
            i2c_stop();                                                 // Detengo la operación de lectura
            printf("\f Puntero: %02d \n\n\r",indicador);                // Imprimo el valor de puntero
            delay_ms(3);                                                // Una demorita por si acaso
            if(indicador>160)                                            // Si el puntero (indicador) pasa de 24 posiciones de memoria, no sigo escribiendo (reescribo)
                {
                puntero=1;                                              // Si llega a 160 pues reseteo al puntero y reescribo la memoria
                }
            ds1307_get_date(date,month,yr,dow);                         // Capturo los datos de fecha del RTC
            ds1307_get_time(hrs,min,sec);                               // Capturo los datos de tiempo del RTC
            i2c_start();                                                // Inicializo la memoria
            i2c_write(0xA0);                                            // Coloco la memoria en modo escritura
            i2c_write(0x00);                                            // Escribo a partir de la dirección 00 de la memoria
            i2c_write(puntero);                                         // Escribo el valor de puntero en la memoria
            i2c_write(yr);                                              // Escribo el valor del año en la memoria
            i2c_write(month);                                           // Escribo el valor del mes en la memoria
            i2c_write(date);                                            // Escribo el valor de la fecha en la memoria
            i2c_write(hrs);                                             // Escribo el valor de la hora en la memoria
            i2c_write(min);                                             // Escribo el valor de los minutos en la memoria
            i2c_write(sec);                                             // Escribo el valor de los segundos en la memoria
            i2c_write(var1);                                            // Escribo el primer digito de la velocidad
            i2c_write(var2);                                            // Escribo el segundo digito de la velocidad
            i2c_stop();                                                 // Detengo la operación de escritura
            puntero=puntero+8;                                          // Incremento puntero
            printf("\n        *********Los datos han sido guardados************        "); // Mando un mensajito de escritura de datos
            delay_ms(3);                                                // Una demorita por si acaso
            i2c_start();                                                // Inicializo la memoria
            i2c_write(0xA0);                                            // Coloco la memoria en modo escritura
            i2c_write(0x00);                                            // Mando la parte alta de la memoria
            i2c_write(0x00);                                            // Escribo a partir de la dirección 00 de la memoria
            i2c_write(puntero);                                         // Escribo y guardo el nuevo valor de puntero
            i2c_stop();                                                 // Detengo la operación de escritura
            delay_ms(2000);                                             // Una demorita por si acaso
            printf("\f");                                               // Limpio pantalla
            printf(" *************************************************************\n\r ");
            printf("*                                                           *\n\r ");
            printf("*                                                           *\n\r ");
            printf("             PRESIONE (N o n) PARA IR AL MENU               *\n\r ");     // Vuelvo al menú
            printf("*                                                           *\n\r ");
            printf("*                                                           *\n\r ");
            printf("*************************************************************\n\r ");
}

//::::::::::::::::::::::::::::Función que permite modificar el ciclo útil del motor::::::::::::::::::::::::
void modiciut(void)
{
      printf("\f");                                                                       // Limpio pantalla
      printf(" *----------->(u_u) MODIFICAR CICLO UTIL (u_u)<-----------*\n\r ");
      printf("*                                                        *\n\r ");
      printf("*                INTRODUZCA EL CICLO UTIL                *\n\r ");
      printf("*                                                        *\n\r ");
      printf("                                                          \n\r ");
      delay_ms(1000);
      dato=getc();                                           // Recojo el dato
      if(dato=='1'|| dato=='2'|| dato=='3'|| dato=='4'|| dato=='5'|| dato=='6'|| dato=='7'|| dato=='8'|| dato=='9'|| dato=='0')
      {
        dato=getc();                                         // Capturo el primer dato
        cont=0;                                              // Para capturar los dos digitos que modifican el ciclo útil del motor
        if(cont==0)
        {
           if (x==0)
            {
               output_high(PIN_D2);                           // Enciendo un led de prueba
               var1=dato;                                     // Asigno a Var1 el primer valor en decimal introducido por teclado
               aux1=dato;
               var1=var1 - 0x30;                              // Le resto 30 a lo que traiga dato desde el teclado de la pc para pasar de ASCII a BCD
               printf("                           %c",dato);  // Mando a mostrar lo que trajo desde el teclado de la pc
               x=1;                                           // Modifico la bandera para que el segundo número introducido por teclado sea guardado en var2
               cont=0;                                        // Porque todavia me falta guardar el segundo digito
            }
           if (x==1)
            {
               dato=getc();                                   // Capturo el segundo dato
               var2=dato;                                     // Asigno a var2 el segundo valor decimal introducido por teclado
               aux2=dato;
               var2=var2 - 0x30;                              // Le resto 30 a lo que traiga dato desde el teclado de la pc para pasar de ASCII a BCD
               printf("%c",dato);                             // Mando a mostrar lo que trajo desde el teclado de la pc
               x=0;                                           // Modifico la bandera para que el primer número introducido por teclado sea guardado en var1
               cont=1;                                        // Ya guarde el segundo digito, me salgo del ciclo
               output_high(PIN_D0);                           // Enciendo un led de prueba
            }
        }
        delay_ms(1000);                                       // Una demora para no apagar tan rapido los leds
        output_low(PIN_D2);                                   // Apago el led de prueba
        output_low(PIN_D0);                                   // Apago el led de prueba
        tamaciclo_u();                                        // Calculo del ciclo útil que se introdujo por teclado
        calcuciclo_u();                                       // Calculo el porcentaje del ciclo útil
        delay_ms(1000);                                       // Una demora para no borrar tan rapido los datos de ciclo útil
        printf("\f");                                         // Limpio pantalla
        printf(" *************************************************************\n\r ");
        printf("*                                                           *\n\r ");
        printf("*                                                           *\n\r ");
        printf("  PRESIONE (N o n) PARA IR AL MENU O (B o b) PARA MODIFICAR  \n\r ");     // Vuelvo al menú
        printf("*            NUEVAMENTE LA VELOCIDAD DEL MOTOR              *\n\r ");
        printf("*                                                           *\n\r ");
        printf("*************************************************************\n\r ");
       }
 }

//::::::::::::::::::::::::::::Función que permite programar el RTC:::::::::::::::::::::::::::::::
void prograreloj(void)
{
      printf("\f");                                           // Limpio pantalla
      printf(" *  ----------->(u_u) PROGRAMAR RELOJ (u_u)<-----------  *\n\r ");
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      delay_ms(1000);
      ds1307_init(DS1307_OUT_ON_DISABLED_HIHG | DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);
      printf("*********************************************\n\r");
      printf("       CONFIGURACION DE FECHA Y HORA         \n\r");
      printf("*********************************************\n\r");
      printf("INGRESE EL DIA DEL MES:                      \n\r");
      dia_H=getc();
      dia_L=getc();
      var_h=dia_H-0x30;
      var_l=dia_L-0x30;
      DIAS=(var_h*10)+var_l;
      printf("DIA: %02d                      \n\r",DIAS);
      delay_ms(1000);
      date=1;
      printf("INGRESE EL MES:                      \n\r");
      mesH=getc();
      mesL=getc();
      var_h=mesH-0x30;
      var_l=mesL-0x30;
      MES=(var_h*10)+var_l;
      printf("MES: %02d                      \n\r",MES);
      delay_ms(900);
      printf("INGRESE EL AÑO:                      \n\r");
      A_H=getc();
      A_L=getc();
      var_h=A_H-0x30;
      var_l=A_L-0x30;
      YEAR=(var_h*10)+var_l;
      printf("AÑO: %02d                      \n\r",YEAR);
      delay_ms(900);
      printf("INGRESE LA HORA:                      \n\r");
      hora_a=getc();
      hora_b=getc();
      var_h=hora_a-0x30;
      var_l=hora_b-0x30;
      hora=(var_h*10)+var_l;
      printf("HORA: %02d                      \n\r",hora);
      delay_ms(900);
      printf("INGRESE LOS MINUTOS:                      \n\r");
      min_h=getc();
      min_l=getc();
      var_h=min_h-0x30;
      var_l=min_l-0x30;
      minutos=(var_h*10)+var_l;
      printf("MINUTOS: %02d                      \n\r",minutos);
      delay_ms(900);
      ds1307_set_date_time(DIAS,mes,YEAR,date,hora,minutos,segundos);
      ds1307_get_date(day,month,yr,dow);
      ds1307_get_time(hrs,min,sec);
      printf("                                                                      \n\r ");
      printf("                                                                      \n\r ");
      printf("                                                            \n\r ");
      printf("                           %02d/%02d/%02d|%02d:%02d:%02d|   \n\r",day,month,yr,hrs,min,sec);
      delay_ms(2500);
      printf("\f");                                         // Limpio pantalla
      printf(" *************************************************************\n\r ");
      printf("*                                                           *\n\r ");
      printf("*                                                           *\n\r ");
      printf("  --------> PRESIONE (N o n) PARA REGRESAR AL MENU <-------- \n\r ");     // Vuelvo al menú
      printf("*                                                           *\n\r ");
      printf("*                                                           *\n\r ");
      printf("*************************************************************\n\r ");
}

//::::::::::::::::::::::::::::Función que permite ver los datos del motor::::::::::::::::::::::::::
void verdatosmot(void)
{
      printf("\f");                                                                     // Limpio pantalla
      printf(" *  ----------->(u_u) DATOS DEL MOTOR (u_u)<-----------  *\n\r ");
      printf("                                                          \n\r ");
      printf("    FECHA              HORA              VELOCIDAD        \n\r ");
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      ds1307_get_date(day,month,yr,dow);
      ds1307_get_time(hrs,min,sec);
      printf("   %02d/%02d/%02d           %02d:%02d:%02d               %c%c       Porciento  \n\r",day,month,yr,hrs,min,sec,aux1,aux2);
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      printf("*************************************************************\n\r ");
      printf("*                                                           *\n\r ");
      printf("*                                                           *\n\r ");
      printf("  PRESIONE (N o n) PARA IR AL MENU O (E o e) PARA ACTUALIZAR \n\r ");     // Vuelvo al menú
      printf("*                    LOS DATOS DEL MOTOR                    *\n\r ");
      printf("*                                                           *\n\r ");
      printf("*************************************************************\n\r ");
}

//::::::::::::::::::::::::::::Función que permite ver los datos de la EEPROM::::::::::::::::::::::::
void verdatoseeprom(void)
{
      printf("\f");
      printf("*  ----------->(u_u) VER DATOS DE LA EEPROM (u_u)<-----------  *\n\r");
      i2c_start();                                                  // Inicializo la memoria
      i2c_write(0xA0);                                              // Coloco a la memoria en modo escritura
      i2c_write(0x00);                                              // Mando la parte baja de la memoria
      i2c_write(0x00);                                              // Empiezo a escribir a partir de la dirección 00 de la memoria
      i2c_start();                                                  // Inicializo la memoria
      i2c_write(0xA1);                                              // Coloco a la memoria en modo lectura
      indicador=i2c_read(0);                                        // Leo el valor de indicador
      i2c_stop();                                                   // Detengo la lectura de la memoria
      printf("\f Nº de registros : %02d  \n\n\r  ",indicador);      // Verifico cuantos registros fueron escritos
      printf("\f");                                                 // Limpio pantalla
      printf(" *  ----------->(u_u) DATOS DEL MOTOR (u_u)<-----------  *\n\r ");
      printf("                                                          \n\r ");
      printf("    FECHA              HORA              VELOCIDAD        \n\r ");
      printf("                                                          \n\r ");
      printf("                                                          \n\r ");
      delay_ms(20);                                                 // Una demorita por si acaso
      i2c_start();                                                  // Inicializo la memoria
      i2c_write(0xA0);                                              // Coloco a la memoria en modo escritura
      i2c_write(0x00);                                              // Mando la parte baja de la memoria
      i2c_write(0x01);                                              // Empiezo a escribir a partir de la dirección 01 de la memoria porque en la 00 está el puntero
      i2c_start();                                                  // Inicializo la memoria
      i2c_write(0xA1);                                              // Coloco a la memoria en modo lectura
       for(i=1;i<indicador;i++)                                     // Un ciclo para que vaya leyendo dato por dato
        {
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Año)
          printf(" %02d/",r);                                       // Imprimo el año
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Dia del mes)
          printf("%02d/",r);                                        // Imprimo el mes
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Mes)
          printf("%02d",r);                                         // Imprimo el dia del mes
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Hora)
          printf("             %02d:",r);                           // Imprimo las horas
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Minuto)
          printf("%02d:",r);                                        // Imprimo los minutos
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Segundo)
          printf("%02d",r);                                         // Imprimo los segundos
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Var1)
          printf("            %01d",r);                             // Imprimo var1
          r=i2c_read();                                             // Recojo los datos que están en cada posición de memoria (Var2)
          printf("%01d     Porciento\n\r",r);                       // Imprimo var2
          i=i+7;
        }
       i2c_stop();                                                  // Detengo la operación de lectura
       delay_ms(2000);                                              // Una demorita por si acaso
       printf("                                                             \n\r ");
       printf("                                                             \n\r ");
       printf(" ************************************************************\n\r ");
       printf("*                                                           *\n\r ");
       printf("*                                                           *\n\r ");
       printf("             PRESIONE (N o n) PARA IR AL MENU               *\n\r ");     // Vuelvo al menú
       printf("*                                                           *\n\r ");
       printf("*                                                           *\n\r ");
       printf("*************************************************************\n\r ");
}


//::::::::::::::::::::::::::::Función que me extrae el ciclo útil desde el teclado::::::::::::::::::::
void tamaciclo_u(void)
{
         resul1=var1*10;                        // Multiplico por diez para llevarlo a decenas
         resul2=resul1+var2;                    // Sumo las decenas con la unidad, para que me de el total del ciclo útil
}
//:::::::::::::::::::::::::::::Función que me calcula el ciclo útil de la PWM mejorada:::::::::::::::
void calcuciclo_u(void)
{
   if(resul2<=50)                               // Si el número marcado es menor a 50
      {
         resul=resul2*2;                        // multiplico el número marcado desde el teclado por 2
         cambiarvelo();                         // Llamo a la función que me modifica el ciclo útil
      }
   else
      {
         resto= resul2 - 50;                    // Resto el número que meti por teclado menos 50 (mitad del 100%)
         resul=resto*3 +100;                    // Multiplico el resto por 3, para que pueda llegar al 90% del ciclo útil, y a eso le sumo 100
         cambiarvelo();                         // Llamo a la función que me modifica el ciclo útil
      }
}

//::::::::::::::::::::::::::Función que cambia la velocidad del motor:::::::::::::::::::::::::::::::::::
void cambiarvelo(void)
{
          SET_PWM1_DUTY(resul);                 // Cambio el ciclo útil de la PWM
}