mirror of https://github.com/arendst/Tasmota.git
lvgl touch added
This commit is contained in:
parent
9e27eb394e
commit
70c2290c9d
|
@ -22,107 +22,15 @@ static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); }
|
|||
#define ADC_YMIN 240
|
||||
#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 lv_coord_t last_x = 0, last_y = 0;
|
||||
// static uint8_t release_count = 0;
|
||||
|
||||
// // Get pointer to glue object from indev user data
|
||||
// Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)indev_drv->user_data;
|
||||
// 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;
|
||||
// }
|
||||
//lv_coord_t last_x = 0, last_y = 0;
|
||||
//static uint8_t release_count = 0;
|
||||
data->point.x = Touch_Status(1); // Last-pressed coordinates
|
||||
data->point.y = Touch_Status(2);
|
||||
data->state = Touch_Status(0);
|
||||
return false; /*No buffering now so no more data read*/
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
// LvGLStatus begin(uDisplay_lvgl *tft, TouchScreen *touch,
|
||||
// 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,
|
||||
// but should be avoided by user code please!
|
||||
Renderer *display; ///< Pointer to the SPITFT display instance
|
||||
|
@ -40,7 +41,6 @@ public:
|
|||
void stopScreenshot(void) { screenshot = nullptr; }
|
||||
|
||||
private:
|
||||
LvGLStatus begin(Renderer *tft, void *touch, bool debug);
|
||||
lv_disp_drv_t lv_disp_drv;
|
||||
lv_disp_buf_t lv_disp_buf;
|
||||
lv_color_t *lv_pixel_buf;
|
||||
|
|
|
@ -7757,9 +7757,17 @@ const char ili9342[] PROGMEM =
|
|||
":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());
|
||||
|
@ -7775,73 +7783,120 @@ int32_t lvgl_test(int32_t p) {
|
|||
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_btn_set_action(btn1, LV_BTN_ACTION_CLICK, my_click_action); /*Assign a callback for clicking*/
|
||||
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
|
||||
|
||||
lv_obj_t * myButton;
|
||||
lv_obj_t * myButtonLabel;
|
||||
lv_obj_t * myLabel;
|
||||
#define CANVAS_WIDTH 200 // Dimensions in pixels
|
||||
#define CANVAS_HEIGHT 150
|
||||
|
||||
lv_style_t myButtonStyleREL; //relesed style
|
||||
lv_style_t myButtonStylePR; //pressed style
|
||||
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);
|
||||
|
||||
static lv_res_t btn_click_action(lv_obj_t * btn) {
|
||||
uint8_t id = lv_obj_get_free_num(btn); //id usefull when there are multiple buttons
|
||||
// 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;
|
||||
|
||||
if(id == 0)
|
||||
{
|
||||
char buffer[100];
|
||||
sprintf(buffer, "button was clicked %i milliseconds from start", pros::millis());
|
||||
lv_label_set_text(myLabel, buffer);
|
||||
}
|
||||
// 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);
|
||||
|
||||
return LV_RES_OK;
|
||||
// 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);
|
||||
*/
|
||||
}
|
||||
|
||||
#define LV_COLOR_MAKE lv_color_make
|
||||
|
||||
void initialize() {
|
||||
lv_style_copy(&myButtonStyleREL, &lv_style_plain);
|
||||
myButtonStyleREL.body.main_color = LV_COLOR_MAKE(150, 0, 0);
|
||||
myButtonStyleREL.body.grad_color = LV_COLOR_MAKE(0, 0, 150);
|
||||
myButtonStyleREL.body.radius = 0;
|
||||
myButtonStyleREL.text.color = LV_COLOR_MAKE(255, 255, 255);
|
||||
|
||||
lv_style_copy(&myButtonStylePR, &lv_style_plain);
|
||||
myButtonStylePR.body.main_color = LV_COLOR_MAKE(255, 0, 0);
|
||||
myButtonStylePR.body.grad_color = LV_COLOR_MAKE(0, 0, 255);
|
||||
myButtonStylePR.body.radius = 0;
|
||||
myButtonStylePR.text.color = LV_COLOR_MAKE(255, 255, 255);
|
||||
|
||||
myButton = lv_btn_create(lv_scr_act(), NULL); //create button, lv_scr_act() is deafult screen object
|
||||
lv_obj_set_free_num(myButton, 0); //set button is to 0
|
||||
lv_btn_set_action(myButton, LV_BTN_ACTION_CLICK, btn_click_action); //set function to be called on button click
|
||||
lv_btn_set_style(myButton, LV_BTN_STYLE_REL, &myButtonStyleREL); //set the relesed style
|
||||
lv_btn_set_style(myButton, LV_BTN_STYLE_PR, &myButtonStylePR); //set the pressed style
|
||||
lv_obj_set_size(myButton, 200, 50); //set the button size
|
||||
lv_obj_align(myButton, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10); //set the position to top mid
|
||||
|
||||
myButtonLabel = lv_label_create(myButton, NULL); //create label and puts it inside of the button
|
||||
lv_label_set_text(myButtonLabel, "Click the Button"); //sets label text
|
||||
|
||||
myLabel = lv_label_create(lv_scr_act(), NULL); //create label and puts it on the screen
|
||||
lv_label_set_text(myLabel, "Button has not been clicked yet"); //sets label text
|
||||
lv_obj_align(myLabel, NULL, LV_ALIGN_LEFT_MID, 10, 0); //set the position to center
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -8008,6 +8063,12 @@ bool Xdrv10(uint8_t function)
|
|||
case FUNC_EVERY_100_MSECOND:
|
||||
ScripterEvery100ms();
|
||||
break;
|
||||
#ifdef USE_LVGL
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
lv_task_handler();
|
||||
break;
|
||||
#endif // USE_LVGL
|
||||
|
||||
case FUNC_EVERY_SECOND:
|
||||
ScriptEverySecond();
|
||||
break;
|
||||
|
|
|
@ -243,7 +243,8 @@ static lv_fs_res_t lvbe_fs_remove(lv_fs_drv_t * drv, const char *path) {
|
|||
* display ecosystem.
|
||||
************************************************************/
|
||||
|
||||
Renderer *Init_uDisplay(const char *desc, int8_t cs);
|
||||
Renderer *Init_uDisplay(const char *desc, int8_t cs);
|
||||
|
||||
|
||||
void start_lvgl(const char * uconfig);
|
||||
void start_lvgl(const char * uconfig) {
|
||||
|
@ -268,7 +269,7 @@ void start_lvgl(const char * uconfig) {
|
|||
glue = new Adafruit_LvGL_Glue();
|
||||
|
||||
// Initialize glue, passing in address of display & touchscreen
|
||||
LvGLStatus status = glue->begin(renderer);
|
||||
LvGLStatus status = glue->begin(renderer, (void*)1, false);
|
||||
if (status != LVGL_OK) {
|
||||
AddLog(LOG_LEVEL_ERROR, PSTR("Glue error %d"), status);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue