mirror of
https://github.com/0015/ThatProject.git
synced 2026-01-12 09:17:42 +03:00
Adding a new folder for LVGL project
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);
|
||||
}
|
||||
200
ESP32_LVGL/SimpleNoteAPP_LVGL6/Part1/0_lv_slider/0_lv_slider.ino
Normal file
200
ESP32_LVGL/SimpleNoteAPP_LVGL6/Part1/0_lv_slider/0_lv_slider.ino
Normal file
@@ -0,0 +1,200 @@
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void slider_event_cb(lv_obj_t * slider, lv_event_t event)
|
||||
{
|
||||
|
||||
printEvent("Slider", event);
|
||||
|
||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
static char buf[4]; /* max 3 bytes for number plus 1 null terminating byte */
|
||||
snprintf(buf, 4, "%u", lv_slider_get_value(slider));
|
||||
lv_label_set_text(slider_label, buf); /*Refresh the text*/
|
||||
}
|
||||
}
|
||||
|
||||
void printEvent(String Event, lv_event_t event)
|
||||
{
|
||||
|
||||
Serial.print(Event);
|
||||
printf(" ");
|
||||
|
||||
switch(event) {
|
||||
case LV_EVENT_PRESSED:
|
||||
printf("Pressed\n");
|
||||
break;
|
||||
|
||||
case LV_EVENT_SHORT_CLICKED:
|
||||
printf("Short clicked\n");
|
||||
break;
|
||||
|
||||
case LV_EVENT_CLICKED:
|
||||
printf("Clicked\n");
|
||||
break;
|
||||
|
||||
case LV_EVENT_LONG_PRESSED:
|
||||
printf("Long press\n");
|
||||
break;
|
||||
|
||||
case LV_EVENT_LONG_PRESSED_REPEAT:
|
||||
printf("Long press repeat\n");
|
||||
break;
|
||||
|
||||
case LV_EVENT_RELEASED:
|
||||
printf("Released\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
//Set the theme..
|
||||
lv_theme_t * th = lv_theme_night_init(210, NULL); //Set a HUE value and a Font for the Night Theme
|
||||
lv_theme_set_current(th);
|
||||
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
//lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
//lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
|
||||
/* 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, -50);
|
||||
|
||||
/* Create a slider in the center of the display */
|
||||
lv_obj_t * slider = lv_slider_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_width(slider, screenWidth-50); /*Set the width*/
|
||||
lv_obj_set_height(slider, 50);
|
||||
lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 0); /*Align to the center of the parent (screen)*/
|
||||
lv_obj_set_event_cb(slider, slider_event_cb); /*Assign an event function*/
|
||||
|
||||
/* Create a label below the slider */
|
||||
slider_label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(slider_label, "0");
|
||||
lv_obj_set_auto_realign(slider, true);
|
||||
lv_obj_align(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
//Set the theme..
|
||||
lv_theme_t * th = lv_theme_night_init(210, NULL); //Set a HUE value and a Font for the Night Theme
|
||||
lv_test_theme_1(th);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void create_tab1(lv_obj_t * parent);
|
||||
static void create_tab2(lv_obj_t * parent);
|
||||
static void create_tab3(lv_obj_t * parent);
|
||||
|
||||
|
||||
|
||||
void lv_test_theme_1(lv_theme_t * th)
|
||||
{
|
||||
lv_theme_set_current(th);
|
||||
th = lv_theme_get_current(); /*If `LV_THEME_LIVE_UPDATE 1` `th` is not used directly so get the real theme after set*/
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "Tab 1");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "Tab 2");
|
||||
lv_obj_t * tab3 = lv_tabview_add_tab(tv, "Tab 3");
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
create_tab3(tab3);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
static void create_tab1(lv_obj_t * parent)
|
||||
{
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
|
||||
static lv_style_t h_style;
|
||||
lv_style_copy(&h_style, &lv_style_transp);
|
||||
h_style.body.padding.inner = LV_DPI / 10;
|
||||
h_style.body.padding.left = LV_DPI / 4;
|
||||
h_style.body.padding.right = LV_DPI / 4;
|
||||
h_style.body.padding.top = LV_DPI / 10;
|
||||
h_style.body.padding.bottom = LV_DPI / 10;
|
||||
|
||||
lv_obj_t * h = lv_cont_create(parent, NULL);
|
||||
lv_obj_set_style(h, &h_style);
|
||||
lv_obj_set_click(h, false);
|
||||
lv_cont_set_fit(h, LV_FIT_TIGHT);
|
||||
lv_cont_set_layout(h, LV_LAYOUT_COL_M);
|
||||
|
||||
lv_obj_t * btn = lv_btn_create(h, NULL);
|
||||
lv_btn_set_fit(btn, LV_FIT_TIGHT);
|
||||
lv_btn_set_toggle(btn, true);
|
||||
lv_obj_t * btn_label = lv_label_create(btn, NULL);
|
||||
lv_label_set_text(btn_label, "Button");
|
||||
|
||||
btn = lv_btn_create(h, btn);
|
||||
lv_btn_toggle(btn);
|
||||
btn_label = lv_label_create(btn, NULL);
|
||||
lv_label_set_text(btn_label, "Toggled");
|
||||
|
||||
btn = lv_btn_create(h, btn);
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_INA);
|
||||
btn_label = lv_label_create(btn, NULL);
|
||||
lv_label_set_text(btn_label, "Inactive");
|
||||
|
||||
lv_obj_t * label = lv_label_create(h, NULL);
|
||||
lv_label_set_text(label, "Primary");
|
||||
lv_obj_set_style(label, th->style.label.prim);
|
||||
|
||||
label = lv_label_create(h, NULL);
|
||||
lv_label_set_text(label, "Secondary");
|
||||
lv_obj_set_style(label, th->style.label.sec);
|
||||
|
||||
label = lv_label_create(h, NULL);
|
||||
lv_label_set_text(label, "Hint");
|
||||
lv_obj_set_style(label, th->style.label.hint);
|
||||
|
||||
static const char * btnm_str[] = {"1", "2", "3", LV_SYMBOL_OK, LV_SYMBOL_CLOSE, ""};
|
||||
lv_obj_t * btnm = lv_btnm_create(h, NULL);
|
||||
lv_obj_set_size(btnm, lv_disp_get_hor_res(NULL) / 4, 2 * LV_DPI / 3);
|
||||
lv_btnm_set_map(btnm, btnm_str);
|
||||
lv_btnm_set_btn_ctrl_all(btnm, LV_BTNM_CTRL_TGL_ENABLE);
|
||||
lv_btnm_set_one_toggle(btnm, true);
|
||||
|
||||
lv_obj_t * table = lv_table_create(h, NULL);
|
||||
lv_table_set_col_cnt(table, 3);
|
||||
lv_table_set_row_cnt(table, 4);
|
||||
lv_table_set_col_width(table, 0, LV_DPI / 3);
|
||||
lv_table_set_col_width(table, 1, LV_DPI / 2);
|
||||
lv_table_set_col_width(table, 2, LV_DPI / 2);
|
||||
lv_table_set_cell_merge_right(table, 0, 0, true);
|
||||
lv_table_set_cell_merge_right(table, 0, 1, true);
|
||||
|
||||
lv_table_set_cell_value(table, 0, 0, "Table");
|
||||
lv_table_set_cell_align(table, 0, 0, LV_LABEL_ALIGN_CENTER);
|
||||
|
||||
lv_table_set_cell_value(table, 1, 0, "1");
|
||||
lv_table_set_cell_value(table, 1, 1, "13");
|
||||
lv_table_set_cell_align(table, 1, 1, LV_LABEL_ALIGN_RIGHT);
|
||||
lv_table_set_cell_value(table, 1, 2, "ms");
|
||||
|
||||
lv_table_set_cell_value(table, 2, 0, "2");
|
||||
lv_table_set_cell_value(table, 2, 1, "46");
|
||||
lv_table_set_cell_align(table, 2, 1, LV_LABEL_ALIGN_RIGHT);
|
||||
lv_table_set_cell_value(table, 2, 2, "ms");
|
||||
|
||||
lv_table_set_cell_value(table, 3, 0, "3");
|
||||
lv_table_set_cell_value(table, 3, 1, "61");
|
||||
lv_table_set_cell_align(table, 3, 1, LV_LABEL_ALIGN_RIGHT);
|
||||
lv_table_set_cell_value(table, 3, 2, "ms");
|
||||
|
||||
h = lv_cont_create(parent, h);
|
||||
|
||||
lv_obj_t * sw_h = lv_cont_create(h, NULL);
|
||||
lv_cont_set_style(sw_h, LV_CONT_STYLE_MAIN, &lv_style_transp);
|
||||
lv_cont_set_fit2(sw_h, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
lv_obj_set_width(sw_h, LV_HOR_RES / 4);
|
||||
lv_cont_set_layout(sw_h, LV_LAYOUT_PRETTY);
|
||||
|
||||
lv_obj_t * sw = lv_sw_create(sw_h, NULL);
|
||||
lv_sw_set_anim_time(sw, 250);
|
||||
|
||||
sw = lv_sw_create(sw_h, sw);
|
||||
lv_sw_on(sw, LV_ANIM_OFF);
|
||||
|
||||
|
||||
lv_obj_t * bar = lv_bar_create(h, NULL);
|
||||
lv_bar_set_value(bar, 70, false);
|
||||
|
||||
lv_obj_t * slider = lv_slider_create(h, NULL);
|
||||
lv_bar_set_value(slider, 70, false);
|
||||
|
||||
lv_obj_t * line = lv_line_create(h, NULL);
|
||||
static lv_point_t line_p[2];
|
||||
line_p[0].x = 0;
|
||||
line_p[0].y = 0;
|
||||
line_p[1].x = lv_disp_get_hor_res(NULL) / 5;
|
||||
line_p[1].y = 0;
|
||||
|
||||
lv_line_set_points(line, line_p, 2);
|
||||
lv_line_set_style(line, LV_LINE_STYLE_MAIN, th->style.line.decor);
|
||||
|
||||
lv_obj_t * cb = lv_cb_create(h, NULL);
|
||||
|
||||
cb = lv_cb_create(h, cb);
|
||||
lv_btn_set_state(cb, LV_BTN_STATE_TGL_REL);
|
||||
|
||||
lv_obj_t * ddlist = lv_ddlist_create(h, NULL);
|
||||
lv_ddlist_set_fix_width(ddlist, lv_obj_get_width(ddlist) + LV_DPI / 2); /*Make space for the arrow*/
|
||||
lv_ddlist_set_draw_arrow(ddlist, true);
|
||||
|
||||
h = lv_cont_create(parent, h);
|
||||
|
||||
lv_obj_t * list = lv_list_create(h, NULL);
|
||||
lv_obj_set_size(list, lv_disp_get_hor_res(NULL) / 4, lv_disp_get_ver_res(NULL) / 2);
|
||||
lv_obj_t * list_btn;
|
||||
list_btn = lv_list_add_btn(list, LV_SYMBOL_GPS, "GPS");
|
||||
lv_btn_set_toggle(list_btn, true);
|
||||
|
||||
lv_list_add_btn(list, LV_SYMBOL_WIFI, "WiFi");
|
||||
lv_list_add_btn(list, LV_SYMBOL_GPS, "GPS");
|
||||
lv_list_add_btn(list, LV_SYMBOL_AUDIO, "Audio");
|
||||
lv_list_add_btn(list, LV_SYMBOL_VIDEO, "Video");
|
||||
lv_list_add_btn(list, LV_SYMBOL_CALL, "Call");
|
||||
lv_list_add_btn(list, LV_SYMBOL_BELL, "Bell");
|
||||
lv_list_add_btn(list, LV_SYMBOL_FILE, "File");
|
||||
lv_list_add_btn(list, LV_SYMBOL_EDIT, "Edit");
|
||||
lv_list_add_btn(list, LV_SYMBOL_CUT, "Cut");
|
||||
lv_list_add_btn(list, LV_SYMBOL_COPY, "Copy");
|
||||
|
||||
lv_obj_t * roller = lv_roller_create(h, NULL);
|
||||
lv_roller_set_options(roller, "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday", true);
|
||||
lv_roller_set_selected(roller, 1, false);
|
||||
lv_roller_set_visible_row_count(roller, 3);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent)
|
||||
{
|
||||
lv_coord_t w = lv_page_get_scrl_width(parent);
|
||||
|
||||
lv_obj_t * chart = lv_chart_create(parent, NULL);
|
||||
lv_chart_set_type(chart, LV_CHART_TYPE_AREA);
|
||||
lv_obj_set_size(chart, w / 3, lv_disp_get_ver_res(NULL) / 3);
|
||||
lv_obj_set_pos(chart, LV_DPI / 10, LV_DPI / 10);
|
||||
lv_chart_series_t * s1 = lv_chart_add_series(chart, LV_COLOR_RED);
|
||||
lv_chart_set_next(chart, s1, 30);
|
||||
lv_chart_set_next(chart, s1, 20);
|
||||
lv_chart_set_next(chart, s1, 10);
|
||||
lv_chart_set_next(chart, s1, 12);
|
||||
lv_chart_set_next(chart, s1, 20);
|
||||
lv_chart_set_next(chart, s1, 27);
|
||||
lv_chart_set_next(chart, s1, 35);
|
||||
lv_chart_set_next(chart, s1, 55);
|
||||
lv_chart_set_next(chart, s1, 70);
|
||||
lv_chart_set_next(chart, s1, 75);
|
||||
|
||||
|
||||
lv_obj_t * gauge = lv_gauge_create(parent, NULL);
|
||||
lv_gauge_set_value(gauge, 0, 40);
|
||||
lv_obj_set_size(gauge, w / 4, w / 4);
|
||||
lv_obj_align(gauge, chart, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 4);
|
||||
|
||||
|
||||
lv_obj_t * arc = lv_arc_create(parent, NULL);
|
||||
lv_obj_align(arc, gauge, LV_ALIGN_OUT_BOTTOM_MID, 0, LV_DPI / 8);
|
||||
|
||||
lv_obj_t * ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, w / 3, lv_disp_get_ver_res(NULL) / 4);
|
||||
lv_obj_align(ta, NULL, LV_ALIGN_IN_TOP_RIGHT, -LV_DPI / 10, LV_DPI / 10);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
|
||||
lv_obj_t * kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, 2 * w / 3, lv_disp_get_ver_res(NULL) / 3);
|
||||
lv_obj_align(kb, ta, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI);
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_obj_t * loader = lv_preload_create(parent, NULL);
|
||||
lv_obj_align(loader, NULL, LV_ALIGN_CENTER, 0, - LV_DPI);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void create_tab3(lv_obj_t * parent)
|
||||
{
|
||||
/*Create a Window*/
|
||||
lv_obj_t * win = lv_win_create(parent, NULL);
|
||||
lv_obj_t * win_btn = lv_win_add_btn(win, LV_SYMBOL_CLOSE);
|
||||
lv_obj_set_event_cb(win_btn, lv_win_close_event_cb);
|
||||
lv_win_add_btn(win, LV_SYMBOL_DOWN);
|
||||
lv_obj_set_size(win, lv_disp_get_hor_res(NULL) / 2, lv_disp_get_ver_res(NULL) / 2);
|
||||
lv_obj_set_pos(win, LV_DPI / 20, LV_DPI / 20);
|
||||
lv_obj_set_top(win, true);
|
||||
|
||||
|
||||
/*Create a Label in the Window*/
|
||||
lv_obj_t * label = lv_label_create(win, NULL);
|
||||
lv_label_set_text(label, "Label in the window");
|
||||
|
||||
/*Create a Line meter in the Window*/
|
||||
lv_obj_t * lmeter = lv_lmeter_create(win, NULL);
|
||||
lv_obj_align(lmeter, label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
||||
lv_lmeter_set_value(lmeter, 70);
|
||||
|
||||
/*Create a 2 LEDs in the Window*/
|
||||
lv_obj_t * led1 = lv_led_create(win, NULL);
|
||||
lv_obj_align(led1, lmeter, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
||||
lv_led_on(led1);
|
||||
|
||||
lv_obj_t * led2 = lv_led_create(win, NULL);
|
||||
lv_obj_align(led2, led1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
||||
lv_led_off(led2);
|
||||
|
||||
/*Create a Page*/
|
||||
lv_obj_t * page = lv_page_create(parent, NULL);
|
||||
lv_obj_set_size(page, lv_disp_get_hor_res(NULL) / 3, lv_disp_get_ver_res(NULL) / 2);
|
||||
lv_obj_set_top(page, true);
|
||||
lv_obj_align(page, win, LV_ALIGN_IN_TOP_RIGHT, LV_DPI, LV_DPI);
|
||||
|
||||
label = lv_label_create(page, NULL);
|
||||
lv_label_set_text(label, "Lorem ipsum dolor sit amet, repudiare voluptatibus pri cu.\n"
|
||||
"Ei mundi pertinax posidonium eum, cum tempor maiorum at,\n"
|
||||
"mea fuisset assentior ad. Usu cu suas civibus iudicabit.\n"
|
||||
"Eum eu congue tempor facilisi. Tale hinc unum te vim.\n"
|
||||
"Te cum populo animal eruditi, labitur inciderint at nec.\n\n"
|
||||
"Eius corpora et quo. Everti voluptaria instructior est id,\n"
|
||||
"vel in falli primis. Mea ei porro essent admodum,\n"
|
||||
"his ei malis quodsi, te quis aeterno his.\n"
|
||||
"Qui tritani recusabo reprehendunt ne,\n"
|
||||
"per duis explicari at. Simul mediocritatem mei et.");
|
||||
|
||||
/*Create a Calendar*/
|
||||
lv_obj_t * cal = lv_calendar_create(parent, NULL);
|
||||
lv_obj_set_size(cal, 5 * LV_DPI / 2, 5 * LV_DPI / 2);
|
||||
lv_obj_align(cal, page, LV_ALIGN_OUT_RIGHT_TOP, -LV_DPI / 2, LV_DPI / 3);
|
||||
lv_obj_set_top(cal, true);
|
||||
|
||||
static lv_calendar_date_t highlighted_days[2];
|
||||
highlighted_days[0].day = 5;
|
||||
highlighted_days[0].month = 5;
|
||||
highlighted_days[0].year = 2018;
|
||||
|
||||
highlighted_days[1].day = 8;
|
||||
highlighted_days[1].month = 5;
|
||||
highlighted_days[1].year = 2018;
|
||||
|
||||
lv_calendar_set_highlighted_dates(cal, highlighted_days, 2);
|
||||
lv_calendar_set_today_date(cal, &highlighted_days[0]);
|
||||
lv_calendar_set_showed_date(cal, &highlighted_days[0]);
|
||||
|
||||
/*Create a Message box*/
|
||||
static const char * mbox_btn_map[] = {" ", "Got it!", " ", ""};
|
||||
lv_obj_t * mbox = lv_mbox_create(parent, NULL);
|
||||
lv_mbox_set_text(mbox, "Click on the window or the page to bring it to the foreground");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map);
|
||||
lv_btnm_set_btn_ctrl(lv_mbox_get_btnm(mbox), 0, LV_BTNM_CTRL_HIDDEN);
|
||||
lv_btnm_set_btn_width(lv_mbox_get_btnm(mbox), 1, 7);
|
||||
lv_btnm_set_btn_ctrl(lv_mbox_get_btnm(mbox), 2, LV_BTNM_CTRL_HIDDEN);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
lv_ex_btn_1();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
static void event_handler(lv_obj_t * obj, lv_event_t event)
|
||||
{
|
||||
if(event == LV_EVENT_CLICKED) {
|
||||
printf("Clicked\n");
|
||||
}
|
||||
else if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
printf("Toggled\n");
|
||||
}
|
||||
}
|
||||
|
||||
void lv_ex_btn_1(void)
|
||||
{
|
||||
lv_obj_t * label;
|
||||
|
||||
lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_event_cb(btn1, event_handler);
|
||||
lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, -40);
|
||||
|
||||
label = lv_label_create(btn1, NULL);
|
||||
lv_label_set_text(label, "Button");
|
||||
|
||||
lv_obj_t * btn2 = lv_btn_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_event_cb(btn2, event_handler);
|
||||
lv_obj_align(btn2, NULL, LV_ALIGN_CENTER, 0, 40);
|
||||
lv_btn_set_toggle(btn2, true);
|
||||
lv_btn_toggle(btn2);
|
||||
lv_btn_set_fit2(btn2, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
|
||||
label = lv_label_create(btn2, NULL);
|
||||
lv_label_set_text(label, "Toggled");
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
lv_main();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
static lv_obj_t *kb;
|
||||
|
||||
static void lv_main(){
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "LIST TAB");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "WRITE TAB");
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
}
|
||||
|
||||
static void create_tab1(lv_obj_t * parent){
|
||||
//List Tab
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent){
|
||||
//Write Tab
|
||||
lv_obj_t * ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) / 2);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
lv_ta_set_text(ta, "hello!");
|
||||
|
||||
/*Create a keyboard and apply the styles*/
|
||||
kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) / 2 - 20);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
/*Assign the text area to the keyboard*/
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_kb_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "SPIFFS.h"
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
String currentFileName;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
if(initSPIFFS()){
|
||||
lv_main();
|
||||
} else {
|
||||
lv_error_page();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
bool initSPIFFS(){
|
||||
if(!SPIFFS.begin(true)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static lv_obj_t *kb;
|
||||
|
||||
static void lv_main(){
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "LIST TAB");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "WRITE TAB");
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
}
|
||||
|
||||
static void lv_error_page(){
|
||||
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(label, "Please check your SPIFFS");
|
||||
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0,0);
|
||||
}
|
||||
|
||||
static void create_tab1(lv_obj_t * parent){
|
||||
//List Tab
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
|
||||
lv_obj_t * list = lv_list_create(parent, NULL);
|
||||
lv_obj_set_size(list, lv_obj_get_width(parent)-20, lv_obj_get_height(parent)-20);
|
||||
lv_obj_align(list, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
|
||||
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "New");
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, file.name());
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent){
|
||||
//Write Tab
|
||||
lv_obj_t * ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) / 2);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
lv_ta_set_text(ta, "hello!");
|
||||
|
||||
/*Create a keyboard and apply the styles*/
|
||||
kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) / 2 - 20);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
/*Assign the text area to the keyboard*/
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_kb_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void file_list_event(lv_obj_t * btn, lv_event_t e){
|
||||
if(e == LV_EVENT_CLICKED){
|
||||
currentFileName = lv_list_get_btn_text(btn);
|
||||
Serial.println(currentFileName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
#include "SPIFFS.h"
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
String currentFileName;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
if(initSPIFFS()){
|
||||
lv_main();
|
||||
} else {
|
||||
lv_error_page();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
bool initSPIFFS(){
|
||||
if(!SPIFFS.begin(true)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String openFile(String filename){
|
||||
File file = SPIFFS.open(filename);
|
||||
if(!file){
|
||||
file.close();
|
||||
return "";
|
||||
}
|
||||
String textData;
|
||||
while(file.available()){
|
||||
textData += char(file.read());
|
||||
}
|
||||
Serial.println(textData);
|
||||
file.close();
|
||||
return textData;
|
||||
}
|
||||
|
||||
bool writeFile(String filename, String contents){
|
||||
File file = SPIFFS.open(filename, FILE_WRITE);
|
||||
|
||||
if(!file){
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(file.print(contents)){
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static lv_obj_t *kb, *ta;
|
||||
|
||||
static void lv_main(){
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "LIST TAB");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "WRITE TAB");
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
}
|
||||
|
||||
static void lv_error_page(){
|
||||
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(label, "Please check your SPIFFS");
|
||||
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0,0);
|
||||
}
|
||||
|
||||
static void create_tab1(lv_obj_t * parent){
|
||||
//List Tab
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
|
||||
lv_obj_t * list = lv_list_create(parent, NULL);
|
||||
lv_obj_set_size(list, lv_obj_get_width(parent)-20, lv_obj_get_height(parent)-20);
|
||||
lv_obj_align(list, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
|
||||
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "New");
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, file.name());
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent){
|
||||
//Write Tab
|
||||
ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) / 2);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
lv_ta_set_text(ta, "");
|
||||
|
||||
/*Create a keyboard and apply the styles*/
|
||||
kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) / 2 - 20);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
/*Assign the text area to the keyboard*/
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_kb_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void file_list_event(lv_obj_t * btn, lv_event_t e){
|
||||
if(e == LV_EVENT_CLICKED){
|
||||
currentFileName = lv_list_get_btn_text(btn);
|
||||
Serial.println(currentFileName);
|
||||
if(strcmp(currentFileName.c_str(),"New") == 0){
|
||||
lv_ta_set_text(ta, "");
|
||||
}else{
|
||||
lv_ta_set_text(ta, openFile(currentFileName).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
#include "SPIFFS.h"
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
String currentFileName;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>screenWidth || touchY > screenHeight)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
/*Save the state and save the pressed coordinate*/
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
/*Set the coordinates (if released use the last pressed coordinates)*/
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
if(initSPIFFS()){
|
||||
lv_main();
|
||||
} else {
|
||||
lv_error_page();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
bool initSPIFFS(){
|
||||
if(!SPIFFS.begin(true)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String openFile(String filename){
|
||||
File file = SPIFFS.open(filename) ;
|
||||
if(!file){
|
||||
file.close();
|
||||
return "";
|
||||
}
|
||||
String textData;
|
||||
while(file.available()){
|
||||
textData += char(file.read());
|
||||
}
|
||||
Serial.println(textData);
|
||||
file.close();
|
||||
return textData;
|
||||
}
|
||||
|
||||
bool writeFile(String filename, String contents){
|
||||
File file = SPIFFS.open(filename, FILE_WRITE);
|
||||
|
||||
if(!file){
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(file.print(contents)){
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteFile(String filename){
|
||||
SPIFFS.remove(filename);
|
||||
}
|
||||
|
||||
|
||||
static lv_obj_t *kb, *ta, *mbox, *mbox_filename, *ta_filename;
|
||||
static const char * modal_popup_btns[] = {"Save", "Save as", "Delete", "Cancel", ""};
|
||||
static const char * filename_popup_btns[] ={"Apply", "Close", ""};
|
||||
|
||||
static void lv_main(){
|
||||
lv_theme_t * th = lv_theme_night_init(210, NULL);
|
||||
lv_theme_set_current(th);
|
||||
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
lv_obj_t * tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "LIST TAB");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "WRITE TAB");
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
}
|
||||
|
||||
static void lv_error_page(){
|
||||
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(label, "Please check your SPIFFS");
|
||||
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0,0);
|
||||
}
|
||||
|
||||
static void create_tab1(lv_obj_t * parent){
|
||||
//List Tab
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
|
||||
lv_obj_t * list = lv_list_create(parent, NULL);
|
||||
lv_obj_set_size(list, lv_obj_get_width(parent)-20, lv_obj_get_height(parent)-20);
|
||||
lv_obj_align(list, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
|
||||
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "New");
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, file.name());
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent){
|
||||
//Write Tab
|
||||
ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) / 2);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
lv_ta_set_text(ta, "");
|
||||
|
||||
/*Create a keyboard and apply the styles*/
|
||||
kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) / 2 - 20);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
/*Assign the text area to the keyboard*/
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_kb_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
mbox_menu_modal();
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void mbox_menu_modal(){
|
||||
static lv_style_t modal_style;
|
||||
/* Create a full-screen background */
|
||||
lv_style_copy(&modal_style, &lv_style_plain_color);
|
||||
|
||||
/* Set the background's style */
|
||||
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
||||
modal_style.body.opa = LV_OPA_50;
|
||||
|
||||
/* Create a base object for the modal background */
|
||||
lv_obj_t *obj = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(obj, &modal_style);
|
||||
lv_obj_set_pos(obj, 0, 0);
|
||||
lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
|
||||
lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */
|
||||
|
||||
/* Create the message box as a child of the modal background */
|
||||
mbox = lv_mbox_create(obj, NULL);
|
||||
lv_mbox_add_btns(mbox, modal_popup_btns);
|
||||
lv_mbox_set_text(mbox, "Menu options!");
|
||||
lv_obj_set_size(mbox, LV_HOR_RES - 100, LV_VER_RES - 50);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_event_cb(mbox, mbox_event_cb);
|
||||
|
||||
/* Fade the message box in with an animation */
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_time(&a, 500, 0);
|
||||
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale);
|
||||
lv_anim_create(&a);
|
||||
|
||||
}
|
||||
|
||||
static void mbox_event_cb(lv_obj_t *obj, lv_event_t evt)
|
||||
{
|
||||
if(evt == LV_EVENT_DELETE && obj == mbox) {
|
||||
/* Delete the parent modal background */
|
||||
lv_obj_del_async(lv_obj_get_parent(mbox));
|
||||
mbox = NULL; /* happens before object is actually deleted! */
|
||||
} else if(evt == LV_EVENT_VALUE_CHANGED) {
|
||||
/* A button was clicked */
|
||||
lv_mbox_start_auto_close(mbox, 0);
|
||||
String contents = lv_ta_get_text(ta);
|
||||
|
||||
if(strcmp(lv_mbox_get_active_btn_text(obj), "Save")==0){
|
||||
if(contents.length() > 0){
|
||||
if(strcmp(currentFileName.c_str(),"New") == 0){
|
||||
Serial.println("New Save");
|
||||
open_mbox_filename();
|
||||
}else{
|
||||
if(writeFile(currentFileName, contents)){
|
||||
Serial.println("Write Success");
|
||||
}else{
|
||||
//Error
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//Nothing to write
|
||||
}
|
||||
|
||||
}else if(strcmp(lv_mbox_get_active_btn_text(obj), "Save As")==0){
|
||||
if(contents.length() > 0){
|
||||
open_mbox_filename();
|
||||
}
|
||||
|
||||
}else if(strcmp(lv_mbox_get_active_btn_text(obj), "Delete")==0){
|
||||
if(strcmp(currentFileName.c_str(), "New")==0){
|
||||
//Just go back to home screen
|
||||
}else{
|
||||
deleteFile(currentFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void open_mbox_filename(){
|
||||
mbox_filename = lv_mbox_create(lv_scr_act(), NULL);
|
||||
lv_mbox_set_text(mbox_filename, "File Name");
|
||||
|
||||
ta_filename = lv_ta_create(mbox_filename, NULL);
|
||||
lv_obj_set_size(ta_filename, 200, 40);
|
||||
lv_ta_set_cursor_type(ta_filename, LV_CURSOR_LINE);
|
||||
lv_ta_set_text(ta_filename, "");
|
||||
|
||||
lv_mbox_add_btns(mbox_filename, filename_popup_btns);
|
||||
lv_obj_set_width(mbox_filename, 200);
|
||||
lv_obj_set_event_cb(mbox_filename, filename_event_handler);
|
||||
lv_obj_align(mbox_filename, NULL, LV_ALIGN_CENTER, 0, 0); /*Align to the corner*/
|
||||
lv_kb_set_ta(kb, ta_filename);
|
||||
}
|
||||
|
||||
static void filename_event_handler(lv_obj_t * obj, lv_event_t event)
|
||||
{
|
||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
lv_mbox_start_auto_close(mbox_filename, 0);
|
||||
printf("Button: %s\n", lv_mbox_get_active_btn_text(obj));
|
||||
|
||||
if(strcmp(lv_mbox_get_active_btn_text(obj), "Apply")==0){
|
||||
String contents = lv_ta_get_text(ta);
|
||||
String fileName = lv_ta_get_text(ta_filename);
|
||||
if(fileName.length() > 0){
|
||||
if(writeFile("/"+fileName, contents)){
|
||||
//Write Success
|
||||
}else{
|
||||
//Cannot write to file
|
||||
}
|
||||
}else{
|
||||
//Check the file name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void file_list_event(lv_obj_t * btn, lv_event_t e){
|
||||
if(e == LV_EVENT_CLICKED){
|
||||
currentFileName = lv_list_get_btn_text(btn);
|
||||
Serial.println(currentFileName);
|
||||
if(strcmp(currentFileName.c_str(),"New") == 0){
|
||||
lv_ta_set_text(ta, "");
|
||||
}else{
|
||||
lv_ta_set_text(ta, openFile(currentFileName).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
#include "SPIFFS.h"
|
||||
#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define LVGL_TICK_PERIOD 60
|
||||
|
||||
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];
|
||||
|
||||
int screenWidth = 480;
|
||||
int screenHeight = 320;
|
||||
String currentFileName;
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX <= screenWidth && touchY <=screenHeight)
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
}
|
||||
|
||||
return false; /*Return `false` because we are not buffering and no more data to read*/
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
static void lv_tick_handler(void)
|
||||
{
|
||||
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200); /* prepare for possible serial debug */
|
||||
|
||||
lv_init();
|
||||
|
||||
tft.begin(); /* TFT init */
|
||||
tft.setRotation(3);
|
||||
|
||||
//uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
|
||||
uint16_t calData[5] = {299, 3588, 348, 3474, 1};
|
||||
tft.setTouch(calData);
|
||||
|
||||
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 = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
|
||||
indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/
|
||||
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
|
||||
|
||||
|
||||
/*Initialize the graphics library's tick*/
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
if(initSPIFFS()){
|
||||
lv_main();
|
||||
} else {
|
||||
lv_error_page();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
lv_task_handler(); /* let the GUI do its work */
|
||||
delay(5);
|
||||
}
|
||||
|
||||
bool initSPIFFS(){
|
||||
if(!SPIFFS.begin(true)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String openFile(String filename){
|
||||
File file = SPIFFS.open(filename) ;
|
||||
if(!file){
|
||||
file.close();
|
||||
return "";
|
||||
}
|
||||
String textData;
|
||||
while(file.available()){
|
||||
textData += char(file.read());
|
||||
}
|
||||
Serial.println(textData);
|
||||
file.close();
|
||||
return textData;
|
||||
}
|
||||
|
||||
bool writeFile(String filename, String contents){
|
||||
File file = SPIFFS.open(filename, FILE_WRITE);
|
||||
|
||||
if(!file){
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(file.print(contents)){
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteFile(String filename){
|
||||
SPIFFS.remove(filename);
|
||||
}
|
||||
|
||||
static lv_obj_t *kb, *ta, *mbox, *mbox_filename, *ta_filename, *list, *header_label, *tv;
|
||||
static const char * modal_popup_btns[] = {"Save", "Save As", "Delete", "Cancel", ""};
|
||||
static const char * filename_popup_btns[] ={"Apply", "Close", ""};
|
||||
|
||||
static void lv_main(){
|
||||
lv_theme_t * th = lv_theme_night_init(210, NULL);
|
||||
lv_theme_set_current(th);
|
||||
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
header_create();
|
||||
|
||||
tv = lv_tabview_create(scr, NULL);
|
||||
lv_obj_set_pos(tv, 0, 40);
|
||||
lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL) - 40);
|
||||
lv_tabview_set_anim_time(tv, 50);
|
||||
|
||||
lv_obj_t * tab1 = lv_tabview_add_tab(tv, "LIST TAB");
|
||||
lv_obj_t * tab2 = lv_tabview_add_tab(tv, "WRITE TAB");
|
||||
lv_tabview_set_btns_hidden(tv, true);
|
||||
lv_tabview_set_sliding(tv, false);
|
||||
|
||||
create_tab1(tab1);
|
||||
create_tab2(tab2);
|
||||
}
|
||||
|
||||
static void lv_error_page(){
|
||||
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(label, "Please check your SPIFFS");
|
||||
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0,0);
|
||||
}
|
||||
|
||||
static void header_create(){
|
||||
lv_obj_t * header = lv_cont_create(lv_disp_get_scr_act(NULL), NULL);
|
||||
lv_obj_set_width(header, lv_disp_get_hor_res(NULL));
|
||||
lv_obj_set_event_cb(header, header_event);
|
||||
lv_obj_t * sym = lv_label_create(header, NULL);
|
||||
lv_label_set_text(sym, LV_SYMBOL_DIRECTORY);
|
||||
lv_obj_align(sym, NULL, LV_ALIGN_IN_RIGHT_MID, -10, 0);
|
||||
|
||||
header_label = lv_label_create(header, NULL);
|
||||
header_set_text("Simple Note");
|
||||
lv_obj_align(header_label, NULL, LV_ALIGN_IN_LEFT_MID, 10, 0);
|
||||
|
||||
lv_cont_set_fit2(header, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
lv_obj_set_pos(header, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
static void header_set_text(String _name){
|
||||
lv_label_set_text(header_label, _name.c_str());
|
||||
}
|
||||
|
||||
static void header_event(lv_obj_t * btn, lv_event_t e){
|
||||
if(e == LV_EVENT_CLICKED){
|
||||
if(lv_tabview_get_tab_act(tv) != 0){
|
||||
Serial.println("GO BACK TO HOME");
|
||||
home_menu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void home_menu(){
|
||||
header_set_text("Simple Note");
|
||||
lv_tabview_set_tab_act(tv, 0, LV_ANIM_ON);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_NONE);
|
||||
}
|
||||
|
||||
static void refresh_list(){
|
||||
if(list != NULL){
|
||||
lv_list_clean(list);
|
||||
}
|
||||
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "New");
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
|
||||
File root = SPIFFS.open("/");
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, file.name());
|
||||
lv_obj_set_event_cb(btn, file_list_event);
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
static void create_tab1(lv_obj_t * parent){
|
||||
//List Tab
|
||||
lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY);
|
||||
|
||||
list = lv_list_create(parent, NULL);
|
||||
lv_obj_set_size(list, lv_obj_get_width(parent)-20, lv_obj_get_height(parent)-20);
|
||||
lv_obj_align(list, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
|
||||
refresh_list();
|
||||
}
|
||||
|
||||
static void create_tab2(lv_obj_t * parent){
|
||||
//Write Tab
|
||||
ta = lv_ta_create(parent, NULL);
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) - 10);
|
||||
lv_obj_set_event_cb(ta, text_area_event_handler);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_NONE);
|
||||
lv_ta_set_text(ta, "");
|
||||
|
||||
/*Create a keyboard and apply the styles*/
|
||||
kb = lv_kb_create(parent, NULL);
|
||||
lv_obj_set_size(kb, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) / 2 - 20);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
/*Assign the text area to the keyboard*/
|
||||
lv_kb_set_ta(kb, ta);
|
||||
|
||||
}
|
||||
|
||||
static void text_area_event_handler(lv_obj_t * text_area, lv_event_t event){
|
||||
lv_obj_t * parent = lv_obj_get_parent(lv_obj_get_parent(ta));
|
||||
if(event == LV_EVENT_LONG_PRESSED){
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) - 10, lv_obj_get_height(parent) / 2);
|
||||
lv_obj_move_foreground(kb);
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_kb_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
mbox_menu_modal();
|
||||
lv_ta_set_cursor_type(ta, LV_CURSOR_NONE);
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
home_menu();
|
||||
}
|
||||
}
|
||||
|
||||
static void mbox_menu_modal(){
|
||||
static lv_style_t modal_style;
|
||||
/* Create a full-screen background */
|
||||
lv_style_copy(&modal_style, &lv_style_plain_color);
|
||||
|
||||
/* Set the background's style */
|
||||
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
||||
modal_style.body.opa = LV_OPA_50;
|
||||
|
||||
/* Create a base object for the modal background */
|
||||
lv_obj_t *obj = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(obj, &modal_style);
|
||||
lv_obj_set_pos(obj, 0, 0);
|
||||
lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
|
||||
lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */
|
||||
|
||||
/* Create the message box as a child of the modal background */
|
||||
mbox = lv_mbox_create(obj, NULL);
|
||||
lv_mbox_add_btns(mbox, modal_popup_btns);
|
||||
lv_mbox_set_text(mbox, "Menu options!");
|
||||
lv_obj_set_size(mbox, LV_HOR_RES - 100, LV_VER_RES - 50);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_event_cb(mbox, mbox_event_cb);
|
||||
|
||||
/* Fade the message box in with an animation */
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_time(&a, 500, 0);
|
||||
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale);
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
|
||||
static void mbox_event_cb(lv_obj_t *obj, lv_event_t evt)
|
||||
{
|
||||
if(evt == LV_EVENT_DELETE && obj == mbox) {
|
||||
/* Delete the parent modal background */
|
||||
lv_obj_del_async(lv_obj_get_parent(mbox));
|
||||
mbox = NULL; /* happens before object is actually deleted! */
|
||||
} else if(evt == LV_EVENT_VALUE_CHANGED) {
|
||||
/* A button was clicked */
|
||||
lv_mbox_start_auto_close(mbox, 0);
|
||||
String contents = lv_ta_get_text(ta);
|
||||
|
||||
if(strcmp(lv_mbox_get_active_btn_text(obj), "Save")==0){
|
||||
if(contents.length() > 0){
|
||||
if(strcmp(currentFileName.c_str(),"New") == 0){
|
||||
Serial.println("New Save");
|
||||
open_mbox_filename();
|
||||
}else{
|
||||
if(writeFile(currentFileName, contents)){
|
||||
Serial.println("Write Success");
|
||||
refresh_list();
|
||||
home_menu();
|
||||
}else{
|
||||
//Error
|
||||
header_set_text("Cannot write to file");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//Nothing to write
|
||||
header_set_text("Nothing to write");
|
||||
}
|
||||
|
||||
}else if(strcmp(lv_mbox_get_active_btn_text(obj), "Save As")==0){
|
||||
if(contents.length() > 0){
|
||||
open_mbox_filename();
|
||||
}
|
||||
|
||||
}else if(strcmp(lv_mbox_get_active_btn_text(obj), "Delete")==0){
|
||||
if(strcmp(currentFileName.c_str(), "New")==0){
|
||||
//Just go back to home screen
|
||||
home_menu();
|
||||
}else{
|
||||
deleteFile(currentFileName);
|
||||
refresh_list();
|
||||
home_menu();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void open_mbox_filename(){
|
||||
mbox_filename = lv_mbox_create(lv_scr_act(), NULL);
|
||||
lv_mbox_set_text(mbox_filename, "File Name");
|
||||
|
||||
ta_filename = lv_ta_create(mbox_filename, NULL);
|
||||
lv_obj_set_size(ta_filename, 200, 40);
|
||||
lv_ta_set_cursor_type(ta_filename, LV_CURSOR_LINE);
|
||||
lv_ta_set_text(ta_filename, "");
|
||||
|
||||
lv_mbox_add_btns(mbox_filename, filename_popup_btns);
|
||||
lv_obj_set_width(mbox_filename, 200);
|
||||
lv_obj_set_event_cb(mbox_filename, filename_event_handler);
|
||||
lv_obj_align(mbox_filename, NULL, LV_ALIGN_IN_TOP_MID, 0, 40);
|
||||
lv_kb_set_ta(kb, ta_filename);
|
||||
}
|
||||
|
||||
static void filename_event_handler(lv_obj_t * obj, lv_event_t event)
|
||||
{
|
||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
lv_mbox_start_auto_close(mbox_filename, 0);
|
||||
printf("Button: %s\n", lv_mbox_get_active_btn_text(obj));
|
||||
|
||||
home_menu();
|
||||
|
||||
if(strcmp(lv_mbox_get_active_btn_text(obj), "Apply")==0){
|
||||
String contents = lv_ta_get_text(ta);
|
||||
String fileName = lv_ta_get_text(ta_filename);
|
||||
if(fileName.length() > 0){
|
||||
if(writeFile("/"+fileName, contents)){
|
||||
//Write Success
|
||||
refresh_list();
|
||||
home_menu();
|
||||
}else{
|
||||
//Cannot write to file
|
||||
header_set_text("Cannot write to file");
|
||||
}
|
||||
}else{
|
||||
//Check the file name
|
||||
header_set_text("Check the file name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void file_list_event(lv_obj_t * btn, lv_event_t e){
|
||||
if(e == LV_EVENT_CLICKED){
|
||||
currentFileName = lv_list_get_btn_text(btn);
|
||||
Serial.println(currentFileName);
|
||||
|
||||
header_set_text(currentFileName);
|
||||
lv_tabview_set_tab_act(tv, 1, LV_ANIM_ON);
|
||||
if(strcmp(currentFileName.c_str(),"New") == 0){
|
||||
lv_ta_set_text(ta, "");
|
||||
}else{
|
||||
lv_ta_set_text(ta, openFile(currentFileName).c_str());
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(lv_obj_get_parent(ta));
|
||||
lv_obj_set_size(ta, lv_obj_get_width(parent) -10, lv_obj_get_height(parent) - 10);
|
||||
lv_obj_move_background(kb);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user