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 0f7b1a5b54a7e1bb33fbd7ad2a78df7b7dc7b1d0
Author: Jerzy Kasenberg <jerzy.kasenb...@codecoup.pl>
AuthorDate: Thu Mar 2 15:09:10 2023 +0100

    lvgl/stmpe610: Add initial support for STMPE610 touch screen
---
 hw/drivers/display/lvgl/indev/stmpe610/pkg.yml     |  35 ++
 .../display/lvgl/indev/stmpe610/src/stmpe610.c     | 354 +++++++++++++++++++++
 hw/drivers/display/lvgl/indev/stmpe610/syscfg.yml  |  53 +++
 hw/drivers/display/lvgl/pkg.yml                    |   2 +
 hw/drivers/display/lvgl/syscfg.yml                 |   3 +
 5 files changed, 447 insertions(+)

diff --git a/hw/drivers/display/lvgl/indev/stmpe610/pkg.yml 
b/hw/drivers/display/lvgl/indev/stmpe610/pkg.yml
new file mode 100644
index 000000000..215acc57b
--- /dev/null
+++ b/hw/drivers/display/lvgl/indev/stmpe610/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/stmpe610
+pkg.description: LVGL touch screen driver for STMPE610
+pkg.author: "Apache Mynewt <d...@mynewt.apache.org>"
+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:
+    stmpe610_os_dev_create: 400
+    stmpe610_register_lv_indev: 1100
diff --git a/hw/drivers/display/lvgl/indev/stmpe610/src/stmpe610.c 
b/hw/drivers/display/lvgl/indev/stmpe610/src/stmpe610.c
new file mode 100644
index 000000000..dd17f603e
--- /dev/null
+++ b/hw/drivers/display/lvgl/indev/stmpe610/src/stmpe610.c
@@ -0,0 +1,354 @@
+/*
+ * 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 <os/os_time.h>
+#include <bsp/bsp.h>
+#include <hal/hal_gpio.h>
+#include <bus/drivers/spi_common.h>
+
+#include <hal/lv_hal_indev.h>
+#include <core/lv_disp.h>
+
+#define STMPE610_XY_SWAP         MYNEWT_VAL(STMPE610_XY_SWAP)
+#define STMPE610_X_INV           MYNEWT_VAL(STMPE610_X_INV)
+#define STMPE610_Y_INV           MYNEWT_VAL(STMPE610_Y_INV)
+#define STMPE610_MIN_X           MYNEWT_VAL(STMPE610_MIN_X)
+#define STMPE610_MIN_Y           MYNEWT_VAL(STMPE610_MIN_Y)
+#define STMPE610_MAX_X           MYNEWT_VAL(STMPE610_MAX_X)
+#define STMPE610_MAX_Y           MYNEWT_VAL(STMPE610_MAX_Y)
+#define STMPE610_X_RANGE         ((STMPE610_MAX_X) - (STMPE610_MIN_X))
+#define STMPE610_Y_RANGE         ((STMPE610_MAX_Y) - (STMPE610_MIN_Y))
+#define STMPE610_HOR_RES         MYNEWT_VAL(STMPE610_HOR_RES)
+#define STMPE610_VER_RES         MYNEWT_VAL(STMPE610_VER_RES)
+
+struct bus_spi_node touch;
+struct bus_spi_node_cfg touch_spi_cfg = {
+    .node_cfg.bus_name = MYNEWT_VAL(STMPE610_SPI_DEV_NAME),
+    .pin_cs = MYNEWT_VAL(STMPE610_SPI_CS_PIN),
+    .mode = BUS_SPI_MODE_0,
+    .data_order = HAL_SPI_MSB_FIRST,
+    .freq = MYNEWT_VAL(STMPE610_SPI_FREQ),
+};
+
+static struct os_dev *touch_dev;
+static lv_indev_drv_t stmpe610_drv;
+static lv_indev_t *stmpe610_dev;
+
+/** Reset Control **/
+#define STMPE_SYS_CTRL1             0x03
+#define STMPE_SYS_CTRL1_RESET       0x02
+
+#define STMPE_SYS_CTRL2             0x04
+
+#define STMPE_SPI_CFG               0x08
+#define STMPE_SPI_AUTO_INCR         0x04
+
+#define STMPE_TSC_CTRL              0x40
+#define STMPE_TSC_CTRL_EN           0x01
+#define STMPE_TSC_CTRL_XYZ          0x00
+#define STMPE_TSC_CTRL_XY           0x02
+#define STMPE_TSC_CTRL_X            0x04
+#define STMPE_TSC_CTRL_Y            0x06
+#define STMPE_TSC_CTRL_Z            0x08
+#define STMPE_TSC_CTRL_TSC_STA      0x80
+
+/** Interrupt control **/
+#define STMPE_INT_CTRL              0x09
+#define STMPE_INT_CTRL_POL_HIGH     0x04
+#define STMPE_INT_CTRL_POL_LOW      0x00
+#define STMPE_INT_CTRL_EDGE         0x02
+#define STMPE_INT_CTRL_LEVEL        0x00
+#define STMPE_INT_CTRL_ENABLE       0x01
+#define STMPE_INT_CTRL_DISABLE      0x00
+
+/** Interrupt enable **/
+#define STMPE_INT_EN                0x0A
+#define STMPE_INT_EN_TOUCHDET       0x01
+#define STMPE_INT_EN_FIFOTH         0x02
+#define STMPE_INT_EN_FIFOOF         0x04
+#define STMPE_INT_EN_FIFOFULL       0x08
+#define STMPE_INT_EN_FIFOEMPTY      0x10
+#define STMPE_INT_EN_ADC            0x40
+#define STMPE_INT_EN_GPIO           0x80
+
+/** Interrupt status **/
+#define STMPE_INT_STA               0x0B
+#define STMPE_INT_STA_TOUCHDET      0x01
+#define STMPE_INT_STA_FIFO_THT      0x02
+
+/** ADC control **/
+#define STMPE_ADC_CTRL1             0x20
+#define STMPE_ADC_CTRL1_12BIT       0x08
+#define STMPE_ADC_CTRL1_10BIT       0x00
+
+/** ADC control **/
+#define STMPE_ADC_CTRL2             0x21
+#define STMPE_ADC_CTRL2_1_625MHZ    0x00
+#define STMPE_ADC_CTRL2_3_25MHZ     0x01
+#define STMPE_ADC_CTRL2_6_5MHZ      0x02
+
+/** Touchscreen controller configuration **/
+#define STMPE_TSC_CFG               0x41
+#define STMPE_TSC_CFG_1SAMPLE       0x00
+#define STMPE_TSC_CFG_2SAMPLE       0x40
+#define STMPE_TSC_CFG_4SAMPLE       0x80
+#define STMPE_TSC_CFG_8SAMPLE       0xC0
+#define STMPE_TSC_CFG_DELAY_10US    0x00
+#define STMPE_TSC_CFG_DELAY_50US    0x08
+#define STMPE_TSC_CFG_DELAY_100US   0x10
+#define STMPE_TSC_CFG_DELAY_500US   0x18
+#define STMPE_TSC_CFG_DELAY_1MS     0x20
+#define STMPE_TSC_CFG_DELAY_5MS     0x28
+#define STMPE_TSC_CFG_DELAY_10MS    0x30
+#define STMPE_TSC_CFG_DELAY_50MS    0x38
+#define STMPE_TSC_CFG_SETTLE_10US   0x00
+#define STMPE_TSC_CFG_SETTLE_100US  0x01
+#define STMPE_TSC_CFG_SETTLE_500US  0x02
+#define STMPE_TSC_CFG_SETTLE_1MS    0x03
+#define STMPE_TSC_CFG_SETTLE_5MS    0x04
+#define STMPE_TSC_CFG_SETTLE_10MS   0x05
+#define STMPE_TSC_CFG_SETTLE_50MS   0x06
+#define STMPE_TSC_CFG_SETTLE_100MS  0x07
+
+/** FIFO level to generate interrupt **/
+#define STMPE_FIFO_TH               0x4A
+
+/** Current filled level of FIFO **/
+#define STMPE_FIFO_SIZE             0x4C
+
+/** Current status of FIFO **/
+#define STMPE_FIFO_STA              0x4B
+#define STMPE_FIFO_STA_RESET        0x01
+#define STMPE_FIFO_STA_OFLOW        0x80
+#define STMPE_FIFO_STA_FULL         0x40
+#define STMPE_FIFO_STA_EMPTY        0x20
+#define STMPE_FIFO_STA_THTRIG       0x10
+
+/** Touchscreen controller drive I **/
+#define STMPE_TSC_I_DRIVE           0x58
+#define STMPE_TSC_I_DRIVE_20MA      0x00
+#define STMPE_TSC_I_DRIVE_50MA      0x01
+
+/** Data port for TSC data address **/
+#define STMPE_TSC_DATA_X            0x4D
+#define STMPE_TSC_DATA_Y            0x4F
+#define STMPE_TSC_FRACTION_Z        0x56
+#define STMPE_TSC_DATA              0x57
+
+/** GPIO **/
+#define STMPE_GPIO_SET_PIN          0x10
+#define STMPE_GPIO_CLR_PIN          0x11
+#define STMPE_GPIO_DIR              0x13
+#define STMPE_GPIO_ALT_FUNCT        0x17
+
+
+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(STMPE610_MIN_X),
+    .right = MYNEWT_VAL(STMPE610_MAX_X),
+    .top = MYNEWT_VAL(STMPE610_MIN_Y),
+    .bottom = MYNEWT_VAL(STMPE610_MAX_Y),
+};
+
+static void
+xpt2046_corr(int16_t *xp, int16_t *yp)
+{
+    int x;
+    int y;
+#if STMPE610_XY_SWAP
+    x = *yp;
+    y = *xp;
+#else
+    x = *xp;
+    y = *yp;
+#endif
+
+    if (x < MYNEWT_VAL(STMPE610_MIN_X)) {
+        x = MYNEWT_VAL(STMPE610_MIN_X);
+    }
+    if (y < MYNEWT_VAL(STMPE610_MIN_Y)) {
+        y = MYNEWT_VAL(STMPE610_MIN_Y);
+    }
+
+    x = (x - STMPE610_MIN_X) * LV_HOR_RES / STMPE610_X_RANGE;
+    y = (y - STMPE610_MIN_Y) * LV_VER_RES / STMPE610_Y_RANGE;
+
+#if STMPE610_X_INV
+    x = LV_HOR_RES - x;
+#endif
+
+#if STMPE610_Y_INV
+    y = LV_VER_RES - y;
+#endif
+    *xp = x;
+    *yp = y;
+}
+
+static void
+stmpe610_spi_write_then_read(const uint8_t *wbuf, int wlen, uint8_t *rbuf, int 
rlen)
+{
+    if (rlen) {
+        bus_node_simple_write_read_transact(touch_dev, wbuf, wlen, rbuf, rlen);
+    } else {
+        bus_node_simple_write(touch_dev, wbuf, wlen);
+    }
+}
+
+static void
+stmpe610_write_reg8(uint8_t reg, uint8_t val)
+{
+    uint8_t buf[2] = { reg, val };
+    stmpe610_spi_write_then_read(buf, 2, NULL, 0);
+}
+
+static uint8_t
+stmpe610_read_reg8(uint8_t reg)
+{
+    uint8_t val;
+    reg |= 0x80;
+
+    stmpe610_spi_write_then_read(&reg, 1, &val, 1);
+
+    return val;
+}
+
+/**
+ * Get the current position and state of the touchpad
+ * @param data store the read data here
+ */
+static void
+stmpe610_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
+{
+    /* If there is not INT pin configured, assume int is active and read 
registers */
+    bool int_detected = MYNEWT_VAL(STMPE610_INT_PIN) < 0 || 
hal_gpio_read(MYNEWT_VAL(STMPE610_INT_PIN));
+    bool touch_detected = false;
+    uint8_t int_sta = 0;
+    uint8_t buf[4];
+
+    int16_t x = touch_screen_data.last_x;
+    int16_t y = touch_screen_data.last_y;
+
+    if (int_detected) {
+        int_sta = stmpe610_read_reg8(STMPE_INT_STA);
+        /* Get only the last value from FIFO */
+        buf[0] = STMPE_TSC_DATA | 0x80;
+        while ((stmpe610_read_reg8(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY) == 
0) {
+            stmpe610_spi_write_then_read(buf, 1, buf + 1, 1);
+            stmpe610_spi_write_then_read(buf, 1, buf + 2, 1);
+            stmpe610_spi_write_then_read(buf, 1, buf + 3, 1);
+            touch_detected = true;
+        }
+
+        if (touch_detected) {
+            x = buf[1] << 4 | (buf[2] >> 4);
+            y = ((buf[2] & 0xF) << 8) | buf[3];
+
+            xpt2046_corr(&x, &y);
+
+            touch_screen_data.last_x = x;
+            touch_screen_data.last_y = y;
+        }
+    }
+    if (int_sta) {
+        /* Clear raised interrupts */
+        stmpe610_write_reg8(STMPE_INT_STA, int_sta);
+    }
+
+    data->state = touch_detected ? LV_INDEV_STATE_PRESSED : 
LV_INDEV_STATE_RELEASED;
+    data->point.x = x;
+    data->point.y = y;
+}
+
+/**
+ * Initialize the STMPE610
+ */
+void
+stmpe610_register_lv_indev(void)
+{
+    stmpe610_read_reg8(0);
+    stmpe610_read_reg8(1);
+    stmpe610_read_reg8(STMPE_SPI_CFG);
+    stmpe610_write_reg8(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
+    os_time_delay(os_time_ticks_to_ms32(10));
+    /* Clocks on */
+    stmpe610_write_reg8(STMPE_SYS_CTRL2, 0x0);
+    stmpe610_write_reg8(STMPE_SPI_CFG, STMPE_SPI_AUTO_INCR);
+    stmpe610_read_reg8(STMPE_SPI_CFG);
+    /* Enable XY */
+    stmpe610_write_reg8(STMPE_TSC_CTRL,
+                   STMPE_TSC_CTRL_XY | STMPE_TSC_CTRL_EN);
+    stmpe610_write_reg8(STMPE_INT_EN, STMPE_INT_EN_TOUCHDET | 
STMPE_INT_EN_FIFOTH);
+    /* 96 clocks per conversion */
+    stmpe610_write_reg8(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_10BIT |
+                        (0x6 << 4));
+    stmpe610_write_reg8(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_6_5MHZ);
+    stmpe610_write_reg8(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE |
+                                       STMPE_TSC_CFG_DELAY_1MS |
+                                       STMPE_TSC_CFG_SETTLE_5MS);
+    stmpe610_write_reg8(STMPE_TSC_FRACTION_Z, 0x6);
+    stmpe610_write_reg8(STMPE_FIFO_TH, 1);
+    /* Reset */
+    stmpe610_write_reg8(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
+    stmpe610_write_reg8(STMPE_FIFO_STA, 0);
+    stmpe610_write_reg8(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
+    /* reset all ints */
+    stmpe610_write_reg8(STMPE_INT_STA, 0xFF);
+    stmpe610_write_reg8(STMPE_INT_CTRL,
+                        STMPE_INT_CTRL_POL_HIGH | STMPE_INT_CTRL_ENABLE);
+
+    /* Register a keypad input device */
+    lv_indev_drv_init(&stmpe610_drv);
+    stmpe610_drv.type = LV_INDEV_TYPE_POINTER;
+    stmpe610_drv.read_cb = stmpe610_read;
+    stmpe610_dev = lv_indev_drv_register(&stmpe610_drv);
+}
+
+void
+stmpe610_os_dev_create(void)
+{
+    struct bus_node_callbacks cbs = { 0 };
+    int rc;
+
+    if (MYNEWT_VAL(STMPE610_INT_PIN) >= 0) {
+        hal_gpio_init_in(MYNEWT_VAL(STMPE610_INT_PIN), HAL_GPIO_PULL_NONE);
+    }
+    hal_gpio_init_out(MYNEWT_VAL(STMPE610_SPI_CS_PIN), 1);
+
+    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/stmpe610/syscfg.yml 
b/hw/drivers/display/lvgl/indev/stmpe610/syscfg.yml
new file mode 100644
index 000000000..69326aa74
--- /dev/null
+++ b/hw/drivers/display/lvgl/indev/stmpe610/syscfg.yml
@@ -0,0 +1,53 @@
+# 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:
+    STMPE610_SPI_DEV_NAME:
+        description: SPI device name that LCD is connected to.
+        value: '"spi0"'
+    STMPE610_SPI_CS_PIN:
+        description: STMPE610 chip select pin for SPI.
+        value:
+        restrictions: $notnull
+    STMPE610_INT_PIN:
+        description: STMPE610 interrupt pin.
+        value: -1
+    STMPE610_SPI_FREQ:
+        description: SPI device frequency for LCD
+        value: 1000
+    STMPE610_MIN_X:
+        description: STMPE610 left margin value.
+        value: 200
+    STMPE610_MAX_X:
+        description: STMPE610 right margin value.
+        value: 3800
+    STMPE610_MIN_Y:
+        description: STMPE610 top margin value.
+        value: 200
+    STMPE610_MAX_Y:
+        description: STMPE610 bottom margin value.
+        value: 3800
+    STMPE610_XY_SWAP:
+        description: Swap X and Y axis.
+        value: 0
+    STMPE610_X_INV:
+        description: Invert X coordinate.
+        value: 0
+    STMPE610_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 d3a665564..faec417cb 100644
--- a/hw/drivers/display/lvgl/pkg.yml
+++ b/hw/drivers/display/lvgl/pkg.yml
@@ -71,6 +71,8 @@ pkg.deps.LVGL_ST7789:
 
 pkg.deps.LVGL_XPT2046:
     - "@apache-mynewt-core/hw/drivers/display/lvgl/indev/xpt2046"
+pkg.deps.LVGL_STMPE610:
+    - "@apache-mynewt-core/hw/drivers/display/lvgl/indev/stmpe610"
 
 pkg.cflags:
     - -DLV_CONF_INCLUDE_SIMPLE=1
diff --git a/hw/drivers/display/lvgl/syscfg.yml 
b/hw/drivers/display/lvgl/syscfg.yml
index a1ff05106..504f2a1ac 100644
--- a/hw/drivers/display/lvgl/syscfg.yml
+++ b/hw/drivers/display/lvgl/syscfg.yml
@@ -40,6 +40,9 @@ syscfg.defs:
     LVGL_XPT2046:
         description: Enable XPT2046 touchscreen driver.
         value:
+    LVGL_STMPE610:
+        description: Enable STMPE610 touchscreen driver.
+        value:
     LVGL_TIMER_PERIOD_MS:
         description: LV timer interval for periodical refresh and touch read
         value: 10

Reply via email to