1 /* LCD tjpgd example
2
3 This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <stdio.h>
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/task.h"
12 #include "esp_lcd_panel_io.h"
13 #include "esp_lcd_panel_vendor.h"
14 #include "esp_lcd_panel_ops.h"
15 #include "esp_heap_caps.h"
16 #include "driver/spi_master.h"
17 #include "driver/gpio.h"
18 #include "pretty_effect.h"
19
20 // Using SPI2 in the example, as it aslo supports octal modes on some targets
21 #define LCD_HOST SPI2_HOST
22 // To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many.
23 // More means more memory use, but less overhead for setting up / finishing transfers. Make sure 240
24 // is dividable by this.
25 #define PARALLEL_LINES 16
26 // The number of frames to show before rotate the graph
27 #define ROTATE_FRAME 30
28
29 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30 //////////////////// Please update the following configuration according to your LCD spec //////////////////////////////
31 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
32 #define EXAMPLE_LCD_PIXEL_CLOCK_HZ (10 * 1000 * 1000)
33 #define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 0
34 #define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
35 #define EXAMPLE_PIN_NUM_DATA0 23 /*!< for 1-line SPI, this also refered as MOSI */
36 #define EXAMPLE_PIN_NUM_PCLK 19
37 #define EXAMPLE_PIN_NUM_CS 22
38 #define EXAMPLE_PIN_NUM_DC 21
39 #define EXAMPLE_PIN_NUM_RST 18
40 #define EXAMPLE_PIN_NUM_BK_LIGHT 5
41
42 // The pixel number in horizontal and vertical
43 #define EXAMPLE_LCD_H_RES 320
44 #define EXAMPLE_LCD_V_RES 240
45 // Bit number used to represent command and parameter
46 #define EXAMPLE_LCD_CMD_BITS 8
47 #define EXAMPLE_LCD_PARAM_BITS 8
48
49 #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE
50 #define EXAMPLE_PIN_NUM_DATA1 7
51 #define EXAMPLE_PIN_NUM_DATA2 8
52 #define EXAMPLE_PIN_NUM_DATA3 9
53 #define EXAMPLE_PIN_NUM_DATA4 10
54 #define EXAMPLE_PIN_NUM_DATA5 11
55 #define EXAMPLE_PIN_NUM_DATA6 12
56 #define EXAMPLE_PIN_NUM_DATA7 13
57 #endif // CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE
58
59 // Simple routine to generate some patterns and send them to the LCD. Because the
60 // SPI driver handles transactions in the background, we can calculate the next line
61 // while the previous one is being sent.
62 static uint16_t *s_lines[2];
display_pretty_colors(esp_lcd_panel_handle_t panel_handle)63 static void display_pretty_colors(esp_lcd_panel_handle_t panel_handle)
64 {
65 int frame = 0;
66 // Indexes of the line currently being sent to the LCD and the line we're calculating
67 int sending_line = 0;
68 int calc_line = 0;
69
70 // After ROTATE_FRAME frames, the image will be rotated
71 while (frame <= ROTATE_FRAME) {
72 frame++;
73 for (int y = 0; y < EXAMPLE_LCD_V_RES; y += PARALLEL_LINES) {
74 // Calculate a line
75 pretty_effect_calc_lines(s_lines[calc_line], y, frame, PARALLEL_LINES);
76 sending_line = calc_line;
77 calc_line = !calc_line;
78 // Send the calculated data
79 esp_lcd_panel_draw_bitmap(panel_handle, 0, y, 0 + EXAMPLE_LCD_H_RES, y + PARALLEL_LINES, s_lines[sending_line]);
80 }
81 }
82 }
83
app_main(void)84 void app_main(void)
85 {
86 gpio_config_t bk_gpio_config = {
87 .mode = GPIO_MODE_OUTPUT,
88 .pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
89 };
90 // Initialize the GPIO of backlight
91 ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
92
93 spi_bus_config_t buscfg = {
94 .sclk_io_num = EXAMPLE_PIN_NUM_PCLK,
95 .mosi_io_num = EXAMPLE_PIN_NUM_DATA0,
96 .miso_io_num = -1,
97 .quadwp_io_num = -1,
98 .quadhd_io_num = -1,
99 .max_transfer_sz = PARALLEL_LINES * EXAMPLE_LCD_H_RES * 2 + 8
100 };
101 #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE
102 buscfg.data1_io_num = EXAMPLE_PIN_NUM_DATA1;
103 buscfg.data2_io_num = EXAMPLE_PIN_NUM_DATA2;
104 buscfg.data3_io_num = EXAMPLE_PIN_NUM_DATA3;
105 buscfg.data4_io_num = EXAMPLE_PIN_NUM_DATA4;
106 buscfg.data5_io_num = EXAMPLE_PIN_NUM_DATA5;
107 buscfg.data6_io_num = EXAMPLE_PIN_NUM_DATA6;
108 buscfg.data7_io_num = EXAMPLE_PIN_NUM_DATA7;
109 buscfg.flags = SPICOMMON_BUSFLAG_OCTAL;
110 #endif
111 // Initialize the SPI bus
112 ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));
113
114 esp_lcd_panel_io_handle_t io_handle = NULL;
115 esp_lcd_panel_io_spi_config_t io_config = {
116 .dc_gpio_num = EXAMPLE_PIN_NUM_DC,
117 .cs_gpio_num = EXAMPLE_PIN_NUM_CS,
118 .pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
119 .lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
120 .lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
121 .spi_mode = 0,
122 .trans_queue_depth = 10,
123 };
124 #if CONFIG_EXAMPLE_LCD_SPI_8_LINE_MODE
125 io_config.spi_mode = 3; // using mode 3 to simulate Intel 8080 timing
126 io_config.flags.octal_mode = 1;
127 #endif
128 // Attach the LCD to the SPI bus
129 ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
130
131 esp_lcd_panel_handle_t panel_handle = NULL;
132 esp_lcd_panel_dev_config_t panel_config = {
133 .reset_gpio_num = EXAMPLE_PIN_NUM_RST,
134 .color_space = ESP_LCD_COLOR_SPACE_BGR,
135 .bits_per_pixel = 16,
136 };
137 // Initialize the LCD configuration
138 ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
139
140 // Turn off backlight to avoid unpredictable display on the LCD screen while initializing
141 // the LCD panel driver. (Different LCD screens may need different levels)
142 ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL));
143
144 // Reset the display
145 ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
146
147 // Initialize LCD panel
148 ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
149
150 // Swap x and y axis (Different LCD screens may need different options)
151 ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
152
153 // Turn on backlight (Different LCD screens may need different levels)
154 ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL));
155
156 // Initialize the effect displayed
157 ESP_ERROR_CHECK(pretty_effect_init());
158
159 // "Rotate or not" flag
160 bool is_rotated = false;
161
162 // Allocate memory for the pixel buffers
163 for (int i = 0; i < 2; i++) {
164 s_lines[i] = heap_caps_malloc(EXAMPLE_LCD_H_RES * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA);
165 assert(s_lines[i] != NULL);
166 }
167
168 // Start and rotate
169 while (1) {
170 // Set driver configuration to rotate 180 degrees each time
171 ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, is_rotated, is_rotated));
172 // Display
173 display_pretty_colors(panel_handle);
174 is_rotated = !is_rotated;
175 }
176 }
177