From 4caa8007d68542e03fa3b239745a8e589d65caef Mon Sep 17 00:00:00 2001 From: Jan Van Winkel Date: Wed, 15 Aug 2018 14:12:46 +0200 Subject: [PATCH 1/4] drivers: display: Migrate to new logging subsystem Migrate from SYS_LOG to LOG logging mechanism. Signed-off-by: Jan Van Winkel --- drivers/display/Kconfig.ili9340 | 14 +++++++------- drivers/display/display_ili9340.c | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/display/Kconfig.ili9340 b/drivers/display/Kconfig.ili9340 index b7318bb28525cf..ceefa4f5c6e488 100644 --- a/drivers/display/Kconfig.ili9340 +++ b/drivers/display/Kconfig.ili9340 @@ -38,19 +38,19 @@ config ILI9340_SPI_FREQ help Frequency to be used to communicate with the ILI9340. -config SYS_LOG_ILI9340_LEVEL - int "ILI9340 Sys Log level" - depends on SYS_LOG +config LOG_ILI9340_LEVEL + int "ILI9340 Log level" + depends on LOG default 0 range 0 4 help Sets log level for ILI9340 display driver. Levels are: - 0 OFF: do not write - - 1 ERROR: only write SYS_LOG_ERR - - 2 WARNING: write SYS_LOG_WRN in addition to previous level - - 3 INFO: write SYS_LOG_INF in addition to previous levels - - 4 DEBUG: write SYS_LOG_DBG in addition to previous levels + - 1 ERROR: only write LOG_ERR + - 2 WARNING: write LOG_WRN in addition to previous level + - 3 INFO: write LOG_INF in addition to previous levels + - 4 DEBUG: write LOG_DBG in addition to previous levels config ILI9340_RESET_GPIO_PORT_NAME string "Reset GPIO controller port name" diff --git a/drivers/display/display_ili9340.c b/drivers/display/display_ili9340.c index 291214d7a5b571..e03c9884b16f39 100644 --- a/drivers/display/display_ili9340.c +++ b/drivers/display/display_ili9340.c @@ -6,9 +6,9 @@ #include "display_ili9340.h" #include -#define SYS_LOG_DOMAIN "ILI9340" -#define SYS_LOG_LEVEL CONFIG_SYS_LOG_ILI9340_LEVEL -#include +#define LOG_LEVEL CONFIG_LOG_ILI9340_LEVEL +#include +LOG_MODULE_REGISTER(display); #include #include @@ -36,11 +36,11 @@ int ili9340_init(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - SYS_LOG_DBG("Initializing display driver"); + LOG_DBG("Initializing display driver"); data->spi_dev = device_get_binding(CONFIG_ILI9340_SPI_DEV_NAME); if (data->spi_dev == NULL) { - SYS_LOG_ERR("Could not get SPI device for ILI9340"); + LOG_ERR("Could not get SPI device for ILI9340"); return -EPERM; } @@ -61,7 +61,7 @@ int ili9340_init(struct device *dev) data->reset_gpio = device_get_binding(CONFIG_ILI9340_RESET_GPIO_PORT_NAME); if (data->reset_gpio == NULL) { - SYS_LOG_ERR("Could not get GPIO port for ILI9340 reset"); + LOG_ERR("Could not get GPIO port for ILI9340 reset"); return -EPERM; } @@ -71,14 +71,14 @@ int ili9340_init(struct device *dev) data->command_data_gpio = device_get_binding(CONFIG_ILI9340_CMD_DATA_GPIO_PORT_NAME); if (data->command_data_gpio == NULL) { - SYS_LOG_ERR("Could not get GPIO port for ILI9340 command/data"); + LOG_ERR("Could not get GPIO port for ILI9340 command/data"); return -EPERM; } gpio_pin_configure(data->command_data_gpio, CONFIG_ILI9340_CMD_DATA_PIN, GPIO_DIR_OUT); - SYS_LOG_DBG("Resetting display driver"); + LOG_DBG("Resetting display driver"); gpio_pin_write(data->reset_gpio, CONFIG_ILI9340_RESET_PIN, 1); k_sleep(1); gpio_pin_write(data->reset_gpio, CONFIG_ILI9340_RESET_PIN, 0); @@ -86,10 +86,10 @@ int ili9340_init(struct device *dev) gpio_pin_write(data->reset_gpio, CONFIG_ILI9340_RESET_PIN, 1); k_sleep(5); - SYS_LOG_DBG("Initializing LCD"); + LOG_DBG("Initializing LCD"); ili9340_lcd_init(data); - SYS_LOG_DBG("Exiting sleep mode"); + LOG_DBG("Exiting sleep mode"); ili9340_exit_sleep(data); /* device_get_binding checks if driver_api is not zero before checking @@ -106,7 +106,7 @@ void ili9340_write_pixel(const struct device *dev, const u16_t x, const u16_t y, { u8_t rgb_data[] = {r, g, b}; - SYS_LOG_DBG("Writing pixel @ %dx%d (x,y)", x, y); + LOG_DBG("Writing pixel @ %dx%d (x,y)", x, y); ili9340_write_bitmap(dev, x, y, 1, 1, &rgb_data[0]); } @@ -116,7 +116,7 @@ void ili9340_write_bitmap(const struct device *dev, const u16_t x, { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - SYS_LOG_DBG("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)", w, h, x, y); + LOG_DBG("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)", w, h, x, y); ili9340_set_mem_area(data, x, y, w, h); ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *)rgb_data, 3 * w * h); @@ -126,7 +126,7 @@ void ili9340_display_on(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - SYS_LOG_DBG("Turning display on"); + LOG_DBG("Turning display on"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0); } @@ -134,7 +134,7 @@ void ili9340_display_off(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - SYS_LOG_DBG("Turning display off"); + LOG_DBG("Turning display off"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0); } From 9680d1038782164c8e38fe746f16a04ce4d4a851 Mon Sep 17 00:00:00 2001 From: Jan Van Winkel Date: Wed, 15 Aug 2018 14:15:06 +0200 Subject: [PATCH 2/4] samples: display: Migrate to new logging subsystem Migrate from SYS_LOG to LOG logging mechanism. Signed-off-by: Jan Van Winkel --- samples/display/ili9340/prj.conf | 8 ++------ samples/display/ili9340/src/main.c | 10 +++++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/samples/display/ili9340/prj.conf b/samples/display/ili9340/prj.conf index 42f6c741cb4ee5..c1e05fc59e9112 100644 --- a/samples/display/ili9340/prj.conf +++ b/samples/display/ili9340/prj.conf @@ -8,16 +8,12 @@ CONFIG_SPI_1=y CONFIG_DISPLAY=y CONFIG_ILI9340=y -CONFIG_SYS_LOG_ILI9340_LEVEL=4 +CONFIG_LOG_ILI9340_LEVEL=4 CONFIG_ILI9340_SPI_DEV_NAME="SPI_1" CONFIG_ILI9340_RESET_GPIO_PORT_NAME="GPIOA" CONFIG_ILI9340_RESET_PIN=9 CONFIG_ILI9340_CMD_DATA_GPIO_PORT_NAME="GPIOA" CONFIG_ILI9340_CMD_DATA_PIN=8 -CONFIG_SYS_LOG=y -CONFIG_SYS_LOG_SHOW_TAGS=y -CONFIG_SYS_LOG_SHOW_COLOR=y -CONFIG_SYS_LOG_DEFAULT_LEVEL=0 -CONFIG_SYS_LOG_OVERRIDE_LEVEL=0 +CONFIG_LOG=y diff --git a/samples/display/ili9340/src/main.c b/samples/display/ili9340/src/main.c index 7601e928b381ed..ea354aa3b772e2 100644 --- a/samples/display/ili9340/src/main.c +++ b/samples/display/ili9340/src/main.c @@ -10,9 +10,9 @@ #include #include -#define SYS_LOG_DOMAIN "main" -#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG -#include +#define LOG_LEVEL LOG_LEVEL_DEBUG +#include +LOG_MODULE_REGISTER(main); #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 @@ -49,7 +49,7 @@ void main(void) dev = device_get_binding("ILI9340"); if (dev == NULL) { - SYS_LOG_ERR("device not found. Aborting test."); + LOG_ERR("Device not found. Aborting test."); return; } @@ -57,7 +57,7 @@ void main(void) buf = k_malloc(buf_size); if (buf == NULL) { - SYS_LOG_ERR("Could not allocate memory. Aborting test."); + LOG_ERR("Could not allocate memory. Aborting test."); return; } From 4cf054cfb3e67694b674c1d5b9af1843e2d2d95f Mon Sep 17 00:00:00 2001 From: Jan Van Winkel Date: Mon, 9 Oct 2017 21:13:24 +0200 Subject: [PATCH 3/4] display: API for display driver API for display drivers, supporting: * Turning on/off display blanking * Writing/Reading a bit map towards/from the display * Requesting framebuffer pointer * Setting display contrast and brightness * Querying display capabilities * Changing pixel format * Changing display orientation Signed-off-by: Jan Van Winkel --- include/display.h | 389 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 include/display.h diff --git a/include/display.h b/include/display.h new file mode 100644 index 00000000000000..87bb1150223879 --- /dev/null +++ b/include/display.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017 Jan Van Winkel + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public API for display drivers and applications + */ + +#ifndef ZEPHYR_INCLUDE_DISPLAY_H_ +#define ZEPHYR_INCLUDE_DISPLAY_H_ + +/** + * @brief Display Interface + * @defgroup display_interface display Interface + * @ingroup io_interfaces + * @{ + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum display_pixel_format { + PIXEL_FORMAT_RGB_888 = (1 << 0), +}; + +/** + * @enum display_orientation + * @brief Enumeration with possible display orientation + * + */ +enum display_orientation { + DISPLAY_ORIENTATION_NORMAL, + DISPLAY_ORIENTATION_ROTATED_90, + DISPLAY_ORIENTATION_ROTATED_180, + DISPLAY_ORIENTATION_ROTATED_270, +}; + +/** + * @struct display_capabilities + * @brief Structure holding display capabilities + * + * @var display_capabilities::x_resolution + * Display resolution in the X direction + * + * @var display_capabilities::y_resolution + * Display resolution in the Y direction + * + * @var display_capabilities::supported_pixel_formats + * Bitwise or of pixel formats supported by the display + * + * @var display_capabilities::current_pixel_format + * Currently active pixel format for the display + * + * @var display_capabilities::current_orientation + * Current display orientation + * + */ +struct display_capabilities { + u16_t x_resolution; + u16_t y_resolution; + u32_t supported_pixel_formats; + enum display_pixel_format current_pixel_format; + enum display_orientation current_orientation; +}; + +/** + * @struct display_buffer_descriptor + * @brief Structure to describe display data buffer layout + * + * @var display_buffer_descriptor::buf_size + * Data buffer size in bytes + * + * @var display_buffer_descriptor::width + * Data buffer row width in pixels + * + * @var display_buffer_descriptor::height + * Data buffer column height in pixels + * + * @var display_buffer_descriptor::pitch + * Number of pixels between consecutive rows in the data buffer + * + */ +struct display_buffer_descriptor { + u32_t buf_size; + u16_t width; + u16_t height; + u16_t pitch; +}; + +/** + * @typedef display_blanking_on_api + * @brief Callback API to turn on display blanking + * See display_blanking_on() for argument description + */ +typedef int (*display_blanking_on_api)(const struct device *dev); + +/** + * @typedef display_blanking_off_api + * @brief Callback API to turn off display blanking + * See display_blanking_off() for argument description + */ +typedef int (*display_blanking_off_api)(const struct device *dev); + +/** + * @typedef display_write_api + * @brief Callback API for writing data to the display + * See display_write() for argument description + */ +typedef int (*display_write_api)(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + const void *buf); + +/** + * @typedef display_read_api + * @brief Callback API for reading data from the display + * See display_read() for argument description + */ +typedef int (*display_read_api)(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + void *buf); + +/** + * @typedef display_get_framebuffer_api + * @brief Callback API to get framebuffer pointer + * See display_get_framebuffer() for argument description + */ +typedef void *(*display_get_framebuffer_api)(const struct device *dev); + +/** + * @typedef display_set_brightness_api + * @brief Callback API to set display brightness + * See display_set_brightness() for argument description + */ +typedef int (*display_set_brightness_api)(const struct device *dev, + const u8_t brightness); + +/** + * @typedef display_set_contrast_api + * @brief Callback API to set display contrast + * See display_set_contrast() for argument description + */ +typedef int (*display_set_contrast_api)(const struct device *dev, + const u8_t contrast); + +/** + * @typedef display_get_capabilities_api + * @brief Callback API to get display capabilities + * See display_get_capabilities() for argument description + */ +typedef void (*display_get_capabilities_api)(const struct device *dev, + struct display_capabilities * + capabilities); + +/** + * @typedef display_set_pixel_format_api + * @brief Callback API to set pixel format used by the display + * See display_set_pixel_format() for argument description + */ +typedef int (*display_set_pixel_format_api)(const struct device *dev, + const enum display_pixel_format + pixel_format); + +/** + * @typedef display_set_orientation_api + * @brief Callback API to set orientation used by the display + * See display_set_orientation() for argument description + */ +typedef int (*display_set_orientation_api)(const struct device *dev, + const enum display_orientation + orientation); + +/** + * @brief Display driver API + * API which a display driver should expose + */ +struct display_driver_api { + display_blanking_on_api blanking_on; + display_blanking_off_api blanking_off; + display_write_api write; + display_read_api read; + display_get_framebuffer_api get_framebuffer; + display_set_brightness_api set_brightness; + display_set_contrast_api set_contrast; + display_get_capabilities_api get_capabilities; + display_set_pixel_format_api set_pixel_format; + display_set_orientation_api set_orientation; +}; + +/** + * @brief Write data to display + * + * @param dev Pointer to device structure + * @param x x Coordinate of the upper left corner where to write the buffer + * @param y y Coordinate of the upper left corner where to write the buffer + * @param desc Pointer to a structure describing the buffer layout + * @param buf Pointer to buffer array + * + * @retval 0 on success else negative errno code. + */ +static inline int display_write(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + const void *buf) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->write(dev, x, y, desc, buf); +} + +/** + * @brief Read data from display + * + * @param dev Pointer to device structure + * @param x x Coordinate of the upper left corner where to read from + * @param y y Coordinate of the upper left corner where to read from + * @param desc Pointer to a structure describing the buffer layout + * @param buf Pointer to buffer array + * + * @retval 0 on success else negative errno code. + */ +static inline int display_read(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + void *buf) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->read(dev, x, y, desc, buf); +} + +/** + * @brief Get pointer to framebuffer for direct access + * + * @param dev Pointer to device structure + * + * @retval Pointer to frame buffer or NULL if direct framebuffer access + * is not supported + * + */ +static inline void *display_get_framebuffer(const struct device *dev) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->get_framebuffer(dev); +} + +/** + * @brief Turn display blanking on + * + * @param dev Pointer to device structure + * + * @retval 0 on success else negative errno code. + */ +static inline int display_blanking_on(const struct device *dev) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->blanking_on(dev); +} + +/** + * @brief Turn display blanking off + * + * @param dev Pointer to device structure + * + * @retval 0 on success else negative errno code. + */ +static inline int display_blanking_off(const struct device *dev) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->blanking_off(dev); +} + +/** + * @brief Set the brightness of the display + * + * Set the brightness of the display in steps of 1/256, where 255 is full + * brightness and 0 is minimal. + * + * @param dev Pointer to device structure + * @param brightness Brightness in steps of 1/256 + * + * @retval 0 on success else negative errno code. + */ +static inline int display_set_brightness(const struct device *dev, + u8_t brightness) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->set_brightness(dev, brightness); +} + +/** + * @brief Set the contrast of the display + * + * Set the contrast of the display in steps of 1/256, where 255 is maximum + * difference and 0 is minimal. + * + * @param dev Pointer to device structure + * @param contrast Contrast in steps of 1/256 + * + * @retval 0 on success else negative errno code. + */ +static inline int display_set_contrast(const struct device *dev, u8_t contrast) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->set_contrast(dev, contrast); +} + +/** + * @brief Get display capabilities + * + * @param dev Pointer to device structure + * @param capabilities Pointer to capabilities structure to populate + */ +static inline void display_get_capabilities(const struct device *dev, + struct display_capabilities * + capabilities) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + api->get_capabilities(dev, capabilities); +} + +/** + * @brief Set pixel format used by the display + * + * @param dev Pointer to device structure + * @param pixel_format Pixel format to be used by display + * + * @retval 0 on success else negative errno code. + */ +static inline int +display_set_pixel_format(const struct device *dev, + const enum display_pixel_format pixel_format) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->set_pixel_format(dev, pixel_format); +} + +/** + * @brief Set display orientation + * + * @param dev Pointer to device structure + * @param orientation Orientation to be used by display + * + * @retval 0 on success else negative errno code. + */ +static inline int display_set_orientation(const struct device *dev, + const enum display_orientation + orientation) +{ + struct display_driver_api *api = + (struct display_driver_api *)dev->driver_api; + + return api->set_orientation(dev, orientation); +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DISPLAY_H_*/ From cfc62418ec1d343ac30b5f4f2ed07ec96c7fdb6b Mon Sep 17 00:00:00 2001 From: Jan Van Winkel Date: Mon, 9 Oct 2017 21:19:12 +0200 Subject: [PATCH 4/4] driver: Updated ILI9340 driver to use display API Updated ILI9340 display driver and sample application to make use off the display API Signed-off-by: Jan Van Winkel --- drivers/display/Kconfig.ili9340 | 2 +- drivers/display/Kconfig.microbit | 2 +- drivers/display/display_ili9340.c | 200 +++++++++++++----- drivers/display/display_ili9340.h | 3 +- .../display/display_ili9340_adafruit_1480.c | 3 +- include/drivers/display/ili9340.h | 8 +- samples/display/ili9340/src/main.c | 56 +++-- 7 files changed, 189 insertions(+), 85 deletions(-) diff --git a/drivers/display/Kconfig.ili9340 b/drivers/display/Kconfig.ili9340 index ceefa4f5c6e488..2fb272f542c872 100644 --- a/drivers/display/Kconfig.ili9340 +++ b/drivers/display/Kconfig.ili9340 @@ -1,7 +1,7 @@ # Kconfig - ILI9340 display driver configuration options # -# Copyright (c) 2017 dXplore +# Copyright (c) 2017 Jan Van Winkel # # SPDX-License-Identifier: Apache-2.0 # diff --git a/drivers/display/Kconfig.microbit b/drivers/display/Kconfig.microbit index ec60d935222f4d..ef46715d90ca78 100644 --- a/drivers/display/Kconfig.microbit +++ b/drivers/display/Kconfig.microbit @@ -1,7 +1,7 @@ # Kconfig - Microbit display driver configuration options # -# Copyright (c) 2017 dXplore +# Copyright (c) 2017 Jan Van Winkel # # SPDX-License-Identifier: Apache-2.0 # diff --git a/drivers/display/display_ili9340.c b/drivers/display/display_ili9340.c index e03c9884b16f39..bde1aa2994b664 100644 --- a/drivers/display/display_ili9340.c +++ b/drivers/display/display_ili9340.c @@ -1,10 +1,11 @@ -/* Copyright (c) 2017 dXplore +/* + * Copyright (c) 2017 Jan Van Winkel * * SPDX-License-Identifier: Apache-2.0 */ #include "display_ili9340.h" -#include +#include #define LOG_LEVEL CONFIG_LOG_ILI9340_LEVEL #include @@ -13,6 +14,7 @@ LOG_MODULE_REGISTER(display); #include #include #include +#include struct ili9340_data { struct device *reset_gpio; @@ -27,12 +29,13 @@ struct ili9340_data { #define ILI9340_CMD_DATA_PIN_COMMAND 0 #define ILI9340_CMD_DATA_PIN_DATA 1 -static void ili9340_exit_sleep(struct ili9340_data *data); -static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, - const u16_t y, const u16_t w, const u16_t h); -static int ili9340_init(struct device *dev); +static void ili9340_exit_sleep(struct ili9340_data *data) +{ + ili9340_transmit(data, ILI9340_CMD_EXIT_SLEEP, NULL, 0); + k_sleep(120); +} -int ili9340_init(struct device *dev) +static int ili9340_init(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; @@ -59,7 +62,7 @@ int ili9340_init(struct device *dev) #endif data->reset_gpio = - device_get_binding(CONFIG_ILI9340_RESET_GPIO_PORT_NAME); + device_get_binding(CONFIG_ILI9340_RESET_GPIO_PORT_NAME); if (data->reset_gpio == NULL) { LOG_ERR("Could not get GPIO port for ILI9340 reset"); return -EPERM; @@ -69,7 +72,7 @@ int ili9340_init(struct device *dev) GPIO_DIR_OUT); data->command_data_gpio = - device_get_binding(CONFIG_ILI9340_CMD_DATA_GPIO_PORT_NAME); + device_get_binding(CONFIG_ILI9340_CMD_DATA_GPIO_PORT_NAME); if (data->command_data_gpio == NULL) { LOG_ERR("Could not get GPIO port for ILI9340 command/data"); return -EPERM; @@ -92,57 +95,152 @@ int ili9340_init(struct device *dev) LOG_DBG("Exiting sleep mode"); ili9340_exit_sleep(data); - /* device_get_binding checks if driver_api is not zero before checking - * device name. - * So just set driver_api to 1 else the function call will fail - */ - dev->driver_api = (void *)1; - return 0; } -void ili9340_write_pixel(const struct device *dev, const u16_t x, const u16_t y, - const u8_t r, const u8_t g, const u8_t b) +static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, + const u16_t y, const u16_t w, const u16_t h) { - u8_t rgb_data[] = {r, g, b}; + u16_t spi_data[2]; - LOG_DBG("Writing pixel @ %dx%d (x,y)", x, y); - ili9340_write_bitmap(dev, x, y, 1, 1, &rgb_data[0]); + spi_data[0] = sys_cpu_to_be16(x); + spi_data[1] = sys_cpu_to_be16(x + w - 1); + ili9340_transmit(data, ILI9340_CMD_COLUMN_ADDR, &spi_data[0], 4); + + spi_data[0] = sys_cpu_to_be16(y); + spi_data[1] = sys_cpu_to_be16(y + h - 1); + ili9340_transmit(data, ILI9340_CMD_PAGE_ADDR, &spi_data[0], 4); } -void ili9340_write_bitmap(const struct device *dev, const u16_t x, - const u16_t y, const u16_t w, const u16_t h, - const u8_t *rgb_data) +static int ili9340_write(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + const void *buf) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; + const u8_t *write_data_start = (u8_t *) buf; + struct spi_buf tx_buf; + struct spi_buf_set tx_bufs; + u16_t write_cnt; + u16_t nbr_of_writes; + u16_t write_h; + + __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width"); + __ASSERT((3 * desc->pitch * desc->height) <= desc->bu_size, + "Input buffer to small"); + + LOG_DBG("Writing %dx%d (w,h) @ %dx%d (x,y)", desc->width, desc->height, + x, y); + ili9340_set_mem_area(data, x, y, desc->width, desc->height); + + if (desc->pitch > desc->width) { + write_h = 1; + nbr_of_writes = desc->height; + } else { + write_h = desc->height; + nbr_of_writes = 1; + } - LOG_DBG("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)", w, h, x, y); - ili9340_set_mem_area(data, x, y, w, h); - ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *)rgb_data, - 3 * w * h); + ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, + (void *) write_data_start, 3 * desc->width * write_h); + + tx_bufs.buffers = &tx_buf; + tx_bufs.count = 1; + + write_data_start += (3 * desc->pitch); + for (write_cnt = 1; write_cnt < nbr_of_writes; ++write_cnt) { + tx_buf.buf = (void *)write_data_start; + tx_buf.len = 3 * desc->width * write_h; + spi_write(data->spi_dev, &data->spi_config, &tx_bufs); + write_data_start += (3 * desc->pitch); + } + + return 0; +} + +static int ili9340_read(const struct device *dev, const u16_t x, + const u16_t y, + const struct display_buffer_descriptor *desc, + void *buf) +{ + LOG_ERR("Reading not supported"); + return -ENOTSUP; +} + +static void *ili9340_get_framebuffer(const struct device *dev) +{ + LOG_ERR("Direct framebuffer access not supported"); + return NULL; } -void ili9340_display_on(struct device *dev) +static int ili9340_display_blanking_off(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - LOG_DBG("Turning display on"); + LOG_DBG("Turning display blanking off"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0); + return 0; } -void ili9340_display_off(struct device *dev) +static int ili9340_display_blanking_on(const struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; - LOG_DBG("Turning display off"); + LOG_DBG("Turning display blanking on"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0); + return 0; +} + +static int ili9340_set_brightness(const struct device *dev, + const u8_t brightness) +{ + LOG_WRN("Set brightness not implemented"); + return -ENOTSUP; +} + +static int ili9340_set_contrast(const struct device *dev, const u8_t contrast) +{ + LOG_ERR("Set contrast not supported"); + return -ENOTSUP; +} + +static int ili9340_set_pixel_format(const struct device *dev, + const enum display_pixel_format + pixel_format) +{ + if (pixel_format == PIXEL_FORMAT_RGB_888) { + return 0; + } + LOG_ERR("Pixel format change not implemented"); + return -ENOTSUP; +} + +static int ili9340_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + return 0; + } + LOG_ERR("Changing display orientation not implemented"); + return -ENOTSUP; +} + +static void ili9340_get_capabilities(const struct device *dev, + struct display_capabilities *capabilities) +{ + memset(capabilities, 0, sizeof(struct display_capabilities)); + capabilities->x_resolution = 320; + capabilities->y_resolution = 240; + capabilities->supported_pixel_formats = PIXEL_FORMAT_RGB_888; + capabilities->current_pixel_format = PIXEL_FORMAT_RGB_888; + capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; } void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data, size_t tx_len) { - struct spi_buf tx_buf = {.buf = &cmd, .len = 1}; - struct spi_buf_set tx_bufs = {.buffers = &tx_buf, .count = 1}; + struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; + struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; gpio_pin_write(data->command_data_gpio, CONFIG_ILI9340_CMD_DATA_PIN, ILI9340_CMD_DATA_PIN_COMMAND); @@ -158,27 +256,21 @@ void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data, } } -void ili9340_exit_sleep(struct ili9340_data *data) -{ - ili9340_transmit(data, ILI9340_CMD_EXIT_SLEEP, NULL, 0); - k_sleep(120); -} - -void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x, - const u16_t y, const u16_t w, const u16_t h) -{ - u16_t spi_data[2]; - - spi_data[0] = sys_cpu_to_be16(x); - spi_data[1] = sys_cpu_to_be16(x + w - 1); - ili9340_transmit(data, ILI9340_CMD_COLUMN_ADDR, &spi_data[0], 4); - - spi_data[0] = sys_cpu_to_be16(y); - spi_data[1] = sys_cpu_to_be16(y + h - 1); - ili9340_transmit(data, ILI9340_CMD_PAGE_ADDR, &spi_data[0], 4); -} +static const struct display_driver_api ili9340_api = { + .blanking_on = ili9340_display_blanking_on, + .blanking_off = ili9340_display_blanking_off, + .write = ili9340_write, + .read = ili9340_read, + .get_framebuffer = ili9340_get_framebuffer, + .set_brightness = ili9340_set_brightness, + .set_contrast = ili9340_set_contrast, + .get_capabilities = ili9340_get_capabilities, + .set_pixel_format = ili9340_set_pixel_format, + .set_orientation = ili9340_set_orientation, +}; static struct ili9340_data ili9340_data; -DEVICE_INIT(ili9340, CONFIG_ILI9340_DEV_NAME, &ili9340_init, &ili9340_data, - NULL, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); +DEVICE_AND_API_INIT(ili9340, CONFIG_ILI9340_DEV_NAME, &ili9340_init, + &ili9340_data, NULL, APPLICATION, + CONFIG_APPLICATION_INIT_PRIORITY, &ili9340_api); diff --git a/drivers/display/display_ili9340.h b/drivers/display/display_ili9340.h index 9182d0b7c67f3a..633413a10703ca 100644 --- a/drivers/display/display_ili9340.h +++ b/drivers/display/display_ili9340.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2017 dXplore +/* + * Copyright (c) 2017 Jan Van Winkel * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/drivers/display/display_ili9340_adafruit_1480.c b/drivers/display/display_ili9340_adafruit_1480.c index 535741a341ae0b..c5a6ca7c56a153 100644 --- a/drivers/display/display_ili9340_adafruit_1480.c +++ b/drivers/display/display_ili9340_adafruit_1480.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2017 dXplore +/* + * Copyright (c) 2017 Jan Van Winkel * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/include/drivers/display/ili9340.h b/include/drivers/display/ili9340.h index 0bbceaf8f48110..8c82a2a30c359b 100644 --- a/include/drivers/display/ili9340.h +++ b/include/drivers/display/ili9340.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2017 dXplore +/* + * Copyright (c) 2017 Jan Van Winkel * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,23 +36,18 @@ void ili9340_write_pixel(const struct device *dev, const u16_t x, const u16_t y, * @param rgb_data pointer to the RGB data array, the data array should be at * minimum w * h * 3 bytes */ -void ili9340_write_bitmap(const struct device *dev, const u16_t x, - const u16_t y, const u16_t w, const u16_t h, - const u8_t *rgb_data); /** * @brief Turn display on * * @param dev Pointer to device structure */ -void ili9340_display_on(struct device *dev); /** * @brief Turn display off * * @param dev Pointer to device structure */ -void ili9340_display_off(struct device *dev); #ifdef __cplusplus } diff --git a/samples/display/ili9340/src/main.c b/samples/display/ili9340/src/main.c index ea354aa3b772e2..8101708b167eb5 100644 --- a/samples/display/ili9340/src/main.c +++ b/samples/display/ili9340/src/main.c @@ -1,11 +1,11 @@ /* - * Copyright (c) 2017 dXplore + * Copyright (c) 2017 Jan Van Winkel * * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include #include #include #include @@ -14,9 +14,6 @@ #include LOG_MODULE_REGISTER(main); -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 240 - /* This example will update each 500ms one of the LCD corners * wit a rectangular bitmap. * The color of the bit map is changed for every @@ -26,6 +23,9 @@ void main(void) { struct device *dev; + struct display_capabilities capabilities; + struct display_buffer_descriptor buf_desc; + /* size of the rectangle */ const size_t w = 40; const size_t h = 20; @@ -33,14 +33,7 @@ void main(void) u8_t *buf; /* xy coordinates where to place rectangles*/ - const size_t x0 = 0; - const size_t y0 = 0; - const size_t x1 = SCREEN_WIDTH - w; - const size_t y1 = 0; - const size_t x2 = SCREEN_WIDTH - w; - const size_t y2 = SCREEN_HEIGHT - h; - const size_t x3 = 0; - const size_t y3 = SCREEN_HEIGHT - h; + size_t x0, y0, x1, y1, x2, y2, x3, y3; size_t color = 0; size_t cnt = 0; @@ -53,6 +46,18 @@ void main(void) return; } + display_get_capabilities(dev, &capabilities); + + x0 = 0; + y0 = 0; + x1 = capabilities.x_resolution - w; + y1 = 0; + x2 = capabilities.x_resolution - w; + y2 = capabilities.y_resolution - h; + x3 = 0; + y3 = capabilities.y_resolution - h; + + /* Allocate rectangular buffer for corner data */ buf = k_malloc(buf_size); @@ -64,13 +69,22 @@ void main(void) /* Clear ili9340 frame buffer before enabling LCD, reuse corner buffer */ (void)memset(buf, 0, buf_size); - h_step = (w * h) / SCREEN_WIDTH; + h_step = (w * h) / capabilities.x_resolution; + + buf_desc.buf_size = buf_size; + buf_desc.pitch = capabilities.x_resolution; + buf_desc.width = capabilities.x_resolution; + buf_desc.height = h_step; - for (int idx = 0; idx < SCREEN_HEIGHT; idx += h_step) { - ili9340_write_bitmap(dev, 0, idx, SCREEN_WIDTH, h_step, buf); + for (int idx = 0; idx < capabilities.y_resolution; idx += h_step) { + display_write(dev, 0, idx, &buf_desc, buf); } - ili9340_display_on(dev); + display_blanking_off(dev); + + buf_desc.pitch = w; + buf_desc.width = w; + buf_desc.height = h; while (1) { /* Update the color of the rectangle buffer and write the buffer @@ -82,16 +96,16 @@ void main(void) } switch (cnt % 4) { case 0: - ili9340_write_bitmap(dev, x0, y0, w, h, buf); + display_write(dev, x0, y0, &buf_desc, buf); break; case 1: - ili9340_write_bitmap(dev, x1, y1, w, h, buf); + display_write(dev, x1, y1, &buf_desc, buf); break; case 2: - ili9340_write_bitmap(dev, x2, y2, w, h, buf); + display_write(dev, x2, y2, &buf_desc, buf); break; case 3: - ili9340_write_bitmap(dev, x3, y3, w, h, buf); + display_write(dev, x3, y3, &buf_desc, buf); break; } ++cnt;