From ef4dcb8eec06427248c071ccd0a7599ba4feac0e Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Mon, 17 Sep 2018 10:26:31 +0200 Subject: [PATCH] ili9341: Initial include This commit adds support for the ili9341 display --- drivers/Makefile.dep | 5 + drivers/Makefile.include | 4 + drivers/ili9341/Makefile | 1 + drivers/ili9341/ili9341.c | 306 +++++++++++++++++++++ drivers/ili9341/include/ili9341_internal.h | 99 +++++++ drivers/ili9341/include/ili9341_params.h | 70 +++++ drivers/include/ili9341.h | 185 +++++++++++++ 7 files changed, 670 insertions(+) create mode 100644 drivers/ili9341/Makefile create mode 100644 drivers/ili9341/ili9341.c create mode 100644 drivers/ili9341/include/ili9341_internal.h create mode 100644 drivers/ili9341/include/ili9341_params.h create mode 100644 drivers/include/ili9341.h diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index fc7f9bee80..5c5b4824eb 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -219,6 +219,11 @@ ifneq (,$(filter hts221,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c endif +ifneq (,$(filter ili9341,$(USEMODULE))) + FEATURES_REQUIRED += periph_spi + FEATURES_REQUIRED += periph_gpio +endif + ifneq (,$(filter ina2%,$(USEMODULE))) USEMODULE += ina2xx endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 8ec41c5264..b95d46f1d6 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -114,6 +114,10 @@ ifneq (,$(filter hts221,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/hts221/include endif +ifneq (,$(filter ili9341,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ili9341/include +endif + ifneq (,$(filter ina2xx,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina2xx/include endif diff --git a/drivers/ili9341/Makefile b/drivers/ili9341/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/ili9341/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/ili9341/ili9341.c b/drivers/ili9341/ili9341.c new file mode 100644 index 0000000000..f0f6fcece3 --- /dev/null +++ b/drivers/ili9341/ili9341.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2018 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ili9341 + * @{ + * + * @file + * @brief Device driver implementation for the ili9341 display controller + * + * @author Koen Zandberg + * + * @} + */ + +#include +#include "byteorder.h" +#include "periph/spi.h" +#include "xtimer.h" +#include "ili9341.h" +#include "ili9341_internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static void _ili9341_spi_acquire(ili9341_t *dev) +{ + spi_acquire(dev->params->spi, dev->params->cs_pin, SPI_MODE_0, + dev->params->spi_clk); +} + +static void _ili9341_cmd_start(ili9341_t *dev, uint8_t cmd, bool cont) +{ + gpio_clear(dev->params->dcx_pin); + spi_transfer_byte(dev->params->spi, dev->params->cs_pin, cont, cmd); + gpio_set(dev->params->dcx_pin); +} + +/* datasheet page 178, table converted to equation. + * gvdd in 1mv increments: 4850 = 4.85V */ +static uint8_t _ili9341_calc_pwrctl1(uint16_t gvdd) +{ + return (gvdd - 2850) / 50; +} + +static uint8_t _ili9341_calc_vmh(uint16_t vcomh) +{ + return (vcomh - 2700) / 25; +} + +static uint8_t _ili9341_calc_vml(int16_t vcoml) +{ + return (vcoml + 2500) / 25; +} + +static void _write_cmd(ili9341_t *dev, uint8_t cmd, const uint8_t *data, + size_t len) +{ + _ili9341_cmd_start(dev, cmd, len ? true : false); + if (len) { + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, data, + NULL, len); + } +} + +static void _ili9341_set_area(ili9341_t *dev, uint16_t x1, uint16_t x2, + uint16_t y1, uint16_t y2) +{ + be_uint16_t params[2]; + + params[0] = byteorder_htons(x1); + params[1] = byteorder_htons(x2); + _write_cmd(dev, ILI9341_CMD_CASET, (uint8_t *)params, + sizeof(params)); + params[0] = byteorder_htons(y1); + params[1] = byteorder_htons(y2); + _write_cmd(dev, ILI9341_CMD_PASET, (uint8_t *)params, + sizeof(params)); +} + +int ili9341_init(ili9341_t *dev, const ili9341_params_t *params) +{ + dev->params = params; + uint8_t command_params[4] = { 0 }; + gpio_init(dev->params->dcx_pin, GPIO_OUT); + int res = spi_init_cs(dev->params->spi, dev->params->cs_pin); + if (res != SPI_OK) { + DEBUG("[ili9341] init: error initializing the CS pin [%i]\n", res); + return -1; + } + + if (dev->params->rst_pin != GPIO_UNDEF) { + gpio_init(dev->params->rst_pin, GPIO_OUT); + gpio_clear(dev->params->rst_pin); + xtimer_usleep(120 * US_PER_MS); + gpio_set(dev->params->rst_pin); + } + xtimer_usleep(120 * US_PER_MS); + + /* Acquire once at release at the end */ + _ili9341_spi_acquire(dev); + /* Soft Reset */ + _write_cmd(dev, ILI9341_CMD_SWRESET, NULL, 0); + xtimer_usleep(120 * US_PER_MS); + + /* Display off */ + _write_cmd(dev, ILI9341_CMD_DISPOFF, NULL, 0); + + /* PWRCTL1/2 */ + command_params[0] = _ili9341_calc_pwrctl1(ILI9341_GVDD); + _write_cmd(dev, ILI9341_CMD_PWCTRL1, command_params, 1); + + command_params[0] = 0x10; /* PWRCTL 0 0 0 */ + _write_cmd(dev, ILI9341_CMD_PWCTRL2, command_params, 1); + + /* VCOMCTL */ + command_params[0] = _ili9341_calc_vmh(ILI9341_VCOMH); + command_params[1] = _ili9341_calc_vml(ILI9341_VCOML); + _write_cmd(dev, ILI9341_CMD_VMCTRL1, command_params, 2); + + command_params[0] = 0x86; + _write_cmd(dev, ILI9341_CMD_VMCTRL2, command_params, 1); + + /* Memory access CTL */ + command_params[0] = ILI9341_MADCTL_HORZ_FLIP | ILI9341_MADCTL_BGR; + _write_cmd(dev, ILI9341_CMD_MADCTL, command_params, 1); + + /* Frame control */ + command_params[0] = 0x00; + command_params[1] = 0x18; + _write_cmd(dev, ILI9341_CMD_FRAMECTL1, command_params, 2); + + /* Display function control */ + command_params[0] = 0x08; + command_params[1] = 0x82; + command_params[2] = 0x27; /* 320 lines */ + _write_cmd(dev, ILI9341_CMD_DFUNC, command_params, 3); + + + /* Pixel format */ + command_params[0] = 0x55; /* 16 bit mode */ + _write_cmd(dev, ILI9341_CMD_PIXSET, command_params, 1); + + + command_params[0] = 0x01; + _write_cmd(dev, ILI9341_CMD_GAMSET, command_params, 1); + + /* Gamma correction */ + { + static const uint8_t gamma_pos[] = { + 0x0F, + 0x31, + 0x2B, + 0x0C, + 0x0E, + 0x08, + 0x4E, + 0xF1, + 0x37, + 0x07, + 0x10, + 0x03, + 0x0E, + 0x09, + 0x00 + }; + _write_cmd(dev, ILI9341_CMD_PGAMCTRL, gamma_pos, + sizeof(gamma_pos)); + } + { + static const uint8_t gamma_neg[] = { + 0x00, + 0x0E, + 0x14, + 0x03, + 0x11, + 0x07, + 0x31, + 0xC1, + 0x48, + 0x08, + 0x0F, + 0x0C, + 0x31, + 0x36, + 0x0F + }; + _write_cmd(dev, ILI9341_CMD_NGAMCTRL, gamma_neg, + sizeof(gamma_neg)); + + } + /* Sleep out (turn off sleep mode) */ + _write_cmd(dev, ILI9341_CMD_SLPOUT, NULL, 0); + /* Display on */ + _write_cmd(dev, ILI9341_CMD_DISPON, NULL, 0); + spi_release(dev->params->spi); + return 0; +} + +void ili9341_write_cmd(ili9341_t *dev, uint8_t cmd, const uint8_t *data, + size_t len) +{ + _ili9341_spi_acquire(dev); + _write_cmd(dev, cmd, data, len); + spi_release(dev->params->spi); +} + +void ili9341_read_cmd(ili9341_t *dev, uint8_t cmd, uint8_t *data, size_t len) +{ + assert(len); + _ili9341_spi_acquire(dev); + _ili9341_cmd_start(dev, cmd, true); + /* Dummy transfer */ + spi_transfer_byte(dev->params->spi, dev->params->cs_pin, true, 0x00); + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, NULL, + data, len); + spi_release(dev->params->spi); +} + + +void ili9341_fill(ili9341_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, + uint16_t y2, uint16_t color) +{ + /* Send fill area to the display */ + + /* Calculate number of pixels */ + int32_t num_pix = (x2 - x1 + 1) * (y2 - y1 + 1); + + DEBUG("[ili9341]: Write x1: %" PRIu16 ", x2: %" PRIu16 ", " + "y1: %" PRIu16 ", y2: %" PRIu16 ". Num pixels: %lu\n", + x1, x2, y1, y2, (unsigned long)num_pix); + + /* Send fill area to the display */ + _ili9341_spi_acquire(dev); + + _ili9341_set_area(dev, x1, x2, y1, y2); + /* Memory access command */ + _ili9341_cmd_start(dev, ILI9341_CMD_RAMWR, true); +#if ILI9341_LE_MODE + color = htons(color); +#endif + for (int i = 0; i < (num_pix - 1); i++) { + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, true, + (uint8_t *)&color, NULL, sizeof(color)); + } + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, + (uint8_t *)&color, NULL, sizeof(color)); + spi_release(dev->params->spi); +} + +void ili9341_pixmap(ili9341_t *dev, uint16_t x1, uint16_t x2, + uint16_t y1, uint16_t y2, const uint16_t *color) +{ + size_t num_pix = (x2 - x1 + 1) * (y2 - y1 + 1); + + DEBUG("[ili9341]: Write x1: %" PRIu16 ", x2: %" PRIu16 ", " + "y1: %" PRIu16 ", y2: %" PRIu16 ". Num pixels: %lu\n", + x1, x2, y1, y2, (unsigned long)num_pix); + + _ili9341_spi_acquire(dev); + + /* Send fill area to the display */ + _ili9341_set_area(dev, x1, x2, y1, y2); + + /* Memory access command */ + _ili9341_cmd_start(dev, ILI9341_CMD_RAMWR, true); + +#if ILI9341_LE_MODE + for (size_t i = 0; i < num_pix - 1; i++) { + uint16_t ncolor = htons(*(color + i)); + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, true, + &ncolor, NULL, sizeof(uint16_t)); + } + uint16_t ncolor = htons(*(color + num_pix - 1)); + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, + &ncolor, NULL, sizeof(uint16_t)); +#else + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, + (const uint8_t *)color, NULL, num_pix * 2); + +#endif + + spi_release(dev->params->spi); +} + +void ili9341_invert_on(ili9341_t *dev) +{ + ili9341_write_cmd(dev, ILI9341_CMD_DINVON, NULL, 0); +} + +void ili9341_invert_off(ili9341_t *dev) +{ + ili9341_write_cmd(dev, ILI9341_CMD_DINVOFF, NULL, 0); +} + +void ili9341_set_brightness(ili9341_t *dev, uint8_t brightness) +{ + ili9341_write_cmd(dev, ILI9341_CMD_WRDISBV, &brightness, 1); + uint8_t param = 0x26; + ili9341_write_cmd(dev, ILI9341_CMD_WRCTRLD, ¶m, 1); +} diff --git a/drivers/ili9341/include/ili9341_internal.h b/drivers/ili9341/include/ili9341_internal.h new file mode 100644 index 0000000000..3a65e63b6d --- /dev/null +++ b/drivers/ili9341/include/ili9341_internal.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ili9341 + * @{ + * + * @file + * @brief Device driver implementation for the ili9341 display controller + * + * @author Koen Zandberg + * + * @} + */ + +#ifndef ILI9341_INTERNAL_H +#define ILI9341_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name ILI9341 commands + * + * Not exhaustive, please extend when required + * @{ + */ +#define ILI9341_CMD_SWRESET 0x01 /**< Software reset */ +#define ILI9341_CMD_RDDIDIF 0x04 /**< Read display ID */ +#define ILI9341_CMD_SPLIN 0x10 /**< Enter sleep mode */ +#define ILI9341_CMD_SLPOUT 0x11 /**< Sleep out */ +#define ILI9341_CMD_DINVOFF 0x20 /**< Display inversion off */ +#define ILI9341_CMD_DINVON 0x21 /**< Display inversion on */ + +#define ILI9341_CMD_GAMSET 0x26 /**< Gamma Set */ +#define ILI9341_CMD_DISPOFF 0x28 /**< Display OFF */ +#define ILI9341_CMD_DISPON 0x29 /**< Display ON */ +#define ILI9341_CMD_CASET 0x2A /**< Column Address Set */ +#define ILI9341_CMD_PASET 0x2b /**< Page Address Set */ +#define ILI9341_CMD_RAMWR 0x2c /**< Memory Write */ +#define ILI9341_CMD_RAMRD 0x2e /**< Memory Read */ +#define ILI9341_CMD_MADCTL 0x36 /**< Memory data access control */ +#define ILI9341_CMD_IDMOFF 0x38 /**< Idle Mode OFF */ +#define ILI9341_CMD_IDMON 0x39 /**< Idle Mode ON */ +#define ILI9341_CMD_PIXSET 0x3A /**< COLMOD: Pixel Format Set */ +#define ILI9341_CMD_WRDISBV 0x51 /**< Write Display Brightness */ +#define ILI9341_CMD_WRCTRLD 0x53 /**< Write Control Display */ +#define ILI9341_CMD_RDCTRLD 0x54 /**< Read Control Display */ +#define ILI9341_CMD_FRAMECTL1 0xb1 /**< Frame control normal*/ +#define ILI9341_CMD_FRAMECTL2 0xb2 /**< Frame control idle */ +#define ILI9341_CMD_FRAMECTL3 0xb3 /**< Frame control partial */ +#define ILI9341_CMD_DFUNC 0xb6 /**< Display function control */ +#define ILI9341_CMD_PWCTRL1 0xc0 /**< Power control 1 */ +#define ILI9341_CMD_PWCTRL2 0xc1 /**< Power control 2 */ +#define ILI9341_CMD_VMCTRL1 0xc5 /**< VCOM control 1 */ +#define ILI9341_CMD_VMCTRL2 0xc7 /**< VCOM control 2 */ +#define ILI9341_CMD_PGAMCTRL 0xe0 /**< Positive gamma correction */ +#define ILI9341_CMD_NGAMCTRL 0xe1 /**< Negative gamma correction */ +#define ILI9341_CMD_IFCTL 0xf6 /**< Interface control */ +/** @} */ + +/** + * @name Memory access control bits + * @{ + */ +#define ILI9341_MADCTL_MY 0x80 /**< Row address order */ +#define ILI9341_MADCTL_MX 0x40 /**< Column access order */ +#define ILI9341_MADCTL_MV 0x20 /**< Row column exchange */ +#define ILI9341_MADCTL_ML 0x10 /**< Vertical refresh order */ +#define ILI9341_MADCTL_BGR 0x08 /**< Color selector switch control */ +#define ILI9341_MADCTL_MH 0x04 /**< Horizontal refresh direction */ +/** @} */ + +/** + * @name Display rotation modes + * @{ + */ +#define ILI9341_MADCTL_VERT ILI9341_MADCTL_MX /**< Vertical mode */ +#define ILI9341_MADCTL_VERT_FLIP ILI9341_MADCTL_MY /**< Flipped vertical */ +#define ILI9341_MADCTL_HORZ ILI9341_MADCTL_MV /**< Horizontal mode */ +#define ILI9341_MADCTL_HORZ_FLIP ILI9341_MADCTL_MV | \ + ILI9341_MADCTL_MY | \ + ILI9341_MADCTL_MX /**< Horizontal flipped */ +/** @} */ + +#define ILI9341_PIXSET_16BIT 0x55 /**< MCU and RGB 16 bit interface */ +#define ILI9341_PIXSET_18BIT 0x66 /**< MCU and RGB 18 bit interface (not implemented) */ + +#ifdef __cplusplus +} +#endif + +#endif /* ILI9341_INTERNAL_H */ diff --git a/drivers/ili9341/include/ili9341_params.h b/drivers/ili9341/include/ili9341_params.h new file mode 100644 index 0000000000..6300c87d59 --- /dev/null +++ b/drivers/ili9341/include/ili9341_params.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ili9341 + * + * @{ + * @file + * @brief Default configuration for ili9341 + * + * @author Koen Zandberg + */ + +#ifndef ILI9341_PARAMS_H +#define ILI9341_PARAMS_H + +#include "board.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Default parameters for ILI9341 display */ +/** + * @name Set default configuration parameters for the ILI9341 + * @{ + */ +#ifndef ILI9341_PARAM_SPI +#define ILI9341_PARAM_SPI SPI_DEV(0) +#endif +#ifndef ILI9341_PARAM_SPI_CLK +#define ILI9341_PARAM_SPI_CLK SPI_CLK_5MHZ +#endif +#ifndef ILI9341_PARAM_CS +#define ILI9341_PARAM_CS GPIO_PIN(2, 2) +#endif +#ifndef ILI9341_PARAM_DCX +#define ILI9341_PARAM_DCX GPIO_PIN(3, 13) +#endif +#ifndef ILI9341_PARAM_RST +#define ILI9341_PARAM_RST GPIO_UNDEF +#endif + +#ifndef ILI9341_PARAMS +#define ILI9341_PARAMS { .spi = ILI9341_PARAM_SPI, \ + .spi_clk = ILI9341_PARAM_SPI_CLK, \ + .cs_pin = ILI9341_PARAM_CS, \ + .dcx_pin = ILI9341_PARAM_DCX, \ + .rst_pin = ILI9341_PARAM_RST } +#endif +/**@}*/ + +/** + * @brief Configure ILI9341 + */ +static const ili9341_params_t ili9341_params[] = +{ + ILI9341_PARAMS, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ILI9341_PARAMS_H */ diff --git a/drivers/include/ili9341.h b/drivers/include/ili9341.h new file mode 100644 index 0000000000..0679dd326c --- /dev/null +++ b/drivers/include/ili9341.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2018 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_ili9341 ili9341 display driver + * @ingroup drivers + * + * @brief ili9341 Display driver + * + * @{ + * + * @file + * @brief Driver for ili941 display + * + * @author Koen Zandberg + * + * The ILI9341 is a generic display driver for small RGB displays. The driver + * implemented here operates over SPI to communicate with the device. + * + * The device requires colors to be send in big endian RGB-565 format. The + * @ref ILI9341_LE_MODE compile time option can switch this, but only use this + * when strictly necessary. This option will slow down the driver as it + * certainly can't use DMA anymore, every short has to be converted before + * transfer. + */ + + +#ifndef ILI9341_H +#define ILI9341_H + +#include "periph/spi.h" +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ILI9341_GVDD +/** + * @brief ili9341 gvdd level. + * + * Default GVDD voltage of 4.8V + */ +#define ILI9341_GVDD 4800 + +#endif /* ILI9341_GVDD */ + +#ifndef ILI9341_VCOMH +/** + * @brief ili9341 VCOMH voltage level. + * + * Default VCOMH voltage of 4.25V + */ +#define ILI9341_VCOMH 4250 + +#endif /* ILI9341_VCOMH */ + +#ifndef ILI9341_VCOML +/** + * @brief ili9341 VCOML voltage level. + * + * Default VCOMH voltage of -2V + */ +#define ILI9341_VCOML -2000 + +#endif /* ILI9341_VCOML */ + +#ifndef ILI9341_LE_MODE +/** + * @brief Compile time switch to change the driver to convert little endian + * colors to big endian. + */ +#define ILI9341_LE_MODE (0) +#endif + +/** + * @brief Device initialization parameters + */ +typedef struct { + spi_t spi; /**< SPI device that the display is connected to */ + spi_clk_t spi_clk; /**< SPI clock speed to use */ + gpio_t cs_pin; /**< pin connected to the CHIP SELECT line */ + gpio_t dcx_pin; /**< pin connected to the DC line */ + gpio_t rst_pin; /**< pin connected to the reset line */ +} ili9341_params_t; + +/** + * @brief Device descriptor for a ili9341 + */ +typedef struct { + const ili9341_params_t *params; /**< Device initialization parameters */ +} ili9341_t; + + +/** + * @brief Setup an ili9341 display device + * + * @param[out] dev device descriptor + * @param[in] params parameters for device initialization + */ +int ili9341_init(ili9341_t *dev, const ili9341_params_t *params); + +/** + * @brief Fill a rectangular area with a single pixel color + * + * the rectangular area is defined as x1 being the first column of pixels and + * x2 being the last column of pixels to fill. similar to that, y1 is the first + * row to fill and y2 is the last row to fill. + * + * @param[in] dev device descriptor + * @param[in] x1 x coordinate of the first corner + * @param[in] x2 x coordinate of the opposite corner + * @param[in] y1 y coordinate of the first corner + * @param[in] y2 y coordinate of the opposite corner + * @param[in] color single color to fill the area with + */ +void ili9341_fill(ili9341_t *dev, uint16_t x1, uint16_t x2, + uint16_t y1, uint16_t y2, uint16_t color); + +/** + * @brief Fill a rectangular area with an array of pixels + * + * the rectangular area is defined as x1 being the first column of pixels and + * x2 being the last column of pixels to fill. similar to that, y1 is the first + * row to fill and y2 is the last row to fill. + * + * @note @p color must have a length equal to `(x2 - x1 + 1) * (y2 - y1 + 1)` + * + * @param[in] dev device descriptor + * @param[in] x1 x coordinate of the first corner + * @param[in] x2 x coordinate of the opposite corner + * @param[in] y1 y coordinate of the first corner + * @param[in] y2 y coordinate of the opposite corner + * @param[in] color array of colors to fill the area with + */ +void ili9341_pixmap(ili9341_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, + uint16_t y2, const uint16_t *color); + +/** + * @brief Raw write command + * + * @param[in] dev device descriptor + * @param[in] cmd command code + * @param[in] data command data to the device + * @param[in] len length of the command data + */ +void ili9341_write_cmd(ili9341_t *dev, uint8_t cmd, const uint8_t *data, + size_t len); + +/** + * @brief Raw read command + * + * @pre len > 0 + * + * @param[in] dev device descriptor + * @param[in] cmd command + * @param[out] data data from the device + * @param[in] len length of the returned data + */ +void ili9341_read_cmd(ili9341_t *dev, uint8_t cmd, uint8_t *data, size_t len); + +/** + * @brief Invert the display colors + * + * @param[in] dev device descriptor + */ +void ili9341_invert_on(ili9341_t *dev); + +/** + * @brief Disable color inversion + * + * @param[in] dev device descriptor + */ +void ili9341_invert_off(ili9341_t *dev); + +#ifdef __cplusplus +} +#endif +#endif /* ILI9341_H */ +/** @} */