////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Librería para el control del controlador gráfico PICASO[SGC] a través de comunicación serial, no es necesario que se use el UART//
//hardware ya que no utiliza interrupciones. Escrita por Andrés Torti. Esta librería es de libre distribución pero está prohibida //
//su venta. Cualquier modificación es aceptada pero se debe mantener este encabezado al comienzo de la librería. Muchas Gracias.  //
//Puede controlar el LCD: uLCD-32PT (SGC) de 4D System                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Autor                    Versión      Fecha               Cambios                                                               //
//                                                                                                                                //
//Andres                   v1.0         21/01/11            Creacion de la librería                                               //
//Andres                   v1.1         24/01/11            Corregidos errores en escritura y lectura de archivos FAT             //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*

                                   GND  RX  TX  VCC
                                    |   |   |   |
                              -----------------------------------------------------------
                            --|0,0             |                                   320,0|    Modo LANDSCAPE
                       MMC |  |                |                                        |
                           |  |                |                                        |
                           |  |                |                                        |
                            --|                |                                        |
                              |<---------------|----------X---------------------------->|
                              |                Y                                        |
                              |                |                                        |
                              |                |       uLCD-32PT                        |
                              |                |       65K Colores                      |
                              |                |       LCD TFT                          |
                              |                |                                        |
                              |                |                                        |
                              |0,240           |                                 320,240|
                              -----------------------------------------------------------
LCD               PIC

GND      ->       GND
RX       ->       TX
TX       ->       RX
*/
#ifndef ULCD32PT
#define ULCD32PT

//Respuestas
#define ACK 0x06
#define NAK 0x15

//Audio
#define STOP 2
#define PAUSE 3
#define RESUME 4
#define LOOP 5

#define MUTE 0
#define MUTEOFF 1
#define VOL_DOWN 0x03
#define VOL_DOWN8 0x01
#define VOL_UP 0xFD
#define VOL_UP8 0xFE

//Modo de dibujo
#define LLENO 0
#define VACIO 1

//Botones
#define PRESS 0
#define NOPRESS 1

//Texto
#define TRANSPARENTE 0
#define OPACO 1

//General
#define ON 1
#define OFF 0

//USART
#define BAUD_110 0x00
#define BAUD_300 0x01
#define BAUD_600 0x02
#define BAUD_1K2 0x03
#define BAUD_2K4 0x04
#define BAUD_4K8 0x05
#define BAUD_9K6 0x06
#define BAUD_14K4 0x07
#define BAUD_19K2 0x08
#define BAUD_31K25 0x09
#define BAUD_38K4 0x0A
#define BAUD_56K 0x0B
#define BAUD_115K2 0x0D
#define BAUD_128K 0x0E
#define BAUD_256K 0x0F

//Texto
#define F5x7 0x00
#define F8x8 0x01
#define F8x12 0x02
#define F12x16 0x03

INT16 cursor_x = 0;        //cursores para coordenadas x,y usados en algunas funciones
INT16 cursor_y = 0;
INT16 text_color;          //características texto
INT fuente = 0;
INT modo_texto = 0;

//Si la función no devuelve un dato extra, como por ejemplo "lcd_read_pin" que devuelve el estado del PIN, la misma devolvera
//en un INT las respuesta del LCD que será un ACK (0x06) o un NAK (0x15) dependiendo de si la funcion tuvo efecto o no.
//Puede haber excepciones.

//Comandos generales
VOID lcd4d_init (VOID);
INT lcd_fat (INT modo);
INT lcd_image_format (INT1 modo);
INT lcd_orientation (INT modo);
INT lcd_mode (INT1 modo);
INT lcd_contrast (INT valor);
INT lcd_display (INT1 mode);
INT lcd_backlight (INT1 modo);
INT lcd_clear (VOID);
INT lcd_volume (INT valor);
INT lcd_sleep (INT modo, INT tiempo);
INT lcd_background (INT16 color);
INT lcd_set_baud (INT baud);
VOID lcd_get_info (INT modo,INT *device_type,INT *hard_ver, INT *soft_ver, INT16 *h_res, INT16 *v_res);

//Pines y bus
INT lcd_write_pin (INT pin, INT valor);
INT lcd_read_pin (INT pin);
INT read_bus (VOID);
INT write_bus (INT valor);

//Touchscreen
INT get_touch (VOID);
INT lcd_touch (INT modo);
INT wait_touch (INT16 time);
INT lcd_touch_region (INT16 x1, INT16 y1, INT16 x2, INT16 y2);
VOID wait_touch_press (INT16 *x, INT16 *y);
VOID wait_touch_release (VOID);
INT get_touch_status (VOID);

//Funciones gráficas
INT lcd_fill (INT1 modo);
INT lcd_circle (INT16 x, INT16 y, INT16 radio, INT16 color, INT1 fill);
INT lcd_triangle (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 x3, INT16 y3, INT16 color, INT1 fill);
INT lcd_line (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 color);
INT lcd_polygon(INT vertices, INT16 *xptr, INT16 *yptr, INT16 color); 
INT lcd_rectangle (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 color, INT1 fill);
INT lcd_elipse (INT16 x, INT16 y, INT16 rx, INT16 ry, INT16 color, INT1 fill);
INT lcd_pixel (INT16 x, INT16 y, INT16 color);
INT16 lcd_read_pixel (INT16 x, INT16 y);
INT lcd_copy_paste (INT16 xs, INT16 ys, INT16 xd, INT16 yd, INT16 ancho, INT16 alto);
INT lcd_replace_color (INT x1, INT y1, INT x2, INT y2, INT16 old_color, INT16 new_color);

//Texto, letras
INT lcd_font (INT tipo);
INT lcd_text_mode (INT1 modo);
INT lcd_char_text (CHAR c, INT x, INT y, INT16 color, INT font, INT modo);
INT lcd_char_graphic (CHAR c, INT16 x, INT16 y, INT16 color, INT ancho, INT alto, INT modo);
INT lcd_text_string (INT x, INT y, INT font, INT16 color, CHAR *textptr, INT modo);
INT lcd_graphic_string (INT16 x, INT16 y, INT font, INT16 color, INT ancho, INT alto, CHAR *textptr, INT modo); 
INT lcd_button (INT estado, INT16 x, INT16 y, INT16 butcolor, INT font, INT16 textcolor, INT ancho, INT alto, CHAR *textptr);

VOID lcd_writting_mode (INT16 x, INT16 y, INT16 color, INT font, INT modo);
VOID lcd_write_text (CHAR c);
VOID lcd_xy (INT16 x, INT16 y);
VOID lcd_color (INT16 color);
VOID text_font (INT font);
VOID text_mode (INT mode);

//[RAW] Memory Card
INT lcd_mmc_init (VOID);
INT lcd_mmc_pointer (INT32 adress);
INT lcd_mmc_read_byte (VOID);
INT lcd_mmc_write_byte (INT data);
VOID lcd_mmc_read_sector (INT32 sector, INT *data);
INT lcd_mmc_write_sector (INT32 sector, INT *data);
INT lcd_copy_mmc (INT16 x, INT16 y, INT16 ancho, INT16 alto, INT32 sector);
INT lcd_img_mmc (INT16 x, INT16 y, INT32 sector);
INT lcd_obj_mmc (INT32 adress);
INT lcd_video (INT16 x, INT16 y, INT delay, INT32 sector);

//[FAT/DOS] Memory Card
INT lcd_mmc_init (VOID);
INT lcd_mmc_read_file (INT handshaking, CHAR *filename, INT32 *size, INT *data);
INT lcd_mmc_write_file (INT handshaking, INT append, CHAR *filename, INT32 filesize, INT *data);
INT lcd_mmc_delete (CHAR *filename); 
INT lcd_copy_mmc_fat (INT16 x, INT16 y, INT16 ancho, INT16 alto, CHAR *filename); 
INT lcd_img_fat (CHAR *filename, INT16 x, INT16 y, INT32 sector);
INT lcd_play_wav (INT modo, CHAR *filename);
VOID mmc_get_size (CHAR *filename, INT32 *size);

//Scripts
VOID run_script_fat (CHAR *filename);
VOID run_script_raw (INT32 adress);
VOID lcd_script_delay (INT16 delay);
VOID lcd_end_script (VOID);

//Termina el script que se esta ejecutando actualmente
VOID lcd_end_script (VOID){
   putc(0x0C);
}

//Un delay que se coloca entre cada acción del script, delay es una variable de 16bits que representa el retardo en mS
VOID lcd_script_delay (INT16 delay){
   putc(0x07);
   putc(make8(delay,1));
   putc(make8(delay,0));
}

//Ejecuta un Script en la memory card con formato RAW en la direccion especificada
/*
A sample script program inside the memory card:
Address     Command                                   Comment
00000000       45                                     Erase Screen
00000001       43 00 64 00 32 00 14 00 1F             Draw Circle
0000000A       07 03 E8                               Delay(1second)
0000000D       72 00 00 00 00 00 3C 00 3C 07 E0       Draw Rectangle
00000018       40 56 00 00 00 00 00 46 00 32 10       Play video from card
               0A 02 5F 00 10 00
00000029       0B 00 00 00 00                         Goto Address 00000000
*/
VOID run_script_raw (INT32 adress){
   putc('@');
   putc('p');
   putc(make8(adress,3));  //parte alta de la direccion
   putc(make8(adress,2));  //parte media de la direccion
   putc(make8(adress,1));  //parte baja de la direccion
   putc(make8(adress,0));  //parte mas baja de la direccion
}
      
//Ejecuta un Script en la memory card formateada con FAT (FAT16) con el nombre en la matriz *filename
VOID run_script_fat (CHAR *filename){
   putc('@');     //comando 1
   putc('p');     //comando 2
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*filename);                      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //fin nombre de archivo
}

//Coloca en la variable donde apunta *size el tamaño del archivo que se encuentra en la matriz *filename
//El nombre del archivo debe sre entre 1 y 12 caracteres terminado en '\0'
VOID mmc_get_size (CHAR *filename, INT32 *size){
int a,b,c,d;
   putc('@');     //comando 1
   putc('a');     //comando 2
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*filename);                      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //indico que termino el nombre del archivo
   a = getc();    //recibo los 4 bytes del tamaño del archivo
   b = getc();
   c = getc();
   d = getc();
   *size = make32(a,b,c,d);      //uno todos los bytes en un INT32 para tener el tamaño del archivo en bytes
   putc(0x15);    //termino transmicion
}

//Reproduce un archivo .WAV de la tarjeta de memoria con el nombre de archivo especificado
//Modo puede ser:
//modo = 0 = retorna de la funcion cuando se completa la reproduccion
//modo = 1 = retorna inmediatamente
//modo = 2 = STOP
//modo = 3 = PAUSE
//modo = 4 = RESUME
//modo = 5 = reproduce en un bucle hasta que se indique STOP
//El nombre del archivo debe terminar con '\0'
INT lcd_play_wav (INT modo, CHAR *filename){
   putc('@');     //comando 1
   putc(0x6C);    //comando 2
   putc(modo);    //modo de reproduccion
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del nombre del archivo hasta llegar a '\0'
         putc(*filename);      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //termina nombre de archivo
   return getc();
}

//Muestra una imagen guardada en la tarjeta de memoria con su esquina superior izquierda en x,y
//con el nombre de archivo definido en el sector que se especifica
//Nota del datasheet:
/*This command can also be used to display multimedia objects in the GCI file, created from
the Graphics Composer. The video parameters such as width, height and colour-mode are
built into the GCI file; they don’t need to be specified by the host controller. All you need is
GCI filename which is loaded to the SD card, and the pointer to the multimedia object which
can be found from the .DAT file created by the Graphics Composer along with the GCI file.*/
INT lcd_img_fat (CHAR *filename, INT16 x, INT16 y, INT32 sector){
   putc('@');     //comando 1
   putc('m');     //comando 2
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del nombre del archivo hasta llegar a '\0'
         putc(*filename);      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //termina nombre de archivo
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
   putc(make8(sector,0));  //parte mas baja del sector
   return getc();
}  

//Copia una seccion de la pantalla que inicia en x,y con un alto y ancho definido a la memory card
//con el nombre que se indica en la matriz filename
INT lcd_copy_mmc_fat (INT16 x, INT16 y, INT16 ancho, INT16 alto, CHAR *filename){
   putc('@');     //comando 1
   putc('c');     //comando 2
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(ancho,1));  //msb del ancho
   putc(make8(ancho,0));  //lsb del ancho
   putc(make8(alto,1));   //msb del alto
   putc(make8(alto,0));   //lsb del alto
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del nombre del archivo hasta llegar a '\0'
         putc(*filename);      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //termina nombre de archivo
   return getc();
}

//Borra el archivo que tenga el nombre que paso a la funcion en una matriz, el nombre debe ser entre 1 y 12 caracteres
//se asume un '.' entre los caracteres 8 y 9, el nombre en la matriz debe terminar con un 0x00
INT lcd_mmc_delete (CHAR *filename){
   putc('@');     //comando 1
   putc('e');     //comando 2
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del nombre del archivo hasta llegar a '\0'
         putc(*filename);      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //termina nombre de archivo
   return getc();
}
   
//Escribe un archivo con la infromacion de la matriz data, se debe especificar el tamaño en filesize en bytes
//handshaking es la cantidad de de bytes que el PIC envía antes de recibir un ACK del LCD
//filename es el nombre con el que quiere que se guarde el archivo entre 1 y 12 caracteres, se asume un '.' entre los
//caracteres 8 y 9, debe terminar en '\0'
//Si append = 0 el archivo se crea o sobreescribe
//Si append = 1 el archivo se añadira o se creara si no existe
INT lcd_mmc_write_file (INT handshaking, INT append, CHAR *filename, INT32 filesize, INT *data){
int n,ready;
int32 nbyte;
   putc('@');     //comando 1
   putc('t');     //comando 2
   putc(handshaking | append);      //operacion logica OR para definir el modo handshaking y append
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del nombre del archivo hasta llegar a '\0'
         putc(*filename);      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //termino texto
   putc(make8(filesize,3));  //parte alta de filesize
   putc(make8(filesize,2));  //parte media de filesize
   putc(make8(filesize,1));  //parte baja de filesize
   putc(make8(filesize,0));  //parte mas baja de filesize
   nbyte = filesize;
   while(getc() != 0x06);    //espero el ACK
IF(handshaking != 0){  //si el handshaking no es 0
    WHILE(!ready){           //envio todo los bytes
      FOR(n=0;n<=handshaking;++n,++data,--nbyte){
         putc(*data);   //envio tantas veces el dato como handshaking y luego espero un ACK del LCD
         if(!nbyte){ ready=1; break; }  //si estoy en el último byte por transmitir, salgo                                                
      }                                 //e indico que la transmicion termino poniendo ready a 1;
      ++data; --nbyte;
      while(getc() != 0x06);    //espero el ACK
    }
return getc();      //retorno el ultimo ACK que indica el fin de la transmicion
}
ELSE{      //si el handshaking es 0 no se envian ACK se recibe todo de una vez
   putc(*data);
   ++data; --nbyte;
   if(*data==0x06 && !nbyte){ break; } //si data es un ACK y estoy en el último paquete de datos por recibir, salgo
 }
}

//Lee un archivo localizado en la tarjeta de memoria con el nombre que se especifica en la matriz "file_name"
//handshaking indica la cantidad de veces que el PIC debe enviar un ACK para pedir mas datos
//handshaking = 0 = no ACK recomendado para archivos menores a 512bytes
//handshaking = 1 = ACK por cada byte recibido
//handshaking = 2 = ACK por cada dos bytes recibidos
//y asi... el máximo es 50
//El filename es de 1 a 12 caracteres con un '.' que se asume entre el caracter 8 y 9 debe terminar con un '\0'
//size es una variable que pasa el usuario y alli la funcion guarda el tamaño del archivo
//data es la matriz donde se guarda el archivo recibido
INT lcd_mmc_read_file (INT handshaking, CHAR *filename, INT32 *size, INT *data){
int a,b,c,d,n,ready;
int32 nbyte;
ready = 0;
   putc('@');     //comando 1
   putc('a');     //comando 2
   putc(handshaking);
      FOR(;*filename != '\0'; ++filename){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*filename);                      //voy colocando cada letra del nombre del archivo
      }
   putc(0x00);    //indico que termino el nombre del archivo
   a = getc();    //recibo los 4 bytes del tamaño del archivo
   b = getc();
   c = getc();
   d = getc();
   *size = make32(a,b,c,d);      //devuelvo el tamaño del archivo a la variable que pase a la funcion
   nbyte = *size;       //el tamaño es la cantidad de bytes que tengo que leer
   putc(0x06);    //pido al LCD que me envíe el archivo
 IF(handshaking != 0){  //si el handshaking no es 0
    WHILE(!ready){      //mientras no sea el último byte sigo pidiendo datos
      FOR(n=0;n<=handshaking;++n,++data,--nbyte){      //recibo tantos datos como handshaking tenga antes de enviar un ACK
         *data = getc();
         if(*data==0x06 && !nbyte){ ready=1; break; }  //si data es un ACK y estoy en el byte de datos por recibir, salgo
      }                                                //e indico que la transmicion termino poniendo ready a 1;
      ++data; --nbyte;
      putc(0x06);    //pido el siguiente paquete de datos
    }
 }
ELSE{      //si el handshaking es 0 no se envian ACK se recibe todo de una vez
   *data = getc();
   ++data; --nbyte;
   if(*data==0x06 && !nbyte){ break; } //al terminar la transmición salgo
return 0x06;      //retorno ACK indicando lectura correcta
 }
}

//Muestra un video y/o animación desde la tarjeta de memoria en el sector especificado
//Se muestra a partir de la posición x,y y con un delay entre cada frame que va de 1 a 255 (8bits)
INT lcd_video (INT16 x, INT16 y, INT delay, INT32 sector){
   putc('@');
   putc('V');
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(delay);
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
   return getc();
}

//Muestra un objeto que se encuentre en la memoria card en la direccion de 4 bytes indicada
INT lcd_obj_mmc (INT32 adress){
   putc('@');
   putc('O');
   putc(make8(adress,3));  //parte alta de la direccion
   putc(make8(adress,2));  //parte media de la direccion
   putc(make8(adress,1));  //parte baja de la direccion
   putc(make8(adress,0));  //parte mas baja de la direccion
   return getc();
}

//Muestra una imagen que este guardada en la tarjeta de memoria en el sector especificado
//La imagen se muestra en x,y
INT lcd_img_mmc (INT16 x, INT16 y, INT32 sector){
   putc('@');     //comando 1
   putc(0x49);    //comando 2
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
   return getc();
}

//Esta funcion copia la pantalla y la copia a un sector en la trjeta de memoria
//El sector es definido por sector, la pantalla se copia a partir de x,y con el ancho y alto que se especifique
//El rango del sector es de 0 a 16.777.215 dependiendo de la capacidad de la tarjeta de memoria
//Cada sector es de 512 bytes por lo tanto en 1Mb hay 2048 sectores
INT lcd_copy_mmc (INT16 x, INT16 y, INT16 ancho, INT16 alto, INT32 sector){
   putc('@');     //comando 1
   putc('C');     //comando 2
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(ancho,1));  //msb del ancho
   putc(make8(ancho,0));  //lsb del ancho
   putc(make8(alto,1));   //msb del alto
   putc(make8(alto,0));   //lsb del alto
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
   return getc();
}

//Esta función escribe un sector completo de la tarjeta de memoria, sector es la direccion de 3 bytes
//El rango del sector es de 0 a 16.777.215 dependiendo de la capacidad de la tarjeta de memoria
//Cada sector es de 512 bytes por lo tanto en 1Mb hay 2048 sectores
//La funcion escribe los 512 bytes que hay en la matriz que el usuario pasa
//La funcion siempre va a pasar 512 bytes por lo tanto la matriz debe ser siempre de 512 bytes, aquello no implementados se pueden
//llenar con 0x00 o 0xFF por ejemplo
//Es ideal para cuando se deben escribir grandes volumenes de datos es mas eficiente que "lcd_mmc_write_byte"
INT lcd_mmc_write_sector (INT32 sector, INT *data){
int16 n;
   putc('@');     //comando 1
   putc('W');     //comando 2
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
      FOR(n=0;n<=512;++n,++data){     //voy pasando a traves de la matriz de datos, lo hago 512 veces, una vez por byte
         putc(*data);      //voy mandando al LCD los 512 bytes del dato en la matriz
      }
   return getc();
}

//Esta función lee un sector completo de la tarjeta de memoria, sector es la direccion de 3 bytes
//El rango del sector es de 0 a 16.777.215 dependiendo de la capacidad de la tarjeta de memoria
//Cada sector es de 512 bytes por lo tanto en 1Mb hay 2048 sectores
//La función devuelve los 512 bytes leidos de la tarjeta a la matriz que el usuario pasa
//data debe ser una matriz de 512 bytes, por ejemplo: data[512]
//Es ideal para cuando se deben leer grandes volumenes de datos es mas eficiente que "lcd_mmc_read_byte"
VOID lcd_mmc_read_sector (INT32 sector, INT *data){
int16 n;
   putc('@');     //comando 1
   putc('R');     //comando 2
   putc(make8(sector,3));  //parte alta del sector
   putc(make8(sector,2));  //parte media del sector
   putc(make8(sector,1));  //parte baja del sector
      FOR(n=0;n<=512;++n,++data){     //voy pasando a traves de la matriz de datos, lo hago 512 veces, una vez por byte
         *data = getc();      //guarda cada dato que el LCD envía en una posicion de la matriz
      }
}

//Escribe el byte "data" en la direccion donde apunte el puntero que setea "lcd_mmc_pointer" en la tarjeta de memoria
//Cada vez que se escribe el puntero se incrementa automaticamente
//Ideal para escribir pequeñas cantidades de datos
INT lcd_mmc_write_byte (INT data){
   putc('@');     //comando 1 
   putc('w');     //comando 2
   putc(data);    //envío dato
   return getc();
}

//Lee el byte situado en la direccion donde apunte el puntero seteado por la funcion "lcd_mmc_pointer" de la tarjeta de memoria
//Cada vez que se lee el puntero se incrementa una posicion automaticamente
//Ideal para leer pequeñas cantidades de datos
INT lcd_mmc_read_byte (VOID){
   putc('@');     //comando 1
   putc('r');     //comando 2
   return getc(); //retorno el byte leido de la tarjeta de memoria
}

//Setea el puntero de la dirección a leer y/o escribir de la tarjeta de memoria, el mismo se autoincrementa luego de cada
//escritura/lectura
INT lcd_mmc_pointer (INT32 adress){
   putc('@');     //comando 1
   putc('A');     //comando 2
   putc(make8(adress,3));  //cuarto byte del INT32 (msb)
   putc(make8(adress,2));  //tercer byte del INT32 (lsb)
   putc(make8(adress,1));  //segundo byte del INT32 (msb)
   putc(make8(adress,0));  //primer byte del INT32 (lsb)
   return getc();
}

//Inicializa la memory card del LCD (es necesario utilizarla por ejemplo luego de un sleep ya que la misma se inicializa
//al encenderse el LCD)
INT lcd_mmc_init (VOID){
   putc('@');     //comando 1
   putc('i');     //comando 2
   return getc();
}

//Modifica el modo (opaco o transparente) para escribir con la función "lcd_writting_mode"
VOID text_mode (INT mode){
   modo_texto = mode;
}

//Modifica la fuente para escribir con la función "lcd_writting_mode"
VOID text_font (INT font){
   fuente = font;
}

//Modifica el color para escribir con la función "lcd_writting_mode"
VOID lcd_color (INT16 color){
   text_color = color;
}

//Modifica los cursores para escribir con la función "lcd_writting_mode"
VOID lcd_xy (INT16 x, INT16 y){
   cursor_x = x;
   cursor_y = y;
}

//Escribe un texto con las características definidas por "lcd_writting_mode"
//Se puede usar con la función printf() por ejemplo:
//printf(lcd_write_text,"Esta variable contiene: %u",variable);
VOID lcd_write_text (CHAR c){
   lcd_char_text(c,cursor_x,cursor_y,text_color,fuente,modo_texto);

//espaciamiento del cursor segun la fuente
        if(fuente==0x00){ cursor_x += 6;  }
   ELSE if(fuente==0x01){ cursor_x += 9;  }
   ELSE if(fuente==0x02){ cursor_x += 9;  }
   ELSE if(fuente==0x03){ cursor_x += 13; }
   
//caracteres especiales
   SWITCH(c){
      CASE '\n':        //nueva linea
         if(fuente==0x00){ cursor_y += 8;  }
         else if(fuente==0x01){ cursor_y += 9;  }
         else if(fuente==0x02){ cursor_y += 13; }
         else if(fuente==0x03){ cursor_y += 17; }
         break;
         
      CASE '\r':        //retorno de carro
         cursor_x = 0;
         break;
   }
      
//si me paso del tamaño de la pantalla
        IF(cursor_x > 320){ 
            cursor_x = 0;
                    if(fuente==0x00){ cursor_y += 8;  }
               else if(fuente==0x01){ cursor_y += 9;  }
               else if(fuente==0x02){ cursor_y += 13; }
               else if(fuente==0x03){ cursor_y += 17; }
        }
}

//Define las coordenadas x,y, el color la fuente y el modo a usarse para escribir el texto con la función
//"lcd_write_text"
VOID lcd_writting_mode (INT16 x, INT16 y, INT16 color, INT font, INT modo){
   fuente = font;        //fuente
   modo_texto = modo;    //modo
   cursor_x = x;         //coordenadas
   cursor_y = y;
   text_color = color;   //color
}

//Esta funcion crea un boton que dependiendo de estado esta presionado o no, se define el color del boton y del texto por separado
//y la fuente con la que se escribe el texto, el ancho y alto definen un "escalado" que se le hace al texto aumentando su
//tamaño y a su vez la del boton
//estado puede ser 1 o 0 dependiendo si esta presionado o no (0 es presionado)
INT lcd_button (INT estado, INT16 x, INT16 y, INT16 butcolor, INT font, INT16 textcolor, INT ancho, INT alto, CHAR *textptr){
   putc('b');     //comando
   putc(estado);  //boton presionado o no
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(butcolor,1));  //msb del color del boton
   putc(make8(butcolor,0));  //lsb del color del boton
   putc(font);
   putc(make8(textcolor,1));  //msb del color del texto
   putc(make8(textcolor,0));  //lsb del color del texto
   putc(ancho);
   putc(alto);
      FOR(;*textptr != '\0'; ++textptr){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*textptr);      //voy colocando cada letra del texto
      }
   putc(0x00);    //termina el texto
   return getc();
}

//Esta funcion es similar a "lcd_text_string" solo que ademas de elejir la fuente se puede designar un ancho y alto
//por el cual se multiplica la fuente original "escalando" el tamaño del texto.
//El modo puede ser opaco o transparente y la letra se dibuja del color definido con su esquina superior izquierda en x,y
INT lcd_graphic_string (INT16 x, INT16 y, INT font, INT16 color, INT ancho, INT alto, CHAR *textptr, INT modo){
   putc('S');
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(font);
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   putc(ancho);
   putc(alto);
      FOR(;*textptr != '\0'; ++textptr){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*textptr);      //voy colocando cada letra del texto
      }
   putc(0x00);    //termina el texto
   return getc();
}

//Esta funcion escribe un texto que se pasa en un array y debe terminar con '\0' con un maximo de 256 caracteres
//Se dibuja en la posicion x,y tomando cada unidad dependiendo del ancho y alto de la fuente elejida en font
//El modo puede ser transparente u opaco
INT lcd_text_string (INT x, INT y, INT font, INT16 color, CHAR *textptr, INT modo){
   lcd_text_mode(modo); //transparente u opaco
   putc('s');     //comando
   putc(x);       //posiciones x,y
   putc(y);
   putc(font);    //fuente a usar
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
      FOR(;*textptr != '\0'; ++textptr){     //voy pasando a traves de la matriz del texto hasta que llege a '\0' donde termina
         putc(*textptr);      //voy colocando cada letra del texto
      }
   putc(0x00);    //al terminar con el texto envio 0x00 para indicar que se termino
   return getc();
}

//Esta funcion es similar a "lcd_char_text" solo que la dibuja graficamente con un ancho y alto especifico
//independiente de las fuentes internas que tenga el LCD, la dibuja con su esquina superior izquierda en x,y
//del color definido
//El modo define si la letra es transparente u opaca
INT lcd_char_graphic (CHAR c, INT16 x, INT16 y, INT16 color, INT ancho, INT alto, INT modo){
   lcd_text_mode(modo);    //transparente u opaco
   putc('t');     //comando
   putc(c);
   putc(make8(x,1));  //msb de x
   putc(make8(x,0));  //lsb de x
   putc(make8(y,1));  //msb de y
   putc(make8(y,0));  //lsb de y 
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   putc(ancho);
   putc(alto);
   return getc();
}

//Escribe un letra "c" de algun tamaño de las fuentes internas del LCD
//CHAR c es la letra a escribir
//INT x es la posicion "x" de la letra, cada unidad se toma como el ancho de la letra
//INT y es la posicion "y" de la letra, cada unidad se toma como el alto de la letra
//INT font elije la fuente del LCD (5x7, 8x8, 8x12, 12x16) siendo 0,1,2 y 3 respectivamente
//INT16 color es el color de la letra a escribir
//INT modo define si la letra es transparente u opaca
INT lcd_char_text (CHAR c, INT x, INT y, INT16 color, INT font, INT modo){
   lcd_font(font);         //fuente de la letra
   lcd_text_mode(modo);    //transparente u opaco
   putc('T');  //comando
   putc(c);    //envio letra
   putc(x);    //posicion "x"
   putc(y);    //posicion "y"
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();
}

//Define si las letras del LCD van a ser Transparentes o Opacas
//modo = 0 = transparente (los objetos detras del texto son visibles)
//modo = 1 = opaco (se crea un recuadro alrededor del texto del color de fondo)
INT lcd_text_mode (INT modo){
   putc('O');     //comando
   putc(modo);
   return getc();
}

//Define el tipo de fuente de las letras del LCD
//tipo = 0 = 5x7     (pequeño)
//tipo = 1 = 8x8     (mediano)
//tipo = 2 = 8x12    (grande)
//tipo = 3 = 12x16   (muy grande)
INT lcd_font (INT tipo){
   putc('F');     //comando
   putc(tipo);    //tipo de fuente
   return getc(); //retorno ACK o NAK
}

//Rellena o no todo lo dibujado
//modo = 0 = todo se rellena
//modo = 1 = se dibuja normalmente con el contorno
INT lcd_fill (INT1 modo){
   putc('p');        //comando
   putc(modo);
   return getc();    //devuelvo el ACK o NAK
}

//Dibuja un circulo en con su centro coordenadas "x" e "y"
//color define el color en RGB
//radio es el radio en píxeles
INT lcd_circle (INT16 x, INT16 y, INT16 radio, INT16 color, INT1 fill){
   lcd_fill(fill);      //relleno o no la figura a dibujar
   putc('C');     //comando
   putc(make8(x,1));  //msb del eje x
   putc(make8(x,0));  //lsb del eje x
   putc(make8(y,1));  //msb del eje y
   putc(make8(y,0));  //lsb del eje y
   putc(make8(radio,1));  //msb del radio
   putc(make8(radio,0));  //lsb del radio
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}

//Dibuja un tríangulo, cada par de coordenadas "x" e "y" definen un vértice del triángulo en sentido antihorario
//el color define el color del triangulo en RGB
//fill rellena o no el triángulo (0 rellena)
INT lcd_triangle (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 x3, INT16 y3, INT16 color, INT1 fill){
   lcd_fill(fill);
   putc('G');     //comando
   putc(make8(x1,1));  //msb del eje x1
   putc(make8(x1,0));  //lsb del eje x1
   putc(make8(y1,1));  //msb del eje y1
   putc(make8(y1,0));  //lsb del eje y1
   putc(make8(x2,1));  //msb del eje x2
   putc(make8(x2,0));  //lsb del eje x2
   putc(make8(y2,1));  //msb del eje y2
   putc(make8(y2,0));  //lsb del eje y2
   putc(make8(x3,1));  //msb del eje x3
   putc(make8(x3,0));  //lsb del eje x3
   putc(make8(y3,1));  //msb del eje y3
   putc(make8(y3,0));  //lsb del eje y3
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}

//Dibuja una linea que comienza en x1,y1 y termina en x2,y2 del color definido
INT lcd_line (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 color){
   putc('L');     //comando
   putc(make8(x1,1));  //msb del eje x1
   putc(make8(x1,0));  //lsb del eje x1
   putc(make8(y1,1));  //msb del eje y1
   putc(make8(y1,0));  //lsb del eje y1
   putc(make8(x2,1));  //msb del eje x2
   putc(make8(x2,0));  //lsb del eje x2
   putc(make8(y2,1));  //msb del eje y2
   putc(make8(y2,0));  //lsb del eje y2
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color
   return getc();    //devuelvo el ACK o NAK
}  

//Dibuja un polígono desde 3 a 7 vértices
//vertices es el número de vertices
//si no se implementa algun vertice se coloca 0 en su "x" e "y" correspondiente
//los vértices se colocan en una matriz para cada eje
INT lcd_polygon(INT vertices, INT16 *xptr, INT16 *yptr, INT16 color){
int n;
   putc('g');     //comando
   putc(vertices);    //numero de vertices
   FOR(n=0;n<=7;++n,++xptr,++yptr){    //voy pasando a través de los 7 ejes de cada matriz (numero máximo)
      IF(*xptr != 0 && *yptr != 0){    //envío el juego de ejes x,y si no son 0 (0 es no implementado)
         putc(make8(*xptr,1));  //msb del eje x correspondiente
         putc(make8(*xptr,0));  //lsb del eje x correspondiente
         putc(make8(*yptr,1));  //msb del eje y correspondiente
         putc(make8(*yptr,0));  //lsb del eje y correspondiente
      }
   }
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}

//Dibuja un rectágulo con las esquina superior izquierda en x1,y2 y la inferior derecha en x2,y2
INT lcd_rectangle (INT16 x1, INT16 y1, INT16 x2, INT16 y2, INT16 color, INT1 fill){
   lcd_fill(fill);
   putc('r');     //comando
   putc(make8(x1,1));  //msb del eje x1
   putc(make8(x1,0));  //lsb del eje x1
   putc(make8(y1,1));  //msb del eje y1
   putc(make8(y1,0));  //lsb del eje y1
   putc(make8(x2,1));  //msb del eje x2
   putc(make8(x2,0));  //lsb del eje x2
   putc(make8(y2,1));  //msb del eje y2
   putc(make8(y2,0));  //lsb del eje y2
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}

//Dibuja un elipse con su centro en x,y
//rx y ry son el radio de los ejes "x" e "y" del elipse
INT lcd_elipse (INT16 x, INT16 y, INT16 rx, INT16 ry, INT16 color, INT1 fill){
   lcd_fill(fill);
   putc('e');
   putc(make8(x,1));  //msb del eje x
   putc(make8(x,0));  //lsb del eje x
   putc(make8(y,1));  //msb del eje y
   putc(make8(y,0));  //lsb del eje y
   putc(make8(rx,1));  //msb del radio x
   putc(make8(rx,0));  //lsb del radio x
   putc(make8(ry,1));  //msb del radio y
   putc(make8(ry,0));  //lsb del radio y
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}
   
//Dibuja un píxel en x,y del color definido
INT lcd_pixel (INT16 x, INT16 y, INT16 color){
   putc('P');     //comando
   putc(make8(x,1));  //msb del eje x
   putc(make8(x,0));  //lsb del eje x
   putc(make8(y,1));  //msb del eje y
   putc(make8(y,0));  //lsb del eje y
   putc(make8(color,1));  //msb del color
   putc(make8(color,0));  //lsb del color 
   return getc();    //devuelvo el ACK o NAK
}

//Lee el color del píxel en la posición x,y
INT16 lcd_read_pixel (INT16 x, INT16 y){
int msb,lsb;   //bytes del color

   putc('R');     //comando
   putc(make8(x,1));  //msb del eje x
   putc(make8(x,0));  //lsb del eje x
   putc(make8(y,1));  //msb del eje y
   putc(make8(y,0));  //lsb del eje y
   msb = getc();      //recibo los 2 bytes del color
   lsb = getc();
   return make16(msb,lsb); //retorno el color  
}
   
//Copia una parte de la pantalla que comienza en xs,ys con su ancho y alto determinado y la copia en xd,yd
INT lcd_copy_paste (INT16 xs, INT16 ys, INT16 xd, INT16 yd, INT16 ancho, INT16 alto){
   putc('c');
   putc(make8(xs,1));  //msb del eje xs
   putc(make8(xs,0));  //lsb del eje xs
   putc(make8(ys,1));  //msb del eje ys
   putc(make8(ys,0));  //lsb del eje ys
   putc(make8(xd,1));  //msb del eje xd
   putc(make8(xd,0));  //lsb del eje xd
   putc(make8(yd,1));  //msb del eje yd
   putc(make8(yd,0));  //lsb del eje yd
   putc(make8(ancho,1));  //msb del ancho
   putc(make8(ancho,0));  //lsb del ancho
   putc(make8(alto,1));   //msb del alto
   putc(make8(alto,0));   //lsb del alto
   return getc();    //devuelvo el ACK o NAK
}

INT lcd_replace_color (INT x1, INT y1, INT x2, INT y2, INT16 old_color, INT16 new_color){
   putc('k');     //comando
   putc(x1);      //ejes
   putc(y1);
   putc(x2);
   putc(y2);
   putc(make8(old_color,1));   //msb de old_color
   putc(make8(old_color,0));   //lsb de old_color
   putc(make8(new_color,1));   //msb de new_color
   putc(make8(new_color,0));   //lsb de new_color
   return getc();    //devuelvo el ACK o NAK
}
   
//Inicia el LCD uLCD-32PT de 4D Systems vía el RS232
//No vuelve de la función hasta que se halla inicializado
VOID lcd4d_init (VOID){
int r; //respuesta del LCD

set_uart_speed(9600);      //velocidad inicial del LCD a 9600 baudios
putc('U');                 //auto baud al LCD
WHILE(getc() != 0x06);

do{ r = lcd_touch(1);          }WHILE(r == 0x15);     //apago touchscreen
do{ r = lcd_orientation(1);    }WHILE(r == 0x15);     //orientacion LANDSCAPE
do{ r = lcd_mode(1);           }WHILE(r == 0x15);     //no bajo consumo
do{ r = lcd_contrast(7);       }WHILE(r == 0x15);     //contraste 7
do{ r = lcd_display(1);        }WHILE(r == 0x15);     //display encendido
do{ r = lcd_backlight(1);      }WHILE(r == 0x15);     //backlight encendido
do{ r = lcd_fat(1);            }WHILE(r == 0x15);     //no protejer FAT
do{ r = lcd_clear();           }WHILE(r == 0x15);     //borro LCD
}

//Obtiene la version del hardware,software y resoluciones horizontales y verticales del LCD y las guarda
//en las variables que pasa el usuario
//Si modo = 0 la versión del dispositivo es mandada por el UART
//Si modo = 1 la versión del dispositivo es mandada por el UART y escrita en pantalla
//*device_type puede ser 0 si es micro-OLED, 1 si es micro-LCD, 2 si es micro-VGA
//*hard_ver es la versión del hardware
//*soft_ver es la versión del software
//*h_res y *v_res son las resoluciones horizontales y verticales en píxeles
VOID lcd_get_info (INT modo,INT *device_type,INT *hard_ver, INT *soft_ver, INT16 *h_res, INT16 *v_res){
int resh,resv;
   putc('V');
   putc(modo);
   *device_type = getc();
   *hard_ver = getc();
   *soft_ver = getc();
   resh = getc();
   resv = getc();
IF(resh==0x22){ *h_res = 220; }
ELSE IF(resh==0x28){ *h_res = 128; }
ELSE IF(resh==0x32){ *h_res = 320; }
ELSE IF(resh==0x60){ *h_res = 160; }
ELSE IF(resh==0x64){ *h_res = 64;  }
ELSE IF(resh==0x76){ *h_res = 176; }
ELSE IF(resh==0x96){ *h_res = 96;  }
ELSE IF(resh==0xFF){ *h_res = 0;   }

IF(resv==0x22){ *v_res = 220; }
ELSE IF(resv==0x28){ *v_res = 128; }
ELSE IF(resv==0x32){ *v_res = 320; }
ELSE IF(resv==0x60){ *v_res = 160; }
ELSE IF(resv==0x64){ *v_res = 64;  }
ELSE IF(resv==0x76){ *v_res = 176; }
ELSE IF(resv==0x96){ *v_res = 96;  }
ELSE IF(resv==0xFF){ *v_res = 0;   }
}

//Setea una nueva velocidad para el UART del LCD
//baud puede ser (todo en hexadecimal):
//00: 110 baudios       01: 300 baudios      02: 600 baudios
//03: 1200 baudios      04: 2400 baudios     05: 4800 baudios
//06: 9600 baudios      07: 14400 baudios    08: 19200 baudios
//09: 31250 baudios     0A: 38400 baudios    0B: 56000 baudios
//0C: 56000 baudios     0D: 115200 baudios   0E: 128000 baudios 
//0F: 256000 baudios
INT lcd_set_baud (INT baud){
   putc('Q');
   putc(baud);
   return getc();
}

//escribe en el bus del LCD siendo de P8 a P15
INT write_bus (INT valor){
   putc('W');
   putc(valor);
   return getc();    //devuelvo el ACK o NAK
}

//devuelve el valor del bus de 8 bits del LCD siendo de P8 a P15
INT read_bus (VOID){
   putc('a');     //comando
   return getc();    //retorno los 8 bits del bus
}

//Pone a 1 o 0 un pin determinado del LCD
//pin va de 1 a 15 siendo de P0 a P15
//valor puede ser 1 o 0
INT lcd_write_pin (INT pin, INT valor){
   putc('y');     //comando
   putc(pin);
   putc(valor);
   return getc();    //devuelvo el ACK o NAK
}

//Lee el estado del pin P0 a P15 y devuelve 1 o 0 según el estado
//pin va de 0 a 15
INT lcd_read_pin (INT pin){
   putc('i');     //comando
   putc(pin);     //pin a leer
   return getc();    //retorno el valor del pin que manda el LCD
}

//Pone al LCD en diferentes modos de sleep y por un tiempo determinado
//modo = 128 = apaga uSD y debe reiniciarse manualmente
//modo = 64 = apaga audio y se reiniciara automaticamente cuando se use
//modo = 32 = apaga touchscreen
//modo = 8 = despertarse por cambio de estado en P1
//modo = 4 = despertarse por cambio de estado en P0
//modo = 2 = despertarse por actividad en touchscreen
//modo = 1 = despertarse por actividad en el UART
//time = 0 = se pone en sleep por siempre (despierta en reset y cambio de estado en P0 o P1)
//time 1-255 = tiempo en segundos de sleep
INT lcd_sleep (INT modo, INT tiempo){
   putc('Z');     //comando
   putc(modo);
   putc(tiempo);
   return getc();    //devuelvo el ACK o NAK
}

//Define el color de fondo del LCD
//color define el color de fondo RGB
INT lcd_background (INT16 color){
   putc('B');     //comando
   putc(make8(color,1));  //msb de color
   putc(make8(color,0));  //lsb de color
   return getc();    //devuelvo el ACK o NAK
}

//Valor del volumen del LCD
//valor va de 8 a 127
//valor = 0 = mute        
//valor = 1 = volumen baja 8 niveles
//valor = 3 = volumen baja 1 nivel
//valor = 253 = volumen sube 1 nivel
//valor = 254 = volumen sube 8 niveles
//valor = 255 = mute OFF
INT lcd_volume (INT valor){
   putc('v');     //comando
   putc(valor);   //protejido o no
   return getc();    //devuelvo el ACK o NAK
}

//Coloca o no al display en bajo consumo
//modo = 0 = proteje FAT
//modo = 2 = no proteje FAT
INT lcd_fat (INT modo){
   putc('Y');     //comando
   putc(8);       //FAT
   putc(modo);    //protejido o no
   return getc();    //devuelvo el ACK o NAK
}

//Formato de las imágenes del LCD
//modo = 1 = formato viejo con header
//modo = 0 = formato nuevo sin header
INT lcd_image_format (INT1 modo){
   putc('Y');     //comando
   putc(6);       //formato de imagen
   putc(modo);    //formato
   return getc();    //devuelvo el ACK o NAK
}

//Configura el touchscreen
//modo = 0 = activado
//modo = 1 = apagado
//modo = 2 = reinicia la región activa a todo el LCD
INT lcd_touch (INT modo){
   putc('Y');     //comando
   putc(5);       //touchscreen
   putc(modo);    //modo
   return getc();    //devuelvo el ACK o NAK
}

//Orientación del LCD
//modo = 1 = LANDSCAPE
//modo = 2 = LANDSCAPE ROTADO
//modo = 3 = PORTRAIT
//modo = 4 = PORTRAIT ROTADO
INT lcd_orientation (INT modo){
   putc('Y');     //comando
   putc(4);       //orientación
   putc(modo);    //valor
   return getc();    //devuelvo el ACK o NAK
}

//Coloca o no al display en bajo consumo
//modo = 1 = encendido
//modo = 0 = apagado
INT lcd_mode (INT1 modo){
   putc('Y');     //comando
   putc(3);       //bajo consumo
   putc(modo);    //ON/OFF
   return getc();    //devuelvo el ACK o NAK
}

//Contraste del LCD
//Valor va de 0 a 15
INT lcd_contrast (INT valor){
  IF(valor>15) valor = 1;  //si me paso del valor máximo lo reinicia
   putc('Y');     //comando
   putc(2);       //contraste
   putc(valor);   //ON/OFF
   return getc();    //devuelvo el ACK o NAK
}

//Enciende o apaga el display
//modo = 1 = encendido
//modo = 0 = apagado
INT lcd_display (INT1 modo){
   putc('Y');     //comando
   putc(1);       //display
   putc(modo);    //ON/OFF
   return getc();    //devuelvo el ACK o NAK
}

//Enciende o apaga el backlight
//modo = 1 = encendido
//modo = 0 = apagado
INT lcd_backlight (INT1 modo){
   putc('Y');     //comando
   putc(0);       //backlight
   putc(modo);    //ON/OFF
   return getc();    //devuelvo el ACK o NAK
}

//Borra la pantalla del LCD y la deja con el color de fondo
INT lcd_clear (VOID){
putc('E');
return getc();    //devuelvo el ACK o NAK
}

//Obtiene las coordenadas de la pantalla táctil y las guarda en dos que el usuario pasa a la funcion
//Retorna un 1 si el panel fue tocado y devuelve las coordenadas
//Retorna un 0 si el panel no fue tocado y no devuelve las coordenadas
INT get_touch (INT16 *x, INT16 *y){

int status;                         //estado del touch
int cor1,cor2,cor3,cor4;            //bytes de las coordenadas

//primero pido el estado de la pantalla táctil
putc('o');        //comando touch
putc(0x04);       //pido estado
status = getc();

IF(status==1 || status==3){  //si el touchscreen esta siendo tocado
   putc('o');     //comando touch
   putc(0x05);    //pido coordenadas touch
   cor1 = getc(); //msb eje x
   cor2 = getc(); //lsb eje x
   cor3 = getc(); //msb eje y
   cor4 = getc(); //lsb eje y
   *x = make16(cor1,cor2);       //uno las coordenadas en int16
   *y = make16(cor3,cor4);
   return 1;      //retorno 1 indicando que tome nuevas coordenadas
   }
ELSE{             //sino retorno un 0 indicando que no hubo nuevo touch
   return 0;
   }
}

//Genera un delay en el cual el LCD no hace nada hasta que se toque el touchscreen
INT wait_touch (INT16 time){
   putc('w');     //comando
   putc(make8(time,1));  //msb de time
   putc(make8(time,0));  //lsb de time
   return getc();
}

//Crea un "filtro" en el touchscreen y solo respondera que el touch ha sido tocado y coordenadas dentro de la region definida
//cualquier actividad fuera de la region es ignorada
INT lcd_touch_region (INT16 x1, INT16 y1, INT16 x2, INT16 y2){
   putc('u');     //comando
   putc(make8(x1,1));  //msb de x1
   putc(make8(x1,0));  //lsb de x1
   putc(make8(y1,1));  //msb de y1
   putc(make8(y1,0));  //lsb de y1
   putc(make8(x2,1));  //msb de x2
   putc(make8(x2,0));  //lsb de x2
   putc(make8(y2,1));  //msb de y2
   putc(make8(y2,0));  //lsb de y2
   return getc();
}
//Obtiene las coordenadas de la pantalla táctil y las guarda en dos que el usuario pasa a la funcion
//No vuelve de la funcion hasta que se alla tocado el touchscreen
VOID wait_touch_press (INT16 *x, INT16 *y){
int cor1,cor2,cor3,cor4;            //bytes de las coordenadas
   putc('o');     //comando
   putc(0x01);    //espero hasta que se toque el touchscreen
   cor1 = getc(); //msb eje x
   cor2 = getc(); //lsb eje x
   cor3 = getc(); //msb eje y
   cor4 = getc(); //lsb eje y
   *x = make16(cor1,cor2);       //uno las coordenadas en int16
   *y = make16(cor3,cor4);
}

//Espera hasta que se deje de tocar el touchscreen
VOID wait_touch_release (VOID){
   putc('o');     //comando
   putc(0x02);    //espero hasta que se suelte el touchscreen
   getc(); getc(); getc(); getc();  //recibo todos los bytes pero no hago nada con ellos
}
   
//Devuelve el estado del touch
//0 = no touch
//1 = touch presionado
//2 = touch soltado
//3 = touch moviendose
INT get_touch_status (VOID){
   putc('o');     //comando
   putc(0x04);    //pido el estado del touch
   return getc(); //retorno el estado del touchscreen
}

#endif

