I am using a 320x240 ILI9341 display with XPT2046 touchscreen. I copied and pasted in all code regarding the phone keypad buttons and display for the Adafruit Fona project on github, it works fine for the most part but I am having a problem with the touchscreen buttons not releasing. Has anyone encountered this and how can I mitigate it? I am not using the actual Fona code since I am just interested in using the layout of the buttons and how to detect press and release. I may have missed something I should have copied, but I get no errors in the IDE output.
I've spent 3 days, so far, trying to get all this working, I've read through most of the libs and am a bit stumped. Is there a better lib or a more reliable button mechanism for touchscreens and buttons layouts?
All code is wired as depicted on https://www.pjrc.com/store/display_ili9341_touch.html . I have modified the positions of the buttons and text diplays slightly from the original code so I can add some features at a later date.
Thank you in advance,
Jorge
Main Program
namedColors.h
I've spent 3 days, so far, trying to get all this working, I've read through most of the libs and am a bit stumped. Is there a better lib or a more reliable button mechanism for touchscreens and buttons layouts?
All code is wired as depicted on https://www.pjrc.com/store/display_ili9341_touch.html . I have modified the positions of the buttons and text diplays slightly from the original code so I can add some features at a later date.
Thank you in advance,
Jorge
Main Program
Code:
// Tests for touchscreen ILI9341_t3
#include <SPI.h>
#include <Wire.h>
#include <ILI9341_t3.h>
#include <XPT2046_Touchscreen.h>
#include "namedColors.h"
// This is calibration data for the raw touch data to the screen coordinates (Set to your Display)
#define TS_MINX 200
#define TS_MINY 175
#define TS_MAXX 3837
#define TS_MAXY 3737
// Device chip select pins
#define XPT_CS 8
#define TFT_CS 10
XPT2046_Touchscreen ts(XPT_CS);
// TFT Data/Command pin
#define TFT_DC 9
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
// Button Code from Adafruit example for "Arduino Phone"
#define BUTTON_X 50
#define BUTTON_Y 140
#define BUTTON_W 60
#define BUTTON_H 30
#define BUTTON_SPACING_X 10
#define BUTTON_SPACING_Y 10
#define BUTTON_TEXTSIZE 2
// text box where numbers go
#define TEXT_X 10
#define TEXT_Y 60
#define TEXT_W 220
#define TEXT_H 50
#define TEXT_TSIZE 3
#define TEXT_TCOLOR ILI9341_MAGENTA
// the data (phone #) we store in the textfield
#define TEXT_LEN 12
char textfield[TEXT_LEN+1] = "";
uint8_t textfield_i=0;
// We have a status line for like, is FONA working
#define STATUS_X 10
#define STATUS_Y 113
/* create 15 buttons, in classic candybar phone style */
char buttonlabels[15][5] = { "Send", "Clr", "End",
"1", "2", "3",
"4", "5", "6",
"7", "8", "9",
"*", "0", "#" };
uint16_t buttoncolors[15] = {c_darkgreen, c_darkgrey, c_red,
c_blue, c_blue, c_blue,
c_blue, c_blue, c_blue,
c_blue, c_blue, c_blue,
c_orange, c_blue, c_orange};
Adafruit_GFX_Button buttons[15];
// Print something in the mini status bar with either flashstring
void status(const __FlashStringHelper *msg) {
tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
tft.setCursor(STATUS_X, STATUS_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print(msg);
}
// or charstring
void status(char *msg) {
tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
tft.setCursor(STATUS_X, STATUS_Y);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.print(msg);
}
/// JJP Code follows, different display sizes will require modifications of this code, also
/// if you change the orientation.
const int screenWidth = ILI9341_TFTWIDTH; // WIDTH from the include
const int screenHeight = ILI9341_TFTHEIGHT; // HEIGHT from the include
//Font properties
const int fntWidth = 6;
const int fntHeight = 8;
// Screen Properties (Dynamicly created with values above)
const int screenMaxCharsPerLine = screenWidth/fntWidth;
const int screenMaxLines = screenHeight/fntHeight;
// padding in pixels, incase font is slightly off screen
const int cpadding = 0; //Column Padding
const int rpadding = 0; // Row/Line Padding
// 53 Columns (0 to 52) and 30 Rows (0 to 29) on a 320x240 display. I use this for calculating the
// columns for text placement using setCursor, default font 6x8!
int tftCol[screenMaxCharsPerLine];
int tftRow[screenMaxLines];
// custom function defines with default values
void cls(int color = c_black, int rotation = 0, int tsRotation = 2); // Set some defaults (SD pins at top of display) touchscreen rotation differs from actual display
void setup() {
Serial.begin(9600);
//start the display and touchscreen
tft.begin();
ts.begin();
// setup easy access for text positions using rows and columns
for (byte i = 0; i < screenMaxCharsPerLine; i++){
tftCol[i] = (cpadding+(i*fntWidth));
}
for (byte i = 0; i < screenMaxLines; i++){
tftRow[i] = (rpadding+(i*fntHeight));
}
// blank the screen to black, set color (fg and bg) to defaults
tft.fillScreen(c_black);
tft.setTextColor(c_white, c_black);
tft.setTextWrap(false);
cls();
// create buttons
for (uint8_t row=0; row<5; row++) {
for (uint8_t col=0; col<3; col++) {
buttons[col + row*3].initButton(&tft, BUTTON_X+col*(BUTTON_W+BUTTON_SPACING_X),
BUTTON_Y+row*(BUTTON_H+BUTTON_SPACING_Y), // x, y, w, h, outline, fill, text
BUTTON_W, BUTTON_H, c_white, buttoncolors[col+row*3], c_white,
buttonlabels[col + row*3], BUTTON_TEXTSIZE);
buttons[col + row*3].drawButton();
}
}
// create 'text field'
tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, c_white);
}
void loop() {
//drawNumpad(); // using FONA code from Adafruit for the Keypad
//checkTouch();
TS_Point p;
if (ts.bufferSize()){
p = ts.getPoint();
} else {
// this is our way of tracking touch 'release'!
p.x = p.y = p.z = -1;
}
// Scale from ~0->4000 to tft.width using the calibration #'s
if (p.z != -1) {
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
Serial.print("("); Serial.print(p.x); Serial.print(", ");
Serial.print(p.y); Serial.print(", ");
Serial.print(p.z); Serial.println(") ");
}
// go thru all the buttons, checking if they were pressed
for (uint8_t b=0; b<15; b++) {
if (buttons[b].contains(p.x, p.y)) {
Serial.print("Pressing: "); Serial.println(b);
buttons[b].press(true); // tell the button it is pressed
} else {
buttons[b].press(false); // tell the button it is NOT pressed
}
}
// now we can ask the buttons if their state has changed
for (uint8_t b=0; b<15; b++) {
if (buttons[b].justReleased()) {
Serial.print("Released: "); Serial.println(b);
buttons[b].drawButton(); // draw normal
}
if (buttons[b].justPressed()) {
buttons[b].drawButton(true); // draw invert!
// if a numberpad button, append the relevant # to the textfield
if (b >= 3) {
if (textfield_i < TEXT_LEN) {
textfield[textfield_i] = buttonlabels[b][0];
textfield_i++;
textfield[textfield_i] = 0; // zero terminate
//fona.playDTMF(buttonlabels[b][0]);
}
}
// clr button! delete char
if (b == 1) {
textfield[textfield_i] = 0;
if (textfield > 0) {
textfield_i--;
textfield[textfield_i] = ' ';
}
}
// update the current text field
//Serial.println(textfield);
tft.setCursor(TEXT_X + 2, TEXT_Y+10);
tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
tft.setTextSize(TEXT_TSIZE);
tft.print(textfield);
// its always OK to just hang up
if (b == 2) {
status(F("Hanging up"));
//fona.hangUp();
}
// we dont really check that the text field makes sense
// just try to call
if (b == 0) {
status(F("Sending"));
Serial.print("Sending "); Serial.print(textfield);
}
delay(100); // UI debouncing
}
}
}
void drawNumpad(){
tft.setTextColor(c_white,c_navy);
//OK/ENTER_key
tft.fillRoundRect(20, 260, 80, 40, 10, c_navy);
tft.drawRoundRect(20, 260, 80, 40, 10, c_maroon);
pl("ENTER",35,7);
//Period_key
tft.fillRoundRect(140,260,40,40,10,c_navy);
tft.drawRoundRect(140,260,40,40,10,c_maroon);
tft.setTextColor(c_white, c_black);
}
void checkTouch(){
if(ts.bufferEmpty()){
return;
}
// just testing, menu is not yet selectable
TS_Point p = ts.getPoint();
p.x = map(p.x, TS_MINX, TS_MAXX, 0, screenWidth);
p.y = map(p.y, TS_MINY, TS_MAXY, 0, screenHeight);
String sx = "X = " + String(p.x) + " ";
String sy = "Y = " + String(p.y) + " ";
pl(sx, 0, 0);
pl(sy, 1, 0);
}
void uprint(String txt, int fg_color, int bg_color, int lineNumber, int columnNumber){
tft.setTextColor(fg_color, bg_color);
pl(txt, lineNumber, columnNumber);
}
// Print a string based on line and column number calculated in the arrays
void pl(String txt, int lineNumber, int columnNumber){
tft.setCursor(tftCol[columnNumber], tftRow[lineNumber]);
tft.print(txt);
}
// Clear the screen with screen rotation
void cls(int color, int rotation, int tsRotation){
tft.setRotation(rotation);
ts.setRotation(tsRotation);
tft.fillScreen(color);
}
namedColors.h
Code:
#define c_black ILI9341_BLACK
#define c_navy ILI9341_NAVY
#define c_darkgreen ILI9341_DARKGREEN
#define c_darkcyan ILI9341_DARKCYAN
#define c_maroon ILI9341_MAROON
#define c_purple ILI9341_PURPLE
#define c_olive ILI9341_OLIVE
#define c_lightgrey ILI9341_LIGHTGREY
#define c_darkgrey ILI9341_DARKGREY
#define c_blue ILI9341_BLUE
#define c_green ILI9341_GREEN
#define c_cyan ILI9341_CYAN
#define c_red ILI9341_RED
#define c_magenta ILI9341_MAGENTA
#define c_yellow ILI9341_YELLOW
#define c_white ILI9341_WHITE
#define c_orange ILI9341_ORANGE
#define c_greenyellow ILI9341_GREENYELLOW
#define c_pink ILI9341_PINK
/*
// from https://cgit.freedesktop.org/xorg/app/rgb/tree/rgb.txt
// converted with http://www.rinkydinkelectronics.com/calc_rgb565.php
*/
#define c_AliceBlue 0xF7DF
#define c_Snow 0xFFDF