mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-28 05:36:37 +00:00
Add M5Stack.hpp
This commit is contained in:
parent
6f4bde6556
commit
66a7d1a394
270
src/drv/tft/M5Stack.hpp
Normal file
270
src/drv/tft/M5Stack.hpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/*----------------------------------------------------------------------------/
|
||||||
|
Lovyan GFX - Graphics library for embedded devices.
|
||||||
|
|
||||||
|
Original Source:
|
||||||
|
https://github.com/lovyan03/LovyanGFX/
|
||||||
|
|
||||||
|
Licence:
|
||||||
|
[FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt)
|
||||||
|
|
||||||
|
Author:
|
||||||
|
[lovyan03](https://twitter.com/lovyan03)
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
[ciniml](https://github.com/ciniml)
|
||||||
|
[mongonta0716](https://github.com/mongonta0716)
|
||||||
|
[tobozo](https://github.com/tobozo)
|
||||||
|
/----------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(ARDUINO) && defined(LGFX_USE_V1)
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LovyanGFX.hpp"
|
||||||
|
#include <driver/i2c.h>
|
||||||
|
|
||||||
|
namespace dev {
|
||||||
|
|
||||||
|
namespace m5stack {
|
||||||
|
static constexpr int32_t axp_i2c_freq = 400000;
|
||||||
|
static constexpr uint_fast8_t axp_i2c_addr = 0x34;
|
||||||
|
static constexpr int_fast16_t axp_i2c_port = I2C_NUM_1;
|
||||||
|
static constexpr int_fast16_t axp_i2c_sda = 21;
|
||||||
|
static constexpr int_fast16_t axp_i2c_scl = 22;
|
||||||
|
} // namespace m5stack
|
||||||
|
|
||||||
|
struct Panel_M5Stack : public lgfx::Panel_ILI9342
|
||||||
|
{
|
||||||
|
Panel_M5Stack(void)
|
||||||
|
{
|
||||||
|
_cfg.pin_cs = 14;
|
||||||
|
_cfg.pin_rst = 33;
|
||||||
|
_cfg.offset_rotation = 3;
|
||||||
|
|
||||||
|
_rotation = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool init(bool use_reset) override
|
||||||
|
{
|
||||||
|
lgfx::gpio_hi(_cfg.pin_rst);
|
||||||
|
lgfx::pinMode(_cfg.pin_rst, lgfx::pin_mode_t::input_pulldown);
|
||||||
|
_cfg.invert = lgfx::gpio_in(_cfg.pin_rst); // get panel type (IPS or TN)
|
||||||
|
lgfx::pinMode(_cfg.pin_rst, lgfx::pin_mode_t::output);
|
||||||
|
|
||||||
|
return lgfx::Panel_ILI9342::init(use_reset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Panel_M5StackCore2 : public lgfx::Panel_ILI9342
|
||||||
|
{
|
||||||
|
Panel_M5StackCore2(void)
|
||||||
|
{
|
||||||
|
_cfg.pin_cs = 5;
|
||||||
|
_cfg.invert = true;
|
||||||
|
_cfg.offset_rotation = 3;
|
||||||
|
|
||||||
|
_rotation = 1; // default rotation
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(void) override
|
||||||
|
{
|
||||||
|
using namespace m5stack;
|
||||||
|
// AXP192 reg 0x96 = GPIO3&4 control
|
||||||
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x96, 0, ~0x02, axp_i2c_freq); // GPIO4 LOW (LCD RST)
|
||||||
|
lgfx::delay(4);
|
||||||
|
lgfx::i2c::writeRegister8(axp_i2c_port, axp_i2c_addr, 0x96, 2, ~0x00, axp_i2c_freq); // GPIO4 HIGH (LCD RST)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Light_M5StackCore2 : public lgfx::ILight
|
||||||
|
{
|
||||||
|
bool init(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
setBrightness(brightness);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBrightness(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
using namespace m5stack;
|
||||||
|
|
||||||
|
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_M5Tough : public lgfx::ILight
|
||||||
|
{
|
||||||
|
bool init(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
setBrightness(brightness);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBrightness(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
using namespace m5stack;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Touch_M5Tough(void)
|
||||||
|
{
|
||||||
|
_cfg.x_min = 0;
|
||||||
|
_cfg.x_max = 319;
|
||||||
|
_cfg.y_min = 0;
|
||||||
|
_cfg.y_max = 239;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::v1::pin_mode_t::input_pullup);
|
||||||
|
}
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint_fast8_t getTouchRaw(lgfx::v1::touch_point_t* __restrict tp, 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(lgfx::v1::gpio_in(_cfg.pin_int)) Serial.print("#");
|
||||||
|
if(lgfx::v1::gpio_in(_cfg.pin_int)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = 3 + count * 6;
|
||||||
|
uint8_t buf[2][len];
|
||||||
|
int32_t retry = 5;
|
||||||
|
bool flip = false;
|
||||||
|
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 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;
|
||||||
|
size_t points = std::min<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(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 = 5;
|
||||||
|
_cfg.pin_rst = 18;
|
||||||
|
_cfg.panel_width = 80;
|
||||||
|
_cfg.panel_height = 160;
|
||||||
|
_cfg.offset_x = 26;
|
||||||
|
_cfg.offset_y = 1;
|
||||||
|
_cfg.offset_rotation = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const uint8_t* getInitCommands(uint8_t listno) const override
|
||||||
|
{
|
||||||
|
static constexpr 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(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
using namespace m5stack;
|
||||||
|
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(uint8_t brightness) override
|
||||||
|
{
|
||||||
|
using namespace m5stack;
|
||||||
|
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 = 5;
|
||||||
|
_cfg.pin_rst = 18;
|
||||||
|
_cfg.panel_width = 135;
|
||||||
|
_cfg.panel_height = 240;
|
||||||
|
_cfg.offset_x = 52;
|
||||||
|
_cfg.offset_y = 40;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dev
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user