mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
This reverts commit 6de0f442fbe44ed26ace8aadbe4e242178e22186.
This commit is contained in:
parent
6de0f442fb
commit
efd3dc43ed
18
.github/workflows/build-firmware.yml
vendored
18
.github/workflows/build-firmware.yml
vendored
@ -126,24 +126,6 @@ jobs:
|
||||
with:
|
||||
board_id: lilygo-tdeck
|
||||
arch: esp32s3
|
||||
lilygo-tdeck-plus:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Build"
|
||||
uses: ./.github/actions/build-firmware
|
||||
with:
|
||||
board_id: lilygo-tdeck-plus
|
||||
arch: esp32s3
|
||||
lilygo-tdeck-pro:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Build"
|
||||
uses: ./.github/actions/build-firmware
|
||||
with:
|
||||
board_id: lilygo-tdeck-pro
|
||||
arch: esp32s3
|
||||
m5stack-core2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@ -37,10 +37,6 @@ menu "Tactility App"
|
||||
bool "Elecrow CrowPanel Basic 5.0"
|
||||
config TT_BOARD_LILYGO_TDECK
|
||||
bool "LilyGo T-Deck"
|
||||
config TT_BOARD_LILYGO_TDECK_PLUS
|
||||
bool "LilyGo T-Deck Plus"
|
||||
config TT_BOARD_LILYGO_TDECK_PRO
|
||||
bool "LilyGo T-Deck Pro"
|
||||
config TT_BOARD_M5STACK_CORE2
|
||||
bool "M5Stack Core2"
|
||||
config TT_BOARD_M5STACK_CORES3
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <sdkconfig.h>
|
||||
|
||||
// Supported hardware:
|
||||
#if defined(CONFIG_TT_BOARD_LILYGO_TDECK) || defined(CONFIG_TT_BOARD_LILYGO_TDECK_PLUS) || defined(CONFIG_TT_BOARD_LILYGO_TDECK_PRO)
|
||||
#if defined(CONFIG_TT_BOARD_LILYGO_TDECK)
|
||||
#include "LilygoTdeck.h"
|
||||
#define TT_BOARD_HARDWARE &lilygo_tdeck
|
||||
#elif defined(CONFIG_TT_BOARD_CYD_2432S024C)
|
||||
@ -14,22 +14,22 @@
|
||||
#elif defined(CONFIG_TT_BOARD_CYD_2432S032C)
|
||||
#include "CYD2432S032C.h"
|
||||
#define TT_BOARD_HARDWARE &cyd_2432S032c_config
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_28)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_28))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_advance_28
|
||||
#include "CrowPanelAdvance28.h"
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_35)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_35))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_advance_35
|
||||
#include "CrowPanelAdvance35.h"
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_50)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_ADVANCE_50))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_advance_50
|
||||
#include "CrowPanelAdvance50.h"
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_28)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_28))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_basic_28
|
||||
#include "CrowPanelBasic28.h"
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_35)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_35))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_basic_35
|
||||
#include "CrowPanelBasic35.h"
|
||||
#elif defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_50)
|
||||
#elif (defined(CONFIG_TT_BOARD_ELECROW_CROWPANEL_BASIC_50))
|
||||
#define TT_BOARD_HARDWARE &crowpanel_basic_50
|
||||
#include "CrowPanelBasic50.h"
|
||||
#elif defined(CONFIG_TT_BOARD_M5STACK_CORE2)
|
||||
|
||||
@ -1,5 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/display/DisplayDevice.h"
|
||||
#include <esp_lcd_types.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
class TdeckDisplay : public tt::hal::display::DisplayDevice {
|
||||
|
||||
private:
|
||||
|
||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
||||
lv_display_t* displayHandle = nullptr;
|
||||
bool poweredOn = false;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const final { return "ST7789"; }
|
||||
std::string getDescription() const final { return "SPI display"; }
|
||||
|
||||
bool start() override;
|
||||
|
||||
bool stop() override;
|
||||
|
||||
void setPowerOn(bool turnOn) override;
|
||||
bool isPoweredOn() const override { return poweredOn; };
|
||||
bool supportsPowerControl() const override { return true; }
|
||||
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable createTouch() override;
|
||||
|
||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
||||
bool supportsBacklightDuty() const override { return true; }
|
||||
|
||||
void setGammaCurve(uint8_t index) override;
|
||||
uint8_t getGammaCurveCount() const override { return 4; };
|
||||
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
||||
};
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility esp_lvgl_port esp_lcd ST7789 GT911 PwmBacklight driver esp_adc
|
||||
)
|
||||
@ -1,63 +0,0 @@
|
||||
#include "PwmBacklight.h"
|
||||
#include "Tactility/kernel/SystemEvents.h"
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <Tactility/hal/gps/GpsConfiguration.h>
|
||||
|
||||
#define TAG "tdeck"
|
||||
|
||||
// Power on
|
||||
#define TDECK_POWERON_GPIO GPIO_NUM_10
|
||||
|
||||
static bool powerOn() {
|
||||
gpio_config_t device_power_signal_config = {
|
||||
.pin_bit_mask = BIT64(TDECK_POWERON_GPIO),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
|
||||
if (gpio_config(&device_power_signal_config) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gpio_set_level(TDECK_POWERON_GPIO, 1) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tdeckInit() {
|
||||
ESP_LOGI(TAG, LOG_MESSAGE_POWER_ON_START);
|
||||
if (!powerOn()) {
|
||||
TT_LOG_E(TAG, LOG_MESSAGE_POWER_ON_FAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 32 Khz and higher gives an issue where the screen starts dimming again above 80% brightness
|
||||
* when moving the brightness slider rapidly from a lower setting to 100%.
|
||||
* This is not a slider bug (data was debug-traced) */
|
||||
if (!driver::pwmbacklight::init(GPIO_NUM_42, 30000)) {
|
||||
TT_LOG_E(TAG, "Backlight init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
tt::kernel::subscribeSystemEvent(tt::kernel::SystemEvent::BootSplash, [](tt::kernel::SystemEvent event) {
|
||||
auto gps_service = tt::service::gps::findGpsService();
|
||||
if (gps_service != nullptr) {
|
||||
std::vector<tt::hal::gps::GpsConfiguration> gps_configurations;
|
||||
gps_service->getGpsConfigurations(gps_configurations);
|
||||
if (gps_configurations.empty()) {
|
||||
if (gps_service->addGpsConfiguration(tt::hal::gps::GpsConfiguration {.uartName = "Grove", .baudRate = 38400, .model = tt::hal::gps::GpsModel::UBLOX10})) {
|
||||
TT_LOG_I(TAG, "Configured internal GPS");
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Failed to configure internal GPS");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
#include "hal/TdeckDisplay.h"
|
||||
#include "hal/TdeckDisplayConstants.h"
|
||||
#include "hal/TdeckKeyboard.h"
|
||||
#include "hal/TdeckPower.h"
|
||||
#include "hal/TdeckSdCard.h"
|
||||
|
||||
#include <Tactility/hal/Configuration.h>
|
||||
|
||||
#define TDECK_SPI_TRANSFER_SIZE_LIMIT (TDECK_LCD_HORIZONTAL_RESOLUTION * TDECK_LCD_SPI_TRANSFER_HEIGHT * (LV_COLOR_DEPTH / 8))
|
||||
|
||||
bool tdeckInit();
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
extern const Configuration lilygo_tdeck = {
|
||||
.initBoot = tdeckInit,
|
||||
.createDisplay = createDisplay,
|
||||
.createKeyboard = createKeyboard,
|
||||
.sdcard = createTdeckSdCard(),
|
||||
.power = tdeck_get_power,
|
||||
.i2c = {
|
||||
i2c::Configuration {
|
||||
.name = "Internal",
|
||||
.port = I2C_NUM_0,
|
||||
.initMode = i2c::InitMode::ByTactility,
|
||||
.isMutable = false,
|
||||
.config = (i2c_config_t) {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = GPIO_NUM_18,
|
||||
.scl_io_num = GPIO_NUM_8,
|
||||
.sda_pullup_en = true,
|
||||
.scl_pullup_en = true,
|
||||
.master = {
|
||||
.clk_speed = 400000
|
||||
},
|
||||
.clk_flags = 0
|
||||
}
|
||||
},
|
||||
i2c::Configuration {
|
||||
.name = "External",
|
||||
.port = I2C_NUM_1,
|
||||
.initMode = i2c::InitMode::Disabled,
|
||||
.isMutable = true,
|
||||
.config = (i2c_config_t) {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = GPIO_NUM_43,
|
||||
.scl_io_num = GPIO_NUM_44,
|
||||
.sda_pullup_en = false,
|
||||
.scl_pullup_en = false,
|
||||
.master = {
|
||||
.clk_speed = 400000
|
||||
},
|
||||
.clk_flags = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
.spi {
|
||||
spi::Configuration {
|
||||
.device = SPI2_HOST,
|
||||
.dma = SPI_DMA_CH_AUTO,
|
||||
.config = {
|
||||
.mosi_io_num = GPIO_NUM_41,
|
||||
.miso_io_num = GPIO_NUM_38,
|
||||
.sclk_io_num = GPIO_NUM_40,
|
||||
.quadwp_io_num = GPIO_NUM_NC, // Quad SPI LCD driver is not yet supported
|
||||
.quadhd_io_num = GPIO_NUM_NC, // Quad SPI LCD driver is not yet supported
|
||||
.data4_io_num = GPIO_NUM_NC,
|
||||
.data5_io_num = GPIO_NUM_NC,
|
||||
.data6_io_num = GPIO_NUM_NC,
|
||||
.data7_io_num = GPIO_NUM_NC,
|
||||
.data_io_default_level = false,
|
||||
.max_transfer_sz = TDECK_SPI_TRANSFER_SIZE_LIMIT,
|
||||
.flags = 0,
|
||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
||||
.intr_flags = 0
|
||||
},
|
||||
.initMode = spi::InitMode::ByTactility,
|
||||
.isMutable = false,
|
||||
.lock = tt::lvgl::getSyncLock() // esp_lvgl_port owns the lock for the display
|
||||
}
|
||||
},
|
||||
.uart {
|
||||
uart::Configuration {
|
||||
.name = "Grove",
|
||||
.port = UART_NUM_1,
|
||||
.rxPin = GPIO_NUM_44,
|
||||
.txPin = GPIO_NUM_43,
|
||||
.rtsPin = GPIO_NUM_NC,
|
||||
.ctsPin = GPIO_NUM_NC,
|
||||
.rxBufferSize = 1024,
|
||||
.txBufferSize = 1024,
|
||||
.config = {
|
||||
.baud_rate = 38400,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 0,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.flags = {
|
||||
.allow_pd = 0,
|
||||
.backup_before_sleep = 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/Configuration.h>
|
||||
|
||||
extern const tt::hal::Configuration lilygo_tdeck;
|
||||
@ -1,114 +0,0 @@
|
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
|
||||
#pragma once
|
||||
|
||||
// color definitions for GxEPD, GxEPD2 and GxEPD_HD, values correspond to RGB565 values for TFTs
|
||||
#define GxEPD_BLACK 0x0000
|
||||
#define GxEPD_WHITE 0xFFFF
|
||||
// some controllers for b/w EPDs support grey levels
|
||||
#define GxEPD_DARKGREY 0x7BEF // 128, 128, 128
|
||||
#define GxEPD_LIGHTGREY 0xC618 // 192, 192, 192
|
||||
// values for 3-color or 7-color EPDs
|
||||
#define GxEPD_RED 0xF800 // 255, 0, 0
|
||||
#define GxEPD_YELLOW 0xFFE0 // 255, 255, 0 !!no longer same as GxEPD_RED!!
|
||||
#define GxEPD_COLORED GxEPD_RED
|
||||
// values for 7-color EPDs only
|
||||
#define GxEPD_BLUE 0x001F // 0, 0, 255
|
||||
#define GxEPD_GREEN 0x07E0 // 0, 255, 0
|
||||
#define GxEPD_ORANGE 0xFC00 // 255, 128, 0
|
||||
|
||||
class GxEPD2
|
||||
{
|
||||
public:
|
||||
enum Panel
|
||||
{
|
||||
GDEW0102T4, Waveshare_1_02_bw = GDEW0102T4,
|
||||
GDEP015OC1, Waveshare_1_54_bw = GDEP015OC1,
|
||||
DEPG0150BN,
|
||||
GDEH0154D67, Waveshare_1_54_bw_D67 = GDEH0154D67,
|
||||
GDEW0154T8,
|
||||
GDEW0154M09,
|
||||
GDEW0154M10,
|
||||
GDEY0154D67,
|
||||
GDE0213B1, Waveshare_2_13_bw = GDE0213B1,
|
||||
GDEH0213B72, Waveshare_2_13_bw_B72 = GDEH0213B72,
|
||||
GDEH0213B73, Waveshare_2_13_bw_B73 = GDEH0213B73,
|
||||
GDEM0213B74,
|
||||
GDEW0213I5F, Waveshare_2_13_flex = GDEW0213I5F,
|
||||
GDEW0213M21,
|
||||
GDEW0213T5D,
|
||||
DEPG0213BN,
|
||||
GDEY0213B74,
|
||||
GDEW026T0, Waveshare_2_6_bw = GDEW026T0,
|
||||
GDEW026M01,
|
||||
DEPG0266BN,
|
||||
GDEY0266T90,
|
||||
GDEH029A1, Waveshare_2_9_bw = GDEH029A1,
|
||||
GDEW029T5, Waveshare_2_9_bw_T5 = GDEW029T5,
|
||||
GDEW029T5D,
|
||||
GDEW029I6FD,
|
||||
GDEW029M06,
|
||||
GDEM029T94,
|
||||
GDEY029T94,
|
||||
DEPG0290BS,
|
||||
GDEW027W3, Waveshare_2_7_bw = GDEW027W3,
|
||||
GDEY027T91,
|
||||
GDEQ031T10,
|
||||
ED037TC1,
|
||||
GDEW0371W7, Waveshare_3_7_bw = GDEW0371W7,
|
||||
GDEW042T2, Waveshare_4_2_bw = GDEW042T2,
|
||||
GDEW042M01,
|
||||
GDEY042T81,
|
||||
GDEQ0426T82,
|
||||
GDEW0583T7, Waveshare_5_83_bw = GDEW0583T7,
|
||||
GDEW0583T8,
|
||||
GDEQ0583T31,
|
||||
GDEW075T8, Waveshare_7_5_bw = GDEW075T8,
|
||||
GDEW075T7, Waveshare_7_5_bw_T7 = GDEW075T7,
|
||||
GDEY075T7,
|
||||
GDEH116T91,
|
||||
GDEW1248T3, Waveshare_12_24_bw = GDEW1248T3,
|
||||
ED060SCT, // on Waveshare IT8951 Driver HAT
|
||||
ED060KC1, // on Waveshare IT8951 Driver HAT 1448x1072
|
||||
ED078KC2, // on Waveshare IT8951 Driver HAT 1872x1404
|
||||
ES103TC1, // on Waveshare IT8951 Driver HAT 1872x1404
|
||||
// 3-color
|
||||
GDEW0154Z04, Waveshare_1_54_bwr = GDEW0154Z04,
|
||||
GDEH0154Z90, Waveshare_1_54_bwr_Z90 = GDEH0154Z90,
|
||||
GDEW0213Z16, Waveshare_2_13_bwr = GDEW0213Z16,
|
||||
GDEW0213Z19,
|
||||
GDEY0213Z98,
|
||||
GDEW029Z10, Waveshare_2_9_bwr = GDEW029Z10,
|
||||
GDEH029Z13,
|
||||
GDEM029C90,
|
||||
GDEY0266Z90, Waveshare_2_66_bwr = GDEY0266Z90,
|
||||
GDEW027C44, Waveshare_2_7_bwr = GDEW027C44,
|
||||
GDEW042Z15, Waveshare_4_2_bwr = GDEW042Z15,
|
||||
GDEQ042Z21, Waveshare_4_2_V2_bwr = GDEQ042Z21,
|
||||
GDEW0583Z21, Waveshare_5_83_bwr = GDEW0583Z21,
|
||||
GDEW0583Z83,
|
||||
GDEW075Z09, Waveshare_7_5_bwr = GDEW075Z09,
|
||||
GDEW075Z08, Waveshare_7_5_bwr_Z08 = GDEW075Z08,
|
||||
GDEH075Z90, Waveshare_7_5_bwr_Z90 = GDEH075Z90,
|
||||
GDEY1248Z51,
|
||||
// 4-color
|
||||
GDEY0266F51H,
|
||||
GDEY029F51H,
|
||||
Waveshare3inch4color,
|
||||
GDEY0420F51,
|
||||
Waveshare437inch4color,
|
||||
// 7-color
|
||||
ACeP565, Waveshare_5_65_7c = ACeP565,
|
||||
GDEY073D46,
|
||||
ACeP730, Waveshare_7_30_7c = ACeP730
|
||||
};
|
||||
};
|
||||
@ -1,297 +0,0 @@
|
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// based on Demo Example from Good Display: https://www.good-display.com/product/426.html
|
||||
// Panel: GDEQ031T10 : https://www.good-display.com/product/426.html
|
||||
// Controller: UC8253 : https://v4.cecdn.yun300.cn/100001_1909185148/UC8253.pdf
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
|
||||
#include "GxEPD2_310_GDEQ031T10.h"
|
||||
#include <Tactility/kernel/Kernel.h>
|
||||
|
||||
constexpr uint32_t LOW = 0;
|
||||
constexpr uint32_t HIGH = 1;
|
||||
|
||||
GxEPD2_310_GDEQ031T10::GxEPD2_310_GDEQ031T10(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
|
||||
GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate) {}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::clearScreen(uint8_t value) {
|
||||
// full refresh needed for all cases (previous != screen)
|
||||
_writeScreenBuffer(0x10, value); // set previous
|
||||
_writeScreenBuffer(0x13, value); // set current
|
||||
refresh(false); // full refresh
|
||||
_initial_write = false;
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeScreenBuffer(uint8_t value) {
|
||||
if (_initial_write) return clearScreen(value);
|
||||
_writeScreenBuffer(0x13, value); // set current
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeScreenBufferAgain(uint8_t value) {
|
||||
_writeScreenBuffer(0x10, value); // set previous
|
||||
//_writeScreenBuffer(0x13, value); // set current, not needed
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_writeScreenBuffer(uint8_t command, uint8_t value) {
|
||||
if (!_init_display_done) _InitDisplay();
|
||||
_writeCommand(command);
|
||||
_startTransfer();
|
||||
for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++) { _transfer(value); }
|
||||
_endTransfer();
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { _writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm); }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
_writeImage(0x10, bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
|
||||
_writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm); // set current
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
_writeImage(0x10, bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
|
||||
//_writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm); // set current, not needed
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
tt::kernel::delayMillis(1); // WDT hack
|
||||
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
|
||||
x -= x % 8; // byte boundary
|
||||
w = wb * 8; // byte boundary
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
|
||||
int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
|
||||
int16_t dx = x1 - x;
|
||||
int16_t dy = y1 - y;
|
||||
w1 -= dx;
|
||||
h1 -= dy;
|
||||
if ((w1 <= 0) || (h1 <= 0)) return;
|
||||
if (!_init_display_done) _InitDisplay();
|
||||
if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
|
||||
_writeCommand(0x91); // partial in
|
||||
_setPartialRamArea(x1, y1, w1, h1);
|
||||
_writeCommand(command);
|
||||
_startTransfer();
|
||||
for (int16_t i = 0; i < h1; i++) {
|
||||
for (int16_t j = 0; j < w1 / 8; j++) {
|
||||
uint8_t data;
|
||||
// use wb, h of bitmap for index!
|
||||
uint16_t idx = mirror_y ? j + dx / 8 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 8 + uint16_t(i + dy) * wb;
|
||||
if (pgm) {
|
||||
#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
|
||||
data = pgm_read_byte(&bitmap[idx]);
|
||||
#else
|
||||
data = bitmap[idx];
|
||||
#endif
|
||||
} else { data = bitmap[idx]; }
|
||||
if (invert) data = ~data;
|
||||
_transfer(data);
|
||||
}
|
||||
}
|
||||
_endTransfer();
|
||||
_writeCommand(0x92); // partial out
|
||||
tt::kernel::delayMillis(1); // WDT hack
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { _writeImagePart(0x13, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
_writeImagePart(0x10, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
|
||||
//_writeImagePart(0x13, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); // set current, not needed
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
tt::kernel::delayMillis(1); // WDT hack
|
||||
if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
|
||||
if ((x_part < 0) || (x_part >= w_bitmap)) return;
|
||||
if ((y_part < 0) || (y_part >= h_bitmap)) return;
|
||||
uint16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
|
||||
x_part -= x_part % 8; // byte boundary
|
||||
w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
|
||||
h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
|
||||
x -= x % 8; // byte boundary
|
||||
w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
|
||||
int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
|
||||
int16_t dx = x1 - x;
|
||||
int16_t dy = y1 - y;
|
||||
w1 -= dx;
|
||||
h1 -= dy;
|
||||
if ((w1 <= 0) || (h1 <= 0)) return;
|
||||
if (!_init_display_done) _InitDisplay();
|
||||
if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
|
||||
_writeCommand(0x91); // partial in
|
||||
_setPartialRamArea(x1, y1, w1, h1);
|
||||
_writeCommand(command);
|
||||
_startTransfer();
|
||||
for (int16_t i = 0; i < h1; i++) {
|
||||
for (int16_t j = 0; j < w1 / 8; j++) {
|
||||
uint8_t data;
|
||||
// use wb_bitmap, h_bitmap of bitmap for index!
|
||||
uint16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + uint16_t((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + uint16_t(y_part + i + dy) * wb_bitmap;
|
||||
if (pgm) {
|
||||
#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
|
||||
data = pgm_read_byte(&bitmap[idx]);
|
||||
#else
|
||||
data = bitmap[idx];
|
||||
#endif
|
||||
} else { data = bitmap[idx]; }
|
||||
if (invert) data = ~data;
|
||||
_transfer(data);
|
||||
}
|
||||
}
|
||||
_endTransfer();
|
||||
_writeCommand(0x92); // partial out
|
||||
tt::kernel::delayMillis(1); // WDT hack
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (black) { writeImage(black, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (black) { writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (data1) { writeImage(data1, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
refresh(x, y, w, h);
|
||||
writeImageAgain(bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) {
|
||||
writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
refresh(x, y, w, h);
|
||||
writeImagePartAgain(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (black) { drawImage(black, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (black) { drawImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) { if (data1) { drawImage(data1, x, y, w, h, invert, mirror_y, pgm); } }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::refresh(bool partial_update_mode) {
|
||||
if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
|
||||
else {
|
||||
_Update_Full();
|
||||
_initial_refresh = false; // initial full update done
|
||||
}
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::refresh(int16_t x, int16_t y, int16_t w, int16_t h) {
|
||||
if (_initial_refresh) return refresh(false); // initial update needs be full update
|
||||
// intersection with screen
|
||||
int16_t w1 = x < 0 ? w + x : w; // reduce
|
||||
int16_t h1 = y < 0 ? h + y : h; // reduce
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit
|
||||
h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit
|
||||
if ((w1 <= 0) || (h1 <= 0)) return;
|
||||
// make x1, w1 multiple of 8
|
||||
w1 += x1 % 8;
|
||||
if (w1 % 8 > 0) w1 += 8 - w1 % 8;
|
||||
x1 -= x1 % 8;
|
||||
if (usePartialUpdateWindow) _writeCommand(0x91); // partial in
|
||||
_setPartialRamArea(x1, y1, w1, h1);
|
||||
_Update_Part();
|
||||
if (usePartialUpdateWindow) _writeCommand(0x92); // partial out
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::powerOff(void) { _PowerOff(); }
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::hibernate() {
|
||||
_PowerOff();
|
||||
if (_rst >= 0) {
|
||||
_writeCommand(0x07); // deep sleep
|
||||
_writeData(0xA5); // check code
|
||||
_hibernating = true;
|
||||
_init_display_done = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte)
|
||||
uint16_t ye = y + h - 1;
|
||||
x &= 0xFFF8; // byte boundary
|
||||
_writeCommand(0x90); // partial window
|
||||
_writeData(x);
|
||||
_writeData(xe);
|
||||
_writeData(y / 256);
|
||||
_writeData(y % 256);
|
||||
_writeData(ye / 256);
|
||||
_writeData(ye % 256);
|
||||
_writeData(0x01);
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_PowerOn() {
|
||||
if (!_power_is_on) {
|
||||
_writeCommand(0x04);
|
||||
_waitWhileBusy("_PowerOn", power_on_time);
|
||||
}
|
||||
_power_is_on = true;
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_PowerOff() {
|
||||
if (_power_is_on) {
|
||||
_writeCommand(0x02); // power off
|
||||
_waitWhileBusy("_PowerOff", power_off_time);
|
||||
}
|
||||
_power_is_on = false;
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_InitDisplay() {
|
||||
_writeCommand(0x00); // PANEL SETTING
|
||||
_writeData(0x1e); // soft reset
|
||||
_writeData(0x0d);
|
||||
tt::kernel::delayMillis(1);
|
||||
_power_is_on = false;
|
||||
_writeCommand(0x00); // PANEL SETTING
|
||||
_writeData(0x1f); // KW: 3f, KWR: 2F, BWROTP: 0f, BWOTP: 1f
|
||||
_writeData(0x0d);
|
||||
_init_display_done = true;
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_Update_Full() {
|
||||
if (useFastFullUpdate) {
|
||||
_writeCommand(0xE0); // Cascade Setting (CCSET)
|
||||
_writeData(0x02); // TSFIX
|
||||
_writeCommand(0xE5); // Force Temperature (TSSET)
|
||||
_writeData(0x5A); // 90, 1015000us
|
||||
//_writeData(0x6E); // 110, 1542001
|
||||
}
|
||||
_writeCommand(0x50);
|
||||
_writeData(0x97);
|
||||
_PowerOn();
|
||||
_writeCommand(0x12); //display refresh
|
||||
_waitWhileBusy("_Update_Full", full_refresh_time);
|
||||
_init_display_done = false; // needed, reason unknown
|
||||
}
|
||||
|
||||
void GxEPD2_310_GDEQ031T10::_Update_Part() {
|
||||
if (hasFastPartialUpdate) {
|
||||
_writeCommand(0xE0); // Cascade Setting (CCSET)
|
||||
_writeData(0x02); // TSFIX
|
||||
_writeCommand(0xE5); // Force Temperature (TSSET)
|
||||
_writeData(0x79); // 121
|
||||
}
|
||||
_writeCommand(0x50);
|
||||
_writeData(0xD7);
|
||||
_PowerOn();
|
||||
_writeCommand(0x12); //display refresh
|
||||
_waitWhileBusy("_Update_Part", partial_refresh_time);
|
||||
_init_display_done = false; // needed, reason unknown
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// based on Demo Example from Good Display: https://www.good-display.com/product/426.html
|
||||
// Panel: GDEQ031T10 : https://www.good-display.com/product/426.html
|
||||
// Controller: UC8253 : https://v4.cecdn.yun300.cn/100001_1909185148/UC8253.pdf
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GxEPD2_EPD.h"
|
||||
|
||||
class GxEPD2_310_GDEQ031T10 : public GxEPD2_EPD
|
||||
{
|
||||
public:
|
||||
// attributes
|
||||
static const uint16_t WIDTH = 240;
|
||||
static const uint16_t WIDTH_VISIBLE = WIDTH;
|
||||
static const uint16_t HEIGHT = 320;
|
||||
static const GxEPD2::Panel panel = GxEPD2::GDEQ031T10;
|
||||
static const bool hasColor = false;
|
||||
static const bool hasPartialUpdate = true;
|
||||
static const bool usePartialUpdateWindow = true; // set false for better image
|
||||
static const bool hasFastPartialUpdate = true; // set this false to force full refresh always
|
||||
static const bool useFastFullUpdate = true;
|
||||
// set false for extended (low) temperature range, 1015000us vs 3082001us
|
||||
static const uint16_t power_on_time = 50; // ms, e.g. 45000us
|
||||
static const uint16_t power_off_time = 50; // ms, e.g. 45000us
|
||||
static const uint16_t full_refresh_time = 1100; // ms, e.g. 1015000us
|
||||
static const uint16_t partial_refresh_time = 700; // ms, e.g. 650000us
|
||||
// constructor
|
||||
GxEPD2_310_GDEQ031T10(int16_t cs, int16_t dc, int16_t rst, int16_t busy);
|
||||
// methods (virtual)
|
||||
// Support for Bitmaps (Sprites) to Controller Buffer and to Screen
|
||||
void clearScreen(uint8_t value = 0xFF); // init controller memory and screen (default white)
|
||||
void writeScreenBuffer(uint8_t value = 0xFF); // init controller memory (default white)
|
||||
void writeScreenBufferAgain(uint8_t value = 0xFF); // init previous buffer controller memory (default white)
|
||||
// write to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false,
|
||||
bool mirror_y = false, bool pgm = false);
|
||||
void writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap,
|
||||
int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
// for differential update: set current and previous buffers equal (for fast partial update to work correctly)
|
||||
void writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false,
|
||||
bool mirror_y = false, bool pgm = false);
|
||||
void writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
// write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
// write to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false,
|
||||
bool mirror_y = false, bool pgm = false);
|
||||
void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap,
|
||||
int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
// write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
void refresh(bool partial_update_mode = false); // screen refresh from controller memory to full screen
|
||||
void refresh(int16_t x, int16_t y, int16_t w, int16_t h); // screen refresh from controller memory, partial screen
|
||||
void powerOff(); // turns off generation of panel driving voltages, avoids screen fading over time
|
||||
void hibernate();
|
||||
// turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
|
||||
private:
|
||||
void _writeScreenBuffer(uint8_t command, uint8_t value);
|
||||
void _writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false);
|
||||
void _writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap,
|
||||
int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false);
|
||||
void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void _PowerOn();
|
||||
void _PowerOff();
|
||||
void _InitDisplay();
|
||||
void _Update_Full();
|
||||
void _Update_Part();
|
||||
};
|
||||
@ -1,161 +0,0 @@
|
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
|
||||
#include "GxEPD2_EPD.h"
|
||||
|
||||
#include <Tactility/hal/spi/Spi.h>
|
||||
#include <Tactility/kernel/Kernel.h>
|
||||
|
||||
constexpr auto* TAG = "GxEPD2";
|
||||
|
||||
GxEPD2_EPD::GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout,
|
||||
uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu) :
|
||||
WIDTH(w), HEIGHT(h), panel(p), hasColor(c), hasPartialUpdate(pu), hasFastPartialUpdate(fpu),
|
||||
_cs(cs), _dc(dc), _rst(rst), _busy(busy), _busy_level(busy_level), _busy_timeout(busy_timeout) {
|
||||
_initial_write = true;
|
||||
_initial_refresh = true;
|
||||
_power_is_on = false;
|
||||
_using_partial_mode = false;
|
||||
_hibernating = false;
|
||||
_init_display_done = false;
|
||||
_busy_callback = 0;
|
||||
_busy_callback_parameter = 0;
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::init() { init(true, 10, false); }
|
||||
|
||||
void GxEPD2_EPD::init(bool initial, uint16_t reset_duration, bool pulldown_rst_mode) {
|
||||
_initial_write = initial;
|
||||
_initial_refresh = initial;
|
||||
_pulldown_rst_mode = pulldown_rst_mode;
|
||||
_power_is_on = false;
|
||||
_using_partial_mode = false;
|
||||
_hibernating = false;
|
||||
_init_display_done = false;
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter) {
|
||||
_busy_callback = busyCallback;
|
||||
_busy_callback_parameter = busy_callback_parameter;
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time) {
|
||||
if (_busy >= 0) {
|
||||
tt::kernel::delayMillis(1); // add some margin to become active
|
||||
unsigned long start = tt::kernel::getMicros();
|
||||
while (1) {
|
||||
if (digitalRead(_busy) != _busy_level) break;
|
||||
if (_busy_callback) _busy_callback(_busy_callback_parameter);
|
||||
else tt::kernel::delayMillis(1);
|
||||
if (digitalRead(_busy) != _busy_level) break;
|
||||
if (tt::kernel::getMicros() - start > _busy_timeout) {
|
||||
TT_LOG_W(TAG, "Busy timeout");
|
||||
break;
|
||||
}
|
||||
vPortYield(); // avoid wdt
|
||||
}
|
||||
(void)start;
|
||||
} else tt::kernel::delayMillis(busy_time);
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeCommand(uint8_t c) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_dc >= 0) digitalWrite(_dc, LOW);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(c);
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
if (_dc >= 0) digitalWrite(_dc, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeData(uint8_t d) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(d);
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeData(const uint8_t* data, uint16_t n) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
for (uint16_t i = 0; i < n; i++) { _pSPIx->transfer(*data++); }
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeDataPGM(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
for (uint16_t i = 0; i < n; i++) { _pSPIx->transfer(pgm_read_byte(&*data++)); }
|
||||
while (fill_with_zeroes > 0) {
|
||||
_pSPIx->transfer(0x00);
|
||||
fill_with_zeroes--;
|
||||
}
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeDataPGM_sCS(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(pgm_read_byte(&*data++));
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
}
|
||||
while (fill_with_zeroes > 0) {
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(0x00);
|
||||
fill_with_zeroes--;
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
}
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeCommandData(const uint8_t* pCommandData, uint8_t datalen) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_dc >= 0) digitalWrite(_dc, LOW);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(*pCommandData++);
|
||||
if (_dc >= 0) digitalWrite(_dc, HIGH);
|
||||
for (uint8_t i = 0; i < datalen - 1; i++) // sub the command
|
||||
{
|
||||
_pSPIx->transfer(*pCommandData++);
|
||||
}
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_writeCommandDataPGM(const uint8_t* pCommandData, uint8_t datalen) {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_dc >= 0) digitalWrite(_dc, LOW);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
_pSPIx->transfer(pgm_read_byte(&*pCommandData++));
|
||||
if (_dc >= 0) digitalWrite(_dc, HIGH);
|
||||
for (uint8_t i = 0; i < datalen - 1; i++) // sub the command
|
||||
{
|
||||
_pSPIx->transfer(pgm_read_byte(&*pCommandData++));
|
||||
}
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_startTransfer() {
|
||||
_pSPIx->beginTransaction(_spi_settings);
|
||||
if (_cs >= 0) digitalWrite(_cs, LOW);
|
||||
}
|
||||
|
||||
void GxEPD2_EPD::_transfer(uint8_t value) { _pSPIx->transfer(value); }
|
||||
|
||||
void GxEPD2_EPD::_endTransfer() {
|
||||
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
||||
_pSPIx->endTransaction();
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GxEPD2.h"
|
||||
#include <cstdint>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
class GxEPD2_EPD
|
||||
{
|
||||
public:
|
||||
// attributes
|
||||
const uint16_t WIDTH;
|
||||
const uint16_t HEIGHT;
|
||||
const GxEPD2::Panel panel;
|
||||
const bool hasColor;
|
||||
const bool hasPartialUpdate;
|
||||
const bool hasFastPartialUpdate;
|
||||
// constructor
|
||||
GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout,
|
||||
uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu);
|
||||
virtual void init();
|
||||
virtual void init(bool initial, uint16_t reset_duration = 10, bool pulldown_rst_mode = false);
|
||||
// Support for Bitmaps (Sprites) to Controller Buffer and to Screen
|
||||
virtual void clearScreen(uint8_t value) = 0; // init controller memory and screen (default white)
|
||||
virtual void writeScreenBuffer(uint8_t value) = 0; // init controller memory (default white)
|
||||
// write to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
virtual void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false,
|
||||
bool mirror_y = false, bool pgm = false) = 0;
|
||||
|
||||
virtual void writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false)
|
||||
{
|
||||
// writeImage is independent from refresh mode for most controllers, exception e.g. SSD1681
|
||||
writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
}
|
||||
|
||||
virtual void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap,
|
||||
int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false,
|
||||
bool pgm = false) = 0;
|
||||
// virtual void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// virtual void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
// int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
// virtual void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// for differential update: set current and previous buffers equal (for fast partial update to work correctly)
|
||||
virtual void writeScreenBufferAgain(uint8_t value = 0xFF) // init controller memory (default white)
|
||||
{
|
||||
// most controllers with differential update do switch buffers on refresh, can use:
|
||||
writeScreenBuffer(value);
|
||||
}
|
||||
|
||||
virtual void writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
bool invert = false, bool mirror_y = false, bool pgm = false)
|
||||
{
|
||||
// most controllers with differential update do switch buffers on refresh, can use:
|
||||
writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
}
|
||||
|
||||
virtual void writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap,
|
||||
int16_t h_bitmap,
|
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false,
|
||||
bool mirror_y = false, bool pgm = false)
|
||||
{
|
||||
// most controllers with differential update do switch buffers on refresh, can use:
|
||||
writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
|
||||
}
|
||||
|
||||
// write to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
// virtual void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// virtual void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
// int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// virtual void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// virtual void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
|
||||
// int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
// virtual void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false) = 0;
|
||||
// a demo bitmap can use yet another bitmap format, e.g. 7-color bitmap from Good Display for GDEY073D46
|
||||
virtual void writeDemoBitmap(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
int16_t mode = 0, bool mirror_y = false, bool pgm = false)
|
||||
{
|
||||
};
|
||||
|
||||
virtual void drawDemoBitmap(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
int16_t mode = 0, bool mirror_y = false, bool pgm = false)
|
||||
{
|
||||
};
|
||||
virtual void refresh(bool partial_update_mode = false) = 0; // screen refresh from controller memory to full screen
|
||||
virtual void refresh(int16_t x, int16_t y, int16_t w, int16_t h) = 0;
|
||||
// screen refresh from controller memory, partial screen
|
||||
virtual void powerOff() = 0; // turns off generation of panel driving voltages, avoids screen fading over time
|
||||
virtual void hibernate() = 0;
|
||||
// turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
|
||||
virtual void setPaged()
|
||||
{
|
||||
}; // for GxEPD2_154c paged workaround
|
||||
// register a callback function to be called during _waitWhileBusy continuously.
|
||||
void setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter = 0);
|
||||
|
||||
static inline uint16_t gx_uint16_min(uint16_t a, uint16_t b)
|
||||
{
|
||||
return (a < b ? a : b);
|
||||
};
|
||||
|
||||
static inline uint16_t gx_uint16_max(uint16_t a, uint16_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
};
|
||||
|
||||
protected:
|
||||
void _waitWhileBusy(const char* comment = 0, uint16_t busy_time = 5000);
|
||||
void _writeCommand(uint8_t c);
|
||||
void _writeData(uint8_t d);
|
||||
void _writeData(const uint8_t* data, uint16_t n);
|
||||
void _writeDataPGM(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes = 0);
|
||||
void _writeDataPGM_sCS(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes = 0);
|
||||
void _writeCommandData(const uint8_t* pCommandData, uint8_t datalen);
|
||||
void _writeCommandDataPGM(const uint8_t* pCommandData, uint8_t datalen);
|
||||
void _startTransfer();
|
||||
void _transfer(uint8_t value);
|
||||
void _endTransfer();
|
||||
|
||||
protected:
|
||||
int16_t _cs, _dc, _rst, _busy, _busy_level;
|
||||
uint32_t _busy_timeout;
|
||||
bool _pulldown_rst_mode;
|
||||
bool _initial_write, _initial_refresh;
|
||||
bool _power_is_on, _using_partial_mode, _hibernating;
|
||||
bool _init_display_done;
|
||||
void (*_busy_callback)(const void*);
|
||||
const void* _busy_callback_parameter;
|
||||
};
|
||||
@ -1,45 +0,0 @@
|
||||
#include "TdeckDisplay.h"
|
||||
#include "TdeckDisplayConstants.h"
|
||||
|
||||
#include <Gt911Touch.h>
|
||||
#include <PwmBacklight.h>
|
||||
#include <St7789Display.h>
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#define TAG "tdeck_display"
|
||||
|
||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
||||
// Note for future changes: Reset pin is 48 and interrupt pin is 47
|
||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
||||
I2C_NUM_0,
|
||||
240,
|
||||
320,
|
||||
true,
|
||||
true,
|
||||
false
|
||||
);
|
||||
|
||||
return std::make_shared<Gt911Touch>(std::move(configuration));
|
||||
}
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||
auto touch = createTouch();
|
||||
|
||||
auto configuration = std::make_unique<St7789Display::Configuration>(
|
||||
TDECK_LCD_SPI_HOST,
|
||||
TDECK_LCD_PIN_CS,
|
||||
TDECK_LCD_PIN_DC,
|
||||
320,
|
||||
240,
|
||||
touch,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
|
||||
|
||||
return std::make_shared<St7789Display>(std::move(configuration));
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/display/DisplayDevice.h"
|
||||
#include <esp_lcd_types.h>
|
||||
#include <lvgl.h>
|
||||
|
||||
class TdeckDisplay : public tt::hal::display::DisplayDevice {
|
||||
|
||||
private:
|
||||
|
||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
||||
lv_display_t* displayHandle = nullptr;
|
||||
bool poweredOn = false;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const final { return "ST7789"; }
|
||||
std::string getDescription() const final { return "SPI display"; }
|
||||
|
||||
bool start() override;
|
||||
|
||||
bool stop() override;
|
||||
|
||||
void setPowerOn(bool turnOn) override;
|
||||
bool isPoweredOn() const override { return poweredOn; };
|
||||
bool supportsPowerControl() const override { return true; }
|
||||
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> _Nullable createTouch() override;
|
||||
|
||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
||||
bool supportsBacklightDuty() const override { return true; }
|
||||
|
||||
void setGammaCurve(uint8_t index) override;
|
||||
uint8_t getGammaCurveCount() const override { return 4; };
|
||||
|
||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
||||
};
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
||||
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define TDECK_LCD_SPI_HOST SPI2_HOST
|
||||
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
||||
#define TDECK_LCD_PIN_DC GPIO_NUM_11 // RS
|
||||
#define TDECK_LCD_HORIZONTAL_RESOLUTION 320
|
||||
#define TDECK_LCD_VERTICAL_RESOLUTION 240
|
||||
#define TDECK_LCD_SPI_TRANSFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
|
||||
@ -1,67 +0,0 @@
|
||||
#include "TdeckKeyboard.h"
|
||||
#include <Tactility/hal/i2c/I2c.h>
|
||||
#include <driver/i2c.h>
|
||||
|
||||
#define TAG "tdeck_keyboard"
|
||||
|
||||
#define TDECK_KEYBOARD_I2C_BUS_HANDLE I2C_NUM_0
|
||||
#define TDECK_KEYBOARD_SLAVE_ADDRESS 0x55
|
||||
|
||||
static inline bool keyboard_i2c_read(uint8_t* output) {
|
||||
return tt::hal::i2c::masterRead(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, output, 1, 100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback simulates press and release events, because the T-Deck
|
||||
* keyboard only publishes press events on I2C.
|
||||
* LVGL currently works without those extra release events, but they
|
||||
* are implemented for correctness and future compatibility.
|
||||
*
|
||||
* @param indev_drv
|
||||
* @param data
|
||||
*/
|
||||
static void keyboard_read_callback(TT_UNUSED lv_indev_t* indev, lv_indev_data_t* data) {
|
||||
static uint8_t last_buffer = 0x00;
|
||||
uint8_t read_buffer = 0x00;
|
||||
|
||||
// Defaults
|
||||
data->key = 0;
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
|
||||
if (keyboard_i2c_read(&read_buffer)) {
|
||||
if (read_buffer == 0 && read_buffer != last_buffer) {
|
||||
TT_LOG_D(TAG, "Released %d", last_buffer);
|
||||
data->key = last_buffer;
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
} else if (read_buffer != 0) {
|
||||
TT_LOG_D(TAG, "Pressed %d", read_buffer);
|
||||
data->key = read_buffer;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
last_buffer = read_buffer;
|
||||
}
|
||||
|
||||
bool TdeckKeyboard::start(lv_display_t* display) {
|
||||
deviceHandle = lv_indev_create();
|
||||
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(deviceHandle, &keyboard_read_callback);
|
||||
lv_indev_set_display(deviceHandle, display);
|
||||
lv_indev_set_user_data(deviceHandle, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TdeckKeyboard::stop() {
|
||||
lv_indev_delete(deviceHandle);
|
||||
deviceHandle = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TdeckKeyboard::isAttached() const {
|
||||
return tt::hal::i2c::masterHasDeviceAtAddress(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, 100);
|
||||
}
|
||||
|
||||
std::shared_ptr<tt::hal::keyboard::KeyboardDevice> createKeyboard() {
|
||||
return std::make_shared<TdeckKeyboard>();
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <esp_lcd_panel_io_interface.h>
|
||||
#include <esp_lcd_touch.h>
|
||||
|
||||
class TdeckKeyboard : public tt::hal::keyboard::KeyboardDevice {
|
||||
|
||||
private:
|
||||
|
||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const final { return "T-Deck Keyboard"; }
|
||||
std::string getDescription() const final { return "I2C keyboard"; }
|
||||
|
||||
bool start(lv_display_t* display) override;
|
||||
bool stop() override;
|
||||
bool isAttached() const override;
|
||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
||||
};
|
||||
|
||||
std::shared_ptr<tt::hal::keyboard::KeyboardDevice> createKeyboard();
|
||||
@ -1,130 +0,0 @@
|
||||
#include "TdeckPower.h"
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
|
||||
#define TAG "power"
|
||||
|
||||
/**
|
||||
* 2.0 ratio, but +.11 added as display voltage sag compensation.
|
||||
*/
|
||||
#define ADC_MULTIPLIER 2.11
|
||||
|
||||
#define ADC_REF_VOLTAGE 3.3f
|
||||
#define BATTERY_VOLTAGE_MIN 3.2f
|
||||
#define BATTERY_VOLTAGE_MAX 4.2f
|
||||
|
||||
static adc_oneshot_unit_init_cfg_t adcConfig = {
|
||||
.unit_id = ADC_UNIT_1,
|
||||
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
|
||||
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||
};
|
||||
|
||||
static adc_oneshot_chan_cfg_t adcChannelConfig = {
|
||||
.atten = ADC_ATTEN_DB_12,
|
||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||
};
|
||||
|
||||
static uint8_t estimateChargeLevelFromVoltage(uint32_t milliVolt) {
|
||||
float volts = std::min((float)milliVolt / 1000.f, BATTERY_VOLTAGE_MAX);
|
||||
float voltage_percentage = (volts - BATTERY_VOLTAGE_MIN) / (BATTERY_VOLTAGE_MAX - BATTERY_VOLTAGE_MIN);
|
||||
float voltage_factor = std::min(1.0f, voltage_percentage);
|
||||
auto charge_level = (uint8_t) (voltage_factor * 100.f);
|
||||
TT_LOG_V(TAG, "mV = %lu, scaled = %.2f, factor = %.2f, result = %d", milliVolt, volts, voltage_factor, charge_level);
|
||||
return charge_level;
|
||||
}
|
||||
|
||||
TdeckPower::TdeckPower() {
|
||||
if (adc_oneshot_new_unit(&adcConfig, &adcHandle) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "ADC config failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (adc_oneshot_config_channel(adcHandle, ADC_CHANNEL_3, &adcChannelConfig) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "ADC channel config failed");
|
||||
|
||||
adc_oneshot_del_unit(adcHandle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TdeckPower::~TdeckPower() {
|
||||
if (adcHandle) {
|
||||
adc_oneshot_del_unit(adcHandle);
|
||||
}
|
||||
}
|
||||
|
||||
bool TdeckPower::supportsMetric(MetricType type) const {
|
||||
switch (type) {
|
||||
using enum MetricType;
|
||||
case BatteryVoltage:
|
||||
case ChargeLevel:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
|
||||
bool TdeckPower::getMetric(MetricType type, MetricData& data) {
|
||||
switch (type) {
|
||||
using enum MetricType;
|
||||
case BatteryVoltage:
|
||||
return readBatteryVoltageSampled(data.valueAsUint32);
|
||||
case ChargeLevel:
|
||||
if (readBatteryVoltageSampled(data.valueAsUint32)) {
|
||||
data.valueAsUint32 = estimateChargeLevelFromVoltage(data.valueAsUint32);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
|
||||
bool TdeckPower::readBatteryVoltageOnce(uint32_t& output) {
|
||||
int raw;
|
||||
if (adc_oneshot_read(adcHandle, ADC_CHANNEL_3, &raw) == ESP_OK) {
|
||||
output = ADC_MULTIPLIER * ((1000.f * ADC_REF_VOLTAGE) / 4096.f) * (float)raw;
|
||||
TT_LOG_V(TAG, "Raw = %d, voltage = %lu", raw, output);
|
||||
return true;
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Read failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_VOLTAGE_SAMPLES 15
|
||||
|
||||
bool TdeckPower::readBatteryVoltageSampled(uint32_t& output) {
|
||||
size_t samples_read = 0;
|
||||
uint32_t sample_accumulator = 0;
|
||||
uint32_t sample_read_buffer;
|
||||
|
||||
for (size_t i = 0; i < MAX_VOLTAGE_SAMPLES; ++i) {
|
||||
if (readBatteryVoltageOnce(sample_read_buffer)) {
|
||||
sample_accumulator += sample_read_buffer;
|
||||
samples_read++;
|
||||
}
|
||||
}
|
||||
|
||||
if (samples_read > 0) {
|
||||
output = sample_accumulator / samples_read;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<PowerDevice> power;
|
||||
|
||||
std::shared_ptr<PowerDevice> tdeck_get_power() {
|
||||
if (power == nullptr) {
|
||||
power = std::make_shared<TdeckPower>();
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/power/PowerDevice.h"
|
||||
#include <esp_adc/adc_oneshot.h>
|
||||
#include <memory>
|
||||
|
||||
using tt::hal::power::PowerDevice;
|
||||
|
||||
class TdeckPower : public PowerDevice {
|
||||
|
||||
adc_oneshot_unit_handle_t adcHandle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
TdeckPower();
|
||||
~TdeckPower();
|
||||
|
||||
std::string getName() const final { return "ADC Power Measurement"; }
|
||||
std::string getDescription() const final { return "Power measurement interface via ADC pin"; }
|
||||
|
||||
bool supportsMetric(MetricType type) const override;
|
||||
bool getMetric(MetricType type, MetricData& data) override;
|
||||
|
||||
private:
|
||||
|
||||
bool readBatteryVoltageSampled(uint32_t& output);
|
||||
bool readBatteryVoltageOnce(uint32_t& output);
|
||||
};
|
||||
|
||||
std::shared_ptr<PowerDevice> tdeck_get_power();
|
||||
@ -1,33 +0,0 @@
|
||||
#include "TdeckSdCard.h"
|
||||
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||
|
||||
#include <esp_vfs_fat.h>
|
||||
|
||||
using tt::hal::sdcard::SpiSdCardDevice;
|
||||
|
||||
#define TDECK_SDCARD_PIN_CS GPIO_NUM_39
|
||||
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
||||
#define TDECK_RADIO_PIN_CS GPIO_NUM_9
|
||||
|
||||
std::shared_ptr<SdCardDevice> createTdeckSdCard() {
|
||||
auto* configuration = new SpiSdCardDevice::Config(
|
||||
TDECK_SDCARD_PIN_CS,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
SdCardDevice::MountBehaviour::AtBoot,
|
||||
tt::lvgl::getSyncLock(),
|
||||
{
|
||||
TDECK_RADIO_PIN_CS,
|
||||
TDECK_LCD_PIN_CS
|
||||
}
|
||||
);
|
||||
|
||||
auto* sdcard = (SdCardDevice*) new SpiSdCardDevice(
|
||||
std::unique_ptr<SpiSdCardDevice::Config>(configuration)
|
||||
);
|
||||
|
||||
return std::shared_ptr<SdCardDevice>(sdcard);
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||
|
||||
using tt::hal::sdcard::SdCardDevice;
|
||||
|
||||
std::shared_ptr<SdCardDevice> createTdeckSdCard();
|
||||
@ -47,10 +47,6 @@ function(INIT_TACTILITY_GLOBALS SDKCONFIG_FILE)
|
||||
set(TACTILITY_BOARD_PROJECT ElecrowCrowpanelBasic50)
|
||||
elseif (board_id STREQUAL "lilygo-tdeck")
|
||||
set(TACTILITY_BOARD_PROJECT LilygoTdeck)
|
||||
elseif (board_id STREQUAL "lilygo-tdeck-plus")
|
||||
set(TACTILITY_BOARD_PROJECT LilygoTdeck)
|
||||
elseif (board_id STREQUAL "lilygo-tdeck-pro")
|
||||
set(TACTILITY_BOARD_PROJECT LilygoTdeckPro)
|
||||
elseif (board_id STREQUAL "m5stack-core2")
|
||||
set(TACTILITY_BOARD_PROJECT M5stackCore2)
|
||||
elseif (board_id STREQUAL "m5stack-cores3")
|
||||
|
||||
2
ExternalApps/HelloWorld/.gitignore
vendored
2
ExternalApps/HelloWorld/.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
build*/
|
||||
.tactility/
|
||||
.tactility/
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
# Software defaults
|
||||
# Increase stack size for WiFi (fixes crash after scan)
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_USE_FS_STDIO=y
|
||||
CONFIG_LV_FS_STDIO_LETTER=65
|
||||
CONFIG_LV_FS_STDIO_PATH=""
|
||||
CONFIG_LV_FS_STDIO_CACHE_SIZE=4096
|
||||
CONFIG_LV_USE_LODEPNG=y
|
||||
CONFIG_LV_USE_BUILTIN_MALLOC=n
|
||||
CONFIG_LV_USE_CLIB_MALLOC=y
|
||||
CONFIG_LV_USE_MSGBOX=n
|
||||
CONFIG_LV_USE_SPINNER=n
|
||||
CONFIG_LV_USE_WIN=n
|
||||
CONFIG_LV_USE_SNAPSHOT=y
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||
CONFIG_FREERTOS_SMP=n
|
||||
CONFIG_FREERTOS_UNICORE=n
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_FATFS_LFN_HEAP=y
|
||||
CONFIG_FATFS_VOLUME_COUNT=3
|
||||
|
||||
# Hardware: Main
|
||||
CONFIG_TT_BOARD_LILYGO_TDECK_PLUS=y
|
||||
CONFIG_TT_BOARD_NAME="LilyGo T-Deck Plus"
|
||||
CONFIG_TT_BOARD_ID="lilygo-tdeck-plus"
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
CONFIG_FLASHMODE_QIO=y
|
||||
# Hardware: SPI RAM
|
||||
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
CONFIG_SPIRAM_SPEED_120M=y
|
||||
CONFIG_SPIRAM_USE_MALLOC=y
|
||||
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
|
||||
# SPI Flash (can set back to 80MHz after ESP-IDF bug is resolved)
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
|
||||
# LVGL
|
||||
CONFIG_LV_DPI_DEF=139
|
||||
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
|
||||
# USB
|
||||
CONFIG_TINYUSB_MSC_ENABLED=y
|
||||
CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
|
||||
@ -1,57 +0,0 @@
|
||||
# Software defaults
|
||||
# Increase stack size for WiFi (fixes crash after scan)
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
|
||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_18=y
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_USE_FS_STDIO=y
|
||||
CONFIG_LV_FS_STDIO_LETTER=65
|
||||
CONFIG_LV_FS_STDIO_PATH=""
|
||||
CONFIG_LV_FS_STDIO_CACHE_SIZE=4096
|
||||
CONFIG_LV_USE_LODEPNG=y
|
||||
CONFIG_LV_USE_BUILTIN_MALLOC=n
|
||||
CONFIG_LV_USE_CLIB_MALLOC=y
|
||||
CONFIG_LV_USE_MSGBOX=n
|
||||
CONFIG_LV_USE_SPINNER=n
|
||||
CONFIG_LV_USE_WIN=n
|
||||
CONFIG_LV_USE_SNAPSHOT=y
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||
CONFIG_FREERTOS_SMP=n
|
||||
CONFIG_FREERTOS_UNICORE=n
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_FATFS_LFN_HEAP=y
|
||||
CONFIG_FATFS_VOLUME_COUNT=3
|
||||
|
||||
# Hardware: Main
|
||||
CONFIG_TT_BOARD_LILYGO_TDECK_PRO=y
|
||||
CONFIG_TT_BOARD_NAME="LilyGo T-Deck Pro"
|
||||
CONFIG_TT_BOARD_ID="lilygo-tdeck-pro"
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_IDF_TARGET="esp32s3"
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
CONFIG_FLASHMODE_QIO=y
|
||||
# Hardware: SPI RAM
|
||||
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
CONFIG_SPIRAM_SPEED_120M=y
|
||||
CONFIG_SPIRAM_USE_MALLOC=y
|
||||
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
|
||||
# SPI Flash (can set back to 80MHz after ESP-IDF bug is resolved)
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
|
||||
# LVGL
|
||||
CONFIG_LV_DPI_DEF=139
|
||||
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
|
||||
CONFIG_LV_USE_THEME_DEFAULT=n
|
||||
CONFIG_LV_USE_THEME_SIMPLE=n
|
||||
CONFIG_LV_USE_THEME_MONO=y
|
||||
CONFIG_LV_COLOR_DEPTH=1
|
||||
# USB
|
||||
CONFIG_TINYUSB_MSC_ENABLED=y
|
||||
CONFIG_TINYUSB_MSC_MOUNT_PATH="/sdcard"
|
||||
Loading…
x
Reference in New Issue
Block a user