Merge pull request #11966 from gemu2015/touch_drv

Touch drv
This commit is contained in:
Theo Arends 2021-04-30 16:32:49 +02:00 committed by GitHub
commit a07abf3ee9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 703 additions and 399 deletions

View File

@ -27,11 +27,7 @@
#include <pgmspace.h>
#include "renderer.h"
#define USE_EPD_FONTS
//#define USE_ALL_EPD_FONTS
//#define USE_GFX_FONTS
#define USE_TINY_FONT
#define USE_7SEG_FONT
uint8_t wr_redir=0;
@ -43,8 +39,12 @@ uint8_t wr_redir=0;
#define OLED_FONT_HEIGTH 8
#define BLACK 0
Renderer::Renderer(int16_t x, int16_t y) :
Adafruit_GFX(x, y) {
#ifdef USE_GFX
Renderer::Renderer(int16_t x, int16_t y) : Adafruit_GFX(x, y) {
#else
Renderer::Renderer(int16_t x, int16_t y) {
#endif
font=0;
#ifdef USE_EPD_FONTS
selected_font = &Font12;
@ -628,6 +628,9 @@ LVGL_PARAMS *Renderer::lvgl_pars(void) {
return &lvgl_param;
}
#ifndef LVGL_RENDERER
void VButton::xdrawButton(bool inverted) {
wr_redir=1;
drawButton(inverted);
@ -723,7 +726,7 @@ uint16_t VButton::UpdateSlider(int16_t x, int16_t y) {
}
}
#endif // LVGL_RENDERER

View File

@ -9,8 +9,20 @@
#define WHITE 1
#define INVERSE 2
#define USE_EPD_FONTS
//#define USE_ALL_EPD_FONTS
//#define USE_GFX_FONTS
#define USE_TINY_FONT
#define USE_7SEG_FONT
#define MAX_INDEXCOLORS 32
//#define LVGL_RENDERER
#ifdef LVGL_RENDERER
#undef USE_EPD_FONTS
#endif
// depends on GFX driver
// GFX patched
// a. in class GFX setCursor,setTextSize => virtual
@ -36,7 +48,14 @@ typedef struct LVGL_PARAMS {
typedef void (*pwr_cb)(uint8_t);
typedef void (*dim_cb)(uint8_t);
#define USE_GFX
#ifdef USE_GFX
class Renderer : public Adafruit_GFX {
#else
class Renderer {
#endif
//Paint(unsigned char* image, int width, int height);
//~Renderer();
public:
@ -115,6 +134,7 @@ struct Slider {
uint16_t barcol;
};
#ifndef LVGL_RENDERER
class VButton : public Adafruit_GFX_Button {
public:
TButton_State vpower;
@ -125,6 +145,7 @@ class VButton : public Adafruit_GFX_Button {
uint16_t UpdateSlider(int16_t x, int16_t y);
void SliderInit(Renderer *rend, uint16_t xp, uint16_t yp, uint16_t xs, uint16_t ys, uint16_t nelem, uint16_t bgcol, uint16_t frcol, uint16_t barcol);
};
#endif // LVGL_RENDERER
#endif

View File

@ -530,7 +530,10 @@ void ili9342_bpwr(uint8_t on);
void ILI9341_2::DisplayOnff(int8_t on) {
if ((_hwspi >= 2) && (_bp < 0)) {
ili9342_bpwr(on);
//ili9342_bpwr(on);
if (pwr_cbp) {
pwr_cbp(on);
}
}
if (on) {
@ -604,7 +607,10 @@ void ILI9341_2::dim(uint8_t dim) {
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
} else {
if (_hwspi>=2) {
ili9342_dimm(dim);
//ili9342_dimm(dim);
if (dim_cbp) {
dim_cbp(dim);
}
}
}
#endif

View File

@ -20,7 +20,7 @@
#include <Arduino.h>
#include "uDisplay.h"
#define UDSP_DEBUG
//#define UDSP_DEBUG
const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\
UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\

View File

@ -951,14 +951,13 @@ void RA8876::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
//RA8876_CS_LOW
while (len--) {
uint16_t color=*data++;
uint16_t color = *data++;
#if 0
SPI.transfer(RA8876_DATA_WRITE);
SPI.transfer(color&0xff);
SPI.transfer(RA8876_DATA_WRITE);
SPI.transfer(color>>8);
#else
//waitWriteFifo();
@ -1467,3 +1466,128 @@ void RA8876::FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str)
setTextColor(tcolor,textbgcolor);
xwrite((uint8_t*)str,strlen(str));
}
// ESP 32 DMA section , derived from TFT_eSPI
#ifdef ESP32
/***************************************************************************************
** Function name: initDMA
** Description: Initialise the DMA engine - returns true if init OK
***************************************************************************************/
bool RA8876::initDMA()
{
if (DMA_Enabled) return false;
esp_err_t ret;
spi_bus_config_t buscfg = {
.mosi_io_num = _mosi,
.miso_io_num = _miso,
.sclk_io_num = _sclk,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = width() * height() * 2 + 8, // TFT screen size
.flags = 0,
.intr_flags = 0
};
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = SPI_MODE3,
.duty_cycle_pos = 0,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.clock_speed_hz = RA8876_SPI_SPEED,
.input_delay_ns = 0,
.spics_io_num = m_csPin,
.flags = SPI_DEVICE_NO_DUMMY, //0,
.queue_size = 1,
.pre_cb = 0, //dc_callback, //Callback to handle D/C line
.post_cb = 0
};
ret = spi_bus_initialize(spi_host, &buscfg, 1);
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL);
ESP_ERROR_CHECK(ret);
DMA_Enabled = true;
spiBusyCheck = 0;
return true;
}
/***************************************************************************************
** Function name: deInitDMA
** Description: Disconnect the DMA engine from SPI
***************************************************************************************/
void RA8876::deInitDMA(void) {
if (!DMA_Enabled) return;
spi_bus_remove_device(dmaHAL);
spi_bus_free(spi_host);
DMA_Enabled = false;
}
/***************************************************************************************
** Function name: dmaBusy
** Description: Check if DMA is busy
***************************************************************************************/
bool RA8876::dmaBusy(void) {
if (!DMA_Enabled || !spiBusyCheck) return false;
spi_transaction_t *rtrans;
esp_err_t ret;
uint8_t checks = spiBusyCheck;
for (int i = 0; i < checks; ++i) {
ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0);
if (ret == ESP_OK) spiBusyCheck--;
}
//Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
if (spiBusyCheck == 0) return false;
return true;
}
/***************************************************************************************
** Function name: dmaWait
** Description: Wait until DMA is over (blocking!)
***************************************************************************************/
void RA8876::dmaWait(void) {
if (!DMA_Enabled || !spiBusyCheck) return;
spi_transaction_t *rtrans;
esp_err_t ret;
for (int i = 0; i < spiBusyCheck; ++i) {
ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY);
assert(ret == ESP_OK);
}
spiBusyCheck = 0;
}
/***************************************************************************************
** Function name: pushPixelsDMA
** Description: Push pixels to TFT (len must be less than 32767)
***************************************************************************************/
// This will byte swap the original image if setSwapBytes(true) was called by sketch.
void RA8876::pushPixelsDMA(uint16_t* image, uint32_t len) {
if ((len == 0) || (!DMA_Enabled)) return;
dmaWait();
esp_err_t ret;
memset(&trans, 0, sizeof(spi_transaction_t));
trans.user = (void *)1;
trans.tx_buffer = image; //finally send the line data
trans.length = len * 16; //Data length, in bits
trans.flags = 0; //SPI_TRANS_USE_TXDATA flag
ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
assert(ret == ESP_OK);
spiBusyCheck++;
}
#endif // ESP32

View File

@ -22,6 +22,9 @@
#include "Arduino.h"
#include <SPI.h>
#include <renderer.h>
#ifdef ESP32
#include "driver/spi_master.h"
#endif
#undef SPRINT
#define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);}
@ -147,7 +150,7 @@ typedef uint8_t FontFlags;
// 1MHz. TODO: Figure out actual speed to use
// Data sheet section 5.2 says maximum SPI clock is 50MHz.
//#define RA8876_SPI_SPEED 10000000
#define RA8876_SPI_SPEED 20000000
#define RA8876_SPI_SPEED 25000000
// With SPI, the RA8876 expects an initial byte where the top two bits are meaningful. Bit 7
// is A0, bit 6 is WR#. See data sheet section 7.3.2 and section 19.
@ -565,6 +568,21 @@ class RA8876 : public Renderer {
enum FontSource m_fontSource;
enum FontSize m_fontSize;
FontFlags m_fontFlags;
#ifdef ESP32
// dma section
bool DMA_Enabled = false;
uint8_t spiBusyCheck = 0;
spi_transaction_t trans;
spi_device_handle_t dmaHAL;
spi_host_device_t spi_host = VSPI_HOST;
// spi_host_device_t spi_host = VSPI_HOST;
bool initDMA();
void deInitDMA(void);
bool dmaBusy(void);
void dmaWait(void);
void pushPixelsDMA(uint16_t* image, uint32_t len);
#endif // ESP32
};
#endif

View File

@ -2668,7 +2668,8 @@ chknext:
#ifdef USE_LVGL
if (!strncmp(vname, "lvgl(", 5)) {
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv);
fvar = lvgl_test(fvar);
SCRIPT_SKIP_SPACES
fvar = lvgl_test(&lp, fvar);
lp++;
len = 0;
goto exit;
@ -7870,82 +7871,192 @@ uint32_t script_i2c(uint8_t sel, uint8_t val, uint8_t val1) {
#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";
#define MAX_LVGL_OBJS 8
uint8_t lvgl_numobjs;
lv_obj_t *lvgl_buttons[MAX_LVGL_OBJS];
void start_lvgl(const char * uconfig);
lv_event_t lvgl_last_event;
uint8_t lvgl_last_object;
uint8_t lvgl_last_slider;
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"));
void lvgl_set_last(lv_obj_t * obj, lv_event_t event);
void lvgl_set_last(lv_obj_t * obj, lv_event_t event) {
lvgl_last_event = event;
lvgl_last_object = 0;
for (uint8_t cnt = 0; cnt < MAX_LVGL_OBJS; cnt++) {
if (lvgl_buttons[cnt] == obj) {
lvgl_last_object = cnt + 1;
return;
}
}
}
int32_t lvgl_test(int32_t p) {
start_lvgl(ili9342);
lv_obj_clean(lv_scr_act());
if (p == 0) {
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);
/*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");
} else {
lvgl_setup();
void btn_event_cb(lv_obj_t * btn, lv_event_t event);
void btn_event_cb(lv_obj_t * btn, lv_event_t event) {
lvgl_set_last(btn, event);
if (event == LV_EVENT_CLICKED) {
Run_Scripter(">lvb", 4, 0);
}
return 0;
}
void slider_event_cb(lv_obj_t * sld, lv_event_t event);
void slider_event_cb(lv_obj_t * sld, lv_event_t event) {
lvgl_set_last(sld, event);
lvgl_last_slider = lv_slider_get_value(sld);
if (event == LV_EVENT_VALUE_CHANGED) {
Run_Scripter(">lvs", 4, 0);
}
}
void lvgl_StoreObj(lv_obj_t *obj);
void lvgl_StoreObj(lv_obj_t *obj) {
if (lvgl_numobjs < MAX_LVGL_OBJS) {
lvgl_buttons[lvgl_numobjs] = obj;
lvgl_numobjs++;
}
}
int32_t lvgl_test(char **lpp, int32_t p) {
char *lp = *lpp;
lv_obj_t *obj;
lv_obj_t *label;
float xp, yp, xs, ys, min, max;
char str[SCRIPT_MAXSSIZE];
int32_t res = 0;
switch (p) {
case 0:
start_lvgl(0);
lvgl_numobjs = 0;
for (uint8_t cnt = 0; cnt < MAX_LVGL_OBJS; cnt++) {
lvgl_buttons[cnt] = 0;
}
break;
case 1:
lv_obj_clean(lv_scr_act());
break;
case 2:
// create button;
lp = GetNumericArgument(lp, OPER_EQU, &xp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &yp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &xs, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &ys, 0);
SCRIPT_SKIP_SPACES
lp = GetStringArgument(lp, OPER_EQU, str, 0);
SCRIPT_SKIP_SPACES
obj = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_pos(obj, xp, yp);
lv_obj_set_size(obj, xs, ys);
lv_obj_set_event_cb(obj, btn_event_cb);
label = lv_label_create(obj, NULL);
lv_label_set_text(label, str);
lvgl_StoreObj(obj);
break;
case 3:
lp = GetNumericArgument(lp, OPER_EQU, &xp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &yp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &xs, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &ys, 0);
SCRIPT_SKIP_SPACES
obj = lv_slider_create(lv_scr_act(), NULL);
lv_obj_set_pos(obj, xp, yp);
lv_obj_set_size(obj, xs, ys);
lv_obj_set_event_cb(obj, slider_event_cb);
lvgl_StoreObj(obj);
break;
case 4:
lp = GetNumericArgument(lp, OPER_EQU, &xp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &yp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &xs, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &ys, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &min, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &max, 0);
SCRIPT_SKIP_SPACES
obj = lv_gauge_create(lv_scr_act(), NULL);
lv_obj_set_pos(obj, xp, yp);
lv_obj_set_size(obj, xs, ys);
lv_gauge_set_range(obj, min, max);
lvgl_StoreObj(obj);
break;
case 5:
lp = GetNumericArgument(lp, OPER_EQU, &min, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &max, 0);
SCRIPT_SKIP_SPACES
if (lvgl_buttons[(uint8_t)min - 1]) {
lv_gauge_set_value(lvgl_buttons[(uint8_t)min - 1], 0, max);
}
break;
case 6:
// create label;
lp = GetNumericArgument(lp, OPER_EQU, &xp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &yp, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &xs, 0);
SCRIPT_SKIP_SPACES
lp = GetNumericArgument(lp, OPER_EQU, &ys, 0);
SCRIPT_SKIP_SPACES
lp = GetStringArgument(lp, OPER_EQU, str, 0);
SCRIPT_SKIP_SPACES
obj = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_pos(obj, xp, yp);
lv_obj_set_size(obj, xs, ys);
lv_label_set_text(obj, str);
lvgl_StoreObj(obj);
break;
case 7:
lp = GetNumericArgument(lp, OPER_EQU, &min, 0);
SCRIPT_SKIP_SPACES
lp = GetStringArgument(lp, OPER_EQU, str, 0);
SCRIPT_SKIP_SPACES
if (lvgl_buttons[(uint8_t)min - 1]) {
lv_label_set_text(lvgl_buttons[(uint8_t)min - 1], str);
}
break;
case 50:
res = lvgl_last_object;
break;
case 51:
res = lvgl_last_event;
break;
case 52:
res = lvgl_last_slider;
break;
default:
lvgl_setup();
break;
}
*lpp = lp;
return res;
}
lv_obj_t *tabview, // LittlevGL tabview object

View File

@ -27,19 +27,12 @@ Renderer *renderer;
enum ColorType { COLOR_BW, COLOR_COLOR };
#ifndef MAX_TOUCH_BUTTONS
#define MAX_TOUCH_BUTTONS 16
#endif
#ifdef USE_UFILESYS
extern FS *ufsp;
extern FS *ffsp;
#endif
#ifdef USE_TOUCH_BUTTONS
VButton *buttons[MAX_TOUCH_BUTTONS];
#endif
// drawing color is WHITE
// on epaper the whole display buffer is transfered inverted this results in white paper
uint16_t fg_color = 1;
@ -2673,277 +2666,6 @@ void AddValue(uint8_t num,float fval) {
}
#endif // USE_GRAPH
/*********************************************************************************************\
* Touch panel control
\*********************************************************************************************/
bool FT5206_found = false;
bool XPT2046_found = false;
int16_t touch_xp;
int16_t touch_yp;
bool touched;
uint32_t Touch_Status(uint32_t sel) {
if (FT5206_found || XPT2046_found) {
switch (sel) {
case 0:
return touched;
case 1:
return touch_xp;
case 2:
return touch_yp;
}
return 0;
} else {
return 0;
}
}
#if defined(USE_FT5206) || defined(USE_XPT2046)
#ifdef USE_M5STACK_CORE2
uint8_t tbstate[3];
#endif // USE_M5STACK_CORE2
#ifdef USE_FT5206
#include <FT5206.h>
// touch panel controller
#undef FT5206_address
#define FT5206_address 0x38
FT5206_Class *FT5206_touchp;
bool FT5206_Touch_Init(TwoWire &i2c) {
FT5206_found = false;
FT5206_touchp = new FT5206_Class();
if (FT5206_touchp->begin(i2c, FT5206_address)) {
I2cSetActiveFound(FT5206_address, "FT5206");
FT5206_found = true;
}
return FT5206_found;
}
bool FT5206_touched() {
return FT5206_touchp->touched();
}
int16_t FT5206_x() {
TP_Point pLoc = FT5206_touchp->getPoint(0);
return pLoc.x;
}
int16_t FT5206_y() {
TP_Point pLoc = FT5206_touchp->getPoint(0);
return pLoc.y;
}
#endif // USE_FT5206
#ifdef USE_XPT2046
#include <XPT2046_Touchscreen.h>
XPT2046_Touchscreen *XPT2046_touchp;
bool XPT2046_Touch_Init(uint16_t CS) {
XPT2046_touchp = new XPT2046_Touchscreen(CS);
XPT2046_found = XPT2046_touchp->begin();
if (XPT2046_found) {
AddLog(LOG_LEVEL_INFO, PSTR("TS: XPT2046"));
}
return XPT2046_found;
}
bool XPT2046_touched() {
return XPT2046_touchp->touched();
}
int16_t XPT2046_x() {
TS_Point pLoc = XPT2046_touchp->getPoint();
return pLoc.x;
}
int16_t XPT2046_y() {
TS_Point pLoc = XPT2046_touchp->getPoint();
return pLoc.y;
}
#endif // USE_XPT2046
void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
#ifdef USE_FT5206
if (FT5206_found) {
touch_xp = FT5206_x();
touch_yp = FT5206_y();
touched = FT5206_touched();
}
#endif // USE_FT5206
#ifdef USE_XPT2046
if (XPT2046_found) {
touch_xp = XPT2046_x();
touch_yp = XPT2046_y();
touched = XPT2046_touched();
}
#endif // USE_XPT2046
if (touched) {
#ifdef USE_TOUCH_BUTTONS
#ifdef USE_M5STACK_CORE2
// handle 3 built in touch buttons
uint16_t xcenter = 80;
#define TDELTA 30
#define TYPOS 275
for (uint32_t tbut = 0; tbut < 3; tbut++) {
if (touch_xp > (xcenter - TDELTA) && touch_xp < (xcenter + TDELTA) && touch_yp > (TYPOS - TDELTA) && touch_yp < (TYPOS + TDELTA)) {
// hit a button
if (!(tbstate[tbut] & 1)) {
// pressed
tbstate[tbut] |= 1;
//AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut);
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
}
}
xcenter += 100;
}
#endif // USE_M5STACK_CORE2
#endif // USE_TOUCH_BUTTONS
rotconvert(&touch_xp, &touch_yp);
#ifdef USE_TOUCH_BUTTONS
CheckTouchButtons(touched, touch_xp, touch_yp);
#endif // USE_TOUCH_BUTTONS
} else {
#ifdef USE_M5STACK_CORE2
for (uint32_t tbut = 0; tbut < 3; tbut++) {
if (tbstate[tbut] & 1) {
// released
tbstate[tbut] &= 0xfe;
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
//AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut);
}
}
#endif // USE_M5STACK_CORE2
#ifdef USE_TOUCH_BUTTONS
CheckTouchButtons(touched, touch_xp, touch_yp);
#endif // USE_TOUCH_BUTTONS
}
}
#endif
#ifdef USE_TOUCH_BUTTONS
void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
#ifdef USE_FT5206
if (FT5206_found) ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
#endif
#ifdef USE_XPT2046
if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
#endif // USE_XPT2046
MqttPublishTeleSensor();
}
void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) {
buttons[count]->xdrawButton(pwr);
if (pwr) buttons[count]->vpower.on_off = 1;
else buttons[count]->vpower.on_off = 0;
}
void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
uint16_t temp;
uint8_t rbutt=0;
uint8_t vbutt=0;
if (!renderer) return;
if (touched) {
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), pLoc.x, pLoc.y);
// now must compare with defined buttons
for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) {
if (buttons[count]) {
if (!buttons[count]->vpower.slider) {
if (!buttons[count]->vpower.disable) {
if (buttons[count]->contains(touch_x, touch_y)) {
// did hit
buttons[count]->press(true);
if (buttons[count]->justPressed()) {
if (!buttons[count]->vpower.is_virtual) {
uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt);
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
Touch_RDW_BUTT(count, !pwr);
}
} else {
// virtual button
const char *cp;
if (!buttons[count]->vpower.is_pushbutton) {
// toggle button
buttons[count]->vpower.on_off ^= 1;
cp="TBT";
} else {
// push button
buttons[count]->vpower.on_off = 1;
cp="PBT";
}
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
Touch_MQTT(count, cp, buttons[count]->vpower.on_off);
}
}
}
if (!buttons[count]->vpower.is_virtual) {
rbutt++;
} else {
vbutt++;
}
}
} else {
// slider
if (buttons[count]->didhit(touch_x, touch_y)) {
uint16_t value = buttons[count]->UpdateSlider(touch_x, touch_y);
Touch_MQTT(count, "SLD", value);
}
}
}
}
} else {
// no hit
for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) {
if (buttons[count]) {
if (!buttons[count]->vpower.slider) {
buttons[count]->press(false);
if (buttons[count]->justReleased()) {
if (buttons[count]->vpower.is_virtual) {
if (buttons[count]->vpower.is_pushbutton) {
// push button
buttons[count]->vpower.on_off = 0;
Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off);
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
}
}
}
if (!buttons[count]->vpower.is_virtual) {
// check if power button stage changed
uint8_t pwr = bitRead(TasmotaGlobal.power, rbutt);
uint8_t vpwr = buttons[count]->vpower.on_off;
if (pwr != vpwr) {
Touch_RDW_BUTT(count, pwr);
}
rbutt++;
}
}
}
}
touch_xp = 0;
touch_yp = 0;
}
}
#endif // USE_TOUCH_BUTTONS
/*********************************************************************************************\
* Interface
\*********************************************************************************************/

314
tasmota/xdrv_55_touch.ino Normal file
View File

@ -0,0 +1,314 @@
/*
xdrv_55_touch.ino - Touch contolers
Copyright (C) 2021 Gerhard Mutz and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47)
#ifdef LVGL_RENDERER
#undef USE_TOUCH_BUTTONS
#endif
#include <renderer.h>
#define XDRV_55 55
bool FT5206_found = false;
bool XPT2046_found = false;
int16_t touch_xp;
int16_t touch_yp;
bool touched;
#ifndef MAX_TOUCH_BUTTONS
#define MAX_TOUCH_BUTTONS 16
#endif
#ifdef USE_TOUCH_BUTTONS
VButton *buttons[MAX_TOUCH_BUTTONS];
#endif
uint32_t Touch_Status(uint32_t sel) {
if (FT5206_found || XPT2046_found) {
switch (sel) {
case 0:
return touched;
case 1:
return touch_xp;
case 2:
return touch_yp;
}
return 0;
} else {
return 0;
}
}
#ifdef USE_M5STACK_CORE2
uint8_t tbstate[3];
#endif // USE_M5STACK_CORE2
#ifdef USE_FT5206
#include <FT5206.h>
// touch panel controller
#undef FT5206_address
#define FT5206_address 0x38
FT5206_Class *FT5206_touchp;
bool FT5206_Touch_Init(TwoWire &i2c) {
FT5206_found = false;
FT5206_touchp = new FT5206_Class();
if (FT5206_touchp->begin(i2c, FT5206_address)) {
I2cSetActiveFound(FT5206_address, "FT5206");
FT5206_found = true;
}
//AddLog(LOG_LEVEL_INFO, PSTR("TS: FT5206 %d"),FT5206_found);
return FT5206_found;
}
bool FT5206_touched() {
return FT5206_touchp->touched();
}
int16_t FT5206_x() {
TP_Point pLoc = FT5206_touchp->getPoint(0);
return pLoc.x;
}
int16_t FT5206_y() {
TP_Point pLoc = FT5206_touchp->getPoint(0);
return pLoc.y;
}
#endif // USE_FT5206
#ifdef USE_XPT2046
#include <XPT2046_Touchscreen.h>
XPT2046_Touchscreen *XPT2046_touchp;
bool XPT2046_Touch_Init(uint16_t CS) {
XPT2046_touchp = new XPT2046_Touchscreen(CS);
XPT2046_found = XPT2046_touchp->begin();
if (XPT2046_found) {
AddLog(LOG_LEVEL_INFO, PSTR("TS: XPT2046"));
}
return XPT2046_found;
}
bool XPT2046_touched() {
return XPT2046_touchp->touched();
}
int16_t XPT2046_x() {
TS_Point pLoc = XPT2046_touchp->getPoint();
return pLoc.x;
}
int16_t XPT2046_y() {
TS_Point pLoc = XPT2046_touchp->getPoint();
return pLoc.y;
}
#endif // USE_XPT2046
void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
#ifdef USE_FT5206
if (FT5206_found) {
touch_xp = FT5206_x();
touch_yp = FT5206_y();
touched = FT5206_touched();
}
#endif // USE_FT5206
#ifdef USE_XPT2046
if (XPT2046_found) {
touch_xp = XPT2046_x();
touch_yp = XPT2046_y();
touched = XPT2046_touched();
}
#endif // USE_XPT2046
if (touched) {
#ifdef USE_TOUCH_BUTTONS
#ifdef USE_M5STACK_CORE2
// handle 3 built in touch buttons
uint16_t xcenter = 80;
#define TDELTA 30
#define TYPOS 275
for (uint32_t tbut = 0; tbut < 3; tbut++) {
if (touch_xp > (xcenter - TDELTA) && touch_xp < (xcenter + TDELTA) && touch_yp > (TYPOS - TDELTA) && touch_yp < (TYPOS + TDELTA)) {
// hit a button
if (!(tbstate[tbut] & 1)) {
// pressed
tbstate[tbut] |= 1;
//AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut);
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
}
}
xcenter += 100;
}
#endif // USE_M5STACK_CORE2
#endif // USE_TOUCH_BUTTONS
rotconvert(&touch_xp, &touch_yp);
#ifdef USE_TOUCH_BUTTONS
CheckTouchButtons(touched, touch_xp, touch_yp);
#endif // USE_TOUCH_BUTTONS
} else {
#ifdef USE_M5STACK_CORE2
for (uint32_t tbut = 0; tbut < 3; tbut++) {
if (tbstate[tbut] & 1) {
// released
tbstate[tbut] &= 0xfe;
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
//AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut);
}
}
#endif // USE_M5STACK_CORE2
#ifdef USE_TOUCH_BUTTONS
CheckTouchButtons(touched, touch_xp, touch_yp);
#endif // USE_TOUCH_BUTTONS
}
}
#ifdef USE_TOUCH_BUTTONS
void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
#ifdef USE_FT5206
if (FT5206_found) ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
#endif
#ifdef USE_XPT2046
if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
#endif // USE_XPT2046
MqttPublishTeleSensor();
}
void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) {
buttons[count]->xdrawButton(pwr);
if (pwr) buttons[count]->vpower.on_off = 1;
else buttons[count]->vpower.on_off = 0;
}
void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
uint16_t temp;
uint8_t rbutt=0;
uint8_t vbutt=0;
if (!renderer) return;
if (touched) {
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), pLoc.x, pLoc.y);
// now must compare with defined buttons
for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) {
if (buttons[count]) {
if (!buttons[count]->vpower.slider) {
if (!buttons[count]->vpower.disable) {
if (buttons[count]->contains(touch_x, touch_y)) {
// did hit
buttons[count]->press(true);
if (buttons[count]->justPressed()) {
if (!buttons[count]->vpower.is_virtual) {
uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt);
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
Touch_RDW_BUTT(count, !pwr);
}
} else {
// virtual button
const char *cp;
if (!buttons[count]->vpower.is_pushbutton) {
// toggle button
buttons[count]->vpower.on_off ^= 1;
cp="TBT";
} else {
// push button
buttons[count]->vpower.on_off = 1;
cp="PBT";
}
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
Touch_MQTT(count, cp, buttons[count]->vpower.on_off);
}
}
}
if (!buttons[count]->vpower.is_virtual) {
rbutt++;
} else {
vbutt++;
}
}
} else {
// slider
if (buttons[count]->didhit(touch_x, touch_y)) {
uint16_t value = buttons[count]->UpdateSlider(touch_x, touch_y);
Touch_MQTT(count, "SLD", value);
}
}
}
}
} else {
// no hit
for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) {
if (buttons[count]) {
if (!buttons[count]->vpower.slider) {
buttons[count]->press(false);
if (buttons[count]->justReleased()) {
if (buttons[count]->vpower.is_virtual) {
if (buttons[count]->vpower.is_pushbutton) {
// push button
buttons[count]->vpower.on_off = 0;
Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off);
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
}
}
}
if (!buttons[count]->vpower.is_virtual) {
// check if power button stage changed
uint8_t pwr = bitRead(TasmotaGlobal.power, rbutt);
uint8_t vpwr = buttons[count]->vpower.on_off;
if (pwr != vpwr) {
Touch_RDW_BUTT(count, pwr);
}
rbutt++;
}
}
}
}
touch_xp = 0;
touch_yp = 0;
}
}
#endif // USE_TOUCH_BUTTONS
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv55(uint8_t function) {
bool result = false;
switch (function) {
case FUNC_INIT:
break;
case FUNC_EVERY_100_MSECOND:
break;
}
return result;
}
#endif // USE_TOUCH

23
tasmota/xdsp_04_ili9341.ino Normal file → Executable file
View File

@ -40,6 +40,8 @@ uint8_t ili9342_ctouch_counter = 0;
bool tft_init_done = false;
void Core2DisplayPower(uint8_t on);
void Core2DisplayDim(uint8_t dim);
//Settings.display_options.type = ILIMODE_9341;
@ -89,6 +91,11 @@ void ILI9341_InitDriver()
ili9341_2->init(Settings.display_width, Settings.display_height);
renderer = ili9341_2;
#ifdef USE_M5STACK_CORE2
renderer->SetPwrCB(Core2DisplayPower);
renderer->SetDimCB(Core2DisplayDim);
#endif
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->dim(Settings.display_dimmer);
@ -131,22 +138,6 @@ void ILI9341_InitDriver()
}
}
void Core2DisplayPower(uint8_t on);
void Core2DisplayDim(uint8_t dim);
void ili9342_bpwr(uint8_t on) {
#ifdef USE_M5STACK_CORE2
Core2DisplayPower(on);
#endif
}
void ili9342_dimm(uint8_t dim) {
#ifdef USE_M5STACK_CORE2
Core2DisplayDim(dim);
#endif
}
#if defined(USE_FT5206) || defined(USE_XPT2046)
#ifdef USE_TOUCH_BUTTONS

View File

@ -18,7 +18,7 @@
*/
#ifdef USE_DISPLAY
#if defined(USE_DISPLAY) || defined(LVGL_RENDERER)
#ifdef USE_UNIVERSAL_DISPLAY
#define XDSP_17 17
@ -27,14 +27,23 @@
bool udisp_init_done = false;
uint8_t ctouch_counter;
extern uint8_t color_type;
extern uint16_t fg_color;
extern uint16_t bg_color;
#ifdef USE_UFILESYS
extern FS *ffsp;
#endif
#ifndef USE_DISPLAY
uint8_t color_type;
uint16_t fg_color;
uint16_t bg_color;
Renderer *renderer;
#else
extern uint8_t color_type;
extern uint16_t fg_color;
extern uint16_t bg_color;
#endif
#define DISPDESC_SIZE 1000
@ -340,22 +349,6 @@ uDisplay *udisp;
/*********************************************************************************************/
/*
void udisp_bpwr(uint8_t on) {
#ifdef USE_M5STACK_CORE2
Core2DisplayPower(on);
#endif
}
void udisp_dimm(uint8_t dim) {
#ifdef USE_M5STACK_CORE2
Core2DisplayDim(dim);
#endif
}
*/
void TS_RotConvert(int16_t *x, int16_t *y) {
if (renderer) renderer->TS_RotConvert(x, y);
}
@ -462,8 +455,8 @@ void UDISP_Refresh(void) // Every second
* Interface
\*********************************************************************************************/
bool Xdsp17(uint8_t function)
{
#ifndef LVGL_RENDERER
bool Xdsp17(uint8_t function) {
bool result = false;
if (FUNC_DISPLAY_INIT_DRIVER == function) {
@ -493,6 +486,7 @@ bool Xdsp17(uint8_t function)
}
return result;
}
#endif // !LVGL_RENDERER
#endif // USE_UNIVERSAL_DISPLAY
#endif // USE_DISPLAY