///////////////////////////////////////
// Definiciones de configuración
///////////////////////////////////////

#include <18f4550.h>

///////////////////////////////////////
// Fuses y ajuste de Clock
///////////////////////////////////////

#fuses HSPLL,NOMCLR,PUT,BROWNOUT,BORV43,NOWDT,NOPROTECT,NOLVP
#fuses NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,CCP2B3
#use delay(clock=48000000)

///////////////////////////////////////
// Canal de Comunicación : usart
///////////////////////////////////////

#define TTL_TX PIN_C6
#define TTL_RX PIN_C7

#use rs232(baud=115200, xmit=TTL_TX, rcv=TTL_RX)

///////////////////////////////////////
// Constantes
///////////////////////////////////////

int const lenbuff=32; // Longitud máxima del buffer

///////////////////////////////////////
// RAM
///////////////////////////////////////

int  xbuff=0x00;     // Índice: siguiente char en cbuff
char cbuff[lenbuff]; // Buffer de recepción
int1 flagcommand=0;  // Flag para comando disponible

///////////////////////////////////////
// Funciones de Buffer
///////////////////////////////////////

// Echo selectivo ----------------------

void echo_sel(char c){

   switch(c){
      case 0x0D:     // Si he pulsado la tecla [Intro]
         printf("\r\n[Ent]\r\n");
         break;
      case 0x08:     // Si he pulsado la tecla [Retroceso]
         printf("\r\n[Del]\r\n>%s",cbuff);
         break;
      case 0x1B:     // Si he pulsado la tecla [Escape]
         printf("\r\n[Esc]\r\n>");
         break;
      default:       // Echo de cualquier otro caracter
         putc(c);
   }
}

// Inicia a \0 cbuff -------------------

void init_cbuff(void){
   int i;

   for(i=0;i<lenbuff;i++){// Bucle que pone a 0 todos los
      cbuff[i]=0x00;      // caracteres en el buffer
   }
   xbuff=0x00;            // Inicializo el indice de siguiente caracter
}

// Añade a cbuff -----------------------

void add_2_cbuff(char c){

      switch(c){
         case 0x0D:  // Enter -> Habilita Flag para procesar comando
            flagcommand=1;
            break;
         case 0x08:  // Del   -> Borra último caracter del Buffer
            if(xbuff>0) cbuff[--xbuff]=0x00;
            break;
         case 0x01B: // Esc   -> Borra el Buffer completamente
            init_cbuff();
            break;
         default:    // Añade caracter recibido al Buffer
            cbuff[xbuff++]=c;
      }
}

///////////////////////////////////////
// Procesador de Comandos
///////////////////////////////////////

void commad_menu(void){

   printf("\r\nTyP_Serie_TTL\r\n");
   printf("Método : Recibiendo sobre Buffer\r\n\n");
   printf("[Enter]  Procesa el buffer recibido.\r\n");
   printf("[Escape] Borra todo el buffer.\r\n");
   printf("[Delete] Borra último carácter del buffer.\r\n");
   printf("\r\n\r\n>");

}

void commad_process(void){

   int i;
   char cmd[lenbuff];        // Comando

   flagcommand=0;            // Desactivo flag de comando pendiente.
   printf("Procesando ...\r\n");

   strcpy(cmd,cbuff);        // Lo copio para procesarlo
   printf("Rec. Buffer <%s>\r\n",cmd); // ... y lo muestro

   init_cbuff();             // Borro buffer.
   printf("Procesado.\r\n\r\n>"); // Monitorizo procesado.
}

///////////////////////////////////////
// INTERRUPCIONES : RDA Recepción USART
///////////////////////////////////////

#int_rda
void serial_isr() {          // Interrupción recepción serie USART

   char rcvchar=0x00;        // último caracter recibido

   if(kbhit()){              // Si hay algo pendiente de recibir ...
      rcvchar=getc();        // lo descargo y ...
      add_2_cbuff(rcvchar);  // lo añado al buffer y ...
      echo_sel(rcvchar);     // hago eco selectivo (si procede).
   }
}

///////////////////////////////////////
// MAIN
///////////////////////////////////////

void main() {

   delay_ms(2000);           // Espero a estabilizar antes de actuar

   // HARD ///////////
   output_low(PIN_E2);
   output_low(PIN_C0);
   output_low(PIN_D7);
   output_low(PIN_E1);
   output_low(PIN_E0);
   output_high(PIN_D1);
   output_high(PIN_D0);
   delay_ms(110);
   output_low(PIN_D0);
   ///////////////////

   commad_menu();
   init_cbuff();               // Borra buffer al inicio
   enable_interrupts(int_rda); // Habilita Interrupción RDA
   enable_interrupts(global);  // Habilita interrupciones

   do {
      if(flagcommand) commad_process(); // Hay algo pendiente de procesar y lo procesa.
   } while (TRUE);

}

///////////////////////////////////////
// Fin de programa
///////////////////////////////////////

