Move classes to separate files.
This commit is contained in:
parent
9e912048ab
commit
03784ac097
@ -9,7 +9,7 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
|||||||
project(
|
project(
|
||||||
#[[NAME]] lcd-panel
|
#[[NAME]] lcd-panel
|
||||||
VERSION 0.1
|
VERSION 0.1
|
||||||
DESCRIPTION "Example of using the SSDLCD"
|
DESCRIPTION "Example of using the SSD1306 LCD display with ESP-IDF and LVGL"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
# For writing pure cmake components, see the documentation
|
# For writing pure cmake components, see the documentation
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS main.cpp display.cpp
|
SRCS main.cpp display.cpp panel_device.cpp ssd1306.cpp
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS .
|
||||||
REQUIRES driver
|
REQUIRES driver
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "display.h"
|
|
||||||
#include "widgets/label/lv_label.h"
|
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
#include "ssd1306.h"
|
||||||
|
|
||||||
|
#include "widgets/label/lv_label.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <esp_lcd_panel_ops.h>
|
#include <esp_lcd_panel_ops.h>
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
@ -11,9 +13,6 @@
|
|||||||
#include <driver/i2c_master.h>
|
#include <driver/i2c_master.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
// To use LV_COLOR_FORMAT_I1 we need an extra buffer to hold the converted data.
|
|
||||||
uint8_t Display::oled_buffer_[LCD_H_RES * LCD_V_RES / 8];
|
|
||||||
|
|
||||||
// LVGL library is not thread-safe, this example calls LVGL APIs from tasks.
|
// LVGL library is not thread-safe, this example calls LVGL APIs from tasks.
|
||||||
// We must use a mutex to protect it.
|
// We must use a mutex to protect it.
|
||||||
_lock_t ScopedLock::lock_;
|
_lock_t ScopedLock::lock_;
|
||||||
@ -136,7 +135,7 @@ void Display::lvgl_flush_cb(lv_display_t *display, const lv_area_t *area,
|
|||||||
|
|
||||||
// Write to the buffer as required for the display.
|
// Write to the buffer as required for the display.
|
||||||
// It writes only 1-bit for monochrome displays mapped vertically.
|
// It writes only 1-bit for monochrome displays mapped vertically.
|
||||||
uint8_t *buf = oled_buffer_ + hor_res * (y >> 3) + (x);
|
uint8_t *buf = SSD1306::oled_buffer_ + hor_res * (y >> 3) + (x);
|
||||||
if (chroma_color) {
|
if (chroma_color) {
|
||||||
(*buf) &= ~(1 << (y % 8));
|
(*buf) &= ~(1 << (y % 8));
|
||||||
} else {
|
} else {
|
||||||
@ -147,7 +146,7 @@ void Display::lvgl_flush_cb(lv_display_t *display, const lv_area_t *area,
|
|||||||
// Pass the draw buffer to the driver.
|
// Pass the draw buffer to the driver.
|
||||||
ESP_ERROR_CHECK(
|
ESP_ERROR_CHECK(
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x1, y1, x2 + 1, y2 + 1,
|
esp_lcd_panel_draw_bitmap(panel_handle, x1, y1, x2 + 1, y2 + 1,
|
||||||
oled_buffer_));
|
SSD1306::oled_buffer_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::lvgl_increase_tick(void *)
|
void Display::lvgl_increase_tick(void *)
|
||||||
@ -156,11 +155,10 @@ void Display::lvgl_increase_tick(void *)
|
|||||||
lv_tick_inc(LVGL_TICK_PERIOD_MS);
|
lv_tick_inc(LVGL_TICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::lvgl_port_task(void *)
|
[[noreturn]] void Display::lvgl_port_task(void *)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Starting LVGL task");
|
ESP_LOGI(TAG, "Starting LVGL task");
|
||||||
uint32_t time_till_next_ms = 0;
|
for (uint32_t time_till_next_ms = 0; true;) {
|
||||||
while (1) {
|
|
||||||
_lock_acquire(&ScopedLock::lock_);
|
_lock_acquire(&ScopedLock::lock_);
|
||||||
time_till_next_ms = lv_timer_handler();
|
time_till_next_ms = lv_timer_handler();
|
||||||
_lock_release(&ScopedLock::lock_);
|
_lock_release(&ScopedLock::lock_);
|
||||||
@ -184,7 +182,15 @@ I2C::I2C() : i2c_bus_(nullptr)
|
|||||||
ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &i2c_bus_));
|
ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &i2c_bus_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Panel::Panel(i2c_master_bus_handle_t i2c) : io_handle_(nullptr), panel_(nullptr)
|
Panel::Panel(i2c_master_bus_handle_t i2c) :
|
||||||
|
io_handle_(nullptr),
|
||||||
|
panel_(nullptr),
|
||||||
|
panel_config_(
|
||||||
|
{
|
||||||
|
.reset_gpio_num = PIN_RST,
|
||||||
|
.bits_per_pixel = 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Install panel IO");
|
ESP_LOGI(TAG, "Install panel IO");
|
||||||
esp_lcd_panel_io_i2c_config_t io_config = {
|
esp_lcd_panel_io_i2c_config_t io_config = {
|
||||||
@ -200,21 +206,9 @@ Panel::Panel(i2c_master_bus_handle_t i2c) : io_handle_(nullptr), panel_(nullptr)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Install SSD1306 panel driver");
|
ESP_LOGI(TAG, "Install SSD1306 panel driver");
|
||||||
SSD1306 ssd1306({.height = LCD_V_RES});
|
SSD1306 ssd1306({.height = LCD_V_RES});
|
||||||
panel_config_ = {
|
|
||||||
.reset_gpio_num = PIN_RST,
|
|
||||||
.bits_per_pixel = 1,
|
|
||||||
};
|
|
||||||
ssd1306.create_panel(panel_config_, io_handle_, panel_);
|
ssd1306.create_panel(panel_config_, io_handle_, panel_);
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_));
|
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_));
|
||||||
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_));
|
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_));
|
||||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true));
|
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
SSD1306::SSD1306(esp_lcd_panel_ssd1306_config_t ssd_config,
|
|
||||||
int width,
|
|
||||||
int height) :
|
|
||||||
PanelDevice<esp_lcd_panel_ssd1306_config_t>(width, height)
|
|
||||||
{
|
|
||||||
vendor_config_ = ssd_config;
|
|
||||||
}
|
|
||||||
|
@ -12,31 +12,15 @@
|
|||||||
#include "display/lv_display.h"
|
#include "display/lv_display.h"
|
||||||
#include "widgets/label/lv_label.h"
|
#include "widgets/label/lv_label.h"
|
||||||
|
|
||||||
|
#include "panel_device.h"
|
||||||
|
|
||||||
#define I2C_BUS_PORT 0
|
#define I2C_BUS_PORT 0
|
||||||
#define LVGL_TICK_PERIOD_MS 5
|
#define LVGL_TICK_PERIOD_MS 5
|
||||||
#define LVGL_TASK_STACK_SIZE (4 * 1024)
|
#define LVGL_TASK_STACK_SIZE (4 * 1024)
|
||||||
#define LVGL_TASK_PRIORITY 2
|
#define LVGL_TASK_PRIORITY 2
|
||||||
#define LVGL_PALETTE_SIZE 8
|
|
||||||
|
|
||||||
static const char *TAG = "lcd-panel";
|
static const char *TAG = "lcd-panel";
|
||||||
|
|
||||||
// According to SSD1306 datasheet
|
|
||||||
// https://www.digikey.com/en/products/detail/winstar-display/WEA012864DWPP3N00003/20533255
|
|
||||||
// Bit number used to represent command and parameter
|
|
||||||
#define SCREEN_WIDTH 128 // OLED display width, in pixels.
|
|
||||||
#define SCREEN_HEIGHT 64 // OLED display height, in pixels.
|
|
||||||
#define LCD_H_RES SCREEN_WIDTH
|
|
||||||
#define LCD_V_RES SCREEN_HEIGHT
|
|
||||||
#define I2C_HW_ADDR 0x3C
|
|
||||||
#define LCD_PIXEL_CLOCK_HZ (400 * 1000)
|
|
||||||
#define LCD_CMD_BITS 8
|
|
||||||
#define LCD_PARAM_BITS 8
|
|
||||||
|
|
||||||
// Pin may vary based on your schematic.
|
|
||||||
#define PIN_SDA GPIO_NUM_21
|
|
||||||
#define PIN_SCL GPIO_NUM_22
|
|
||||||
#define PIN_RST -1
|
|
||||||
|
|
||||||
struct I2C {
|
struct I2C {
|
||||||
I2C();
|
I2C();
|
||||||
|
|
||||||
@ -55,67 +39,6 @@ struct ScopedLock {
|
|||||||
static _lock_t lock_;
|
static _lock_t lock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class PanelDevice {
|
|
||||||
public:
|
|
||||||
PanelDevice(size_t width, size_t height) : width_(width), height_(height) { }
|
|
||||||
|
|
||||||
~PanelDevice() = default;
|
|
||||||
|
|
||||||
[[nodiscard]] size_t get_width() const { return width_; }
|
|
||||||
|
|
||||||
[[nodiscard]] size_t get_height() const { return height_; }
|
|
||||||
|
|
||||||
[[nodiscard]] size_t get_area() const { return width_ * height_; }
|
|
||||||
|
|
||||||
[[nodiscard]] size_t get_draw_buffer_size() const
|
|
||||||
{
|
|
||||||
// LVGL reserves 2x4 bytes in the buffer to be used as a palette.
|
|
||||||
return width_ * height_ / 8 + LVGL_PALETTE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] lv_display_t *create_display() const
|
|
||||||
{
|
|
||||||
return lv_display_create(width_, height_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] T &get_vendor_config() const { return vendor_config_; }
|
|
||||||
|
|
||||||
void create_panel(esp_lcd_panel_dev_config_t &panel_config,
|
|
||||||
esp_lcd_panel_io_handle_t io_handle,
|
|
||||||
esp_lcd_panel_handle_t &panel_handle);
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t width_;
|
|
||||||
size_t height_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T vendor_config_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void PanelDevice<T>::create_panel(esp_lcd_panel_dev_config_t &config,
|
|
||||||
esp_lcd_panel_io_handle_t io,
|
|
||||||
esp_lcd_panel_handle_t &panel)
|
|
||||||
{
|
|
||||||
// If the passed handle is already allocated, delete it.
|
|
||||||
if (panel != nullptr) {
|
|
||||||
esp_lcd_panel_del(panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the vendor config and allocate a new panel handle.
|
|
||||||
config.vendor_config = &vendor_config_;
|
|
||||||
ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(io, &config, &panel));
|
|
||||||
}
|
|
||||||
|
|
||||||
class SSD1306 : public PanelDevice<esp_lcd_panel_ssd1306_config_t> {
|
|
||||||
public:
|
|
||||||
explicit SSD1306(esp_lcd_panel_ssd1306_config_t ssd_config,
|
|
||||||
int width = SCREEN_WIDTH, int height = SCREEN_HEIGHT);
|
|
||||||
|
|
||||||
~SSD1306() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Panel {
|
class Panel {
|
||||||
public:
|
public:
|
||||||
explicit Panel(i2c_master_bus_handle_t i2c);
|
explicit Panel(i2c_master_bus_handle_t i2c);
|
||||||
@ -170,10 +93,7 @@ public:
|
|||||||
|
|
||||||
static void lvgl_increase_tick(void *arg);
|
static void lvgl_increase_tick(void *arg);
|
||||||
|
|
||||||
static void lvgl_port_task(void *arg);
|
[[noreturn]] static void lvgl_port_task(void *arg);
|
||||||
|
|
||||||
// For LV_COLOR_FORMAT_I1 we need an extra buffer to hold the converted data.
|
|
||||||
static uint8_t oled_buffer_[LCD_H_RES * LCD_V_RES / 8];
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Panel panel_;
|
Panel panel_;
|
||||||
|
2
esp/cpp/07_lcd-panel/main/panel_device.cpp
Normal file
2
esp/cpp/07_lcd-panel/main/panel_device.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
#include "panel_device.h"
|
65
esp/cpp/07_lcd-panel/main/panel_device.h
Normal file
65
esp/cpp/07_lcd-panel/main/panel_device.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef PANEL_DEVICE_H
|
||||||
|
#define PANEL_DEVICE_H
|
||||||
|
|
||||||
|
#include <esp_lcd_panel_dev.h>
|
||||||
|
#include <esp_lcd_panel_ops.h>
|
||||||
|
#include <esp_lcd_panel_ssd1306.h>
|
||||||
|
#include "display/lv_display.h"
|
||||||
|
|
||||||
|
#define LVGL_PALETTE_SIZE 8
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class PanelDevice {
|
||||||
|
public:
|
||||||
|
PanelDevice(size_t width, size_t height) : width_(width), height_(height) { }
|
||||||
|
|
||||||
|
~PanelDevice() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] size_t get_width() const { return width_; }
|
||||||
|
|
||||||
|
[[nodiscard]] size_t get_height() const { return height_; }
|
||||||
|
|
||||||
|
[[nodiscard]] size_t get_area() const { return width_ * height_; }
|
||||||
|
|
||||||
|
[[nodiscard]] size_t get_draw_buffer_size() const
|
||||||
|
{
|
||||||
|
// LVGL reserves 2x4 bytes in the buffer to be used as a palette.
|
||||||
|
return width_ * height_ / 8 + LVGL_PALETTE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] lv_display_t *create_display() const
|
||||||
|
{
|
||||||
|
return lv_display_create(width_, height_);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] T &get_vendor_config() const { return vendor_config_; }
|
||||||
|
|
||||||
|
void create_panel(esp_lcd_panel_dev_config_t &panel_config,
|
||||||
|
esp_lcd_panel_io_handle_t io_handle,
|
||||||
|
esp_lcd_panel_handle_t &panel_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t width_;
|
||||||
|
size_t height_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T vendor_config_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void PanelDevice<T>::create_panel(esp_lcd_panel_dev_config_t &config,
|
||||||
|
esp_lcd_panel_io_handle_t io,
|
||||||
|
esp_lcd_panel_handle_t &panel)
|
||||||
|
{
|
||||||
|
// If the passed handle is already allocated, delete it.
|
||||||
|
if (panel != nullptr) {
|
||||||
|
esp_lcd_panel_del(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the vendor config and allocate a new panel handle.
|
||||||
|
config.vendor_config = &vendor_config_;
|
||||||
|
// TODO: This needs moved to SSD1306
|
||||||
|
ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(io, &config, &panel));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PANEL_DEVICE_H
|
13
esp/cpp/07_lcd-panel/main/ssd1306.cpp
Normal file
13
esp/cpp/07_lcd-panel/main/ssd1306.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
#include "ssd1306.h"
|
||||||
|
|
||||||
|
// To use LV_COLOR_FORMAT_I1 we need an extra buffer to hold the converted data.
|
||||||
|
uint8_t SSD1306::oled_buffer_[LCD_H_RES * LCD_V_RES / 8];
|
||||||
|
|
||||||
|
SSD1306::SSD1306(esp_lcd_panel_ssd1306_config_t ssd_config,
|
||||||
|
int width,
|
||||||
|
int height) :
|
||||||
|
PanelDevice<esp_lcd_panel_ssd1306_config_t>(width, height)
|
||||||
|
{
|
||||||
|
vendor_config_ = ssd_config;
|
||||||
|
}
|
36
esp/cpp/07_lcd-panel/main/ssd1306.h
Normal file
36
esp/cpp/07_lcd-panel/main/ssd1306.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef SSD1306_H
|
||||||
|
#define SSD1306_H
|
||||||
|
|
||||||
|
#include <esp_lcd_panel_ssd1306.h>
|
||||||
|
|
||||||
|
#include "panel_device.h"
|
||||||
|
|
||||||
|
// According to SSD1306 datasheet
|
||||||
|
// https://www.digikey.com/en/products/detail/winstar-display/WEA012864DWPP3N00003/20533255
|
||||||
|
// Bit number used to represent command and parameter
|
||||||
|
#define SCREEN_WIDTH 128 // OLED display width, in pixels.
|
||||||
|
#define SCREEN_HEIGHT 64 // OLED display height, in pixels.
|
||||||
|
#define LCD_H_RES SCREEN_WIDTH
|
||||||
|
#define LCD_V_RES SCREEN_HEIGHT
|
||||||
|
#define I2C_HW_ADDR 0x3C
|
||||||
|
#define LCD_PIXEL_CLOCK_HZ (400 * 1000)
|
||||||
|
#define LCD_CMD_BITS 8
|
||||||
|
#define LCD_PARAM_BITS 8
|
||||||
|
|
||||||
|
// Pin may vary based on your schematic.
|
||||||
|
#define PIN_SDA GPIO_NUM_21
|
||||||
|
#define PIN_SCL GPIO_NUM_22
|
||||||
|
#define PIN_RST -1
|
||||||
|
|
||||||
|
class SSD1306 : public PanelDevice<esp_lcd_panel_ssd1306_config_t> {
|
||||||
|
public:
|
||||||
|
explicit SSD1306(esp_lcd_panel_ssd1306_config_t ssd_config,
|
||||||
|
int width = SCREEN_WIDTH, int height = SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
~SSD1306() = default;
|
||||||
|
|
||||||
|
// For LV_COLOR_FORMAT_I1 we need an extra buffer to hold the converted data.
|
||||||
|
static uint8_t oled_buffer_[LCD_H_RES * LCD_V_RES / 8];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SSD1306_H
|
Loading…
x
Reference in New Issue
Block a user