mirror of
https://github.com/0015/ThatProject.git
synced 2026-01-12 09:17:42 +03:00
ESP32 | LittlevGL | Arduino IDE - [Part.0] Touch Display Setup for Simple Note App📝
This commit is contained in:
@@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
Adapted from the Adafruit graphicstest sketch, see orignal header at end
|
||||||
|
of sketch.
|
||||||
|
|
||||||
|
This sketch uses the GLCD font (font 1) only.
|
||||||
|
|
||||||
|
Make sure all the display driver and pin comnenctions are correct by
|
||||||
|
editting the User_Setup.h file in the TFT_eSPI library folder.
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||||
|
#########################################################################
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "SPI.h"
|
||||||
|
#include "TFT_eSPI.h"
|
||||||
|
|
||||||
|
TFT_eSPI tft = TFT_eSPI();
|
||||||
|
|
||||||
|
unsigned long total = 0;
|
||||||
|
unsigned long tn = 0;
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
while (!Serial);
|
||||||
|
|
||||||
|
Serial.println(""); Serial.println("");
|
||||||
|
Serial.println("TFT_eSPI library test!");
|
||||||
|
|
||||||
|
tft.init();
|
||||||
|
|
||||||
|
tn = micros();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
yield(); Serial.println(F("Benchmark Time (microseconds)"));
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Screen fill "));
|
||||||
|
yield(); Serial.println(testFillScreen());
|
||||||
|
//total+=testFillScreen();
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Text "));
|
||||||
|
yield(); Serial.println(testText());
|
||||||
|
//total+=testText();
|
||||||
|
//delay(3000);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Lines "));
|
||||||
|
yield(); Serial.println(testLines(TFT_CYAN));
|
||||||
|
//total+=testLines(TFT_CYAN);
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Horiz/Vert Lines "));
|
||||||
|
yield(); Serial.println(testFastLines(TFT_RED, TFT_BLUE));
|
||||||
|
//total+=testFastLines(TFT_RED, TFT_BLUE);
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Rectangles (outline) "));
|
||||||
|
yield(); Serial.println(testRects(TFT_GREEN));
|
||||||
|
//total+=testRects(TFT_GREEN);
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Rectangles (filled) "));
|
||||||
|
yield(); Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
|
||||||
|
//total+=testFilledRects(TFT_YELLOW, TFT_MAGENTA);
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Circles (filled) "));
|
||||||
|
yield(); Serial.println(testFilledCircles(10, TFT_MAGENTA));
|
||||||
|
//total+= testFilledCircles(10, TFT_MAGENTA);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Circles (outline) "));
|
||||||
|
yield(); Serial.println(testCircles(10, TFT_WHITE));
|
||||||
|
//total+=testCircles(10, TFT_WHITE);
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Triangles (outline) "));
|
||||||
|
yield(); Serial.println(testTriangles());
|
||||||
|
//total+=testTriangles();
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Triangles (filled) "));
|
||||||
|
yield(); Serial.println(testFilledTriangles());
|
||||||
|
//total += testFilledTriangles();
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Rounded rects (outline) "));
|
||||||
|
yield(); Serial.println(testRoundRects());
|
||||||
|
//total+=testRoundRects();
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.print(F("Rounded rects (filled) "));
|
||||||
|
yield(); Serial.println(testFilledRoundRects());
|
||||||
|
//total+=testFilledRoundRects();
|
||||||
|
//delay(500);
|
||||||
|
|
||||||
|
yield(); Serial.println(F("Done!")); yield();
|
||||||
|
//Serial.print(F("Total = ")); Serial.println(total);
|
||||||
|
|
||||||
|
//yield();Serial.println(millis()-tn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
for (uint8_t rotation = 0; rotation < 4; rotation++) {
|
||||||
|
tft.setRotation(rotation);
|
||||||
|
testText();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long testFillScreen() {
|
||||||
|
unsigned long start = micros();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
tft.fillScreen(TFT_RED);
|
||||||
|
tft.fillScreen(TFT_GREEN);
|
||||||
|
tft.fillScreen(TFT_BLUE);
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testText() {
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
unsigned long start = micros();
|
||||||
|
tft.setCursor(0, 0);
|
||||||
|
tft.setTextColor(TFT_WHITE); tft.setTextSize(1);
|
||||||
|
tft.println("Hello World!");
|
||||||
|
tft.setTextColor(TFT_YELLOW); tft.setTextSize(2);
|
||||||
|
tft.println(1234.56);
|
||||||
|
tft.setTextColor(TFT_RED); tft.setTextSize(3);
|
||||||
|
tft.println(0xDEADBEEF, HEX);
|
||||||
|
tft.println();
|
||||||
|
tft.setTextColor(TFT_GREEN);
|
||||||
|
tft.setTextSize(5);
|
||||||
|
tft.println("Groop");
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("I implore thee,");
|
||||||
|
//tft.setTextColor(TFT_GREEN,TFT_BLACK);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.println("my foonting turlingdromes.");
|
||||||
|
tft.println("And hooptiously drangle me");
|
||||||
|
tft.println("with crinkly bindlewurdles,");
|
||||||
|
tft.println("Or I will rend thee");
|
||||||
|
tft.println("in the gobberwarts");
|
||||||
|
tft.println("with my blurglecruncheon,");
|
||||||
|
tft.println("see if I don't!");
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testLines(uint16_t color) {
|
||||||
|
unsigned long start, t;
|
||||||
|
int x1, y1, x2, y2,
|
||||||
|
w = tft.width(),
|
||||||
|
h = tft.height();
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
x1 = y1 = 0;
|
||||||
|
y2 = h - 1;
|
||||||
|
start = micros();
|
||||||
|
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = w - 1;
|
||||||
|
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t = micros() - start; // fillScreen doesn't count against timing
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
x1 = w - 1;
|
||||||
|
y1 = 0;
|
||||||
|
y2 = h - 1;
|
||||||
|
start = micros();
|
||||||
|
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = 0;
|
||||||
|
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t += micros() - start;
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
x1 = 0;
|
||||||
|
y1 = h - 1;
|
||||||
|
y2 = 0;
|
||||||
|
start = micros();
|
||||||
|
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = w - 1;
|
||||||
|
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t += micros() - start;
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
x1 = w - 1;
|
||||||
|
y1 = h - 1;
|
||||||
|
y2 = 0;
|
||||||
|
start = micros();
|
||||||
|
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = 0;
|
||||||
|
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
yield();
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, w = tft.width(), h = tft.height();
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
|
||||||
|
for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testRects(uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int n, i, i2,
|
||||||
|
cx = tft.width() / 2,
|
||||||
|
cy = tft.height() / 2;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
n = min(tft.width(), tft.height());
|
||||||
|
start = micros();
|
||||||
|
for (i = 2; i < n; i += 6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.drawRect(cx - i2, cy - i2, i, i, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
|
||||||
|
unsigned long start, t = 0;
|
||||||
|
int n, i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
n = min(tft.width(), tft.height());
|
||||||
|
for (i = n - 1; i > 0; i -= 6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
start = micros();
|
||||||
|
tft.fillRect(cx - i2, cy - i2, i, i, color1);
|
||||||
|
t += micros() - start;
|
||||||
|
// Outlines are not included in timing results
|
||||||
|
tft.drawRect(cx - i2, cy - i2, i, i, color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for (x = radius; x < w; x += r2) {
|
||||||
|
for (y = radius; y < h; y += r2) {
|
||||||
|
tft.fillCircle(x, y, radius, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testCircles(uint8_t radius, uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, r2 = radius * 2,
|
||||||
|
w = tft.width() + radius,
|
||||||
|
h = tft.height() + radius;
|
||||||
|
|
||||||
|
// Screen is not cleared for this one -- this is
|
||||||
|
// intentional and does not affect the reported time.
|
||||||
|
start = micros();
|
||||||
|
for (x = 0; x < w; x += r2) {
|
||||||
|
for (y = 0; y < h; y += r2) {
|
||||||
|
tft.drawCircle(x, y, radius, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testTriangles() {
|
||||||
|
unsigned long start;
|
||||||
|
int n, i, cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
n = min(cx, cy);
|
||||||
|
start = micros();
|
||||||
|
for (i = 0; i < n; i += 5) {
|
||||||
|
tft.drawTriangle(
|
||||||
|
cx , cy - i, // peak
|
||||||
|
cx - i, cy + i, // bottom left
|
||||||
|
cx + i, cy + i, // bottom right
|
||||||
|
tft.color565(0, 0, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledTriangles() {
|
||||||
|
unsigned long start, t = 0;
|
||||||
|
int i, cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for (i = min(cx, cy); i > 10; i -= 5) {
|
||||||
|
start = micros();
|
||||||
|
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||||
|
tft.color565(0, i, i));
|
||||||
|
t += micros() - start;
|
||||||
|
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||||
|
tft.color565(i, i, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testRoundRects() {
|
||||||
|
unsigned long start;
|
||||||
|
int w, i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
w = min(tft.width(), tft.height());
|
||||||
|
start = micros();
|
||||||
|
for (i = 0; i < w; i += 6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(i, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledRoundRects() {
|
||||||
|
unsigned long start;
|
||||||
|
int i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for (i = min(tft.width(), tft.height()); i > 20; i -= 6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(0, i, 0));
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
Original Adafruit text:
|
||||||
|
|
||||||
|
This is an example sketch for the Adafruit 2.2" SPI display.
|
||||||
|
This library works with the Adafruit 2.2" TFT Breakout w/SD card
|
||||||
|
----> http://www.adafruit.com/products/1480
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||||
|
interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing
|
||||||
|
products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
****************************************************/
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "SPIFFS.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <TFT_eSPI.h>
|
||||||
|
TFT_eSPI tft = TFT_eSPI();
|
||||||
|
|
||||||
|
#define CALIBRATION_FILE "/calibrationData"
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
uint16_t calibrationData[5];
|
||||||
|
uint8_t calDataOK = 0;
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("starting");
|
||||||
|
|
||||||
|
tft.init();
|
||||||
|
|
||||||
|
tft.setRotation(3);
|
||||||
|
tft.fillScreen((0xFFFF));
|
||||||
|
|
||||||
|
tft.setCursor(20, 0, 2);
|
||||||
|
tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextSize(1);
|
||||||
|
tft.println("calibration run");
|
||||||
|
|
||||||
|
// check file system
|
||||||
|
if (SPIFFS.begin(true)) { // always formatting
|
||||||
|
Serial.println("formating file system");
|
||||||
|
|
||||||
|
SPIFFS.format();
|
||||||
|
SPIFFS.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if calibration file exists
|
||||||
|
if (SPIFFS.exists(CALIBRATION_FILE)) {
|
||||||
|
File f = SPIFFS.open(CALIBRATION_FILE, "r");
|
||||||
|
if (f) {
|
||||||
|
if (f.readBytes((char *)calibrationData, 14) == 14)
|
||||||
|
calDataOK = 1;
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (calDataOK) {
|
||||||
|
// calibration data valid
|
||||||
|
tft.setTouch(calibrationData);
|
||||||
|
} else {
|
||||||
|
// data not valid. recalibrate
|
||||||
|
tft.calibrateTouch(calibrationData, TFT_WHITE, TFT_RED, 15);
|
||||||
|
// store data
|
||||||
|
File f = SPIFFS.open(CALIBRATION_FILE, "w");
|
||||||
|
if (f) {
|
||||||
|
f.write((const unsigned char *)calibrationData, 14);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<5; i++){
|
||||||
|
Serial.printf("%d,%d\n",i, calibrationData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tft.fillScreen((0xFFFF));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
uint16_t x, y;
|
||||||
|
static uint16_t color;
|
||||||
|
|
||||||
|
if (tft.getTouch(&x, &y)) {
|
||||||
|
|
||||||
|
tft.setCursor(5, 5, 2);
|
||||||
|
tft.printf("x: %i ", x);
|
||||||
|
tft.setCursor(5, 20, 2);
|
||||||
|
tft.printf("y: %i ", y);
|
||||||
|
|
||||||
|
tft.drawPixel(x, y, color);
|
||||||
|
color += 155;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
The TFT_eSPI library incorporates an Adafruit_GFX compatible
|
||||||
|
button handling class, this sketch is based on the Arduin-o-phone
|
||||||
|
example.
|
||||||
|
|
||||||
|
This example diplays a keypad where numbers can be entered and
|
||||||
|
send to the Serial Monitor window.
|
||||||
|
|
||||||
|
The sketch has been tested on the ESP8266 (which supports SPIFFS)
|
||||||
|
|
||||||
|
The minimum screen size is 320 x 240 as that is the keypad size.
|
||||||
|
|
||||||
|
TOUCH_CS and SPI_TOUCH_FREQUENCY must be defined in the User_Setup.h file
|
||||||
|
for the touch functions to do anything.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The SPIFFS (FLASH filing system) is used to hold touch screen
|
||||||
|
// calibration data
|
||||||
|
|
||||||
|
#include "FS.h"
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <TFT_eSPI.h> // Hardware-specific library
|
||||||
|
|
||||||
|
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
|
||||||
|
|
||||||
|
// This is the file name used to store the calibration data
|
||||||
|
// You can change this to create new calibration files.
|
||||||
|
// The SPIFFS file name must start with "/".
|
||||||
|
#define CALIBRATION_FILE "/TouchCalData2"
|
||||||
|
|
||||||
|
// Set REPEAT_CAL to true instead of false to run calibration
|
||||||
|
// again, otherwise it will only be done once.
|
||||||
|
// Repeat calibration if you change the screen rotation.
|
||||||
|
#define REPEAT_CAL false
|
||||||
|
|
||||||
|
// Keypad start position, key sizes and spacing
|
||||||
|
#define KEY_X 40 // Centre of key
|
||||||
|
#define KEY_Y 96
|
||||||
|
#define KEY_W 62 // Width and height
|
||||||
|
#define KEY_H 30
|
||||||
|
#define KEY_SPACING_X 18 // X and Y gap
|
||||||
|
#define KEY_SPACING_Y 20
|
||||||
|
#define KEY_TEXTSIZE 1 // Font size multiplier
|
||||||
|
|
||||||
|
// Using two fonts since numbers are nice when bold
|
||||||
|
#define LABEL1_FONT &FreeSansOblique12pt7b // Key label font 1
|
||||||
|
#define LABEL2_FONT &FreeSansBold12pt7b // Key label font 2
|
||||||
|
|
||||||
|
// Numeric display box size and location
|
||||||
|
#define DISP_X 1
|
||||||
|
#define DISP_Y 10
|
||||||
|
#define DISP_W 238
|
||||||
|
#define DISP_H 50
|
||||||
|
#define DISP_TSIZE 3
|
||||||
|
#define DISP_TCOLOR TFT_CYAN
|
||||||
|
|
||||||
|
// Number length, buffer for storing it and character index
|
||||||
|
#define NUM_LEN 12
|
||||||
|
char numberBuffer[NUM_LEN + 1] = "";
|
||||||
|
uint8_t numberIndex = 0;
|
||||||
|
|
||||||
|
// We have a status line for messages
|
||||||
|
#define STATUS_X 120 // Centred on this
|
||||||
|
#define STATUS_Y 65
|
||||||
|
|
||||||
|
// Create 15 keys for the keypad
|
||||||
|
char keyLabel[15][5] = {"New", "Del", "Send", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "#" };
|
||||||
|
uint16_t keyColor[15] = {TFT_RED, TFT_DARKGREY, TFT_DARKGREEN,
|
||||||
|
TFT_BLUE, TFT_BLUE, TFT_BLUE,
|
||||||
|
TFT_BLUE, TFT_BLUE, TFT_BLUE,
|
||||||
|
TFT_BLUE, TFT_BLUE, TFT_BLUE,
|
||||||
|
TFT_BLUE, TFT_BLUE, TFT_BLUE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke the TFT_eSPI button class and create all the button objects
|
||||||
|
TFT_eSPI_Button key[15];
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// Use serial port
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Initialise the TFT screen
|
||||||
|
tft.init();
|
||||||
|
|
||||||
|
// Set the rotation before we calibrate
|
||||||
|
tft.setRotation(3);
|
||||||
|
|
||||||
|
// Calibrate the touch screen and retrieve the scaling factors
|
||||||
|
//touch_calibrate();
|
||||||
|
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||||
|
tft.setTouch(calData);
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
// Draw keypad background
|
||||||
|
tft.fillRect(0, 0, 240, 320, TFT_DARKGREY);
|
||||||
|
|
||||||
|
// Draw number display area and frame
|
||||||
|
tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK);
|
||||||
|
tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE);
|
||||||
|
|
||||||
|
// Draw keypad
|
||||||
|
drawKeypad();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
|
||||||
|
|
||||||
|
// Pressed will be set true is there is a valid touch on the screen
|
||||||
|
boolean pressed = tft.getTouch(&t_x, &t_y);
|
||||||
|
|
||||||
|
// / Check if any key coordinate boxes contain the touch coordinates
|
||||||
|
for (uint8_t b = 0; b < 15; b++) {
|
||||||
|
if (pressed && key[b].contains(t_x, t_y)) {
|
||||||
|
key[b].press(true); // tell the button it is pressed
|
||||||
|
} else {
|
||||||
|
key[b].press(false); // tell the button it is NOT pressed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if any key has changed state
|
||||||
|
for (uint8_t b = 0; b < 15; b++) {
|
||||||
|
|
||||||
|
if (b < 3) tft.setFreeFont(LABEL1_FONT);
|
||||||
|
else tft.setFreeFont(LABEL2_FONT);
|
||||||
|
|
||||||
|
if (key[b].justReleased()) key[b].drawButton(); // draw normal
|
||||||
|
|
||||||
|
if (key[b].justPressed()) {
|
||||||
|
key[b].drawButton(true); // draw invert
|
||||||
|
|
||||||
|
// if a numberpad button, append the relevant # to the numberBuffer
|
||||||
|
if (b >= 3) {
|
||||||
|
if (numberIndex < NUM_LEN) {
|
||||||
|
numberBuffer[numberIndex] = keyLabel[b][0];
|
||||||
|
numberIndex++;
|
||||||
|
numberBuffer[numberIndex] = 0; // zero terminate
|
||||||
|
}
|
||||||
|
status(""); // Clear the old status
|
||||||
|
}
|
||||||
|
|
||||||
|
// Del button, so delete last char
|
||||||
|
if (b == 1) {
|
||||||
|
numberBuffer[numberIndex] = 0;
|
||||||
|
if (numberIndex > 0) {
|
||||||
|
numberIndex--;
|
||||||
|
numberBuffer[numberIndex] = 0;//' ';
|
||||||
|
}
|
||||||
|
status(""); // Clear the old status
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b == 2) {
|
||||||
|
status("Sent value to serial port");
|
||||||
|
Serial.println(numberBuffer);
|
||||||
|
}
|
||||||
|
// we dont really check that the text field makes sense
|
||||||
|
// just try to call
|
||||||
|
if (b == 0) {
|
||||||
|
status("Value cleared");
|
||||||
|
numberIndex = 0; // Reset index to 0
|
||||||
|
numberBuffer[numberIndex] = 0; // Place null in buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the number display field
|
||||||
|
tft.setTextDatum(TL_DATUM); // Use top left corner as text coord datum
|
||||||
|
tft.setFreeFont(&FreeSans18pt7b); // Choose a nicefont that fits box
|
||||||
|
tft.setTextColor(DISP_TCOLOR); // Set the font colour
|
||||||
|
|
||||||
|
// Draw the string, the value returned is the width in pixels
|
||||||
|
int xwidth = tft.drawString(numberBuffer, DISP_X + 4, DISP_Y + 12);
|
||||||
|
|
||||||
|
// Now cover up the rest of the line up by drawing a black rectangle. No flicker this way
|
||||||
|
// but it will not work with italic or oblique fonts due to character overlap.
|
||||||
|
tft.fillRect(DISP_X + 4 + xwidth, DISP_Y + 1, DISP_W - xwidth - 5, DISP_H - 2, TFT_BLACK);
|
||||||
|
|
||||||
|
delay(10); // UI debouncing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawKeypad()
|
||||||
|
{
|
||||||
|
// Draw the keys
|
||||||
|
for (uint8_t row = 0; row < 5; row++) {
|
||||||
|
for (uint8_t col = 0; col < 3; col++) {
|
||||||
|
uint8_t b = col + row * 3;
|
||||||
|
|
||||||
|
if (b < 3) tft.setFreeFont(LABEL1_FONT);
|
||||||
|
else tft.setFreeFont(LABEL2_FONT);
|
||||||
|
|
||||||
|
key[b].initButton(&tft, KEY_X + col * (KEY_W + KEY_SPACING_X),
|
||||||
|
KEY_Y + row * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
|
||||||
|
KEY_W, KEY_H, TFT_WHITE, keyColor[b], TFT_WHITE,
|
||||||
|
keyLabel[b], KEY_TEXTSIZE);
|
||||||
|
key[b].drawButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void touch_calibrate()
|
||||||
|
{
|
||||||
|
uint16_t calData[5];
|
||||||
|
uint8_t calDataOK = 0;
|
||||||
|
|
||||||
|
// check file system exists
|
||||||
|
if (!SPIFFS.begin()) {
|
||||||
|
Serial.println("Formating file system");
|
||||||
|
SPIFFS.format();
|
||||||
|
SPIFFS.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if calibration file exists and size is correct
|
||||||
|
if (SPIFFS.exists(CALIBRATION_FILE)) {
|
||||||
|
if (REPEAT_CAL)
|
||||||
|
{
|
||||||
|
// Delete if we want to re-calibrate
|
||||||
|
SPIFFS.remove(CALIBRATION_FILE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File f = SPIFFS.open(CALIBRATION_FILE, "r");
|
||||||
|
if (f) {
|
||||||
|
if (f.readBytes((char *)calData, 14) == 14)
|
||||||
|
calDataOK = 1;
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calDataOK && !REPEAT_CAL) {
|
||||||
|
// calibration data valid
|
||||||
|
tft.setTouch(calData);
|
||||||
|
} else {
|
||||||
|
// data not valid so recalibrate
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
tft.setCursor(20, 0);
|
||||||
|
tft.setTextFont(2);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||||
|
|
||||||
|
tft.println("Touch corners as indicated");
|
||||||
|
|
||||||
|
tft.setTextFont(1);
|
||||||
|
tft.println();
|
||||||
|
|
||||||
|
if (REPEAT_CAL) {
|
||||||
|
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||||
|
tft.println("Set REPEAT_CAL to false to stop this running again!");
|
||||||
|
}
|
||||||
|
|
||||||
|
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
|
||||||
|
|
||||||
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
|
tft.println("Calibration complete!");
|
||||||
|
|
||||||
|
// store data
|
||||||
|
File f = SPIFFS.open(CALIBRATION_FILE, "w");
|
||||||
|
if (f) {
|
||||||
|
f.write((const unsigned char *)calData, 14);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Print something in the mini status bar
|
||||||
|
void status(const char *msg) {
|
||||||
|
tft.setTextPadding(240);
|
||||||
|
//tft.setCursor(STATUS_X, STATUS_Y);
|
||||||
|
tft.setTextColor(TFT_WHITE, TFT_DARKGREY);
|
||||||
|
tft.setTextFont(0);
|
||||||
|
tft.setTextDatum(TC_DATUM);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.drawString(msg, STATUS_X, STATUS_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#include <lvgl.h>
|
||||||
|
#include <Ticker.h>
|
||||||
|
#include <TFT_eSPI.h>
|
||||||
|
|
||||||
|
#define LVGL_TICK_PERIOD 20
|
||||||
|
|
||||||
|
Ticker tick; /* timer for interrupt handler */
|
||||||
|
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
|
||||||
|
static lv_disp_buf_t disp_buf;
|
||||||
|
static lv_color_t buf[LV_HOR_RES_MAX * 10];
|
||||||
|
|
||||||
|
#if USE_LV_LOG != 0
|
||||||
|
/* Serial debugging */
|
||||||
|
void my_print(lv_log_level_t level, const char * file, uint32_t line, const char * dsc)
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.printf("%s@%d->%s\r\n", file, line, dsc);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Display flushing */
|
||||||
|
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
|
||||||
|
{
|
||||||
|
uint16_t c;
|
||||||
|
|
||||||
|
tft.startWrite(); /* Start new TFT transaction */
|
||||||
|
tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
|
||||||
|
for (int y = area->y1; y <= area->y2; y++) {
|
||||||
|
for (int x = area->x1; x <= area->x2; x++) {
|
||||||
|
c = color_p->full;
|
||||||
|
tft.writeColor(c, 1);
|
||||||
|
color_p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tft.endWrite(); /* terminate TFT transaction */
|
||||||
|
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interrupt driven periodic handler */
|
||||||
|
static void lv_tick_handler(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reading input device (simulated encoder here) */
|
||||||
|
bool read_encoder(lv_indev_drv_t * indev, lv_indev_data_t * data)
|
||||||
|
{
|
||||||
|
static int32_t last_diff = 0;
|
||||||
|
int32_t diff = 0; /* Dummy - no movement */
|
||||||
|
int btn_state = LV_INDEV_STATE_REL; /* Dummy - no press */
|
||||||
|
|
||||||
|
data->enc_diff = diff - last_diff;;
|
||||||
|
data->state = btn_state;
|
||||||
|
|
||||||
|
last_diff = diff;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(115200); /* prepare for possible serial debug */
|
||||||
|
|
||||||
|
lv_init();
|
||||||
|
|
||||||
|
#if USE_LV_LOG != 0
|
||||||
|
lv_log_register_print(my_print); /* register print function for debugging */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tft.begin(); /* TFT init */
|
||||||
|
tft.setRotation(3); /* Landscape orientation */
|
||||||
|
|
||||||
|
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
|
||||||
|
|
||||||
|
/*Initialize the display*/
|
||||||
|
lv_disp_drv_t disp_drv;
|
||||||
|
lv_disp_drv_init(&disp_drv);
|
||||||
|
disp_drv.hor_res = 480;
|
||||||
|
disp_drv.ver_res = 320;
|
||||||
|
disp_drv.flush_cb = my_disp_flush;
|
||||||
|
disp_drv.buffer = &disp_buf;
|
||||||
|
lv_disp_drv_register(&disp_drv);
|
||||||
|
|
||||||
|
|
||||||
|
/*Initialize the touch pad*/
|
||||||
|
lv_indev_drv_t indev_drv;
|
||||||
|
lv_indev_drv_init(&indev_drv);
|
||||||
|
indev_drv.type = LV_INDEV_TYPE_ENCODER;
|
||||||
|
indev_drv.read_cb = read_encoder;
|
||||||
|
lv_indev_drv_register(&indev_drv);
|
||||||
|
|
||||||
|
/*Initialize the graphics library's tick*/
|
||||||
|
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||||
|
|
||||||
|
/* Create simple label */
|
||||||
|
lv_obj_t *label = lv_label_create(lv_scr_act(), NULL);
|
||||||
|
lv_label_set_text(label, "Hello Arduino! (V6.1)");
|
||||||
|
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
lv_task_handler(); /* let the GUI do its work */
|
||||||
|
delay(5);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user