This is an automated email from the ASF dual-hosted git repository. rymek pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 220e8ebca1573eebab276cc179996da13fa479fb Author: Jerzy Kasenberg <[email protected]> AuthorDate: Thu Mar 2 14:10:36 2023 +0100 lvgl/xpt2046: Add initial support for XPT2046 touch screen Signed-off-by: Jerzy Kasenberg <[email protected]> --- hw/drivers/display/lvgl/indev/xpt2046/pkg.yml | 35 ++++ .../display/lvgl/indev/xpt2046/src/xpt2046.c | 192 +++++++++++++++++++++ hw/drivers/display/lvgl/indev/xpt2046/syscfg.yml | 54 ++++++ hw/drivers/display/lvgl/pkg.yml | 3 + hw/drivers/display/lvgl/syscfg.yml | 3 + 5 files changed, 287 insertions(+) diff --git a/hw/drivers/display/lvgl/indev/xpt2046/pkg.yml b/hw/drivers/display/lvgl/indev/xpt2046/pkg.yml new file mode 100644 index 000000000..b0ef9e5b6 --- /dev/null +++ b/hw/drivers/display/lvgl/indev/xpt2046/pkg.yml @@ -0,0 +1,35 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: hw/drivers/display/lvgl/indev/xpt2046 +pkg.description: LVGL touch screen driver for XPT2046 +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - touchscreen + - lvgl + +pkg.deps: + - "@apache-mynewt-core/hw/bus/drivers/spi_common" + +pkg.include_dirs: + - "@lvgl/src" + +pkg.init: + xpt2046_os_dev_create: 400 + xpt2046_register_lv_indev: 1100 diff --git a/hw/drivers/display/lvgl/indev/xpt2046/src/xpt2046.c b/hw/drivers/display/lvgl/indev/xpt2046/src/xpt2046.c new file mode 100644 index 000000000..9ec052066 --- /dev/null +++ b/hw/drivers/display/lvgl/indev/xpt2046/src/xpt2046.c @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#include <stddef.h> +#include <stdio.h> +#include <os/os_time.h> +#include <hal/hal_gpio.h> +#include <bus/drivers/spi_common.h> +#include <bsp/bsp.h> + +#include <hal/lv_hal_indev.h> +#include <core/lv_disp.h> + +#define CMD_X_READ 0x90 +#define CMD_Y_READ 0xD0 +#define XPT2046_XY_SWAP MYNEWT_VAL(XPT2046_XY_SWAP) +#define XPT2046_X_INV MYNEWT_VAL(XPT2046_X_INV) +#define XPT2046_Y_INV MYNEWT_VAL(XPT2046_Y_INV) +#define XPT2046_MIN_X MYNEWT_VAL(XPT2046_MIN_X) +#define XPT2046_MIN_Y MYNEWT_VAL(XPT2046_MIN_Y) +#define XPT2046_MAX_X MYNEWT_VAL(XPT2046_MAX_X) +#define XPT2046_MAX_Y MYNEWT_VAL(XPT2046_MAX_Y) +#define XPT2046_X_RANGE ((XPT2046_MAX_X) - (XPT2046_MIN_X)) +#define XPT2046_Y_RANGE ((XPT2046_MAX_Y) - (XPT2046_MIN_Y)) +#define XPT2046_HOR_RES MYNEWT_VAL(XPT2046_HOR_RES) +#define XPT2046_VER_RES MYNEWT_VAL(XPT2046_VER_RES) + +struct bus_spi_node touch; +struct bus_spi_node_cfg touch_spi_cfg = { + .node_cfg.bus_name = MYNEWT_VAL(XPT2046_SPI_DEV_NAME), + .pin_cs = MYNEWT_VAL(XPT2046_SPI_CS_PIN), + .mode = BUS_SPI_MODE_0, + .data_order = HAL_SPI_MSB_FIRST, + .freq = MYNEWT_VAL(XPT2046_SPI_FREQ), +}; + +static struct os_dev *touch_dev; +static lv_indev_drv_t xpt2046_drv; +static lv_indev_t *xpt2046_dev; + +struct touch_screen_data { + /* ADC value for left edge */ + uint16_t left; + /* ADC value for right edge */ + uint16_t right; + /* ADC value for top edge */ + uint16_t top; + /* ADC value for bottom edge */ + uint16_t bottom; + /* Current value for X, Y detected */ + int x; + int y; + /* Values that were last reported */ + int last_x; + int last_y; +}; + +static struct touch_screen_data touch_screen_data = { + .left = MYNEWT_VAL(XPT2046_MIN_X), + .right = MYNEWT_VAL(XPT2046_MAX_X), + .top = MYNEWT_VAL(XPT2046_MIN_Y), + .bottom = MYNEWT_VAL(XPT2046_MAX_Y), +}; + +static void +xpt2046_corr(int16_t *xp, int16_t *yp) +{ + int x; + int y; +#if XPT2046_XY_SWAP + x = *yp; + y = *xp; +#else + x = *xp; + y = *yp; +#endif + + if (x < MYNEWT_VAL(XPT2046_MIN_X)) { + x = MYNEWT_VAL(XPT2046_MIN_X); + } + if (y < MYNEWT_VAL(XPT2046_MIN_Y)) { + y = MYNEWT_VAL(XPT2046_MIN_Y); + } + + x = (x - XPT2046_MIN_X) * LV_HOR_RES / XPT2046_X_RANGE; + y = (y - XPT2046_MIN_Y) * LV_VER_RES / XPT2046_Y_RANGE; + +#if XPT2046_X_INV + x = LV_HOR_RES - x; +#endif + +#if XPT2046_Y_INV + y = LV_VER_RES - y; +#endif + *xp = x; + *yp = y; +} + +/** + * Get the current position and state of the touchpad + * @param data store the read data here + * @return false: because no ore data to be read + */ +void +xpt2046_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) +{ + uint8_t cmd[5] = {0}; + uint8_t buf[5] = {0}; + int16_t x; + int16_t y; + (void)indev_drv; + + if (hal_gpio_read(MYNEWT_VAL(XPT2046_INT_PIN)) == 0) { + cmd[0] = CMD_X_READ; + cmd[1] = 0; + cmd[2] = CMD_Y_READ; + cmd[3] = 0; + cmd[4] = 0; + bus_node_duplex_write_read(touch_dev, cmd, buf, 5, 1000, 0); + + /* Normalize */ + x = (((uint16_t)buf[1] << 8) | buf[2]) >> 3; + y = (((uint16_t)buf[3] << 8) | buf[4]) >> 3; + + /* Convert to screen coordinates */ + xpt2046_corr(&x, &y); + + touch_screen_data.last_x = x; + touch_screen_data.last_y = y; + + data->state = LV_INDEV_STATE_PRESSED; + } else { + x = touch_screen_data.last_x; + y = touch_screen_data.last_y; + data->state = LV_INDEV_STATE_RELEASED; + } + + data->point.x = x; + data->point.y = y; +} + +/** + * Initialize the XPT2046 + */ +void +xpt2046_register_lv_indev(void) +{ + hal_gpio_init_in(MYNEWT_VAL(XPT2046_INT_PIN), HAL_GPIO_PULL_NONE); + /* Register a keypad input device */ + lv_indev_drv_init(&xpt2046_drv); + xpt2046_drv.type = LV_INDEV_TYPE_POINTER; + xpt2046_drv.read_cb = xpt2046_read; + xpt2046_dev = lv_indev_drv_register(&xpt2046_drv); +} + +void +lv_touch_handler(void) +{ + +} + +void +xpt2046_os_dev_create(void) +{ + hal_gpio_init_out(MYNEWT_VAL(XPT2046_SPI_CS_PIN), 1); + + struct bus_node_callbacks cbs = { 0 }; + int rc; + + bus_node_set_callbacks((struct os_dev *)&touch, &cbs); + + rc = bus_spi_node_create("touch", &touch, &touch_spi_cfg, NULL); + assert(rc == 0); + touch_dev = os_dev_open("touch", 0, NULL); +} diff --git a/hw/drivers/display/lvgl/indev/xpt2046/syscfg.yml b/hw/drivers/display/lvgl/indev/xpt2046/syscfg.yml new file mode 100644 index 000000000..37bd86e89 --- /dev/null +++ b/hw/drivers/display/lvgl/indev/xpt2046/syscfg.yml @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + XPT2046_SPI_DEV_NAME: + description: SPI device name that LCD is connected to. + value: '"spi0"' + XPT2046_SPI_CS_PIN: + description: STMPE610 chip select pin for SPI. + value: + restrictions: $notnull + XPT2046_SPI_FREQ: + description: SPI device frequency for LCD + value: 1000 + XPT2046_INT_PIN: + description: XPT2046 interrupt pin. + value: + restrictions: $notnull + XPT2046_MIN_X: + description: XPT2046 left margin value. + value: 200 + XPT2046_MAX_X: + description: XPT2046 right margin value. + value: 3800 + XPT2046_MIN_Y: + description: XPT2046 top margin value. + value: 200 + XPT2046_MAX_Y: + description: XPT2046 bottom margin value. + value: 3800 + XPT2046_XY_SWAP: + description: Swap X and Y axis. + value: 0 + XPT2046_X_INV: + description: Invert X coordinate. + value: 0 + XPT2046_Y_INV: + description: Invert Y coordinate. + value: 0 diff --git a/hw/drivers/display/lvgl/pkg.yml b/hw/drivers/display/lvgl/pkg.yml index 56360660f..d3a665564 100644 --- a/hw/drivers/display/lvgl/pkg.yml +++ b/hw/drivers/display/lvgl/pkg.yml @@ -69,6 +69,9 @@ pkg.deps.LVGL_ST7735S: pkg.deps.LVGL_ST7789: - "@apache-mynewt-core/hw/drivers/display/lvgl/tft/st7789" +pkg.deps.LVGL_XPT2046: + - "@apache-mynewt-core/hw/drivers/display/lvgl/indev/xpt2046" + pkg.cflags: - -DLV_CONF_INCLUDE_SIMPLE=1 - -Wno-unused-variable diff --git a/hw/drivers/display/lvgl/syscfg.yml b/hw/drivers/display/lvgl/syscfg.yml index 67a4a5837..a1ff05106 100644 --- a/hw/drivers/display/lvgl/syscfg.yml +++ b/hw/drivers/display/lvgl/syscfg.yml @@ -37,6 +37,9 @@ syscfg.defs: LVGL_ST7789: description: Enable ST7789 display driver. value: + LVGL_XPT2046: + description: Enable XPT2046 touchscreen driver. + value: LVGL_TIMER_PERIOD_MS: description: LV timer interval for periodical refresh and touch read value: 10
