Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display api #7833

Merged
merged 4 commits into from
Oct 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions drivers/display/Kconfig.ili9340
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Kconfig - ILI9340 display driver configuration options

#
# Copyright (c) 2017 dXplore
# Copyright (c) 2017 Jan Van Winkel <[email protected]>
#
# SPDX-License-Identifier: Apache-2.0
#
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion drivers/display/Kconfig.microbit
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Kconfig - Microbit display driver configuration options

#
# Copyright (c) 2017 dXplore
# Copyright (c) 2017 Jan Van Winkel <[email protected]>
#
# SPDX-License-Identifier: Apache-2.0
#
Expand Down
220 changes: 156 additions & 64 deletions drivers/display/display_ili9340.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/* Copyright (c) 2017 dXplore
/*
* Copyright (c) 2017 Jan Van Winkel <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "display_ili9340.h"
#include <drivers/display/ili9340.h>
#include <display.h>

#define SYS_LOG_DOMAIN "ILI9340"
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_ILI9340_LEVEL
#include <logging/sys_log.h>
#define LOG_LEVEL CONFIG_LOG_ILI9340_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(display);

#include <gpio.h>
#include <misc/byteorder.h>
#include <spi.h>
#include <string.h>

struct ili9340_data {
struct device *reset_gpio;
Expand All @@ -27,20 +29,21 @@ 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;

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;
}

Expand All @@ -59,90 +62,185 @@ 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) {
SYS_LOG_ERR("Could not get GPIO port for ILI9340 reset");
LOG_ERR("Could not get GPIO port for ILI9340 reset");
return -EPERM;
}

gpio_pin_configure(data->reset_gpio, CONFIG_ILI9340_RESET_PIN,
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) {
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);
k_sleep(1);
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
* 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];

SYS_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;
}

SYS_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;

SYS_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;

SYS_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);
Expand All @@ -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);
3 changes: 2 additions & 1 deletion drivers/display/display_ili9340.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (c) 2017 dXplore
/*
* Copyright (c) 2017 Jan Van Winkel <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down
3 changes: 2 additions & 1 deletion drivers/display/display_ili9340_adafruit_1480.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (c) 2017 dXplore
/*
* Copyright (c) 2017 Jan Van Winkel <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down
Loading