M5stack CoreS3 support (#71)

This commit is contained in:
Ken Van Hoeylandt
2024-11-07 23:17:26 +01:00
committed by GitHub
parent 68aa34ad14
commit 67b9fc710a
30 changed files with 355 additions and 334 deletions
+5
View File
@@ -0,0 +1,5 @@
idf_component_register(
SRC_DIRS "src"
INCLUDE_DIRS "src"
REQUIRES tactility esp_lvgl_port M5Unified
)
@@ -0,0 +1,18 @@
#include "M5Unified.hpp"
#include "log.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TAG "m5stack_bootstrap"
bool m5stack_bootstrap() {
TT_LOG_I(TAG, "Initializing M5Unified");
M5.begin();
return true;
}
#ifdef __cplusplus
}
#endif
+46
View File
@@ -0,0 +1,46 @@
#include "esp_lvgl_port.h"
#include "log.h"
#include "thread.h"
#include "ui/lvgl_sync.h"
#define TAG "cores3_lvgl"
extern _Nullable lv_disp_t* m5stack_lvgl_display(bool usePsram);
extern _Nullable lv_indev_t* m5stack_lvgl_touch();
bool m5stack_lvgl_init() {
static lv_display_t* display = NULL;
const lvgl_port_cfg_t lvgl_cfg = {
.task_priority = ThreadPriorityHigh,
.task_stack = 8096,
.task_affinity = -1, // core pinning
.task_max_sleep_ms = 500,
.timer_period_ms = 5
};
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
TT_LOG_E(TAG, "lvgl_port_init failed");
return false;
}
// Add display
display = m5stack_lvgl_display(true);
if (display == NULL) {
TT_LOG_E(TAG, "failed to add display");
return false;
}
// Add touch
lv_indev_t* touch_indev = m5stack_lvgl_touch();
if (touch_indev == NULL) {
TT_LOG_E(TAG, "failed to add touch");
return false;
}
lv_indev_set_display(touch_indev, display);
// Set syncing functions
tt_lvgl_sync_set(&lvgl_port_lock, &lvgl_port_unlock);
return true;
}
@@ -0,0 +1,69 @@
#include "tactility_core.h"
#include "M5Unified.hpp"
#include "esp_err.h"
#include "esp_lvgl_port.h"
#ifdef __cplusplus
extern "C" {
#endif
static void flush_callback(lv_display_t* display, const lv_area_t* area, uint8_t* px_map) {
M5GFX& gfx = *(M5GFX*)lv_display_get_driver_data(display);
int32_t width = (area->x2 - area->x1 + 1);
int32_t height = (area->y2 - area->y1 + 1);
gfx.startWrite();
gfx.setAddrWindow(area->x1, area->y1, width, height);
gfx.writePixels((lgfx::rgb565_t*)px_map, width * height);
gfx.endWrite();
lv_display_flush_ready(display);
}
_Nullable lv_disp_t* m5stack_lvgl_display(bool usePsram) {
M5GFX& gfx = M5.Display;
static lv_display_t* display = lv_display_create(gfx.width(), gfx.height());
LV_ASSERT_MALLOC(display)
if (display == nullptr) {
return nullptr;
}
lv_display_set_driver_data(display, &gfx);
lv_display_set_flush_cb(display, flush_callback);
const size_t bytes_per_pixel = 2; // assume 16-bit color
const size_t buffer_size = gfx.width() * gfx.height() * bytes_per_pixel / 8;
if (usePsram) {
static auto* buffer1 = (uint8_t*)heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM);
LV_ASSERT_MALLOC(buffer1)
static auto* buffer2 = (uint8_t*)heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM);
LV_ASSERT_MALLOC(buffer2)
lv_display_set_buffers(
display,
(void*)buffer1,
(void*)buffer2,
buffer_size,
LV_DISPLAY_RENDER_MODE_PARTIAL
);
} else {
static auto* buffer = (uint8_t*)malloc(buffer_size);
LV_ASSERT_MALLOC(buffer)
lv_display_set_buffers(
display,
(void*)buffer,
nullptr,
buffer_size,
LV_DISPLAY_RENDER_MODE_PARTIAL
);
}
return display;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,37 @@
#include "M5Unified.hpp"
#include "lvgl.h"
#include "tactility_core.h"
#define TAG "cores3_touch"
#ifdef __cplusplus
extern "C" {
#endif
static void touch_read_callback(TT_UNUSED lv_indev_t* indev, lv_indev_data_t* data) {
lgfx::touch_point_t point; // Making it static makes it unreliable
bool touched = M5.Lcd.getTouch(&point) > 0;
if (!touched) {
data->state = LV_INDEV_STATE_REL;
} else {
data->state = LV_INDEV_STATE_PR;
data->point.x = point.x;
data->point.y = point.y;
}
}
_Nullable lv_indev_t* m5stack_lvgl_touch() {
static lv_indev_t* indev = lv_indev_create();
LV_ASSERT_MALLOC(indev)
if (indev == nullptr) {
return nullptr;
}
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, touch_read_callback);
return indev;
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,46 @@
#include "power.h"
#include "M5Unified.hpp"
#ifdef __cplusplus
extern "C" {
#endif
/**
* M5.Power by default doesn't have a check to see if charging is enabled.
* However, it's always enabled by default after boot, so we cover that here:
*/
static bool is_charging_enabled = true;
static bool power_is_charging() {
return M5.Power.isCharging() == m5::Power_Class::is_charging;
}
static bool power_is_charging_enabled() {
return is_charging_enabled;
}
static void power_set_charging_enabled(bool enabled) {
is_charging_enabled = enabled; // Local shadow copy because M5 API doesn't provide a function for it
M5.Power.setBatteryCharge(enabled);
}
static uint8_t power_get_charge_level() {
uint16_t scaled = (uint16_t)M5.Power.getBatteryLevel() * 255 / 100;
return (uint8_t)scaled;
}
static int32_t power_get_current() {
return M5.Power.getBatteryCurrent();
}
Power m5stack_power = {
.is_charging = &power_is_charging,
.is_charging_enabled = &power_is_charging_enabled,
.set_charging_enabled = &power_set_charging_enabled,
.get_charge_level = &power_get_charge_level,
.get_current = &power_get_current
};
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,18 @@
#pragma once
#include "power.h"
#include "sdcard.h"
#ifdef __cplusplus
extern "C" {
#endif
extern bool m5stack_lvgl_init();
extern bool m5stack_bootstrap();
extern Power m5stack_power;
extern const SdCard m5stack_sdcard;
#ifdef __cplusplus
}
#endif