Uso de la pantalla táctilEl acceso a la pantalla táctil está bastante optimizado en la libreria GD2; la función para activarla es:
GD.get_inputs();
Para crear una entrada táctil se usa la siguiente instrucción:
GD.Tag(x);
Se pueden crear hasta 244 entradas táctiles (1-244), en teoría 0 también se podría usar, sin embargo en las pruebas que he hecho asignando esa entrada, la pantalla FT843 se torna inestable.
Es posible asociar entradas táctiles a objetos individuales como números, lineas de texto, gráficos primarios, imágenes, funciones con varias imágenes, incluso a cada uno de las imágenes contenidas en un asset de iconos.
Para evitar que varios objetos tengan la misma entrada táctil, se coloca la siguiente instrucción:
GD.Tag(255);
Justo después de asignar una entrada táctil a un determinado objeto.
Tomando como base el ejemplo con el arreglo de iconos creado previamente y con algunas pequeñas modificaciones, el sketch base queda así:
//22012016
#include <SPI.h>
#include <GD2.h>
#include "Icons2.h"
void setup() {
GD.begin();
LOAD_ASSETS0();
MP(); //menu principal
}
void loop() {}
void MP()
{
while(1)
{
GD.Clear();
GD.Begin(BITMAPS);
carga_iconos();
GD.swap();
}
}
void carga_iconos()
{
GD.Vertex2ii(0, 0, 0);
GD.Vertex2ii(0, 48, 1);
GD.Vertex2ii(0, 96, 2);
GD.Vertex2ii(0, 144, 3);
GD.Vertex2ii(0, 192, 4);
GD.Vertex2ii(60, 0, 5);
GD.Vertex2ii(60, 48, 6);
GD.Vertex2ii(60, 96, 7);
GD.Vertex2ii(60, 144, 8);
GD.Vertex2ii(60, 192, 9);
GD.Vertex2ii(120, 0, 10);
GD.Vertex2ii(120, 48, 11);
GD.Vertex2ii(120, 96, 12);
GD.Vertex2ii(120, 144, 13);
}
Me gusta dejar aislada la función
void loop()
Tal como está estructurado el sketch, es posible conseguir la misma funcionalidad que haciéndolo sobre void loop.
Insertemos ahora un icono que usaremos como si fuera un botón de encendido y apagado; este será el objeto al que asignaremos una entrada táctil
void MP()
{
while(1)
{
GD.Clear();
GD.Begin(BITMAPS);
carga_iconos();
GD.get_inputs();
GD.Tag(1); GD.Vertex2ii(300, 100, 0); GD.Tag(255);
GD.swap();
}
}
Esta secuencia ya nos permitirá usar la pantalla táctil, asignando una entrada al icono 0 del arreglo de iconos. Para tener la sensación de que estamos pulsando el botón digital, podemos conseguirlo recurriendo a algunas técnicas de animación simples.
El primer paso es asignar un fondo de pantalla en color claro. Por ejemplo, podemos usar un fondo uniforme con la instrucción:
GD.ClearColorRGB(0x108000);

También podemos establecer un degradado vertical, con el comando
cmd_gradient, por ejemplo:
GD.cmd_gradient(0, 0, 0x0060c0, 0, 271, 0xc06000);

El segundo paso consiste en agregar un sombreado al botón, ésto se puede conseguir usando una máscara de color oscuro tomando tomando como base la imagen a la que queremos agregar el efecto, en este caso el botón hexagonal.
Para evitar que ajustes como la selección de un color RGB determinado, cambio de zoom, colores de relleno de gadgets; afecten todos los comandos posteriores a un cambio específico, se emplean estas dos instrucciones:
GD.SaveContext();
GD.RestoreContext();
Con ellas es posible almacenar la combinación de colores y efectos previos, sin alterar el diseño de todo el proyecto.
GD.SaveContext();
GD.ColorA(50); GD.ColorRGB(0x000000);
GD.Vertex2ii(300, 120, 0);
GD.RestoreContext();
En esta secuencia dibujamos el icono hexagonal con una degradación del color RGB=0x000000 (negro), ubicándolo 20 pixeles debajo del icono hexagonal principal. Como nos interesa conseguir un efecto de sombreado, hay que dibujarlo antes del icono en colores reales.

Al combinar ambos gráficos obtenemos el sombreado en el icono-botón:

Para asegurar que la animación sea perceptible, hay que crear una bandera de control que monitoree todo el tiempo el estatus del botón. Para ello podemos crear una función que dibuje el botón en la posición 0 = apagado y 1 = encendido.
Designamos una variable o bandera, por ejemplo
int cambio_1 = 0;
Con ello indicamos que al iniciar el sketch el botón estará en la posición de apagado. Si deseamos controlar algo como un rele o bien conseguir un efecto visual con un led, por ejemplo, es conveniente que la bandera sea global.
El botón debemos dibujarlo ahora como una función con dos valores, por ejemplo
void status_1()
{
if (cambio_1==0){GD.Vertex2ii(128, 150, 0);}
if (cambio_1==1){GD.Vertex2ii(128, 165, 1);}
}
También podemos usar un
select case. La imagen que da la idea de botón encendido, corresponde a la segunda imagen del arreglo de iconos
La entrada táctil ya no estará dirigida a un solo icono, estará dirigida a las dos posiciones que tomará el botón al estar en modo encendido o en modo apagado:
GD.Tag(1); status_1(); GD.Tag(255);
Finalmente debemos asignar lo que se hará cuando pulsemos el botón, para ello basta con colocar un comparador usando una instrucción
if, que esté ligada al valor de la entrada táctil 1
if (GD.inputs.tag==1){
delay(155);
cambio_1=cambio_1+1;
if (cambio_1>=2){cambio_1=0;}
}
No soy partidario de usar delays, sin embargo en las entradas táctiles resulta muy útil colocar un pequeño lapso de espera de entre 145 y 200 ms, esto permite que la pantalla táctil no se sature de datos y dé la impresión de que la estamos presionando constantemente, haciéndonos suponer que no funciona correctamente.
Este es el núcleo principal del sketch:
void MP()
{
while(1)
{
// GD.ClearColorRGB(0x108000);
GD.Clear();
GD.cmd_gradient(0, 0, 0x0060c0, 0, 271, 0xc06000);
GD.Begin(BITMAPS);
carga_iconos();
GD.get_inputs();
GD.SaveContext();
GD.ColorA(50); GD.ColorRGB(0x000000);
GD.Vertex2ii(300, 120, 0);
GD.RestoreContext();
GD.Tag(1); status_1(); GD.Tag(255);
if (GD.inputs.tag==1){
delay(195);
cambio_1=cambio_1+1;
if (cambio_1>=2){cambio_1=0;}
}
GD.swap();
}
}
void status_1()
{
if (cambio_1==0){GD.Vertex2ii(300, 100, 0);}
if (cambio_1==1){GD.Vertex2ii(300, 120, 1);}
}
Este es el resultado en el TFT Sigue: creación de un menu principal y de submenus