full implementation
This commit is contained in:
557
AXS15231B.cpp
Normal file
557
AXS15231B.cpp
Normal file
@@ -0,0 +1,557 @@
|
|||||||
|
#include "AXS15231B.h"
|
||||||
|
#include "SPI.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
|
||||||
|
static volatile bool lcd_spi_dma_write = false;
|
||||||
|
extern void my_print(const char *buf);
|
||||||
|
uint32_t transfer_num = 0;
|
||||||
|
size_t lcd_PushColors_len = 0;
|
||||||
|
|
||||||
|
const static lcd_cmd_t axs15231b_qspi_init[] = {
|
||||||
|
{0x28, {0x00}, 0x40},
|
||||||
|
{0x10, {0x00}, 0x20},
|
||||||
|
{0x11, {0x00}, 0x80},
|
||||||
|
{0x29, {0x00}, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
const static lcd_cmd_t axs15231b_qspi_init_new[] = {
|
||||||
|
{0x28, {0x00}, 0x40},
|
||||||
|
{0x10, {0x00}, 0x80},
|
||||||
|
{0xbb, {0x00,0x00,0x00,0x00,0x00,0x00,0x5a,0xa5}, 0x08},
|
||||||
|
{0xa0, {0x00,0x30,0x00,0x02,0x00,0x00,0x05,0x3f,0x30,0x05,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00}, 0x11},
|
||||||
|
{0xa2, {0x30,0x04,0x14,0x50,0x80,0x30,0x85,0x80,0xb4,0x28,0xff,0xff,0xff,0x20,0x50,0x10,0x02,0x06,0x20,0xd0,0xc0,0x01,0x12,0xa0,0x91,0xc0,0x20,0x7f,0xff,0x00,0x06}, 0x1F},
|
||||||
|
{0xd0, {0x80,0xb4,0x21,0x24,0x08,0x05,0x10,0x01,0xf2,0x02,0xc2,0x02,0x22,0x22,0xaa,0x03,0x10,0x12,0xc0,0x10,0x10,0x40,0x04,0x00,0x30,0x10,0x00,0x03,0x0d,0x12}, 0x1E},
|
||||||
|
{0xa3, {0xa0,0x06,0xaa,0x00,0x08,0x02,0x0a,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x55,0x55}, 0x16},
|
||||||
|
{0xc1, {0x33,0x04,0x02,0x02,0x71,0x05,0x24,0x55,0x02,0x00,0x01,0x01,0x53,0xff,0xff,0xff,0x4f,0x52,0x00,0x4f,0x52,0x00,0x45,0x3b,0x0b,0x04,0x0d,0x00,0xff,0x42}, 0x1E},
|
||||||
|
{0xc4, {0x00,0x24,0x33,0x80,0x66,0xea,0x64,0x32,0xc8,0x64,0xc8,0x32,0x90,0x90,0x11,0x06,0xdc,0xfa,0x00,0x00,0x80,0xfe,0x10,0x10,0x00,0x0a,0x0a,0x44,0x50}, 0x1D},
|
||||||
|
{0xc5, {0x18,0x00,0x00,0x03,0xfe,0xe8,0x3b,0x20,0x30,0x10,0x88,0xde,0x0d,0x08,0x0f,0x0f,0x01,0xe8,0x3b,0x20,0x10,0x10,0x00}, 0x17},
|
||||||
|
{0xc6, {0x05,0x0a,0x05,0x0a,0x00,0xe0,0x2e,0x0b,0x12,0x22,0x12,0x22,0x01,0x03,0x00,0x02,0x6a,0x18,0xc8,0x22}, 0x14},
|
||||||
|
{0xc7, {0x50,0x36,0x28,0x00,0xa2,0x80,0x8f,0x00,0x80,0xff,0x07,0x11,0x9c,0x6f,0xff,0x24,0x0c,0x0d,0x0e,0x0f,0x01,0x01,0x01,0x01,0x3f,0x07,0x00}, 0x1B},
|
||||||
|
{0xc9, {0x33,0x44,0x44,0x01}, 0x04},
|
||||||
|
{0xcf, {0x2c,0x1e,0x88,0x58,0x13,0x18,0x56,0x18,0x1e,0x68,0xf7,0x00,0x66,0x0d,0x22,0xc4,0x0c,0x77,0x22,0x44,0xaa,0x55,0x04,0x04,0x12,0xa0,0x08}, 0x1B},
|
||||||
|
{0xd5, {0x30,0x30,0x8a,0x00,0x44,0x04,0x4a,0xe5,0x02,0x4a,0xe5,0x02,0x04,0xd9,0x02,0x47,0x03,0x03,0x03,0x03,0x83,0x00,0x00,0x00,0x80,0x52,0x53,0x50,0x50,0x00}, 0x1E},
|
||||||
|
{0xd6, {0x10,0x32,0x54,0x76,0x98,0xba,0xdc,0xfe,0x34,0x02,0x01,0x83,0xff,0x00,0x20,0x50,0x00,0x30,0x03,0x03,0x50,0x13,0x00,0x00,0x00,0x04,0x50,0x20,0x01,0x00}, 0x1E},
|
||||||
|
{0xd7, {0x03,0x01,0x09,0x0b,0x0d,0x0f,0x1e,0x1f,0x18,0x1d,0x1f,0x19,0x30,0x30,0x04,0x00,0x20,0x20,0x1f}, 0x13},
|
||||||
|
{0xd8, {0x02,0x00,0x08,0x0a,0x0c,0x0e,0x1e,0x1f,0x18,0x1d,0x1f,0x19}, 0x0C},
|
||||||
|
{0xdf, {0x44,0x33,0x4b,0x69,0x00,0x0a,0x02,0x90}, 0x06},
|
||||||
|
{0xe0, {0x1f,0x20,0x10,0x17,0x0d,0x09,0x12,0x2a,0x44,0x25,0x0c,0x15,0x13,0x31,0x36,0x2f,0x02}, 0x11},
|
||||||
|
{0xe1, {0x3f,0x20,0x10,0x16,0x0c,0x08,0x12,0x29,0x43,0x25,0x0c,0x15,0x13,0x32,0x36,0x2f,0x27}, 0x11},
|
||||||
|
{0xe2, {0x3b,0x07,0x12,0x18,0x0e,0x0d,0x17,0x35,0x44,0x32,0x0c,0x14,0x14,0x36,0x3a,0x2f,0x0d}, 0x11},
|
||||||
|
{0xe3, {0x37,0x07,0x12,0x18,0x0e,0x0d,0x17,0x35,0x44,0x32,0x0c,0x14,0x14,0x36,0x32,0x2f,0x0f}, 0x11},
|
||||||
|
{0xe4, {0x3b,0x07,0x12,0x18,0x0e,0x0d,0x17,0x39,0x44,0x2e,0x0c,0x14,0x14,0x36,0x3a,0x2f,0x0d}, 0x11},
|
||||||
|
{0xe5, {0x37,0x07,0x12,0x18,0x0e,0x0d,0x17,0x39,0x44,0x2e,0x0c,0x14,0x14,0x36,0x3a,0x2f,0x0f}, 0x11},
|
||||||
|
{0xbb, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 0x06},
|
||||||
|
{0x28, {0x00}, 0x40},
|
||||||
|
{0x10, {0x00}, 0x80},
|
||||||
|
{0x11, {0x00}, 0x80},
|
||||||
|
{0x29, {0x00}, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool get_lcd_spi_dma_write(void)
|
||||||
|
{
|
||||||
|
return lcd_spi_dma_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
static spi_device_handle_t spi;
|
||||||
|
|
||||||
|
static void WriteComm(uint8_t data)
|
||||||
|
{
|
||||||
|
TFT_CS_L;
|
||||||
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
|
||||||
|
SPI.write(0x00);
|
||||||
|
SPI.write(data);
|
||||||
|
SPI.write(0x00);
|
||||||
|
SPI.endTransaction();
|
||||||
|
TFT_CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteData(uint8_t data)
|
||||||
|
{
|
||||||
|
TFT_CS_L;
|
||||||
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
|
||||||
|
SPI.write(data);
|
||||||
|
SPI.endTransaction();
|
||||||
|
TFT_CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcd_send_cmd(uint32_t cmd, uint8_t *dat, uint32_t len)
|
||||||
|
{
|
||||||
|
#if LCD_USB_QSPI_DREVER == 1
|
||||||
|
TFT_CS_L;
|
||||||
|
spi_transaction_t t;
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
t.flags = (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR);
|
||||||
|
#ifdef LCD_SPI_DMA
|
||||||
|
if(cmd == 0xff && len == 0x1f)
|
||||||
|
{
|
||||||
|
t.cmd = 0x02;
|
||||||
|
t.addr = 0xffff;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
else if(cmd == 0x00)
|
||||||
|
{
|
||||||
|
t.cmd = 0X00;
|
||||||
|
t.addr = 0X0000;
|
||||||
|
len = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t.cmd = 0x02;
|
||||||
|
t.addr = cmd << 8;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
t.cmd = 0x02;
|
||||||
|
t.addr = cmd << 8;
|
||||||
|
#endif
|
||||||
|
if (len != 0) {
|
||||||
|
t.tx_buffer = dat;
|
||||||
|
t.length = 8 * len;
|
||||||
|
} else {
|
||||||
|
t.tx_buffer = NULL;
|
||||||
|
t.length = 0;
|
||||||
|
}
|
||||||
|
spi_device_polling_transmit(spi, &t);
|
||||||
|
TFT_CS_H;
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
WriteComm(cmd);
|
||||||
|
if (len != 0) {
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
WriteData(dat[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
WriteComm(cmd);
|
||||||
|
if (len != 0) {
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
WriteData(dat[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IRAM_ATTR spi_dma_cd(spi_transaction_t *trans)
|
||||||
|
{
|
||||||
|
if(transfer_num > 0)
|
||||||
|
{
|
||||||
|
transfer_num--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lcd_PushColors_len <= 0 && transfer_num <= 0)
|
||||||
|
{
|
||||||
|
if(lcd_spi_dma_write) {
|
||||||
|
lcd_spi_dma_write = false;
|
||||||
|
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||||
|
if(disp != NULL)
|
||||||
|
lv_disp_flush_ready(disp->driver);
|
||||||
|
|
||||||
|
TFT_CS_H;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lcd_send_data8(uint8_t dat) {
|
||||||
|
unsigned char i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (dat & 0x80) {
|
||||||
|
digitalWrite(TFT_QSPI_D0, 1);
|
||||||
|
} else {
|
||||||
|
digitalWrite(TFT_QSPI_D0, 0);
|
||||||
|
}
|
||||||
|
dat <<= 1;
|
||||||
|
digitalWrite(TFT_QSPI_SCK, 0);
|
||||||
|
digitalWrite(TFT_QSPI_SCK, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void axs15231_init(void)
|
||||||
|
{
|
||||||
|
pinMode(TFT_QSPI_CS, OUTPUT);
|
||||||
|
pinMode(TFT_QSPI_RST, OUTPUT);
|
||||||
|
|
||||||
|
TFT_RES_H;
|
||||||
|
delay(130);
|
||||||
|
TFT_RES_L;
|
||||||
|
delay(130);
|
||||||
|
TFT_RES_H;
|
||||||
|
delay(300);
|
||||||
|
|
||||||
|
#if LCD_USB_QSPI_DREVER == 1
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
spi_bus_config_t buscfg = {
|
||||||
|
.data0_io_num = TFT_QSPI_D0,
|
||||||
|
.data1_io_num = TFT_QSPI_D1,
|
||||||
|
.sclk_io_num = TFT_QSPI_SCK,
|
||||||
|
.data2_io_num = TFT_QSPI_D2,
|
||||||
|
.data3_io_num = TFT_QSPI_D3,
|
||||||
|
.max_transfer_sz = (SEND_BUF_SIZE * 16) + 8,
|
||||||
|
.flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS /* |
|
||||||
|
SPICOMMON_BUSFLAG_QUAD */
|
||||||
|
,
|
||||||
|
};
|
||||||
|
spi_device_interface_config_t devcfg = {
|
||||||
|
.command_bits = 8,
|
||||||
|
.address_bits = 24,
|
||||||
|
.mode = TFT_SPI_MODE,
|
||||||
|
.clock_speed_hz = SPI_FREQUENCY,
|
||||||
|
.spics_io_num = -1,
|
||||||
|
// .spics_io_num = TFT_QSPI_CS,
|
||||||
|
.flags = SPI_DEVICE_HALFDUPLEX,
|
||||||
|
.queue_size = 17,
|
||||||
|
.post_cb = spi_dma_cd,
|
||||||
|
};
|
||||||
|
ret = spi_bus_initialize(TFT_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
ret = spi_bus_add_device(TFT_SPI_HOST, &devcfg, &spi);
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
#else
|
||||||
|
SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);
|
||||||
|
SPI.setFrequency(SPI_FREQUENCY);
|
||||||
|
pinMode(TFT_DC, OUTPUT);
|
||||||
|
#endif
|
||||||
|
// Initialize the screen multiple times to prevent initialization failure
|
||||||
|
int i = 1;
|
||||||
|
while (i--) {
|
||||||
|
#if LCD_USB_QSPI_DREVER == 1
|
||||||
|
const lcd_cmd_t *lcd_init = axs15231b_qspi_init;
|
||||||
|
for (int i = 0; i < sizeof(axs15231b_qspi_init) / sizeof(lcd_cmd_t); i++)
|
||||||
|
#else
|
||||||
|
const lcd_cmd_t *lcd_init = axs15231_spi_init;
|
||||||
|
for (int i = 0; i < sizeof(axs15231_spi_init) / sizeof(lcd_cmd_t); i++)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
lcd_send_cmd(lcd_init[i].cmd,
|
||||||
|
(uint8_t *)lcd_init[i].data,
|
||||||
|
lcd_init[i].len & 0x3f);
|
||||||
|
|
||||||
|
if (lcd_init[i].len & 0x80)
|
||||||
|
delay(200);
|
||||||
|
if (lcd_init[i].len & 0x40)
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_setRotation(uint8_t r)
|
||||||
|
{
|
||||||
|
uint8_t gbr = TFT_MAD_RGB;
|
||||||
|
|
||||||
|
switch (r) {
|
||||||
|
case 0: // Portrait
|
||||||
|
// WriteData(gbr);
|
||||||
|
break;
|
||||||
|
case 1: // Landscape (Portrait + 90)
|
||||||
|
gbr = TFT_MAD_MX | TFT_MAD_MV | gbr;
|
||||||
|
break;
|
||||||
|
case 2: // Inverter portrait
|
||||||
|
gbr = TFT_MAD_MX | TFT_MAD_MY | gbr;
|
||||||
|
break;
|
||||||
|
case 3: // Inverted landscape
|
||||||
|
gbr = TFT_MAD_MV | TFT_MAD_MY | gbr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lcd_send_cmd(TFT_MADCTL, &gbr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_address_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
|
||||||
|
{
|
||||||
|
lcd_cmd_t t[3] = {
|
||||||
|
{0x2a, {(uint8_t)(x1 >> 8), (uint8_t)x1, uint8_t(x2 >> 8), (uint8_t)(x2)}, 0x04},
|
||||||
|
{0x2b, {(uint8_t)(y1 >> 8), (uint8_t)(y1), (uint8_t)(y2 >> 8), (uint8_t)(y2)}, 0x04},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
lcd_send_cmd(t[i].cmd, t[i].data, t[i].len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_fill(uint16_t xsta,
|
||||||
|
uint16_t ysta,
|
||||||
|
uint16_t xend,
|
||||||
|
uint16_t yend,
|
||||||
|
uint16_t color)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint16_t w = xend - xsta;
|
||||||
|
uint16_t h = yend - ysta;
|
||||||
|
uint16_t *color_p = (uint16_t *)heap_caps_malloc(w * h * 2, MALLOC_CAP_INTERNAL);
|
||||||
|
int i = 0;
|
||||||
|
for(i = 0; i < w * h ; i+=1)
|
||||||
|
{
|
||||||
|
color_p[i] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd_PushColors(xsta, ysta, w, h, color_p);
|
||||||
|
free(color_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
|
||||||
|
{
|
||||||
|
lcd_address_set(x, y, x + 1, y + 1);
|
||||||
|
lcd_PushColors(&color, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_device_queue_trans_fun(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(spi_device_queue_trans(spi, (spi_transaction_t *)trans_desc, portMAX_DELAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LCD_SPI_DMA
|
||||||
|
spi_transaction_ext_t t = {0};
|
||||||
|
void lcd_PushColors(uint16_t x,
|
||||||
|
uint16_t y,
|
||||||
|
uint16_t width,
|
||||||
|
uint16_t high,
|
||||||
|
uint16_t *data)
|
||||||
|
{
|
||||||
|
static bool first_send = 1;
|
||||||
|
static uint16_t *p = (uint16_t *)data;
|
||||||
|
static uint32_t transfer_num_old = 0;
|
||||||
|
|
||||||
|
if(data != NULL && (width != 0) && (high != 0))
|
||||||
|
{
|
||||||
|
lcd_PushColors_len = width * high;
|
||||||
|
p = (uint16_t *)data;
|
||||||
|
first_send = 1;
|
||||||
|
|
||||||
|
transfer_num = 0;
|
||||||
|
lcd_address_set(x, y, x + width - 1, y + high - 1);
|
||||||
|
TFT_CS_L;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0; x < (transfer_num_old - (transfer_num_old-(transfer_num_old-transfer_num))); x++) {
|
||||||
|
spi_transaction_t *rtrans;
|
||||||
|
esp_err_t ret = spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
// ESP_LOGW(TAG, "1. transfer_num = %d", transfer_num_old);
|
||||||
|
}
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
}
|
||||||
|
transfer_num_old -= (transfer_num_old - (transfer_num_old-(transfer_num_old-transfer_num)));
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(transfer_num >= 3 || ESP.getFreeHeap() <= 70000)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_t chunk_size = lcd_PushColors_len;
|
||||||
|
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
if (first_send) {
|
||||||
|
t.base.flags =
|
||||||
|
SPI_TRANS_MODE_QIO ;// | SPI_TRANS_MODE_DIOQIO_ADDR
|
||||||
|
t.base.cmd = 0x32 ;// 0x12
|
||||||
|
t.base.addr = 0x002C00;
|
||||||
|
first_send = 0;
|
||||||
|
} else {
|
||||||
|
t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||||
|
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||||
|
t.command_bits = 0;
|
||||||
|
t.address_bits = 0;
|
||||||
|
t.dummy_bits = 0;
|
||||||
|
}
|
||||||
|
if (chunk_size > SEND_BUF_SIZE) {
|
||||||
|
chunk_size = SEND_BUF_SIZE;
|
||||||
|
}
|
||||||
|
t.base.tx_buffer = p;
|
||||||
|
t.base.length = chunk_size * 16;
|
||||||
|
|
||||||
|
lcd_spi_dma_write = true;
|
||||||
|
|
||||||
|
transfer_num++;
|
||||||
|
transfer_num_old++;
|
||||||
|
lcd_PushColors_len -= chunk_size;
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(spi_device_queue_trans(spi, (spi_transaction_t *)&t, portMAX_DELAY));
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
|
p += chunk_size;
|
||||||
|
} while (lcd_PushColors_len > 0);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
void lcd_PushColors(uint16_t x,
|
||||||
|
uint16_t y,
|
||||||
|
uint16_t width,
|
||||||
|
uint16_t high,
|
||||||
|
uint16_t *data)
|
||||||
|
{
|
||||||
|
bool first_send = 1;
|
||||||
|
lcd_PushColors_len = width * high;
|
||||||
|
uint16_t *p = (uint16_t *)data;
|
||||||
|
|
||||||
|
spi_transaction_t *rtrans;
|
||||||
|
|
||||||
|
for (int x = 0; x < transfer_num; x++) {
|
||||||
|
esp_err_t ret = spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "1. transfer_num = %d", transfer_num);
|
||||||
|
}
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
}
|
||||||
|
transfer_num = 0;
|
||||||
|
|
||||||
|
lcd_address_set(x, y, x + width - 1, y + high - 1);
|
||||||
|
TFT_CS_L;
|
||||||
|
do {
|
||||||
|
size_t chunk_size = lcd_PushColors_len;
|
||||||
|
spi_transaction_ext_t t = {0};
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
if (first_send) {
|
||||||
|
t.base.flags =
|
||||||
|
SPI_TRANS_MODE_QIO /* | SPI_TRANS_MODE_DIOQIO_ADDR */;
|
||||||
|
t.base.cmd = 0x32 /* 0x12 */;
|
||||||
|
t.base.addr = 0x002C00;
|
||||||
|
first_send = 0;
|
||||||
|
} else {
|
||||||
|
t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||||
|
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||||
|
t.command_bits = 0;
|
||||||
|
t.address_bits = 0;
|
||||||
|
t.dummy_bits = 0;
|
||||||
|
}
|
||||||
|
if (chunk_size > SEND_BUF_SIZE) {
|
||||||
|
chunk_size = SEND_BUF_SIZE;
|
||||||
|
}
|
||||||
|
t.base.tx_buffer = p;
|
||||||
|
t.base.length = chunk_size * 16;
|
||||||
|
|
||||||
|
lcd_spi_dma_write = true;
|
||||||
|
|
||||||
|
transfer_num++;
|
||||||
|
lcd_PushColors_len -= chunk_size;
|
||||||
|
|
||||||
|
spi_device_queue_trans_fun(spi, (spi_transaction_t *)&t, portMAX_DELAY);
|
||||||
|
|
||||||
|
p += chunk_size;
|
||||||
|
} while (lcd_PushColors_len > 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
void lcd_PushColors(uint16_t x,
|
||||||
|
uint16_t y,
|
||||||
|
uint16_t width,
|
||||||
|
uint16_t high,
|
||||||
|
uint16_t *data)
|
||||||
|
{
|
||||||
|
#if LCD_USB_QSPI_DREVER == 1
|
||||||
|
bool first_send = 1;
|
||||||
|
size_t len = width * high;
|
||||||
|
uint16_t *p = (uint16_t *)data;
|
||||||
|
|
||||||
|
lcd_address_set(x, y, x + width - 1, y + high - 1);
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
TFT_CS_L;
|
||||||
|
size_t chunk_size = len;
|
||||||
|
spi_transaction_ext_t t = {0};
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
if (1) {
|
||||||
|
t.base.flags =
|
||||||
|
SPI_TRANS_MODE_QIO /* | SPI_TRANS_MODE_DIOQIO_ADDR */;
|
||||||
|
t.base.cmd = 0x32 /* 0x12 */;
|
||||||
|
if(first_send)
|
||||||
|
{
|
||||||
|
t.base.addr = 0x002C00;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t.base.addr = 0x003C00;
|
||||||
|
first_send = 0;
|
||||||
|
} else {
|
||||||
|
t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||||
|
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||||
|
t.command_bits = 0;
|
||||||
|
t.address_bits = 0;
|
||||||
|
t.dummy_bits = 0;
|
||||||
|
}
|
||||||
|
if (chunk_size > SEND_BUF_SIZE) {
|
||||||
|
chunk_size = SEND_BUF_SIZE;
|
||||||
|
}
|
||||||
|
t.base.tx_buffer = p;
|
||||||
|
t.base.length = chunk_size * 16;
|
||||||
|
int aaa = 0;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
if(!first_send)
|
||||||
|
TFT_CS_H;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
TFT_CS_L;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
aaa = aaa>>1;
|
||||||
|
spi_device_polling_transmit(spi, (spi_transaction_t *)&t);
|
||||||
|
len -= chunk_size;
|
||||||
|
p += chunk_size;
|
||||||
|
} while (len > 0);
|
||||||
|
TFT_CS_H;
|
||||||
|
|
||||||
|
#else
|
||||||
|
lcd_address_set(x, y, x + width - 1, y + high - 1);
|
||||||
|
TFT_CS_L;
|
||||||
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
|
||||||
|
|
||||||
|
SPI.writeBytes((uint8_t *)data, width * high * 2);
|
||||||
|
SPI.endTransaction();
|
||||||
|
TFT_CS_H;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void lcd_PushColors(uint16_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
#if LCD_USB_QSPI_DREVER == 1
|
||||||
|
bool first_send = 1;
|
||||||
|
uint16_t *p = (uint16_t *)data;
|
||||||
|
TFT_CS_L;
|
||||||
|
do {
|
||||||
|
size_t chunk_size = len;
|
||||||
|
spi_transaction_ext_t t = {0};
|
||||||
|
memset(&t, 0, sizeof(t));
|
||||||
|
if (first_send) {
|
||||||
|
t.base.flags =
|
||||||
|
SPI_TRANS_MODE_QIO /* | SPI_TRANS_MODE_DIOQIO_ADDR */;
|
||||||
|
t.base.cmd = 0x32 /* 0x12 */;
|
||||||
|
t.base.addr = 0x002C00;
|
||||||
|
first_send = 0;
|
||||||
|
} else {
|
||||||
|
t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||||
|
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||||
|
t.command_bits = 0;
|
||||||
|
t.address_bits = 0;
|
||||||
|
t.dummy_bits = 0;
|
||||||
|
}
|
||||||
|
if (chunk_size > SEND_BUF_SIZE) {
|
||||||
|
chunk_size = SEND_BUF_SIZE;
|
||||||
|
}
|
||||||
|
t.base.tx_buffer = p;
|
||||||
|
t.base.length = chunk_size * 16;
|
||||||
|
|
||||||
|
spi_device_polling_transmit(spi, (spi_transaction_t *)&t);
|
||||||
|
len -= chunk_size;
|
||||||
|
p += chunk_size;
|
||||||
|
} while (len > 0);
|
||||||
|
TFT_CS_H;
|
||||||
|
|
||||||
|
#else
|
||||||
|
TFT_CS_L;
|
||||||
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
|
||||||
|
|
||||||
|
SPI.writeBytes((uint8_t *)data, len * 2);
|
||||||
|
SPI.endTransaction();
|
||||||
|
TFT_CS_H;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_sleep()
|
||||||
|
{
|
||||||
|
lcd_send_cmd(0x10, NULL, 0);
|
||||||
|
}
|
||||||
60
AXS15231B.h
Normal file
60
AXS15231B.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "pins_config.h"
|
||||||
|
#include "lvgl.h"/* https://github.com/lvgl/lvgl.git */
|
||||||
|
|
||||||
|
#define LCD_SPI_DMA
|
||||||
|
#define AX15231B
|
||||||
|
|
||||||
|
#define TFT_MADCTL 0x36
|
||||||
|
#define TFT_MAD_MY 0x80
|
||||||
|
#define TFT_MAD_MX 0x40
|
||||||
|
#define TFT_MAD_MV 0x20
|
||||||
|
#define TFT_MAD_ML 0x10
|
||||||
|
#define TFT_MAD_BGR 0x08
|
||||||
|
#define TFT_MAD_MH 0x04
|
||||||
|
#define TFT_MAD_RGB 0x00
|
||||||
|
|
||||||
|
#define TFT_INVOFF 0x20
|
||||||
|
#define TFT_INVON 0x21
|
||||||
|
|
||||||
|
#define TFT_SCK_H digitalWrite(TFT_SCK, 1);
|
||||||
|
#define TFT_SCK_L digitalWrite(TFT_SCK, 0);
|
||||||
|
#define TFT_SDA_H digitalWrite(TFT_MOSI, 1);
|
||||||
|
#define TFT_SDA_L digitalWrite(TFT_MOSI, 0);
|
||||||
|
|
||||||
|
#define TFT_RES_H digitalWrite(TFT_QSPI_RST, 1);
|
||||||
|
#define TFT_RES_L digitalWrite(TFT_QSPI_RST, 0);
|
||||||
|
#define TFT_DC_H digitalWrite(TFT_DC, 1);
|
||||||
|
#define TFT_DC_L digitalWrite(TFT_DC, 0);
|
||||||
|
#define TFT_CS_H digitalWrite(TFT_QSPI_CS, 1);
|
||||||
|
#define TFT_CS_L digitalWrite(TFT_QSPI_CS, 0);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t data[36];
|
||||||
|
uint8_t len;
|
||||||
|
} lcd_cmd_t;
|
||||||
|
|
||||||
|
void axs15231_init(void);
|
||||||
|
|
||||||
|
// Set the display window size
|
||||||
|
void lcd_address_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
|
||||||
|
void lcd_setRotation(uint8_t r);
|
||||||
|
void lcd_DrawPoint(uint16_t x, uint16_t y, uint16_t color);
|
||||||
|
void lcd_fill(uint16_t xsta,
|
||||||
|
uint16_t ysta,
|
||||||
|
uint16_t xend,
|
||||||
|
uint16_t yend,
|
||||||
|
uint16_t color);
|
||||||
|
void lcd_PushColors(uint16_t x,
|
||||||
|
uint16_t y,
|
||||||
|
uint16_t width,
|
||||||
|
uint16_t high,
|
||||||
|
uint16_t *data);
|
||||||
|
void lcd_PushColors(uint16_t *data, uint32_t len);
|
||||||
|
void lcd_sleep();
|
||||||
|
|
||||||
|
bool get_lcd_spi_dma_write(void);
|
||||||
309
lilygo-sensor-clock.ino
Normal file
309
lilygo-sensor-clock.ino
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
#include "lvgl.h"
|
||||||
|
#include "pins_config.h"
|
||||||
|
#include "AXS15231B.h"
|
||||||
|
#include "ui-util.h"
|
||||||
|
#include "WiFi.h"
|
||||||
|
#include "sntp.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <XPowersLib.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
// Serial
|
||||||
|
#define BAUD 115200
|
||||||
|
|
||||||
|
// Sensor pins
|
||||||
|
#define RX2_PIN TOUCH_IICSCL
|
||||||
|
#define TX2_PIN TOUCH_IICSDA
|
||||||
|
|
||||||
|
// Sensor configuration
|
||||||
|
#define COMMAND "FDFCFBFA0800120000006400000004030201" //Normal mode command, see documentation waveshare sensor
|
||||||
|
#define PRESENCE_DISTANCE 200 // in cm
|
||||||
|
#define DELAY_STATUS_CHECK 1000 // delay (in ms) between two checks of the presence
|
||||||
|
#define SLEEP_DELAY 10000 // delay (in ms) until sleep mode
|
||||||
|
#define POWER_DELAY 30000 // delay (in ms) until turning off the screen
|
||||||
|
|
||||||
|
SemaphoreHandle_t xSemaphore = NULL;
|
||||||
|
PowersSY6970 PMU;
|
||||||
|
|
||||||
|
// Sensor variables
|
||||||
|
uint16_t state = 1; // 0 = presence detected, 1 = no presence detected for the past SLEEP_DELAY ms, 2 = no presence detected for the past POWER_DELAY ms
|
||||||
|
unsigned long lastMotionCheckTime = millis();
|
||||||
|
unsigned long lastMotionDetected = 0;
|
||||||
|
|
||||||
|
// Time variables
|
||||||
|
static uint32_t last_tick;
|
||||||
|
struct tm timeinfo;
|
||||||
|
uint32_t cycleInterval = 0;
|
||||||
|
|
||||||
|
// Display variables
|
||||||
|
static lv_disp_draw_buf_t draw_buf;
|
||||||
|
static lv_color_t *buf;
|
||||||
|
static lv_color_t *buf1;
|
||||||
|
|
||||||
|
// REST API Home assistant request
|
||||||
|
static String BASE_URL_HA = "http://192.168.1.2:8123/api/services";
|
||||||
|
static String HA_TOKEN = "abc";
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive(xSemaphore);
|
||||||
|
|
||||||
|
initSerial();
|
||||||
|
initializeWifi();
|
||||||
|
initializeTime();
|
||||||
|
sendCommandAsHex(COMMAND);
|
||||||
|
initializeUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
delay(1);
|
||||||
|
if (transfer_num <= 0 && lcd_PushColors_len <= 0)
|
||||||
|
lv_timer_handler();
|
||||||
|
|
||||||
|
if (transfer_num <= 1 && lcd_PushColors_len > 0) {
|
||||||
|
lcd_PushColors(0, 0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flag_bl = 0;
|
||||||
|
static unsigned long cnt = 0;
|
||||||
|
|
||||||
|
printLocalTime();
|
||||||
|
readAndProcessSensorLines();
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
if (cnt >= 100) {
|
||||||
|
if (flag_bl == 0) {
|
||||||
|
pinMode(TFT_BL, OUTPUT);
|
||||||
|
digitalWrite(TFT_BL, HIGH);
|
||||||
|
flag_bl = 1;
|
||||||
|
lv_delay_ms(500);
|
||||||
|
ui_begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initSerial() {
|
||||||
|
// Start the primary serial communication (USB Monitor)
|
||||||
|
Serial.begin(BAUD);
|
||||||
|
unsigned long startAttemptTime = millis();
|
||||||
|
while (!Serial && millis() - startAttemptTime < 2000) {
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
Serial.println("Serial Monitor Initialized.");
|
||||||
|
|
||||||
|
pinMode(PIN_BAT_VOLT, ANALOG);
|
||||||
|
|
||||||
|
// Screen
|
||||||
|
pinMode(TOUCH_RES, OUTPUT);
|
||||||
|
digitalWrite(TOUCH_RES, HIGH);
|
||||||
|
delay(2);
|
||||||
|
digitalWrite(TOUCH_RES, LOW);
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(TOUCH_RES, HIGH);
|
||||||
|
delay(2);
|
||||||
|
|
||||||
|
// Start Serial2 for the HMMD Sensor
|
||||||
|
Serial2.begin(BAUD, SERIAL_8N1, RX2_PIN, TX2_PIN);
|
||||||
|
Serial.println("Serial2 Initialized on RX:" + String(RX2_PIN) + ", TX:" + String(TX2_PIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendCommandAsHex(String hexString) {
|
||||||
|
int hexStringLength = hexString.length();
|
||||||
|
if (hexStringLength % 2 != 0) {
|
||||||
|
Serial.println("Error: Hex string must have an even number of characters.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int byteCount = hexStringLength / 2;
|
||||||
|
byte hexBytes[byteCount];
|
||||||
|
for (int i = 0; i < hexStringLength; i += 2) {
|
||||||
|
String byteString = hexString.substring(i, i + 2);
|
||||||
|
byte hexByte = (byte)strtoul(byteString.c_str(), NULL, 16);
|
||||||
|
hexBytes[i / 2] = hexByte;
|
||||||
|
}
|
||||||
|
// Print confirmation of what's being sent
|
||||||
|
Serial.print("Sending ");
|
||||||
|
Serial.print(byteCount);
|
||||||
|
Serial.print(" bytes: ");
|
||||||
|
for(int i=0; i<byteCount; i++) {
|
||||||
|
if (hexBytes[i] < 16) Serial.print("0");;
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
// Send the data
|
||||||
|
Serial2.write(hexBytes, byteCount);
|
||||||
|
Serial.println("Initial command sent to Serial2.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeWifi() {
|
||||||
|
|
||||||
|
WiFi.persistent(true);
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||||
|
Serial.println("Connecting to WiFi...");
|
||||||
|
int connectTime = millis();
|
||||||
|
while(WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(200);
|
||||||
|
Serial.print(".");
|
||||||
|
if (millis() - connectTime >= WIFI_CONNECT_WAIT_MAX) {
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Connection succesful!");
|
||||||
|
Serial.printf("SSID: %s\r\n", WiFi.SSID().c_str());
|
||||||
|
String IP = WiFi.localIP().toString();
|
||||||
|
Serial.printf("IP address: %s\r\n", IP.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeTime() {
|
||||||
|
Serial.println("Initializing time...");
|
||||||
|
configTime(GMT_OFFSET_SEC, DAY_LIGHT_OFFSET_SEC, NTP_SERVER1, NTP_SERVER2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeUI() {
|
||||||
|
|
||||||
|
Serial.println("Initializing UI....");
|
||||||
|
axs15231_init();
|
||||||
|
lv_init();
|
||||||
|
size_t buffer_size =
|
||||||
|
sizeof(lv_color_t) * EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES;
|
||||||
|
buf = (lv_color_t *)ps_malloc(buffer_size);
|
||||||
|
if (buf == NULL) {
|
||||||
|
while (1) {
|
||||||
|
Serial.println("buf NULL");
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf1 = (lv_color_t *)ps_malloc(buffer_size);
|
||||||
|
if (buf1 == NULL) {
|
||||||
|
while (1) {
|
||||||
|
Serial.println("buf NULL");
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_disp_draw_buf_init(&draw_buf, buf, buf1, buffer_size);
|
||||||
|
/*Initialize the display*/
|
||||||
|
static lv_disp_drv_t disp_drv;
|
||||||
|
lv_disp_drv_init(&disp_drv);
|
||||||
|
/*Change the following line to your display resolution*/
|
||||||
|
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
|
||||||
|
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
|
||||||
|
disp_drv.flush_cb = my_disp_flush;
|
||||||
|
disp_drv.draw_buf = &draw_buf;
|
||||||
|
disp_drv.sw_rotate = 1; // If you turn on software rotation, Do not update or replace LVGL
|
||||||
|
disp_drv.rotated = LV_DISP_ROT_90;
|
||||||
|
disp_drv.full_refresh = 1; // full_refresh must be 1
|
||||||
|
lv_disp_drv_register(&disp_drv);
|
||||||
|
|
||||||
|
static lv_indev_drv_t indev_drv;
|
||||||
|
lv_indev_drv_init(&indev_drv);
|
||||||
|
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||||
|
lv_indev_drv_register(&indev_drv);
|
||||||
|
|
||||||
|
Serial.println("UI initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printLocalTime() {
|
||||||
|
if (millis() - last_tick > 100) {
|
||||||
|
struct tm timeInfo;
|
||||||
|
if(!getLocalTime(&timeInfo)){
|
||||||
|
Serial.println("Failed to obtain time");
|
||||||
|
} else {
|
||||||
|
lv_msg_send(MSG_NEW_HOUR, &timeInfo.tm_hour);
|
||||||
|
lv_msg_send(MSG_NEW_MIN, &timeInfo.tm_min);
|
||||||
|
lv_msg_send(MSG_NEW_SEC, &timeInfo.tm_sec);
|
||||||
|
}
|
||||||
|
last_tick = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readAndProcessSensorLines() {
|
||||||
|
|
||||||
|
if (millis() - lastMotionCheckTime >= DELAY_STATUS_CHECK) {
|
||||||
|
lastMotionCheckTime = millis();
|
||||||
|
// Check if data is available on Serial2
|
||||||
|
while (Serial2.available() > 0) {
|
||||||
|
// Read a line of text until a newline character (\n) is received
|
||||||
|
// The timeout helps prevent blocking forever if a line ending is missed
|
||||||
|
String line = Serial2.readStringUntil('\n');
|
||||||
|
|
||||||
|
// Clean up the line: remove potential carriage return (\r) and leading/trailing whitespace
|
||||||
|
line.trim();
|
||||||
|
|
||||||
|
// Check if the line contains the "Range" information
|
||||||
|
if (line.startsWith("Range ")) {
|
||||||
|
// Extract the substring after "Range "
|
||||||
|
String distanceStr = line.substring(6);
|
||||||
|
int distance = distanceStr.toInt();
|
||||||
|
bool currentStatus = distance <= PRESENCE_DISTANCE;
|
||||||
|
|
||||||
|
if (currentStatus) {
|
||||||
|
lastMotionDetected = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentStatus && state != 0) {
|
||||||
|
state = 0;
|
||||||
|
Serial.println("Motion detected, turning screen on.");
|
||||||
|
//rest_api_action(0);
|
||||||
|
} else if (!currentStatus && state == 1 && (millis() - lastMotionDetected >= POWER_DELAY)) {
|
||||||
|
state = 2;
|
||||||
|
Serial.printf("No motion detected for %d seconds, turning screen off.\n", POWER_DELAY);
|
||||||
|
//rest_api_action(2);
|
||||||
|
} else if (!currentStatus && state == 0 && (millis() - lastMotionDetected >= SLEEP_DELAY)) {
|
||||||
|
state = 1;
|
||||||
|
Serial.printf("No motion detected for %d seconds, turning screen screensaver on.\n", SLEEP_DELAY);
|
||||||
|
//rest_api_action(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// action: 0 => Screen on, => 1 Screen off, => 2 Power off
|
||||||
|
void rest_api_action(int action) {
|
||||||
|
WiFiClient client;
|
||||||
|
HTTPClient http;
|
||||||
|
int httpResponseCode;
|
||||||
|
String url;
|
||||||
|
|
||||||
|
if(WiFi.status() != WL_CONNECTED){
|
||||||
|
Serial.println("WiFi Disconnected. No request sent");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 0: // Screen on
|
||||||
|
Serial.println("Sending Screen ON Request");
|
||||||
|
url = BASE_URL_HA + "/webostv/command";
|
||||||
|
http.begin(client, url);
|
||||||
|
http.addHeader("Authorization", "Bearer " + HA_TOKEN);
|
||||||
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
httpResponseCode = http.POST("{\"entity_id\":\"media_player.lg_webos_smart_tv\",\"command\":\"com.webos.service.tvpower/power/turnOnScreen\"}");
|
||||||
|
break;
|
||||||
|
case 1: // Screen off
|
||||||
|
Serial.println("Sending Screen OFF Request");
|
||||||
|
url = BASE_URL_HA + "/webostv/command";
|
||||||
|
http.begin(client, url);
|
||||||
|
http.addHeader("Authorization", "Bearer " + HA_TOKEN);
|
||||||
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
httpResponseCode = http.POST("{\"entity_id\":\"media_player.lg_webos_smart_tv\",\"command\":\"com.webos.service.tvpower/power/turnOffScreen\"}");
|
||||||
|
break;
|
||||||
|
case 2: // Power off
|
||||||
|
Serial.println("Sending Power Off Request");
|
||||||
|
url = BASE_URL_HA + "/webostv/command";
|
||||||
|
http.begin(client, url);
|
||||||
|
http.addHeader("Authorization", "Bearer " + HA_TOKEN);
|
||||||
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
httpResponseCode = http.POST("{\"entity_id\":\"media_player.lg_webos_smart_tv\",\"command\":\"com.webos.service.tvpower/power/powerOffScreen\"}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("HTTP Response code: ");
|
||||||
|
Serial.println(httpResponseCode);
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
}
|
||||||
60
pins_config.h
Normal file
60
pins_config.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/***********************config*************************/
|
||||||
|
#define LCD_USB_QSPI_DREVER 1
|
||||||
|
|
||||||
|
#define SPI_FREQUENCY 32000000
|
||||||
|
#define TFT_SPI_MODE SPI_MODE0
|
||||||
|
#define TFT_SPI_HOST SPI2_HOST
|
||||||
|
|
||||||
|
#define WIFI_SSID "WIFI SSID"
|
||||||
|
#define WIFI_PASSWORD "WIFI Password"
|
||||||
|
|
||||||
|
#define WIFI_CONNECT_WAIT_MAX (30 * 1000)
|
||||||
|
|
||||||
|
#define NTP_SERVER1 "pool.ntp.org"
|
||||||
|
#define NTP_SERVER2 "time.nist.gov"
|
||||||
|
#define GMT_OFFSET_SEC 1*60*60
|
||||||
|
#define DAY_LIGHT_OFFSET_SEC 3600
|
||||||
|
|
||||||
|
/* Automatically update local time */
|
||||||
|
#define GET_TIMEZONE_API "https://ipapi.co/timezone/"
|
||||||
|
|
||||||
|
/***********************config*************************/
|
||||||
|
|
||||||
|
#define TFT_WIDTH 180
|
||||||
|
#define TFT_HEIGHT 640
|
||||||
|
|
||||||
|
#ifdef TFT_WIDTH
|
||||||
|
#define EXAMPLE_LCD_H_RES TFT_WIDTH
|
||||||
|
#else
|
||||||
|
#define EXAMPLE_LCD_H_RES 180
|
||||||
|
#endif
|
||||||
|
#ifdef TFT_HEIGHT
|
||||||
|
#define EXAMPLE_LCD_V_RES TFT_HEIGHT
|
||||||
|
#else
|
||||||
|
#define EXAMPLE_LCD_V_RES 640
|
||||||
|
#endif
|
||||||
|
#define LVGL_LCD_BUF_SIZE (EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES)
|
||||||
|
|
||||||
|
#define SEND_BUF_SIZE (28800/2) //16bit(RGB565)
|
||||||
|
|
||||||
|
#define TFT_QSPI_CS 12
|
||||||
|
#define TFT_QSPI_SCK 17
|
||||||
|
#define TFT_QSPI_D0 13
|
||||||
|
#define TFT_QSPI_D1 18
|
||||||
|
#define TFT_QSPI_D2 21
|
||||||
|
#define TFT_QSPI_D3 14
|
||||||
|
#define TFT_QSPI_RST 16
|
||||||
|
#define TFT_BL 1
|
||||||
|
|
||||||
|
|
||||||
|
#define PIN_BAT_VOLT 2
|
||||||
|
|
||||||
|
#define PIN_BUTTON_1 0
|
||||||
|
#define PIN_BUTTON_2 21
|
||||||
|
|
||||||
|
#define TOUCH_IICSCL 10
|
||||||
|
#define TOUCH_IICSDA 15
|
||||||
|
#define TOUCH_INT 11
|
||||||
|
#define TOUCH_RES 16
|
||||||
BIN
src/arduino-lilygo-t-display-config.png
Normal file
BIN
src/arduino-lilygo-t-display-config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
3316
src/font_Alibaba.c
Normal file
3316
src/font_Alibaba.c
Normal file
File diff suppressed because it is too large
Load Diff
2216
src/gif_01.c
Normal file
2216
src/gif_01.c
Normal file
File diff suppressed because it is too large
Load Diff
2404
src/gif_12.c
Normal file
2404
src/gif_12.c
Normal file
File diff suppressed because it is too large
Load Diff
2286
src/gif_23.c
Normal file
2286
src/gif_23.c
Normal file
File diff suppressed because it is too large
Load Diff
2106
src/gif_34.c
Normal file
2106
src/gif_34.c
Normal file
File diff suppressed because it is too large
Load Diff
2526
src/gif_45.c
Normal file
2526
src/gif_45.c
Normal file
File diff suppressed because it is too large
Load Diff
2176
src/gif_56.c
Normal file
2176
src/gif_56.c
Normal file
File diff suppressed because it is too large
Load Diff
2217
src/gif_67.c
Normal file
2217
src/gif_67.c
Normal file
File diff suppressed because it is too large
Load Diff
2481
src/gif_78.c
Normal file
2481
src/gif_78.c
Normal file
File diff suppressed because it is too large
Load Diff
2506
src/gif_89.c
Normal file
2506
src/gif_89.c
Normal file
File diff suppressed because it is too large
Load Diff
2676
src/gif_90.c
Normal file
2676
src/gif_90.c
Normal file
File diff suppressed because it is too large
Load Diff
1415
src/lilygo1_gif.c
Normal file
1415
src/lilygo1_gif.c
Normal file
File diff suppressed because it is too large
Load Diff
32565
src/lilygo2_gif.c
Normal file
32565
src/lilygo2_gif.c
Normal file
File diff suppressed because it is too large
Load Diff
156
ui-util.cpp
Normal file
156
ui-util.cpp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#include "lvgl.h"
|
||||||
|
#include "pins_config.h"
|
||||||
|
#include "AXS15231B.h"
|
||||||
|
#include "ui-util.h"
|
||||||
|
#include "time.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
#define set_anim_src(x) ((const void *)trans_ainm_buf[(x)])
|
||||||
|
#define buf_limit(idx) ((idx) % 10)
|
||||||
|
#define timer_h(v, n, obj) \
|
||||||
|
do { \
|
||||||
|
if (v != n / 10) { \
|
||||||
|
v = buf_limit(n / 10); \
|
||||||
|
if (v != 0) \
|
||||||
|
lv_gif_set_src(obj, (const void *)trans_ainm_buf[v - 1]); \
|
||||||
|
else \
|
||||||
|
lv_gif_set_src(obj, (const void *)trans_ainm_buf[buf_limit(9)]); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define timer_l(v, n, obj) \
|
||||||
|
do { \
|
||||||
|
if (v != n % 10) { \
|
||||||
|
v = buf_limit(n % 10); \
|
||||||
|
if (v != 0) \
|
||||||
|
lv_gif_set_src(obj, (const void *)trans_ainm_buf[v - 1]); \
|
||||||
|
else \
|
||||||
|
lv_gif_set_src(obj, (const void *)trans_ainm_buf[buf_limit(9)]); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
static lv_obj_t *dis;
|
||||||
|
static lv_obj_t *img1;
|
||||||
|
static lv_obj_t *img2;
|
||||||
|
static lv_obj_t *img3;
|
||||||
|
static lv_obj_t *img4;
|
||||||
|
static lv_obj_t *img5;
|
||||||
|
static lv_obj_t *img6;
|
||||||
|
|
||||||
|
// Transition animation
|
||||||
|
static const void *trans_ainm_buf[] = {
|
||||||
|
&gif_01, &gif_12, &gif_23, &gif_34, &gif_45,
|
||||||
|
&gif_56, &gif_67, &gif_78, &gif_89, &gif_90
|
||||||
|
};
|
||||||
|
|
||||||
|
static void update_text_subscriber_cb_demo1(void *s, lv_msg_t *msg);
|
||||||
|
void set_flip_time_anim(int hour, int minute, int second);
|
||||||
|
|
||||||
|
void ui_begin() {
|
||||||
|
dis = lv_tileview_create(lv_scr_act());
|
||||||
|
lv_obj_align(dis, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||||
|
lv_obj_set_size(dis, LV_PCT(100), LV_PCT(100));
|
||||||
|
// lv_obj_remove_style(dis, 0, LV_PART_SCROLLBAR);
|
||||||
|
lv_obj_set_style_bg_color(dis, lv_color_black(), LV_PART_MAIN | LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
lv_obj_t *tv1 = lv_tileview_add_tile(dis, 0, 0, LV_DIR_VER);
|
||||||
|
lv_obj_t *tv2 = lv_tileview_add_tile(dis, 0, 1, LV_DIR_VER);
|
||||||
|
lv_obj_t *tv3 = lv_tileview_add_tile(dis, 0, 2, LV_DIR_VER);
|
||||||
|
lv_obj_t *tv4 = lv_tileview_add_tile(dis, 0, 3, LV_DIR_VER);
|
||||||
|
|
||||||
|
img1 = lv_gif_create(tv1);
|
||||||
|
img2 = lv_gif_create(tv1);
|
||||||
|
img3 = lv_gif_create(tv1);
|
||||||
|
img4 = lv_gif_create(tv1);
|
||||||
|
img5 = lv_gif_create(tv1);
|
||||||
|
img6 = lv_gif_create(tv1);
|
||||||
|
|
||||||
|
lv_gif_set_src(img1, set_anim_src(9));
|
||||||
|
lv_gif_set_src(img2, set_anim_src(9));
|
||||||
|
lv_gif_set_src(img3, set_anim_src(9));
|
||||||
|
lv_gif_set_src(img4, set_anim_src(9));
|
||||||
|
lv_gif_set_src(img5, set_anim_src(9));
|
||||||
|
lv_gif_set_src(img6, set_anim_src(9));
|
||||||
|
|
||||||
|
lv_obj_align(img1, LV_ALIGN_LEFT_MID, 20, 0);
|
||||||
|
lv_obj_align_to(img2, img1, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
lv_obj_align(img3, LV_ALIGN_LEFT_MID, 225, 0);
|
||||||
|
lv_obj_align_to(img4, img3, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
lv_obj_align(img5, LV_ALIGN_LEFT_MID, 430, 0);
|
||||||
|
lv_obj_align_to(img6, img5, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
|
lv_msg_subsribe(MSG_NEW_HOUR, update_text_subscriber_cb_demo1, NULL);
|
||||||
|
lv_msg_subsribe(MSG_NEW_MIN, update_text_subscriber_cb_demo1, NULL);
|
||||||
|
lv_msg_subsribe(MSG_NEW_SEC, update_text_subscriber_cb_demo1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_text_subscriber_cb_demo1(void *s, lv_msg_t *msg) {
|
||||||
|
static int hour = 0;
|
||||||
|
static int minute = 0;
|
||||||
|
static int second = 0;
|
||||||
|
static uint32_t start_tick = lv_tick_get();
|
||||||
|
const int32_t *v = (const int32_t *)lv_msg_get_payload(msg);
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
switch (lv_msg_get_id(msg)) {
|
||||||
|
case MSG_NEW_HOUR: hour = *v; break;
|
||||||
|
case MSG_NEW_MIN: minute = *v; break;
|
||||||
|
case MSG_NEW_SEC: second = *v; break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} /* clang-format off */
|
||||||
|
|
||||||
|
if (lv_tick_elaps(start_tick) >= 1000) {
|
||||||
|
start_tick = lv_tick_get();
|
||||||
|
set_flip_time_anim(hour, minute, second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_flip_time_anim(int hour, int minute, int second) {
|
||||||
|
static int sec_h, sec_l, min_h, min_l, hou_h, hou_l;
|
||||||
|
|
||||||
|
timer_l(sec_l, second, img6);
|
||||||
|
timer_h(sec_h, second, img5);
|
||||||
|
timer_l(min_l, minute, img4);
|
||||||
|
timer_h(min_h, minute, img3);
|
||||||
|
timer_l(hou_l, hour, img2);
|
||||||
|
timer_h(hou_h, hour, img1);
|
||||||
|
|
||||||
|
// printf("clock=%02d:%02d:%02d\n", hour, minute, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
|
||||||
|
uint32_t w = (area->x2 - area->x1 + 1);
|
||||||
|
uint32_t h = (area->y2 - area->y1 + 1);
|
||||||
|
|
||||||
|
#ifdef LCD_SPI_DMA
|
||||||
|
char i = 0;
|
||||||
|
while (get_lcd_spi_dma_write()) {
|
||||||
|
i = i >> 1;
|
||||||
|
lcd_PushColors(0, 0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
lcd_PushColors(area->x1, area->y1, w, h, (uint16_t *)&color_p->full);
|
||||||
|
|
||||||
|
#ifdef LCD_SPI_DMA
|
||||||
|
|
||||||
|
#else
|
||||||
|
lv_disp_flush_ready(disp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_delay_ms(int x) {
|
||||||
|
do {
|
||||||
|
uint32_t t = x;
|
||||||
|
while (t--) {
|
||||||
|
delay(1);
|
||||||
|
if (transfer_num <= 0 && lcd_PushColors_len <= 0)
|
||||||
|
lv_timer_handler();
|
||||||
|
|
||||||
|
if (transfer_num <= 1 && lcd_PushColors_len > 0) {
|
||||||
|
lcd_PushColors(0, 0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
33
ui-util.h
Normal file
33
ui-util.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#define UI_BG_COLOR lv_color_black()
|
||||||
|
#define UI_FRAME_COLOR lv_color_hex(0x282828)
|
||||||
|
#define UI_FONT_COLOR lv_color_white()
|
||||||
|
#define UI_PAGE_COUNT 3
|
||||||
|
|
||||||
|
#define MSG_NEW_HOUR 1
|
||||||
|
#define MSG_NEW_MIN 2
|
||||||
|
#define MSG_NEW_VOLT 3
|
||||||
|
#define MSG_NEW_TOUCH_POINT 4
|
||||||
|
#define MSG_NEW_SEC 5
|
||||||
|
#define MSG_NEW_USB 6
|
||||||
|
#define MSG_NEW_OTG_BTN 7
|
||||||
|
|
||||||
|
LV_FONT_DECLARE(font_Alibaba);
|
||||||
|
LV_IMG_DECLARE(lilygo1_gif);
|
||||||
|
LV_IMG_DECLARE(lilygo2_gif);
|
||||||
|
LV_IMG_DECLARE(gif_01);
|
||||||
|
LV_IMG_DECLARE(gif_12);
|
||||||
|
LV_IMG_DECLARE(gif_23);
|
||||||
|
LV_IMG_DECLARE(gif_34);
|
||||||
|
LV_IMG_DECLARE(gif_45);
|
||||||
|
LV_IMG_DECLARE(gif_56);
|
||||||
|
LV_IMG_DECLARE(gif_67);
|
||||||
|
LV_IMG_DECLARE(gif_78);
|
||||||
|
LV_IMG_DECLARE(gif_89);
|
||||||
|
LV_IMG_DECLARE(gif_90);
|
||||||
|
|
||||||
|
extern uint32_t transfer_num;
|
||||||
|
extern size_t lcd_PushColors_len;
|
||||||
|
|
||||||
|
void ui_begin();
|
||||||
|
void lv_delay_ms(int x);
|
||||||
|
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
|
||||||
Reference in New Issue
Block a user