mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 19:26:37 +00:00
commit
f119c20e80
@ -153,6 +153,13 @@ void Renderer::DrawStringAt(int16_t x, int16_t y, const char* text, uint16_t col
|
|||||||
int refcolumn = x;
|
int refcolumn = x;
|
||||||
sFONT *xfont = selected_font;
|
sFONT *xfont = selected_font;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (font == 5 && !drawmode) {
|
||||||
|
// clear bckground
|
||||||
|
int16_t x1,y1;
|
||||||
|
uint16_t w,h;
|
||||||
|
Adafruit_GFX::getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
|
||||||
|
}*/
|
||||||
#ifndef USE_EPD_FONTS
|
#ifndef USE_EPD_FONTS
|
||||||
font=0;
|
font=0;
|
||||||
#endif
|
#endif
|
||||||
@ -297,13 +304,15 @@ void Renderer::setTextFont(uint8_t f) {
|
|||||||
|
|
||||||
|
|
||||||
void Renderer::SetRamfont(uint8_t *font) {
|
void Renderer::SetRamfont(uint8_t *font) {
|
||||||
|
|
||||||
ramfont = (GFXfont*)font;
|
ramfont = (GFXfont*)font;
|
||||||
uint32_t bitmap_offset = (uint32_t)ramfont->bitmap;
|
if (font) {
|
||||||
uint32_t glyph_offset = (uint32_t)ramfont->glyph;
|
uint32_t bitmap_offset = (uint32_t)ramfont->bitmap;
|
||||||
|
uint32_t glyph_offset = (uint32_t)ramfont->glyph;
|
||||||
ramfont->bitmap = (uint8_t*)((uint32_t)font + bitmap_offset);
|
|
||||||
ramfont->glyph = (GFXglyph*)((uint32_t)font + glyph_offset);
|
|
||||||
|
|
||||||
|
ramfont->bitmap = (uint8_t*)((uint32_t)font + bitmap_offset);
|
||||||
|
ramfont->glyph = (GFXglyph*)((uint32_t)font + glyph_offset);
|
||||||
|
}
|
||||||
setFont(ramfont);
|
setFont(ramfont);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,6 +597,33 @@ void Renderer::scrollTo(uint16_t y) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::SetPwrCB(pwr_cb cb) {
|
||||||
|
|
||||||
|
}
|
||||||
|
void Renderer::SetDimCB(dim_cb cb) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Renderer::fgcol(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t Renderer::bgcol(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int8_t Renderer::color_type(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Splash(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char dname[1] = {0};
|
||||||
|
|
||||||
|
char *Renderer::devname(void) {
|
||||||
|
return (char*)dname;
|
||||||
|
}
|
||||||
|
|
||||||
void VButton::xdrawButton(bool inverted) {
|
void VButton::xdrawButton(bool inverted) {
|
||||||
wr_redir=1;
|
wr_redir=1;
|
||||||
drawButton(inverted);
|
drawButton(inverted);
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
// a. in class GFX setCursor,setTextSize => virtual
|
// a. in class GFX setCursor,setTextSize => virtual
|
||||||
// b. textcolor,textbgcolor => public;
|
// b. textcolor,textbgcolor => public;
|
||||||
|
|
||||||
|
typedef void (*pwr_cb)(uint8_t);
|
||||||
|
typedef void (*dim_cb)(uint8_t);
|
||||||
|
|
||||||
class Renderer : public Adafruit_GFX {
|
class Renderer : public Adafruit_GFX {
|
||||||
//Paint(unsigned char* image, int width, int height);
|
//Paint(unsigned char* image, int width, int height);
|
||||||
@ -42,12 +44,21 @@ public:
|
|||||||
virtual void setScrollMargins(uint16_t top, uint16_t bottom);
|
virtual void setScrollMargins(uint16_t top, uint16_t bottom);
|
||||||
virtual void scrollTo(uint16_t y);
|
virtual void scrollTo(uint16_t y);
|
||||||
virtual void TS_RotConvert(int16_t *x, int16_t *y);
|
virtual void TS_RotConvert(int16_t *x, int16_t *y);
|
||||||
|
virtual void SetPwrCB(pwr_cb cb);
|
||||||
|
virtual void SetDimCB(dim_cb cb);
|
||||||
|
virtual uint16_t fgcol(void);
|
||||||
|
virtual uint16_t bgcol(void);
|
||||||
|
virtual int8_t color_type(void);
|
||||||
|
virtual void Splash(void);
|
||||||
|
virtual char *devname(void);
|
||||||
|
|
||||||
void setDrawMode(uint8_t mode);
|
void setDrawMode(uint8_t mode);
|
||||||
uint8_t drawmode;
|
uint8_t drawmode;
|
||||||
virtual void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str);
|
virtual void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str);
|
||||||
void setTextSize(uint8_t s);
|
void setTextSize(uint8_t s);
|
||||||
virtual uint8_t *allocate_framebuffer(uint32_t size);
|
virtual uint8_t *allocate_framebuffer(uint32_t size);
|
||||||
|
pwr_cb pwr_cbp = 0;
|
||||||
|
dim_cb dim_cbp = 0;
|
||||||
private:
|
private:
|
||||||
void DrawCharAt(int16_t x, int16_t y, char ascii_char,int16_t colored);
|
void DrawCharAt(int16_t x, int16_t y, char ascii_char,int16_t colored);
|
||||||
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
||||||
|
@ -31,6 +31,17 @@ uint16_t uDisplay::GetColorFromIndex(uint8_t index) {
|
|||||||
return udisp_colors[index];
|
return udisp_colors[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t uDisplay::fgcol(void) {
|
||||||
|
return fg_col;
|
||||||
|
}
|
||||||
|
uint16_t uDisplay::bgcol(void) {
|
||||||
|
return bg_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t uDisplay::color_type(void) {
|
||||||
|
return col_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uDisplay::~uDisplay(void) {
|
uDisplay::~uDisplay(void) {
|
||||||
if (framebuffer) {
|
if (framebuffer) {
|
||||||
@ -40,6 +51,8 @@ uDisplay::~uDisplay(void) {
|
|||||||
|
|
||||||
uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
|
uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
|
||||||
// analyse decriptor
|
// analyse decriptor
|
||||||
|
pwr_cbp = 0;
|
||||||
|
dim_cbp = 0;
|
||||||
framebuffer = 0;
|
framebuffer = 0;
|
||||||
col_mode = 16;
|
col_mode = 16;
|
||||||
sa_mode = 16;
|
sa_mode = 16;
|
||||||
@ -915,8 +928,8 @@ void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
|
|||||||
SPI_CS_HIGH
|
SPI_CS_HIGH
|
||||||
SPI_END_TRANSACTION
|
SPI_END_TRANSACTION
|
||||||
} else {
|
} else {
|
||||||
SPI_CS_LOW
|
|
||||||
SPI_BEGIN_TRANSACTION
|
SPI_BEGIN_TRANSACTION
|
||||||
|
SPI_CS_LOW
|
||||||
setAddrWindow_int(x0, y0, x1 - x0, y1 - y0 );
|
setAddrWindow_int(x0, y0, x1 - x0, y1 - y0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1092,7 +1105,11 @@ void uDisplay::DisplayOnff(int8_t on) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
udisp_bpwr(on);
|
if (pwr_cbp) {
|
||||||
|
pwr_cbp(on);
|
||||||
|
}
|
||||||
|
|
||||||
|
// udisp_bpwr(on);
|
||||||
|
|
||||||
if (interface == _UDSP_I2C) {
|
if (interface == _UDSP_I2C) {
|
||||||
if (on) {
|
if (on) {
|
||||||
@ -1162,7 +1179,10 @@ void uDisplay::dim(uint8_t dim) {
|
|||||||
if (bpanel >= 0) {
|
if (bpanel >= 0) {
|
||||||
ledcWrite(ESP32_PWM_CHANNEL, dimmer);
|
ledcWrite(ESP32_PWM_CHANNEL, dimmer);
|
||||||
} else {
|
} else {
|
||||||
udisp_dimm(dim);
|
//udisp_dimm(dim);
|
||||||
|
if (dim_cbp) {
|
||||||
|
dim_cbp(dim);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -79,9 +79,9 @@ class uDisplay : public Renderer {
|
|||||||
void DisplayOnff(int8_t on);
|
void DisplayOnff(int8_t on);
|
||||||
void Splash(void);
|
void Splash(void);
|
||||||
char *devname(void);
|
char *devname(void);
|
||||||
uint16_t fgcol(void) const { return fg_col; };
|
uint16_t fgcol(void);
|
||||||
uint16_t bgcol(void) const { return bg_col; };
|
uint16_t bgcol(void);
|
||||||
int8_t color_type(void) const { return col_type; };
|
int8_t color_type(void);
|
||||||
void dim(uint8_t dim);
|
void dim(uint8_t dim);
|
||||||
uint16_t GetColorFromIndex(uint8_t index);
|
uint16_t GetColorFromIndex(uint8_t index);
|
||||||
void setRotation(uint8_t m);
|
void setRotation(uint8_t m);
|
||||||
@ -90,6 +90,8 @@ class uDisplay : public Renderer {
|
|||||||
void pushColors(uint16_t *data, uint16_t len, boolean first);
|
void pushColors(uint16_t *data, uint16_t len, boolean first);
|
||||||
void TS_RotConvert(int16_t *x, int16_t *y);
|
void TS_RotConvert(int16_t *x, int16_t *y);
|
||||||
void invertDisplay(boolean i);
|
void invertDisplay(boolean i);
|
||||||
|
void SetPwrCB(pwr_cb cb) { pwr_cbp = cb; };
|
||||||
|
void SetDimCB(dim_cb cb) { dim_cbp = cb; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||||
|
@ -22,107 +22,15 @@ static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); }
|
|||||||
#define ADC_YMIN 240
|
#define ADC_YMIN 240
|
||||||
#define ADC_YMAX 840
|
#define ADC_YMAX 840
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Touch_Status(uint32_t sel);
|
||||||
|
|
||||||
static bool touchscreen_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
|
static bool touchscreen_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
|
||||||
// static lv_coord_t last_x = 0, last_y = 0;
|
//lv_coord_t last_x = 0, last_y = 0;
|
||||||
// static uint8_t release_count = 0;
|
//static uint8_t release_count = 0;
|
||||||
|
data->point.x = Touch_Status(1); // Last-pressed coordinates
|
||||||
// // Get pointer to glue object from indev user data
|
data->point.y = Touch_Status(2);
|
||||||
// Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)indev_drv->user_data;
|
data->state = Touch_Status(0);
|
||||||
// uDisplay_lvgl *disp = glue->display;
|
|
||||||
|
|
||||||
// if (glue->is_adc_touch) {
|
|
||||||
// TouchScreen *touch = (TouchScreen *)glue->touchscreen;
|
|
||||||
// TSPoint p = touch->getPoint();
|
|
||||||
// // Serial.printf("%d %d %d\r\n", p.x, p.y, p.z);
|
|
||||||
// // Having an issue with spurious z=0 results from TouchScreen lib.
|
|
||||||
// // Since touch is polled periodically, workaround is to watch for
|
|
||||||
// // several successive z=0 results, and only then regard it as
|
|
||||||
// // a release event (otherwise still touched).
|
|
||||||
// if (p.z < touch->pressureThreshhold) { // A zero-ish value
|
|
||||||
// release_count += (release_count < 255);
|
|
||||||
// if (release_count >= 4) {
|
|
||||||
// data->state = LV_INDEV_STATE_REL; // Is REALLY RELEASED
|
|
||||||
// } else {
|
|
||||||
// data->state = LV_INDEV_STATE_PR; // Is STILL PRESSED
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// release_count = 0; // Reset release counter
|
|
||||||
// data->state = LV_INDEV_STATE_PR; // Is PRESSED
|
|
||||||
// switch (glue->display->getRotation()) {
|
|
||||||
// case 0:
|
|
||||||
// last_x = map(p.x, ADC_XMIN, ADC_XMAX, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.y, ADC_YMAX, ADC_YMIN, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 1:
|
|
||||||
// last_x = map(p.y, ADC_YMAX, ADC_YMIN, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.x, ADC_XMAX, ADC_XMIN, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 2:
|
|
||||||
// last_x = map(p.x, ADC_XMAX, ADC_XMIN, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.y, ADC_YMIN, ADC_YMAX, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 3:
|
|
||||||
// last_x = map(p.y, ADC_YMIN, ADC_YMAX, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.x, ADC_XMIN, ADC_XMAX, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// data->point.x = last_x; // Last-pressed coordinates
|
|
||||||
// data->point.y = last_y;
|
|
||||||
// return false; // No buffering of ADC touch data
|
|
||||||
// } else {
|
|
||||||
// uint8_t fifo; // Number of points in touchscreen FIFO
|
|
||||||
// bool moar = false;
|
|
||||||
// Adafruit_STMPE610 *touch = (Adafruit_STMPE610 *)glue->touchscreen;
|
|
||||||
// // Before accessing SPI touchscreen, wait on any in-progress
|
|
||||||
// // DMA screen transfer to finish (shared bus).
|
|
||||||
// //disp->dmaWait();
|
|
||||||
// // disp->endWrite();
|
|
||||||
// if ((fifo = touch->bufferSize())) { // 1 or more points await
|
|
||||||
// data->state = LV_INDEV_STATE_PR; // Is PRESSED
|
|
||||||
// TS_Point p = touch->getPoint();
|
|
||||||
// // Serial.printf("%d %d %d\r\n", p.x, p.y, p.z);
|
|
||||||
// // On big TFT FeatherWing, raw X axis is flipped??
|
|
||||||
// if ((glue->display->width() == 480) || (glue->display->height() == 480)) {
|
|
||||||
// p.x = (TS_MINX + TS_MAXX) - p.x;
|
|
||||||
// }
|
|
||||||
// switch (glue->display->getRotation()) {
|
|
||||||
// case 0:
|
|
||||||
// last_x = map(p.x, TS_MAXX, TS_MINX, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.y, TS_MINY, TS_MAXY, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 1:
|
|
||||||
// last_x = map(p.y, TS_MINY, TS_MAXY, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.x, TS_MINX, TS_MAXX, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 2:
|
|
||||||
// last_x = map(p.x, TS_MINX, TS_MAXX, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.y, TS_MAXY, TS_MINY, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// case 3:
|
|
||||||
// last_x = map(p.y, TS_MAXY, TS_MINY, 0, disp->width() - 1);
|
|
||||||
// last_y = map(p.x, TS_MAXX, TS_MINX, 0, disp->height() - 1);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// moar = (fifo > 1); // true if more in FIFO, false if last point
|
|
||||||
// #if defined(NRF52_SERIES)
|
|
||||||
// // Not sure what's up here, but nRF doesn't seem to always poll
|
|
||||||
// // the FIFO size correctly, causing false release events. If it
|
|
||||||
// // looks like we've read the last point from the FIFO, pause
|
|
||||||
// // briefly to allow any more FIFO events to pile up. This
|
|
||||||
// // doesn't seem to be necessary on SAMD or ESP32. ???
|
|
||||||
// if (!moar) {
|
|
||||||
// delay(50);
|
|
||||||
// }
|
|
||||||
// #endif
|
|
||||||
// } else { // FIFO empty
|
|
||||||
// data->state = LV_INDEV_STATE_REL; // Is RELEASED
|
|
||||||
// }
|
|
||||||
|
|
||||||
// data->point.x = last_x; // Last-pressed coordinates
|
|
||||||
// data->point.y = last_y;
|
|
||||||
// return moar;
|
|
||||||
// }
|
|
||||||
return false; /*No buffering now so no more data read*/
|
return false; /*No buffering now so no more data read*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +73,7 @@ static void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_col
|
|||||||
return; // ok
|
return; // ok
|
||||||
}
|
}
|
||||||
|
|
||||||
uDisplay_lvgl *display = glue->display;
|
Renderer *display = glue->display;
|
||||||
|
|
||||||
if (!glue->first_frame) {
|
if (!glue->first_frame) {
|
||||||
//display->dmaWait(); // Wait for prior DMA transfer to complete
|
//display->dmaWait(); // Wait for prior DMA transfer to complete
|
||||||
@ -174,11 +82,9 @@ static void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_col
|
|||||||
glue->first_frame = false;
|
glue->first_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// display->startWrite();
|
display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height);
|
||||||
// display->setAddrWindow(area->x1, area->y1, width, height);
|
display->pushColors((uint16_t *)color_p, width * height, true);
|
||||||
display->writePixels(area->x1, area->y1, width, height,
|
display->setAddrWindow(0,0,0,0);
|
||||||
(uint16_t *)color_p, width * height);
|
|
||||||
// display->pushColors((uint16_t *)color_p, width * height, false);
|
|
||||||
|
|
||||||
lv_disp_flush_ready(disp);
|
lv_disp_flush_ready(disp);
|
||||||
}
|
}
|
||||||
@ -286,11 +192,11 @@ Adafruit_LvGL_Glue::~Adafruit_LvGL_Glue(void) {
|
|||||||
* * LVGL_ERR_TIMER : Failure to set up timers
|
* * LVGL_ERR_TIMER : Failure to set up timers
|
||||||
* * LVGL_ERR_ALLOC : Failure to allocate memory
|
* * LVGL_ERR_ALLOC : Failure to allocate memory
|
||||||
*/
|
*/
|
||||||
LvGLStatus Adafruit_LvGL_Glue::begin(uDisplay_lvgl *tft, bool debug) {
|
LvGLStatus Adafruit_LvGL_Glue::begin(Renderer *tft, bool debug) {
|
||||||
return begin(tft, (void *)NULL, debug);
|
return begin(tft, (void *)NULL, debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
LvGLStatus Adafruit_LvGL_Glue::begin(uDisplay_lvgl *tft, void *touch, bool debug) {
|
LvGLStatus Adafruit_LvGL_Glue::begin(Renderer *tft, void *touch, bool debug) {
|
||||||
|
|
||||||
lv_init();
|
lv_init();
|
||||||
// #if (LV_USE_LOG)
|
// #if (LV_USE_LOG)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define _ADAFRUIT_LVGL_GLUE_H_
|
#define _ADAFRUIT_LVGL_GLUE_H_
|
||||||
|
|
||||||
#include <lvgl.h> // LittlevGL core lib
|
#include <lvgl.h> // LittlevGL core lib
|
||||||
#include <uDisplay_lvgl.h>
|
#include <renderer.h>
|
||||||
#include <Ticker.h> // ESP32-specific timer lib
|
#include <Ticker.h> // ESP32-specific timer lib
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
@ -27,10 +27,11 @@ public:
|
|||||||
// bool debug = false);
|
// bool debug = false);
|
||||||
// LvGLStatus begin(uDisplay_lvgl *tft, TouchScreen *touch,
|
// LvGLStatus begin(uDisplay_lvgl *tft, TouchScreen *touch,
|
||||||
// bool debug = false);
|
// bool debug = false);
|
||||||
LvGLStatus begin(uDisplay_lvgl *tft, bool debug = false);
|
LvGLStatus begin(Renderer *tft, bool debug = false);
|
||||||
|
LvGLStatus begin(Renderer *tft, void *touch, bool debug);
|
||||||
// These items need to be public for some internal callbacks,
|
// These items need to be public for some internal callbacks,
|
||||||
// but should be avoided by user code please!
|
// but should be avoided by user code please!
|
||||||
uDisplay_lvgl *display; ///< Pointer to the SPITFT display instance
|
Renderer *display; ///< Pointer to the SPITFT display instance
|
||||||
void *touchscreen; ///< Pointer to the touchscreen object to use
|
void *touchscreen; ///< Pointer to the touchscreen object to use
|
||||||
bool is_adc_touch; ///< determines if the touchscreen controlelr is ADC based
|
bool is_adc_touch; ///< determines if the touchscreen controlelr is ADC based
|
||||||
bool first_frame; ///< Tracks if a call to `lv_flush_callback` needs to wait
|
bool first_frame; ///< Tracks if a call to `lv_flush_callback` needs to wait
|
||||||
@ -40,7 +41,6 @@ public:
|
|||||||
void stopScreenshot(void) { screenshot = nullptr; }
|
void stopScreenshot(void) { screenshot = nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LvGLStatus begin(uDisplay_lvgl *tft, void *touch, bool debug);
|
|
||||||
lv_disp_drv_t lv_disp_drv;
|
lv_disp_drv_t lv_disp_drv;
|
||||||
lv_disp_buf_t lv_disp_buf;
|
lv_disp_buf_t lv_disp_buf;
|
||||||
lv_color_t *lv_pixel_buf;
|
lv_color_t *lv_pixel_buf;
|
||||||
|
@ -2621,6 +2621,15 @@ chknext:
|
|||||||
tind->bits.is_string = 0;
|
tind->bits.is_string = 0;
|
||||||
return lp + len;
|
return lp + len;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_LVGL
|
||||||
|
if (!strncmp(vname, "lvgl(", 5)) {
|
||||||
|
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
|
||||||
|
fvar = lvgl_test(fvar);
|
||||||
|
lp++;
|
||||||
|
len = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
if (!strncmp(vname, "med(", 4)) {
|
if (!strncmp(vname, "med(", 4)) {
|
||||||
@ -7704,6 +7713,192 @@ void cpy2lf(char *dst, uint32_t dstlen, char *src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_LVGL
|
||||||
|
#include <renderer.h>
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char ili9342[] PROGMEM =
|
||||||
|
":H,ILI9342,320,240,16,SPI,1,*,*,*,*,*,*,*,40\n"
|
||||||
|
":S,2,1,3,0,100,100\n"
|
||||||
|
":I\n"
|
||||||
|
"EF,3,03,80,02\n"
|
||||||
|
"CF,3,00,C1,30\n"
|
||||||
|
"ED,4,64,03,12,81\n"
|
||||||
|
"E8,3,85,00,78\n"
|
||||||
|
"CB,5,39,2C,00,34,02\n"
|
||||||
|
"F7,1,20\n"
|
||||||
|
"EA,2,00,00\n"
|
||||||
|
"C0,1,23\n"
|
||||||
|
"C1,1,10\n"
|
||||||
|
"C5,2,3e,28\n"
|
||||||
|
"C7,1,86\n"
|
||||||
|
"36,1,48\n"
|
||||||
|
"37,1,00\n"
|
||||||
|
"3A,1,55\n"
|
||||||
|
"B1,2,00,18\n"
|
||||||
|
"B6,3,08,82,27\n"
|
||||||
|
"F2,1,00\n"
|
||||||
|
"26,1,01\n"
|
||||||
|
"E0,0F,0F,31,2B,0C,0E,08,4E,F1,37,07,10,03,0E,09,00\n"
|
||||||
|
"E1,0F,00,0E,14,03,11,07,31,C1,48,08,0F,0C,31,36,0F\n"
|
||||||
|
"21,80\n"
|
||||||
|
"11,80\n"
|
||||||
|
"29,80\n"
|
||||||
|
":o,28\n"
|
||||||
|
":O,29\n"
|
||||||
|
":A,2A,2B,2C,16\n"
|
||||||
|
":R,36\n"
|
||||||
|
":0,08,00,00,00\n"
|
||||||
|
":1,A8,00,00,01\n"
|
||||||
|
":2,C8,00,00,02\n"
|
||||||
|
":3,68,00,00,03\n"
|
||||||
|
":i,21,20\n"
|
||||||
|
":TI2,38,22,21\n"
|
||||||
|
"#\n";
|
||||||
|
|
||||||
|
void start_lvgl(const char * uconfig);
|
||||||
|
|
||||||
|
void btn_event_cb(lv_obj_t * btn, lv_event_t event);
|
||||||
|
void btn_event_cb(lv_obj_t * btn, lv_event_t event) {
|
||||||
|
if (event == LV_EVENT_CLICKED) {
|
||||||
|
AddLog_P(LOG_LEVEL_INFO,PSTR(">>> clicked"));
|
||||||
|
}
|
||||||
|
AddLog_P(LOG_LEVEL_INFO,PSTR(">>> clicked"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t lvgl_test(int32_t p) {
|
||||||
|
start_lvgl(ili9342);
|
||||||
|
lv_obj_clean(lv_scr_act());
|
||||||
|
|
||||||
|
lv_obj_t *label1 = lv_label_create(lv_scr_act(), NULL);
|
||||||
|
|
||||||
|
/*Modify the Label's text*/
|
||||||
|
lv_label_set_text(label1, "Hello world!");
|
||||||
|
|
||||||
|
/* Align the Label to the center
|
||||||
|
* NULL means align on parent (which is the screen now)
|
||||||
|
* 0, 0 at the end means an x, y offset after alignment*/
|
||||||
|
lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
lvgl_setup();
|
||||||
|
|
||||||
|
/*Add a button*/
|
||||||
|
lv_obj_t *btn1 = lv_btn_create(lv_scr_act(), NULL); /*Add to the active screen*/
|
||||||
|
lv_obj_set_pos(btn1, 2, 2); /*Adjust the position*/
|
||||||
|
lv_obj_set_size(btn1, 96, 30); /* set size of button */
|
||||||
|
lv_obj_set_event_cb(btn1, btn_event_cb);
|
||||||
|
|
||||||
|
/*Add text*/
|
||||||
|
lv_obj_t *label = lv_label_create(btn1, NULL); /*Put on 'btn1'*/
|
||||||
|
lv_label_set_text(label, "Click");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_obj_t *tabview, // LittlevGL tabview object
|
||||||
|
*gauge, // Gauge object (on first of three tabs)
|
||||||
|
*chart, // Chart object (second tab)
|
||||||
|
*canvas; // Canvas object (third tab)
|
||||||
|
uint8_t active_tab = 0, // Index of currently-active tab (0-2)
|
||||||
|
prev_tab = 0; // Index of previously-active tab
|
||||||
|
lv_chart_series_t *series; // 'Series' data for the bar chart
|
||||||
|
lv_draw_line_dsc_t draw_dsc; // Drawing style (for canvas) is similarly global
|
||||||
|
|
||||||
|
#define CANVAS_WIDTH 200 // Dimensions in pixels
|
||||||
|
#define CANVAS_HEIGHT 150
|
||||||
|
|
||||||
|
void lvgl_setup(void) {
|
||||||
|
// Create a tabview object, by default this covers the full display.
|
||||||
|
tabview = lv_tabview_create(lv_disp_get_scr_act(NULL), NULL);
|
||||||
|
// The CLUE display has a lot of pixels and can't refresh very fast.
|
||||||
|
// To show off the tabview animation, let's slow it down to 1 second.
|
||||||
|
lv_tabview_set_anim_time(tabview, 1000);
|
||||||
|
|
||||||
|
// Because they're referenced any time an object is drawn, styles need
|
||||||
|
// to be permanent in scope; either declared globally (outside all
|
||||||
|
// functions), or static. The styles used on tabs are never modified after
|
||||||
|
// they're used here, so let's use static on those...
|
||||||
|
static lv_style_t tab_style, tab_background_style, indicator_style;
|
||||||
|
|
||||||
|
// This is the background style "behind" the tabs. This is what shows
|
||||||
|
// through for "off" (inactive) tabs -- a vertical green gradient,
|
||||||
|
// minimal padding around edges (zero at bottom).
|
||||||
|
lv_style_init(&tab_background_style);
|
||||||
|
lv_style_set_bg_color(&tab_background_style, LV_STATE_DEFAULT, lv_color_hex(0x408040));
|
||||||
|
lv_style_set_bg_grad_color(&tab_background_style, LV_STATE_DEFAULT, lv_color_hex(0x304030));
|
||||||
|
lv_style_set_bg_grad_dir(&tab_background_style, LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
|
||||||
|
lv_style_set_pad_top(&tab_background_style, LV_STATE_DEFAULT, 2);
|
||||||
|
lv_style_set_pad_left(&tab_background_style, LV_STATE_DEFAULT, 2);
|
||||||
|
lv_style_set_pad_right(&tab_background_style, LV_STATE_DEFAULT, 2);
|
||||||
|
lv_style_set_pad_bottom(&tab_background_style, LV_STATE_DEFAULT, 0);
|
||||||
|
lv_obj_add_style(tabview, LV_TABVIEW_PART_TAB_BG, &tab_background_style);
|
||||||
|
|
||||||
|
// Style for tabs. Active tab is white with opaque background, inactive
|
||||||
|
// tabs are transparent so the background shows through (only the white
|
||||||
|
// text is seen). A little top & bottom padding reduces scrunchyness.
|
||||||
|
lv_style_init(&tab_style);
|
||||||
|
lv_style_set_pad_top(&tab_style, LV_STATE_DEFAULT, 3);
|
||||||
|
lv_style_set_pad_bottom(&tab_style, LV_STATE_DEFAULT, 10);
|
||||||
|
lv_style_set_bg_color(&tab_style, LV_STATE_CHECKED, LV_COLOR_WHITE);
|
||||||
|
lv_style_set_bg_opa(&tab_style, LV_STATE_CHECKED, LV_OPA_100);
|
||||||
|
lv_style_set_text_color(&tab_style, LV_STATE_CHECKED, LV_COLOR_GRAY);
|
||||||
|
lv_style_set_bg_opa(&tab_style, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||||
|
lv_style_set_text_color(&tab_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||||
|
lv_obj_add_style(tabview, LV_TABVIEW_PART_TAB_BTN, &tab_style);
|
||||||
|
|
||||||
|
// Style for the small indicator bar that appears below the active tab.
|
||||||
|
lv_style_init(&indicator_style);
|
||||||
|
lv_style_set_bg_color(&indicator_style, LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||||
|
lv_style_set_size(&indicator_style, LV_STATE_DEFAULT, 5);
|
||||||
|
lv_obj_add_style(tabview, LV_TABVIEW_PART_INDIC, &indicator_style);
|
||||||
|
|
||||||
|
// Back to creating widgets...
|
||||||
|
|
||||||
|
// Add three tabs to the tabview
|
||||||
|
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Gauge");
|
||||||
|
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Chart");
|
||||||
|
lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Canvas");
|
||||||
|
|
||||||
|
// And then add stuff in each tab...
|
||||||
|
|
||||||
|
// The first tab holds a gauge. To keep the demo simple, let's just use
|
||||||
|
// the default style and range (0-100). See LittlevGL docs for options.
|
||||||
|
gauge = lv_gauge_create(tab1, NULL);
|
||||||
|
lv_obj_set_size(gauge, 186, 186);
|
||||||
|
lv_obj_align(gauge, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
|
// Second tab, make a chart...
|
||||||
|
chart = lv_chart_create(tab2, NULL);
|
||||||
|
lv_obj_set_size(chart, 200, 180);
|
||||||
|
lv_obj_align(chart, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_chart_set_type(chart, LV_CHART_TYPE_COLUMN);
|
||||||
|
// For simplicity, we'll stick with the chart's default 10 data points:
|
||||||
|
series = lv_chart_add_series(chart, LV_COLOR_RED);
|
||||||
|
lv_chart_init_points(chart, series, 0);
|
||||||
|
// Make each column shift left as new values enter on right:
|
||||||
|
lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);
|
||||||
|
|
||||||
|
// Third tab is a canvas, which we'll fill with random colored lines.
|
||||||
|
// LittlevGL draw functions only work on TRUE_COLOR canvas.
|
||||||
|
/* canvas = lv_canvas_create(tab3, NULL);
|
||||||
|
lv_canvas_set_buffer(canvas, canvas_buffer,
|
||||||
|
CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_TRUE_COLOR);
|
||||||
|
lv_obj_align(canvas, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_canvas_fill_bg(canvas, LV_COLOR_WHITE, LV_OPA_100);
|
||||||
|
|
||||||
|
// Set up canvas line-drawing style based on defaults.
|
||||||
|
// Later we'll change color settings when drawing each line.
|
||||||
|
lv_draw_line_dsc_init(&draw_dsc);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
@ -7868,6 +8063,12 @@ bool Xdrv10(uint8_t function)
|
|||||||
case FUNC_EVERY_100_MSECOND:
|
case FUNC_EVERY_100_MSECOND:
|
||||||
ScripterEvery100ms();
|
ScripterEvery100ms();
|
||||||
break;
|
break;
|
||||||
|
#ifdef USE_LVGL
|
||||||
|
case FUNC_EVERY_50_MSECOND:
|
||||||
|
lv_task_handler();
|
||||||
|
break;
|
||||||
|
#endif // USE_LVGL
|
||||||
|
|
||||||
case FUNC_EVERY_SECOND:
|
case FUNC_EVERY_SECOND:
|
||||||
ScriptEverySecond();
|
ScriptEverySecond();
|
||||||
break;
|
break;
|
||||||
|
@ -824,27 +824,36 @@ extern FS *ffsp;
|
|||||||
char fname[32];
|
char fname[32];
|
||||||
*ep = 0;
|
*ep = 0;
|
||||||
ep++;
|
ep++;
|
||||||
if (*cp != '/') {
|
if (*cp == '-' && *(cp + 1) == 0) {
|
||||||
fname[0] = '/';
|
if (ram_font) {
|
||||||
fname[1] = 0;
|
free (ram_font);
|
||||||
|
ram_font = 0;
|
||||||
|
if (renderer) renderer->SetRamfont(0);
|
||||||
|
}
|
||||||
|
cp = ep;
|
||||||
} else {
|
} else {
|
||||||
fname[0] = 0;
|
if (*cp != '/') {
|
||||||
}
|
fname[0] = '/';
|
||||||
strlcat(fname, cp, sizeof(fname));
|
fname[1] = 0;
|
||||||
if (!strstr(cp, ".fnt")) {
|
} else {
|
||||||
strlcat(fname, ".fnt", sizeof(fname));
|
fname[0] = 0;
|
||||||
}
|
}
|
||||||
if (ffsp) {
|
strlcat(fname, cp, sizeof(fname));
|
||||||
File fp;
|
if (!strstr(cp, ".fnt")) {
|
||||||
fp = ffsp->open(fname, "r");
|
strlcat(fname, ".fnt", sizeof(fname));
|
||||||
if (fp > 0) {
|
}
|
||||||
uint32_t size = fp.size();
|
if (ffsp) {
|
||||||
if (ram_font) free (ram_font);
|
File fp;
|
||||||
ram_font = (uint8_t*)special_malloc(size + 4);
|
fp = ffsp->open(fname, "r");
|
||||||
fp.read((uint8_t*)ram_font, size);
|
if (fp > 0) {
|
||||||
fp.close();
|
uint32_t size = fp.size();
|
||||||
if (renderer) renderer->SetRamfont(ram_font);
|
if (ram_font) free (ram_font);
|
||||||
//Serial.printf("Font loaded: %s\n",fname );
|
ram_font = (uint8_t*)special_malloc(size + 4);
|
||||||
|
fp.read((uint8_t*)ram_font, size);
|
||||||
|
fp.close();
|
||||||
|
if (renderer) renderer->SetRamfont(ram_font);
|
||||||
|
//Serial.printf("Font loaded: %s\n",fname );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cp = ep;
|
cp = ep;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#ifdef USE_LVGL
|
#ifdef USE_LVGL
|
||||||
|
|
||||||
#include <uDisplay_lvgl.h>
|
#include <renderer.h>
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
#define XDRV_54 54
|
#define XDRV_54 54
|
||||||
@ -37,7 +37,7 @@
|
|||||||
* you should lock on the very same semaphore! */
|
* you should lock on the very same semaphore! */
|
||||||
|
|
||||||
SemaphoreHandle_t xGuiSemaphore;
|
SemaphoreHandle_t xGuiSemaphore;
|
||||||
uDisplay_lvgl * udisp = nullptr;
|
//uDisplay * udisp = nullptr;
|
||||||
|
|
||||||
// necessary for compilation
|
// necessary for compilation
|
||||||
uint8_t color_type_lvgl = 0;
|
uint8_t color_type_lvgl = 0;
|
||||||
@ -121,7 +121,7 @@ static void guiTask(void *pvParameter) {
|
|||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Callbacks for file system access from LVGL
|
* Callbacks for file system access from LVGL
|
||||||
*
|
*
|
||||||
* Useful to load fonts or images from file system
|
* Useful to load fonts or images from file system
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ static lv_fs_res_t lvbe_fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos)
|
|||||||
return LV_FS_RES_OK;
|
return LV_FS_RES_OK;
|
||||||
} else {
|
} else {
|
||||||
return LV_FS_RES_UNKNOWN;
|
return LV_FS_RES_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_fs_res_t lvbe_fs_size(lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
|
static lv_fs_res_t lvbe_fs_size(lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
|
||||||
@ -238,11 +238,14 @@ static lv_fs_res_t lvbe_fs_remove(lv_fs_drv_t * drv, const char *path) {
|
|||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Initialize the display / touchscreen drivers then launch lvgl
|
* Initialize the display / touchscreen drivers then launch lvgl
|
||||||
*
|
*
|
||||||
* We use Adafruit_LvGL_Glue to leverage the Adafruit
|
* We use Adafruit_LvGL_Glue to leverage the Adafruit
|
||||||
* display ecosystem.
|
* display ecosystem.
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
|
Renderer *Init_uDisplay(const char *desc, int8_t cs);
|
||||||
|
|
||||||
|
|
||||||
void start_lvgl(const char * uconfig);
|
void start_lvgl(const char * uconfig);
|
||||||
void start_lvgl(const char * uconfig) {
|
void start_lvgl(const char * uconfig) {
|
||||||
|
|
||||||
@ -251,25 +254,22 @@ void start_lvgl(const char * uconfig) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (udisp == nullptr) {
|
if (uconfig && !renderer) {
|
||||||
udisp = new uDisplay_lvgl((char*)uconfig);
|
#ifdef USE_UNIVERSAL_DISPLAY
|
||||||
|
renderer = Init_uDisplay((char*)uconfig, -1);
|
||||||
|
if (!renderer) return;
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
udisp->Init();
|
|
||||||
|
|
||||||
// Settings.display_width = udisp->width();
|
|
||||||
// Settings.display_height = udisp->height();
|
|
||||||
|
|
||||||
udisp->DisplayInit(0 /* DISPLAY_INIT_MODE */, Settings.display_size, Settings.display_rotate, Settings.display_font);
|
|
||||||
udisp->dim(Settings.display_dimmer);
|
|
||||||
|
|
||||||
// **************************************************
|
// **************************************************
|
||||||
// Initialize the glue between Adafruit and LVGL
|
// Initialize the glue between Adafruit and LVGL
|
||||||
// **************************************************
|
// **************************************************
|
||||||
glue = new Adafruit_LvGL_Glue();
|
glue = new Adafruit_LvGL_Glue();
|
||||||
|
|
||||||
// Initialize glue, passing in address of display & touchscreen
|
// Initialize glue, passing in address of display & touchscreen
|
||||||
LvGLStatus status = glue->begin(udisp);
|
LvGLStatus status = glue->begin(renderer, (void*)1, false);
|
||||||
if (status != LVGL_OK) {
|
if (status != LVGL_OK) {
|
||||||
AddLog(LOG_LEVEL_ERROR, PSTR("Glue error %d"), status);
|
AddLog(LOG_LEVEL_ERROR, PSTR("Glue error %d"), status);
|
||||||
return;
|
return;
|
||||||
@ -277,8 +277,10 @@ void start_lvgl(const char * uconfig) {
|
|||||||
|
|
||||||
// Set the default background color of the display
|
// Set the default background color of the display
|
||||||
// This is normally overriden by an opaque screen on top
|
// This is normally overriden by an opaque screen on top
|
||||||
|
#ifdef USE_BERRY
|
||||||
lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, lv_color_from_uint32(USE_LVGL_BG_DEFAULT));
|
lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, lv_color_from_uint32(USE_LVGL_BG_DEFAULT));
|
||||||
lv_obj_set_style_local_bg_opa(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_obj_set_style_local_bg_opa(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LV_USE_LOG
|
#if LV_USE_LOG
|
||||||
lv_log_register_print_cb(lvbe_debug);
|
lv_log_register_print_cb(lvbe_debug);
|
||||||
@ -319,6 +321,8 @@ void start_lvgl(const char * uconfig) {
|
|||||||
* Otherwise there can be problem such as memory corruption and so on.
|
* Otherwise there can be problem such as memory corruption and so on.
|
||||||
* NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */
|
* NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */
|
||||||
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
|
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("LVGL initialized"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
|
Loading…
x
Reference in New Issue
Block a user