#include #include #include "esp_lcd_panel_ssd1306.h" #include "HardwareSerial.h" #include "WiFi.h" #include "lvgl.h" #include "soc/gpio_num.h" #include "esp_lvgl_port.h" static const char *TAG = "lcd-panel"; // According to SSD1306 datasheet // Bit number used to represent command and parameter #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define SCREEN_WIDTH 128 // OLED display width, in pixels #define I2C_HW_ADDR 0x3C #define LCD_PIXEL_CLOCK_HZ (400 * 1000) #define LCD_CMD_BITS 8 #define LCD_PARAM_BITS 8 #define PIN_NUM_RST -1 #define LCD_H_RES 128 #define LCD_V_RES 64 // TODO: Or? //#define LCD_V_RES 32 // Pin number may vary based on your schematic #define SDA_PIN GPIO_NUM_21 #define SCL_PIN GPIO_NUM_22 void setup() { Serial.begin(115200); ESP_LOGI(TAG, "Initialize I2C bus"); i2c_master_bus_handle_t i2c_bus = nullptr; i2c_master_bus_config_t bus_config = { .i2c_port = I2C_STATUS_READ, .sda_io_num = SDA_PIN, .scl_io_num = SCL_PIN, .clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7, .intr_priority = 0, .trans_queue_depth = 0, .flags = { .enable_internal_pullup = true, } }; ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &i2c_bus)); ESP_LOGI(TAG, "Install panel IO"); esp_lcd_panel_io_handle_t io_handle = nullptr; esp_lcd_panel_io_i2c_config_t io_config = { .dev_addr = I2C_HW_ADDR, .control_phase_bytes = 1, .dc_bit_offset = 6, .lcd_cmd_bits = LCD_CMD_BITS, .lcd_param_bits = LCD_PARAM_BITS, .scl_speed_hz = LCD_PIXEL_CLOCK_HZ, }; ESP_LOGI(TAG, "Install SSD1306 panel driver"); ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus, &io_config, &io_handle)); esp_lcd_panel_handle_t panel_handle = nullptr; esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = PIN_NUM_RST, .bits_per_pixel = 1, }; esp_lcd_panel_ssd1306_config_t ssd1306_config = { .height = LCD_V_RES, }; panel_config.vendor_config = &ssd1306_config; ESP_LOGI(TAG, "Install SSD1306 panel driver"); ESP_ERROR_CHECK( esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle)); ESP_LOGI(TAG, "Initialize LVGL"); const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); lvgl_port_init(&lvgl_cfg); const lvgl_port_display_cfg_t disp_cfg = { .io_handle = io_handle, .panel_handle = panel_handle, .buffer_size = LCD_H_RES * LCD_V_RES, .double_buffer = true, .hres = LCD_H_RES, .vres = LCD_V_RES, .monochrome = true, .rotation = { .swap_xy = false, .mirror_x = false, .mirror_y = false, }, .color_format = LV_COLOR_FORMAT_RGB565, .flags = { .sw_rotate = false, } }; lv_disp_t *disp = lvgl_port_add_disp(&disp_cfg); ESP_LOGI(TAG, "Display Scroll Text"); // Lock the mutex due to the LVGL APIs are not thread-safe if (lvgl_port_lock(0)) { /* Rotation of the screen */ lv_disp_set_rotation(disp, LV_DISPLAY_ROTATION_0); // // TODO: Set text here lv_obj_t *scr = lv_disp_get_scr_act(disp); lv_obj_t *label = lv_label_create(scr); // Circular scroll lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_label_set_text(label, "Hello world!"); // Size of the screen // If you use rotation 90 or 270, please set disp->driver->ver_res lv_obj_set_width(label, lv_display_get_physical_horizontal_resolution(disp)); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0); // Release the mutex lvgl_port_unlock(); } } void loop() { }