/* * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "esp_heap_caps.h" #include "driver/spi_master.h" #include "driver/gpio.h" #include "pretty_effect.h" // Using SPI2 in the example, as it also supports octal modes on some targets #define LCD_HOST SPI2_HOST // To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. // More means more memory use, but less overhead for setting up / finishing transfers. Make sure 240 // is dividable by this. #define PARALLEL_LINES CONFIG_EXAMPLE_LCD_FLUSH_PARALLEL_LINES // The number of frames to show before rotate the graph #define ROTATE_FRAME 30 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// Please update the following configuration according to your LCD spec ////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define EXAMPLE_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) #define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 0 #define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL #define EXAMPLE_PIN_NUM_DATA0 23 /*!< for 1-line SPI, this also refereed as MOSI */ #define EXAMPLE_PIN_NUM_PCLK 19 #define EXAMPLE_PIN_NUM_CS 22 #define EXAMPLE_PIN_NUM_DC 21 #define EXAMPLE_PIN_NUM_RST 18 #define EXAMPLE_PIN_NUM_BK_LIGHT 5 // The pixel number in horizontal and vertical #define EXAMPLE_LCD_H_RES 320 #define EXAMPLE_LCD_V_RES 240 // Bit number used to represent command and parameter #define EXAMPLE_LCD_CMD_BITS 8 #define EXAMPLE_LCD_PARAM_BITS 8 #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE #define EXAMPLE_PIN_NUM_DATA1 7 #define EXAMPLE_PIN_NUM_DATA2 8 #define EXAMPLE_PIN_NUM_DATA3 9 #define EXAMPLE_PIN_NUM_DATA4 10 #define EXAMPLE_PIN_NUM_DATA5 11 #define EXAMPLE_PIN_NUM_DATA6 12 #define EXAMPLE_PIN_NUM_DATA7 13 #endif // CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE // Simple routine to generate some patterns and send them to the LCD. Because the // SPI driver handles transactions in the background, we can calculate the next line // while the previous one is being sent. static uint16_t *s_lines[2]; static void display_pretty_colors(esp_lcd_panel_handle_t panel_handle) { int frame = 0; // Indexes of the line currently being sent to the LCD and the line we're calculating int sending_line = 0; int calc_line = 0; // After ROTATE_FRAME frames, the image will be rotated while (frame <= ROTATE_FRAME) { frame++; for (int y = 0; y < EXAMPLE_LCD_V_RES; y += PARALLEL_LINES) { // Calculate a line pretty_effect_calc_lines(s_lines[calc_line], y, frame, PARALLEL_LINES); sending_line = calc_line; calc_line = !calc_line; // Send the calculated data esp_lcd_panel_draw_bitmap(panel_handle, 0, y, 0 + EXAMPLE_LCD_H_RES, y + PARALLEL_LINES, s_lines[sending_line]); } } } void app_main(void) { gpio_config_t bk_gpio_config = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT }; // Initialize the GPIO of backlight ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); spi_bus_config_t buscfg = { .sclk_io_num = EXAMPLE_PIN_NUM_PCLK, .mosi_io_num = EXAMPLE_PIN_NUM_DATA0, .miso_io_num = -1, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = PARALLEL_LINES * EXAMPLE_LCD_H_RES * 2 + 8 }; #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE buscfg.data1_io_num = EXAMPLE_PIN_NUM_DATA1; buscfg.data2_io_num = EXAMPLE_PIN_NUM_DATA2; buscfg.data3_io_num = EXAMPLE_PIN_NUM_DATA3; buscfg.data4_io_num = EXAMPLE_PIN_NUM_DATA4; buscfg.data5_io_num = EXAMPLE_PIN_NUM_DATA5; buscfg.data6_io_num = EXAMPLE_PIN_NUM_DATA6; buscfg.data7_io_num = EXAMPLE_PIN_NUM_DATA7; buscfg.flags = SPICOMMON_BUSFLAG_OCTAL; #endif // Initialize the SPI bus ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); esp_lcd_panel_io_handle_t io_handle = NULL; esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = EXAMPLE_PIN_NUM_DC, .cs_gpio_num = EXAMPLE_PIN_NUM_CS, .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ, .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, .spi_mode = 0, .trans_queue_depth = 10, }; #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE io_config.spi_mode = 3; // using mode 3 to simulate Intel 8080 timing io_config.flags.octal_mode = 1; #endif // Attach the LCD to the SPI bus ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle)); esp_lcd_panel_handle_t panel_handle = NULL; esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = EXAMPLE_PIN_NUM_RST, .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, .bits_per_pixel = 16, }; // Initialize the LCD configuration ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); // Turn off backlight to avoid unpredictable display on the LCD screen while initializing // the LCD panel driver. (Different LCD screens may need different levels) ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL)); // Reset the display ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); // Initialize LCD panel ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); // Turn on the screen ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); // Swap x and y axis (Different LCD screens may need different options) ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true)); // Turn on backlight (Different LCD screens may need different levels) ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL)); // Initialize the effect displayed ESP_ERROR_CHECK(pretty_effect_init()); // "Rotate or not" flag bool is_rotated = false; // Allocate memory for the pixel buffers for (int i = 0; i < 2; i++) { s_lines[i] = heap_caps_malloc(EXAMPLE_LCD_H_RES * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA); assert(s_lines[i] != NULL); } // Start and rotate while (1) { // Set driver configuration to rotate 180 degrees each time ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, is_rotated, is_rotated)); // Display display_pretty_colors(panel_handle); is_rotated = !is_rotated; } }