/* Copyright (c) 2017 dXplore * * SPDX-License-Identifier: Apache-2.0 */ #include "display_ili9340.h" #include #define SYS_LOG_DOMAIN "ILI9340" #define SYS_LOG_LEVEL CONFIG_SYS_LOG_ILI9340_LEVEL #include #include #include #include struct ili9340_data { struct device *reset_gpio; struct device *command_data_gpio; struct device *spi_dev; struct spi_config spi_config; #ifdef CONFIG_ILI9340_GPIO_CS struct spi_cs_control cs_ctrl; #endif }; #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); int ili9340_init(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; SYS_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"); return -EPERM; } data->spi_config.frequency = CONFIG_ILI9340_SPI_FREQ; data->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8); data->spi_config.slave = CONFIG_ILI9340_SPI_SLAVE_NUMBER; #ifdef CONFIG_ILI9340_GPIO_CS data->cs_ctrl.gpio_dev = device_get_binding(CONFIG_ILI9340_CS_GPIO_PORT_NAME); data->cs_ctrl.gpio_pin = CONFIG_ILI9340_CS_GPIO_PIN; data->cs_ctrl.delay = 0; data->spi_config.cs = &(data->cs_ctrl); #else data->spi_config.cs = NULL; #endif 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"); 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); if (data->command_data_gpio == NULL) { SYS_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"); 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"); ili9340_lcd_init(data); SYS_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) { u8_t rgb_data[] = {r, g, b}; SYS_LOG_DBG("Writing pixel @ %dx%d (x,y)", x, y); ili9340_write_bitmap(dev, x, y, 1, 1, &rgb_data[0]); } 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) { 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); ili9340_set_mem_area(data, x, y, w, h); ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *)rgb_data, 3 * w * h); } void ili9340_display_on(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; SYS_LOG_DBG("Turning display on"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0); } void ili9340_display_off(struct device *dev) { struct ili9340_data *data = (struct ili9340_data *)dev->driver_data; SYS_LOG_DBG("Turning display off"); ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0); } 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}; gpio_pin_write(data->command_data_gpio, CONFIG_ILI9340_CMD_DATA_PIN, ILI9340_CMD_DATA_PIN_COMMAND); spi_write(data->spi_dev, &data->spi_config, &tx_bufs); if (tx_data != NULL) { tx_buf.buf = tx_data; tx_buf.len = tx_len; gpio_pin_write(data->command_data_gpio, CONFIG_ILI9340_CMD_DATA_PIN, ILI9340_CMD_DATA_PIN_DATA); spi_write(data->spi_dev, &data->spi_config, &tx_bufs); } } 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 struct ili9340_data ili9340_data; DEVICE_INIT(ili9340, CONFIG_ILI9340_DEV_NAME, &ili9340_init, &ili9340_data, NULL, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);