#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_log.h"
// Include your image header file
#include "dog.h" // Ensure this contains the RGB565 pixel array
// Define pins for the ILI9341 display
#define TFT_DC GPIO_NUM_2
#define TFT_CS GPIO_NUM_15
#define TFT_RST GPIO_NUM_4
#define TFT_MOSI GPIO_NUM_23
#define TFT_SCLK GPIO_NUM_18
// ILI9341 Commands
#define ILI9341_SWRESET 0x01
#define ILI9341_SLPOUT 0x11
#define ILI9341_DISPON 0x29
#define ILI9341_MADCTL 0x36
#define ILI9341_COLMOD 0x3A
#define ILI9341_CASET 0x2A
#define ILI9341_RASET 0x2B
#define ILI9341_RAMWR 0x2C
// Display dimensions
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
static const char *TAG = "ILI9341";
// SPI device handle
spi_device_handle_t spi;
// Function to send a command to the display
void ili9341_send_command(uint8_t cmd) {
gpio_set_level(TFT_DC, 0); // Command mode
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8;
t.tx_buffer = &cmd;
spi_device_polling_transmit(spi, &t);
}
// Function to send data to the display
void ili9341_send_data(const uint8_t *data, size_t len) {
gpio_set_level(TFT_DC, 1); // Data mode
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = len * 8;
t.tx_buffer = data;
spi_device_polling_transmit(spi, &t);
}
// Function to initialize the ILI9341 display
void ili9341_init() {
// Reset the display
gpio_set_direction(TFT_RST, GPIO_MODE_OUTPUT);
gpio_set_level(TFT_RST, 0);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(TFT_RST, 1);
vTaskDelay(pdMS_TO_TICKS(100));
// Send initialization commands
ili9341_send_command(ILI9341_SWRESET); // Software reset
vTaskDelay(pdMS_TO_TICKS(150));
ili9341_send_command(ILI9341_SLPOUT); // Sleep out
vTaskDelay(pdMS_TO_TICKS(150));
ili9341_send_command(ILI9341_COLMOD); // Set color mode
uint8_t colmod_data[] = {0x55}; // 16-bit color
ili9341_send_data(colmod_data, 1);
ili9341_send_command(ILI9341_MADCTL); // Memory access control
uint8_t madctl_data[] = {0x48}; // Portrait mode
ili9341_send_data(madctl_data, 1);
ili9341_send_command(ILI9341_DISPON); // Display on
vTaskDelay(pdMS_TO_TICKS(100));
}
// Function to set the drawing window
void ili9341_set_window(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end) {
uint8_t caset_data[] = {
(x_start >> 8) & 0xFF, x_start & 0xFF,
(x_end >> 8) & 0xFF, x_end & 0xFF
};
ili9341_send_command(ILI9341_CASET);
ili9341_send_data(caset_data, sizeof(caset_data));
uint8_t raset_data[] = {
(y_start >> 8) & 0xFF, y_start & 0xFF,
(y_end >> 8) & 0xFF, y_end & 0xFF
};
ili9341_send_command(ILI9341_RASET);
ili9341_send_data(raset_data, sizeof(raset_data));
ili9341_send_command(ILI9341_RAMWR); // Start writing to RAM
}
// Function to draw an RGB565 bitmap
void ili9341_draw_rgb_bitmap(const uint16_t *bitmap, uint16_t width, uint16_t height) {
ili9341_set_window(0, 0, width - 1, height - 1);
gpio_set_level(TFT_DC, 1); // Data mode
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = width * height * 16; // Total bits
t.tx_buffer = bitmap;
spi_device_polling_transmit(spi, &t);
}
void app_main() {
// Initialize SPI bus
spi_bus_config_t buscfg = {
.miso_io_num = -1, // Not used
.mosi_io_num = TFT_MOSI,
.sclk_io_num = TFT_SCLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
// Attach the ILI9341 to the SPI bus
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.mode = 0, // SPI mode 0
.clock_speed_hz = 40 * 1000 * 1000, // 40 MHz
.spics_io_num = TFT_CS,
.queue_size = 7,
.flags = 0
};
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi));
// Initialize GPIOs
gpio_set_direction(TFT_DC, GPIO_MODE_OUTPUT);
// Initialize the display
ili9341_init();
// Draw the image from dog.h onto the screen
ili9341_draw_rgb_bitmap(dog, 240, 196); // Assuming image is 240x196 pixels
ESP_LOGI(TAG, "Image displayed successfully");
}