|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: CC0-1.0 |
| 5 | + */ |
| 6 | +#include <memory> |
| 7 | +#include "freertos/FreeRTOS.h" |
| 8 | +#include "freertos/task.h" |
| 9 | +#include "esp_heap_caps.h" |
| 10 | +#include "esp_log.h" |
| 11 | +#include "esp_timer.h" |
| 12 | +#include "unity.h" |
| 13 | +#include "unity_test_runner.h" |
| 14 | +#include "ESP_Panel_Library.h" |
| 15 | + |
| 16 | +using namespace std; |
| 17 | + |
| 18 | +/* The following default configurations are for the board 'Espressif: ESP32-P4-Function-EV-Board, EK79007' */ |
| 19 | +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 20 | +//////////////////// Please update the following configuration according to your LCD spec ////////////////////////////// |
| 21 | +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 22 | +#define TEST_LCD_WIDTH (1024) |
| 23 | +#define TEST_LCD_HEIGHT (600) |
| 24 | +#define TEST_LCD_COLOR_BITS (ESP_PANEL_LCD_RGB888_COLOR_BITS_24) |
| 25 | +#define TEST_LCD_DSI_PHY_LDO_ID (3) |
| 26 | +#define TEST_LCD_DSI_LANE_NUM (2) |
| 27 | +#define TEST_LCD_DSI_LANE_RATE_MBPS (1000) |
| 28 | +#define TEST_LCD_DPI_CLK_MHZ (52) |
| 29 | +#define TEST_LCD_DPI_COLOR_BITS (ESP_PANEL_LCD_RGB888_COLOR_BITS_24) |
| 30 | +#define TEST_LCD_DPI_HPW (10) |
| 31 | +#define TEST_LCD_DPI_HBP (160) |
| 32 | +#define TEST_LCD_DPI_HFP (160) |
| 33 | +#define TEST_LCD_DPI_VPW (1) |
| 34 | +#define TEST_LCD_DPI_VBP (23) |
| 35 | +#define TEST_LCD_DPI_VFP (12) |
| 36 | +#define TEST_LCD_USE_EXTERNAL_CMD (0) |
| 37 | +#if TEST_LCD_USE_EXTERNAL_CMD |
| 38 | +/** |
| 39 | + * LCD initialization commands. |
| 40 | + * |
| 41 | + * Vendor specific initialization can be different between manufacturers, should consult the LCD supplier for |
| 42 | + * initialization sequence code. |
| 43 | + * |
| 44 | + * Please uncomment and change the following macro definitions, then use `configVendorCommands()` to pass them in the |
| 45 | + * same format if needed. Otherwise, the LCD driver will use the default initialization sequence code. |
| 46 | + * |
| 47 | + * There are two formats for the sequence code: |
| 48 | + * 1. Raw data: {command, (uint8_t []){ data0, data1, ... }, data_size, delay_ms} |
| 49 | + * 2. Formatter: ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(delay_ms, command, { data0, data1, ... }) and |
| 50 | + * ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(delay_ms, command) |
| 51 | + */ |
| 52 | +const esp_lcd_panel_vendor_init_cmd_t lcd_init_cmd[] = { |
| 53 | + // {0xFF, (uint8_t []){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, |
| 54 | + // {0xC0, (uint8_t []){0x3B, 0x00}, 2, 0}, |
| 55 | + // {0xC1, (uint8_t []){0x0D, 0x02}, 2, 0}, |
| 56 | + // {0x29, (uint8_t []){0x00}, 0, 120}, |
| 57 | + // // or |
| 58 | + ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xFF, {0x77, 0x01, 0x00, 0x00, 0x10}), |
| 59 | + ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC0, {0x3B, 0x00}), |
| 60 | + ESP_PANEL_LCD_CMD_WITH_8BIT_PARAM(0, 0xC1, {0x0D, 0x02}), |
| 61 | + ESP_PANEL_LCD_CMD_WITH_NONE_PARAM(120, 0x29), |
| 62 | +}; |
| 63 | +#endif |
| 64 | + |
| 65 | +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 66 | +//////////////////// Please update the following configuration according to your board spec //////////////////////////// |
| 67 | +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 68 | +#define TEST_LCD_PIN_NUM_RST (27) // Set to -1 if not used |
| 69 | +#define TEST_LCD_PIN_NUM_BK_LIGHT (26) // Set to -1 if not used |
| 70 | +#define TEST_LCD_BK_LIGHT_ON_LEVEL (1) |
| 71 | +#define TEST_LCD_BK_LIGHT_OFF_LEVEL !TEST_LCD_BK_LIGHT_ON_LEVEL |
| 72 | + |
| 73 | +/* Enable or disable pattern test */ |
| 74 | +#define TEST_ENABLE_PATTERN_TEST (1) |
| 75 | +/* Enable or disable printing LCD refresh rate */ |
| 76 | +#define TEST_ENABLE_PRINT_LCD_FPS (1) |
| 77 | +#define TEST_PRINT_LCD_FPS_PERIOD_MS (1000) |
| 78 | +/* Enable or disable the attachment of a callback function that is called after each bitmap drawing is completed */ |
| 79 | +#define TEST_ENABLE_ATTACH_CALLBACK (1) |
| 80 | +#define TEST_COLOR_BAR_SHOW_TIME_MS (5000) |
| 81 | + |
| 82 | +#define delay(ms) vTaskDelay(pdMS_TO_TICKS(ms)) |
| 83 | + |
| 84 | +static const char *TAG = "test_spi_lcd"; |
| 85 | + |
| 86 | +static shared_ptr<ESP_PanelBacklight> init_backlight(void) |
| 87 | +{ |
| 88 | +#if TEST_LCD_PIN_NUM_BK_LIGHT >= 0 |
| 89 | + ESP_LOGI(TAG, "Initialize backlight control pin and turn it on"); |
| 90 | + shared_ptr<ESP_PanelBacklight> backlight = make_shared<ESP_PanelBacklight>( |
| 91 | + TEST_LCD_PIN_NUM_BK_LIGHT, TEST_LCD_BK_LIGHT_ON_LEVEL, true |
| 92 | + ); |
| 93 | + TEST_ASSERT_NOT_NULL_MESSAGE(backlight, "Create backlight object failed"); |
| 94 | + |
| 95 | + TEST_ASSERT_TRUE_MESSAGE(backlight->begin(), "Backlight begin failed"); |
| 96 | + TEST_ASSERT_TRUE_MESSAGE(backlight->on(), "Backlight on failed"); |
| 97 | + |
| 98 | + return backlight; |
| 99 | +#else |
| 100 | + return nullptr; |
| 101 | +#endif |
| 102 | +} |
| 103 | + |
| 104 | +static shared_ptr<ESP_PanelBus_DSI> init_panel_bus(void) |
| 105 | +{ |
| 106 | + ESP_LOGI(TAG, "Create LCD bus"); |
| 107 | + shared_ptr<ESP_PanelBus_DSI> panel_bus = make_shared<ESP_PanelBus_DSI>( |
| 108 | + TEST_LCD_DSI_LANE_NUM, TEST_LCD_DSI_LANE_RATE_MBPS, |
| 109 | + TEST_LCD_DPI_CLK_MHZ, TEST_LCD_DPI_COLOR_BITS, TEST_LCD_WIDTH, TEST_LCD_HEIGHT, |
| 110 | + TEST_LCD_DPI_HPW, TEST_LCD_DPI_HBP, TEST_LCD_DPI_HFP, |
| 111 | + TEST_LCD_DPI_VPW, TEST_LCD_DPI_VBP, TEST_LCD_DPI_VFP, |
| 112 | + TEST_LCD_DSI_PHY_LDO_ID |
| 113 | + ); |
| 114 | + TEST_ASSERT_NOT_NULL_MESSAGE(panel_bus, "Create panel bus object failed"); |
| 115 | + |
| 116 | + TEST_ASSERT_TRUE_MESSAGE(panel_bus->begin(), "Panel bus begin failed"); |
| 117 | + |
| 118 | + return panel_bus; |
| 119 | +} |
| 120 | + |
| 121 | +#if TEST_ENABLE_ATTACH_CALLBACK |
| 122 | +IRAM_ATTR static bool onDrawBitmapFinishCallback(void *user_data) |
| 123 | +{ |
| 124 | + esp_rom_printf("Draw bitmap finish callback\n"); |
| 125 | + |
| 126 | + return false; |
| 127 | +} |
| 128 | +#endif |
| 129 | + |
| 130 | +#if TEST_ENABLE_PRINT_LCD_FPS |
| 131 | +#define TEST_LCD_FPS_COUNT_MAX (100) |
| 132 | +#ifndef millis |
| 133 | +#define millis() (esp_timer_get_time() / 1000) |
| 134 | +#endif |
| 135 | + |
| 136 | +DRAM_ATTR int frame_count = 0; |
| 137 | +DRAM_ATTR int fps = 0; |
| 138 | +DRAM_ATTR long start_time = 0; |
| 139 | + |
| 140 | +IRAM_ATTR bool onVsyncEndCallback(void *user_data) |
| 141 | +{ |
| 142 | + long frame_start_time = *(long *)user_data; |
| 143 | + if (frame_start_time == 0) { |
| 144 | + (*(long *)user_data) = millis(); |
| 145 | + |
| 146 | + return false; |
| 147 | + } |
| 148 | + |
| 149 | + frame_count++; |
| 150 | + if (frame_count >= TEST_LCD_FPS_COUNT_MAX) { |
| 151 | + fps = TEST_LCD_FPS_COUNT_MAX * 1000 / (millis() - frame_start_time); |
| 152 | + frame_count = 0; |
| 153 | + (*(long *)user_data) = millis(); |
| 154 | + } |
| 155 | + |
| 156 | + return false; |
| 157 | +} |
| 158 | +#endif |
| 159 | + |
| 160 | +static void run_test(shared_ptr<ESP_PanelLcd> lcd) |
| 161 | +{ |
| 162 | + frame_count = 0; |
| 163 | + fps = 0; |
| 164 | + start_time = 0; |
| 165 | + |
| 166 | +#if TEST_LCD_USE_EXTERNAL_CMD |
| 167 | + // Configure external initialization commands, should called before `init()` |
| 168 | + lcd->configVendorCommands(lcd_init_cmd, sizeof(lcd_init_cmd) / sizeof(lcd_init_cmd[0])); |
| 169 | +#endif |
| 170 | + TEST_ASSERT_TRUE_MESSAGE(lcd->init(), "LCD init failed"); |
| 171 | + TEST_ASSERT_TRUE_MESSAGE(lcd->reset(), "LCD reset failed"); |
| 172 | + TEST_ASSERT_TRUE_MESSAGE(lcd->begin(), "LCD begin failed"); |
| 173 | + TEST_ASSERT_TRUE_MESSAGE(lcd->displayOn(), "LCD display on failed"); |
| 174 | + |
| 175 | +#if TEST_ENABLE_PATTERN_TEST |
| 176 | + ESP_LOGI(TAG, "Show MIPI-DSI patterns"); |
| 177 | + TEST_ASSERT_TRUE_MESSAGE( |
| 178 | + lcd->showDsiPattern(ESP_PanelLcd::DsiPatternType::BAR_HORIZONTAL), "MIPI DPI bar horizontal pattern test failed" |
| 179 | + ); |
| 180 | + delay(1000); |
| 181 | + TEST_ASSERT_TRUE_MESSAGE( |
| 182 | + lcd->showDsiPattern(ESP_PanelLcd::DsiPatternType::BAR_VERTICAL), "MIPI DPI bar vertical pattern test failed" |
| 183 | + ); |
| 184 | + delay(1000); |
| 185 | + TEST_ASSERT_TRUE_MESSAGE( |
| 186 | + lcd->showDsiPattern(ESP_PanelLcd::DsiPatternType::BER_VERTICAL), "MIPI DPI ber vertical pattern test failed" |
| 187 | + ); |
| 188 | + delay(1000); |
| 189 | + TEST_ASSERT_TRUE_MESSAGE( |
| 190 | + lcd->showDsiPattern(ESP_PanelLcd::DsiPatternType::NONE), "MIPI DPI none pattern test failed" |
| 191 | + ); |
| 192 | +#endif |
| 193 | +#if TEST_ENABLE_ATTACH_CALLBACK |
| 194 | + TEST_ASSERT_TRUE_MESSAGE( |
| 195 | + lcd->attachDrawBitmapFinishCallback(onDrawBitmapFinishCallback, nullptr), "Attach callback failed" |
| 196 | + ); |
| 197 | +#endif |
| 198 | +#if TEST_ENABLE_PRINT_LCD_FPS |
| 199 | + TEST_ASSERT_TRUE_MESSAGE( |
| 200 | + lcd->attachRefreshFinishCallback(onVsyncEndCallback, (void *)&start_time), "Attach refresh callback failed" |
| 201 | + ); |
| 202 | +#endif |
| 203 | + |
| 204 | + ESP_LOGI(TAG, "Draw color bar from top left to bottom right, the order is B - G - R"); |
| 205 | + TEST_ASSERT_TRUE_MESSAGE(lcd->colorBarTest(TEST_LCD_WIDTH, TEST_LCD_HEIGHT), "LCD color bar test failed"); |
| 206 | + |
| 207 | + ESP_LOGI(TAG, "Wait for %d ms to show the color bar", TEST_COLOR_BAR_SHOW_TIME_MS); |
| 208 | +#if TEST_ENABLE_PRINT_LCD_FPS |
| 209 | + int i = 0; |
| 210 | + while (i++ < TEST_COLOR_BAR_SHOW_TIME_MS / TEST_PRINT_LCD_FPS_PERIOD_MS) { |
| 211 | + ESP_LOGI(TAG, "FPS: %d", fps); |
| 212 | + vTaskDelay(pdMS_TO_TICKS(TEST_PRINT_LCD_FPS_PERIOD_MS)); |
| 213 | + } |
| 214 | +#else |
| 215 | + vTaskDelay(pdMS_TO_TICKS(TEST_COLOR_BAR_SHOW_TIME_MS)); |
| 216 | +#endif |
| 217 | +} |
| 218 | + |
| 219 | +#define CREATE_LCD(name, panel_bus) \ |
| 220 | + ({ \ |
| 221 | + ESP_LOGI(TAG, "Create LCD device: " #name); \ |
| 222 | + shared_ptr<ESP_PanelLcd> lcd = make_shared<ESP_PanelLcd_##name>(panel_bus, TEST_LCD_COLOR_BITS, TEST_LCD_PIN_NUM_RST); \ |
| 223 | + TEST_ASSERT_NOT_NULL_MESSAGE(lcd, "Create LCD object failed"); \ |
| 224 | + lcd; \ |
| 225 | + }) |
| 226 | +#define CREATE_TEST_CASE(name) \ |
| 227 | + TEST_CASE("Test LCD (" #name ") to draw color bar", "[spi_lcd][" #name "]") \ |
| 228 | + { \ |
| 229 | + shared_ptr<ESP_PanelBacklight> backlight = init_backlight(); \ |
| 230 | + shared_ptr<ESP_PanelBus_DSI> panel_bus = init_panel_bus(); \ |
| 231 | + shared_ptr<ESP_PanelLcd> lcd = CREATE_LCD(name, panel_bus.get()); \ |
| 232 | + run_test(lcd); \ |
| 233 | + } |
| 234 | + |
| 235 | +/** |
| 236 | + * Here to create test cases for different LCDs |
| 237 | + * |
| 238 | + */ |
| 239 | +CREATE_TEST_CASE(EK79007) |
0 commit comments