esp-idf/examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c
2022-08-18 10:59:16 +08:00

179 lines
6.8 KiB
C

/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#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 aslo 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 (10 * 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 refered 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_endian = LCD_RGB_ENDIAN_BGR,
.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));
// 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;
}
}