From 06284590d0a09e67c2fbef75adca0efeffc11ce8 Mon Sep 17 00:00:00 2001 From: lovyan03 <42724151+lovyan03@users.noreply.github.com> Date: Sun, 18 Feb 2024 19:46:19 +0900 Subject: [PATCH] add support M5Stack Core2 v1.1 (#518) --- .../LGFX_AutoDetect_ESP32_all.hpp | 145 ++++++++++++++---- 1 file changed, 112 insertions(+), 33 deletions(-) diff --git a/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp b/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp index bafe559d..904ff233 100644 --- a/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp +++ b/src/lgfx/v1_autodetect/LGFX_AutoDetect_ESP32_all.hpp @@ -43,6 +43,15 @@ namespace lgfx static constexpr char LIBRARY_NAME[] = "LovyanGFX"; + void i2c_write_register8_array(int_fast16_t i2c_port, uint_fast8_t i2c_addr, const uint8_t* reg_data_mask, uint32_t freq) + { + while (reg_data_mask[0] != 0xFF || reg_data_mask[1] != 0xFF || reg_data_mask[2] != 0xFF) + { + lgfx::i2c::writeRegister8(i2c_port, i2c_addr, reg_data_mask[0], reg_data_mask[1], reg_data_mask[2], freq); + reg_data_mask += 3; + } + } + #if defined (CONFIG_IDF_TARGET_ESP32S3) #if defined ( ARDUINO_ESP32_S3_BOX ) @@ -348,6 +357,33 @@ namespace lgfx } }; + struct Light_M5StackCore2_AXP2101 : public lgfx::ILight + { + bool init(uint8_t brightness) override + { + setBrightness(brightness); + return true; + } + + void setBrightness(uint8_t brightness) override + { + using namespace m5stack; + + // BLDO1 + if (brightness) + { + brightness = ((brightness + 641) >> 5); + lgfx::i2c::bitOn(axp_i2c_port, axp_i2c_addr, 0x90, 0x10, axp_i2c_freq); // BLDO1 enable + } + else + { + lgfx::i2c::bitOff(axp_i2c_port, axp_i2c_addr, 0x90, 0x10, axp_i2c_freq); // BLDO1 disable + } + // AXP192 reg 0x96 = BLO1 voltage setting (0.5v ~ 3.5v 100mv/step) + lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x96, brightness, 0, axp_i2c_freq); + } + }; + struct Light_M5Tough : public lgfx::ILight { bool init(uint8_t brightness) override @@ -2133,47 +2169,85 @@ namespace lgfx using namespace m5stack; _pin_backup_t backup[] = { axp_i2c_sda, axp_i2c_scl }; lgfx::i2c::init(axp_i2c_port, axp_i2c_sda, axp_i2c_scl); - if (lgfx::i2c::readRegister8(axp_i2c_port, axp_i2c_addr, 0x03, 400000) == 0x03) // AXP192 found + + auto chk_axp = lgfx::i2c::readRegister8(axp_i2c_port, axp_i2c_addr, 0x03, 400000); + if (chk_axp.has_value()) { - _pin_level(GPIO_NUM_5, true); - // AXP192_LDO2 = LCD PWR - // AXP192_IO4 = LCD RST - // AXP192_DC3 = LCD BL (Core2) - // AXP192_LDO3 = LCD BL (Tough) - // AXP192_IO1 = TP RST (Tough) - static constexpr uint8_t reg_data[] = - { - 0x28, 0xF0, 0xFF, // set LDO2 3300mv // LCD PWR - 0x12, 0x04, 0xFF, // LDO2 enable - 0x92, 0x00, 0xF8, // GPIO1 OpenDrain (M5Tough TOUCH) - 0x95, 0x84, 0x72, // GPIO4 enable - 0x96, 0x02, 0xFF, // GPIO4 HIGH (LCD RST) - 0x94, 0x02, 0xFF, // GPIO1 HIGH (M5Tough TOUCH RST) - }; - for (size_t i = 0; i < sizeof(reg_data); i += 3) - { - lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, reg_data[i ], reg_data[i+1], reg_data[i+2], axp_i2c_freq); + uint_fast16_t axp_exists = 0; + if (chk_axp.value() == 0x03) { // AXP192 found + axp_exists = 192; + ESP_LOGD(LIBRARY_NAME, "AXP192 found"); } - if (use_reset) + else if (chk_axp.value() == 0x4A) { // AXP2101 found + axp_exists = 2101; + ESP_LOGD(LIBRARY_NAME, "AXP2101 found"); + } + if (axp_exists) { - static constexpr uint8_t reset_reg_data[] = - { - 0x96, 0, 0xFD, // GPIO4 LOW (LCD RST) - 0x94, 0, 0xFD, // GPIO1 LOW (M5Tough TOUCH RST) + // fore Core2 1st gen (AXP192) + // AXP192_LDO2 = LCD PWR + // AXP192_IO4 = LCD RST + // AXP192_DC3 = LCD BL (Core2) + // AXP192_LDO3 = LCD BL (Tough) + // AXP192_IO1 = TP RST (Tough) + static constexpr uint8_t reg_data_axp192_first[] = { + 0x95, 0x84, 0x72, // GPIO4 enable + 0x28, 0xF0, 0xFF, // set LDO2 3300mv // LCD PWR + 0x12, 0x04, 0xFF, // LDO2 enable + 0x92, 0x00, 0xF8, // GPIO1 OpenDrain (M5Tough TOUCH) + 0xFF, 0xFF, 0xFF, + }; + static constexpr uint8_t reg_data_axp192_reset[] = { + 0x96, 0x00, 0xFD, // GPIO4 LOW (LCD RST) + 0x94, 0x00, 0xFD, // GPIO1 LOW (M5Tough TOUCH RST) + 0xFF, 0xFF, 0xFF, + }; + static constexpr uint8_t reg_data_axp192_second[] = { 0x96, 0x02, 0xFF, // GPIO4 HIGH (LCD RST) 0x94, 0x02, 0xFF, // GPIO1 HIGH (M5Tough TOUCH RST) + 0xFF, 0xFF, 0xFF, }; - for (size_t i = 0; i < sizeof(reset_reg_data); i += 3) - { - lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, reset_reg_data[i ], reset_reg_data[i+1], reset_reg_data[i+2], axp_i2c_freq); + + // for Core2 v1.1 (AXP2101) + // ALDO2 == LCD+TOUCH RST + // ALDO3 == SPK EN + // ALDO4 == TF, TP, LCD PWR + // BLDO1 == LCD BL + // BLDO2 == Boost EN + // DLDO1 == Vibration Motor + static constexpr uint8_t reg_data_axp2101_first[] = { + 0x90, 0x08, 0x7B, // ALDO4 ON / ALDO3 OFF, DLDO1 OFF + 0x80, 0x05, 0xFF, // DCDC1 + DCDC3 ON + 0x82, 0x12, 0x00, // DCDC1 3.3V + 0x84, 0x6A, 0x00, // DCDC3 3.3V + 0xFF, 0xFF, 0xFF, + }; + static constexpr uint8_t reg_data_axp2101_reset[] = { + 0x90, 0x00, 0xFD, // ALDO2 OFF + 0xFF, 0xFF, 0xFF, + }; + static constexpr uint8_t reg_data_axp2101_second[] = { + 0x90, 0x02, 0xFF, // ALDO2 ON + 0xFF, 0xFF, 0xFF, + }; + + _pin_level(GPIO_NUM_5, true); + + bool isAxp192 = axp_exists == 192; + + i2c_write_register8_array(axp_i2c_port, axp_i2c_addr, isAxp192 ? reg_data_axp192_first : reg_data_axp2101_first, axp_i2c_freq); + if (use_reset) { + i2c_write_register8_array(axp_i2c_port, axp_i2c_addr, isAxp192 ? reg_data_axp192_reset : reg_data_axp2101_reset, axp_i2c_freq); lgfx::delay(1); } - } + i2c_write_register8_array(axp_i2c_port, axp_i2c_addr, isAxp192 ? reg_data_axp192_second : reg_data_axp2101_second, axp_i2c_freq); + lgfx::delay(1); - result->board = board_t::board_unknown; - if (_detector_spi_t::detect(result, use_reset)) - { - return true; + result->board = board_t::board_unknown; + if (_detector_spi_t::detect(result, use_reset)) + { + return true; + } } } lgfx::i2c::release(axp_i2c_port); @@ -2207,7 +2281,12 @@ namespace lgfx else { ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StackCore2"); - p->light(new Light_M5StackCore2()); + + auto chk_axp = lgfx::i2c::readRegister8(axp_i2c_port, axp_i2c_addr, 0x03, 400000); + p->light( chk_axp.value() == 0x4A // AXP2101 found + ? (lgfx::ILight*)(new Light_M5StackCore2_AXP2101()) + : (lgfx::ILight*)(new Light_M5StackCore2()) + ); t = new lgfx::Touch_FT5x06(); auto cfg = t->config(); cfg.x_min = 0;