diff --git a/LICENSE b/LICENSE index c2a8edc..a1af433 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,18 @@ -MIT License - -Copyright (c) 2022 Rodrigo Garcia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Copyright 2022 Rodrigo Garcia + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/examples/CapTouchPaint/CapTouchPaint.ino b/examples/CapTouchPaint/CapTouchPaint.ino new file mode 100644 index 0000000..0b38de0 --- /dev/null +++ b/examples/CapTouchPaint/CapTouchPaint.ino @@ -0,0 +1,118 @@ +/* + This sketch targets the ESP32-S3-BOX board ONLY + It demonstrates a compatible Touch Screen sketch +*/ + +// Testing if the user has selected the right board in the menu +#ifndef TT21100_ADDR +#error Please select the right board in the Arduino IDE: ESP32-S3-Box +#endif + +#include "ESP32_S3_Box_TFT.h" +#include "ESP32_S3_Box_TouchScreen.h" + +ESP32S3BOX_TFT tft = ESP32S3BOX_TFT(); +ESP32S3BOX_TS ts = ESP32S3BOX_TS(); + +// Size of the color selection boxes and the paintbrush size +#define BOXSIZE 40 +#define PENRADIUS 3 +int oldcolor, currentcolor; + +void setup(void) { + Serial.begin(115200); + delay(500); + + Serial.println("Cap Touch Paint!"); + + tft.init(); + + if (! ts.begin()) { + Serial.println("Couldn't start TT21100 touchscreen controller"); + while (1); + } + + Serial.println("Capacitive touchscreen started"); + + tft.fillScreen(ST7789_BLACK); + + // make the color selection boxes + tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ST7789_RED); + tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ST7789_YELLOW); + tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ST7789_GREEN); + tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ST7789_CYAN); + tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ST7789_BLUE); + tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ST7789_MAGENTA); + + // select the current color 'red' + tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + currentcolor = ST7789_RED; +} + +void loop() { + // Wait for a touch + if (! ts.touched()) { + return; + } + + // Retrieve a point + TS_Point p = ts.getPoint(); + + + // Print out raw data from screen touch controller + Serial.print("X = "); Serial.print(p.x); + Serial.print("\tY = "); Serial.print(p.y); + Serial.print(" -> "); + + + // flip X around to match the screen. + p.x = map(p.x, 0, 320, 320, 0); + + // Print out the remapped (rotated) coordinates + Serial.print("("); Serial.print(p.x); + Serial.print(", "); Serial.print(p.y); + Serial.println(")"); + + + if (p.y < BOXSIZE) { + oldcolor = currentcolor; + + if (p.x < BOXSIZE) { + currentcolor = ST7789_RED; + tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } else if (p.x < BOXSIZE*2) { + currentcolor = ST7789_YELLOW; + tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } else if (p.x < BOXSIZE*3) { + currentcolor = ST7789_GREEN; + tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } else if (p.x < BOXSIZE*4) { + currentcolor = ST7789_CYAN; + tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } else if (p.x < BOXSIZE*5) { + currentcolor = ST7789_BLUE; + tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } else if (p.x <= BOXSIZE*6) { + currentcolor = ST7789_MAGENTA; + tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ST7789_WHITE); + } + + if (oldcolor != currentcolor) { + if (oldcolor == ST7789_RED) + tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ST7789_RED); + if (oldcolor == ST7789_YELLOW) + tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ST7789_YELLOW); + if (oldcolor == ST7789_GREEN) + tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ST7789_GREEN); + if (oldcolor == ST7789_CYAN) + tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ST7789_CYAN); + if (oldcolor == ST7789_BLUE) + tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ST7789_BLUE); + if (oldcolor == ST7789_MAGENTA) + tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ST7789_MAGENTA); + } + } + if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) { + tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor); + } +} \ No newline at end of file diff --git a/examples/CapTouch_onoffbutton/CapTouch_onoffbutton.ino b/examples/CapTouch_onoffbutton/CapTouch_onoffbutton.ino new file mode 100644 index 0000000..f50b363 --- /dev/null +++ b/examples/CapTouch_onoffbutton/CapTouch_onoffbutton.ino @@ -0,0 +1,116 @@ +//This example implements a simple sliding On/Off button. The example +// demonstrates drawing and touch operations. + +// Testing if the user has selected the right board in the menu +#ifndef TT21100_ADDR +#error Please select the right board in the Arduino IDE: ESP32-S3-Box +#endif + +#include "ESP32_S3_Box_TFT.h" +#include "ESP32_S3_Box_TouchScreen.h" + +ESP32S3BOX_TFT tft = ESP32S3BOX_TFT(); +ESP32S3BOX_TS ts = ESP32S3BOX_TS(); + +boolean RecordOn = false; + +#define FRAME_X 110 +#define FRAME_Y 130 +#define FRAME_W 200 +#define FRAME_H 100 + +#define REDBUTTON_X FRAME_X +#define REDBUTTON_Y FRAME_Y +#define REDBUTTON_W (FRAME_W/2) +#define REDBUTTON_H FRAME_H + +#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W) +#define GREENBUTTON_Y FRAME_Y +#define GREENBUTTON_W (FRAME_W/2) +#define GREENBUTTON_H FRAME_H + +void drawFrame() +{ + tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ST7789_BLACK); +} + +void redBtn() +{ + tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ST7789_RED); + tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ST7789_BLUE); + drawFrame(); + tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2)); + tft.setTextColor(ST7789_BLACK); + tft.setTextSize(3); + tft.println("ON"); + tft.setCursor(GREENBUTTON_X + 6 + 3 , GREENBUTTON_Y + (GREENBUTTON_H/2) + 2); + tft.setTextColor(ST7789_CYAN); + tft.setTextSize(3); + tft.println("ON"); + RecordOn = false; +} + +void greenBtn() +{ + tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ST7789_GREEN); + tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ST7789_BLUE); + drawFrame(); + tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2)); + tft.setTextColor(ST7789_BLACK); + tft.setTextSize(3); + tft.println("OFF"); + tft.setCursor(REDBUTTON_X + 6 + 3 , REDBUTTON_Y + (REDBUTTON_H/2) + 2); + tft.setTextColor(ST7789_CYAN); + tft.setTextSize(3); + tft.println("OFF"); + RecordOn = true; +} + +void setup(void) +{ + Serial.begin(115200); + tft.init(); + if (!ts.begin()) { + Serial.println("Unable to start touchscreen."); + } + else { + Serial.println("Touchscreen started."); + } + + tft.fillScreen(ST7789_BLACK); + tft.setRotation(0); + redBtn(); +} + +void loop() +{ + // See if there's any touch data for us + if (ts.touched()) + { + // Retrieve a point + TS_Point p = ts.getPoint(); + // flip X around to match the screen. + p.x = map(p.x, 0, 320, 320, 0); + + if (RecordOn) + { + if((p.x > REDBUTTON_X) && (p.x < (REDBUTTON_X + REDBUTTON_W))) { + if ((p.y > REDBUTTON_Y) && (p.y <= (REDBUTTON_Y + REDBUTTON_H))) { + Serial.println("Red btn hit"); + redBtn(); + } + } + } + else //Record is off (RecordOn == false) + { + if((p.x > GREENBUTTON_X) && (p.x < (GREENBUTTON_X + GREENBUTTON_W))) { + if ((p.y > GREENBUTTON_Y) && (p.y <= (GREENBUTTON_Y + GREENBUTTON_H))) { + Serial.println("Green btn hit"); + greenBtn(); + } + } + } + + Serial.println(RecordOn); + } +} \ No newline at end of file diff --git a/examples/GraphicTest/GraphicTest.ino b/examples/GraphicTest/GraphicTest.ino new file mode 100644 index 0000000..41786aa --- /dev/null +++ b/examples/GraphicTest/GraphicTest.ino @@ -0,0 +1,375 @@ +/* + This sketch targets the ESP32-S3-BOX board ONLY + It demonstrates a compatible Adafruit GFX Graphics Library benchmark sketch +*/ + +// Testing if the user has selected the right board in the menu +#ifndef TT21100_ADDR +#error Please select the right board in the Arduino IDE: ESP32-S3-Box +#endif + +#include "ESP32_S3_Box_TFT.h" + +ESP32S3BOX_TFT tft = ESP32S3BOX_TFT(); + +void setup() { + // put your setup code here, to run once: + Serial.begin(115200); + delay(500); + + tft.init(); + tft.setRotation(0); // Landscape orientation + tft.setTextSize(2); + + Serial.println("TFT Initialized."); + + // large block of text + tft.fillScreen(ST7789_BLACK); + tft.setTextWrap(true); + tft.setTextColor(ST7789_WHITE); + + tft.setCursor(0, 0); + tft.print("Hello ESP32S3-Box"); + + tft.setCursor(0, 30); + tft.print("Chip Model: " + String(ESP.getChipModel())); + tft.setCursor(0, 50); + tft.print("rotation: " + String(tft.getRotation())); + tft.setCursor(0, 70); + tft.print(String(tft.width()) + " x " + String(tft.height())); + + delay(4000); + + tft.setTextSize(4); + tft.fillScreen(ST7789_RED); + tft.setCursor(50, 50); + tft.print("RED"); + delay(1000); + tft.fillScreen(ST7789_GREEN); + tft.setCursor(50, 50); + tft.print("GREEN"); + delay(1000); + tft.fillScreen(ST7789_BLUE); + tft.setCursor(50, 50); + tft.print("BLUE"); + delay(1000); + + Serial.println("Benchmark Time (microseconds)"); + delay(10); + Serial.print("Screen fill "); + Serial.println(testFillScreen()); + delay(500); + + Serial.print("Text "); + Serial.println(testText()); + delay(3000); + + Serial.print("Lines "); + Serial.println(testLines(ST7789_CYAN)); + delay(500); + + Serial.print("Horiz/Vert Lines "); + Serial.println(testFastLines(ST7789_RED, ST7789_BLUE)); + delay(500); + + Serial.print("Rectangles (outline) "); + Serial.println(testRects(ST7789_GREEN)); + delay(500); + + Serial.print("Rectangles (filled) "); + Serial.println(testFilledRects(ST7789_YELLOW, ST7789_MAGENTA)); + delay(500); + + Serial.print("Circles (filled) "); + Serial.println(testFilledCircles(10, ST7789_MAGENTA)); + + Serial.print("Circles (outline) "); + Serial.println(testCircles(10, ST7789_WHITE)); + delay(500); + + Serial.print("Triangles (outline) "); + Serial.println(testTriangles()); + delay(500); + + Serial.print("Triangles (filled) "); + Serial.println(testFilledTriangles()); + delay(500); + + Serial.print("Rounded rects (outline) "); + Serial.println(testRoundRects()); + delay(500); + + Serial.print("Rounded rects (filled) "); + Serial.println(testFilledRoundRects()); + delay(500); + + Serial.println("Done!"); +} + +void loop() { + for (uint8_t rotation = 0; rotation < 4; rotation++) { + tft.setRotation(rotation); + testText(); + delay(500); + tft.invertDisplay(true); + delay(500); + tft.invertDisplay(false); + } +} + +unsigned long testFillScreen() { + unsigned long start = micros(); + tft.fillScreen(ST7789_BLACK); + yield(); + tft.fillScreen(ST7789_RED); + yield(); + tft.fillScreen(ST7789_GREEN); + yield(); + tft.fillScreen(ST7789_BLUE); + yield(); + tft.fillScreen(ST7789_BLACK); + yield(); + return micros() - start; +} + +unsigned long testText() { + tft.fillScreen(ST7789_BLACK); + unsigned long start = micros(); + tft.setCursor(0, 0); + tft.setTextColor(ST7789_WHITE); tft.setTextSize(1); + tft.println("Hello World!"); + tft.setTextColor(ST7789_YELLOW); tft.setTextSize(2); + tft.println(1234.56); + tft.setTextColor(ST7789_RED); tft.setTextSize(3); + tft.println(0xDEADBEEF, HEX); + tft.println(); + tft.setTextColor(ST7789_GREEN); + tft.setTextSize(5); + tft.println("Groop"); + tft.setTextSize(2); + tft.println("I implore thee,"); + 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(ST7789_BLACK); + yield(); + + 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(ST7789_BLACK); + yield(); + + 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(ST7789_BLACK); + yield(); + + 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(ST7789_BLACK); + yield(); + + 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(ST7789_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(ST7789_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(ST7789_BLACK); + n = min(tft.width(), tft.height()); + for (i = n; 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); + yield(); + } + + 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(ST7789_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(ST7789_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(i, i, 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(ST7789_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 * 10, i * 10)); + t += micros() - start; + tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, + tft.color565(i * 10, i * 10, 0)); + yield(); + } + + return t; +} + +unsigned long testRoundRects() { + unsigned long start; + int w, i, i2, + cx = tft.width() / 2 - 1, + cy = tft.height() / 2 - 1; + + tft.fillScreen(ST7789_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(ST7789_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; +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..aa45768 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,40 @@ +###################################### +# Syntax Coloring Map For ESP32S3-BOX +###################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +TS_Point KEYWORD1 TS_Point +ESP32S3BOX_TS KEYWORD1 ESP32S3BOX_TS +ESP32S3BOX_TFT KEYWORD1 ESP32S3BOX_TFT + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +init KEYWORD2 +setRotation KEYWORD2 +setAddrWindow KEYWORD2 +enableDisplay KEYWORD2 +enableTearing KEYWORD2 +enableSleep KEYWORD2 +begin KEYWORD2 +touched KEYWORD2 +getPoint KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +ESP32S3BOX_TFTWIDTH LITERAL1 +ESP32S3BOX_TFTHEIGHT LITERAL1 +ST7789_BLACK LITERAL1 +ST7789_WHITE LITERAL1 +ST7789_RED LITERAL1 +ST7789_GREEN LITERAL1 +ST7789_BLUE LITERAL1 +ST7789_CYAN LITERAL1 +ST7789_MAGENTA LITERAL1 +ST7789_YELLOW LITERAL1 +ST7789_ORANGE LITERAL1 \ No newline at end of file diff --git a/library.json b/library.json new file mode 100644 index 0000000..3e60a3c --- /dev/null +++ b/library.json @@ -0,0 +1,21 @@ +{ + "name": "ESP32S3_BOX TFT Touch", + "keywords": "Adafruit GFX Capacitive Touch Screen TT21100 TFT Display ST7789 320x240", + "description": "Adafruit GFX SPI compatible library for the ESP32S3-BOX board with Touch Screen driver. TFT ST7789 320x240. Capacitive Touch Screen TT21100", + "license": "MIT", + "repository": + { + "type": "git", + "url": "https://github.com/SuGlider/Adafruit_ESP32S3_BOX" + }, + "authors": + [ + { + "name": "Rodrigo Garcia", + "maintainer": true + } + ], + "version": "1.0.0", + "frameworks": "arduino", + "platforms": "espressif32" +} \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..5b5e1c3 --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=ESP32S3_BOX TFT Touch +version=1.0.0 +author=Rodrigo Garcia +maintainer=Rodrigo Garcia +sentence=ESP32S3-Box board drivers. +paragraph=TFT ST7789 SPI and Touch TT21100 I2C driver compatible with Adafruit GFX. +category=Display +url=https://github.com/SuGlider/Adafruit_ESP32S3_BOX +architectures=* +depends=Adafruit BusIO, Adafruit GFX Library diff --git a/src/ESP32_S3_Box_TFT.cpp b/src/ESP32_S3_Box_TFT.cpp new file mode 100644 index 0000000..17e7062 --- /dev/null +++ b/src/ESP32_S3_Box_TFT.cpp @@ -0,0 +1,174 @@ +#include "ESP32_S3_Box_TFT.h" + +static const uint8_t ST7789_INIT_CMD[] = { + 21, // 21 commands in list: + ST7789_SWRESET, ST_CMD_DELAY, // 1: Software reset, 0 args, w/delay + 150, // 150 ms delay + ST7789_SLPOUT, ST_CMD_DELAY, // 2: Out of sleep mode, 0 args, w/delay + 255, // 500 ms delay + ST7789_FRMCTR1, 3, // 3: Framerate ctrl - normal mode, 3 arg: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ST7789_FRMCTR2, 3, // 4: Framerate ctrl - idle mode, 3 args: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ST7789_FRMCTR3, 6, // 5: Framerate - partial mode, 6 args: + 0x01, 0x2C, 0x2D, // Dot inversion mode + 0x01, 0x2C, 0x2D, // Line inversion mode + ST7789_INVCTR, 1, // 6: Display inversion ctrl, 1 arg: + 0x07, // No inversion + ST7789_PWCTR1, 3, // 7: Power control, 3 args, no delay: + 0xA2, + 0x02, // -4.6V + 0x84, // AUTO mode + ST7789_PWCTR2, 1, // 8: Power control, 1 arg, no delay: + 0xC5, // VGH25=2.4C VGSEL=-10 VGH=3 * AVDD + ST7789_PWCTR3, 2, // 9: Power control, 2 args, no delay: + 0x0A, // Opamp current small + 0x00, // Boost frequency + ST7789_PWCTR4, 2, // 10: Power control, 2 args, no delay: + 0x8A, // BCLK/2, + 0x2A, // opamp current small & medium low + ST7789_PWCTR5, 2, // 11: Power control, 2 args, no delay: + 0x8A, 0xEE, + ST7789_VMCTR1, 1, // 12: Power control, 1 arg, no delay: + 0x0E, + ST7789_INVOFF, 0, // 13: Don't invert display, no args + ST7789_MADCTL, 1, // 14: Mem access ctl (directions), 1 arg: + 0xC8, // row/col addr, bottom-top refresh + ST7789_COLMOD, 1, // 15: set color mode, 1 arg, no delay: + 0x05, // 16-bit color + ST7789_CASET, 4, // 16: Column addr set, 4 args, no delay: + 0x00, 0x02, // XSTART = 0 + 0x00, 0x7F + 0x02, // XEND = 127 + ST7789_RASET, 4, // 17: Row addr set, 4 args, no delay: + 0x00, 0x01, // XSTART = 0 + 0x00, 0x9F + 0x01, // XEND = 159 + ST7789_GMCTRP1, 16 , // 18: Gamma Adjustments (pos. polarity), 16 args + delay: + 0x02, 0x1c, 0x07, 0x12, // (Not entirely necessary, but provides + 0x37, 0x32, 0x29, 0x2d, // accurate colors) + 0x29, 0x25, 0x2B, 0x39, + 0x00, 0x01, 0x03, 0x10, + ST7789_GMCTRN1, 16 , // 19: Gamma Adjustments (neg. polarity), 16 args + delay: + 0x03, 0x1d, 0x07, 0x06, // (Not entirely necessary, but provides + 0x2E, 0x2C, 0x29, 0x2D, // accurate colors) + 0x2E, 0x2E, 0x37, 0x3F, + 0x00, 0x00, 0x02, 0x10, + ST7789_NORON, ST_CMD_DELAY, // 20: Normal display on, no args, w/delay + 10, // 10 ms delay + ST7789_DISPON, ST_CMD_DELAY, // 21: Main screen turn on, no args w/delay + 100 // 100 ms delay +}; + +ESP32S3BOX_TFT::ESP32S3BOX_TFT() + : Adafruit_SPITFT(ESP32S3BOX_TFTWIDTH, ESP32S3BOX_TFTHEIGHT, -1, TFT_DC, TFT_RST) { + + // Turn LCD Backlight ON + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, HIGH); + // Set SPI to work with the TFT + SPI.begin(TFT_CLK, TFT_MISO, TFT_MOSI, TFT_CS); + SPI.setHwCs(true); +} + +void ESP32S3BOX_TFT::init() { + // base class setup + invertOnCommand = ST7789_INVON; + invertOffCommand = ST7789_INVOFF; + + // initialization + initSPI(40000000, SPI_MODE0); // 40Mhz SPI + displayInit(); +} + +void ESP32S3BOX_TFT::displayInit() { + + uint8_t numCommands, cmd, numArgs; + uint16_t ms; + + const uint8_t *addr = ST7789_INIT_CMD; + numCommands = *addr++; // Number of commands to follow + while (numCommands--) { // For each command... + cmd = *addr++; // Read command + numArgs = *addr++; // Number of args to follow + ms = numArgs & ST_CMD_DELAY; // If hibit set, delay follows args + numArgs &= ~ST_CMD_DELAY; // Mask out delay bit + sendCommand(cmd, addr, numArgs); + addr += numArgs; + + if (ms) { + ms = *addr++; // Read post-command delay time (ms) + if (ms == 255) + ms = 500; // If 255, delay for 500 ms + delay(ms); + } + } +} + +void ESP32S3BOX_TFT::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + x += _xstart; + y += _ystart; + uint32_t xa = ((uint32_t)x << 16) | (x + w - 1); + uint32_t ya = ((uint32_t)y << 16) | (y + h - 1); + + writeCommand(ST7789_CASET); // Column addr set + SPI_WRITE32(xa); + + writeCommand(ST7789_RASET); // Row addr set + SPI_WRITE32(ya); + + writeCommand(ST7789_RAMWR); // write to RAM +} + +void ESP32S3BOX_TFT::enableDisplay(boolean enable) { + sendCommand(enable ? ST7789_DISPON : ST7789_DISPOFF); +} + +void ESP32S3BOX_TFT::enableTearing(boolean enable) { + sendCommand(enable ? ST7789_TEON : ST7789_TEOFF); +} + +void ESP32S3BOX_TFT::enableSleep(boolean enable) { + sendCommand(enable ? ST7789_SLPIN : ST7789_SLPOUT); +} + +void ESP32S3BOX_TFT::setRotation(uint8_t m) { + uint8_t madctl = 0; + + rotation = m & 3; // can't be higher than 3 + + switch (rotation) { + case 0: + madctl = ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_BGR; + + _height = ESP32S3BOX_TFTHEIGHT; + _width = ESP32S3BOX_TFTWIDTH; + _xstart = 0; + _ystart = 0; + break; + case 1: + madctl = ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_BGR; + + _width = ESP32S3BOX_TFTHEIGHT; + _height = ESP32S3BOX_TFTWIDTH; + _ystart = 0; + _xstart = 0; + break; + case 2: + madctl = ST7789_MADCTL_BGR; + + _height = ESP32S3BOX_TFTHEIGHT; + _width = ESP32S3BOX_TFTWIDTH; + _xstart = 0; + _ystart = 0; + break; + case 3: + madctl = ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_BGR; + + _width = ESP32S3BOX_TFTHEIGHT; + _height = ESP32S3BOX_TFTWIDTH; + _ystart = 0; + _xstart = 0; + break; + } + + sendCommand(ST7789_MADCTL, &madctl, 1); +} diff --git a/src/ESP32_S3_Box_TFT.h b/src/ESP32_S3_Box_TFT.h new file mode 100644 index 0000000..6311052 --- /dev/null +++ b/src/ESP32_S3_Box_TFT.h @@ -0,0 +1,104 @@ +#pragma once + +#include "Arduino.h" +#include "Print.h" + +// Testing if the user has selected the right board in the menu +#ifndef TT21100_ADDR +#error Please select the right board in the Arduino IDE: ESP32-S3-Box +#endif + +#include +#include +#include + +#define ESP32S3BOX_TFTWIDTH 320 +#define ESP32S3BOX_TFTHEIGHT 240 + +#define ST_CMD_DELAY 0x80 // special signifier for command lists + +// Some register settings +#define ST7789_MADCTL_BGR 0x08 +#define ST7789_MADCTL_MH 0x04 + +#define ST7789_FRMCTR1 0xB1 +#define ST7789_FRMCTR2 0xB2 +#define ST7789_FRMCTR3 0xB3 +#define ST7789_INVCTR 0xB4 +#define ST7789_DISSET5 0xB6 + +#define ST7789_PWCTR1 0xC0 +#define ST7789_PWCTR2 0xC1 +#define ST7789_PWCTR3 0xC2 +#define ST7789_PWCTR4 0xC3 +#define ST7789_PWCTR5 0xC4 +#define ST7789_VMCTR1 0xC5 + +#define ST7789_PWCTR6 0xFC + +#define ST7789_GMCTRP1 0xE0 +#define ST7789_GMCTRN1 0xE1 + +#define ST7789_NOP 0x00 +#define ST7789_SWRESET 0x01 +#define ST7789_RDDID 0x04 +#define ST7789_RDDST 0x09 + +#define ST7789_SLPIN 0x10 +#define ST7789_SLPOUT 0x11 +#define ST7789_PTLON 0x12 +#define ST7789_NORON 0x13 + +#define ST7789_INVOFF 0x20 +#define ST7789_INVON 0x21 +#define ST7789_DISPOFF 0x28 +#define ST7789_DISPON 0x29 +#define ST7789_CASET 0x2A +#define ST7789_RASET 0x2B +#define ST7789_RAMWR 0x2C +#define ST7789_RAMRD 0x2E + +#define ST7789_PTLAR 0x30 +#define ST7789_TEOFF 0x34 +#define ST7789_TEON 0x35 +#define ST7789_MADCTL 0x36 +#define ST7789_COLMOD 0x3A + +#define ST7789_MADCTL_MY 0x80 +#define ST7789_MADCTL_MX 0x40 +#define ST7789_MADCTL_MV 0x20 +#define ST7789_MADCTL_ML 0x10 +#define ST7789_MADCTL_RGB 0x00 + +#define ST7789_RDID1 0xDA +#define ST7789_RDID2 0xDB +#define ST7789_RDID3 0xDC +#define ST7789_RDID4 0xDD + +// Some ready-made 16-bit ('RGB565') color settings: +#define ST7789_BLACK 0x0000 +#define ST7789_WHITE 0xFFFF +#define ST7789_RED 0xF800 +#define ST7789_GREEN 0x07E0 +#define ST7789_BLUE 0x001F +#define ST7789_CYAN 0x07FF +#define ST7789_MAGENTA 0xF81F +#define ST7789_YELLOW 0xFFE0 +#define ST7789_ORANGE 0xFC00 + +/// Subclass of SPITFT for ST77xx displays (lots in common!) +class ESP32S3BOX_TFT : public Adafruit_SPITFT { +public: + ESP32S3BOX_TFT(); + + void init(); // ESP32-S3-BOX DISPLAY + void setRotation(uint8_t m); + void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h); + void enableDisplay(boolean enable); + void enableTearing(boolean enable); + void enableSleep(boolean enable); + +protected: + void begin(uint32_t freq) {} // empty virtual function declaration from Adafruit_SPITFT + void displayInit(); +}; diff --git a/src/ESP32_S3_Box_TouchScreen.cpp b/src/ESP32_S3_Box_TouchScreen.cpp new file mode 100644 index 0000000..1b10fb1 --- /dev/null +++ b/src/ESP32_S3_Box_TouchScreen.cpp @@ -0,0 +1,103 @@ +#include "Arduino.h" +#include "ESP32_S3_Box_TouchScreen.h" +#include + +ESP32S3BOX_TS::ESP32S3BOX_TS() { + // reset all information + touchX[0] = touchY[0] = touchPressure[0] = 0; + touchX[1] = touchY[1] = touchPressure[1] = 0; + touches = 0; +} + +boolean ESP32S3BOX_TS::begin() { + Wire1.begin(I2C_SDA, I2C_SCL, 400000); + + uint8_t tries = 5; + do { + readMessageLen(); + tries--; + } while (_readdata[0] == 0 && tries > 0); + return _readdata[0] == 2; +} + +uint16_t ESP32S3BOX_TS::readMessageLen(void) { + + _readdata[0] = 0; + _readdata[1] = 0; + Wire1.beginTransmission(TT21100_ADDR); + Wire1.endTransmission(); + Wire1.requestFrom((byte)TT21100_ADDR, (byte)2); + _readdata[0] = Wire1.read(); + _readdata[1] = Wire1.read(); + return _readdata[0] + (_readdata[1] << 8); +} + +// reads sensor and touches +// updates Touch Points, but if not touched, resets all Touch Point Information +uint8_t ESP32S3BOX_TS::touched(void) { + // reset all information + touchX[0] = touchY[0] = touchPressure[0] = 0; + touchX[1] = touchY[1] = touchPressure[1] = 0; + touches = 0; + + // was it touched? + uint16_t msgLen = readMessageLen(); + + if (msgLen == 7 || msgLen == 17 || msgLen == 27 || msgLen == 14) { + // read actual data + Wire1.beginTransmission(TT21100_ADDR); + Wire1.endTransmission(); + Wire1.requestFrom((byte)TT21100_ADDR, (byte)msgLen); + for (uint8_t i = 0; i < msgLen; i++) { + _readdata[i] = Wire1.read(); + } + + // check that it is not the touch button event of ESP32BOX (little red circle) + if (msgLen != 14) { + + // set touch information + touches = msgLen / 10; + if (touches == 1) { + touchX[0] = _readdata[9] + (_readdata[10] << 8); + touchY[0] = _readdata[11] + (_readdata[12] << 8); + touchPressure[0] = _readdata[13]; + } + if (touches == 2) { + touchX[0] = _readdata[19] + (_readdata[20] << 8); + touchY[0] = _readdata[21] + (_readdata[22] << 8); + touchPressure[0] = _readdata[23]; + } + } // for now just ignore that button... + } + + + return touches; +} + +// Returns last Touched Coordinates got using touched() +TS_Point ESP32S3BOX_TS::getPoint(uint8_t n) { + + if ((touches == 0) || (n > 1)) { + return TS_Point(0, 0, 0); + } else { + return TS_Point(touchX[n], touchY[n], touchPressure[n]); + } +} + +TS_Point::TS_Point(void) { + x = y = z = 0; +} + +TS_Point::TS_Point(int16_t _x, int16_t _y, int16_t _z) { + x = _x; + y = _y; + z = _z; +} + +bool TS_Point::operator==(TS_Point p1) { + return ((p1.x == x) && (p1.y == y)); +} + +bool TS_Point::operator!=(TS_Point p1) { + return ((p1.x != x) || (p1.y != y)); +} diff --git a/src/ESP32_S3_Box_TouchScreen.h b/src/ESP32_S3_Box_TouchScreen.h new file mode 100644 index 0000000..b08543f --- /dev/null +++ b/src/ESP32_S3_Box_TouchScreen.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Arduino.h" + +// Testing if the user has selected the right board in the menu +#ifndef TT21100_ADDR +#error Please select the right board in the Arduino IDE: ESP32-S3-Box +#endif + +class TS_Point { + public: + TS_Point(void); + TS_Point(int16_t x, int16_t y, int16_t z); + + bool operator==(TS_Point); + bool operator!=(TS_Point); + + int16_t x; /*!< X coordinate */ + int16_t y; /*!< Y coordinate */ + int16_t z; /*!< Z coordinate (often used for pressure) */ +}; + +class ESP32S3BOX_TS { + public: + ESP32S3BOX_TS(void); + boolean begin(); + uint8_t touched(void); + TS_Point getPoint(uint8_t n = 0); // return touch coordinates for the touch 0 or 1 + + private: + uint8_t _readdata[28] = {0}; // 2 points * 10byte + 7 bytes + uint16_t readMessageLen(void); + + uint8_t touches; + uint16_t touchX[2], touchY[2], touchPressure[2]; +};