2144 lines
71 KiB
C++
2144 lines
71 KiB
C++
// Copyright (c) M5Stack. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
#include "M5GFX.h"
|
|
|
|
#if defined ( ESP_PLATFORM )
|
|
|
|
#include <cstdint>
|
|
#include <sdkconfig.h>
|
|
#include <nvs.h>
|
|
#include <esp_log.h>
|
|
#include <driver/i2c.h>
|
|
#include <soc/efuse_reg.h>
|
|
#include <soc/gpio_reg.h>
|
|
|
|
#include "lgfx/v1/panel/Panel_ILI9342.hpp"
|
|
#include "lgfx/v1/panel/Panel_ST7735.hpp"
|
|
#include "lgfx/v1/panel/Panel_ST7789.hpp"
|
|
#include "lgfx/v1/panel/Panel_GC9A01.hpp"
|
|
#include "lgfx/v1/panel/Panel_GDEW0154M09.hpp"
|
|
#include "lgfx/v1/panel/Panel_GDEW0154D67.hpp"
|
|
#include "lgfx/v1/panel/Panel_IT8951.hpp"
|
|
#include "lgfx/v1/touch/Touch_CST816S.hpp"
|
|
#include "lgfx/v1/touch/Touch_FT5x06.hpp"
|
|
#include "lgfx/v1/touch/Touch_GT911.hpp"
|
|
|
|
#if defined ( CONFIG_IDF_TARGET_ESP32P4 )
|
|
|
|
#include "lgfx/v1/platforms/esp32p4/Panel_ILI9881C.hpp"
|
|
|
|
static constexpr int_fast16_t in_i2c_port = I2C_NUM_1;
|
|
|
|
#elif defined ( CONFIG_IDF_TARGET_ESP32S3 )
|
|
|
|
// for M5PaperS3
|
|
#if defined (CONFIG_ESP32S3_SPIRAM_SUPPORT) && defined (CONFIG_SPIRAM_MODE_OCT)
|
|
|
|
#include <lgfx/v1/platforms/esp32/Panel_EPD.hpp>
|
|
|
|
#endif
|
|
#endif
|
|
|
|
#else
|
|
|
|
#include "lgfx/v1/platforms/sdl/Panel_sdl.hpp"
|
|
#include "picture_frame/picture_frame.h"
|
|
|
|
#endif
|
|
|
|
namespace m5gfx
|
|
{
|
|
static constexpr char LIBRARY_NAME[] = "M5GFX";
|
|
|
|
M5GFX* M5GFX::_instance = nullptr;
|
|
|
|
M5GFX::M5GFX(void) : LGFX_Device()
|
|
{
|
|
if (_instance == nullptr) _instance = this;
|
|
}
|
|
|
|
#if defined ( ESP_PLATFORM )
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static constexpr std::uint_fast8_t pi4io1_i2c_addr = 0x43;
|
|
static constexpr std::uint_fast8_t pi4io2_i2c_addr = 0x44;
|
|
#if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
|
|
static constexpr std::int32_t axp_i2c_freq = 400000;
|
|
static constexpr std::uint_fast8_t axp_i2c_addr = 0x34;
|
|
static constexpr std::int_fast16_t axp_i2c_port = I2C_NUM_1;
|
|
static constexpr std::int_fast16_t axp_i2c_sda = GPIO_NUM_21;
|
|
static constexpr std::int_fast16_t axp_i2c_scl = GPIO_NUM_22;
|
|
|
|
struct Panel_M5Stack : public lgfx::Panel_ILI9342
|
|
{
|
|
Panel_M5Stack(void)
|
|
{
|
|
_cfg.pin_cs = GPIO_NUM_14;
|
|
_cfg.pin_rst = GPIO_NUM_33;
|
|
_cfg.offset_rotation = 3;
|
|
|
|
_rotation = 1;
|
|
}
|
|
|
|
bool init(bool use_reset) override
|
|
{
|
|
_cfg.invert = lgfx::gpio::command(
|
|
(const uint8_t[]) {
|
|
lgfx::gpio::command_mode_output , GPIO_NUM_33,
|
|
lgfx::gpio::command_write_low , GPIO_NUM_33,
|
|
lgfx::gpio::command_mode_input_pulldown, GPIO_NUM_33,
|
|
lgfx::gpio::command_write_high , GPIO_NUM_33,
|
|
lgfx::gpio::command_read , GPIO_NUM_33,
|
|
lgfx::gpio::command_mode_output , GPIO_NUM_33,
|
|
lgfx::gpio::command_end
|
|
});
|
|
return lgfx::Panel_ILI9342::init(use_reset);
|
|
}
|
|
};
|
|
|
|
struct Panel_M5StackCore2 : public lgfx::Panel_ILI9342
|
|
{
|
|
Panel_M5StackCore2(void)
|
|
{
|
|
_cfg.pin_cs = GPIO_NUM_5;
|
|
_cfg.invert = true;
|
|
_cfg.offset_rotation = 3;
|
|
|
|
_rotation = 1; // default rotation
|
|
}
|
|
|
|
void rst_control(bool level) override
|
|
{
|
|
uint8_t bits = level ? 2 : 0;
|
|
uint8_t mask = level ? ~0 : ~2;
|
|
// AXP192 reg 0x96 = GPIO3&4 control
|
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x96, bits, mask, axp_i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Light_M5StackCore2 : public lgfx::ILight
|
|
{
|
|
bool init(std::uint8_t brightness) override
|
|
{
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(std::uint8_t brightness) override
|
|
{
|
|
if (brightness)
|
|
{
|
|
brightness = (brightness >> 3) + 72;
|
|
lgfx::i2c::bitOn(axp_i2c_port, axp_i2c_addr, 0x12, 0x02, axp_i2c_freq); // DC3 enable
|
|
}
|
|
else
|
|
{
|
|
lgfx::i2c::bitOff(axp_i2c_port, axp_i2c_addr, 0x12, 0x02, axp_i2c_freq); // DC3 disable
|
|
}
|
|
// AXP192 reg 0x27 = DC3
|
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x27, brightness, 0x80, axp_i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Light_M5StackCore2_AXP2101 : public lgfx::ILight
|
|
{
|
|
bool init(std::uint8_t brightness) override
|
|
{
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(std::uint8_t brightness) override
|
|
{
|
|
// 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(std::uint8_t brightness) override
|
|
{
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(std::uint8_t brightness) override
|
|
{
|
|
if (brightness)
|
|
{
|
|
if (brightness > 4)
|
|
{
|
|
brightness = (brightness / 24) + 5;
|
|
}
|
|
lgfx::i2c::bitOn(axp_i2c_port, axp_i2c_addr, 0x12, 0x08, axp_i2c_freq); // LDO3 enable
|
|
}
|
|
else
|
|
{
|
|
lgfx::i2c::bitOff(axp_i2c_port, axp_i2c_addr, 0x12, 0x08, axp_i2c_freq); // LDO3 disable
|
|
}
|
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x28, brightness, 0xF0, axp_i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Touch_M5Tough : public lgfx::ITouch
|
|
{
|
|
void wakeup(void) override {}
|
|
void sleep(void) override {}
|
|
|
|
bool init(void) override
|
|
{
|
|
_inited = false;
|
|
if (isSPI()) return false;
|
|
|
|
if (_cfg.pin_int >= 0)
|
|
{
|
|
lgfx::pinMode(_cfg.pin_int, lgfx::pin_mode_t::input);
|
|
}
|
|
_inited = lgfx::i2c::init(_cfg.i2c_port, _cfg.pin_sda, _cfg.pin_scl).has_value();
|
|
static constexpr uint8_t irq_modechange_cmd[] = { 0x5a, 0x5a }; /// (INT mode change)
|
|
lgfx::i2c::transactionWrite(_cfg.i2c_port, _cfg.i2c_addr, irq_modechange_cmd, 2);
|
|
|
|
return _inited;
|
|
}
|
|
|
|
std::uint_fast8_t getTouchRaw(touch_point_t *tp, std::uint_fast8_t count) override
|
|
{
|
|
if (tp) tp->size = 0;
|
|
if (!_inited || count == 0) return 0;
|
|
if (count > 2) count = 2; // max 2 point.
|
|
if (_cfg.pin_int >= 0)
|
|
{
|
|
if (gpio_in(_cfg.pin_int)) return 0;
|
|
}
|
|
|
|
std::size_t len = 3 + count * 6;
|
|
std::uint8_t buf[2][len];
|
|
std::int32_t retry = 5;
|
|
bool flip = false;
|
|
std::uint8_t* tmp;
|
|
for (;;)
|
|
{
|
|
tmp = buf[flip];
|
|
memset(tmp, 0, len);
|
|
if (lgfx::i2c::beginTransaction(_cfg.i2c_port, _cfg.i2c_addr, _cfg.freq, false))
|
|
{
|
|
static constexpr std::uint8_t reg_number = 2;
|
|
if (lgfx::i2c::writeBytes(_cfg.i2c_port, ®_number, 1)
|
|
&& lgfx::i2c::restart(_cfg.i2c_port, _cfg.i2c_addr, _cfg.freq, true)
|
|
&& lgfx::i2c::readBytes(_cfg.i2c_port, tmp, 1)
|
|
&& (tmp[0] != 0))
|
|
{
|
|
flip = !flip;
|
|
std::size_t points = std::min<std::uint_fast8_t>(count, tmp[0]);
|
|
if (points && lgfx::i2c::readBytes(_cfg.i2c_port, &tmp[1], points * 6 - 2))
|
|
{}
|
|
}
|
|
if (lgfx::i2c::endTransaction(_cfg.i2c_port)) {}
|
|
if (tmp[0] == 0 || memcmp(buf[0], buf[1], len) == 0) break;
|
|
}
|
|
if (0 == --retry) return 0;
|
|
}
|
|
if (count > tmp[0]) count = tmp[0];
|
|
|
|
for (std::size_t idx = 0; idx < count; ++idx)
|
|
{
|
|
auto data = &tmp[1 + idx * 6];
|
|
tp[idx].size = 1;
|
|
tp[idx].x = (data[0] & 0x0F) << 8 | data[1];
|
|
tp[idx].y = (data[2] & 0x0F) << 8 | data[3];
|
|
tp[idx].id = idx;
|
|
}
|
|
return count;
|
|
}
|
|
};
|
|
|
|
struct Panel_M5StickC : public lgfx::Panel_ST7735S
|
|
{
|
|
Panel_M5StickC(void)
|
|
{
|
|
_cfg.invert = true;
|
|
_cfg.pin_cs = GPIO_NUM_5;
|
|
_cfg.pin_rst = GPIO_NUM_18;
|
|
_cfg.panel_width = 80;
|
|
_cfg.panel_height = 160;
|
|
_cfg.offset_x = 26;
|
|
_cfg.offset_y = 1;
|
|
_cfg.offset_rotation = 2;
|
|
}
|
|
|
|
protected:
|
|
|
|
const std::uint8_t* getInitCommands(std::uint8_t listno) const override
|
|
{
|
|
static constexpr std::uint8_t list[] = {
|
|
CMD_GAMMASET, 1, 0x08, // Gamma set, curve 4
|
|
0xFF,0xFF, // end
|
|
};
|
|
if (listno == 2) return list;
|
|
return Panel_ST7735S::getInitCommands(listno);
|
|
}
|
|
};
|
|
|
|
struct Light_M5StickC : public lgfx::ILight
|
|
{
|
|
bool init(std::uint8_t brightness) override
|
|
{
|
|
lgfx::i2c::init(axp_i2c_port, axp_i2c_sda, axp_i2c_scl);
|
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x12, 0x4D, ~0, axp_i2c_freq);
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(std::uint8_t brightness) override
|
|
{
|
|
if (brightness)
|
|
{
|
|
brightness = (((brightness >> 1) + 8) / 13) + 5;
|
|
lgfx::i2c::bitOn(axp_i2c_port, axp_i2c_addr, 0x12, 1 << 2, axp_i2c_freq);
|
|
}
|
|
else
|
|
{
|
|
lgfx::i2c::bitOff(axp_i2c_port, axp_i2c_addr, 0x12, 1 << 2, axp_i2c_freq);
|
|
}
|
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x28, brightness << 4, 0x0F, axp_i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Panel_M5StickCPlus : public lgfx::Panel_ST7789
|
|
{
|
|
Panel_M5StickCPlus(void)
|
|
{
|
|
_cfg.invert = true;
|
|
_cfg.pin_cs = GPIO_NUM_5;
|
|
_cfg.pin_rst = GPIO_NUM_18;
|
|
_cfg.panel_width = 135;
|
|
_cfg.panel_height = 240;
|
|
_cfg.offset_x = 52;
|
|
_cfg.offset_y = 40;
|
|
}
|
|
};
|
|
|
|
#elif defined (CONFIG_IDF_TARGET_ESP32S3)
|
|
|
|
static constexpr int32_t i2c_freq = 400000;
|
|
static constexpr int_fast16_t aw9523_i2c_addr = 0x58; // AW9523B
|
|
static constexpr int_fast16_t axp_i2c_addr = 0x34; // AXP2101
|
|
static constexpr int_fast16_t gc0308_i2c_addr = 0x21; // GC0308
|
|
static constexpr int_fast16_t i2c_port = I2C_NUM_1;
|
|
static constexpr int_fast16_t i2c_sda = GPIO_NUM_12;
|
|
static constexpr int_fast16_t i2c_scl = GPIO_NUM_11;
|
|
|
|
struct Panel_M5StackCoreS3 : public lgfx::Panel_ILI9342
|
|
{
|
|
Panel_M5StackCoreS3(void)
|
|
{
|
|
_cfg.pin_cs = GPIO_NUM_3;
|
|
_cfg.invert = true;
|
|
_cfg.offset_rotation = 3;
|
|
|
|
_rotation = 1; // default rotation
|
|
}
|
|
|
|
void rst_control(bool level) override
|
|
{
|
|
uint8_t bits = level ? (1<<5) : 0;
|
|
uint8_t mask = level ? ~0 : ~(1<<5);
|
|
// LCD_RST
|
|
lgfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x03, bits, mask, i2c_freq);
|
|
}
|
|
|
|
void cs_control(bool flg) override
|
|
{
|
|
lgfx::Panel_ILI9342::cs_control(flg);
|
|
// CS操作時にGPIO35の役割を切り替える (MISO or D/C);
|
|
|
|
// FSPIQ_IN_IDX==FSPI MISO / SIG_GPIO_OUT_IDX==GPIO OUT
|
|
// *(volatile uint32_t*)GPIO_FUNC35_OUT_SEL_CFG_REG = flg ? FSPIQ_OUT_IDX : SIG_GPIO_OUT_IDX;
|
|
|
|
// CS HIGHの場合はGPIO出力を無効化し、MISO入力として機能させる。
|
|
// CS LOW の場合はGPIO出力を有効化し、D/Cとして機能させる。
|
|
*(volatile uint32_t*)( flg
|
|
? GPIO_ENABLE1_W1TC_REG
|
|
: GPIO_ENABLE1_W1TS_REG
|
|
) = 1u << (GPIO_NUM_35 & 31);
|
|
}
|
|
};
|
|
|
|
struct Touch_M5StackCoreS3 : public lgfx::Touch_FT5x06
|
|
{
|
|
Touch_M5StackCoreS3(void)
|
|
{
|
|
_cfg.pin_int = GPIO_NUM_21;
|
|
_cfg.pin_sda = i2c_sda;
|
|
_cfg.pin_scl = i2c_scl;
|
|
_cfg.i2c_addr = 0x38;
|
|
_cfg.i2c_port = i2c_port;
|
|
_cfg.freq = i2c_freq;
|
|
_cfg.x_min = 0;
|
|
_cfg.x_max = 319;
|
|
_cfg.y_min = 0;
|
|
_cfg.y_max = 239;
|
|
_cfg.bus_shared = false;
|
|
}
|
|
|
|
uint_fast8_t getTouchRaw(touch_point_t* tp, uint_fast8_t count) override
|
|
{
|
|
uint_fast8_t res = 0;
|
|
if (!gpio_in(_cfg.pin_int))
|
|
{
|
|
res = lgfx::Touch_FT5x06::getTouchRaw(tp, count);
|
|
if (res == 0)
|
|
{ /// clear INT.
|
|
// レジスタ 0x00を読み出すとPort0のINTがクリアされ、レジスタ 0x01を読み出すとPort1のINTがクリアされる。
|
|
lgfx::i2c::readRegister8(i2c_port, aw9523_i2c_addr, 0x00, i2c_freq);
|
|
lgfx::i2c::readRegister8(i2c_port, aw9523_i2c_addr, 0x01, i2c_freq);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
|
|
struct Light_M5StackCoreS3 : public lgfx::ILight
|
|
{
|
|
bool init(uint8_t brightness) override
|
|
{
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(uint8_t brightness) override
|
|
{
|
|
if (brightness)
|
|
{
|
|
brightness = ((brightness + 641) >> 5);
|
|
// AXP2101 reg 0x90 = LDOS ON/OFF control
|
|
lgfx::i2c::bitOn(i2c_port, axp_i2c_addr, 0x90, 0x80, i2c_freq); // DLDO1 enable
|
|
}
|
|
else
|
|
{
|
|
lgfx::i2c::bitOff(i2c_port, axp_i2c_addr, 0x90, 0x80, i2c_freq); // DLDO1 disable
|
|
}
|
|
// AXP2101 reg 0x99 = DLDO1 voltage setting
|
|
lgfx::i2c::writeRegister8(i2c_port, axp_i2c_addr, 0x99, brightness, 0, i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Light_M5StackAtomS3R : public lgfx::ILight
|
|
{
|
|
bool init(uint8_t brightness) override
|
|
{
|
|
lgfx::i2c::init(i2c_port, GPIO_NUM_45, GPIO_NUM_0);
|
|
lgfx::i2c::writeRegister8(i2c_port, 48, 0x00, 0b01000000, 0, i2c_freq);
|
|
lgfx::delay(1);
|
|
lgfx::i2c::writeRegister8(i2c_port, 48, 0x08, 0b00000001, 0, i2c_freq);
|
|
lgfx::i2c::writeRegister8(i2c_port, 48, 0x70, 0b00000000, 0, i2c_freq);
|
|
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(uint8_t brightness) override
|
|
{
|
|
lgfx::i2c::writeRegister8(i2c_port, 48, 0x0e, brightness, 0, i2c_freq);
|
|
}
|
|
};
|
|
|
|
struct Light_M5StackStampPLC : public lgfx::ILight
|
|
{
|
|
bool _is_backlight_inited = false;
|
|
|
|
bool init(uint8_t brightness) override
|
|
{
|
|
lgfx::i2c::init(i2c_port, GPIO_NUM_13, GPIO_NUM_15);
|
|
|
|
// set direction: output
|
|
auto value = lgfx::i2c::readRegister8(i2c_port, pi4io1_i2c_addr, 0x03, i2c_freq).has_value();
|
|
value |= (1 << 7);
|
|
lgfx::i2c::writeRegister8(i2c_port, pi4io1_i2c_addr, 0x03, value, 0, i2c_freq);
|
|
|
|
// set pull mode: down
|
|
value = lgfx::i2c::readRegister8(i2c_port, pi4io1_i2c_addr, 0x0d, i2c_freq).has_value();
|
|
value &= ~(1 << 7);
|
|
lgfx::i2c::writeRegister8(i2c_port, pi4io1_i2c_addr, 0x0d, value, 0, i2c_freq);
|
|
|
|
// set high impedance: off
|
|
value = lgfx::i2c::readRegister8(i2c_port, pi4io1_i2c_addr, 0x07, i2c_freq).has_value();
|
|
value &= ~(1 << 7);
|
|
lgfx::i2c::writeRegister8(i2c_port, pi4io1_i2c_addr, 0x07, value, 0, i2c_freq);
|
|
|
|
_is_backlight_inited = true;
|
|
setBrightness(brightness);
|
|
return true;
|
|
}
|
|
|
|
void setBrightness(uint8_t brightness) override
|
|
{
|
|
if (!_is_backlight_inited) init(127);
|
|
|
|
auto value = lgfx::i2c::readRegister8(i2c_port, pi4io1_i2c_addr, 0x05, i2c_freq).has_value();
|
|
if (brightness == 0) {
|
|
value |= (1 << 7);
|
|
} else {
|
|
value &= ~(1 << 7);
|
|
}
|
|
lgfx::i2c::writeRegister8(i2c_port, pi4io1_i2c_addr, 0x05, value, 0, i2c_freq);
|
|
}
|
|
};
|
|
#endif
|
|
|
|
__attribute__ ((unused))
|
|
static void _pin_level(std::int_fast16_t pin, bool level)
|
|
{
|
|
lgfx::pinMode(pin, lgfx::pin_mode_t::output);
|
|
if (level) lgfx::gpio_hi(pin);
|
|
else lgfx::gpio_lo(pin);
|
|
}
|
|
|
|
__attribute__ ((unused))
|
|
static void _pin_reset(std::int_fast16_t pin, bool use_reset)
|
|
{
|
|
lgfx::gpio_hi(pin);
|
|
lgfx::pinMode(pin, lgfx::pin_mode_t::output);
|
|
lgfx::delay(1);
|
|
if (!use_reset) return;
|
|
lgfx::gpio_lo(pin);
|
|
lgfx::delay(2);
|
|
lgfx::gpio_hi(pin);
|
|
lgfx::delay(10);
|
|
}
|
|
|
|
/// TF card dummy clock送信 ;
|
|
static void _send_sd_dummy_clock(int spi_host, int_fast16_t pin_cs)
|
|
{
|
|
static constexpr uint32_t dummy_clock[] = { ~0u, ~0u, ~0u, ~0u };
|
|
_pin_level(pin_cs, true);
|
|
m5gfx::spi::writeBytes(spi_host, (const uint8_t*)dummy_clock, sizeof(dummy_clock));
|
|
_pin_level(pin_cs, false);
|
|
}
|
|
|
|
/// TF card をSPIモードに移行する ;
|
|
__attribute__ ((unused))
|
|
static void _set_sd_spimode(int spi_host, int_fast16_t pin_cs)
|
|
{
|
|
m5gfx::spi::beginTransaction(spi_host, 400000, 0);
|
|
_send_sd_dummy_clock(spi_host, pin_cs);
|
|
|
|
uint8_t sd_cmd58[] = { 0x7A, 0, 0, 0, 0, 0xFD, 0xFF, 0xFF }; // READ_OCR command.
|
|
m5gfx::spi::readBytes(spi_host, sd_cmd58, sizeof(sd_cmd58));
|
|
|
|
if (sd_cmd58[6] == sd_cmd58[7]) // not SPI mode
|
|
{
|
|
_send_sd_dummy_clock(spi_host, pin_cs);
|
|
|
|
static constexpr uint8_t sd_cmd0[] = { 0x40, 0, 0, 0, 0, 0x95, 0xFF, 0xFF }; // GO_IDLE_STATE command.
|
|
m5gfx::spi::writeBytes(spi_host, sd_cmd0, sizeof(sd_cmd0));
|
|
}
|
|
_pin_level(pin_cs, true);
|
|
m5gfx::spi::endTransaction(spi_host);
|
|
}
|
|
|
|
__attribute__ ((unused))
|
|
static std::uint32_t _read_panel_id(lgfx::Bus_SPI* bus, std::int32_t pin_cs, std::uint32_t cmd = 0x04, std::uint8_t dummy_read_bit = 1) // 0x04 = RDDID command
|
|
{
|
|
bus->beginTransaction();
|
|
_pin_level(pin_cs, true);
|
|
bus->writeCommand(0, 8);
|
|
bus->wait();
|
|
_pin_level(pin_cs, false);
|
|
bus->writeCommand(cmd, 8);
|
|
bus->beginRead(dummy_read_bit);
|
|
std::uint32_t res = bus->readData(32);
|
|
bus->endTransaction();
|
|
_pin_level(pin_cs, true);
|
|
|
|
ESP_LOGD(LIBRARY_NAME, "[Autodetect] read cmd:%02x = %08x", (int)cmd, (int)res);
|
|
return res;
|
|
}
|
|
|
|
void M5GFX::_set_backlight(lgfx::ILight* bl)
|
|
{
|
|
// if (_light_last) { delete _light_last; }
|
|
_light_last.reset(bl);
|
|
_panel_last->setLight(bl);
|
|
}
|
|
|
|
void M5GFX::_set_pwm_backlight(std::int16_t pin, std::uint8_t ch, std::uint32_t freq, bool invert, uint8_t offset)
|
|
{
|
|
auto bl = new lgfx::Light_PWM();
|
|
auto cfg = bl->config();
|
|
cfg.pin_bl = pin;
|
|
cfg.freq = freq;
|
|
cfg.pwm_channel = ch;
|
|
cfg.offset = offset;
|
|
cfg.invert = invert;
|
|
bl->config(cfg);
|
|
_set_backlight(bl);
|
|
}
|
|
|
|
bool M5GFX::init_impl(bool use_reset, bool use_clear)
|
|
{
|
|
if (getBoard() != board_t::board_unknown)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static constexpr char NVS_KEY[] = "AUTODETECT";
|
|
std::uint32_t nvs_board = 0;
|
|
std::uint32_t nvs_handle = 0;
|
|
if (0 == nvs_open(LIBRARY_NAME, NVS_READONLY, &nvs_handle))
|
|
{
|
|
nvs_get_u32(nvs_handle, NVS_KEY, static_cast<uint32_t*>(&nvs_board));
|
|
nvs_close(nvs_handle);
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] load from NVS : board:%d", (int)nvs_board);
|
|
}
|
|
|
|
if (0 == nvs_board)
|
|
{
|
|
#if defined ( M5GFX_BOARD )
|
|
|
|
nvs_board = M5GFX_BOARD;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_CORE_ESP32 ) || defined ( ARDUINO_M5STACK_FIRE ) || defined ( ARDUINO_M5Stack_Core_ESP32 )
|
|
|
|
nvs_board = board_t::board_M5Stack;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 )
|
|
|
|
nvs_board = board_t::board_M5StackCore2;
|
|
|
|
#elif defined ( ARDUINO_M5STICK_C ) || defined ( ARDUINO_M5Stick_C )
|
|
|
|
nvs_board = board_t::board_M5StickC;
|
|
|
|
#elif defined ( ARDUINO_M5STICK_C_PLUS ) || defined ( ARDUINO_M5Stick_C_Plus )
|
|
|
|
nvs_board = board_t::board_M5StickCPlus;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_COREINK ) || defined ( ARDUINO_M5Stack_CoreInk )
|
|
|
|
nvs_board = board_t::board_M5StackCoreInk;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_PAPER ) || defined ( ARDUINO_M5STACK_Paper )
|
|
|
|
nvs_board = board_t::board_M5Paper;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_TOUGH )
|
|
|
|
nvs_board = board_t::board_M5Tough;
|
|
|
|
#elif defined ( ARDUINO_M5STACK_ATOM ) || defined ( ARDUINO_M5Stack_ATOM )
|
|
|
|
nvs_board = board_t::board_M5Atom;
|
|
|
|
//#elif defined ( ARDUINO_M5STACK_TIMER_CAM ) || defined ( ARDUINO_M5Stack_Timer_CAM )
|
|
#endif
|
|
}
|
|
|
|
auto board = (board_t)nvs_board;
|
|
|
|
int retry = 4;
|
|
do
|
|
{
|
|
if (retry == 1) use_reset = true;
|
|
board = autodetect(use_reset, board);
|
|
//ESP_LOGD(LIBRARY_NAME,"autodetect board:%d", (int)board);
|
|
} while (board_t::board_unknown == board && --retry >= 0);
|
|
_board = board;
|
|
|
|
#if defined ( ARDUINO_M5STACK_ATOM ) || defined ( ARDUINO_M5Stack_ATOM )
|
|
|
|
if (board == board_t::board_unknown || board == board_t::board_M5Atom)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#endif
|
|
|
|
if (nvs_board != board) {
|
|
if (0 == nvs_open(LIBRARY_NAME, NVS_READWRITE, &nvs_handle)) {
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] save to NVS : board:%d", (int)board);
|
|
nvs_set_u32(nvs_handle, NVS_KEY, board);
|
|
nvs_close(nvs_handle);
|
|
}
|
|
}
|
|
|
|
/// autodetectの際にreset済みなのでここではuse_resetをfalseで呼び出す。;
|
|
/// M5Paperはreset後の復帰に800msec程度掛かるのでreset省略は起動時間短縮に有効;
|
|
return LGFX_Device::init_impl(false, use_clear);
|
|
}
|
|
|
|
board_t M5GFX::autodetect(bool use_reset, board_t board)
|
|
{
|
|
auto bus_spi = new Bus_SPI();
|
|
_bus_last.reset(bus_spi);
|
|
|
|
panel(nullptr);
|
|
|
|
auto bus_cfg = bus_spi->config();
|
|
(void)bus_cfg; // prevent compiler warning.
|
|
bus_cfg.freq_write = 8000000;
|
|
bus_cfg.freq_read = 8000000;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.use_lock = true;
|
|
|
|
#if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
|
|
|
|
bus_cfg.spi_host = VSPI_HOST;
|
|
bus_cfg.dma_channel = 1;
|
|
|
|
std::uint32_t id;
|
|
|
|
std::uint32_t pkg_ver = m5gfx::get_pkg_ver();
|
|
// ESP_LOGD(LIBRARY_NAME, "pkg_ver : %02x", (int)pkg_ver);
|
|
|
|
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) /// check PICO-D4 (M5StickC,CPlus,T,T2 / CoreInk / ATOM )
|
|
{
|
|
if (board == 0 || board == board_t::board_M5StickC || board == board_t::board_M5StickCPlus)
|
|
{
|
|
_pin_reset(GPIO_NUM_18, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_15;
|
|
bus_cfg.pin_miso = GPIO_NUM_14;
|
|
bus_cfg.pin_sclk = GPIO_NUM_13;
|
|
bus_cfg.pin_dc = GPIO_NUM_23;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_5);
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{ // check panel (ST7789)
|
|
board = board_t::board_M5StickCPlus;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StickCPlus");
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = HSPI_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 15000000;
|
|
bus_spi->config(bus_cfg);
|
|
auto p = new Panel_M5StickCPlus();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
_set_backlight(new Light_M5StickC());
|
|
goto init_clear;
|
|
}
|
|
if ((id & 0xFF) == 0x7C)
|
|
{ // check panel (ST7735)
|
|
board = board_t::board_M5StickC;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StickC");
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = HSPI_HOST;
|
|
bus_cfg.freq_write = 27000000;
|
|
bus_cfg.freq_read = 14000000;
|
|
bus_spi->config(bus_cfg);
|
|
auto p = new Panel_M5StickC();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
_set_backlight(new Light_M5StickC());
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_18, lgfx::pin_mode_t::input); // LCD RST
|
|
lgfx::pinMode(GPIO_NUM_5 , lgfx::pin_mode_t::input); // LCD CS
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5StackCoreInk)
|
|
{
|
|
_pin_reset( GPIO_NUM_0, true); // EPDがDeepSleepしている場合は自動認識に失敗する。そのためRST制御を必ず行う。;
|
|
bus_cfg.pin_mosi = GPIO_NUM_23;
|
|
bus_cfg.pin_miso = GPIO_NUM_34;
|
|
bus_cfg.pin_sclk = GPIO_NUM_18;
|
|
bus_cfg.pin_dc = GPIO_NUM_15;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
lgfx::Panel_HasBuffer* p = nullptr;
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_9, 0x2f ,0);
|
|
if (id == 0x00010001)
|
|
{ // check panel (e-paper GDEW0154D67)
|
|
p = new lgfx::Panel_GDEW0154D67();
|
|
} else {
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_9, 0x70, 0);
|
|
if ((id & 0xFFFF00FFu) == 0x00F00000u)
|
|
{ // check panel (e-paper GDEW0154M09)
|
|
// ID of first lot : 0x00F00000u
|
|
// ID of 2023/11/17 : 0x00F01600u
|
|
p = new lgfx::Panel_GDEW0154M09();
|
|
}
|
|
}
|
|
if (p != nullptr)
|
|
{
|
|
_pin_level(GPIO_NUM_12, true); // POWER_HOLD_PIN 12
|
|
board = board_t::board_M5StackCoreInk;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StackCoreInk");
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
auto cfg = p->config();
|
|
cfg.panel_height = 200;
|
|
cfg.panel_width = 200;
|
|
cfg.pin_cs = GPIO_NUM_9;
|
|
cfg.pin_rst = GPIO_NUM_0;
|
|
cfg.pin_busy = GPIO_NUM_4;
|
|
p->config(cfg);
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_0, lgfx::pin_mode_t::input); // RST
|
|
lgfx::pinMode(GPIO_NUM_9, lgfx::pin_mode_t::input); // CS
|
|
bus_spi->release();
|
|
}
|
|
|
|
/// LCD / EPD 検出失敗の場合はATOM 判定;
|
|
|
|
}
|
|
else if (pkg_ver == 6) // PICOV3_02 (StickCPlus2 / ATOM PSRAM)
|
|
{
|
|
if (board == 0 || board == board_t::board_M5StickCPlus2)
|
|
{
|
|
_pin_reset(GPIO_NUM_12, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_15;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_13;
|
|
bus_cfg.pin_dc = GPIO_NUM_14;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_5);
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{ // check panel (ST7789)
|
|
_pin_level(GPIO_NUM_4, true); // POWER_HOLD_PIN 4
|
|
board = board_t::board_M5StickCPlus2;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StickCPlus2");
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = HSPI_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 15000000;
|
|
bus_spi->config(bus_cfg);
|
|
auto p = new Panel_M5StickCPlus();
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_rst = GPIO_NUM_12;
|
|
p->config(cfg);
|
|
}
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_27, 7, 256, false, 40);
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_12, lgfx::pin_mode_t::input); // LCD RST
|
|
lgfx::pinMode(GPIO_NUM_5 , lgfx::pin_mode_t::input); // LCD CS
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0)
|
|
{
|
|
board = board_t::board_M5AtomPsram;
|
|
goto init_clear;
|
|
}
|
|
}
|
|
else
|
|
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6)
|
|
{
|
|
/// AXP192の有無を最初に判定し、分岐する。;
|
|
if (board == 0
|
|
|| board == board_t::board_M5Station
|
|
|| board == board_t::board_M5StackCore2
|
|
|| board == board_t::board_M5Tough)
|
|
{
|
|
// I2C addr 0x34 = AXP192
|
|
lgfx::i2c::init(axp_i2c_port, axp_i2c_sda, axp_i2c_scl);
|
|
|
|
auto chk_axp = lgfx::i2c::readRegister8(axp_i2c_port, axp_i2c_addr, 0x03, 400000);
|
|
if (chk_axp.has_value())
|
|
{
|
|
uint_fast16_t axp_exists = 0;
|
|
if (chk_axp.value() == 0x03) { // AXP192 found
|
|
axp_exists = 192;
|
|
ESP_LOGD(LIBRARY_NAME, "AXP192 found");
|
|
}
|
|
else if (chk_axp.value() == 0x4A) { // AXP2101 found
|
|
axp_exists = 2101;
|
|
ESP_LOGD(LIBRARY_NAME, "AXP2101 found");
|
|
}
|
|
|
|
if (axp_exists == 192 && (board == 0 || board == board_t::board_M5Station))
|
|
{
|
|
_pin_reset(GPIO_NUM_15, use_reset); // LCD RST;
|
|
bus_cfg.pin_mosi = GPIO_NUM_23;
|
|
bus_cfg.pin_miso = -1;
|
|
bus_cfg.pin_sclk = GPIO_NUM_18;
|
|
bus_cfg.pin_dc = GPIO_NUM_19;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_5);
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{ // check panel (ST7789)
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5Station");
|
|
board = board_t::board_M5Station;
|
|
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = HSPI_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 15000000;
|
|
bus_spi->config(bus_cfg);
|
|
|
|
auto p = new Panel_M5StickCPlus();
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_rst = 15;
|
|
p->config(cfg);
|
|
p->setRotation(1);
|
|
}
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
/// M5StationのバックライトはM5Toughと同じ;
|
|
_set_backlight(new Light_M5Tough());
|
|
goto init_clear;
|
|
}
|
|
bus_spi->release();
|
|
lgfx::pinMode(GPIO_NUM_5 , lgfx::pin_mode_t::input); // LCD CS
|
|
lgfx::pinMode(GPIO_NUM_15, lgfx::pin_mode_t::input); // LCD RST
|
|
}
|
|
|
|
if (axp_exists && (board == 0 || board == board_t::board_M5StackCore2 || board == board_t::board_M5Tough))
|
|
{
|
|
// 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 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);
|
|
|
|
{
|
|
bus_cfg.pin_mosi = GPIO_NUM_23;
|
|
bus_cfg.pin_miso = GPIO_NUM_38;
|
|
bus_cfg.pin_sclk = GPIO_NUM_18;
|
|
bus_cfg.pin_dc = GPIO_NUM_15;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
|
|
_set_sd_spimode(bus_cfg.spi_host, GPIO_NUM_4);
|
|
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_5);
|
|
if ((id & 0xFF) == 0xE3)
|
|
{ // ILI9342c
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
|
|
auto p = new Panel_M5StackCore2();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
|
|
// Tough のタッチコントローラ有無をチェックする;
|
|
// Core2/Tough 判別条件としてCore2のTP(0x38)の有無を用いた場合、以下の問題が生じる;
|
|
// ・Core2のTPがスリープしている場合は反応が得られない;
|
|
// ・ToughにGoPlus2を組み合わせると0x38に反応がある;
|
|
// 上記のことから、ここではToughのTP(0x2E)の有無によって判定する;
|
|
if ( ! lgfx::i2c::readRegister8(axp_i2c_port, 0x2E, 0, 400000).has_value()) // 0x2E:M5Tough TOUCH
|
|
{
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5StackCore2");
|
|
board = board_t::board_M5StackCore2;
|
|
|
|
ILight* light = nullptr;
|
|
if (isAxp192) {
|
|
light = new Light_M5StackCore2();
|
|
} else {
|
|
light = new Light_M5StackCore2_AXP2101();
|
|
}
|
|
_set_backlight(light);
|
|
|
|
auto t = new lgfx::Touch_FT5x06();
|
|
_touch_last.reset(t);
|
|
auto cfg = t->config();
|
|
cfg.pin_int = GPIO_NUM_39;
|
|
cfg.pin_sda = GPIO_NUM_21;
|
|
cfg.pin_scl = GPIO_NUM_22;
|
|
cfg.i2c_addr = 0x38;
|
|
cfg.i2c_port = I2C_NUM_1;
|
|
cfg.freq = 400000;
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 319;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 279;
|
|
cfg.bus_shared = false;
|
|
t->config(cfg);
|
|
p->touch(t);
|
|
float affine[6] = { 1, 0, 0, 0, 1, 0 };
|
|
p->setCalibrateAffine(affine);
|
|
}
|
|
else
|
|
{
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5Tough");
|
|
board = board_t::board_M5Tough;
|
|
|
|
_set_backlight(new Light_M5Tough());
|
|
|
|
auto t = new Touch_M5Tough();
|
|
_touch_last.reset(t);
|
|
auto cfg = t->config();
|
|
cfg.pin_int = GPIO_NUM_39;
|
|
cfg.pin_sda = GPIO_NUM_21;
|
|
cfg.pin_scl = GPIO_NUM_22;
|
|
cfg.i2c_addr = 0x2E;
|
|
cfg.i2c_port = I2C_NUM_1;
|
|
cfg.freq = 400000;
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 319;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 239;
|
|
cfg.bus_shared = false;
|
|
t->config(cfg);
|
|
p->touch(t);
|
|
}
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_4, lgfx::pin_mode_t::input); // TF card CS
|
|
lgfx::pinMode(GPIO_NUM_5, lgfx::pin_mode_t::input); // LCD CS
|
|
bus_spi->release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5Stack)
|
|
{
|
|
_pin_reset(GPIO_NUM_33, use_reset); // LCD RST;
|
|
bus_cfg.pin_mosi = GPIO_NUM_23;
|
|
bus_cfg.pin_miso = GPIO_NUM_19;
|
|
bus_cfg.pin_sclk = GPIO_NUM_18;
|
|
bus_cfg.pin_dc = GPIO_NUM_27;
|
|
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
|
|
_set_sd_spimode(bus_cfg.spi_host, GPIO_NUM_4);
|
|
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_14);
|
|
if ((id & 0xFF) == 0xE3)
|
|
{ // ILI9342c
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5Stack");
|
|
board = board_t::board_M5Stack;
|
|
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
|
|
auto p = new Panel_M5Stack();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_32, 7, 44100);
|
|
goto init_clear;
|
|
}
|
|
bus_spi->release();
|
|
lgfx::pinMode(GPIO_NUM_4 , lgfx::pin_mode_t::input); // TF card CS
|
|
lgfx::pinMode(GPIO_NUM_14, lgfx::pin_mode_t::input); // LCD CS
|
|
lgfx::pinMode(GPIO_NUM_33, lgfx::pin_mode_t::input); // LCD RST
|
|
}
|
|
|
|
|
|
if (board == 0 || board == board_t::board_M5Paper)
|
|
{
|
|
_pin_reset(GPIO_NUM_23, true);
|
|
lgfx::pinMode(GPIO_NUM_27, lgfx::pin_mode_t::input_pullup); // M5Paper EPD busy pin
|
|
if (!lgfx::gpio_in(GPIO_NUM_27))
|
|
{
|
|
_pin_level(GPIO_NUM_2, true); // M5EPD_MAIN_PWR_PIN 2
|
|
lgfx::pinMode(GPIO_NUM_27, lgfx::pin_mode_t::input);
|
|
bus_cfg.pin_mosi = GPIO_NUM_12;
|
|
bus_cfg.pin_miso = GPIO_NUM_13;
|
|
bus_cfg.pin_sclk = GPIO_NUM_14;
|
|
bus_cfg.pin_dc = -1;
|
|
bus_cfg.spi_3wire = false;
|
|
bus_spi->config(bus_cfg);
|
|
id = lgfx::millis();
|
|
|
|
_pin_level(GPIO_NUM_15, true); // M5Paper CS;
|
|
bus_spi->init();
|
|
_set_sd_spimode(bus_cfg.spi_host, GPIO_NUM_4);
|
|
do
|
|
{
|
|
vTaskDelay(1);
|
|
if (lgfx::millis() - id > 1024) { id = 0; break; }
|
|
} while (!lgfx::gpio_in(GPIO_NUM_27));
|
|
if (id)
|
|
{
|
|
bus_spi->beginTransaction();
|
|
lgfx::gpio_lo(GPIO_NUM_15);
|
|
bus_spi->writeData(__builtin_bswap16(0x6000), 16);
|
|
bus_spi->writeData(__builtin_bswap16(0x0302), 16); // read DevInfo
|
|
id = lgfx::millis();
|
|
bus_spi->wait();
|
|
lgfx::gpio_hi(GPIO_NUM_15);
|
|
do
|
|
{
|
|
vTaskDelay(1);
|
|
if (lgfx::millis() - id > 192) { break; }
|
|
} while (!lgfx::gpio_in(GPIO_NUM_27));
|
|
lgfx::gpio_lo(GPIO_NUM_15);
|
|
bus_spi->writeData(__builtin_bswap16(0x1000), 16);
|
|
bus_spi->writeData(__builtin_bswap16(0x0000), 16);
|
|
std::uint8_t buf[40];
|
|
bus_spi->beginRead();
|
|
bus_spi->readBytes(buf, 40, false);
|
|
bus_spi->endRead();
|
|
bus_spi->endTransaction();
|
|
lgfx::gpio_hi(GPIO_NUM_15);
|
|
id = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
|
|
// ESP_LOGI(LIBRARY_NAME, "[Autodetect] panel size :%08x", (int)id);
|
|
if (id == 0x03C0021C)
|
|
{ // check panel ( panel size 960(0x03C0) x 540(0x021C) )
|
|
board = board_t::board_M5Paper;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5Paper");
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 20000000;
|
|
bus_spi->config(bus_cfg);
|
|
{
|
|
auto p = new lgfx::Panel_IT8951();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
auto cfg = p->config();
|
|
cfg.panel_height = 540;
|
|
cfg.panel_width = 960;
|
|
cfg.pin_cs = GPIO_NUM_15;
|
|
cfg.pin_rst = GPIO_NUM_23;
|
|
cfg.pin_busy = GPIO_NUM_27;
|
|
cfg.offset_rotation = 3;
|
|
p->config(cfg);
|
|
}
|
|
{
|
|
auto t = new lgfx::Touch_GT911();
|
|
_touch_last.reset(t);
|
|
auto cfg = t->config();
|
|
cfg.pin_int = GPIO_NUM_36;
|
|
cfg.pin_sda = GPIO_NUM_21;
|
|
cfg.pin_scl = GPIO_NUM_22;
|
|
#ifdef _M5EPD_H_
|
|
cfg.i2c_port = I2C_NUM_0;
|
|
#else
|
|
cfg.i2c_port = I2C_NUM_1;
|
|
#endif
|
|
cfg.freq = 400000;
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 539;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 959;
|
|
cfg.offset_rotation = 1;
|
|
cfg.bus_shared = false;
|
|
t->config(cfg);
|
|
_panel_last->touch(t);
|
|
}
|
|
goto init_clear;
|
|
}
|
|
}
|
|
bus_spi->release();
|
|
lgfx::pinMode(GPIO_NUM_15, lgfx::pin_mode_t::input); // EPD CS
|
|
lgfx::pinMode(GPIO_NUM_4, lgfx::pin_mode_t::input); // M5Paper TF card CS
|
|
lgfx::pinMode(GPIO_NUM_2, lgfx::pin_mode_t::input); // M5EPD_MAIN_PWR_PIN 2
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_27, lgfx::pin_mode_t::input); // BUSY
|
|
lgfx::pinMode(GPIO_NUM_23, lgfx::pin_mode_t::input); // RST
|
|
}
|
|
}
|
|
|
|
#elif defined (CONFIG_IDF_TARGET_ESP32S3)
|
|
|
|
bus_cfg.spi_host = SPI2_HOST;
|
|
bus_cfg.dma_channel = SPI_DMA_CH_AUTO;
|
|
|
|
std::uint32_t id;
|
|
|
|
std::uint32_t pkg_ver = m5gfx::get_pkg_ver();
|
|
// ESP_LOGD(LIBRARY_NAME, "pkg_ver : %02x / board:%d", (int)pkg_ver, (int)board);
|
|
switch (pkg_ver) {
|
|
case 0: // EFUSE_PKG_VERSION_ESP32S3: // QFN56
|
|
|
|
if (board == 0 || board == board_t::board_M5StackCoreS3 || board == board_t::board_M5StackCoreS3SE)
|
|
{
|
|
lgfx::i2c::init(i2c_port, i2c_sda, i2c_scl);
|
|
|
|
// ESP_LOGI("DEBUG","AW 0x10 :%02x", (int)lgfx::i2c::readRegister8(i2c_port, aw9523_i2c_addr, 0x10, 400000).value());
|
|
// ESP_LOGI("DEBUG","AXP0x03 :%02x", (int)lgfx::i2c::readRegister8(i2c_port, axp_i2c_addr, 0x03, 400000).value());
|
|
|
|
auto chk_axp = lgfx::i2c::readRegister8(i2c_port, axp_i2c_addr, 0x03, i2c_freq);
|
|
if (chk_axp.has_value() && chk_axp.value() == 0x4A)
|
|
{
|
|
auto chk_aw = lgfx::i2c::readRegister8(i2c_port, aw9523_i2c_addr, 0x10, i2c_freq);
|
|
if (chk_aw .has_value() && chk_aw .value() == 0x23)
|
|
{
|
|
auto result = lgfx::gpio::command(
|
|
(const uint8_t[]) {
|
|
lgfx::gpio::command_mode_input_pullup, GPIO_NUM_35,
|
|
lgfx::gpio::command_mode_input_pullup, GPIO_NUM_36,
|
|
lgfx::gpio::command_mode_input_pullup, GPIO_NUM_37,
|
|
lgfx::gpio::command_read , GPIO_NUM_35,
|
|
lgfx::gpio::command_read , GPIO_NUM_36,
|
|
lgfx::gpio::command_read , GPIO_NUM_37,
|
|
lgfx::gpio::command_end
|
|
}
|
|
);
|
|
/// SPIバスのプルアップが効いていない場合はVBUS 5V出力を有効化する。
|
|
/// (USBホストモジュール等、5Vが出ていないと信号線の電気を吸い込む組合せがあるため)
|
|
uint8_t reg0x02 = (result == 0) ? 0b00000111 : 0b00000101;
|
|
uint8_t reg0x03 = (result == 0) ? 0b10000011 : 0b00000011;
|
|
m5gfx::i2c::bitOn(i2c_port, aw9523_i2c_addr, 0x02, reg0x02); //port0 output ctrl
|
|
m5gfx::i2c::bitOn(i2c_port, aw9523_i2c_addr, 0x03, reg0x03); //port1 output ctrl
|
|
m5gfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x04, 0b00011000); // CONFIG_P0
|
|
m5gfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x05, 0b00001100); // CONFIG_P1
|
|
m5gfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x11, 0b00010000); // GCR P0 port is Push-Pull mode.
|
|
m5gfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x12, 0b11111111); // LEDMODE_P0
|
|
m5gfx::i2c::writeRegister8(i2c_port, aw9523_i2c_addr, 0x13, 0b11111111); // LEDMODE_P1
|
|
m5gfx::i2c::writeRegister8(i2c_port, axp_i2c_addr, 0x90, 0xBF); // LDOS ON/OFF control 0
|
|
m5gfx::i2c::writeRegister8(i2c_port, axp_i2c_addr, 0x94, 33 - 5); // ALDO3 set to 3.3v // for GC0308 Camera
|
|
m5gfx::i2c::writeRegister8(i2c_port, axp_i2c_addr, 0x95, 33 - 5); // ALDO4 set to 3.3v // for TF card slot
|
|
|
|
bus_cfg.pin_mosi = GPIO_NUM_37;
|
|
bus_cfg.pin_miso = GPIO_NUM_35;
|
|
bus_cfg.pin_sclk = GPIO_NUM_36;
|
|
bus_cfg.pin_dc = GPIO_NUM_35;// MISOとLCD D/CをGPIO35でシェアしている;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
|
|
_set_sd_spimode(bus_cfg.spi_host, GPIO_NUM_4);
|
|
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_3);
|
|
if ((id & 0xFF) == 0xE3)
|
|
{ // check panel (ILI9342)
|
|
board = board_t::board_M5StackCoreS3;
|
|
// Camera GC0308 check (not found == M5StackCoreS3SE)
|
|
auto chk_gc = lgfx::i2c::readRegister8(i2c_port, gc0308_i2c_addr, 0x00, i2c_freq);
|
|
if (chk_gc .has_value() && chk_gc .value() == 0x9b) {
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5StackCoreS3");
|
|
} else {
|
|
board = board_M5StackCoreS3SE;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5StackCoreS3SE");
|
|
}
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
auto p = new Panel_M5StackCoreS3();
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
|
|
_set_backlight(new Light_M5StackCoreS3());
|
|
|
|
{
|
|
auto t = new Touch_M5StackCoreS3();
|
|
_touch_last.reset(t);
|
|
_panel_last->touch(t);
|
|
}
|
|
|
|
goto init_clear;
|
|
}
|
|
bus_spi->release();
|
|
lgfx::pinMode(GPIO_NUM_4, lgfx::pin_mode_t::input); // TF card CS
|
|
lgfx::pinMode(GPIO_NUM_3, lgfx::pin_mode_t::input); // LCD CS
|
|
}
|
|
}
|
|
lgfx::i2c::release(i2c_port);
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5Dial)
|
|
{
|
|
_pin_reset(GPIO_NUM_8, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_5;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_6;
|
|
bus_cfg.pin_dc = GPIO_NUM_4;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_7);
|
|
if ((id & 0xFFFFFF) == 0x019a00)
|
|
{ // check panel (GC9A01)
|
|
board = board_t::board_M5Dial;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5Dial");
|
|
bus_spi->release();
|
|
bus_cfg.freq_write = 80000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_GC9A01();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_7;
|
|
cfg.pin_rst = GPIO_NUM_8;
|
|
cfg.panel_width = 240;
|
|
cfg.panel_height = 240;
|
|
cfg.readable = false;
|
|
cfg.invert = true;
|
|
p->config(cfg);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_9, 7, 44100);
|
|
|
|
{
|
|
auto t = new m5gfx::Touch_FT5x06();
|
|
if (t) {
|
|
_touch_last.reset(t);
|
|
|
|
auto cfg = t->config();
|
|
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 239;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 239;
|
|
cfg.pin_int = GPIO_NUM_14;
|
|
cfg.bus_shared = false;
|
|
cfg.offset_rotation = 0;
|
|
|
|
cfg.i2c_port = 1;
|
|
cfg.i2c_addr = 0x38;
|
|
cfg.pin_sda = GPIO_NUM_11;
|
|
cfg.pin_scl = GPIO_NUM_12;
|
|
cfg.freq = 400000;
|
|
|
|
t->config(cfg);
|
|
|
|
_panel_last->touch(t);
|
|
}
|
|
}
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_8, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5PaperS3)
|
|
{
|
|
static constexpr int_fast16_t papers3_i2c_sda = GPIO_NUM_41;
|
|
static constexpr int_fast16_t papers3_i2c_scl = GPIO_NUM_42;
|
|
static constexpr const uint8_t gt911_i2c_addr[] = { 0x14, 0x5D };
|
|
gpio::pin_backup_t backup_pins[] = { papers3_i2c_sda, papers3_i2c_scl };
|
|
auto result = lgfx::gpio::command(
|
|
(const uint8_t[]) {
|
|
lgfx::gpio::command_mode_output , papers3_i2c_scl,
|
|
lgfx::gpio::command_write_low , papers3_i2c_scl,
|
|
lgfx::gpio::command_mode_output , papers3_i2c_sda,
|
|
lgfx::gpio::command_write_low , papers3_i2c_sda,
|
|
lgfx::gpio::command_write_high , papers3_i2c_scl,
|
|
lgfx::gpio::command_write_high , papers3_i2c_sda,
|
|
lgfx::gpio::command_mode_input_pulldown, papers3_i2c_scl,
|
|
lgfx::gpio::command_mode_input_pulldown, papers3_i2c_sda,
|
|
lgfx::gpio::command_delay , 1,
|
|
lgfx::gpio::command_read , papers3_i2c_scl,
|
|
lgfx::gpio::command_read , papers3_i2c_sda,
|
|
lgfx::gpio::command_end
|
|
}
|
|
);
|
|
// Check G41,G42 HIGH
|
|
if (result == 0x03) {
|
|
lgfx::i2c::init(i2c_port, papers3_i2c_sda, papers3_i2c_scl);
|
|
{
|
|
bool gt911_found = false;
|
|
for (auto addr: gt911_i2c_addr) {
|
|
if (lgfx::i2c::beginTransaction(i2c_port, addr, 400000).has_value()) {
|
|
gt911_found = lgfx::i2c::endTransaction(i2c_port).has_value();
|
|
if (gt911_found) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (gt911_found) {
|
|
board = board_t::board_M5PaperS3;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5PaperS3");
|
|
// PWROFF_PULSE_PIN
|
|
lgfx::pinMode(GPIO_NUM_44, lgfx::pin_mode_t::output);
|
|
lgfx::gpio_lo(GPIO_NUM_44);
|
|
|
|
#if !(defined(CONFIG_ESP32S3_SPIRAM_SUPPORT))
|
|
ESP_LOGE(LIBRARY_NAME, "M5PaperS3 need OPI-PSRAM enabled");
|
|
#elif !defined (CONFIG_SPIRAM_MODE_OCT)
|
|
ESP_LOGE(LIBRARY_NAME, "M5PaperS3 need OPI-PSRAM enabled");
|
|
#else
|
|
auto bus_epd = new Bus_EPD();
|
|
_bus_last.reset(bus_epd);
|
|
auto p = new lgfx::Panel_EPD();
|
|
_panel_last.reset(p);
|
|
|
|
{
|
|
auto bus_cfg = bus_epd->config();
|
|
bus_cfg.bus_speed = 20000000;
|
|
bus_cfg.pin_data[0] = GPIO_NUM_6;
|
|
bus_cfg.pin_data[1] = GPIO_NUM_14;
|
|
bus_cfg.pin_data[2] = GPIO_NUM_7;
|
|
bus_cfg.pin_data[3] = GPIO_NUM_12;
|
|
bus_cfg.pin_data[4] = GPIO_NUM_9;
|
|
bus_cfg.pin_data[5] = GPIO_NUM_11;
|
|
bus_cfg.pin_data[6] = GPIO_NUM_8;
|
|
bus_cfg.pin_data[7] = GPIO_NUM_10;
|
|
bus_cfg.pin_pwr = GPIO_NUM_46;
|
|
bus_cfg.pin_spv = GPIO_NUM_17;
|
|
bus_cfg.pin_ckv = GPIO_NUM_18;
|
|
bus_cfg.pin_sph = GPIO_NUM_13;
|
|
bus_cfg.pin_oe = GPIO_NUM_45;
|
|
bus_cfg.pin_le = GPIO_NUM_15;
|
|
bus_cfg.pin_cl = GPIO_NUM_16;
|
|
bus_cfg.bus_width = 8;
|
|
bus_epd->config(bus_cfg);
|
|
p->setBus(bus_epd);
|
|
}
|
|
{
|
|
auto cfg_detail = p->config_detail();
|
|
cfg_detail.line_padding = 8;
|
|
p->config_detail(cfg_detail);
|
|
}
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.memory_width = 960;
|
|
cfg.panel_width = 960;
|
|
cfg.memory_height = 540;
|
|
cfg.panel_height = 540;
|
|
cfg.offset_rotation = 3;
|
|
cfg.offset_x = 0;
|
|
cfg.offset_y = 0;
|
|
cfg.bus_shared = false;
|
|
p->config(cfg);
|
|
}
|
|
|
|
{
|
|
auto t = new lgfx::Touch_GT911();
|
|
_touch_last.reset(t);
|
|
auto cfg = t->config();
|
|
cfg.pin_int = GPIO_NUM_48;
|
|
cfg.pin_sda = GPIO_NUM_41;
|
|
cfg.pin_scl = GPIO_NUM_42;
|
|
cfg.freq = 400000;
|
|
cfg.i2c_port = I2C_NUM_1;
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 539;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 959;
|
|
cfg.offset_rotation = 1;
|
|
cfg.bus_shared = false;
|
|
t->config(cfg);
|
|
_panel_last->touch(t);
|
|
p->touch(t);
|
|
}
|
|
goto init_clear;
|
|
#endif
|
|
}
|
|
}
|
|
lgfx::i2c::release(i2c_port);
|
|
}
|
|
for (auto &bup : backup_pins) { bup.restore(); }
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5AtomS3)
|
|
{
|
|
_pin_reset(GPIO_NUM_34, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_21;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_17;
|
|
bus_cfg.pin_dc = GPIO_NUM_33;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_15);
|
|
if ((id & 0xFFFFFF) == 0x079100)
|
|
{ // check panel (GC9107)
|
|
board = board_t::board_M5AtomS3;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5AtomS3");
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = SPI3_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_GC9107();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_15;
|
|
cfg.pin_rst = GPIO_NUM_34;
|
|
cfg.panel_width = 128;
|
|
cfg.panel_height = 128;
|
|
cfg.offset_y = 32;
|
|
cfg.readable = false;
|
|
p->config(cfg);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_16, 7, 256, false, 48);
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_48, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5DinMeter)
|
|
{
|
|
_pin_reset(GPIO_NUM_8, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_5;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_6;
|
|
bus_cfg.pin_dc = GPIO_NUM_4;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_7);
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{ // check panel (ST7789)
|
|
board = board_t::board_M5DinMeter;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5DinMeter");
|
|
bus_spi->release();
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_ST7789();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_7;
|
|
cfg.pin_rst = GPIO_NUM_8;
|
|
cfg.panel_width = 135;
|
|
cfg.panel_height = 240;
|
|
cfg.offset_x = 52;
|
|
cfg.offset_y = 40;
|
|
cfg.offset_rotation = 2;
|
|
cfg.readable = true;
|
|
cfg.invert = true;
|
|
p->config(cfg);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_9, 7, 256, false, 16);
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_8, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5Cardputer || board == board_t::board_M5VAMeter)
|
|
{
|
|
_pin_reset(GPIO_NUM_33, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_35;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_36;
|
|
bus_cfg.pin_dc = GPIO_NUM_34;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_37);
|
|
// check panel (ST7789)
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{
|
|
board = board_t::board_M5Cardputer;
|
|
gpio::pin_backup_t backup_pins[] = { GPIO_NUM_5, GPIO_NUM_6 };
|
|
auto result = lgfx::gpio::command(
|
|
(const uint8_t[]) {
|
|
lgfx::gpio::command_mode_input_pulldown, GPIO_NUM_6,
|
|
lgfx::gpio::command_mode_input_pulldown, GPIO_NUM_5,
|
|
lgfx::gpio::command_read , GPIO_NUM_6,
|
|
lgfx::gpio::command_read , GPIO_NUM_5,
|
|
lgfx::gpio::command_end
|
|
}
|
|
);
|
|
for (auto &bup : backup_pins) { bup.restore(); }
|
|
if (result == 3) {
|
|
m5gfx::i2c::i2c_temporary_switcher_t backup_i2c_setting(1, GPIO_NUM_5, GPIO_NUM_6);
|
|
result = (m5gfx::i2c::transactionWrite(1, 0x40, nullptr, 0).has_value()
|
|
&& m5gfx::i2c::transactionWrite(1, 0x41, nullptr, 0).has_value());
|
|
backup_i2c_setting.restore();
|
|
if (result) {
|
|
board = board_t::board_M5VAMeter;
|
|
}
|
|
}
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = SPI3_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_ST7789();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_37;
|
|
cfg.pin_rst = GPIO_NUM_33;
|
|
cfg.panel_height = 240;
|
|
cfg.offset_rotation = 0;
|
|
cfg.readable = true;
|
|
cfg.invert = true;
|
|
int rotation = 0;
|
|
int bl_freq = 256;
|
|
int bl_offset = 16;
|
|
if (board == board_t::board_M5Cardputer) {
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5Cardputer");
|
|
cfg.panel_width = 135;
|
|
cfg.offset_x = 52;
|
|
cfg.offset_y = 40;
|
|
rotation = 1;
|
|
} else {
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5VAMeter");
|
|
cfg.panel_width = 240;
|
|
cfg.offset_x = 0;
|
|
cfg.offset_y = 0;
|
|
bl_freq = 512;
|
|
bl_offset = 64;
|
|
}
|
|
p->config(cfg);
|
|
p->setRotation(rotation);
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_38, 7, bl_freq, false, bl_offset);
|
|
}
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_33, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5AirQ)
|
|
{
|
|
_pin_reset( GPIO_NUM_2, true); // EPDがDeepSleepしている場合は自動認識に失敗する。そのためRST制御を必ず行う。;
|
|
bus_cfg.pin_mosi = GPIO_NUM_6;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_5;
|
|
bus_cfg.pin_dc = GPIO_NUM_3;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
lgfx::Panel_HasBuffer* p = nullptr;
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_4, 0x2f ,0);
|
|
if (id == 0x00010001)
|
|
{ // check panel (e-paper GDEW0154D67)
|
|
p = new lgfx::Panel_GDEW0154D67();
|
|
} else {
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_4, 0x70, 0);
|
|
if ((id & 0xFFFF00FFu) == 0x00F00000u)
|
|
{ // check panel (e-paper GDEW0154M09)
|
|
// ID of first lot : 0x00F00000u
|
|
// ID of 2023/11/17 : 0x00F01600u
|
|
p = new lgfx::Panel_GDEW0154M09();
|
|
}
|
|
}
|
|
if (p != nullptr)
|
|
{
|
|
_pin_level(GPIO_NUM_46, true); // POWER_HOLD_PIN 46
|
|
board = board_t::board_M5AirQ;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] M5AirQ");
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
p->bus(bus_spi);
|
|
_panel_last.reset(p);
|
|
auto cfg = p->config();
|
|
cfg.panel_height = 200;
|
|
cfg.panel_width = 200;
|
|
cfg.pin_cs = GPIO_NUM_4;
|
|
cfg.pin_rst = GPIO_NUM_2;
|
|
cfg.pin_busy = GPIO_NUM_1;
|
|
p->config(cfg);
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_2, lgfx::pin_mode_t::input); // RST
|
|
lgfx::pinMode(GPIO_NUM_4, lgfx::pin_mode_t::input); // CS
|
|
bus_spi->release();
|
|
}
|
|
|
|
if (board == 0 || board == board_t::board_M5StampPLC)
|
|
{
|
|
_pin_reset(GPIO_NUM_3, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_8;
|
|
bus_cfg.pin_miso = GPIO_NUM_9;
|
|
bus_cfg.pin_sclk = GPIO_NUM_7;
|
|
bus_cfg.pin_dc = GPIO_NUM_6;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
|
|
_set_sd_spimode(bus_cfg.spi_host, GPIO_NUM_10);
|
|
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_12);
|
|
// check panel (ST7789)
|
|
if ((id & 0xFB) == 0x81) // 0x81 or 0x85
|
|
{
|
|
board = board_t::board_M5StampPLC;
|
|
bus_spi->release();
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_ST7789();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_12;
|
|
cfg.pin_rst = GPIO_NUM_3;
|
|
cfg.panel_width = 135;
|
|
cfg.panel_height = 240;
|
|
cfg.offset_x = 52;
|
|
cfg.offset_y = 40;
|
|
cfg.offset_rotation = 0;
|
|
cfg.readable = true;
|
|
cfg.invert = true;
|
|
cfg.bus_shared = true;
|
|
p->config(cfg);
|
|
p->setRotation(1);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_backlight(new Light_M5StackStampPLC());
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_3, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
|
|
break;
|
|
case 1: // EFUSE_PKG_VERSION_ESP32S3PICO: // LGA56
|
|
|
|
if (board == 0 || board == board_t::board_M5AtomS3R)
|
|
{
|
|
_pin_reset(GPIO_NUM_48, use_reset); // LCD RST
|
|
bus_cfg.pin_mosi = GPIO_NUM_21;
|
|
bus_cfg.pin_miso = (gpio_num_t)-1; //GPIO_NUM_NC;
|
|
bus_cfg.pin_sclk = GPIO_NUM_15;
|
|
bus_cfg.pin_dc = GPIO_NUM_42;
|
|
bus_cfg.spi_mode = 0;
|
|
bus_cfg.spi_3wire = true;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
id = _read_panel_id(bus_spi, GPIO_NUM_14);
|
|
if ((id & 0xFFFFFF) == 0x079100)
|
|
{ // check panel (GC9107)
|
|
board = board_t::board_M5AtomS3R;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5AtomS3R");
|
|
bus_spi->release();
|
|
bus_cfg.spi_host = SPI3_HOST;
|
|
bus_cfg.freq_write = 40000000;
|
|
bus_cfg.freq_read = 16000000;
|
|
bus_spi->config(bus_cfg);
|
|
bus_spi->init();
|
|
auto p = new Panel_GC9107();
|
|
p->bus(bus_spi);
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.pin_cs = GPIO_NUM_14;
|
|
cfg.pin_rst = GPIO_NUM_48;
|
|
cfg.panel_width = 128;
|
|
cfg.panel_height = 128;
|
|
cfg.offset_y = 32;
|
|
cfg.readable = false;
|
|
cfg.bus_shared = false;
|
|
p->config(cfg);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_backlight(new Light_M5StackAtomS3R());
|
|
|
|
goto init_clear;
|
|
}
|
|
lgfx::pinMode(GPIO_NUM_48, lgfx::pin_mode_t::input); // LCD RST
|
|
bus_spi->release();
|
|
}
|
|
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
#elif defined (CONFIG_IDF_TARGET_ESP32P4)
|
|
|
|
std::uint32_t id;
|
|
|
|
std::uint32_t pkg_ver = m5gfx::get_pkg_ver();
|
|
ESP_LOGD(LIBRARY_NAME, "pkg_ver : %02x", (int)pkg_ver);
|
|
|
|
if (true) // pkg_ver == EFUSE_RD_CHIP_VER_PKG_
|
|
{
|
|
if (board == 0 || board == board_t::board_M5Tab5)
|
|
{
|
|
// SDA = GPIO_NUM_31
|
|
// SCL = GPIO_NUM_32
|
|
// TP INT = GPIO_NUM_23
|
|
lgfx::pinMode(GPIO_NUM_23, lgfx::pin_mode_t::output); // TP INT
|
|
lgfx::gpio_hi(GPIO_NUM_23); // select I2C Addr (high=0x14 / low=0x5D)
|
|
lgfx::i2c::init(in_i2c_port, GPIO_NUM_31, GPIO_NUM_32);
|
|
|
|
id = lgfx::i2c::readRegister8(in_i2c_port, pi4io1_i2c_addr, 0x01).has_value()
|
|
&& lgfx::i2c::readRegister8(in_i2c_port, pi4io2_i2c_addr, 0x01).has_value();
|
|
if (id != 0) {
|
|
board = board_t::board_M5Tab5;
|
|
ESP_LOGI(LIBRARY_NAME, "[Autodetect] board_M5Tab5");
|
|
|
|
static constexpr const uint8_t reg_data_io1_1[] = {
|
|
0x03, 0b01111111, 0, // PI4IO_REG_IO_DIR
|
|
0x05, 0b01010110, 0, // PI4IO_REG_OUT_SET (bit5=GT911 TouchReset LOW)
|
|
0x07, 0b00000000, 0, // PI4IO_REG_OUT_H_IM
|
|
0x0D, 0b01111111, 0, // PI4IO_REG_PULL_SEL
|
|
0x0B, 0b01111111, 0, // PI4IO_REG_PULL_EN
|
|
0xFF,0xFF,0xFF,
|
|
};
|
|
static constexpr const uint8_t reg_data_io1_2[] = {
|
|
0x05, 0b01110110, 0, // PI4IO_REG_OUT_SET (bit5=GT911 TouchReset HIGH)
|
|
0xFF,0xFF,0xFF,
|
|
};
|
|
|
|
static constexpr const uint8_t reg_data_io2[] = {
|
|
0x03, 0b10111001, 0, // PI4IO_REG_IO_DIR
|
|
0x07, 0b00000110, 0, // PI4IO_REG_OUT_H_IM
|
|
0x0D, 0b10111001, 0, // PI4IO_REG_PULL_SEL
|
|
0x0B, 0b11111001, 0, // PI4IO_REG_PULL_EN
|
|
0x09, 0b01000000, 0, // PI4IO_REG_IN_DEF_STA
|
|
0x11, 0b10111111, 0, // PI4IO_REG_INT_MASK
|
|
0x05, 0b10001001, 0, // PI4IO_REG_OUT_SET
|
|
0xFF,0xFF,0xFF,
|
|
};
|
|
|
|
i2c_write_register8_array(in_i2c_port, pi4io1_i2c_addr, reg_data_io1_1, 400000);
|
|
i2c_write_register8_array(in_i2c_port, pi4io2_i2c_addr, reg_data_io2, 400000);
|
|
i2c_write_register8_array(in_i2c_port, pi4io1_i2c_addr, reg_data_io1_2, 400000);
|
|
|
|
auto p = new Panel_ILI9881C();
|
|
{
|
|
auto cfg = p->config();
|
|
cfg.panel_width = 720;
|
|
cfg.panel_height = 1280;
|
|
cfg.memory_width = 720;
|
|
cfg.memory_height = 1280;
|
|
cfg.readable = true;
|
|
p->config(cfg);
|
|
}
|
|
_panel_last.reset(p);
|
|
_set_pwm_backlight(GPIO_NUM_22, 7, 44100);
|
|
|
|
{
|
|
auto t = new m5gfx::Touch_GT911();
|
|
if (t) {
|
|
_touch_last.reset(t);
|
|
|
|
auto cfg = t->config();
|
|
|
|
cfg.pin_rst = -1;
|
|
cfg.pin_sda = GPIO_NUM_31;
|
|
cfg.pin_scl = GPIO_NUM_32;
|
|
cfg.pin_int = GPIO_NUM_23;
|
|
cfg.freq = 400000;
|
|
cfg.x_min = 0;
|
|
cfg.x_max = 719;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = 1279;
|
|
cfg.i2c_port = 1;
|
|
cfg.bus_shared = true;
|
|
cfg.offset_rotation = 0;
|
|
t->config(cfg);
|
|
|
|
_panel_last->touch(t);
|
|
}
|
|
}
|
|
|
|
goto init_clear;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
board = board_t::board_unknown;
|
|
goto init_clear;
|
|
init_clear:
|
|
|
|
panel(_panel_last.get());
|
|
|
|
return board;
|
|
}
|
|
|
|
#else
|
|
|
|
bool M5GFX::init_impl(bool use_reset, bool use_clear)
|
|
{
|
|
board_t b = board_t::board_unknown;
|
|
#if defined (M5GFX_BOARD)
|
|
b = M5GFX_BOARD;
|
|
#endif
|
|
_board = autodetect(use_reset, b);
|
|
return LGFX_Device::init_impl(use_reset, use_clear);
|
|
}
|
|
|
|
board_t M5GFX::autodetect(bool use_reset, board_t board)
|
|
{
|
|
(void)use_reset;
|
|
auto p = new Panel_sdl();
|
|
_panel_last.reset(p);
|
|
auto pnl_cfg = p->config();
|
|
|
|
int_fast16_t w = 320;
|
|
int_fast16_t h = 240;
|
|
int_fast16_t r = 0;
|
|
int scale = 1;
|
|
#if defined (M5GFX_SCALE)
|
|
#if M5GFX_SCALE > 1
|
|
scale = M5GFX_SCALE;
|
|
#endif
|
|
#endif
|
|
|
|
if (board == 0) {
|
|
board = board_M5Stack;
|
|
}
|
|
|
|
const char* title;
|
|
switch (board) {
|
|
case board_M5Stack: title = "M5Stack"; break;
|
|
case board_M5StackCore2: title = "M5StackCore2"; break;
|
|
case board_M5StackCoreS3: title = "M5StackCoreS3"; break;
|
|
case board_M5StackCoreS3SE:title = "M5StackCoreS3SE";break;
|
|
case board_M5StickC: title = "M5StickC"; break;
|
|
case board_M5StickCPlus: title = "M5StickCPlus"; break;
|
|
case board_M5StickCPlus2: title = "M5StickCPlus2"; break;
|
|
case board_M5StackCoreInk: title = "M5StackCoreInk"; break;
|
|
case board_M5Paper: title = "M5Paper"; break;
|
|
case board_M5PaperS3: title = "M5PaperS3"; break;
|
|
case board_M5Tough: title = "M5Tough"; break;
|
|
case board_M5Station: title = "M5Station"; break;
|
|
case board_M5AtomS3: title = "M5AtomS3"; break;
|
|
case board_M5AtomS3R: title = "M5AtomS3R"; break;
|
|
case board_M5Dial: title = "M5Dial"; break;
|
|
case board_M5Cardputer: title = "M5Cardputer"; break;
|
|
case board_M5DinMeter: title = "M5DinMeter"; break;
|
|
case board_M5AirQ: title = "M5AirQ"; break;
|
|
case board_M5VAMeter: title = "M5VAMeter"; break;
|
|
case board_M5StampPLC: title = "M5StampPLC"; break;
|
|
case board_M5Tab5: title = "M5Tab5"; break;
|
|
default: title = "M5GFX"; break;
|
|
}
|
|
p->setWindowTitle(title);
|
|
|
|
switch (board) {
|
|
case board_M5AtomS3:
|
|
case board_M5AtomS3R:
|
|
w = 128;
|
|
h = 128;
|
|
break;
|
|
|
|
case board_M5Paper:
|
|
case board_M5PaperS3:
|
|
w = 960;
|
|
h = 540;
|
|
pnl_cfg.offset_rotation = 3;
|
|
p->setColorDepth(lgfx::color_depth_t::grayscale_8bit);
|
|
r = 1;
|
|
break;
|
|
|
|
case board_M5StackCoreInk:
|
|
case board_M5AirQ:
|
|
w = 200;
|
|
h = 200;
|
|
p->setColorDepth(lgfx::color_depth_t::grayscale_8bit);
|
|
break;
|
|
|
|
case board_M5StickC:
|
|
w = 80;
|
|
h = 160;
|
|
break;
|
|
|
|
case board_M5Station:
|
|
case board_M5Cardputer:
|
|
w = 240;
|
|
h = 135;
|
|
pnl_cfg.offset_rotation = 3;
|
|
r = 1;
|
|
break;
|
|
|
|
case board_M5StickCPlus:
|
|
case board_M5StickCPlus2:
|
|
case board_M5DinMeter:
|
|
case board_M5StampPLC:
|
|
w = 135;
|
|
h = 240;
|
|
break;
|
|
|
|
case board_M5StackCore2:
|
|
pnl_cfg.offset_rotation = 3;
|
|
r = 1;
|
|
break;
|
|
case board_M5Stack:
|
|
case board_M5StackCoreS3:
|
|
case board_M5StackCoreS3SE:
|
|
pnl_cfg.offset_rotation = 3;
|
|
r = 1;
|
|
break;
|
|
|
|
case board_M5Dial:
|
|
w = 240;
|
|
h = 240;
|
|
break;
|
|
|
|
case board_M5VAMeter:
|
|
w = 240;
|
|
h = 240;
|
|
break;
|
|
|
|
case board_M5Tab5:
|
|
w = 720;
|
|
h = 1280;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#if defined (M5GFX_SHORTCUT_MOD)
|
|
p->setShortcutKeymod(M5GFX_SHORTCUT_MOD);
|
|
#endif
|
|
|
|
#if defined (M5GFX_SHOW_FRAME)
|
|
auto pf = getPictureFrame(board);
|
|
if (pf) {
|
|
p->setFrameImage(pf->img, pf->w, pf->h, pf->x, pf->y);
|
|
}
|
|
#endif
|
|
|
|
pnl_cfg.memory_width = w;
|
|
pnl_cfg.panel_width = w;
|
|
pnl_cfg.memory_height = h;
|
|
pnl_cfg.panel_height = h;
|
|
pnl_cfg.bus_shared = false;
|
|
p->config(pnl_cfg);
|
|
p->setScaling(scale, scale);
|
|
|
|
#if defined (M5GFX_ROTATION)
|
|
p->setFrameRotation(M5GFX_ROTATION);
|
|
#endif
|
|
|
|
p->setRotation(r);
|
|
|
|
auto t = new lgfx::Touch_sdl();
|
|
_touch_last.reset(t);
|
|
{
|
|
auto cfg = t->config();
|
|
cfg.x_min = 0;
|
|
cfg.x_max = w - 1;
|
|
cfg.y_min = 0;
|
|
cfg.y_max = h - 1;
|
|
cfg.bus_shared = false;
|
|
t->config(cfg);
|
|
p->touch(t);
|
|
// float affine[6] = { 1, 0, 0, 0, 1, 0 };
|
|
// p->setCalibrateAffine(affine);
|
|
}
|
|
|
|
panel(_panel_last.get());
|
|
|
|
return board;
|
|
}
|
|
|
|
|
|
#endif /// end of if defined (ESP_PLATFORM)
|
|
|
|
void M5GFX::progressBar(int x, int y, int w, int h, uint8_t val)
|
|
{
|
|
drawRect(x, y, w, h, 0x09F1);
|
|
fillRect(x + 1, y + 1, w * (((float)val) / 100.0f), h - 1, 0x09F1);
|
|
}
|
|
|
|
void M5GFX::pushState(void)
|
|
{
|
|
DisplayState s;
|
|
s.gfxFont = _font;
|
|
s.style = _text_style;
|
|
s.metrics = _font_metrics;
|
|
s.cursor_x = _cursor_x;
|
|
s.cursor_y = _cursor_y;
|
|
_displayStateStack.push_back(s);
|
|
}
|
|
|
|
void M5GFX::popState(void)
|
|
{
|
|
if (_displayStateStack.empty()) return;
|
|
DisplayState s = _displayStateStack.back();
|
|
_displayStateStack.pop_back();
|
|
_font = s.gfxFont;
|
|
_text_style = s.style;
|
|
_font_metrics = s.metrics;
|
|
_cursor_x = s.cursor_x;
|
|
_cursor_y = s.cursor_y;
|
|
}
|
|
}
|