mirror of https://github.com/arendst/Tasmota.git
LilyGo TWtach prep (#14800)
* LilyGo TWtach prep * Fix compilation * Add USE_LVGL_TOUCHSCREEN * fix
This commit is contained in:
parent
cddbb47930
commit
7df607f471
|
@ -747,6 +747,7 @@ extern const bcstring be_const_str_tomap;
|
|||
extern const bcstring be_const_str_top;
|
||||
extern const bcstring be_const_str_toptr;
|
||||
extern const bcstring be_const_str_tostring;
|
||||
extern const bcstring be_const_str_touch_update;
|
||||
extern const bcstring be_const_str_toupper;
|
||||
extern const bcstring be_const_str_tr;
|
||||
extern const bcstring be_const_str_traceback;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,14 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libdisplay_map) {
|
||||
{ be_const_key(touch_update, -1), be_const_ctype_func(be_ntv_display_touch_update) },
|
||||
{ be_const_key(dimmer, -1), be_const_func(be_ntv_display_dimmer) },
|
||||
{ be_const_key(start, 0), be_const_func(be_ntv_display_start) },
|
||||
{ be_const_key(start, -1), be_const_func(be_ntv_display_start) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libdisplay_map,
|
||||
2
|
||||
3
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
|
|
|
@ -6,16 +6,20 @@
|
|||
* Initialize Universal Display driver
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
|
||||
extern int be_ntv_display_start(bvm *vm);
|
||||
extern int be_ntv_display_dimmer(bvm *vm);
|
||||
extern void be_ntv_display_touch_update(int32_t touches, int32_t raw_x, int32_t raw_y, int32_t gesture);
|
||||
BE_FUNC_CTYPE_DECLARE(be_ntv_display_touch_update, "", "iiii[ii]")
|
||||
|
||||
/* @const_object_info_begin
|
||||
module display (scope: global) {
|
||||
start, func(be_ntv_display_start)
|
||||
dimmer, func(be_ntv_display_dimmer)
|
||||
touch_update, ctype_func(be_ntv_display_touch_update)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_display.h"
|
|
@ -0,0 +1,190 @@
|
|||
#-------------------------------------------------------------
|
||||
- Generic driver for AXP202 - solidified
|
||||
-------------------------------------------------------------#
|
||||
class AXP202 : I2C_Driver
|
||||
def init()
|
||||
super(self, I2C_Driver).init("AXP202", 0x35)
|
||||
end
|
||||
|
||||
# Return True = Battery Exist
|
||||
def battery_present()
|
||||
if self.wire.read(self.addr, 0x01, 1) & 0x20 return true
|
||||
else return false
|
||||
end
|
||||
end
|
||||
|
||||
# Input Power Status ???
|
||||
def get_input_power_status()
|
||||
return self.wire.read(self.addr, 0x00, 1)
|
||||
end
|
||||
|
||||
# Battery Charging Status
|
||||
def get_battery_chargin_status()
|
||||
return self.wire.read(self.addr, 0x01, 1)
|
||||
end
|
||||
|
||||
# AXP chip temperature in °C
|
||||
def get_temp()
|
||||
return self.read12(0x5E) * 0.1 - 144.7
|
||||
end
|
||||
|
||||
def get_bat_power()
|
||||
return self.read24(0x70) * 0.00055
|
||||
end
|
||||
|
||||
def get_bat_voltage()
|
||||
return self.read12(0x78) * 0.0011
|
||||
end
|
||||
def get_bat_current()
|
||||
return (self.read13(0x7A) - self.read13(0x7C)) * 0.5
|
||||
end
|
||||
def get_bat_charge_current()
|
||||
return self.read13(0x7A) * 0.5
|
||||
end
|
||||
def get_aps_voltage()
|
||||
return self.read12(0x7E) * 0.0014
|
||||
end
|
||||
def get_vbus_voltage()
|
||||
return self.read12(0x5A) * 0.0017
|
||||
end
|
||||
def get_vbus_current()
|
||||
return self.read12(0x5C) * 0.375
|
||||
end
|
||||
|
||||
# set LDO voltage
|
||||
# ldo: 2/3/4
|
||||
# voltage: (mV) 1800mV - 3300mV in 100mV steps
|
||||
def set_ldo_voltage(ldo, voltage)
|
||||
if voltage > 3300 voltage = 15 end
|
||||
|
||||
if ldo == 2 || ldo == 4
|
||||
voltage = (voltage / 100) - 18
|
||||
if ldo == 2
|
||||
self.write8(0x28, self.read8(0x28) & 0x0F | ((voltage & 0x0F) << 4))
|
||||
else
|
||||
self.write8(0x28, self.read8(0x28) & 0xF0 | (voltage & 0x0F))
|
||||
end
|
||||
else
|
||||
# ldo 3, range is 0v7~3v3
|
||||
voltage = (voltage / 25) - 28
|
||||
self.write8(0x28, self.read8(0x29) & 0x80 | (voltage & 0x7F))
|
||||
end
|
||||
end
|
||||
|
||||
# set EXTEN which enables external power on M5Stack, powering Hat with 5V
|
||||
def set_exten(state)
|
||||
self.write_bit(0x12, 0, state)
|
||||
end
|
||||
|
||||
# VBUS current-limit selection set to not limit
|
||||
def set_limiting_off()
|
||||
self.write8(0x30, self.read8(0x30) | 0x03)
|
||||
end
|
||||
|
||||
# set DCDC enable, 2/3
|
||||
def set_dcdc_enable(dcdc, state)
|
||||
# if dcdc == 1 self.write_bit(0x12, 0, state) end # no dcdc1 on AXP202
|
||||
if dcdc == 2 self.write_bit(0x12, 4, state) end
|
||||
if dcdc == 3 self.write_bit(0x12, 1, state) end
|
||||
end
|
||||
|
||||
# set LDO enable, 2/3/4 (LDO 1 is always on)
|
||||
def set_ldo_enable(ldo, state)
|
||||
if ldo == 2 self.write_bit(0x12, 2, state) end
|
||||
if ldo == 3 self.write_bit(0x12, 6, state) end
|
||||
if ldo == 4 self.write_bit(0x12, 3, state) end
|
||||
end
|
||||
|
||||
# # set GPIO output state 0/1/2 and 3/4
|
||||
# def write_gpio(gpio, state)
|
||||
# if gpio >= 0 && gpio <= 2
|
||||
# self.write_bit(0x94, gpio, state)
|
||||
# elif gpio >= 3 && gpio <= 4
|
||||
# self.write_bit(0x96, gpio - 3, state)
|
||||
# end
|
||||
# end
|
||||
|
||||
# Set voltage on DC-DC 2/3
|
||||
# dcdc: 2/3 (warning some C libs start at 0)
|
||||
# voltage:
|
||||
def set_dc_voltage(dcdc, voltage)
|
||||
if dcdc < 2 || dcdc > 3 return end
|
||||
var v
|
||||
if voltage < 700 v = 0
|
||||
elif voltage > 3500 v = 112
|
||||
elif dcdc == 2 && voltage > 2275 v = 63 # dcdc2 is limited to 2.275V
|
||||
else v = (voltage - 700) / 25
|
||||
end
|
||||
|
||||
var addr = 0x23
|
||||
if dcdc == 3 addr = 0x27
|
||||
# elif dcdc == 2 addr = 0x23
|
||||
end
|
||||
|
||||
self.write8(addr, self.read8(addr) & 0x80 | (v & 0x7F))
|
||||
end
|
||||
|
||||
# Set charging current
|
||||
# current = 300+(val)*100 mA, range 300-1800
|
||||
def set_chg_current_ma(ma)
|
||||
var current_code = (ma - 300) / 100
|
||||
self.write8(0x33, self.read8(0x33) & 0xF0 | (current_code & 0x0F))
|
||||
end
|
||||
|
||||
# set shutdown time, possible values: 4, 6, 8, 10
|
||||
def set_shutdown_time(st)
|
||||
var val = 0 # 4s
|
||||
if st == 6 val = 1 end
|
||||
if st == 8 val = 2 end
|
||||
if st == 10 val = 3 end
|
||||
self.write8(0x36, self.read8(0x36) & 0xFC | (val & 0x03))
|
||||
end
|
||||
|
||||
# change charging led mode
|
||||
# 0=off, 1=blink_1Hz, 2=blink_4Hz, 3=low_level
|
||||
def set_chg_led_mode(mode)
|
||||
var val = self.read8(0x32)
|
||||
val = (val & 0xCF) | 0x08
|
||||
val = val | ((mode & 0x03) << 4)
|
||||
self.write8(0x32, val)
|
||||
end
|
||||
|
||||
# # // Low Volt Level 1, when APS Volt Output < 3.4496 V
|
||||
# # // Low Volt Level 2, when APS Volt Output < 3.3992 V, then this flag is SET (0x01)
|
||||
# # // Flag will reset once battery volt is charged above Low Volt Level 1
|
||||
# # // Note: now AXP192 have the Shutdown Voltage of 3.0V (B100) Def in REG 31H
|
||||
# def get_warning_level()
|
||||
# return self.read12(0x47) & 1
|
||||
# end
|
||||
|
||||
# #- display sensor value in the web UI -#
|
||||
# def web_sensor()
|
||||
# if !self.wire return nil end #- exit if not initialized -#
|
||||
# import string
|
||||
# var msg = string.format(
|
||||
# "{s}VBus Voltage{m}%.3f V{e}"..
|
||||
# "{s}VBus Current{m}%.1f mA{e}"..
|
||||
# "{s}Batt Voltage{m}%.3f V{e}"..
|
||||
# "{s}Batt Current{m}%.1f mA{e}"..
|
||||
# #"{s}Batt Power{m}%.3f{e}"..
|
||||
# "{s}Temp AXP{m}%.1f °C{e}",
|
||||
# self.get_vbus_voltage(), self.get_vbus_voltage(),
|
||||
# self.get_bat_voltage(), self.get_bat_current(),
|
||||
# #self.get_bat_power(),
|
||||
# self.get_temp()
|
||||
# )
|
||||
# tasmota.web_send_decimal(msg)
|
||||
# end
|
||||
|
||||
# #- add sensor value to teleperiod -#
|
||||
# def json_append()
|
||||
# if !self.wire return nil end #- exit if not initialized -#
|
||||
# # import string
|
||||
# # var ax = int(self.accel[0] * 1000)
|
||||
# # var ay = int(self.accel[1] * 1000)
|
||||
# # var az = int(self.accel[2] * 1000)
|
||||
# # var msg = string.format(",\"MPU6886\":{\"AX\":%i,\"AY\":%i,\"AZ\":%i,\"GX\":%i,\"GY\":%i,\"GZ\":%i}",
|
||||
# # ax, ay, az, self.gyro[0], self.gyro[1], self.gyro[2])
|
||||
# # tasmota.response_append(msg)
|
||||
# end
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
#-------------------------------------------------------------
|
||||
- Driver for FT3663 - Capacitive Touch Screen
|
||||
-------------------------------------------------------------#
|
||||
class FT3663 : I2C_Driver
|
||||
static gest_id_codes = {
|
||||
0x00: 0x00,
|
||||
0x10: 0x10, # Move Up
|
||||
0x14: 0x13, # Move Right
|
||||
0x18: 0x11, # Move Down
|
||||
0x1C: 0x12, # Move Left
|
||||
0x48: 0x20, # Zoom In
|
||||
0x49: 0x21, # Zoom Out
|
||||
# 0x10 Move Up
|
||||
# 0x14 Move Right
|
||||
# 0x18 Move Down
|
||||
# 0x1C Move Left
|
||||
# 0x48 Zoom In
|
||||
# 0x49 Zoom Out
|
||||
# 0x00 No Gesture
|
||||
#
|
||||
# TS_Gest_None = 0,
|
||||
# TS_Gest_Move_Up = 0x10,
|
||||
# TS_Gest_Move_Down = 0x11,
|
||||
# TS_Gest_Move_Left = 0x12,
|
||||
# TS_Gest_Move_Right = 0x13,
|
||||
# TS_Gest_Zoom_In = 0x20,
|
||||
# TS_Gest_Zoom_Out = 0x21,
|
||||
}
|
||||
def init()
|
||||
super(self).init("FT3663", 0x38)
|
||||
# check that ID from register 0xA8 is 0x11
|
||||
var vendid = self.read8(0xA8)
|
||||
var chipid = self.read8(0xA3)
|
||||
if vendid != 0x11 || chipid != 0x64
|
||||
tasmota.log("I2C: ignoring address 0x38, not FT3663", 2)
|
||||
self.wire = nil
|
||||
return
|
||||
end
|
||||
|
||||
# FT3663 is now confirmed
|
||||
tasmota.log("TS : FT3663 Touch Screen detected")
|
||||
|
||||
self.write8(0x00, 0x00) # writeRegister8(FT6X36_REG_DEVICE_MODE, 0x00);
|
||||
self.write8(0x80, 22) # writeRegister8(FT6X36_REG_THRESHHOLD, FT6X36_DEFAULT_THRESHOLD);
|
||||
self.write8(0x88, 0x0E) # writeRegister8(FT6X36_REG_TOUCHRATE_ACTIVE, 0x0E);
|
||||
|
||||
# register ourself
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
|
||||
# read touch screen and publish result
|
||||
def ts_loop()
|
||||
if !self.wire return end
|
||||
import display
|
||||
|
||||
var data = self.wire.read_bytes(self.addr, 0, 15)
|
||||
# ex: data = bytes('0000018098009B0000FFFFFFFFFFFF')
|
||||
|
||||
var touches = data[0x02] & 0x0F # number of touches
|
||||
var x1 = (data[0x03] & 0x0F) << 8 | data[0x04]
|
||||
var y1 = (data[0x05] & 0x0F) << 8 | data[0x06]
|
||||
var pressure1 = data[0x07]
|
||||
var x2 = (data[0x03] & 0x09) << 8 | data[0x0A]
|
||||
var y2 = (data[0x05] & 0x0B) << 8 | data[0x0C]
|
||||
var pressure2 = data[0x0D]
|
||||
var gesture = self.gest_id_codes.find(data[0x01], 0x00)
|
||||
#define FT6X36_REG_DEVICE_MODE 0x00
|
||||
#define FT6X36_REG_GESTURE_ID 0x01
|
||||
#define FT6X36_REG_NUM_TOUCHES 0x02
|
||||
#define FT6X36_REG_P1_XH 0x03
|
||||
#define FT6X36_REG_P1_XL 0x04
|
||||
#define FT6X36_REG_P1_YH 0x05
|
||||
#define FT6X36_REG_P1_YL 0x06
|
||||
#define FT6X36_REG_P1_WEIGHT 0x07
|
||||
#define FT6X36_REG_P1_MISC 0x08
|
||||
#define FT6X36_REG_P2_XH 0x09
|
||||
#define FT6X36_REG_P2_XL 0x0A
|
||||
#define FT6X36_REG_P2_YH 0x0B
|
||||
#define FT6X36_REG_P2_YL 0x0C
|
||||
#define FT6X36_REG_P2_WEIGHT 0x0D
|
||||
#define FT6X36_REG_P2_MISC 0x0E
|
||||
display.touch_update(touches, x1, y1, gesture)
|
||||
end
|
||||
|
||||
def every_100ms()
|
||||
if self.wire self.ts_loop() end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
ts = FT3663()
|
|
@ -0,0 +1,70 @@
|
|||
#-------------------------------------------------------------
|
||||
- Specialized driver for AXP202 of LilyGo TWatch 2020V3
|
||||
- source is from: https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library/blob/master/src/TTGO.cpp
|
||||
-------------------------------------------------------------#
|
||||
class AXP202_LilyGo_TWatch_2020V3 : AXP202
|
||||
def init()
|
||||
super(self).init()
|
||||
if self.wire
|
||||
# Change the shutdown time to 4 seconds
|
||||
# power->setShutdownTime(AXP_POWER_OFF_TIME_4S);
|
||||
self. set_shutdown_time(4)
|
||||
|
||||
# Turn off the charging led
|
||||
# power->setChgLEDMode(AXP20X_LED_OFF);
|
||||
self.set_chg_led_mode(0)
|
||||
|
||||
# // Turn off external enable
|
||||
# power->setPowerOutPut(AXP202_EXTEN, false);
|
||||
self.set_exten(false)
|
||||
|
||||
# axp202 allows maximum charging current of 1800mA, minimum 300mA
|
||||
# power->setChargeControlCur(300);
|
||||
self.set_chg_current_ma(300)
|
||||
|
||||
# power->setLDO2Voltage(3300);
|
||||
self.set_ldo_voltage(2, 3300)
|
||||
|
||||
# // New features of Twatch V3
|
||||
# power->limitingOff();
|
||||
self.set_limiting_off()
|
||||
|
||||
# //Audio power domain is AXP202 LDO4
|
||||
# power->setPowerOutPut(AXP202_LDO4, false);
|
||||
self.set_ldo_enable(4, false)
|
||||
# power->setLDO4Voltage(AXP202_LDO4_3300MV);
|
||||
self.set_ldo_voltage(4, 3300)
|
||||
# power->setPowerOutPut(AXP202_LDO4, true);
|
||||
self.set_ldo_enable(4, true)
|
||||
|
||||
# // No use
|
||||
# power->setPowerOutPut(AXP202_LDO3, false);
|
||||
self.set_ldo_enable(3, false)
|
||||
end
|
||||
end
|
||||
|
||||
# enable power to audio chip
|
||||
def audio_enable(en)
|
||||
self.set_ldo_enable(4, en)
|
||||
end
|
||||
|
||||
# set power to backlight, dimming is controlled via PWM on GPIO15
|
||||
def backlight_enable(en)
|
||||
self.set_ldo_enable(2, en)
|
||||
end
|
||||
|
||||
# Dimmer in percentage
|
||||
def set_displaydimmer(x)
|
||||
self.backlight_enable(x > 0)
|
||||
end
|
||||
|
||||
# respond to display events
|
||||
def display(cmd, idx, payload, raw)
|
||||
if cmd == "dim" || cmd == "power"
|
||||
self.set_displaydimmer(idx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
axp202 = AXP202_LilyGo_TWatch_2020V3()
|
||||
tasmota.add_driver(axp202)
|
|
@ -1028,6 +1028,7 @@
|
|||
#define USE_LVGL_OPENHASP // Enable OpenHASP template compatiblity (adds LVGL template and some fonts)
|
||||
#define USE_LVGL_MAX_SLEEP 10 // max sleep in ms when LVGL is enabled, more than 10ms will make display less responsive
|
||||
#define USE_LVGL_PNG_DECODER // include a PNG image decoder from file system (+16KB)
|
||||
//#define USE_LVGL_TOUCHSCREEN // Use virtual touch screen with Berry driver
|
||||
//#define USE_LVGL_FREETYPE // Use the FreeType renderer to display fonts using native TTF files in file system (+77KB flash)
|
||||
#define LV_USE_FT_CACHE_MANAGER 1 // define whether glyphs are cached by FreeType library
|
||||
#define USE_LVGL_FREETYPE_MAX_FACES 64 // max number of FreeType faces in cache
|
||||
|
|
|
@ -34,43 +34,47 @@ Renderer *Init_uDisplay(const char *desc);
|
|||
* display.start(string) -> comptr or nil if failed
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
int be_ntv_display_start(bvm *vm) {
|
||||
#ifdef USE_UNIVERSAL_DISPLAY
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 1 && be_isstring(vm, 1)) {
|
||||
const char * desc = be_tostring(vm, 1);
|
||||
// remove all objects on stack to avoid warnings in subsequent calls to Berry
|
||||
be_pop(vm, argc);
|
||||
Renderer * renderer = Init_uDisplay(desc);
|
||||
if (renderer) {
|
||||
be_pushcomptr(vm, renderer);
|
||||
} else {
|
||||
be_pushnil(vm);
|
||||
}
|
||||
be_return(vm);
|
||||
int be_ntv_display_start(struct bvm *vm) {
|
||||
#ifdef USE_UNIVERSAL_DISPLAY
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
if (argc >= 1 && be_isstring(vm, 1)) {
|
||||
const char * desc = be_tostring(vm, 1);
|
||||
// remove all objects on stack to avoid warnings in subsequent calls to Berry
|
||||
be_pop(vm, argc);
|
||||
Renderer * renderer = Init_uDisplay(desc);
|
||||
if (renderer) {
|
||||
be_pushcomptr(vm, renderer);
|
||||
} else {
|
||||
be_pushnil(vm);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
#else // USE_UNIVERSAL_DISPLAY
|
||||
be_raise(vm, "internal_error", "universal display driver not present");
|
||||
#endif // USE_UNIVERSAL_DISPLAY
|
||||
}
|
||||
|
||||
// `display.dimmer([dim:int]) -> int` sets the dimmer of display, value 0..100. If `0` then turn off display. If no arg, read the current value.
|
||||
int be_ntv_display_dimmer(bvm *vm) {
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
int32_t dimmer;
|
||||
if (argc >= 1) {
|
||||
if (!be_isint(vm, 1)) { be_raise(vm, "type_error", "arg must be int"); }
|
||||
dimmer = be_toint(vm, 1);
|
||||
if ((dimmer < 0) || (dimmer > 100)) { be_raise(vm, "value_error", "value must be in range 0..100"); }
|
||||
be_pop(vm, argc); // clear stack to avoid ripple errors in code called later
|
||||
SetDisplayDimmer(dimmer);
|
||||
ApplyDisplayDimmer();
|
||||
}
|
||||
be_pushint(vm, GetDisplayDimmer());
|
||||
be_return(vm);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
#else // USE_UNIVERSAL_DISPLAY
|
||||
be_raise(vm, "internal_error", "universal display driver not present");
|
||||
#endif // USE_UNIVERSAL_DISPLAY
|
||||
}
|
||||
|
||||
// `display.dimmer([dim:int]) -> int` sets the dimmer of display, value 0..100. If `0` then turn off display. If no arg, read the current value.
|
||||
int be_ntv_display_dimmer(struct bvm *vm) {
|
||||
int32_t argc = be_top(vm); // Get the number of arguments
|
||||
int32_t dimmer;
|
||||
if (argc >= 1) {
|
||||
if (!be_isint(vm, 1)) { be_raise(vm, "type_error", "arg must be int"); }
|
||||
dimmer = be_toint(vm, 1);
|
||||
if ((dimmer < 0) || (dimmer > 100)) { be_raise(vm, "value_error", "value must be in range 0..100"); }
|
||||
be_pop(vm, argc); // clear stack to avoid ripple errors in code called later
|
||||
SetDisplayDimmer(dimmer);
|
||||
ApplyDisplayDimmer();
|
||||
}
|
||||
be_pushint(vm, GetDisplayDimmer());
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
void be_ntv_display_touch_update(int32_t touches, int32_t raw_x, int32_t raw_y, int32_t gesture) {
|
||||
#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS)
|
||||
Touch_SetStatus(touches, raw_x, raw_y, gesture);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
xdrv_55_touch.ino - Touch contolers
|
||||
|
||||
Copyright (C) 2021 Gerhard Mutz and Theo Arends
|
||||
Copyright (C) 2021 Gerhard Mutz, Theo Arends & Stephan Hadinger
|
||||
|
||||
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
|
||||
|
@ -17,9 +17,26 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*******************************************************************************************\
|
||||
* Universal TouchScreen driver, extensible via Berry
|
||||
*
|
||||
* API:
|
||||
* void Touch_Init() - TODO
|
||||
*
|
||||
* uint32_t Touch_Status(int32_t sel)
|
||||
* 0: return 1 if TSGlobal.touched
|
||||
* 1: return x
|
||||
* 2: return y
|
||||
* -1: return raw x (before conersion for resistive)
|
||||
* -2: return raw y
|
||||
*
|
||||
* void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y))
|
||||
*
|
||||
* void TS_RotConvert(int16_t *x, int16_t *y) - calls the renderer's rotation converter
|
||||
\*******************************************************************************************/
|
||||
|
||||
|
||||
#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS)
|
||||
#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS)
|
||||
|
||||
#ifdef USE_DISPLAY_LVGL_ONLY
|
||||
#undef USE_TOUCH_BUTTONS
|
||||
|
@ -29,13 +46,33 @@
|
|||
|
||||
#define XDRV_55 55
|
||||
|
||||
// Codes for gestures, when supported by the Touch Screen controller
|
||||
enum TS_Gesture {
|
||||
TS_Gest_None = 0,
|
||||
TS_Gest_Move_Up = 0x10,
|
||||
TS_Gest_Move_Down = 0x11,
|
||||
TS_Gest_Move_Left = 0x12,
|
||||
TS_Gest_Move_Right = 0x13,
|
||||
TS_Gest_Zoom_In = 0x20,
|
||||
TS_Gest_Zoom_Out = 0x21,
|
||||
};
|
||||
|
||||
typedef struct TSGlobal_t {
|
||||
int16_t raw_touch_xp = 0;
|
||||
int16_t raw_touch_yp = 0;
|
||||
int16_t touch_xp = 0;
|
||||
int16_t touch_yp = 0;
|
||||
uint8_t touches = 0; // number of touches for multi-touch
|
||||
uint8_t gesture = 0; // gesture code
|
||||
// multi-point is not yet supported
|
||||
bool touched = false;
|
||||
bool external_ts = false;
|
||||
} TSGlobal_t;
|
||||
|
||||
TSGlobal_t TSGlobal;
|
||||
|
||||
bool FT5206_found = false;
|
||||
bool XPT2046_found = false;
|
||||
int16_t raw_touch_xp;
|
||||
int16_t raw_touch_yp;
|
||||
int16_t touch_xp;
|
||||
int16_t touch_yp;
|
||||
bool touched;
|
||||
|
||||
#ifndef MAX_TOUCH_BUTTONS
|
||||
#define MAX_TOUCH_BUTTONS 16
|
||||
|
@ -45,19 +82,44 @@ bool touched;
|
|||
VButton *buttons[MAX_TOUCH_BUTTONS];
|
||||
#endif
|
||||
|
||||
void Touch_SetStatus(uint8_t touches, uint16_t raw_x, uint16_t raw_y, uint8_t gesture) {
|
||||
TSGlobal.external_ts = true;
|
||||
TSGlobal.gesture = gesture;
|
||||
TSGlobal.touches = touches;
|
||||
TSGlobal.touched = (TSGlobal.touches > 0);
|
||||
TSGlobal.touch_xp = TSGlobal.raw_touch_xp = raw_x;
|
||||
TSGlobal.touch_yp = TSGlobal.raw_touch_yp = raw_y;
|
||||
TS_RotConvert(&TSGlobal.touch_xp, &TSGlobal.touch_yp);
|
||||
}
|
||||
|
||||
// return true if succesful, false if not configured
|
||||
bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gesture,
|
||||
uint16_t* raw_x, uint16_t* raw_y) {
|
||||
if (TSGlobal.external_ts || FT5206_found || XPT2046_found) {
|
||||
if (touches) { *touches = TSGlobal.touches; }
|
||||
if (x) { *x = TSGlobal.touch_xp; }
|
||||
if (y) { *y = TSGlobal.touch_yp; }
|
||||
if (raw_x) { *raw_x = TSGlobal.raw_touch_xp; }
|
||||
if (raw_y) { *raw_y = TSGlobal.raw_touch_yp; }
|
||||
if (gesture) { *touches = TSGlobal.gesture; }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t Touch_Status(int32_t sel) {
|
||||
if (FT5206_found || XPT2046_found) {
|
||||
if (TSGlobal.external_ts || FT5206_found || XPT2046_found) {
|
||||
switch (sel) {
|
||||
case 0:
|
||||
return touched;
|
||||
return TSGlobal.touched;
|
||||
case 1:
|
||||
return touch_xp;
|
||||
return TSGlobal.touch_xp;
|
||||
case 2:
|
||||
return touch_yp;
|
||||
return TSGlobal.touch_yp;
|
||||
case -1: // before calibration
|
||||
return raw_touch_xp;
|
||||
return TSGlobal.raw_touch_xp;
|
||||
case -2:
|
||||
return raw_touch_yp;
|
||||
return TSGlobal.raw_touch_yp;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -134,27 +196,27 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
|
||||
#ifdef USE_FT5206
|
||||
if (FT5206_found) {
|
||||
touched = FT5206_touched();
|
||||
if (touched) {
|
||||
raw_touch_xp = FT5206_x();
|
||||
raw_touch_yp = FT5206_y();
|
||||
TSGlobal.touched = FT5206_touched();
|
||||
if (TSGlobal.touched) {
|
||||
TSGlobal.raw_touch_xp = FT5206_x();
|
||||
TSGlobal.raw_touch_yp = FT5206_y();
|
||||
}
|
||||
}
|
||||
#endif // USE_FT5206
|
||||
|
||||
#ifdef USE_XPT2046
|
||||
if (XPT2046_found) {
|
||||
touched = XPT2046_touched();
|
||||
if (touched) {
|
||||
raw_touch_xp = XPT2046_x();
|
||||
raw_touch_yp = XPT2046_y();
|
||||
TSGlobal.touched = XPT2046_touched();
|
||||
if (TSGlobal.touched) {
|
||||
TSGlobal.raw_touch_xp = XPT2046_x();
|
||||
TSGlobal.raw_touch_yp = XPT2046_y();
|
||||
}
|
||||
}
|
||||
#endif // USE_XPT2046
|
||||
touch_xp = raw_touch_xp;
|
||||
touch_yp = raw_touch_yp;
|
||||
TSGlobal.touch_xp = TSGlobal.raw_touch_xp;
|
||||
TSGlobal.touch_yp = TSGlobal.raw_touch_yp;
|
||||
|
||||
if (touched) {
|
||||
if (TSGlobal.touched) {
|
||||
was_touched = true;
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
|
@ -163,7 +225,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
#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)) {
|
||||
if (TSGlobal.touch_xp > (xcenter - TDELTA) && TSGlobal.touch_xp < (xcenter + TDELTA) && TSGlobal.touch_yp > (TYPOS - TDELTA) && TSGlobal.touch_yp < (TYPOS + TDELTA)) {
|
||||
// hit a button
|
||||
if (!(tbstate[tbut] & 1)) {
|
||||
// pressed
|
||||
|
@ -177,11 +239,11 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
#endif // USE_M5STACK_CORE2
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
|
||||
rotconvert(&touch_xp, &touch_yp);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, "TS : touched x=%i y=%i (raw x=%i y=%i)", touch_xp, touch_yp, raw_touch_xp, raw_touch_yp);
|
||||
rotconvert(&TSGlobal.touch_xp, &TSGlobal.touch_yp);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, "TS : TSGlobal.touched x=%i y=%i (raw x=%i y=%i)", TSGlobal.touch_xp, TSGlobal.touch_yp, TSGlobal.raw_touch_xp, TSGlobal.raw_touch_yp);
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
CheckTouchButtons(touched, touch_xp, touch_yp);
|
||||
CheckTouchButtons(TSGlobal.touched, TSGlobal.touch_xp, TSGlobal.touch_yp);
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
|
||||
} else {
|
||||
|
@ -196,13 +258,13 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
}
|
||||
#endif // USE_M5STACK_CORE2
|
||||
|
||||
rotconvert(&touch_xp, &touch_yp); // still do rot convert if not touched
|
||||
rotconvert(&TSGlobal.touch_xp, &TSGlobal.touch_yp); // still do rot convert if not TSGlobal.touched
|
||||
if (was_touched) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, "TS : released x=%i y=%i (raw x=%i y=%i)", touch_xp, touch_yp, raw_touch_xp, raw_touch_yp);
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, "TS : released x=%i y=%i (raw x=%i y=%i)", TSGlobal.touch_xp, TSGlobal.touch_yp, TSGlobal.raw_touch_xp, TSGlobal.raw_touch_yp);
|
||||
was_touched = false;
|
||||
}
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
CheckTouchButtons(touched, touch_xp, touch_yp);
|
||||
CheckTouchButtons(TSGlobal.touched, TSGlobal.touch_xp, TSGlobal.touch_yp);
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
|
||||
}
|
||||
|
@ -231,7 +293,7 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
uint8_t vbutt=0;
|
||||
|
||||
if (!renderer) return;
|
||||
if (touched) {
|
||||
if (TSGlobal.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++) {
|
||||
|
@ -309,8 +371,8 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
}
|
||||
}
|
||||
}
|
||||
raw_touch_xp = touch_xp = 0;
|
||||
raw_touch_yp = touch_yp = 0;
|
||||
TSGlobal.raw_touch_xp = TSGlobal.touch_xp = 0;
|
||||
TSGlobal.raw_touch_yp = TSGlobal.touch_yp = 0;
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
|
|
Loading…
Reference in New Issue