From 7d8f78a08b7f37bbe46903d24ed46f181c89e52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Mi=C5=9B?= Date: Mon, 8 Feb 2021 21:14:29 +0100 Subject: [PATCH] drv: display: Initial FT800 display driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch includes initial support for FT800 display driver. It includes basic features. It can be easily extended with more FT800 display list and co-processor features. Signed-off-by: Hubert Miś --- CODEOWNERS | 2 + drivers/CMakeLists.txt | 1 + drivers/Kconfig | 2 + drivers/misc/CMakeLists.txt | 3 + drivers/misc/Kconfig | 10 + drivers/misc/ft8xx/CMakeLists.txt | 10 + drivers/misc/ft8xx/Kconfig | 10 + drivers/misc/ft8xx/ft8xx.c | 228 +++++++ drivers/misc/ft8xx/ft8xx_common.c | 71 ++ drivers/misc/ft8xx/ft8xx_copro.c | 179 +++++ drivers/misc/ft8xx/ft8xx_drv.c | 202 ++++++ drivers/misc/ft8xx/ft8xx_drv.h | 36 + drivers/misc/ft8xx/ft8xx_host_commands.h | 36 + dts/bindings/display/ftdi,ft800.yaml | 99 +++ include/device.h | 7 + include/drivers/misc/README | 17 + include/drivers/misc/ft8xx/ft8xx.h | 106 +++ include/drivers/misc/ft8xx/ft8xx_common.h | 87 +++ include/drivers/misc/ft8xx/ft8xx_copro.h | 149 +++++ include/drivers/misc/ft8xx/ft8xx_dl.h | 230 +++++++ include/drivers/misc/ft8xx/ft8xx_memory.h | 232 +++++++ .../drivers/misc/ft8xx/ft8xx_reference_api.h | 629 ++++++++++++++++++ 22 files changed, 2346 insertions(+) create mode 100644 drivers/misc/CMakeLists.txt create mode 100644 drivers/misc/Kconfig create mode 100644 drivers/misc/ft8xx/CMakeLists.txt create mode 100644 drivers/misc/ft8xx/Kconfig create mode 100644 drivers/misc/ft8xx/ft8xx.c create mode 100644 drivers/misc/ft8xx/ft8xx_common.c create mode 100644 drivers/misc/ft8xx/ft8xx_copro.c create mode 100644 drivers/misc/ft8xx/ft8xx_drv.c create mode 100644 drivers/misc/ft8xx/ft8xx_drv.h create mode 100644 drivers/misc/ft8xx/ft8xx_host_commands.h create mode 100644 dts/bindings/display/ftdi,ft800.yaml create mode 100644 include/drivers/misc/README create mode 100644 include/drivers/misc/ft8xx/ft8xx.h create mode 100644 include/drivers/misc/ft8xx/ft8xx_common.h create mode 100644 include/drivers/misc/ft8xx/ft8xx_copro.h create mode 100644 include/drivers/misc/ft8xx/ft8xx_dl.h create mode 100644 include/drivers/misc/ft8xx/ft8xx_memory.h create mode 100644 include/drivers/misc/ft8xx/ft8xx_reference_api.h diff --git a/CODEOWNERS b/CODEOWNERS index 4c16881d121..4a3f07f7985 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -235,6 +235,8 @@ /drivers/led_strip/ @mbolivar-nordic /drivers/lora/ @Mani-Sadhasivam /drivers/memc/ @gmarull +/drivers/misc/ @tejlmand +/drivers/misc/ft8xx/ @hubertmis /drivers/modem/*gsm* @jukkar /drivers/modem/hl7800.c @rerickson1 /drivers/modem/Kconfig.hl7800 @rerickson1 diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 972a91d1e99..ec925601afd 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -4,6 +4,7 @@ add_definitions(-D__ZEPHYR_SUPERVISOR__) add_subdirectory(console) add_subdirectory(interrupt_controller) +add_subdirectory(misc) add_subdirectory(pcie) add_subdirectory_ifdef(CONFIG_ADC adc) diff --git a/drivers/Kconfig b/drivers/Kconfig index c8cdc01f31f..027fd131436 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -109,4 +109,6 @@ source "drivers/edac/Kconfig" source "drivers/pm_cpu_ops/Kconfig" +source "drivers/misc/Kconfig" + endmenu diff --git a/drivers/misc/CMakeLists.txt b/drivers/misc/CMakeLists.txt new file mode 100644 index 00000000000..3d53d351dc7 --- /dev/null +++ b/drivers/misc/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory_ifdef(CONFIG_FT800 ft8xx) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig new file mode 100644 index 00000000000..33915d8dbe1 --- /dev/null +++ b/drivers/misc/Kconfig @@ -0,0 +1,10 @@ +# Miscellaneous drivers not exposing Zephyr Device Driver API + +# Copyright (c) 2021 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +menu "Miscellaneous Drivers" + +source "drivers/misc/ft8xx/Kconfig" + +endmenu diff --git a/drivers/misc/ft8xx/CMakeLists.txt b/drivers/misc/ft8xx/CMakeLists.txt new file mode 100644 index 00000000000..8583a3d072c --- /dev/null +++ b/drivers/misc/ft8xx/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + ft8xx.c + ft8xx_common.c + ft8xx_copro.c + ft8xx_drv.c +) diff --git a/drivers/misc/ft8xx/Kconfig b/drivers/misc/ft8xx/Kconfig new file mode 100644 index 00000000000..fb67efafb42 --- /dev/null +++ b/drivers/misc/ft8xx/Kconfig @@ -0,0 +1,10 @@ +# FT8xx Embedded Video Engine configuration options + +# Copyright (c) 2020-2021 Hubert Miś +# SPDX-License-Identifier: Apache-2.0 + +config FT800 + bool "FT800 Embedded Video Engine driver" + depends on SPI + help + Enable driver for FT800 controller. diff --git a/drivers/misc/ft8xx/ft8xx.c b/drivers/misc/ft8xx/ft8xx.c new file mode 100644 index 00000000000..7a3fc0754d3 --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ftdi_ft800 + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "ft8xx_drv.h" +#include "ft8xx_host_commands.h" + +LOG_MODULE_REGISTER(ft8xx, CONFIG_DISPLAY_LOG_LEVEL); + +#define FT8XX_DLSWAP_FRAME 0x02 + +#define FT8XX_EXPECTED_ID 0x7C + +struct ft8xx_config { + uint16_t vsize; + uint16_t voffset; + uint16_t vcycle; + uint16_t vsync0; + uint16_t vsync1; + uint16_t hsize; + uint16_t hoffset; + uint16_t hcycle; + uint16_t hsync0; + uint16_t hsync1; + uint8_t pclk; + uint8_t pclk_pol :1; + uint8_t cspread :1; + uint8_t swizzle :4; +}; + +struct ft8xx_data { + const struct ft8xx_config *config; + ft8xx_int_callback irq_callback; +}; + +const static struct ft8xx_config ft8xx_config = { + .pclk = DT_INST_PROP(0, pclk), + .pclk_pol = DT_INST_PROP(0, pclk_pol), + .cspread = DT_INST_PROP(0, cspread), + .swizzle = DT_INST_PROP(0, swizzle), + .vsize = DT_INST_PROP(0, vsize), + .voffset = DT_INST_PROP(0, voffset), + .vcycle = DT_INST_PROP(0, vcycle), + .vsync0 = DT_INST_PROP(0, vsync0), + .vsync1 = DT_INST_PROP(0, vsync1), + .hsize = DT_INST_PROP(0, hsize), + .hoffset = DT_INST_PROP(0, hoffset), + .hcycle = DT_INST_PROP(0, hcycle), + .hsync0 = DT_INST_PROP(0, hsync0), + .hsync1 = DT_INST_PROP(0, hsync1), +}; + +static struct ft8xx_data ft8xx_data = { + .config = &ft8xx_config, + .irq_callback = NULL, +}; + +static void host_command(uint8_t cmd) +{ + int err; + + err = ft8xx_drv_command(cmd); + __ASSERT(err == 0, "Writing FT8xx command failed"); +} + +static void wait(void) +{ + k_sleep(K_MSEC(20)); +} + +static bool verify_chip(void) +{ + uint32_t id = ft8xx_rd32(FT800_REG_ID); + + return (id & 0xff) == FT8XX_EXPECTED_ID; +} + +static int ft8xx_init(const struct device *dev) +{ + int ret; + struct ft8xx_config *config = (struct ft8xx_config *)dev->config; + + ret = ft8xx_drv_init(); + if (ret < 0) { + LOG_ERR("FT8xx driver initialization failed with %d", ret); + return ret; + } + + /* Reset display controller */ + host_command(CORERST); + host_command(ACTIVE); + wait(); + host_command(CLKEXT); + host_command(CLK48M); + wait(); + + host_command(CORERST); + host_command(ACTIVE); + wait(); + host_command(CLKEXT); + host_command(CLK48M); + wait(); + + if (!verify_chip()) { + LOG_ERR("FT8xx chip not recognized"); + return -ENODEV; + } + + /* Disable LCD */ + ft8xx_wr8(FT800_REG_GPIO, 0); + ft8xx_wr8(FT800_REG_PCLK, 0); + + /* Configure LCD */ + ft8xx_wr16(FT800_REG_HSIZE, config->hsize); + ft8xx_wr16(FT800_REG_HCYCLE, config->hcycle); + ft8xx_wr16(FT800_REG_HOFFSET, config->hoffset); + ft8xx_wr16(FT800_REG_HSYNC0, config->hsync0); + ft8xx_wr16(FT800_REG_HSYNC1, config->hsync1); + ft8xx_wr16(FT800_REG_VSIZE, config->vsize); + ft8xx_wr16(FT800_REG_VCYCLE, config->vcycle); + ft8xx_wr16(FT800_REG_VOFFSET, config->voffset); + ft8xx_wr16(FT800_REG_VSYNC0, config->vsync0); + ft8xx_wr16(FT800_REG_VSYNC1, config->vsync1); + ft8xx_wr8(FT800_REG_SWIZZLE, config->swizzle); + ft8xx_wr8(FT800_REG_PCLK_POL, config->pclk_pol); + ft8xx_wr8(FT800_REG_CSPREAD, config->cspread); + + /* Display initial screen */ + + /* Set the initial color */ + ft8xx_wr32(FT800_RAM_DL + 0, FT8XX_CLEAR_COLOR_RGB(0, 0x80, 0)); + /* Clear to the initial color */ + ft8xx_wr32(FT800_RAM_DL + 4, FT8XX_CLEAR(1, 1, 1)); + /* End the display list */ + ft8xx_wr32(FT800_RAM_DL + 8, FT8XX_DISPLAY()); + ft8xx_wr8(FT800_REG_DLSWAP, FT8XX_DLSWAP_FRAME); + + /* Enable LCD */ + + /* Enable display bit */ + ft8xx_wr8(FT800_REG_GPIO_DIR, 0x80); + ft8xx_wr8(FT800_REG_GPIO, 0x80); + /* Enable backlight */ + ft8xx_wr16(FT800_REG_PWM_HZ, 0x00FA); + ft8xx_wr8(FT800_REG_PWM_DUTY, 0x10); + /* Enable LCD signals */ + ft8xx_wr8(FT800_REG_PCLK, config->pclk); + + return 0; +} + +DEVICE_DEFINE(ft8xx_spi, "ft8xx_spi", ft8xx_init, NULL, + &ft8xx_data, &ft8xx_config, + APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); + +int ft8xx_get_touch_tag(void) +{ + /* Read FT800_REG_INT_FLAGS to clear IRQ */ + (void)ft8xx_rd8(FT800_REG_INT_FLAGS); + + return (int)ft8xx_rd8(FT800_REG_TOUCH_TAG); +} + +void ft8xx_drv_irq_triggered(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + if (ft8xx_data.irq_callback != NULL) { + ft8xx_data.irq_callback(); + } +} + +void ft8xx_register_int(ft8xx_int_callback callback) +{ + if (ft8xx_data.irq_callback != NULL) { + return; + } + + ft8xx_data.irq_callback = callback; + ft8xx_wr8(FT800_REG_INT_MASK, 0x04); + ft8xx_wr8(FT800_REG_INT_EN, 0x01); +} + +void ft8xx_calibrate(struct ft8xx_touch_transform *data) +{ + uint32_t result = 0; + + do { + ft8xx_copro_cmd_dlstart(); + ft8xx_copro_cmd(FT8XX_CLEAR_COLOR_RGB(0x00, 0x00, 0x00)); + ft8xx_copro_cmd(FT8XX_CLEAR(1, 1, 1)); + ft8xx_copro_cmd_calibrate(&result); + } while (result == 0); + + data->a = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_A); + data->b = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_B); + data->c = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_C); + data->d = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_D); + data->e = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_E); + data->f = ft8xx_rd32(FT800_REG_TOUCH_TRANSFORM_F); +} + +void ft8xx_touch_transform_set(const struct ft8xx_touch_transform *data) +{ + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_A, data->a); + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_B, data->b); + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_C, data->c); + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_D, data->d); + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_E, data->e); + ft8xx_wr32(FT800_REG_TOUCH_TRANSFORM_F, data->f); +} diff --git a/drivers/misc/ft8xx/ft8xx_common.c b/drivers/misc/ft8xx/ft8xx_common.c new file mode 100644 index 00000000000..49081dca2ac --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx_common.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include "ft8xx_drv.h" + +void ft8xx_wr8(uint32_t address, uint8_t data) +{ + int err; + + err = ft8xx_drv_write(address, &data, sizeof(data)); + __ASSERT(err == 0, "Writing FT8xx data at 0x%x failed", address); +} + +void ft8xx_wr16(uint32_t address, uint16_t data) +{ + int err; + uint8_t buffer[2]; + + *(uint16_t *)buffer = sys_cpu_to_le16(data); + err = ft8xx_drv_write(address, buffer, sizeof(buffer)); + __ASSERT(err == 0, "Writing FT8xx data at 0x%x failed", address); +} + +void ft8xx_wr32(uint32_t address, uint32_t data) +{ + int err; + uint8_t buffer[4]; + + *(uint32_t *)buffer = sys_cpu_to_le32(data); + err = ft8xx_drv_write(address, buffer, sizeof(buffer)); + __ASSERT(err == 0, "Writing FT8xx data at 0x%x failed", address); +} + +uint8_t ft8xx_rd8(uint32_t address) +{ + int err; + uint8_t data = 0; + + err = ft8xx_drv_read(address, &data, sizeof(data)); + __ASSERT(err == 0, "Reading FT8xx data from 0x%x failed", address); + + return data; +} + +uint16_t ft8xx_rd16(uint32_t address) +{ + int err; + uint8_t buffer[2] = {0}; + + err = ft8xx_drv_read(address, buffer, sizeof(buffer)); + __ASSERT(err == 0, "Reading FT8xx data from 0x%x failed", address); + + return sys_le16_to_cpu(*(const uint16_t *)buffer); +} + +uint32_t ft8xx_rd32(uint32_t address) +{ + int err; + uint8_t buffer[4] = {0}; + + err = ft8xx_drv_read(address, buffer, sizeof(buffer)); + __ASSERT(err == 0, "Reading FT8xx data from 0x%x failed", address); + + return sys_le32_to_cpu(*(const uint32_t *)buffer); +} diff --git a/drivers/misc/ft8xx/ft8xx_copro.c b/drivers/misc/ft8xx/ft8xx_copro.c new file mode 100644 index 00000000000..f9aa1e2407c --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx_copro.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +#include +#include +#include "ft8xx_drv.h" + +#define FT800_RAM_CMD_SIZE 4096UL + +enum { + CMD_DLSTART = 0xffffff00, + CMD_SWAP = 0xffffff01, + CMD_TEXT = 0xffffff0c, + CMD_NUMBER = 0xffffff2e, + CMD_CALIBRATE = 0xffffff15, +} ft8xx_cmd; + +static uint16_t reg_cmd_read; +static uint16_t reg_cmd_write; + +static uint16_t ram_cmd_fullness(void) +{ + return (reg_cmd_write - reg_cmd_read) % 4096UL; +} + +static uint16_t ram_cmd_freespace(void) +{ + return (FT800_RAM_CMD_SIZE - 4UL) - ram_cmd_fullness(); +} + +static void refresh_reg_cmd_read(void) +{ + reg_cmd_read = ft8xx_rd32(FT800_REG_CMD_READ); +} + +static void flush_reg_cmd_write(void) +{ + ft8xx_wr32(FT800_REG_CMD_WRITE, reg_cmd_write); +} + +static void increase_reg_cmd_write(uint16_t value) +{ + reg_cmd_write = (reg_cmd_write + value) % FT800_RAM_CMD_SIZE; +} + +void ft8xx_copro_cmd(uint32_t cmd) +{ + while (ram_cmd_freespace() < sizeof(cmd)) { + refresh_reg_cmd_read(); + } + + ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, cmd); + increase_reg_cmd_write(sizeof(cmd)); + + flush_reg_cmd_write(); +} + +void ft8xx_copro_cmd_dlstart(void) +{ + ft8xx_copro_cmd(CMD_DLSTART); +} + +void ft8xx_copro_cmd_swap(void) +{ + ft8xx_copro_cmd(CMD_SWAP); +} + +void ft8xx_copro_cmd_text(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + const char *s) +{ + const uint16_t str_bytes = strlen(s) + 1; + const uint16_t padding_bytes = (4 - (str_bytes % 4)) % 4; + const uint16_t cmd_size = sizeof(CMD_TEXT) + + sizeof(x) + + sizeof(y) + + sizeof(font) + + sizeof(options) + + str_bytes + + padding_bytes; + + while (ram_cmd_freespace() < cmd_size) { + refresh_reg_cmd_read(); + } + + ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_TEXT); + increase_reg_cmd_write(sizeof(CMD_TEXT)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, x); + increase_reg_cmd_write(sizeof(x)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, y); + increase_reg_cmd_write(sizeof(y)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, font); + increase_reg_cmd_write(sizeof(font)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, options); + increase_reg_cmd_write(sizeof(options)); + + (void)ft8xx_drv_write(FT800_RAM_CMD + reg_cmd_write, s, str_bytes); + increase_reg_cmd_write(str_bytes + padding_bytes); + + flush_reg_cmd_write(); +} + +void ft8xx_copro_cmd_number(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + int32_t n) +{ + const uint16_t cmd_size = sizeof(CMD_NUMBER) + + sizeof(x) + + sizeof(y) + + sizeof(font) + + sizeof(options) + + sizeof(n); + + while (ram_cmd_freespace() < cmd_size) { + refresh_reg_cmd_read(); + } + + ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_NUMBER); + increase_reg_cmd_write(sizeof(CMD_NUMBER)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, x); + increase_reg_cmd_write(sizeof(x)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, y); + increase_reg_cmd_write(sizeof(y)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, font); + increase_reg_cmd_write(sizeof(font)); + + ft8xx_wr16(FT800_RAM_CMD + reg_cmd_write, options); + increase_reg_cmd_write(sizeof(options)); + + ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, n); + increase_reg_cmd_write(sizeof(n)); + + flush_reg_cmd_write(); +} + +void ft8xx_copro_cmd_calibrate(uint32_t *result) +{ + const uint16_t cmd_size = sizeof(CMD_CALIBRATE) + sizeof(uint32_t); + uint32_t result_address; + + while (ram_cmd_freespace() < cmd_size) { + refresh_reg_cmd_read(); + } + + ft8xx_wr32(FT800_RAM_CMD + reg_cmd_write, CMD_CALIBRATE); + increase_reg_cmd_write(sizeof(CMD_CALIBRATE)); + + result_address = FT800_RAM_CMD + reg_cmd_write; + ft8xx_wr32(result_address, 1UL); + increase_reg_cmd_write(sizeof(uint32_t)); + + flush_reg_cmd_write(); + + /* Wait until calibration is finished. */ + while (ram_cmd_fullness() > 0) { + refresh_reg_cmd_read(); + } + + *result = ft8xx_rd32(result_address); +} diff --git a/drivers/misc/ft8xx/ft8xx_drv.c b/drivers/misc/ft8xx/ft8xx_drv.c new file mode 100644 index 00000000000..eb909009953 --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx_drv.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ft8xx_drv.h" + +#include +#include +#include +#include + +#define LOG_MODULE_NAME ft8xx_drv +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#define DT_DRV_COMPAT ftdi_ft800 +#define NODE_ID DT_INST(0, DT_DRV_COMPAT) + +/* SPI device */ +static const struct device *spi_ft8xx_dev; +static struct spi_cs_control cs_ctrl; +static const struct spi_config spi_cfg = { + .frequency = 8000000UL, + .operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER, + .cs = &cs_ctrl, +}; + +/* GPIO int line */ +#define IRQ_PIN DT_GPIO_PIN(NODE_ID, irq_gpios) +static const struct device *int_ft8xx_dev; + +static struct gpio_callback irq_cb_data; + +__weak void ft8xx_drv_irq_triggered(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + /* Intentionally empty */ +} + +/* Protocol details */ +#define ADDR_SIZE 3 +#define DUMMY_READ_SIZE 1 +#define COMMAND_SIZE 3 +#define MAX_READ_LEN (UINT16_MAX - ADDR_SIZE - DUMMY_READ_SIZE) +#define MAX_WRITE_LEN (UINT16_MAX - ADDR_SIZE) + +#define READ_OP 0x00 +#define WRITE_OP 0x80 +#define COMMAND_OP 0x40 + +static void insert_addr(uint32_t addr, uint8_t *buff) +{ + buff[0] = (addr >> 16) & 0x3f; + buff[1] = (addr >> 8) & 0xff; + buff[2] = (addr) & 0xff; +} + +int ft8xx_drv_init(void) +{ + int ret; + + cs_ctrl = (struct spi_cs_control){ + .gpio_dev = device_get_binding( + DT_SPI_DEV_CS_GPIOS_LABEL(NODE_ID)), + .gpio_pin = DT_SPI_DEV_CS_GPIOS_PIN(NODE_ID), + .gpio_dt_flags = DT_SPI_DEV_CS_GPIOS_FLAGS(NODE_ID), + .delay = 0, + }; + + spi_ft8xx_dev = device_get_binding(DT_BUS_LABEL(NODE_ID)); + if (!spi_ft8xx_dev) { + return -ENODEV; + } + + /* TODO: Verify if such entry in DTS is present. + * If not, use polling mode. + */ + int_ft8xx_dev = device_get_binding(DT_GPIO_LABEL(NODE_ID, irq_gpios)); + if (!int_ft8xx_dev) { + return -ENODEV; + } + + ret = gpio_pin_configure(int_ft8xx_dev, IRQ_PIN, + GPIO_INPUT | DT_GPIO_FLAGS(NODE_ID, irq_gpios)); + if (ret != 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure(int_ft8xx_dev, IRQ_PIN, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret != 0) { + return ret; + } + + gpio_init_callback(&irq_cb_data, ft8xx_drv_irq_triggered, BIT(IRQ_PIN)); + gpio_add_callback(int_ft8xx_dev, &irq_cb_data); + + return 0; +} + +int ft8xx_drv_write(uint32_t address, const uint8_t *data, unsigned int length) +{ + int ret; + uint8_t addr_buf[ADDR_SIZE]; + + insert_addr(address, addr_buf); + addr_buf[0] |= WRITE_OP; + + struct spi_buf tx[] = { + { + .buf = addr_buf, + .len = sizeof(addr_buf), + }, + { + /* Discard const, it is implicit for TX buffer */ + .buf = (uint8_t *)data, + .len = length, + }, + }; + + struct spi_buf_set tx_bufs = { + .buffers = tx, + .count = 2, + }; + + ret = spi_write(spi_ft8xx_dev, &spi_cfg, &tx_bufs); + if (ret < 0) { + LOG_ERR("SPI write error: %d", ret); + } + + return ret; +} + +int ft8xx_drv_read(uint32_t address, uint8_t *data, unsigned int length) +{ + int ret; + uint8_t dummy_read_buf[ADDR_SIZE + DUMMY_READ_SIZE]; + uint8_t addr_buf[ADDR_SIZE]; + + insert_addr(address, addr_buf); + addr_buf[0] |= READ_OP; + + struct spi_buf tx = { + .buf = addr_buf, + .len = sizeof(addr_buf), + }; + + struct spi_buf_set tx_bufs = { + .buffers = &tx, + .count = 1, + }; + + struct spi_buf rx[] = { + { + .buf = dummy_read_buf, + .len = sizeof(dummy_read_buf), + }, + { + .buf = data, + .len = length, + }, + }; + + struct spi_buf_set rx_bufs = { + .buffers = rx, + .count = 2, + }; + + ret = spi_transceive(spi_ft8xx_dev, &spi_cfg, &tx_bufs, &rx_bufs); + if (ret < 0) { + LOG_ERR("SPI transceive error: %d", ret); + } + + return ret; +} + +int ft8xx_drv_command(uint8_t command) +{ + int ret; + /* Most commands include COMMAND_OP bit. ACTIVE power mode command is + * an exception with value 0x00. + */ + uint8_t cmd_buf[COMMAND_SIZE] = {command, 0, 0}; + + struct spi_buf tx = { + .buf = cmd_buf, + .len = sizeof(cmd_buf), + }; + + struct spi_buf_set tx_bufs = { + .buffers = &tx, + .count = 1, + }; + + ret = spi_write(spi_ft8xx_dev, &spi_cfg, &tx_bufs); + if (ret < 0) { + LOG_ERR("SPI command error: %d", ret); + } + + return ret; +} diff --git a/drivers/misc/ft8xx/ft8xx_drv.h b/drivers/misc/ft8xx/ft8xx_drv.h new file mode 100644 index 00000000000..d742c31fcbf --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx_drv.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX serial driver API + */ + +#ifndef ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_DRV_H_ +#define ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_DRV_H_ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int ft8xx_drv_init(void); +int ft8xx_drv_read(uint32_t address, uint8_t *data, unsigned int length); +int ft8xx_drv_write(uint32_t address, const uint8_t *data, unsigned int length); +int ft8xx_drv_command(uint8_t command); + +extern void ft8xx_drv_irq_triggered(const struct device *dev, + struct gpio_callback *cb, uint32_t pins); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_DRV_H_ */ diff --git a/drivers/misc/ft8xx/ft8xx_host_commands.h b/drivers/misc/ft8xx/ft8xx_host_commands.h new file mode 100644 index 00000000000..3de8a39a828 --- /dev/null +++ b/drivers/misc/ft8xx/ft8xx_host_commands.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX host commands enumeration + */ + +#ifndef ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_HOST_COMMANDS_H_ +#define ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_HOST_COMMANDS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum ft800_command_t { + ACTIVE = 0, + STANDBY = 0x41, + SLEEP = 0x42, + PWRDOWN = 0x50, + + CLKEXT = 0x44, + CLK48M = 0x62, + CLK36M = 0x61, + + CORERST = 0x68 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_DISPLAY_FT8XX_FT8XX_HOST_COMMANDS_H_ */ diff --git a/dts/bindings/display/ftdi,ft800.yaml b/dts/bindings/display/ftdi,ft800.yaml new file mode 100644 index 00000000000..573cc85b727 --- /dev/null +++ b/dts/bindings/display/ftdi,ft800.yaml @@ -0,0 +1,99 @@ +# Copyright (c) 2020 Hubert Miś +# SPDX-License-Identifier: Apache-2.0 + +description: FTDI FT800 graphic controller + +compatible: "ftdi,ft800" + +include: spi-device.yaml + +properties: + irq-gpios: + type: phandle-array + required: false + description: Optional IRQ line of FT800 controller + + pclk: + type: int + required: true + description: The value to divide the main clock by for PCLK. If the + typical main clock was 48MHz and this value is 5, the PCLK + will be 9.6 MHz. Must be positive value to enable the screen + + pclk_pol: + type: int + required: true + description: Polarity of PCLK. If it is set to zero, PCLK polarity is on + the rising edge. If it is set to one, PCLK polarity is on + the falling edge. + + cspread: + type: int + required: true + description: Controls the transition of RGB signals with PCLK active clock + edge. When set to 0, R[7:2],G[7:2] and B[7:2] signals change + following the active edge of PCLK. When set to 1, R[7:2] + changes a PCLK clock early and B[7:2] a PCLK clock later, + which helps reduce the system noise. + + swizzle: + type: int + required: true + description: Controls the arrangement of output RGB pins, which may help + support different LCD panel. Please check FT800 Programmers + Guide for details. + + vsize: + type: int + required: true + description: Number of visible lines of pixels in one frame + + voffset: + type: int + required: true + description: Number of invisible lines at the beginning of a new frame + + vcycle: + type: int + required: true + description: Number of all lines in a frame. It includes all visible and + invisible lines at the beginning and at the end of a frame. + + vsync0: + type: int + required: true + description: Number of lines for the high state of signal VSYNC at + the start of new frame. + + vsync1: + type: int + required: true + description: Number of lines for signal VSYNC toggle takes at the start + of new frame. + + hsize: + type: int + required: true + description: Number of PCLK cycles per visible part of horizontal line + + hoffset: + type: int + required: true + description: Number of PCLK cycles before pixels are scanned out for + given line + + hcycle: + type: int + required: true + description: Number of total PCLK cycles per horizontal line scan. + + hsync0: + type: int + required: true + description: Number of PCLK cycles of HSYNC high state during start of + line + + hsync1: + type: int + required: true + description: Number of PCLK cycles for HSYNC toggle during start of line. diff --git a/include/device.h b/include/device.h index 2aebe25091c..2a26d7d4b3a 100644 --- a/include/device.h +++ b/include/device.h @@ -13,6 +13,13 @@ * @{ * @} */ +/** + * @brief Miscellaneous Drivers APIs + * @defgroup misc_interfaces Miscellaneous Drivers APIs + * @ingroup io_interfaces + * @{ + * @} + */ /** * @brief Device Model APIs * @defgroup device_model Device Model APIs diff --git a/include/drivers/misc/README b/include/drivers/misc/README new file mode 100644 index 00000000000..17a18102f36 --- /dev/null +++ b/include/drivers/misc/README @@ -0,0 +1,17 @@ +Miscellaneous Drivers + +Misc (or miscellaneous) drivers are device drivers that do not expose generic +Zephyr Device Drivers API. Such drivers have only device-specific API providing +functionalities not covered by any Generic Device Driver API. + +This directory contains header files of the Miscellaneous Drivers. + + +* FT8xx + + Embedded Video Engine containing graphic controller, audio processing, and + resistive touch controller. The graphic controller does not provide frame + buffer required by generic display driver API. Instead, it exposes higher + layer graphic operations like widgets, shapes, fonts, text, or bitmaps + rendering. These operations are controlled by a vendor-specific API designed + for this device. diff --git a/include/drivers/misc/ft8xx/ft8xx.h b/include/drivers/misc/ft8xx/ft8xx.h new file mode 100644 index 00000000000..59eaee5c66b --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX public API + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx driver public APIs + * @defgroup ft8xx_interface FT8xx driver APIs + * @ingroup misc_interfaces + * @{ + */ + +/** + * @struct ft8xx_touch_transform + * @brief Structure holding touchscreen calibration data + * + * The content of this structure is filled by ft8xx_calibrate(). + */ +struct ft8xx_touch_transform { + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t e; + uint32_t f; +}; + +/** + * @typedef ft8xx_int_callback + * @brief Callback API to inform API user that FT8xx triggered interrupt + * + * This callback is called from IRQ context. + */ +typedef void (*ft8xx_int_callback)(void); + +/** + * @brief Calibrate touchscreen + * + * Run touchscreen calibration procedure that collectw three touches from touch + * screen. Computed calibration result is automatically applied to the + * touchscreen processing and returned with @p data. + * + * The content of @p data may be stored and used after reset in + * ft8xx_touch_transform_set() to avoid calibrating touchscreen after each + * device reset. + * + * @param data Pointer to touchscreen transform structure to populate + */ +void ft8xx_calibrate(struct ft8xx_touch_transform *data); + +/** + * @brief Set touchscreen calibration data + * + * Apply given touchscreen transform data to the touchscreen processing. + * Data is to be obtained from calibration procedure started with + * ft8xx_calibrate(). + * + * @param data Pointer to touchscreen transform structure to apply + */ +void ft8xx_touch_transform_set(const struct ft8xx_touch_transform *data); + +/** + * @brief Get tag of recently touched element + * + * @return Tag value 0-255 of recently touched element + */ +int ft8xx_get_touch_tag(void); + +/** + * @brief Set callback executed when FT8xx triggers interrupt + * + * This function configures FT8xx to trigger interrupt when touch event changes + * tag value. + * + * When touch event changes tag value, FT8xx activates INT line. The line is + * kept active until ft8xx_get_touch_tag() is called. It results in single + * execution of @p callback until ft8xx_get_touch_tag() is called. + * + * @param callback Pointer to function called when FT8xx triggers interrupt + */ +void ft8xx_register_int(ft8xx_int_callback callback); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_H_ */ diff --git a/include/drivers/misc/ft8xx/ft8xx_common.h b/include/drivers/misc/ft8xx/ft8xx_common.h new file mode 100644 index 00000000000..2fde40e740a --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx_common.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX common functions + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COMMON_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COMMON_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx functions to write and read memory + * @defgroup ft8xx_common FT8xx common functions + * @ingroup ft8xx_interface + * @{ + */ + +/** + * @brief Write 1 byte (8 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Byte to write + */ +void ft8xx_wr8(uint32_t address, uint8_t data); + +/** + * @brief Write 2 bytes (16 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Value to write + */ +void ft8xx_wr16(uint32_t address, uint16_t data); + +/** + * @brief Write 4 bytes (32 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Value to write + */ +void ft8xx_wr32(uint32_t address, uint32_t data); + +/** + * @brief Read 1 byte (8 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +uint8_t ft8xx_rd8(uint32_t address); + +/** + * @brief Read 2 bytes (16 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +uint16_t ft8xx_rd16(uint32_t address); + +/** + * @brief Read 4 bytes (32 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +uint32_t ft8xx_rd32(uint32_t address); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COMMON_H_ */ diff --git a/include/drivers/misc/ft8xx/ft8xx_copro.h b/include/drivers/misc/ft8xx/ft8xx_copro.h new file mode 100644 index 00000000000..0913656ffde --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx_copro.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX coprocessor functions + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COPRO_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COPRO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx co-processor engine functions + * @defgroup ft8xx_copro FT8xx co-processor + * @ingroup ft8xx_interface + * @{ + */ + +/** Co-processor widget is drawn in 3D effect */ +#define FT8XX_OPT_3D 0 +/** Co-processor option to decode the JPEG image to RGB565 format */ +#define FT8XX_OPT_RGB565 0 +/** Co-processor option to decode the JPEG image to L8 format, i.e., monochrome */ +#define FT8XX_OPT_MONO 1 +/** No display list commands generated for bitmap decoded from JPEG image */ +#define FT8XX_OPT_NODL 2 +/** Co-processor widget is drawn without 3D effect */ +#define FT8XX_OPT_FLAT 256 +/** The number is treated as 32 bit signed integer */ +#define FT8XX_OPT_SIGNED 256 +/** Co-processor widget centers horizontally */ +#define FT8XX_OPT_CENTERX 512 +/** Co-processor widget centers vertically */ +#define FT8XX_OPT_CENTERY 1024 +/** Co-processor widget centers horizontally and vertically */ +#define FT8XX_OPT_CENTER 1536 +/** The label on the Coprocessor widget is right justified */ +#define FT8XX_OPT_RIGHTX 2048 +/** Co-processor widget has no background drawn */ +#define FT8XX_OPT_NOBACK 4096 +/** Co-processor clock widget is drawn without hour ticks. + * Gauge widget is drawn without major and minor ticks. + */ +#define FT8XX_OPT_NOTICKS 8192 +/** Co-processor clock widget is drawn without hour and minutes hands, + * only seconds hand is drawn + */ +#define FT8XX_OPT_NOHM 16384 +/** The Co-processor gauge has no pointer */ +#define FT8XX_OPT_NOPOINTER 16384 +/** Co-processor clock widget is drawn without seconds hand */ +#define FT8XX_OPT_NOSECS 32768 +/** Co-processor clock widget is drawn without hour, minutes and seconds hands */ +#define FT8XX_OPT_NOHANDS 49152 + +/** + * @brief Execute a display list command by co-processor engine + * + * @param cmd Display list command to execute + */ +void ft8xx_copro_cmd(uint32_t cmd); + +/** + * @brief Start a new display list + */ +void ft8xx_copro_cmd_dlstart(void); + +/** + * @brief Swap the current display list + */ +void ft8xx_copro_cmd_swap(void); + +/** + * @brief Draw text + * + * By default (@p x, @p y) is the top-left pixel of the text and the value of + * @p options is zero. @ref FT8XX_OPT_CENTERX centers the text horizontally, + * @ref FT8XX_OPT_CENTERY centers it vertically. @ref FT8XX_OPT_CENTER centers + * the text in both directions. @ref FT8XX_OPT_RIGHTX right-justifies the text, + * so that the @p x is the rightmost pixel. + * + * @param x x-coordinate of text base, in pixels + * @param y y-coordinate of text base, in pixels + * @param font Font to use for text, 0-31. 16-31 are ROM fonts + * @param options Options to apply + * @param s Character string to display, terminated with a null character + */ +void ft8xx_copro_cmd_text(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + const char *s); + +/** + * @brief Draw a decimal number + * + * By default (@p x, @p y) is the top-left pixel of the text. + * @ref FT8XX_OPT_CENTERX centers the text horizontally, @ref FT8XX_OPT_CENTERY + * centers it vertically. @ref FT8XX_OPT_CENTER centers the text in both + * directions. @ref FT8XX_OPT_RIGHTX right-justifies the text, so that the @p x + * is the rightmost pixel. By default the number is displayed with no leading + * zeroes, but if a width 1-9 is specified in the @p options, then the number + * is padded if necessary with leading zeroes so that it has the given width. + * If @ref FT8XX_OPT_SIGNED is given, the number is treated as signed, and + * prefixed by a minus sign if negative. + * + * @param x x-coordinate of text base, in pixels + * @param y y-coordinate of text base, in pixels + * @param font Font to use for text, 0-31. 16-31 are ROM fonts + * @param options Options to apply + * @param n The number to display. + */ +void ft8xx_copro_cmd_number(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + int32_t n); + +/** + * @brief Execute the touch screen calibration routine + * + * The calibration procedure collects three touches from the touch screen, then + * computes and loads an appropriate matrix into REG_TOUCH_TRANSFORM_A-F. To + * use it, create a display list and then use CMD_CALIBRATE. The co-processor + * engine overlays the touch targets on the current display list, gathers the + * calibration input and updates REG_TOUCH_TRANSFORM_A-F. + * + * @param result Calibration result, written with 0 on failure of calibration + */ +void ft8xx_copro_cmd_calibrate(uint32_t *result); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_COPRO_H_ */ diff --git a/include/drivers/misc/ft8xx/ft8xx_dl.h b/include/drivers/misc/ft8xx/ft8xx_dl.h new file mode 100644 index 00000000000..c946797e5f5 --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx_dl.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX display list commands + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_DL_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_DL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx display list commands + * @defgroup ft8xx_dl FT8xx display list + * @ingroup ft8xx_interface + * @{ + */ + +/** Rectangular pixel arrays, in various color formats */ +#define FT8XX_BITMAPS 1U +/** Anti-aliased points, point radius is 1-256 pixels */ +#define FT8XX_POINTS 2U +/** + * Anti-aliased lines, with width from 0 to 4095 1/16th of pixel units. + * (width is from center of the line to boundary) + */ +#define FT8XX_LINES 3U +/** Anti-aliased lines, connected head-to-tail */ +#define FT8XX_LINE_STRIP 4U +/** Edge strips for right */ +#define FT8XX_EDGE_STRIP_R 5U +/** Edge strips for left */ +#define FT8XX_EDGE_STRIP_L 6U +/** Edge strips for above */ +#define FT8XX_EDGE_STRIP_A 7U +/** Edge strips for below */ +#define FT8XX_EDGE_STRIP_B 8U +/** + * Round-cornered rectangles, curvature of the corners can be adjusted using + * FT8XX_LINE_WIDTH + */ +#define FT8XX_RECTS 9U + +/** + * @brief Begin drawing a graphics primitive + * + * The valid primitives are defined as: + * - @ref FT8XX_BITMAPS + * - @ref FT8XX_POINTS + * - @ref FT8XX_LINES + * - @ref FT8XX_LINE_STRIP + * - @ref FT8XX_EDGE_STRIP_R + * - @ref FT8XX_EDGE_STRIP_L + * - @ref FT8XX_EDGE_STRIP_A + * - @ref FT8XX_EDGE_STRIP_B + * - @ref FT8XX_RECTS + * + * The primitive to be drawn is selected by the @ref FT8XX_BEGIN command. Once + * the primitive is selected, it will be valid till the new primitive is + * selected by the @ref FT8XX_BEGIN command. + * + * @note The primitive drawing operation will not be performed until + * @ref FT8XX_VERTEX2II or @ref FT8XX_VERTEX2F is executed. + * + * @param prim Graphics primitive + */ +#define FT8XX_BEGIN(prim) (0x1f000000 | ((prim) & 0x0f)) + +/** + * @brief Clear buffers to preset values + * + * Setting @p c to true will clear the color buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the color buffer of the FT8xx + * with an unchanged value. The preset value is defined in command + * @ref FT8XX_CLEAR_COLOR_RGB for RGB channel and FT8XX_CLEAR_COLOR_A for alpha + * channel. + * + * Setting @p s to true will clear the stencil buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the stencil buffer of the + * FT8xx with an unchanged value. The preset value is defined in command + * FT8XX_CLEAR_STENCIL. + * + * Setting @p t to true will clear the tag buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the tag buffer of the FT8xx + * with an unchanged value. The preset value is defined in command + * FT8XX_CLEAR_TAG. + * + * @param c Clear color buffer + * @param s Clear stencil buffer + * @param t Clear tag buffer + */ +#define FT8XX_CLEAR(c, s, t) (0x26000000 | \ + ((c) ? 0x04 : 0) | ((s) ? 0x02 : 0) | ((t) ? 0x01 : 0)) + +/** + * @brief Specify clear values for red, green and blue channels + * + * Sets the color values used by a following @ref FT8XX_CLEAR. + * + * @param red Red value used when the color buffer is cleared + * @param green Green value used when the color buffer is cleared + * @param blue Blue value used when the color buffer is cleared + */ +#define FT8XX_CLEAR_COLOR_RGB(red, green, blue) (0x02000000 | \ + (((uint32_t)(red) & 0xff) << 16) | \ + (((uint32_t)(green) & 0xff) << 8) | \ + ((uint32_t)(blue) & 0xff)) + +/** + * @brief Set the current color red, green and blue + * + * Sets red, green and blue values of the FT8xx color buffer which will be + * applied to the following draw operation. + * + * @param red Red value for the current color + * @param green Green value for the current color + * @param blue Blue value for the current color + */ +#define FT8XX_COLOR_RGB(red, green, blue) (0x04000000 | \ + (((uint32_t)(red) & 0xff) << 16) | \ + (((uint32_t)(green) & 0xff) << 8) | \ + ((uint32_t)(blue) & 0xff)) + +/** + * @brief End the display list + * + * FT8xx will ignore all the commands following this command. + */ +#define FT8XX_DISPLAY() 0 + +/** + * @brief End drawing a graphics primitive + * + * It is recommended to have an @ref FT8XX_END for each @ref FT8XX_BEGIN. + * Whereas advanced users can avoid the usage of @ref FT8XX_END in order to + * save extra graphics instructions in the display list RAM. + */ +#define FT8XX_END() 0x21000000 + +/** + * @brief Specify the width of lines to be drawn with primitive @ref FT8XX_LINES + * + * Sets the width of drawn lines. The width is the distance from the center of + * the line to the outermost drawn pixel, in units of 1/16 pixel. The valid + * range is from 16 to 4095 in terms of 1/16th pixel units. + * + * @note The @ref FT8XX_LINE_WIDTH command will affect the @ref FT8XX_LINES, + * @ref FT8XX_LINE_STRIP, @ref FT8XX_RECTS, @ref FT8XX_EDGE_STRIP_A /B/R/L + * primitives. + * + * @param width Line width in 1/16 pixel + */ +#define FT8XX_LINE_WIDTH(width) (0x0e000000 | ((uint32_t)(width) & 0xfff)) + +/** + * @brief Attach the tag value for the following graphics objects. + * + * The initial value of the tag buffer of the FT8xx is specified by command + * FT8XX_CLEAR_TAG and taken effect by command @ref FT8XX_CLEAR. @ref FT8XX_TAG + * command can specify the value of the tag buffer of the FT8xx that applies to + * the graphics objects when they are drawn on the screen. This tag value will + * be assigned to all the following objects, unless the FT8XX_TAG_MASK command + * is used to disable it. Once the following graphics objects are drawn, they + * are attached with the tag value successfully. When the graphics objects + * attached with the tag value are touched, the register + * @ref FT800_REG_TOUCH_TAG or @ref FT810_REG_TOUCH_TAG will be updated with the + * tag value of the graphics object being touched. If there is no @ref FT8XX_TAG + * commands in one display list, all the graphics objects rendered by the + * display list will report tag value as 255 in @ref FT800_REG_TOUCH_TAG or + * @ref FT810_REG_TOUCH_TAG when they were touched. + * + * @param s Tag value 1-255 + */ +#define FT8XX_TAG(s) (0x03000000 | (uint8_t)(s)) + +/** + * @brief Start the operation of graphics primitives at the specified coordinate + * + * The range of coordinates is from -16384 to +16383 in terms of 1/16th pixel + * units. The negative x coordinate value means the coordinate in the left + * virtual screen from (0, 0), while the negative y coordinate value means the + * coordinate in the upper virtual screen from (0, 0). If drawing on the + * negative coordinate position, the drawing operation will not be visible. + * + * @param x Signed x-coordinate in 1/16 pixel precision + * @param y Signed y-coordinate in 1/16 pixel precision + */ +#define FT8XX_VERTEX2F(x, y) (0x40000000 | \ + (((int32_t)(x) & 0x7fff) << 15) | \ + ((int32_t)(y) & 0x7fff)) + +/** + * @brief Start the operation of graphics primitive at the specified coordinates + * + * The valid range of @p handle is from 0 to 31. From 16 to 31 the bitmap handle + * is dedicated to the FT8xx built-in font. + * + * Cell number is the index of bitmap with same bitmap layout and format. + * For example, for handle 31, the cell 65 means the character "A" in the + * largest built in font. + * + * @param x x-coordinate in pixels, from 0 to 511 + * @param y y-coordinate in pixels, from 0 to 511 + * @param handle Bitmap handle + * @param cell Cell number + */ +#define FT8XX_VERTEX2II(x, y, handle, cell) (0x80000000 | \ + (((uint32_t)(x) & 0x01ff) << 21) | \ + (((uint32_t)(y) & 0x01ff) << 12) | \ + (((uint32_t)(handle) & 0x1f) << 7) | \ + ((uint32_t)(cell) & 0x7f)) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_DL_H_ */ diff --git a/include/drivers/misc/ft8xx/ft8xx_memory.h b/include/drivers/misc/ft8xx/ft8xx_memory.h new file mode 100644 index 00000000000..9747cdc4b8f --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx_memory.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2020 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX memory map + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_MEMORY_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx memory addresses + * @defgroup ft8xx_memory FT8xx memory map + * @ingroup ft8xx_interface + * @{ + */ + +/** Main parts of FT800 memory map */ +enum ft800_memory_map_t { + FT800_RAM_G = 0x000000, + FT800_ROM_CHIPID = 0x0C0000, + FT800_ROM_FONT = 0x0BB23C, + FT800_ROM_FONT_ADDR = 0x0FFFFC, + FT800_RAM_DL = 0x100000, + FT800_RAM_PAL = 0x102000, + FT800_REG_ = 0x102400, + FT800_RAM_CMD = 0x108000 +}; + +/** Main parts of FT810 memory map */ +enum ft810_memory_map_t { + FT810_RAM_G = 0x000000, + FT810_RAM_DL = 0x300000, + FT810_REG_ = 0x302000, + FT810_RAM_CMD = 0x308000 +}; + +/** FT800 register addresses */ +enum ft800_register_address_t { + FT800_REG_ID = 0x102400, + FT800_REG_FRAMES = 0x102404, + FT800_REG_CLOCK = 0x102408, + FT800_REG_FREQUENCY = 0x10240C, + FT800_REG_RENDERMODE = 0x102410, + FT800_REG_SNAPY = 0x102414, + FT800_REG_SNAPSHOT = 0x102418, + FT800_REG_CPURESET = 0x10241C, + FT800_REG_TAP_CRC = 0x102420, + FT800_REG_TAP_MASK = 0x102424, + FT800_REG_HCYCLE = 0x102428, + FT800_REG_HOFFSET = 0x10242C, + FT800_REG_HSIZE = 0x102430, + FT800_REG_HSYNC0 = 0x102434, + FT800_REG_HSYNC1 = 0x102438, + FT800_REG_VCYCLE = 0x10243C, + FT800_REG_VOFFSET = 0x102440, + FT800_REG_VSIZE = 0x102444, + FT800_REG_VSYNC0 = 0x102448, + FT800_REG_VSYNC1 = 0x10244C, + FT800_REG_DLSWAP = 0x102450, + FT800_REG_ROTATE = 0x102454, + FT800_REG_OUTBITS = 0x102458, + FT800_REG_DITHER = 0x10245C, + FT800_REG_SWIZZLE = 0x102460, + FT800_REG_CSPREAD = 0x102464, + FT800_REG_PCLK_POL = 0x102468, + FT800_REG_PCLK = 0x10246C, + FT800_REG_TAG_X = 0x102470, + FT800_REG_TAG_Y = 0x102474, + FT800_REG_TAG = 0x102478, + FT800_REG_VOL_PB = 0x10247C, + FT800_REG_VOL_SOUND = 0x102480, + FT800_REG_SOUND = 0x102484, + FT800_REG_PLAY = 0x102488, + FT800_REG_GPIO_DIR = 0x10248C, + FT800_REG_GPIO = 0x102490, + + FT800_REG_INT_FLAGS = 0x102498, + FT800_REG_INT_EN = 0x10249C, + FT800_REG_INT_MASK = 0x1024A0, + FT800_REG_PLAYBACK_START = 0x1024A4, + FT800_REG_PLAYBACK_LENGTH = 0x1024A8, + FT800_REG_PLAYBACK_READPTR = 0x1024AC, + FT800_REG_PLAYBACK_FREQ = 0x1024B0, + FT800_REG_PLAYBACK_FORMAT = 0x1024B4, + FT800_REG_PLAYBACK_LOOP = 0x1024B8, + FT800_REG_PLAYBACK_PLAY = 0x1024BC, + FT800_REG_PWM_HZ = 0x1024C0, + FT800_REG_PWM_DUTY = 0x1024C4, + FT800_REG_MACRO_0 = 0x1024C8, + FT800_REG_MACRO_1 = 0x1024CC, + + FT800_REG_CMD_READ = 0x1024E4, + FT800_REG_CMD_WRITE = 0x1024E8, + FT800_REG_CMD_DL = 0x1024EC, + FT800_REG_TOUCH_MODE = 0x1024F0, + FT800_REG_TOUCH_ADC_MODE = 0x1024F4, + FT800_REG_TOUCH_CHARGE = 0x1024F8, + FT800_REG_TOUCH_SETTLE = 0x1024FC, + FT800_REG_TOUCH_OVERSAMPLE = 0x102500, + FT800_REG_TOUCH_RZTHRESH = 0x102504, + FT800_REG_TOUCH_RAW_XY = 0x102508, + FT800_REG_TOUCH_RZ = 0x10250C, + FT800_REG_TOUCH_SCREEN_XY = 0x102510, + FT800_REG_TOUCH_TAG_XY = 0x102514, + FT800_REG_TOUCH_TAG = 0x102518, + FT800_REG_TOUCH_TRANSFORM_A = 0x10251C, + FT800_REG_TOUCH_TRANSFORM_B = 0x102520, + FT800_REG_TOUCH_TRANSFORM_C = 0x102524, + FT800_REG_TOUCH_TRANSFORM_D = 0x102528, + FT800_REG_TOUCH_TRANSFORM_E = 0x10252C, + FT800_REG_TOUCH_TRANSFORM_F = 0x102530, + + FT800_REG_TOUCH_DIRECT_XY = 0x102574, + FT800_REG_TOUCH_DIRECT_Z1Z2 = 0x102578, + + FT800_REG_TRACKER = 0x109000 +}; + +/** FT810 register addresses */ +enum ft810_register_address_t { + FT810_REG_TRIM = 0x10256C, + + FT810_REG_ID = 0x302000, + FT810_REG_FRAMES = 0x302004, + FT810_REG_CLOCK = 0x302008, + FT810_REG_FREQUENCY = 0x30200C, + FT810_REG_RENDERMODE = 0x302010, + FT810_REG_SNAPY = 0x302014, + FT810_REG_SNAPSHOT = 0x302018, + FT810_REG_CPURESET = 0x302020, + FT810_REG_TAP_CRC = 0x302020, + FT810_REG_TAP_MASK = 0x302024, + FT810_REG_HCYCLE = 0x30202C, + FT810_REG_HOFFSET = 0x302030, + FT810_REG_HSIZE = 0x302034, + FT810_REG_HSYNC0 = 0x302038, + FT810_REG_HSYNC1 = 0x30203C, + FT810_REG_VCYCLE = 0x302040, + FT810_REG_VOFFSET = 0x302044, + FT810_REG_VSIZE = 0x302048, + FT810_REG_VSYNC0 = 0x30204C, + FT810_REG_VSYNC1 = 0x302050, + FT810_REG_DLSWAP = 0x302054, + FT810_REG_ROTATE = 0x302058, + FT810_REG_OUTBITS = 0x30205C, + FT810_REG_DITHER = 0x302060, + FT810_REG_SWIZZLE = 0x302064, + FT810_REG_CSPREAD = 0x302068, + FT810_REG_PCLK_POL = 0x30206C, + FT810_REG_PCLK = 0x302070, + FT810_REG_TAG_X = 0x302074, + FT810_REG_TAG_Y = 0x302078, + FT810_REG_TAG = 0x30207C, + FT810_REG_VOL_PB = 0x302080, + FT810_REG_VOL_SOUND = 0x302084, + FT810_REG_SOUND = 0x302088, + FT810_REG_PLAY = 0x30208C, + FT810_REG_GPIO_DIR = 0x302090, + FT810_REG_GPIO = 0x302094, + FT810_REG_GPIOX_DIR = 0x302098, + FT810_REG_GPIOX = 0x30209C, + + FT810_REG_INT_FLAGS = 0x3020A8, + FT810_REG_INT_EN = 0x3020AC, + FT810_REG_INT_MASK = 0x3020B0, + FT810_REG_PLAYBACK_START = 0x3020B4, + FT810_REG_PLAYBACK_LENGTH = 0x3020B8, + FT810_REG_PLAYBACK_READPTR = 0x3020BC, + FT810_REG_PLAYBACK_FREQ = 0x3020C0, + FT810_REG_PLAYBACK_FORMAT = 0x3020C4, + FT810_REG_PLAYBACK_LOOP = 0x3020C8, + FT810_REG_PLAYBACK_PLAY = 0x3020CC, + FT810_REG_PWM_HZ = 0x3020D0, + FT810_REG_PWM_DUTY = 0x3020D4, + + FT810_REG_CMD_READ = 0x3020F8, + FT810_REG_CMD_WRITE = 0x3020FC, + FT810_REG_CMD_DL = 0x302100, + FT810_REG_TOUCH_MODE = 0x302104, + FT810_REG_TOUCH_ADC_MODE = 0x302108, + FT810_REG_TOUCH_CHARGE = 0x30210C, + FT810_REG_TOUCH_SETTLE = 0x302110, + FT810_REG_TOUCH_OVERSAMPLE = 0x302114, + FT810_REG_TOUCH_RZTHRESH = 0x302118, + FT810_REG_TOUCH_RAW_XY = 0x30211C, + FT810_REG_TOUCH_RZ = 0x302120, + FT810_REG_TOUCH_SCREEN_XY = 0x302124, + FT810_REG_TOUCH_TAG_XY = 0x302128, + FT810_REG_TOUCH_TAG = 0x30212C, + FT810_REG_TOUCH_TRANSFORM_A = 0x302150, + FT810_REG_TOUCH_TRANSFORM_B = 0x302154, + FT810_REG_TOUCH_TRANSFORM_C = 0x302158, + FT810_REG_TOUCH_TRANSFORM_D = 0x30215C, + FT810_REG_TOUCH_TRANSFORM_E = 0x302160, + FT810_REG_TOUCH_TRANSFORM_F = 0x302164, + FT810_REG_TOUCH_CONFIG = 0x302168, + + FT810_REG_SPI_WIDTH = 0x302180, + + FT810_REG_TOUCH_DIRECT_XY = 0x30218C, + FT810_REG_TOUCH_DIRECT_Z1Z2 = 0x302190, + + FT810_REG_CMDB_SPACE = 0x302574, + FT810_REG_CMDB_WRITE = 0x302578, + + FT810_REG_TRACKER = 0x309000, + FT810_REG_TRACKER1 = 0x309004, + FT810_REG_TRACKER2 = 0x309008, + FT810_REG_TRACKER3 = 0x30900C, + FT810_REG_TRACKER4 = 0x309010, + FT810_REG_MEDIAFIFO_READ = 0x309014, + FT810_REG_MEDIAFIFO_WRITE = 0x309018, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_MEMORY_H_ */ diff --git a/include/drivers/misc/ft8xx/ft8xx_reference_api.h b/include/drivers/misc/ft8xx/ft8xx_reference_api.h new file mode 100644 index 00000000000..f9638a9558d --- /dev/null +++ b/include/drivers/misc/ft8xx/ft8xx_reference_api.h @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2021 Hubert Miś + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief FT8XX reference API + */ + +#ifndef ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_REFERENCE_API_H_ +#define ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_REFERENCE_API_H_ + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FT8xx reference API + * + * API defined according to FT800 Programmers Guide API reference definition. + * + * @note Function names defined in this header may easily collide with names + * provided by other modules. Include this header with caution. If naming + * conflict occurs instead of including this header, use @c ft8xx_ + * prefixed names. + * + * @defgroup ft8xx_reference_api FT8xx reference API + * @ingroup ft8xx_interface + * @{ + */ + +/** + * @brief Write 1 byte (8 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Byte to write + */ +static inline void wr8(uint32_t address, uint8_t data) +{ + ft8xx_wr8(address, data); +} + +/** + * @brief Write 2 bytes (16 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Value to write + */ +static inline void wr16(uint32_t address, uint16_t data) +{ + ft8xx_wr16(address, data); +} + +/** + * @brief Write 4 bytes (32 bits) to FT8xx memory + * + * @param address Memory address to write to + * @param data Value to write + */ +static inline void wr32(uint32_t address, uint32_t data) +{ + ft8xx_wr32(address, data); +} + +/** + * @brief Read 1 byte (8 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +static inline uint8_t rd8(uint32_t address) +{ + return ft8xx_rd8(address); +} + +/** + * @brief Read 2 bytes (16 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +static inline uint16_t rd16(uint32_t address) +{ + return ft8xx_rd16(address); +} + +/** + * @brief Read 4 bytes (32 bits) from FT8xx memory + * + * @param address Memory address to read from + * + * @return Value read from memory + */ +static inline uint32_t rd32(uint32_t address) +{ + return ft8xx_rd32(address); +} + + +/** Co-processor widget is drawn in 3D effect */ +#define OPT_3D FT8XX_OPT_3D +/** Co-processor option to decode the JPEG image to RGB565 format */ +#define OPT_RGB565 FT8XX_OPT_RGB565 +/** Co-processor option to decode the JPEG image to L8 format, i.e., monochrome */ +#define OPT_MONO FT8XX_OPT_MONO +/** No display list commands generated for bitmap decoded from JPEG image */ +#define OPT_NODL FT8XX_OPT_NODL +/** Co-processor widget is drawn without 3D effect */ +#define OPT_FLAT FT8XX_OPT_FLAT +/** The number is treated as 32 bit signed integer */ +#define OPT_SIGNED FT8XX_OPT_SIGNED +/** Co-processor widget centers horizontally */ +#define OPT_CENTERX FT8XX_OPT_CENTERX +/** Co-processor widget centers vertically */ +#define OPT_CENTERY FT8XX_OPT_CENTERY +/** Co-processor widget centers horizontally and vertically */ +#define OPT_CENTER FT8XX_OPT_CENTER +/** The label on the Coprocessor widget is right justified */ +#define OPT_RIGHTX FT8XX_OPT_RIGHTX +/** Co-processor widget has no background drawn */ +#define OPT_NOBACK FT8XX_OPT_NOBACK +/** Co-processor clock widget is drawn without hour ticks. + * Gauge widget is drawn without major and minor ticks. + */ +#define OPT_NOTICKS FT8XX_OPT_NOTICKS +/** Co-processor clock widget is drawn without hour and minutes hands, + * only seconds hand is drawn + */ +#define OPT_NOHM FT8XX_OPT_NOHM +/** The Co-processor gauge has no pointer */ +#define OPT_NOPOINTER FT8XX_OPT_NOPOINTER +/** Co-processor clock widget is drawn without seconds hand */ +#define OPT_NOSECS FT8XX_OPT_NOSECS +/** Co-processor clock widget is drawn without hour, minutes and seconds hands */ +#define OPT_NOHANDS FT8XX_OPT_NOHANDS + +/** + * @brief Execute a display list command by co-processor engine + * + * @param command Display list command to execute + */ +static inline void cmd(uint32_t command) +{ + ft8xx_copro_cmd(command); +} + +/** + * @brief Start a new display list + */ +static inline void cmd_dlstart(void) +{ + ft8xx_copro_cmd_dlstart(); +} + +/** + * @brief Swap the current display list + */ +static inline void cmd_swap(void) +{ + ft8xx_copro_cmd_swap(); +} + +/** + * @brief Draw text + * + * By default (x,y) is the top-left pixel of the text and the value of + * @p options is zero. OPT_CENTERX centers the text horizontally, OPT_CENTERY + * centers it vertically. OPT_CENTER centers the text in both directions. + * OPT_RIGHTX right-justifies the text, so that the x is the rightmost pixel. + * + * @param x x-coordinate of text base, in pixels + * @param y y-coordinate of text base, in pixels + * @param font Font to use for text, 0-31. 16-31 are ROM fonts + * @param options Options to apply + * @param s Character string to display, terminated with a null character + */ +static inline void cmd_text(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + const char *s) +{ + ft8xx_copro_cmd_text(x, y, font, options, s); +} + +/** + * @brief Draw a decimal number + * + * By default (@p x, @p y) is the top-left pixel of the text. OPT_CENTERX + * centers the text horizontally, OPT_CENTERY centers it vertically. OPT_CENTER + * centers the text in both directions. OPT_RIGHTX right-justifies the text, so + * that the @p x is the rightmost pixel. By default the number is displayed + * with no leading zeroes, but if a width 1-9 is specified in the @p options, + * then the number is padded if necessary with leading zeroes so that it has + * the given width. If OPT_SIGNED is given, the number is treated as signed, + * and prefixed by a minus sign if negative. + * + * @param x x-coordinate of text base, in pixels + * @param y y-coordinate of text base, in pixels + * @param font Font to use for text, 0-31. 16-31 are ROM fonts + * @param options Options to apply + * @param n The number to display. + */ +static inline void cmd_number(int16_t x, + int16_t y, + int16_t font, + uint16_t options, + int32_t n) +{ + ft8xx_copro_cmd_number(x, y, font, options, n); +} + +/** + * @brief Execute the touch screen calibration routine + * + * The calibration procedure collects three touches from the touch screen, then + * computes and loads an appropriate matrix into REG_TOUCH_TRANSFORM_A-F. To + * use it, create a display list and then use CMD_CALIBRATE. The co-processor + * engine overlays the touch targets on the current display list, gathers the + * calibration input and updates REG_TOUCH_TRANSFORM_A-F. + * + * @param result Calibration result, written with 0 on failure of calibration + */ +static inline void cmd_calibrate(uint32_t *result) +{ + ft8xx_copro_cmd_calibrate(result); +} + + +/** Rectangular pixel arrays, in various color formats */ +#define BITMAPS FT8XX_BITMAPS +/** Anti-aliased points, point radius is 1-256 pixels */ +#define POINTS FT8XX_POINTS +/** + * Anti-aliased lines, with width from 0 to 4095 1/16th of pixel units. + * (width is from center of the line to boundary) + */ +#define LINES FT8XX_LINES +/** Anti-aliased lines, connected head-to-tail */ +#define LINE_STRIP FT8XX_LINE_STRIP +/** Edge strips for right */ +#define EDGE_STRIP_R FT8XX_EDGE_STRIP_R +/** Edge strips for left */ +#define EDGE_STRIP_L FT8XX_EDGE_STRIP_L +/** Edge strips for above */ +#define EDGE_STRIP_A FT8XX_EDGE_STRIP_A +/** Edge strips for below */ +#define EDGE_STRIP_B FT8XX_EDGE_STRIP_B +/** + * Round-cornered rectangles, curvature of the corners can be adjusted using + * LINE_WIDTH + */ +#define RECTS FT8XX_RECTS + +/** + * @brief Begin drawing a graphics primitive + * + * The valid primitives are defined as: + * - @ref BITMAPS + * - @ref POINTS + * - @ref LINES + * - @ref LINE_STRIP + * - @ref EDGE_STRIP_R + * - @ref EDGE_STRIP_L + * - @ref EDGE_STRIP_A + * - @ref EDGE_STRIP_B + * - @ref RECTS + * + * The primitive to be drawn is selected by the @ref BEGIN command. Once the + * primitive is selected, it will be valid till the new primitive is selected + * by the @ref BEGIN command. + * + * @note The primitive drawing operation will not be performed until + * @ref VERTEX2II or @ref VERTEX2F is executed. + * + * @param prim Graphics primitive + */ +#define BEGIN(prim) FT8XX_BEGIN(prim) + +/** + * @brief Clear buffers to preset values + * + * Setting @p c to true will clear the color buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the color buffer of the FT8xx + * with an unchanged value. The preset value is defined in command + * @ref CLEAR_COLOR_RGB for RGB channel and CLEAR_COLOR_A for alpha channel. + * + * Setting @p s to true will clear the stencil buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the stencil buffer of the + * FT8xx with an unchanged value. The preset value is defined in command + * CLEAR_STENCIL. + * + * Setting @p t to true will clear the tag buffer of the FT8xx to the preset + * value. Setting this bit to false will maintain the tag buffer of the FT8xx + * with an unchanged value. The preset value is defined in command CLEAR_TAG. + * + * @param c Clear color buffer + * @param s Clear stencil buffer + * @param t Clear tag buffer + */ +#define CLEAR(c, s, t) FT8XX_CLEAR(c, s, t) + +/** + * @brief Specify clear values for red, green and blue channels + * + * Sets the color values used by a following @ref CLEAR. + * + * @param red Red value used when the color buffer is cleared + * @param green Green value used when the color buffer is cleared + * @param blue Blue value used when the color buffer is cleared + */ +#define CLEAR_COLOR_RGB(red, green, blue) FT8XX_CLEAR_COLOR_RGB(red, green, blue) + +/** + * @brief Set the current color red, green and blue + * + * Sets red, green and blue values of the FT8xx color buffer which will be + * applied to the following draw operation. + * + * @param red Red value for the current color + * @param green Green value for the current color + * @param blue Blue value for the current color + */ +#define COLOR_RGB(red, green, blue) FT8XX_COLOR_RGB(red, green, blue) + +/** + * @brief End the display list + * + * FT8xx will ignore all the commands following this command. + */ +#define DISPLAY() FT8XX_DISPLAY() + +/** + * @brief End drawing a graphics primitive + * + * It is recommended to have an @ref END for each @ref BEGIN. Whereas advanced + * users can avoid the usage of @ref END in order to save extra graphics + * instructions in the display list RAM. + */ +#define END() FT8XX_END() + +/** + * @brief Specify the width of lines to be drawn with primitive @ref LINES + * + * Sets the width of drawn lines. The width is the distance from the center of + * the line to the outermost drawn pixel, in units of 1/16 pixel. The valid + * range is from 16 to 4095 in terms of 1/16th pixel units. + * + * @note The @ref LINE_WIDTH command will affect the @ref LINES, + * @ref LINE_STRIP, @ref RECTS, @ref EDGE_STRIP_A /B/R/L primitives. + * + * @param width Line width in 1/16 pixel + */ +#define LINE_WIDTH(width) FT8XX_LINE_WIDTH(width) + +/** + * @brief Attach the tag value for the following graphics objects. + * + * The initial value of the tag buffer of the FT8xx is specified by command + * CLEAR_TAG and taken effect by command @ref CLEAR. @ref TAG command can + * specify the value of the tag buffer of the FT8xx that applies to the graphics + * objects when they are drawn on the screen. This @ref TAG value will be + * assigned to all the following objects, unless the TAG_MASK command is used to + * disable it. Once the following graphics objects are drawn, they are attached + * with the tag value successfully. When the graphics objects attached with the + * tag value are touched, the register @ref REG_TOUCH_TAG will be updated with + * the tag value of the graphics object being touched. If there is no @ref TAG + * commands in one display list, all the graphics objects rendered by the + * display list will report tag value as 255 in @ref REG_TOUCH_TAG when they + * were touched. + * + * @param s Tag value 1-255 + */ +#define TAG(s) FT8XX_TAG(s) + +/** + * @brief Start the operation of graphics primitives at the specified coordinate + * + * The range of coordinates is from -16384 to +16383 in terms of 1/16th pixel + * units. The negative x coordinate value means the coordinate in the left + * virtual screen from (0, 0), while the negative y coordinate value means the + * coordinate in the upper virtual screen from (0, 0). If drawing on the + * negative coordinate position, the drawing operation will not be visible. + * + * @param x Signed x-coordinate in 1/16 pixel precision + * @param y Signed y-coordinate in 1/16 pixel precision + */ +#define VERTEX2F(x, y) FT8XX_VERTEX2F(x, y) + +/** + * @brief Start the operation of graphics primitive at the specified coordinates + * + * The valid range of @p handle is from 0 to 31. From 16 to 31 the bitmap handle + * is dedicated to the FT8xx built-in font. + * + * Cell number is the index of bitmap with same bitmap layout and format. + * For example, for handle 31, the cell 65 means the character "A" in the + * largest built in font. + * + * @param x x-coordinate in pixels, from 0 to 511 + * @param y y-coordinate in pixels, from 0 to 511 + * @param handle Bitmap handle + * @param cell Cell number + */ +#define VERTEX2II(x, y, handle, cell) FT8XX_VERTEX2II(x, y, handle, cell) + + +#if defined(CONFIG_FT800) +/** Main parts of FT800 memory map */ +enum ft8xx_memory_map_t { + RAM_G = FT800_RAM_G, + ROM_CHIPID = FT800_ROM_CHIPID, + ROM_FONT = FT800_ROM_FONT, + ROM_FONT_ADDR = FT800_ROM_FONT_ADDR, + RAM_DL = FT800_RAM_DL, + RAM_PAL = FT800_RAM_PAL, + REG_ = FT800_REG_, + RAM_CMD = FT800_RAM_CMD +}; +#else /* Definition of FT810 memory map */ +/** Main parts of FT810 memory map */ +enum ft8xx_memory_map_t { + RAM_G = FT810_RAM_G, + RAM_DL = FT810_RAM_DL, + REG_ = FT810_REG_, + RAM_CMD = FT810_RAM_CMD +}; +#endif + +#if defined(CONFIG_FT800) +/** FT800 register addresses */ +enum ft8xx_register_address_t { + REG_ID = FT800_REG_ID, + REG_FRAMES = FT800_REG_FRAMES, + REG_CLOCK = FT800_REG_CLOCK, + REG_FREQUENCY = FT800_REG_FREQUENCY, + REG_RENDERMODE = FT800_REG_RENDERMODE, + REG_SNAPY = FT800_REG_SNAPY, + REG_SNAPSHOT = FT800_REG_SNAPSHOT, + REG_CPURESET = FT800_REG_CPURESET, + REG_TAP_CRC = FT800_REG_TAP_CRC, + REG_TAP_MASK = FT800_REG_TAP_MASK, + REG_HCYCLE = FT800_REG_HCYCLE, + REG_HOFFSET = FT800_REG_HOFFSET, + REG_HSIZE = FT800_REG_HSIZE, + REG_HSYNC0 = FT800_REG_HSYNC0, + REG_HSYNC1 = FT800_REG_HSYNC1, + REG_VCYCLE = FT800_REG_VCYCLE, + REG_VOFFSET = FT800_REG_VOFFSET, + REG_VSIZE = FT800_REG_VSIZE, + REG_VSYNC0 = FT800_REG_VSYNC0, + REG_VSYNC1 = FT800_REG_VSYNC1, + REG_DLSWAP = FT800_REG_DLSWAP, + REG_ROTATE = FT800_REG_ROTATE, + REG_OUTBITS = FT800_REG_OUTBITS, + REG_DITHER = FT800_REG_DITHER, + REG_SWIZZLE = FT800_REG_SWIZZLE, + REG_CSPREAD = FT800_REG_CSPREAD, + REG_PCLK_POL = FT800_REG_PCLK_POL, + REG_PCLK = FT800_REG_PCLK, + REG_TAG_X = FT800_REG_TAG_X, + REG_TAG_Y = FT800_REG_TAG_Y, + REG_TAG = FT800_REG_TAG, + REG_VOL_PB = FT800_REG_VOL_PB, + REG_VOL_SOUND = FT800_REG_VOL_SOUND, + REG_SOUND = FT800_REG_SOUND, + REG_PLAY = FT800_REG_PLAY, + REG_GPIO_DIR = FT800_REG_GPIO_DIR, + REG_GPIO = FT800_REG_GPIO, + + REG_INT_FLAGS = FT800_REG_INT_FLAGS, + REG_INT_EN = FT800_REG_INT_EN, + REG_INT_MASK = FT800_REG_INT_MASK, + REG_PLAYBACK_START = FT800_REG_PLAYBACK_START, + REG_PLAYBACK_LENGTH = FT800_REG_PLAYBACK_LENGTH, + REG_PLAYBACK_READPTR = FT800_REG_PLAYBACK_READPTR, + REG_PLAYBACK_FREQ = FT800_REG_PLAYBACK_FREQ, + REG_PLAYBACK_FORMAT = FT800_REG_PLAYBACK_FORMAT, + REG_PLAYBACK_LOOP = FT800_REG_PLAYBACK_LOOP, + REG_PLAYBACK_PLAY = FT800_REG_PLAYBACK_PLAY, + REG_PWM_HZ = FT800_REG_PWM_HZ, + REG_PWM_DUTY = FT800_REG_PWM_DUTY, + REG_MACRO_0 = FT800_REG_MACRO_0, + REG_MACRO_1 = FT800_REG_MACRO_1, + + REG_CMD_READ = FT800_REG_CMD_READ, + REG_CMD_WRITE = FT800_REG_CMD_WRITE, + REG_CMD_DL = FT800_REG_CMD_DL, + REG_TOUCH_MODE = FT800_REG_TOUCH_MODE, + REG_TOUCH_ADC_MODE = FT800_REG_TOUCH_ADC_MODE, + REG_TOUCH_CHARGE = FT800_REG_TOUCH_CHARGE, + REG_TOUCH_SETTLE = FT800_REG_TOUCH_SETTLE, + REG_TOUCH_OVERSAMPLE = FT800_REG_TOUCH_OVERSAMPLE, + REG_TOUCH_RZTHRESH = FT800_REG_TOUCH_RZTHRESH, + REG_TOUCH_RAW_XY = FT800_REG_TOUCH_RAW_XY, + REG_TOUCH_RZ = FT800_REG_TOUCH_RZ, + REG_TOUCH_SCREEN_XY = FT800_REG_TOUCH_SCREEN_XY, + REG_TOUCH_TAG_XY = FT800_REG_TOUCH_TAG_XY, + REG_TOUCH_TAG = FT800_REG_TOUCH_TAG, + REG_TOUCH_TRANSFORM_A = FT800_REG_TOUCH_TRANSFORM_A, + REG_TOUCH_TRANSFORM_B = FT800_REG_TOUCH_TRANSFORM_B, + REG_TOUCH_TRANSFORM_C = FT800_REG_TOUCH_TRANSFORM_C, + REG_TOUCH_TRANSFORM_D = FT800_REG_TOUCH_TRANSFORM_D, + REG_TOUCH_TRANSFORM_E = FT800_REG_TOUCH_TRANSFORM_E, + REG_TOUCH_TRANSFORM_F = FT800_REG_TOUCH_TRANSFORM_F, + + REG_TOUCH_DIRECT_XY = FT800_REG_TOUCH_DIRECT_XY, + REG_TOUCH_DIRECT_Z1Z2 = FT800_REG_TOUCH_DIRECT_Z1Z2, + + REG_TRACKER = FT800_REG_TRACKER +}; +#else /* Definition of FT810 registers */ +/** FT810 register addresses */ +enum ft8xx_register_address_t { + REG_TRIM = FT810_REG_TRIM, + + REG_ID = FT810_REG_ID, + REG_FRAMES = FT810_REG_FRAMES, + REG_CLOCK = FT810_REG_CLOCK, + REG_FREQUENCY = FT810_REG_FREQUENCY, + REG_RENDERMODE = FT810_REG_RENDERMODE, + REG_SNAPY = FT810_REG_SNAPY, + REG_SNAPSHOT = FT810_REG_SNAPSHOT, + REG_CPURESET = FT810_REG_CPURESET, + REG_TAP_CRC = FT810_REG_TAP_CRC, + REG_TAP_MASK = FT810_REG_TAP_MASK, + REG_HCYCLE = FT810_REG_HCYCLE, + REG_HOFFSET = FT810_REG_HOFFSET, + REG_HSIZE = FT810_REG_HSIZE, + REG_HSYNC0 = FT810_REG_HSYNC0, + REG_HSYNC1 = FT810_REG_HSYNC1, + REG_VCYCLE = FT810_REG_VCYCLE, + REG_VOFFSET = FT810_REG_VOFFSET, + REG_VSIZE = FT810_REG_VSIZE, + REG_VSYNC0 = FT810_REG_VSYNC0, + REG_VSYNC1 = FT810_REG_VSYNC1, + REG_DLSWAP = FT810_REG_DLSWAP, + REG_ROTATE = FT810_REG_ROTATE, + REG_OUTBITS = FT810_REG_OUTBITS, + REG_DITHER = FT810_REG_DITHER, + REG_SWIZZLE = FT810_REG_SWIZZLE, + REG_CSPREAD = FT810_REG_CSPREAD, + REG_PCLK_POL = FT810_REG_PCLK_POL, + REG_PCLK = FT810_REG_PCLK, + REG_TAG_X = FT810_REG_TAG_X, + REG_TAG_Y = FT810_REG_TAG_Y, + REG_TAG = FT810_REG_TAG, + REG_VOL_PB = FT810_REG_VOL_PB, + REG_VOL_SOUND = FT810_REG_VOL_SOUND, + REG_SOUND = FT810_REG_SOUND, + REG_PLAY = FT810_REG_PLAY, + REG_GPIO_DIR = FT810_REG_GPIO_DIR, + REG_GPIO = FT810_REG_GPIO, + REG_GPIOX_DIR = FT810_REG_GPIOX_DIR, + REG_GPIOX = FT810_REG_GPIOX, + + REG_INT_FLAGS = FT810_REG_INT_FLAGS, + REG_INT_EN = FT810_REG_INT_EN, + REG_INT_MASK = FT810_REG_INT_MASK, + REG_PLAYBACK_START = FT810_REG_PLAYBACK_START, + REG_PLAYBACK_LENGTH = FT810_REG_PLAYBACK_LENGTH, + REG_PLAYBACK_READPTR = FT810_REG_PLAYBACK_READPTR, + REG_PLAYBACK_FREQ = FT810_REG_PLAYBACK_FREQ, + REG_PLAYBACK_FORMAT = FT810_REG_PLAYBACK_FORMAT, + REG_PLAYBACK_LOOP = FT810_REG_PLAYBACK_LOOP, + REG_PLAYBACK_PLAY = FT810_REG_PLAYBACK_PLAY, + REG_PWM_HZ = FT810_REG_PWM_HZ, + REG_PWM_DUTY = FT810_REG_PWM_DUTY, + + REG_CMD_READ = FT810_REG_CMD_READ, + REG_CMD_WRITE = FT810_REG_CMD_WRITE, + REG_CMD_DL = FT810_REG_CMD_DL, + REG_TOUCH_MODE = FT810_REG_TOUCH_MODE, + REG_TOUCH_ADC_MODE = FT810_REG_TOUCH_ADC_MODE, + REG_TOUCH_CHARGE = FT810_REG_TOUCH_CHARGE, + REG_TOUCH_SETTLE = FT810_REG_TOUCH_SETTLE, + REG_TOUCH_OVERSAMPLE = FT810_REG_TOUCH_OVERSAMPLE, + REG_TOUCH_RZTHRESH = FT810_REG_TOUCH_RZTHRESH, + REG_TOUCH_RAW_XY = FT810_REG_TOUCH_RAW_XY, + REG_TOUCH_RZ = FT810_REG_TOUCH_RZ, + REG_TOUCH_SCREEN_XY = FT810_REG_TOUCH_SCREEN_XY, + REG_TOUCH_TAG_XY = FT810_REG_TOUCH_TAG_XY, + REG_TOUCH_TAG = FT810_REG_TOUCH_TAG, + REG_TOUCH_TRANSFORM_A = FT810_REG_TOUCH_TRANSFORM_A, + REG_TOUCH_TRANSFORM_B = FT810_REG_TOUCH_TRANSFORM_B, + REG_TOUCH_TRANSFORM_C = FT810_REG_TOUCH_TRANSFORM_C, + REG_TOUCH_TRANSFORM_D = FT810_REG_TOUCH_TRANSFORM_D, + REG_TOUCH_TRANSFORM_E = FT810_REG_TOUCH_TRANSFORM_E, + REG_TOUCH_TRANSFORM_F = FT810_REG_TOUCH_TRANSFORM_F, + REG_TOUCH_CONFIG = FT810_REG_TOUCH_CONFIG, + + REG_SPI_WIDTH = FT810_REG_SPI_WIDTH, + + REG_TOUCH_DIRECT_XY = FT810_REG_TOUCH_DIRECT_XY, + REG_TOUCH_DIRECT_Z1Z2 = FT810_REG_TOUCH_DIRECT_Z1Z2, + + REG_CMDB_SPACE = FT810_REG_CMDB_SPACE, + REG_CMDB_WRITE = FT810_REG_CMDB_WRITE, + + REG_TRACKER = FT810_REG_TRACKER, + REG_TRACKER1 = FT810_REG_TRACKER1, + REG_TRACKER2 = FT810_REG_TRACKER2, + REG_TRACKER3 = FT810_REG_TRACKER3, + REG_TRACKER4 = FT810_REG_TRACKER4, + REG_MEDIAFIFO_READ = FT810_REG_MEDIAFIFO_READ, + REG_MEDIAFIFO_WRITE = FT810_REG_MEDIAFIFO_WRITE, +}; +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_FT8XX_FT8XX_REFERENCE_API_H_ */