Re-implement Core2 and other improvements (#141)
- Create real drivers instead of wrapping M5Unified/M5GFX - Display HAL improvements (better default base class behaviour) - Fixed bug with LVGL statusbar service locking (would hang indefinitely waiting for mutex, causing WDT issues) - Fixes for `Critical.h` - Fixes and improvements for `Dispatcher` and `DispatcherThread`
This commit is contained in:
parent
50bd6e8bf6
commit
9581978fc7
@ -117,12 +117,12 @@ bool TdeckDisplay::start() {
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_swap_xy(panelHandle, true) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to init panel");
|
||||
TT_LOG_E(TAG, "Failed to swap XY ");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_mirror(panelHandle, true, false) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to init panel");
|
||||
TT_LOG_E(TAG, "Failed to mirror panel");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "Source"
|
||||
SRC_DIRS "Source" "Source/hal" "Source/ft6x36"
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility M5stackShared M5Unified
|
||||
REQUIRES Tactility esp_lvgl_port esp_lcd esp_lcd_ili9341 driver vfs fatfs M5Unified
|
||||
)
|
||||
|
||||
68
Boards/M5stackCore2/Source/InitBoot.cpp
Normal file
68
Boards/M5stackCore2/Source/InitBoot.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <driver/i2c.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include <intr_types.h>
|
||||
#include "Log.h"
|
||||
#include "hal/Core2DisplayConstants.h"
|
||||
#include "M5Unified/src/utility/AXP192_Class.hpp"
|
||||
|
||||
#define TAG "core2"
|
||||
|
||||
#define CORE2_SPI2_PIN_SCLK GPIO_NUM_18
|
||||
#define CORE2_SPI2_PIN_MOSI GPIO_NUM_23
|
||||
#define CORE2_SPI2_PIN_MISO GPIO_NUM_38
|
||||
|
||||
m5::I2C_Class i2c;
|
||||
m5::AXP192_Class axpDevice(0x34, 400000, &i2c);
|
||||
|
||||
static bool initSpi2() {
|
||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, SPI2_HOST);
|
||||
const spi_bus_config_t bus_config = {
|
||||
.mosi_io_num = CORE2_SPI2_PIN_MOSI,
|
||||
.miso_io_num = CORE2_SPI2_PIN_MISO,
|
||||
.sclk_io_num = CORE2_SPI2_PIN_SCLK,
|
||||
.data2_io_num = GPIO_NUM_NC,
|
||||
.data3_io_num = GPIO_NUM_NC,
|
||||
.data4_io_num = GPIO_NUM_NC,
|
||||
.data5_io_num = GPIO_NUM_NC,
|
||||
.data6_io_num = GPIO_NUM_NC,
|
||||
.data7_io_num = GPIO_NUM_NC,
|
||||
.max_transfer_sz = CORE2_LCD_DRAW_BUFFER_SIZE,
|
||||
.flags = 0,
|
||||
.isr_cpu_id = INTR_CPU_ID_AUTO,
|
||||
.intr_flags = 0
|
||||
};
|
||||
|
||||
if (spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, SPI2_HOST);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool initAxp() {
|
||||
if (!i2c.begin(I2C_NUM_0, GPIO_NUM_21, GPIO_NUM_22)) {
|
||||
TT_LOG_E(TAG, "I2C init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!axpDevice.begin()) {
|
||||
TT_LOG_E(TAG, "AXP init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
axpDevice.setLDO2(3300); // LCD + SD peripheral power supply
|
||||
axpDevice.setLDO3(0); // VIB_MOTOR STOP
|
||||
axpDevice.setGPIO2(false); // SPEAKER STOP
|
||||
axpDevice.writeRegister8(0x9A, 255); // PWM 255 (LED OFF)
|
||||
axpDevice.writeRegister8(0x92, 0x02); // GPIO1 PWM
|
||||
axpDevice.setChargeCurrent(390); // Core2 battery = 390mAh
|
||||
axpDevice.setDCDC3(3300);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool initBoot() {
|
||||
TT_LOG_I(TAG, "initBoot");
|
||||
return initAxp() && initSpi2();
|
||||
}
|
||||
3
Boards/M5stackCore2/Source/InitBoot.h
Normal file
3
Boards/M5stackCore2/Source/InitBoot.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
bool initBoot();
|
||||
31
Boards/M5stackCore2/Source/InitLvgl.cpp
Normal file
31
Boards/M5stackCore2/Source/InitLvgl.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
#include "lvgl/LvglSync.h"
|
||||
#include "esp_lvgl_port.h"
|
||||
|
||||
#define TAG "core2"
|
||||
|
||||
// LVGL
|
||||
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
||||
// At 4000, it crashes when the fps renderer is available
|
||||
#define CORE2_LVGL_TASK_STACK_DEPTH 8192
|
||||
|
||||
bool initLvgl() {
|
||||
const lvgl_port_cfg_t lvgl_cfg = {
|
||||
.task_priority = tt::THREAD_PRIORITY_RENDER,
|
||||
.task_stack = CORE2_LVGL_TASK_STACK_DEPTH,
|
||||
.task_affinity = -1, // core pinning
|
||||
.task_max_sleep_ms = 500,
|
||||
.timer_period_ms = 5
|
||||
};
|
||||
|
||||
TT_LOG_D(TAG, "LVGL port init");
|
||||
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "LVGL port init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
||||
|
||||
return true;
|
||||
}
|
||||
3
Boards/M5stackCore2/Source/InitLvgl.h
Normal file
3
Boards/M5stackCore2/Source/InitLvgl.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
bool initLvgl();
|
||||
@ -1,18 +1,22 @@
|
||||
#include "M5stackCore2.h"
|
||||
#include "M5stackShared.h"
|
||||
#include "InitBoot.h"
|
||||
#include "InitLvgl.h"
|
||||
#include "hal/Core2Display.h"
|
||||
#include "hal/Core2SdCard.h"
|
||||
#include "hal/Core2Power.h"
|
||||
|
||||
extern const tt::hal::Configuration m5stack_core2 = {
|
||||
.initBoot = m5stack_bootstrap,
|
||||
.initLvgl = m5stack_lvgl_init,
|
||||
.initBoot = initBoot,
|
||||
.initLvgl = initLvgl,
|
||||
.createDisplay = createDisplay,
|
||||
.sdcard = createM5SdCard(),
|
||||
.power = m5stack_get_power,
|
||||
.sdcard = createSdCard(),
|
||||
.power = createPower,
|
||||
.i2c = {
|
||||
tt::hal::i2c::Configuration {
|
||||
.name = "Internal",
|
||||
.port = I2C_NUM_0,
|
||||
.initMode = tt::hal::i2c::InitByExternal,
|
||||
.canReinit = false,
|
||||
.initMode = tt::hal::i2c::InitByTactility,
|
||||
.canReinit = false, // Might be set to try after trying out what it does AXP and screen
|
||||
.hasMutableConfiguration = false,
|
||||
.config = (i2c_config_t) {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
@ -29,7 +33,7 @@ extern const tt::hal::Configuration m5stack_core2 = {
|
||||
tt::hal::i2c::Configuration {
|
||||
.name = "External", // (Grove)
|
||||
.port = I2C_NUM_1,
|
||||
.initMode = tt::hal::i2c::InitByExternal,
|
||||
.initMode = tt::hal::i2c::InitByTactility,
|
||||
.canReinit = true,
|
||||
.hasMutableConfiguration = true,
|
||||
.config = (i2c_config_t) {
|
||||
|
||||
378
Boards/M5stackCore2/Source/ft6x36/FT6X36.cpp
Normal file
378
Boards/M5stackCore2/Source/ft6x36/FT6X36.cpp
Normal file
@ -0,0 +1,378 @@
|
||||
#include "FT6X36.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#define CONFIG_FT6X36_DEBUG false
|
||||
|
||||
FT6X36 *FT6X36::_instance = nullptr;
|
||||
static const char *TAG = "i2c-touch";
|
||||
|
||||
//Handle indicating I2C is ready to read the touch
|
||||
SemaphoreHandle_t TouchSemaphore = xSemaphoreCreateBinary();
|
||||
|
||||
FT6X36::FT6X36(i2c_port_t port, gpio_num_t interruptPin)
|
||||
{
|
||||
_instance = this;
|
||||
_port = port;
|
||||
_intPin = interruptPin;
|
||||
}
|
||||
|
||||
// Destructor should detach interrupt to the pin
|
||||
FT6X36::~FT6X36()
|
||||
{
|
||||
if (_intPin >= 0)
|
||||
gpio_isr_handler_remove((gpio_num_t)_intPin);
|
||||
}
|
||||
|
||||
bool FT6X36::begin(uint8_t threshold, uint16_t width, uint16_t height)
|
||||
{
|
||||
_touch_width = width;
|
||||
_touch_height = height;
|
||||
if (width == 0 || height ==0) {
|
||||
ESP_LOGE(TAG,"begin(uint8_t threshold, uint16_t width, uint16_t height) did not receive the width / height so touch cannot be rotation aware");
|
||||
}
|
||||
|
||||
uint8_t data_panel_id;
|
||||
readRegister8(FT6X36_REG_PANEL_ID, &data_panel_id);
|
||||
|
||||
if (data_panel_id != FT6X36_VENDID) {
|
||||
ESP_LOGE(TAG,"FT6X36_VENDID does not match. Received:0x%x Expected:0x%x\n",data_panel_id,FT6X36_VENDID);
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_panel_id);
|
||||
|
||||
uint8_t chip_id;
|
||||
readRegister8(FT6X36_REG_CHIPID, &chip_id);
|
||||
if (chip_id != FT6206_CHIPID && chip_id != FT6236_CHIPID && chip_id != FT6336_CHIPID) {
|
||||
ESP_LOGE(TAG,"FT6206_CHIPID does not match. Received:0x%x\n",chip_id);
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAG, "\tFound touch controller with Chip ID: 0x%02x", chip_id);
|
||||
|
||||
if (_intPin >= 0)
|
||||
{
|
||||
// INT pin triggers the callback function on the Falling edge of the GPIO
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_NEGEDGE; // GPIO_INTR_NEGEDGE repeats always interrupt
|
||||
io_conf.pin_bit_mask = 1ULL<<_intPin;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_down_en = (gpio_pulldown_t) 0; // disable pull-down mode
|
||||
io_conf.pull_up_en = (gpio_pullup_t) 1; // pull-up mode
|
||||
gpio_config(&io_conf);
|
||||
|
||||
esp_err_t isr_service = gpio_install_isr_service(0);
|
||||
printf("ISR trigger install response: 0x%x %s\n", isr_service, (isr_service==0)?"ESP_OK":"");
|
||||
gpio_isr_handler_add((gpio_num_t)_intPin, isr, (void*) 1);
|
||||
}
|
||||
|
||||
writeRegister8(FT6X36_REG_DEVICE_MODE, 0x00);
|
||||
writeRegister8(FT6X36_REG_THRESHHOLD, threshold);
|
||||
writeRegister8(FT6X36_REG_TOUCHRATE_ACTIVE, 0x0E);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FT6X36::registerTouchHandler(void (*fn)(TPoint point, TEvent e))
|
||||
{
|
||||
_touchHandler = fn;
|
||||
if (CONFIG_FT6X36_DEBUG) printf("Touch handler function registered\n");
|
||||
}
|
||||
|
||||
uint8_t FT6X36::touched()
|
||||
{
|
||||
uint8_t data_buf;
|
||||
esp_err_t ret = readRegister8(FT6X36_REG_NUM_TOUCHES, &data_buf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
if (data_buf > 2)
|
||||
{
|
||||
data_buf = 0;
|
||||
}
|
||||
|
||||
return data_buf;
|
||||
}
|
||||
|
||||
void FT6X36::loop()
|
||||
{
|
||||
processTouch();
|
||||
}
|
||||
|
||||
void IRAM_ATTR FT6X36::isr(void* arg)
|
||||
{
|
||||
/* Un-block the interrupt processing task now */
|
||||
xSemaphoreGive(TouchSemaphore);
|
||||
//xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
|
||||
}
|
||||
|
||||
void FT6X36::processTouch()
|
||||
{
|
||||
/* Task move to Block state to wait for interrupt event */
|
||||
if (_intPin >= 0)
|
||||
{
|
||||
if (xSemaphoreTake(TouchSemaphore, portMAX_DELAY) == false) return;
|
||||
}
|
||||
|
||||
readData();
|
||||
uint8_t n = 0;
|
||||
TRawEvent event = (TRawEvent)_touchEvent[n];
|
||||
TPoint point{_touchX[n], _touchY[n]};
|
||||
|
||||
switch (event) {
|
||||
|
||||
case TRawEvent::PressDown:
|
||||
_points[0] = point;
|
||||
_dragMode = false;
|
||||
// Note: Is in microseconds. Ref https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
|
||||
_touchStartTime = esp_timer_get_time()/1000;
|
||||
fireEvent(point, TEvent::TouchStart);
|
||||
break;
|
||||
|
||||
case TRawEvent::Contact:
|
||||
// Dragging makes no sense IMHO. Since the X & Y are not getting updated while dragging
|
||||
// Dragging && _points[0].aboutEqual(point) - Not used IDEA 2: && (lastEvent == 2)
|
||||
if (!_dragMode &&
|
||||
(abs(lastX-_touchX[n]) <= maxDeviation || abs(lastY-_touchY[n])<=maxDeviation) &&
|
||||
esp_timer_get_time()/1000 - _touchStartTime > 300) {
|
||||
_dragMode = true;
|
||||
fireEvent(point, TEvent::DragStart);
|
||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
||||
printf("EV: DragStart\n");
|
||||
#endif
|
||||
|
||||
} else if (_dragMode) {
|
||||
fireEvent(point, TEvent::DragMove);
|
||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
||||
printf("EV: DragMove\n");
|
||||
#endif
|
||||
}
|
||||
fireEvent(point, TEvent::TouchMove);
|
||||
|
||||
// For me the _touchStartTime shouold be set in both PressDown & Contact events, but after Drag detection
|
||||
_touchStartTime = esp_timer_get_time()/1000;
|
||||
break;
|
||||
|
||||
case TRawEvent::LiftUp:
|
||||
|
||||
_points[9] = point;
|
||||
_touchEndTime = esp_timer_get_time()/1000;
|
||||
|
||||
//printf("TIMEDIFF: %lu End: %lu\n", _touchEndTime - _touchStartTime, _touchEndTime);
|
||||
|
||||
fireEvent(point, TEvent::TouchEnd);
|
||||
if (_dragMode) {
|
||||
fireEvent(point, TEvent::DragEnd);
|
||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
||||
printf("EV: DragEnd\n");
|
||||
#endif
|
||||
_dragMode = false;
|
||||
}
|
||||
|
||||
if ( _touchEndTime - _touchStartTime <= 900) {
|
||||
// Do not get why this: _points[0].aboutEqual(point) (Original library)
|
||||
fireEvent(point, TEvent::Tap);
|
||||
_points[0] = {0, 0};
|
||||
_touchStartTime = 0;
|
||||
|
||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
||||
printf("EV: Tap\n");
|
||||
#endif
|
||||
_dragMode = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TRawEvent::NoEvent:
|
||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
||||
printf("EV: NoEvent\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
// Store lastEvent
|
||||
lastEvent = (int) event;
|
||||
lastX = _touchX[0];
|
||||
lastY = _touchY[0];
|
||||
}
|
||||
|
||||
void FT6X36::poll(TPoint * point, TEvent * e)
|
||||
{
|
||||
readData();
|
||||
// TPoint point{_touchX[0], _touchY[0]};
|
||||
TRawEvent event = (TRawEvent)_touchEvent[0];
|
||||
|
||||
if (point != NULL)
|
||||
{
|
||||
point->x = _touchX[0];
|
||||
point->y = _touchY[0];
|
||||
}
|
||||
if (e != NULL)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case TRawEvent::PressDown:
|
||||
*e = TEvent::TouchStart;
|
||||
break;
|
||||
case TRawEvent::Contact:
|
||||
*e = TEvent::TouchMove;
|
||||
break;
|
||||
case TRawEvent::LiftUp:
|
||||
default:
|
||||
*e = TEvent::TouchEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t FT6X36::read8(uint8_t regName) {
|
||||
uint8_t buf;
|
||||
readRegister8(regName, &buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define data_size 16 // Discarding last 2: 0x0E & 0x0F as not relevant
|
||||
bool FT6X36::readData(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t data[data_size];
|
||||
uint8_t touch_pnt_cnt; // Number of detected touch points
|
||||
readRegister8(FT6X36_REG_NUM_TOUCHES, &touch_pnt_cnt);
|
||||
|
||||
// Read data
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1), ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, 0, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1)|1, ACK_CHECK_EN);
|
||||
i2c_master_read(cmd, data, data_size, I2C_MASTER_LAST_NACK);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
if (CONFIG_FT6X36_DEBUG) {
|
||||
//printf("REGISTERS:\n");
|
||||
for (int16_t i = 0; i < data_size; i++)
|
||||
{
|
||||
printf("%x:%x ", i, data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
const uint8_t addrShift = 6;
|
||||
|
||||
// READ X, Y and Touch events (X 2)
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
{
|
||||
_touchX[i] = data[FT6X36_REG_P1_XH + i * addrShift] & 0x0F;
|
||||
_touchX[i] <<= 8;
|
||||
_touchX[i] |= data[FT6X36_REG_P1_XL + i * addrShift];
|
||||
_touchY[i] = data[FT6X36_REG_P1_YH + i * addrShift] & 0x0F;
|
||||
_touchY[i] <<= 8;
|
||||
_touchY[i] |= data[FT6X36_REG_P1_YL + i * addrShift];
|
||||
_touchEvent[i] = data[FT6X36_REG_P1_XH + i * addrShift] >> 6;
|
||||
}
|
||||
|
||||
// Make _touchX[idx] and _touchY[idx] rotation aware
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
swap(_touchX[0], _touchY[0]);
|
||||
swap(_touchX[1], _touchY[1]);
|
||||
_touchY[0] = _touch_width - _touchY[0] -1;
|
||||
_touchY[1] = _touch_width - _touchY[1] -1;
|
||||
break;
|
||||
case 2:
|
||||
_touchX[0] = _touch_width - _touchX[0] - 1;
|
||||
_touchX[1] = _touch_width - _touchX[1] - 1;
|
||||
_touchY[0] = _touch_height - _touchY[0] - 1;
|
||||
_touchY[1] = _touch_height - _touchY[1] - 1;
|
||||
break;
|
||||
case 3:
|
||||
swap(_touchX[0], _touchY[0]);
|
||||
swap(_touchX[1], _touchY[1]);
|
||||
_touchX[0] = _touch_height - _touchX[0] - 1;
|
||||
_touchX[1] = _touch_height - _touchX[1] - 1;
|
||||
break;
|
||||
}
|
||||
if (CONFIG_FT6X36_DEBUG) {
|
||||
printf("X0:%d Y0:%d EVENT:%d\n", _touchX[0], _touchY[0], _touchEvent[0]);
|
||||
//printf("X1:%d Y1:%d EVENT:%d\n", _touchX[1], _touchY[1], _touchEvent[1]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FT6X36::writeRegister8(uint8_t reg, uint8_t value)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, FT6X36_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, reg , ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, value , ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
uint8_t FT6X36::readRegister8(uint8_t reg, uint8_t *data_buf)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, FT6X36_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, reg, I2C_MASTER_ACK);
|
||||
// Research: Why it's started a 2nd time here
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (FT6X36_ADDR << 1) | I2C_MASTER_READ, true);
|
||||
|
||||
i2c_master_read_byte(cmd, data_buf, I2C_MASTER_NACK);
|
||||
i2c_master_stop(cmd);
|
||||
esp_err_t ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
|
||||
//FT6X36_REG_GESTURE_ID. Check if it can be read!
|
||||
#if defined(FT6X36_DEBUG) && FT6X36_DEBUG==1
|
||||
printf("REG 0x%x: 0x%x\n",reg,ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FT6X36::fireEvent(TPoint point, TEvent e)
|
||||
{
|
||||
if (_touchHandler)
|
||||
_touchHandler(point, e);
|
||||
}
|
||||
|
||||
void FT6X36::debugInfo()
|
||||
{
|
||||
printf(" TH_DIFF: %d CTRL: %d\n", read8(FT6X36_REG_FILTER_COEF), read8(FT6X36_REG_CTRL));
|
||||
printf(" TIMEENTERMONITOR: %d PERIODACTIVE: %d\n", read8(FT6X36_REG_TIME_ENTER_MONITOR), read8(FT6X36_REG_TOUCHRATE_ACTIVE));
|
||||
printf(" PERIODMONITOR: %d RADIAN_VALUE: %d\n", read8(FT6X36_REG_TOUCHRATE_MONITOR), read8(FT6X36_REG_RADIAN_VALUE));
|
||||
printf(" OFFSET_LEFT_RIGHT: %d OFFSET_UP_DOWN: %d\n", read8(FT6X36_REG_OFFSET_LEFT_RIGHT), read8(FT6X36_REG_OFFSET_UP_DOWN));
|
||||
printf("DISTANCE_LEFT_RIGHT: %d DISTANCE_UP_DOWN: %d\n", read8(FT6X36_REG_DISTANCE_LEFT_RIGHT), read8(FT6X36_REG_DISTANCE_UP_DOWN));
|
||||
printf(" DISTANCE_ZOOM: %d CIPHER: %d\n", read8(FT6X36_REG_DISTANCE_ZOOM), read8(FT6X36_REG_CHIPID));
|
||||
printf(" G_MODE: %d PWR_MODE: %d\n", read8(FT6X36_REG_INTERRUPT_MODE), read8(FT6X36_REG_POWER_MODE));
|
||||
printf(" FIRMID: %d FOCALTECH_ID: %d STATE: %d\n", read8(FT6X36_REG_FIRMWARE_VERSION), read8(FT6X36_REG_PANEL_ID), read8(FT6X36_REG_STATE));
|
||||
}
|
||||
|
||||
void FT6X36::setRotation(uint8_t rotation) {
|
||||
_rotation = rotation;
|
||||
}
|
||||
|
||||
void FT6X36::setTouchWidth(uint16_t width) {
|
||||
printf("touch w:%d\n",width);
|
||||
_touch_width = width;
|
||||
}
|
||||
|
||||
void FT6X36::setTouchHeight(uint16_t height) {
|
||||
printf("touch h:%d\n",height);
|
||||
_touch_height = height;
|
||||
}
|
||||
184
Boards/M5stackCore2/Source/ft6x36/FT6X36.h
Normal file
184
Boards/M5stackCore2/Source/ft6x36/FT6X36.h
Normal file
@ -0,0 +1,184 @@
|
||||
#include <stdint.h>
|
||||
#include <cstdlib>
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "sdkconfig.h"
|
||||
#include <esp_timer.h>
|
||||
|
||||
#ifndef ft6x36_h
|
||||
#define ft6x36_h
|
||||
// I2C Constants
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
|
||||
//SemaphoreHandle_t print_mux = NULL;
|
||||
|
||||
#define FT6X36_ADDR 0x38
|
||||
|
||||
#define FT6X36_REG_DEVICE_MODE 0x00
|
||||
#define FT6X36_REG_GESTURE_ID 0x01
|
||||
#define FT6X36_REG_NUM_TOUCHES 0x02
|
||||
#define FT6X36_REG_P1_XH 0x03
|
||||
#define FT6X36_REG_P1_XL 0x04
|
||||
#define FT6X36_REG_P1_YH 0x05
|
||||
#define FT6X36_REG_P1_YL 0x06
|
||||
#define FT6X36_REG_P1_WEIGHT 0x07
|
||||
#define FT6X36_REG_P1_MISC 0x08
|
||||
#define FT6X36_REG_P2_XH 0x09
|
||||
#define FT6X36_REG_P2_XL 0x0A
|
||||
#define FT6X36_REG_P2_YH 0x0B
|
||||
#define FT6X36_REG_P2_YL 0x0C
|
||||
#define FT6X36_REG_P2_WEIGHT 0x0D
|
||||
#define FT6X36_REG_P2_MISC 0x0E
|
||||
#define FT6X36_REG_THRESHHOLD 0x80
|
||||
#define FT6X36_REG_FILTER_COEF 0x85
|
||||
#define FT6X36_REG_CTRL 0x86
|
||||
#define FT6X36_REG_TIME_ENTER_MONITOR 0x87
|
||||
#define FT6X36_REG_TOUCHRATE_ACTIVE 0x88
|
||||
#define FT6X36_REG_TOUCHRATE_MONITOR 0x89 // value in ms
|
||||
#define FT6X36_REG_RADIAN_VALUE 0x91
|
||||
#define FT6X36_REG_OFFSET_LEFT_RIGHT 0x92
|
||||
#define FT6X36_REG_OFFSET_UP_DOWN 0x93
|
||||
#define FT6X36_REG_DISTANCE_LEFT_RIGHT 0x94
|
||||
#define FT6X36_REG_DISTANCE_UP_DOWN 0x95
|
||||
#define FT6X36_REG_DISTANCE_ZOOM 0x96
|
||||
#define FT6X36_REG_LIB_VERSION_H 0xA1
|
||||
#define FT6X36_REG_LIB_VERSION_L 0xA2
|
||||
#define FT6X36_REG_CHIPID 0xA3
|
||||
#define FT6X36_REG_INTERRUPT_MODE 0xA4
|
||||
#define FT6X36_REG_POWER_MODE 0xA5
|
||||
#define FT6X36_REG_FIRMWARE_VERSION 0xA6
|
||||
#define FT6X36_REG_PANEL_ID 0xA8
|
||||
#define FT6X36_REG_STATE 0xBC
|
||||
|
||||
#define FT6X36_PMODE_ACTIVE 0x00
|
||||
#define FT6X36_PMODE_MONITOR 0x01
|
||||
#define FT6X36_PMODE_STANDBY 0x02
|
||||
#define FT6X36_PMODE_HIBERNATE 0x03
|
||||
|
||||
/* Possible values returned by FT6X36_GEST_ID_REG */
|
||||
#define FT6X36_GEST_ID_NO_GESTURE 0x00
|
||||
#define FT6X36_GEST_ID_MOVE_UP 0x10
|
||||
#define FT6X36_GEST_ID_MOVE_RIGHT 0x14
|
||||
#define FT6X36_GEST_ID_MOVE_DOWN 0x18
|
||||
#define FT6X36_GEST_ID_MOVE_LEFT 0x1C
|
||||
#define FT6X36_GEST_ID_ZOOM_IN 0x48
|
||||
#define FT6X36_GEST_ID_ZOOM_OUT 0x49
|
||||
|
||||
#define FT6X36_VENDID 0x11
|
||||
#define FT6206_CHIPID 0x06
|
||||
#define FT6236_CHIPID 0x36
|
||||
#define FT6336_CHIPID 0x64
|
||||
|
||||
#define FT6X36_DEFAULT_THRESHOLD 22
|
||||
|
||||
// From: https://github.com/lvgl/lv_port_esp32/blob/master/components/lvgl_esp32_drivers/lvgl_touch/ft6x36.h
|
||||
#define FT6X36_MSB_MASK 0x0F
|
||||
#define FT6X36_LSB_MASK 0xFF
|
||||
|
||||
enum class TRawEvent
|
||||
{
|
||||
PressDown,
|
||||
LiftUp,
|
||||
Contact,
|
||||
NoEvent
|
||||
};
|
||||
|
||||
enum class TEvent
|
||||
{
|
||||
None,
|
||||
TouchStart,
|
||||
TouchMove,
|
||||
TouchEnd,
|
||||
Tap,
|
||||
DragStart,
|
||||
DragMove,
|
||||
DragEnd
|
||||
};
|
||||
|
||||
struct TPoint
|
||||
{
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
/**
|
||||
* This is being used in the original library but I'm not using it in this implementation
|
||||
*/
|
||||
bool aboutEqual(const TPoint point)
|
||||
{
|
||||
return abs(x - point.x) <= 5 && abs(y - point.y) <= 5;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FT6X36
|
||||
{
|
||||
static void IRAM_ATTR isr(void* arg);
|
||||
public:
|
||||
// TwoWire * wire will be replaced by ESP-IDF https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html
|
||||
FT6X36(i2c_port_t = I2C_NUM_0, gpio_num_t interruptPin = GPIO_NUM_NC);
|
||||
~FT6X36();
|
||||
bool begin(uint8_t threshold = FT6X36_DEFAULT_THRESHOLD, uint16_t width = 0, uint16_t height = 0);
|
||||
void registerTouchHandler(void(*fn)(TPoint point, TEvent e));
|
||||
uint8_t touched();
|
||||
void loop();
|
||||
void processTouch();
|
||||
void debugInfo();
|
||||
void poll(TPoint * point, TEvent * event);
|
||||
// Helper functions to make the touch display aware
|
||||
void setRotation(uint8_t rotation);
|
||||
void setTouchWidth(uint16_t width);
|
||||
void setTouchHeight(uint16_t height);
|
||||
// Pending implementation. How much x->touch y↓touch is placed (In case is smaller than display)
|
||||
void setXoffset(uint16_t x_offset);
|
||||
void setYoffset(uint16_t y_offset);
|
||||
// Smart template from EPD to swap x,y:
|
||||
template <typename T> static inline void
|
||||
swap(T& a, T& b)
|
||||
{
|
||||
T t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
void(*_touchHandler)(TPoint point, TEvent e) = nullptr;
|
||||
|
||||
bool readData(void);
|
||||
private:
|
||||
void writeRegister8(uint8_t reg, uint8_t val);
|
||||
uint8_t readRegister8(uint8_t reg, uint8_t *data_buf);
|
||||
void fireEvent(TPoint point, TEvent e);
|
||||
uint8_t read8(uint8_t regName);
|
||||
static FT6X36 * _instance;
|
||||
|
||||
i2c_port_t _port;
|
||||
int8_t _intPin;
|
||||
|
||||
// Make touch rotation aware:
|
||||
uint8_t _rotation = 0;
|
||||
uint16_t _touch_width = 0;
|
||||
uint16_t _touch_height = 0;
|
||||
|
||||
uint8_t _touches;
|
||||
uint16_t _touchX[2], _touchY[2], _touchEvent[2];
|
||||
TPoint _points[10];
|
||||
uint8_t _pointIdx = 0;
|
||||
unsigned long _touchStartTime = 0;
|
||||
unsigned long _touchEndTime = 0;
|
||||
uint8_t lastEvent = 3; // No event
|
||||
uint16_t lastX = 0;
|
||||
uint16_t lastY = 0;
|
||||
bool _dragMode = false;
|
||||
const uint8_t maxDeviation = 5;
|
||||
};
|
||||
|
||||
#endif
|
||||
21
Boards/M5stackCore2/Source/ft6x36/LICENSE
Normal file
21
Boards/M5stackCore2/Source/ft6x36/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 strange_v
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
8
Boards/M5stackCore2/Source/ft6x36/README.md
Normal file
8
Boards/M5stackCore2/Source/ft6x36/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
This project is an adaption of the code at https://github.com/martinberlin/FT6X36-IDF which is an adaptation of https://github.com/strange-v/FT6X36
|
||||
The original license is an MIT license and is included in this directory.
|
||||
|
||||
Changes:
|
||||
- Remove Kconfig-based configuratio
|
||||
- Removed I2C init code
|
||||
- Allow for passing a different I2C port
|
||||
|
||||
164
Boards/M5stackCore2/Source/hal/Core2Display.cpp
Normal file
164
Boards/M5stackCore2/Source/hal/Core2Display.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include "Core2Display.h"
|
||||
#include "Core2DisplayConstants.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <TactilityCore.h>
|
||||
#include <esp_lcd_panel_commands.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_lcd_ili9341.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lvgl_port.h"
|
||||
#include "Core2Touch.h"
|
||||
|
||||
#define TAG "yellow_display"
|
||||
|
||||
bool Core2Display::start() {
|
||||
TT_LOG_I(TAG, "Starting");
|
||||
|
||||
const esp_lcd_panel_io_spi_config_t panel_io_config = ILI9341_PANEL_IO_SPI_CONFIG(
|
||||
CORE2_LCD_PIN_CS,
|
||||
CORE2_LCD_PIN_DC,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)CORE2_LCD_SPI_HOST, &panel_io_config, &ioHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to create panel");
|
||||
return false;
|
||||
}
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = GPIO_NUM_NC,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = CORE2_LCD_BITS_PER_PIXEL,
|
||||
.flags = {
|
||||
.reset_active_high = false
|
||||
},
|
||||
.vendor_config = nullptr
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_ili9341(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to create ili9341");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to reset panel");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to init panel");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_mirror(panelHandle, false, false) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to set panel to mirror");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_invert_color(panelHandle, true) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to set panel to invert");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to turn display on");
|
||||
return false;
|
||||
}
|
||||
|
||||
const lvgl_port_display_cfg_t disp_cfg = {
|
||||
.io_handle = ioHandle,
|
||||
.panel_handle = panelHandle,
|
||||
.control_handle = nullptr,
|
||||
.buffer_size = CORE2_LCD_DRAW_BUFFER_SIZE,
|
||||
.double_buffer = true,
|
||||
.trans_size = 0,
|
||||
.hres = CORE2_LCD_HORIZONTAL_RESOLUTION,
|
||||
.vres = CORE2_LCD_VERTICAL_RESOLUTION,
|
||||
.monochrome = false,
|
||||
.rotation = {
|
||||
.swap_xy = false,
|
||||
.mirror_x = false,
|
||||
.mirror_y = false,
|
||||
},
|
||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
||||
.flags = {
|
||||
.buff_dma = false,
|
||||
.buff_spiram = true,
|
||||
.sw_rotate = false,
|
||||
.swap_bytes = true,
|
||||
.full_refresh = false,
|
||||
.direct_mode = false
|
||||
}
|
||||
};
|
||||
|
||||
displayHandle = lvgl_port_add_disp(&disp_cfg);
|
||||
TT_LOG_I(TAG, "Finished");
|
||||
return displayHandle != nullptr;
|
||||
}
|
||||
|
||||
bool Core2Display::stop() {
|
||||
tt_assert(displayHandle != nullptr);
|
||||
|
||||
lvgl_port_remove_disp(displayHandle);
|
||||
|
||||
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
displayHandle = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note:
|
||||
* The datasheet implies this should work, but it doesn't:
|
||||
* https://www.digikey.com/htmldatasheets/production/1640716/0/0/1/ILI9341-Datasheet.pdf
|
||||
*
|
||||
* This repo claims it only has 1 curve:
|
||||
* https://github.com/brucemack/hello-ili9341
|
||||
*
|
||||
* I'm leaving it in as I'm not sure if it's just my hardware that's problematic.
|
||||
*/
|
||||
void Core2Display::setGammaCurve(uint8_t index) {
|
||||
uint8_t gamma_curve;
|
||||
switch (index) {
|
||||
case 0:
|
||||
gamma_curve = 0x01;
|
||||
break;
|
||||
case 1:
|
||||
gamma_curve = 0x04;
|
||||
break;
|
||||
case 2:
|
||||
gamma_curve = 0x02;
|
||||
break;
|
||||
case 3:
|
||||
gamma_curve = 0x08;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
const uint8_t param[] = {
|
||||
gamma_curve
|
||||
};
|
||||
|
||||
if (esp_lcd_panel_io_tx_param(ioHandle , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to set gamma");
|
||||
}
|
||||
}
|
||||
|
||||
tt::hal::Touch* _Nullable Core2Display::createTouch() {
|
||||
return static_cast<tt::hal::Touch*>(new Core2Touch());
|
||||
}
|
||||
|
||||
tt::hal::Display* createDisplay() {
|
||||
return static_cast<tt::hal::Display*>(new Core2Display());
|
||||
}
|
||||
34
Boards/M5stackCore2/Source/hal/Core2Display.h
Normal file
34
Boards/M5stackCore2/Source/hal/Core2Display.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "hal/Display.h"
|
||||
|
||||
#include <esp_lcd_types.h>
|
||||
|
||||
extern lv_disp_t* displayHandle;
|
||||
|
||||
class Core2Display : public tt::hal::Display {
|
||||
|
||||
private:
|
||||
|
||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
||||
lv_display_t* displayHandle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
bool start() override;
|
||||
|
||||
bool stop() override;
|
||||
|
||||
tt::hal::Touch* _Nullable createTouch() override;
|
||||
|
||||
bool supportsBacklightDuty() const override { return false; }
|
||||
|
||||
void setGammaCurve(uint8_t index) override;
|
||||
uint8_t getGammaCurveCount() const override { return 4; };
|
||||
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
||||
};
|
||||
|
||||
tt::hal::Display* createDisplay();
|
||||
11
Boards/M5stackCore2/Source/hal/Core2DisplayConstants.h
Normal file
11
Boards/M5stackCore2/Source/hal/Core2DisplayConstants.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// Display
|
||||
#define CORE2_LCD_SPI_HOST SPI2_HOST
|
||||
#define CORE2_LCD_PIN_CS GPIO_NUM_5
|
||||
#define CORE2_LCD_PIN_DC GPIO_NUM_15
|
||||
#define CORE2_LCD_HORIZONTAL_RESOLUTION 320
|
||||
#define CORE2_LCD_VERTICAL_RESOLUTION 240
|
||||
#define CORE2_LCD_BITS_PER_PIXEL 16
|
||||
#define CORE2_LCD_DRAW_BUFFER_HEIGHT (CORE2_LCD_VERTICAL_RESOLUTION / 10)
|
||||
#define CORE2_LCD_DRAW_BUFFER_SIZE (CORE2_LCD_HORIZONTAL_RESOLUTION * CORE2_LCD_DRAW_BUFFER_HEIGHT * (CORE2_LCD_BITS_PER_PIXEL / 8))
|
||||
63
Boards/M5stackCore2/Source/hal/Core2Power.cpp
Normal file
63
Boards/M5stackCore2/Source/hal/Core2Power.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "Core2Power.h"
|
||||
|
||||
#include "utility/AXP192_Class.hpp"
|
||||
#include "TactilityCore.h"
|
||||
|
||||
#define TAG "core2_power"
|
||||
|
||||
extern m5::AXP192_Class axpDevice;
|
||||
|
||||
bool Core2Power::supportsMetric(MetricType type) const {
|
||||
switch (type) {
|
||||
case BATTERY_VOLTAGE:
|
||||
case CHARGE_LEVEL:
|
||||
case IS_CHARGING:
|
||||
return true;
|
||||
case CURRENT:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
|
||||
bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) {
|
||||
switch (type) {
|
||||
case BATTERY_VOLTAGE:
|
||||
data.valueAsUint32 = (uint32_t)TT_MAX((axpDevice.getBatteryVoltage() * 1000.f), 0.0f);
|
||||
return true;
|
||||
case CHARGE_LEVEL: {
|
||||
auto level = axpDevice.getBatteryLevel();
|
||||
if (level > 0) {
|
||||
data.valueAsUint8 = (uint8_t)level;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case IS_CHARGING:
|
||||
data.valueAsBool = axpDevice.isCharging();
|
||||
return true;
|
||||
case CURRENT:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
|
||||
bool Core2Power::isAllowedToCharge() const {
|
||||
return allowedToCharge;
|
||||
}
|
||||
|
||||
void Core2Power::setAllowedToCharge(bool canCharge) {
|
||||
allowedToCharge = canCharge;
|
||||
axpDevice.setBatteryCharge(canCharge);
|
||||
}
|
||||
|
||||
static std::shared_ptr<Power> power;
|
||||
|
||||
std::shared_ptr<Power> createPower() {
|
||||
if (power == nullptr) {
|
||||
power = std::make_shared<Core2Power>();
|
||||
}
|
||||
return power;
|
||||
}
|
||||
27
Boards/M5stackCore2/Source/hal/Core2Power.h
Normal file
27
Boards/M5stackCore2/Source/hal/Core2Power.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "hal/Power.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
class Core2Power : public Power {
|
||||
|
||||
private:
|
||||
|
||||
bool allowedToCharge = true;
|
||||
|
||||
public:
|
||||
|
||||
Core2Power() = default;
|
||||
~Core2Power() override = default;
|
||||
|
||||
bool supportsMetric(MetricType type) const override;
|
||||
bool getMetric(Power::MetricType type, Power::MetricData& data) override;
|
||||
|
||||
bool supportsChargeControl() const override { return true; }
|
||||
bool isAllowedToCharge() const override;
|
||||
void setAllowedToCharge(bool canCharge) override;
|
||||
};
|
||||
|
||||
std::shared_ptr<Power> createPower();
|
||||
31
Boards/M5stackCore2/Source/hal/Core2SdCard.cpp
Normal file
31
Boards/M5stackCore2/Source/hal/Core2SdCard.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "Core2SdCard.h"
|
||||
|
||||
#include "lvgl/LvglSync.h"
|
||||
#include "hal/SpiSdCard.h"
|
||||
|
||||
#include <esp_vfs_fat.h>
|
||||
|
||||
#define CORE2_SDCARD_SPI_FREQUENCY 800000U
|
||||
#define CORE2_SDCARD_PIN_CS GPIO_NUM_4
|
||||
#define CORE2_LCD_PIN_CS GPIO_NUM_5
|
||||
|
||||
std::shared_ptr<SdCard> createSdCard() {
|
||||
auto* configuration = new tt::hal::SpiSdCard::Config(
|
||||
CORE2_SDCARD_SPI_FREQUENCY,
|
||||
CORE2_SDCARD_PIN_CS,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
SdCard::MountBehaviourAtBoot,
|
||||
tt::lvgl::getLvglSyncLockable(),
|
||||
{
|
||||
CORE2_LCD_PIN_CS
|
||||
}
|
||||
);
|
||||
|
||||
auto* sdcard = (SdCard*) new SpiSdCard(
|
||||
std::unique_ptr<SpiSdCard::Config>(configuration)
|
||||
);
|
||||
|
||||
return std::shared_ptr<SdCard>(sdcard);
|
||||
}
|
||||
7
Boards/M5stackCore2/Source/hal/Core2SdCard.h
Normal file
7
Boards/M5stackCore2/Source/hal/Core2SdCard.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "hal/SdCard.h"
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
std::shared_ptr<SdCard> createSdCard();
|
||||
94
Boards/M5stackCore2/Source/hal/Core2Touch.cpp
Normal file
94
Boards/M5stackCore2/Source/hal/Core2Touch.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "Core2Touch.h"
|
||||
#include <esp_lvgl_port.h>
|
||||
|
||||
#define TAG "core2_touch"
|
||||
|
||||
static void touchReadCallback(lv_indev_t* indev, lv_indev_data_t* data) {
|
||||
auto* touch = (Core2Touch*)lv_indev_get_driver_data(indev);
|
||||
touch->readLast(data);
|
||||
}
|
||||
|
||||
static int32_t threadCallback(void* context) {
|
||||
auto* touch = (Core2Touch*)context;
|
||||
touch->driverThreadMain();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Core2Touch::Core2Touch() :
|
||||
driverThread(tt::Thread("core2_touch", 4096, threadCallback, this))
|
||||
{ }
|
||||
|
||||
void Core2Touch::driverThreadMain() {
|
||||
TPoint point = { .x = 0, .y = 0 };
|
||||
TEvent event = TEvent::None;
|
||||
|
||||
while (!shouldInterruptDriverThread()) {
|
||||
driver.processTouch();
|
||||
driver.poll(&point, &event);
|
||||
|
||||
if (mutex.lock(100)) {
|
||||
switch (event) {
|
||||
case TEvent::TouchStart:
|
||||
case TEvent::TouchMove:
|
||||
case TEvent::DragStart:
|
||||
case TEvent::DragMove:
|
||||
case TEvent::DragEnd:
|
||||
lastState = LV_INDEV_STATE_PR;
|
||||
lastPoint.x = point.x;
|
||||
lastPoint.y = point.y;
|
||||
break;
|
||||
case TEvent::TouchEnd:
|
||||
lastState = LV_INDEV_STATE_REL;
|
||||
lastPoint.x = point.x;
|
||||
lastPoint.y = point.y;
|
||||
break;
|
||||
case TEvent::Tap:
|
||||
case TEvent::None:
|
||||
break;
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Core2Touch::shouldInterruptDriverThread() {
|
||||
bool interrupt = false;
|
||||
if (mutex.lock(50 / portTICK_PERIOD_MS)) {
|
||||
interrupt = interruptDriverThread;
|
||||
mutex.unlock();
|
||||
}
|
||||
return interrupt;
|
||||
}
|
||||
|
||||
bool Core2Touch::start(lv_display_t* display) {
|
||||
TT_LOG_I(TAG, "start");
|
||||
|
||||
driverThread.start();
|
||||
|
||||
uint16_t width = lv_display_get_horizontal_resolution(display);
|
||||
uint16_t height = lv_display_get_vertical_resolution(display);
|
||||
if (!driver.begin(FT6X36_DEFAULT_THRESHOLD, width, height)) {
|
||||
TT_LOG_E(TAG, "driver.begin() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceHandle = lv_indev_create();
|
||||
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_driver_data(deviceHandle, this);
|
||||
lv_indev_set_read_cb(deviceHandle, touchReadCallback);
|
||||
|
||||
TT_LOG_I(TAG, "start success");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Core2Touch::stop() {
|
||||
lv_indev_delete(deviceHandle);
|
||||
interruptDriverThread = true;
|
||||
driverThread.join();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Core2Touch::readLast(lv_indev_data_t* data) {
|
||||
data->point = lastPoint;
|
||||
data->state = lastState;
|
||||
}
|
||||
32
Boards/M5stackCore2/Source/hal/Core2Touch.h
Normal file
32
Boards/M5stackCore2/Source/hal/Core2Touch.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "hal/Touch.h"
|
||||
#include "TactilityCore.h"
|
||||
#include "ft6x36/FT6X36.h"
|
||||
|
||||
class Core2Touch : public tt::hal::Touch {
|
||||
|
||||
private:
|
||||
|
||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
||||
FT6X36 driver = FT6X36(I2C_NUM_0, GPIO_NUM_39);
|
||||
tt::Thread driverThread;
|
||||
bool interruptDriverThread = false;
|
||||
tt::Mutex mutex;
|
||||
|
||||
lv_point_t lastPoint = { .x = 0, .y = 0 };
|
||||
lv_indev_state_t lastState = LV_INDEV_STATE_RELEASED;
|
||||
|
||||
bool shouldInterruptDriverThread();
|
||||
|
||||
public:
|
||||
|
||||
Core2Touch();
|
||||
|
||||
bool start(lv_display_t* display) override;
|
||||
bool stop() override;
|
||||
|
||||
void readLast(lv_indev_data_t* data);
|
||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
||||
void driverThreadMain();
|
||||
};
|
||||
@ -17,10 +17,6 @@ public:
|
||||
|
||||
bool stop() override;
|
||||
|
||||
void setPowerOn(bool turnOn) override {}
|
||||
bool isPoweredOn() const override { return true; };
|
||||
bool supportsPowerControl() const override { return false; }
|
||||
|
||||
tt::hal::Touch* _Nullable createTouch() override;
|
||||
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
||||
|
||||
@ -13,10 +13,6 @@ public:
|
||||
|
||||
bool stop() override { tt_crash("Not supported"); }
|
||||
|
||||
void setPowerOn(bool turnOn) override {}
|
||||
bool isPoweredOn() const override { return displayHandle != nullptr; }
|
||||
bool supportsPowerControl() const override { return false; }
|
||||
|
||||
tt::hal::Touch* _Nullable createTouch() override { return dynamic_cast<tt::hal::Touch*>(new SdlTouch()); }
|
||||
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
bool twodotfour_lvgl_init() {
|
||||
const lvgl_port_cfg_t lvgl_cfg = {
|
||||
.task_priority = tt::Thread::PriorityHigh,
|
||||
.task_priority = tt::THREAD_PRIORITY_RENDER,
|
||||
.task_stack = 8096,
|
||||
.task_affinity = -1, // core pinning
|
||||
.task_max_sleep_ms = 500,
|
||||
|
||||
@ -23,7 +23,8 @@ static bool initBacklight() {
|
||||
.duty_resolution = TWODOTFOUR_LCD_BACKLIGHT_LEDC_DUTY_RES,
|
||||
.timer_num = TWODOTFOUR_LCD_BACKLIGHT_LEDC_TIMER,
|
||||
.freq_hz = TWODOTFOUR_LCD_BACKLIGHT_LEDC_FREQUENCY,
|
||||
.clk_cfg = LEDC_AUTO_CLK
|
||||
.clk_cfg = LEDC_AUTO_CLK,
|
||||
.deconfigure = false
|
||||
};
|
||||
|
||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
||||
|
||||
@ -20,10 +20,6 @@ public:
|
||||
|
||||
bool stop() override;
|
||||
|
||||
void setPowerOn(bool turnOn) override {}
|
||||
bool isPoweredOn() const override { return true; };
|
||||
bool supportsPowerControl() const override { return false; }
|
||||
|
||||
tt::hal::Touch* _Nullable createTouch() override;
|
||||
|
||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
// Dipslay backlight (PWM)
|
||||
// Display backlight (PWM)
|
||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_TIMER LEDC_TIMER_0
|
||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_0
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include "esp_lcd_touch.h"
|
||||
#include "esp_lvgl_port.h"
|
||||
|
||||
#define TAG "m5stack_touch"
|
||||
#define TAG "twodotfour_touch"
|
||||
|
||||
bool YellowTouch::start(lv_display_t* display) {
|
||||
TT_LOG_I(TAG, "Starting");
|
||||
|
||||
@ -35,12 +35,12 @@ typedef struct {
|
||||
PubSubSubscription* pubsub_subscription;
|
||||
} Statusbar;
|
||||
|
||||
static void statusbar_lock() {
|
||||
statusbar_data.mutex.acquire(TtWaitForever);
|
||||
static bool statusbar_lock(uint32_t timeoutTicks) {
|
||||
return statusbar_data.mutex.lock(timeoutTicks);
|
||||
}
|
||||
|
||||
static void statusbar_unlock() {
|
||||
statusbar_data.mutex.release();
|
||||
static bool statusbar_unlock() {
|
||||
return statusbar_data.mutex.unlock();
|
||||
}
|
||||
|
||||
static void statusbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj);
|
||||
@ -113,7 +113,7 @@ lv_obj_t* statusbar_create(lv_obj_t* parent) {
|
||||
lv_obj_t* left_spacer = spacer_create(obj, 1, 1);
|
||||
lv_obj_set_flex_grow(left_spacer, 1);
|
||||
|
||||
statusbar_lock();
|
||||
statusbar_lock(TtWaitForever);
|
||||
for (int i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
|
||||
lv_obj_t* image = lv_image_create(obj);
|
||||
lv_obj_set_size(image, STATUSBAR_ICON_SIZE, STATUSBAR_ICON_SIZE);
|
||||
@ -129,11 +129,12 @@ lv_obj_t* statusbar_create(lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
static void update_main(Statusbar* statusbar) {
|
||||
statusbar_lock();
|
||||
for (int i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
|
||||
update_icon(statusbar->icons[i], &(statusbar_data.icons[i]));
|
||||
if (statusbar_lock(50 / portTICK_PERIOD_MS)) {
|
||||
for (int i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
|
||||
update_icon(statusbar->icons[i], &(statusbar_data.icons[i]));
|
||||
}
|
||||
statusbar_unlock();
|
||||
}
|
||||
statusbar_unlock();
|
||||
}
|
||||
|
||||
static void statusbar_event(TT_UNUSED const lv_obj_class_t* class_p, lv_event_t* event) {
|
||||
@ -154,7 +155,7 @@ static void statusbar_event(TT_UNUSED const lv_obj_class_t* class_p, lv_event_t*
|
||||
}
|
||||
|
||||
int8_t statusbar_icon_add(const char* _Nullable image) {
|
||||
statusbar_lock();
|
||||
statusbar_lock(TtWaitForever);
|
||||
int8_t result = -1;
|
||||
for (int8_t i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
|
||||
if (!statusbar_data.icons[i].claimed) {
|
||||
@ -174,7 +175,7 @@ int8_t statusbar_icon_add(const char* _Nullable image) {
|
||||
void statusbar_icon_remove(int8_t id) {
|
||||
TT_LOG_I(TAG, "id %d: remove", id);
|
||||
tt_check(id >= 0 && id < STATUSBAR_ICON_LIMIT);
|
||||
statusbar_lock();
|
||||
statusbar_lock(TtWaitForever);
|
||||
StatusbarIcon* icon = &statusbar_data.icons[id];
|
||||
icon->claimed = false;
|
||||
icon->visible = false;
|
||||
@ -184,25 +185,27 @@ void statusbar_icon_remove(int8_t id) {
|
||||
}
|
||||
|
||||
void statusbar_icon_set_image(int8_t id, const char* image) {
|
||||
TT_LOG_I(TAG, "id %d: set image %s", id, image);
|
||||
TT_LOG_I(TAG, "id %d: set image %s", id, image ? image : "(none)");
|
||||
tt_check(id >= 0 && id < STATUSBAR_ICON_LIMIT);
|
||||
statusbar_lock();
|
||||
StatusbarIcon* icon = &statusbar_data.icons[id];
|
||||
tt_check(icon->claimed);
|
||||
icon->image = image;
|
||||
tt_pubsub_publish(statusbar_data.pubsub, nullptr);
|
||||
statusbar_unlock();
|
||||
if (statusbar_lock(50 / portTICK_PERIOD_MS)) {
|
||||
StatusbarIcon* icon = &statusbar_data.icons[id];
|
||||
tt_check(icon->claimed);
|
||||
icon->image = image;
|
||||
tt_pubsub_publish(statusbar_data.pubsub, nullptr);
|
||||
statusbar_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void statusbar_icon_set_visibility(int8_t id, bool visible) {
|
||||
TT_LOG_I(TAG, "id %d: set visibility %d", id, visible);
|
||||
tt_check(id >= 0 && id < STATUSBAR_ICON_LIMIT);
|
||||
statusbar_lock();
|
||||
StatusbarIcon* icon = &statusbar_data.icons[id];
|
||||
tt_check(icon->claimed);
|
||||
icon->visible = visible;
|
||||
tt_pubsub_publish(statusbar_data.pubsub, nullptr);
|
||||
statusbar_unlock();
|
||||
if (statusbar_lock(50 / portTICK_PERIOD_MS)) {
|
||||
StatusbarIcon* icon = &statusbar_data.icons[id];
|
||||
tt_check(icon->claimed);
|
||||
icon->visible = visible;
|
||||
tt_pubsub_publish(statusbar_data.pubsub, nullptr);
|
||||
statusbar_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "service/wifi/Wifi.h"
|
||||
#include "service/ServiceRegistry.h"
|
||||
#include "TactilityHeadless.h"
|
||||
#include "lvgl/LvglSync.h"
|
||||
|
||||
namespace tt::service::statusbar {
|
||||
|
||||
@ -182,7 +183,10 @@ static void onUpdate(std::shared_ptr<void> parameter) {
|
||||
}
|
||||
|
||||
static void onStart(ServiceContext& service) {
|
||||
lvgl::lock(TtWaitForever);
|
||||
auto data = std::make_shared<ServiceData>();
|
||||
lvgl::unlock();
|
||||
|
||||
service.setData(data);
|
||||
|
||||
// TODO: Make thread-safe for LVGL
|
||||
|
||||
@ -6,6 +6,7 @@ namespace tt {
|
||||
|
||||
#define TAG "Dispatcher"
|
||||
#define BACKPRESSURE_WARNING_COUNT 100
|
||||
#define WAIT_FLAG 1
|
||||
|
||||
Dispatcher::Dispatcher() :
|
||||
mutex(Mutex::TypeNormal)
|
||||
@ -22,13 +23,12 @@ void Dispatcher::dispatch(Callback callback, std::shared_ptr<void> context) {
|
||||
// Mutate
|
||||
if (mutex.lock(1000 / portTICK_PERIOD_MS)) {
|
||||
queue.push(std::move(message));
|
||||
TT_LOG_I(TAG, "dispatch");
|
||||
if (queue.size() == BACKPRESSURE_WARNING_COUNT) {
|
||||
TT_LOG_W(TAG, "Backpressure: You're not consuming fast enough (100 queued)");
|
||||
}
|
||||
mutex.unlock();
|
||||
tt_check(mutex.unlock());
|
||||
// Signal
|
||||
eventFlag.set(1);
|
||||
eventFlag.set(WAIT_FLAG);
|
||||
} else {
|
||||
TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED);
|
||||
}
|
||||
@ -37,15 +37,15 @@ void Dispatcher::dispatch(Callback callback, std::shared_ptr<void> context) {
|
||||
uint32_t Dispatcher::consume(uint32_t timeout_ticks) {
|
||||
// Wait for signal and clear
|
||||
TickType_t start_ticks = kernel::getTicks();
|
||||
if (eventFlag.wait(1, TtFlagWaitAny, timeout_ticks) == TtStatusErrorTimeout) {
|
||||
if (eventFlag.wait(WAIT_FLAG, TtFlagWaitAny, timeout_ticks) == WAIT_FLAG) {
|
||||
eventFlag.clear(WAIT_FLAG);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TickType_t ticks_remaining = TT_MAX(timeout_ticks - (kernel::getTicks() - start_ticks), 0);
|
||||
|
||||
eventFlag.clear(1);
|
||||
|
||||
TT_LOG_I(TAG, "Dispatcher continuing");
|
||||
TT_LOG_I(TAG, "Dispatcher continuing (%d ticks)", (int)ticks_remaining);
|
||||
|
||||
// Mutate
|
||||
bool processing = true;
|
||||
@ -53,16 +53,15 @@ uint32_t Dispatcher::consume(uint32_t timeout_ticks) {
|
||||
do {
|
||||
if (mutex.lock(ticks_remaining / portTICK_PERIOD_MS)) {
|
||||
if (!queue.empty()) {
|
||||
TT_LOG_I(TAG, "Dispatcher popping from queue");
|
||||
auto item = queue.front();
|
||||
queue.pop();
|
||||
consumed++;
|
||||
processing = !queue.empty();
|
||||
// Don't keep lock as callback might be slow
|
||||
|
||||
tt_check(mutex.unlock());
|
||||
item->callback(item->context);
|
||||
} else {
|
||||
processing = false;
|
||||
tt_check(mutex.unlock());
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ DispatcherThread::~DispatcherThread() {
|
||||
|
||||
void DispatcherThread::_threadMain() {
|
||||
do {
|
||||
dispatcher.consume(1000);
|
||||
dispatcher.consume(1000 / portTICK_PERIOD_MS);
|
||||
} while (!interruptThread);
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,6 @@ TtStatus Mutex::acquire(uint32_t timeout) const {
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
break;
|
||||
case TypeRecursive:
|
||||
if (xSemaphoreTakeRecursive(semaphore, timeout) != pdPASS) {
|
||||
if (timeout != 0U) {
|
||||
@ -72,7 +71,6 @@ TtStatus Mutex::acquire(uint32_t timeout) const {
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tt_crash("mutex type unknown/corrupted");
|
||||
}
|
||||
@ -90,7 +88,6 @@ TtStatus Mutex::release() const {
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeRecursive:
|
||||
if (xSemaphoreGiveRecursive(semaphore) != pdPASS) {
|
||||
@ -98,7 +95,6 @@ TtStatus Mutex::release() const {
|
||||
} else {
|
||||
return TtStatusOk;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tt_crash("mutex type unknown/corrupted");
|
||||
}
|
||||
|
||||
@ -2,14 +2,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef TT_CRITICAL_ENTER
|
||||
#define TT_CRITICAL_ENTER() __TtCriticalInfo __tt_critical_info = __tt_critical_enter();
|
||||
#endif
|
||||
|
||||
#ifndef TT_CRITICAL_EXIT
|
||||
#define TT_CRITICAL_EXIT() __tt_critical_exit(__tt_critical_info);
|
||||
#endif
|
||||
|
||||
namespace tt::kernel::critical {
|
||||
|
||||
typedef struct {
|
||||
|
||||
@ -11,9 +11,9 @@ public:
|
||||
virtual bool start() = 0;
|
||||
virtual bool stop() = 0;
|
||||
|
||||
virtual void setPowerOn(bool turnOn) = 0;
|
||||
virtual bool isPoweredOn() const = 0;
|
||||
virtual bool supportsPowerControl() const = 0;
|
||||
virtual void setPowerOn(bool turnOn) {}
|
||||
virtual bool isPoweredOn() const { return true; }
|
||||
virtual bool supportsPowerControl() const { return false; }
|
||||
|
||||
virtual Touch* _Nullable createTouch() = 0;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user