temp
This commit is contained in:
commit
eaaf17b1d8
279
CMakeLists.txt
Normal file
279
CMakeLists.txt
Normal file
@ -0,0 +1,279 @@
|
||||
# Copyright (C) 2020 QUECTEL Technologies Limited and/or its affiliates("QUECTEL").
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
add_subdirectory_if_exist(init)
|
||||
|
||||
add_subdirectory_if_exist(nw)
|
||||
|
||||
add_subdirectory_if_exist(peripheral)
|
||||
|
||||
add_subdirectory_if_exist(osi)
|
||||
|
||||
add_subdirectory_if_exist(dev)
|
||||
|
||||
add_subdirectory_if_exist(power)
|
||||
|
||||
if(QL_APP_FEATURE_USB)
|
||||
add_subdirectory_if_exist(usb)
|
||||
endif()
|
||||
|
||||
add_subdirectory_if_exist(qnewlib)
|
||||
|
||||
if(QL_APP_FEATURE_FILE)
|
||||
add_subdirectory_if_exist(fs)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_AUDIO)
|
||||
add_subdirectory_if_exist(audio)
|
||||
if(QL_APP_FEATURE_TTS)
|
||||
add_subdirectory_if_exist(tts)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_BT)
|
||||
add_subdirectory_if_exist(bt)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_GNSS)
|
||||
add_subdirectory_if_exist(gnss)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FTP)
|
||||
add_subdirectory_if_exist(ftp)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_HTTP)
|
||||
add_subdirectory_if_exist(http)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_MMS)
|
||||
add_subdirectory_if_exist(mms)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_MQTT)
|
||||
add_subdirectory_if_exist(mqtt)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FIREWALL)
|
||||
add_subdirectory_if_exist(firewall)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SSL)
|
||||
add_subdirectory_if_exist(ssl)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_STK)
|
||||
add_subdirectory_if_exist(stk)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_PING)
|
||||
add_subdirectory_if_exist(ping)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_NTP)
|
||||
add_subdirectory_if_exist(ntp)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_LBS)
|
||||
add_subdirectory_if_exist(lbs)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_QTHSDK)
|
||||
add_subdirectory_if_exist(qthsdk)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_CTSREG)
|
||||
add_subdirectory_if_exist(ctsreg)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SOCKET)
|
||||
add_subdirectory_if_exist(socket)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_LCD)
|
||||
add_subdirectory_if_exist(lcd)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_MIPI_LCD)
|
||||
add_subdirectory_if_exist(mipi_lcd)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_LVGL)
|
||||
add_subdirectory_if_exist(EC600U_lvgl_lib)
|
||||
add_subdirectory_if_exist(EC600U_lvgl)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_CAMERA)
|
||||
add_subdirectory_if_exist(camera)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_WIFISCAN)
|
||||
add_subdirectory_if_exist(wifi_scan)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SIM)
|
||||
add_subdirectory_if_exist(sim)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_VSIM_ADAPT)
|
||||
add_subdirectory_if_exist(vsim_adapt)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SMS)
|
||||
add_subdirectory_if_exist(sms)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_VOICE_CALL)
|
||||
add_subdirectory_if_exist(voice_call)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_VOLTE)
|
||||
add_subdirectory_if_exist(volte)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SPI)
|
||||
add_subdirectory_if_exist(spi)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SPI_NOR_FLASH)
|
||||
add_subdirectory_if_exist(spi_nor_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SPI4_EXT_NOR_SFFS)
|
||||
add_subdirectory_if_exist(spi4_ext_nor_sffs)
|
||||
endif()
|
||||
if(QL_APP_FEATURE_SPI6_EXT_NOR)
|
||||
add_subdirectory_if_exist(spi6_ext_nor_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SPI_NAND_FLASH)
|
||||
add_subdirectory_if_exist(spi_nand_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_HTTP_FOTA)
|
||||
add_subdirectory_if_exist(http_fota)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FTP_FOTA)
|
||||
add_subdirectory_if_exist(ftp_fota)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_DECODER)
|
||||
add_subdirectory_if_exist(decoder)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_APP_IMG_AT)
|
||||
add_subdirectory_if_exist(app_img_at)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_RTC)
|
||||
add_subdirectory_if_exist(rtc)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_VIRT_AT)
|
||||
add_subdirectory_if_exist(virt_at)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_ALI_LINKSDK)
|
||||
add_subdirectory_if_exist(LinkSDK)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_QCLOUD_IOT)
|
||||
add_subdirectory_if_exist(qcloud-iot)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_I2C)
|
||||
add_subdirectory_if_exist(i2c)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SDMMC)
|
||||
add_subdirectory_if_exist(sdmmc)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_USBNET)
|
||||
add_subdirectory_if_exist(usbnet)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FS_NAND_FLASH)
|
||||
add_subdirectory_if_exist(fs_nand_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FS_NOR_FLASH)
|
||||
add_subdirectory_if_exist(fs_nor_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_FILE_ZIP)
|
||||
add_subdirectory_if_exist(zip)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SFTP)
|
||||
add_subdirectory_if_exist(sftp)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_MXML)
|
||||
add_subdirectory_if_exist(mxml)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_CLOUDOTA)
|
||||
add_subdirectory_if_exist(cloud_ota)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_HILINK)
|
||||
add_subdirectory_if_exist(HiLinkSDK)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_EMBED_NOR_FLASH)
|
||||
add_subdirectory_if_exist(embed_nor_flash)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_GPRS_DATA_TRANSFER)
|
||||
add_subdirectory_if_exist(gprs_data_transfer)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_TP)
|
||||
add_subdirectory_if_exist(tp)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_ALIOTSMARTCARD)
|
||||
add_subdirectory_if_exist(aliotsmartcard)
|
||||
endif()
|
||||
if (QL_APP_FEATURE_ALIPAY_IOT_SDK)
|
||||
add_subdirectory_if_exist(alipay_iot_sdk)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_NTRIP_RTK)
|
||||
add_subdirectory_if_exist(ntrip_rtk)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_LWM2M)
|
||||
add_subdirectory_if_exist(lwm2m)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_WEBSOCKET)
|
||||
add_subdirectory_if_exist(libwebsockets)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_SS)
|
||||
add_subdirectory_if_exist(ss)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_ETHERNET)
|
||||
add_subdirectory_if_exist(ethernet)
|
||||
endif()
|
||||
|
||||
if(QL_APP_FEATURE_WIFI)
|
||||
add_subdirectory_if_exist(wifi)
|
||||
endif()
|
||||
|
||||
# add_subdirectory_if_exist(EC600U_rtk+t2n)
|
||||
add_subdirectory_if_exist(EC600U_lora)
|
||||
add_subdirectory_if_exist(EC600U_rtk)
|
||||
add_subdirectory_if_exist(EC600U_t2n)
|
||||
add_subdirectory_if_exist(EC600U_can)
|
||||
add_subdirectory_if_exist(EC600U_bl0939)
|
||||
add_subdirectory_if_exist(EC600U_soft_enc)
|
||||
add_subdirectory_if_exist(EC600U_rs485)
|
||||
add_subdirectory_if_exist(EC600U_uart1)
|
||||
|
||||
add_subdirectory_if_exist(esp32_iap)
|
46
EC600U_bl0939/CMakeLists.txt
Normal file
46
EC600U_bl0939/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright (C) 2020 QUECTEL Technologies Limited and/or its affiliates("QUECTEL").
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
# set(target ql_app_t2n)
|
||||
|
||||
# add_library(${target} STATIC)
|
||||
# set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
# target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
# target_include_directories(${target} PUBLIC inc)
|
||||
# #target_link_libraries(${target} PRIVATE ql_api_common)
|
||||
|
||||
# target_sources(${target}
|
||||
# # cfg.c
|
||||
# # cJSON.c
|
||||
# # md5.c
|
||||
# modbus-tcp.c
|
||||
# modbus-udp.c
|
||||
# ModbusS.c
|
||||
# network_ql.c
|
||||
# t2n.c
|
||||
# )
|
||||
|
||||
|
||||
# target_sources_if(QL_APP_FEATURE_KEYPAD THEN ${target} PRIVATE keypad_demo.c)
|
||||
# target_sources_if(QL_APP_FEATURE_RS485 THEN ${target} PRIVATE rs485_demo.c)
|
||||
|
||||
# relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
# beautify_c_code(${target} ${srcs})
|
||||
|
||||
|
||||
set(target ac_current)
|
||||
|
||||
add_library(${target} STATIC)
|
||||
set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
# target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
target_include_directories(${target} PUBLIC inc)
|
||||
include_directories(${SOURCE_TOP_DIR}/components/app/t2n/include)
|
||||
target_link_libraries(${target} PUBLIC)
|
||||
|
||||
target_sources(${target} PUBLIC
|
||||
ac_current.c
|
||||
)
|
||||
|
||||
relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
beautify_c_code(${target} ${srcs})
|
328
EC600U_bl0939/ac_current.c
Normal file
328
EC600U_bl0939/ac_current.c
Normal file
@ -0,0 +1,328 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "osi_api.h"
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_api_spi.h"
|
||||
#include "osi_compiler.h"
|
||||
//#include "cfg.h"
|
||||
#include "../EC600U_t2n/include/t2n.h"
|
||||
#include "ql_log.h"
|
||||
#define AC_CURRENT_REG_ADDR 24
|
||||
#define ENC_VALUE_REG_ADDR 28
|
||||
// #define LOGD(msg, ...) QL_LOG(QL_LOG_LEVEL_DEBUG, "bl0939", msg, ##__VA_ARGS__)
|
||||
// #define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "bl0939", msg, ##__VA_ARGS__)
|
||||
// #define LOGW(msg, ...) QL_LOG(QL_LOG_LEVEL_WARN, "bl0939", msg, ##__VA_ARGS__)
|
||||
// #define LOGE(msg, ...) QL_LOG(QL_LOG_LEVEL_ERROR, "bl0939", msg, ##__VA_ARGS__)
|
||||
|
||||
#define LOGD(msg, ...) QL_LOG(QL_LOG_LEVEL_VERBOSE, "bl0939", msg, ##__VA_ARGS__)
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_VERBOSE, "bl0939", msg, ##__VA_ARGS__)
|
||||
#define LOGW(msg, ...) QL_LOG(QL_LOG_LEVEL_WARN, "bl0939", msg, ##__VA_ARGS__)
|
||||
#define LOGE(msg, ...) QL_LOG(QL_LOG_LEVEL_ERROR, "bl0939", msg, ##__VA_ARGS__)
|
||||
|
||||
extern int enc_value;
|
||||
|
||||
// static ql_task_t *current_task_handle = NULL;
|
||||
|
||||
#define BL0939_READ_TIMER 0x8000
|
||||
|
||||
osiThread_t *bl_thread_handle = NULL;
|
||||
osiTimer_t *bl_timer = NULL;
|
||||
static int spi_wait_write_read = 0;
|
||||
ql_sem_t spi_write_semaphore;
|
||||
ql_sem_t spi_read_semaphore;
|
||||
|
||||
#define QL_SPI_WAIT_NONE 0
|
||||
#define QL_SPI_WAIT_WRITE 1
|
||||
#define QL_SPI_WAIT_READ 2
|
||||
|
||||
extern uint16_t gWordVar[];
|
||||
|
||||
static const uint8_t bl0939_cmd[36] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x55, 0x00, 0, 0, 0, 0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x55, 0x07, 0, 0, 0, 0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x55, 0x06, 0, 0, 0, 0};
|
||||
|
||||
static uint8_t spi_txbuf[36] OSI_CACHE_LINE_ALIGNED;
|
||||
static uint8_t spi_rxbuf[36] OSI_CACHE_LINE_ALIGNED;
|
||||
|
||||
static void spi_cb_handler(ql_spi_irq_s cause)
|
||||
{
|
||||
if (cause.rx_dma_done == 1 && spi_wait_write_read == QL_SPI_WAIT_READ)
|
||||
{
|
||||
spi_wait_write_read = 0;
|
||||
ql_rtos_semaphore_release(spi_read_semaphore);
|
||||
}
|
||||
if (cause.tx_dma_done == 1 && spi_wait_write_read == QL_SPI_WAIT_WRITE)
|
||||
{
|
||||
spi_wait_write_read = 0;
|
||||
ql_rtos_semaphore_release(spi_write_semaphore);
|
||||
}
|
||||
LOGD("spi_cb_handler rx_dma_done=%d tx_dma_done=%d\r\n", cause.rx_dma_done, cause.tx_dma_done);
|
||||
}
|
||||
|
||||
static int spi_write(int fd, uint8_t *inbuf, int len)
|
||||
{
|
||||
int ret;
|
||||
spi_wait_write_read = QL_SPI_WAIT_WRITE;
|
||||
ql_spi_request_sys_clk(fd);
|
||||
ret = ql_spi_write(fd, inbuf, len);
|
||||
ql_rtos_semaphore_wait(spi_write_semaphore, 10);
|
||||
LOGD("spi_write inbuf=%p,len=%d,ret=%d", inbuf, len, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_write_read(int fd, uint8_t *outbuf, uint8_t *inbuf, int len)
|
||||
{
|
||||
int ret;
|
||||
spi_wait_write_read = QL_SPI_WAIT_READ;
|
||||
ret = ql_spi_write_read(fd, inbuf, outbuf, len);
|
||||
ql_rtos_semaphore_wait(spi_read_semaphore, 10);
|
||||
LOGD("spi_write_read inbuf=%p,outbuf=%p,len=%d,ret=%d", inbuf, outbuf, len, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_sum_ch(uint8_t *resp, uint8_t *cmd, int offset)
|
||||
{
|
||||
uint8_t sum = ~(0x55 + cmd[offset - 1] + resp[offset] + resp[offset + 1] + resp[offset + 2]);
|
||||
if (resp[offset + 3] == sum)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint32_t readUint24LE(uint8_t *buf, int offset)
|
||||
{
|
||||
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
||||
}
|
||||
uint32_t readUint24BE(uint8_t *buf, int offset)
|
||||
{
|
||||
return buf[offset] << 16 | buf[offset + 1] << 8 | buf[offset + 2];
|
||||
}
|
||||
|
||||
float ac_current_coef[3] = {
|
||||
1.218f / (324004.f * 0.225 * 1000 / 2000) * 100.f,
|
||||
1.218f / (324004.f * 0.23 * 1000 / 2000) * 100.f,
|
||||
1.218f / (79931.f * 0.002 * 500) * 100.f};
|
||||
|
||||
// uint8_t bl0939_rxbuf[36];
|
||||
int32_t ac_ad_values[3] = {0};
|
||||
|
||||
static void bl_read_data_timer(void *parm)
|
||||
{
|
||||
osiTimerStart(bl_timer, 20);
|
||||
ql_event_t event;
|
||||
event.id = BL0939_READ_TIMER;
|
||||
if (bl_thread_handle)
|
||||
{
|
||||
ql_rtos_event_send(bl_thread_handle, &event);
|
||||
}
|
||||
// LOGD("bl_read_data_timer\r\n");
|
||||
}
|
||||
|
||||
static uint32_t bl0939_read_reg(int fd, uint8_t reg)
|
||||
{
|
||||
spi_txbuf[0] = 0x55;
|
||||
spi_txbuf[1] = reg;
|
||||
spi_txbuf[2] = 0;
|
||||
spi_txbuf[3] = 0;
|
||||
spi_txbuf[4] = 0;
|
||||
spi_txbuf[5] = 0;
|
||||
// bl0939_spi_reset();
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, 6);
|
||||
spi_wait_write_read = QL_SPI_WAIT_READ;
|
||||
ql_rtos_semaphore_wait(spi_read_semaphore, 10);
|
||||
if (spi_rxbuf[5] == (uint8_t) ~(0x55 + reg + spi_rxbuf[2] + spi_rxbuf[3] + spi_rxbuf[4]))
|
||||
{
|
||||
return (uint32_t)spi_rxbuf[2] << 16 |
|
||||
(uint32_t)spi_rxbuf[3] << 8 |
|
||||
(uint32_t)spi_rxbuf[4] << 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void bl0939_spi_reset(int fd)
|
||||
{
|
||||
spi_txbuf[0] = 0xff;
|
||||
spi_txbuf[1] = 0xff;
|
||||
spi_txbuf[2] = 0xff;
|
||||
spi_txbuf[3] = 0xff;
|
||||
spi_txbuf[4] = 0xff;
|
||||
spi_txbuf[5] = 0xff;
|
||||
spi_write(fd, spi_txbuf, 6);
|
||||
}
|
||||
uint32_t r_temp = 0;
|
||||
static int bl0939_write_reg(int fd, uint8_t reg, uint32_t val, int check)
|
||||
{
|
||||
int try_times = 0;
|
||||
uint8_t h = val >> 16;
|
||||
uint8_t m = val >> 8;
|
||||
uint8_t l = val >> 0;
|
||||
do
|
||||
{
|
||||
// bl0939_spi_reset();
|
||||
spi_txbuf[0] = 0xA5;
|
||||
spi_txbuf[1] = reg;
|
||||
spi_txbuf[2] = h;
|
||||
spi_txbuf[3] = m;
|
||||
spi_txbuf[4] = l;
|
||||
spi_txbuf[5] = ~(0XA5 + reg + h + m + l);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, 6);
|
||||
ql_rtos_semaphore_wait(spi_read_semaphore, 10);
|
||||
if (0 == check)
|
||||
return 0;
|
||||
r_temp = bl0939_read_reg(fd, reg);
|
||||
if (r_temp == val)
|
||||
return 0;
|
||||
ql_rtos_task_sleep_ms(100);
|
||||
} while (try_times++ < 5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bl0939_init(int fd)
|
||||
{
|
||||
bl0939_spi_reset(fd);
|
||||
bl0939_write_reg(fd, 0x19, 0x005a5a5a, 0); // <20><>λ<EFBFBD>û<EFBFBD><C3BB>Ĵ<EFBFBD><C4B4><EFBFBD>
|
||||
bl0939_write_reg(fd, 0x1a, 0x00000055, 1); // <20><><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
bl0939_write_reg(fd, 0x10, 0xffff, 0); // Threshold A
|
||||
bl0939_write_reg(fd, 0x1E, 0xffff, 1); // Threshold B
|
||||
bl0939_write_reg(fd, 0x18, 0x00002000, 1); // cf
|
||||
bl0939_write_reg(fd, 0x1B, 0x000047ff, 0); // cf
|
||||
bl0939_write_reg(fd, 0x1a, 0x00000000, 1); // д<><D0B4><EFBFBD><EFBFBD>
|
||||
}
|
||||
void bl0939_task(void *data)
|
||||
{
|
||||
|
||||
int ret;
|
||||
ql_spi_config_s spi_config = {0};
|
||||
int spi_no = QL_SPI_PORT1;
|
||||
spi_config.port = spi_no;
|
||||
spi_config.spiclk = QL_SPI_CLK_781_25KHZ;
|
||||
spi_config.framesize = 8;
|
||||
spi_config.input_mode = QL_SPI_INPUT_TRUE;
|
||||
spi_config.cs_polarity0 = QL_SPI_CS_ACTIVE_LOW;
|
||||
spi_config.cs_polarity1 = QL_SPI_CS_ACTIVE_LOW;
|
||||
spi_config.cpol = QL_SPI_CPOL_LOW;
|
||||
spi_config.cpha = QL_SPI_CPHA_2Edge; // mode 1
|
||||
spi_config.input_sel = QL_SPI_DI_1;
|
||||
spi_config.transmode = QL_SPI_DMA_IRQ;
|
||||
spi_config.cs = QL_SPI_CS0;
|
||||
spi_config.clk_delay = QL_SPI_CLK_DELAY_0;
|
||||
LOGD("bl0939_task entry");
|
||||
ql_rtos_task_sleep_ms(5000);
|
||||
ql_spi_init_ext(spi_config);
|
||||
ql_spi_cs_auto(spi_no);
|
||||
|
||||
// uint32_t addr = (uint32_t)__spi_dma_out_buf;
|
||||
// addr += 32 - addr % 32;
|
||||
// spi_txbuf = (uint8_t *)(addr);
|
||||
// LOGD("spi_txbuf=%p",spi_txbuf);
|
||||
// addr = (uint32_t)__spi_dma_in_buf;
|
||||
// addr += 32 - addr % 32;
|
||||
// spi_rxbuf = (uint8_t *)(addr);
|
||||
// LOGD("spi_rxbuf=%p", spi_rxbuf);
|
||||
LOGD("ql_spi_init done");
|
||||
ql_rtos_semaphore_create(&spi_read_semaphore, 0);
|
||||
ql_rtos_semaphore_create(&spi_write_semaphore, 0);
|
||||
LOGD("semaphore create done");
|
||||
ql_spi_irq_s mask = {
|
||||
.rx_dma_done = 1,
|
||||
.tx_dma_done = 1,
|
||||
};
|
||||
|
||||
ql_spi_set_irq(spi_no, mask, spi_cb_handler);
|
||||
LOGD("ql_spi_set_irq done");
|
||||
bl0939_init(spi_no);
|
||||
bl_thread_handle = osiThreadCurrent();
|
||||
bl_timer = osiTimerCreate(bl_thread_handle, bl_read_data_timer, (void *)spi_no); // 创建定时器
|
||||
if (NULL == bl_timer)
|
||||
{
|
||||
LOGE("bl_timer create failed\n");
|
||||
osiThreadExit();
|
||||
}
|
||||
ret = osiTimerStart(bl_timer, 20);
|
||||
if (ret)
|
||||
{
|
||||
LOGE("osiTimerStart failed ret=%d\n", ret);
|
||||
}
|
||||
LOGD("bl0939_task init done");
|
||||
|
||||
ret = ql_pin_set_func(95, 5); // set pin 95 to gpio10
|
||||
if (ret != QL_GPIO_SUCCESS)
|
||||
{
|
||||
LOGE("ql_pin_set_func 95 err ret=%d", ret);
|
||||
}
|
||||
ql_gpio_set_direction(GPIO_10, GPIO_INPUT);
|
||||
ret = ql_pin_set_func(98, 5); // set pin 95 to gpio9
|
||||
if (ret != QL_GPIO_SUCCESS)
|
||||
{
|
||||
LOGE("ql_pin_set_func 98 err ret=%d", ret);
|
||||
}
|
||||
ql_gpio_set_direction(GPIO_9, GPIO_INPUT);
|
||||
|
||||
ret = ql_pin_set_func(99, 5); // set pin 98 to gpio8
|
||||
if (ret != QL_GPIO_SUCCESS)
|
||||
{
|
||||
LOGE("ql_pin_set_func 99 err ret=%d", ret);
|
||||
}
|
||||
ql_gpio_set_direction(GPIO_8, GPIO_OUTPUT);
|
||||
ret = ql_pin_set_func(100, 5); // set pin 95 to gpio12
|
||||
if (ret != QL_GPIO_SUCCESS)
|
||||
{
|
||||
LOGE("ql_pin_set_func 100 err ret=%d", ret);
|
||||
}
|
||||
ql_gpio_set_direction(GPIO_8, GPIO_OUTPUT);
|
||||
while (1)
|
||||
{
|
||||
ql_event_t event;
|
||||
ret = ql_event_wait(&event, 1000);
|
||||
if (ret == 0)
|
||||
{
|
||||
switch (event.id)
|
||||
{
|
||||
case BL0939_READ_TIMER:
|
||||
memcpy(spi_txbuf, bl0939_cmd, sizeof(bl0939_cmd));
|
||||
ret = spi_write_read(spi_no, spi_txbuf, spi_rxbuf, 36);
|
||||
if (ret == 0)
|
||||
{
|
||||
for (int ch = 0; ch < 3; ch++)
|
||||
{
|
||||
if (check_sum_ch(spi_rxbuf, spi_txbuf, 8 + ch * 12))
|
||||
{
|
||||
ac_ad_values[ch] = readUint24BE(spi_rxbuf, 8 + ch * 12);
|
||||
LOGI("channel : %d ac_ad_values: %d\n ", ch, ac_ad_values[ch]);
|
||||
gWordVar[AC_CURRENT_REG_ADDR + ch] = ac_ad_values[ch] * ac_current_coef[ch];
|
||||
}
|
||||
else
|
||||
{
|
||||
int value = readUint24BE(spi_rxbuf, 8 + ch * 12);
|
||||
LOGW("check bed ch: %d ac_ad_values: %d\n ", ch, value);
|
||||
}
|
||||
// ac_ad_values[ch] = readUint24BE(bl0939_rxbuf,8+ch*12);
|
||||
// ESP_LOGI(TAG, "channel : %d ac_ad_values: %d\n ", ch, ac_ad_values[ch]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE("spi_write_read err ret=%d\r\n", ret);
|
||||
}
|
||||
gWordVar[ENC_VALUE_REG_ADDR] = enc_value & 0xffff;
|
||||
gWordVar[ENC_VALUE_REG_ADDR + 1] = enc_value >> 16;
|
||||
ql_LvlMode gpio_value9;
|
||||
ql_LvlMode gpio_value10;
|
||||
ql_gpio_get_level(GPIO_9, &gpio_value9);
|
||||
ql_gpio_get_level(GPIO_10, &gpio_value10);
|
||||
gWordVar[ENC_VALUE_REG_ADDR + 2] = gpio_value9 | (gpio_value10 << 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE("timer not work ??", ret);
|
||||
osiTimerStart(bl_timer, 20);
|
||||
}
|
||||
}
|
||||
}
|
47
EC600U_can/CMakeLists.txt
Normal file
47
EC600U_can/CMakeLists.txt
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (C) 2020 QUECTEL Technologies Limited and/or its affiliates("QUECTEL").
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
# set(target ql_app_t2n)
|
||||
|
||||
# add_library(${target} STATIC)
|
||||
# set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
# target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
# target_include_directories(${target} PUBLIC inc)
|
||||
# #target_link_libraries(${target} PRIVATE ql_api_common)
|
||||
|
||||
# target_sources(${target}
|
||||
# # cfg.c
|
||||
# # cJSON.c
|
||||
# # md5.c
|
||||
# modbus-tcp.c
|
||||
# modbus-udp.c
|
||||
# ModbusS.c
|
||||
# network_ql.c
|
||||
# t2n.c
|
||||
# )
|
||||
|
||||
|
||||
# target_sources_if(QL_APP_FEATURE_KEYPAD THEN ${target} PRIVATE keypad_demo.c)
|
||||
# target_sources_if(QL_APP_FEATURE_RS485 THEN ${target} PRIVATE rs485_demo.c)
|
||||
|
||||
# relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
# beautify_c_code(${target} ${srcs})
|
||||
|
||||
|
||||
set(target can)
|
||||
|
||||
add_library(${target} STATIC)
|
||||
set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
# target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
target_include_directories(${target} PUBLIC inc)
|
||||
include_directories(${SOURCE_TOP_DIR}/components/app/t2n/include)
|
||||
target_link_libraries(${target} PUBLIC)
|
||||
|
||||
target_sources(${target} PUBLIC
|
||||
app_can.c
|
||||
mcp2515.c
|
||||
)
|
||||
|
||||
relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
beautify_c_code(${target} ${srcs})
|
256
EC600U_can/app_can.c
Normal file
256
EC600U_can/app_can.c
Normal file
@ -0,0 +1,256 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "osi_api.h"
|
||||
#include "ql_api_osi.h"
|
||||
|
||||
#include "ql_api_spi.h"
|
||||
#include "mcp2515.h"
|
||||
// #include "hw.h"
|
||||
// #include "cfg.h"
|
||||
#include "../EC600U_t2n/include/t2n.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#define LOGD(msg, ...) QL_LOG(QL_LOG_LEVEL_DEBUG, "can", msg, ##__VA_ARGS__)
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "can", msg, ##__VA_ARGS__)
|
||||
#define LOGW(msg, ...) QL_LOG(QL_LOG_LEVEL_WARN, "can", msg, ##__VA_ARGS__)
|
||||
#define LOGE(msg, ...) QL_LOG(QL_LOG_LEVEL_ERROR, "can", msg, ##__VA_ARGS__)
|
||||
#define QL_SPI_WAIT_NONE 0
|
||||
#define QL_SPI_WAIT_WRITE 1
|
||||
#define QL_SPI_WAIT_READ 2
|
||||
osiThread_t *can_task_handle = NULL;
|
||||
|
||||
extern uint16_t gWordVar[];
|
||||
|
||||
struct can_status *can_status[2] = {(struct can_status *)&gWordVar[512], (struct can_status *)&gWordVar[520]};
|
||||
// struct can_dev_cfg *can_dev_cfg = (struct can_dev_cfg *)&gWordVar[0x1000];
|
||||
|
||||
// ql_sem_t spi_write_semaphore;
|
||||
// ql_sem_t spi_read_semaphore;
|
||||
// static int spi_wait_write_read;
|
||||
|
||||
// static void spi_cb_handler(ql_spi_irq_s cause)
|
||||
// {
|
||||
// if (cause.rx_dma_done == 1 && spi_wait_write_read == QL_SPI_WAIT_READ)
|
||||
// {
|
||||
// spi_wait_write_read = 0;
|
||||
// ql_rtos_semaphore_release(spi_read_semaphore);
|
||||
// }
|
||||
// if (cause.tx_dma_done == 1 && spi_wait_write_read == QL_SPI_WAIT_WRITE)
|
||||
// {
|
||||
// spi_wait_write_read = 0;
|
||||
// ql_rtos_semaphore_release(spi_write_semaphore);
|
||||
// }
|
||||
// // LOGD("spi_cb_handler rx_dma_done=%d tx_dma_done=%d\r\n", cause.rx_dma_done, cause.tx_dma_done);
|
||||
// }
|
||||
|
||||
int spi_write(int fd, uint8_t *outbuf, int len)
|
||||
{
|
||||
int ret;
|
||||
// spi_wait_write_read = QL_SPI_WAIT_WRITE;
|
||||
// ql_spi_request_sys_clk(fd);
|
||||
ret = ql_spi_write(fd, outbuf, len);
|
||||
// ql_rtos_semaphore_wait(spi_write_semaphore, 10);
|
||||
// LOGD("spi_write inbuf=%p,len=%d,ret=%x", outbuf, len, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int spi_write_read(int fd, uint8_t *outbuf, uint8_t *inbuf, int len)
|
||||
{
|
||||
int ret;
|
||||
// spi_wait_write_read = QL_SPI_WAIT_READ;
|
||||
ret = ql_spi_write_read(fd, inbuf, outbuf, len);
|
||||
// ql_rtos_semaphore_wait(spi_read_semaphore, 10);
|
||||
// LOGD("spi_write_read inbuf=%p,outbuf=%p,len=%d,ret=%x", inbuf, outbuf, len, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gpio_mcp_int_cb(void *ctx)
|
||||
{
|
||||
ql_event_t event;
|
||||
event.id = 1000;
|
||||
if (can_task_handle)
|
||||
{
|
||||
ql_rtos_event_send(can_task_handle, &event);
|
||||
}
|
||||
|
||||
// LOGI("gpio_mcp_int_cb");
|
||||
}
|
||||
|
||||
osiTimer_t *can_led_timer = NULL;
|
||||
void can_led_timer_cb(void *param)
|
||||
{
|
||||
ql_event_t event;
|
||||
event.id = 1001;
|
||||
if (can_task_handle)
|
||||
{
|
||||
ql_rtos_event_send(can_task_handle, &event);
|
||||
}
|
||||
}
|
||||
void can_task(void *data)
|
||||
{
|
||||
int ret;
|
||||
// ret = ql_pin_set_func(QL_CUR_SPI2_CS_PIN, QUEC_PIN_SPI2_FUNC);
|
||||
// if (ret != QL_GPIO_SUCCESS)
|
||||
// {
|
||||
// LOGE("set pin err");
|
||||
// }
|
||||
// ret = ql_pin_set_func(QL_CUR_SPI2_CLK_PIN, QUEC_PIN_SPI2_FUNC);
|
||||
// if (ret != QL_GPIO_SUCCESS)
|
||||
// {
|
||||
// LOGE("set pin err");
|
||||
// }
|
||||
// ret = ql_pin_set_func(QL_CUR_SPI2_DO_PIN, QUEC_PIN_SPI2_FUNC);
|
||||
// if (ret != QL_GPIO_SUCCESS)
|
||||
// {
|
||||
// LOGE("set pin err");
|
||||
// }
|
||||
// ret = ql_pin_set_func(QL_CUR_SPI2_DI_PIN, QUEC_PIN_SPI2_FUNC);
|
||||
// if (ret != QL_GPIO_SUCCESS)
|
||||
// {
|
||||
// LOGE("set pin err");
|
||||
// }
|
||||
// ret = ql_pin_set_func(GPIO_10, 0); // set pin4 sp1_cs to gpio fun
|
||||
// if (ret != QL_GPIO_SUCCESS)
|
||||
// {
|
||||
// LOGE("set pin err");
|
||||
// }
|
||||
// ql_gpio_deinit(GPIO_10);
|
||||
// ql_gpio_init(GPIO_10, GPIO_INPUT, PULL_UP, LVL_HIGH);
|
||||
|
||||
ql_spi_config_s spi_config = {0};
|
||||
int spi_no = QL_SPI_PORT2;
|
||||
spi_config.port = spi_no;
|
||||
spi_config.spiclk = QL_SPI_CLK_6_25MHZ;
|
||||
spi_config.framesize = 8;
|
||||
spi_config.input_mode = QL_SPI_INPUT_TRUE;
|
||||
spi_config.cs_polarity0 = QL_SPI_CS_ACTIVE_LOW;
|
||||
spi_config.cs_polarity1 = QL_SPI_CS_ACTIVE_LOW;
|
||||
spi_config.cpol = QL_SPI_CPOL_LOW;
|
||||
spi_config.cpha = QL_SPI_CPHA_1Edge;
|
||||
spi_config.input_sel = QL_SPI_DI_1;
|
||||
spi_config.transmode = QL_SPI_DIRECT_POLLING;
|
||||
spi_config.cs = QL_SPI_CS0;
|
||||
spi_config.clk_delay = QL_SPI_CLK_DELAY_0;
|
||||
ql_spi_init_ext(spi_config);
|
||||
ql_spi_cs_auto(spi_no);
|
||||
// ql_rtos_semaphore_create(&spi_read_semaphore, 0);
|
||||
// ql_rtos_semaphore_create(&spi_write_semaphore, 0);
|
||||
|
||||
// ql_spi_irq_s mask = {
|
||||
// .rx_dma_done = 1,
|
||||
// .tx_dma_done = 1,
|
||||
// };
|
||||
|
||||
// ql_spi_set_irq(spi_no, mask, spi_cb_handler);
|
||||
|
||||
can_config_t can_cfg;
|
||||
memset(&can_cfg, 0, sizeof(can_cfg));
|
||||
can_cfg.baud_rate = 500000;
|
||||
can_cfg.can_mode = MODE_NORMAL;
|
||||
can_cfg.rx_ctrl[0] = RXB_RX_ANY;
|
||||
can_cfg.rx_ctrl[1] = RXB_RX_ANY;
|
||||
can_cfg.rx_mask[0] = 0x1fffffff | CAN_EFF_FLAG;
|
||||
can_cfg.rx_mask[1] = 0x1fffffff | CAN_EFF_FLAG;
|
||||
can_cfg.rx_filter[0] = 0x18FEEE00 | CAN_EFF_FLAG;
|
||||
can_cfg.rx_filter[1] = 0x18FEEF00 | CAN_EFF_FLAG;
|
||||
can_cfg.rx_filter[2] = 0X18FEE500 | CAN_EFF_FLAG;
|
||||
ret = mcp_can_init(spi_no, &can_cfg);
|
||||
if (ret != 0)
|
||||
{
|
||||
LOGE("mcp_can_init fail ret=%d\n", ret);
|
||||
}
|
||||
// ql_rtos_task_get_current_ref(&can_task_handle);
|
||||
can_task_handle = osiThreadCurrent();
|
||||
// ql_pin_set_func(15, 4); // set GPIO22
|
||||
ql_int_register(GPIO_22, EDGE_TRIGGER, DEBOUNCE_DIS, EDGE_FALLING, PULL_UP, gpio_mcp_int_cb, NULL);
|
||||
ql_int_enable(GPIO_22);
|
||||
int tx_led_status = 0;
|
||||
int rx_led_status = 0;
|
||||
// can_led_timer = osiTimerCreate(can_task_handle, can_led_timer_cb, NULL); // 创建定时器
|
||||
// if (NULL == can_led_timer)
|
||||
// {
|
||||
// LOGE("can_led_timer create failed\n");
|
||||
// osiThreadExit();
|
||||
// }
|
||||
// ret = osiTimerStart(can_led_timer, 100);
|
||||
// if (ret != TRUE)
|
||||
// {
|
||||
// LOGE("can_led_timer start failed\n");
|
||||
// }
|
||||
while (1)
|
||||
{
|
||||
ql_event_t event;
|
||||
ql_LvlMode int_value;
|
||||
if (ql_event_wait(&event, 100) != 0) // 中断有时会丢失,所以超时也读取接收缓冲区
|
||||
{
|
||||
event.id = 1000;
|
||||
ql_gpio_get_level(GPIO_22, &int_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int_value = 0;
|
||||
}
|
||||
switch (event.id)
|
||||
{
|
||||
|
||||
case 1000: {
|
||||
if (int_value == 0)
|
||||
{
|
||||
LED0_ON(spi_no);
|
||||
rx_led_status = 1;
|
||||
do
|
||||
{
|
||||
CanRxMsg RxMsg;
|
||||
if (can_read_rxbuf(spi_no, &RxMsg))
|
||||
{
|
||||
// LOGI("CAN0: Id=0x%x,IDE=%d,DLC=%d,Data=[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]", RxMsg.Id, RxMsg.IDE, RxMsg.DLC, RxMsg.Data[0], RxMsg.Data[1], RxMsg.Data[2], RxMsg.Data[3], RxMsg.Data[4], RxMsg.Data[5], RxMsg.Data[6], RxMsg.Data[7]);
|
||||
// if (can_ops[0] != NULL && can_ops[0]->parse)
|
||||
// {
|
||||
// can_status[0]->rx_cnt++;
|
||||
// can_ops[0]->parse(&RxMsg);
|
||||
// }
|
||||
}
|
||||
ql_gpio_get_level(GPIO_22, &int_value);
|
||||
} while (int_value == 0);
|
||||
LED0_OFF(spi_no);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// case 1001:
|
||||
// if (rx_led_status == 1)
|
||||
// {
|
||||
// LED0_OFF(spi_no);
|
||||
// rx_led_status = 2;
|
||||
// }
|
||||
// else if(rx_led_status == 2)
|
||||
// {
|
||||
// rx_led_status = 0;
|
||||
// }
|
||||
// if (tx_led_status == 1)
|
||||
// {
|
||||
// LED1_OFF(spi_no);
|
||||
// tx_led_status = 2;
|
||||
// }
|
||||
// else if(rx_led_status == 2)
|
||||
// {
|
||||
// rx_led_status = 0;
|
||||
// }
|
||||
// osiTimerStart(can_led_timer, 100);
|
||||
// break;
|
||||
case 0: {
|
||||
CanTxMsg TxPack = {
|
||||
.Id = 0x182,
|
||||
.IDE = CAN_ID_STD,
|
||||
.DLC = 8,
|
||||
.Data = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}};
|
||||
LED1_ON(spi_no);
|
||||
tx_led_status = 1;
|
||||
can_tx_pack(spi_no, &TxPack);
|
||||
can_status[0]->bus_status = get_mcp_status(spi_no);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
475
EC600U_can/mcp2515.c
Normal file
475
EC600U_can/mcp2515.c
Normal file
@ -0,0 +1,475 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mcp2515.h"
|
||||
#include "ql_api_spi.h"
|
||||
#include "ql_api_osi.h"
|
||||
// #include "hw.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#define LOGD(msg, ...) QL_LOG(QL_LOG_LEVEL_DEBUG, "mcp2515", msg, ##__VA_ARGS__)
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "mcp2515", msg, ##__VA_ARGS__)
|
||||
#define LOGW(msg, ...) QL_LOG(QL_LOG_LEVEL_WARN, "mcp2515", msg, ##__VA_ARGS__)
|
||||
#define LOGE(msg, ...) QL_LOG(QL_LOG_LEVEL_ERROR, "mcp2515", msg, ##__VA_ARGS__)
|
||||
|
||||
extern struct can_status *can_status[2];
|
||||
|
||||
#define mcp_cs(fd) // ql_spi_cs_low(fd)
|
||||
#define mcp_ncs(fd) // ql_spi_cs_high(fd)
|
||||
|
||||
static uint8_t spi_txbuf[32] __attribute__((aligned(32)));
|
||||
static uint8_t spi_rxbuf[32] __attribute__((aligned(32)));
|
||||
unsigned char spi_put(unsigned char);
|
||||
|
||||
void mcp_wr_can_eid(int fd, unsigned char add, unsigned long can_id)
|
||||
{
|
||||
unsigned char txbuf[4];
|
||||
uint16_t canid;
|
||||
canid = (uint16_t)can_id;
|
||||
txbuf[EID0] = canid & 0xff;
|
||||
txbuf[EID8] = (canid >> 8) & 0xff;
|
||||
canid = (uint16_t)(can_id >> 16);
|
||||
|
||||
txbuf[SIDL] = canid & 0x03;
|
||||
canid = canid << 3;
|
||||
txbuf[SIDL] |= (canid & 0xe0);
|
||||
txbuf[SIDL] |= 0x8;
|
||||
txbuf[SIDH] = canid >> 8;
|
||||
mcp_wrs(fd, add, txbuf, 4);
|
||||
}
|
||||
|
||||
unsigned long mcp_rd_can_eid(int fd, unsigned char add)
|
||||
{
|
||||
unsigned char rcbuf[4];
|
||||
uint32_t can_id;
|
||||
uint16_t canid;
|
||||
mcp_rds(fd, add, rcbuf, 4);
|
||||
can_id = rcbuf[EID0] + (rcbuf[EID8] << 8);
|
||||
canid = rcbuf[SIDL] + (rcbuf[SIDH] << 8);
|
||||
canid = canid >> 3;
|
||||
canid |= (rcbuf[SIDL] & 0x03);
|
||||
can_id |= (canid << 16);
|
||||
return can_id;
|
||||
}
|
||||
|
||||
void mcp_wr_can_id(int fd, unsigned char add, unsigned int CanId)
|
||||
{
|
||||
unsigned char txbuf[4];
|
||||
uint16_t sid;
|
||||
uint32_t eid;
|
||||
if (CanId & CAN_EFF_FLAG) // eid
|
||||
{
|
||||
sid = (CanId >> 18) & 0x7ff;
|
||||
eid = CanId & 0x3ffff;
|
||||
txbuf[SIDH] = (uint8_t)(sid >> 3);
|
||||
txbuf[SIDL] = (sid << 5) & 0xe0;
|
||||
txbuf[SIDL] |= (1 << 3);
|
||||
txbuf[SIDL] |= (eid >> 16);
|
||||
txbuf[EID8] = (eid >> 8) & 0xff;
|
||||
txbuf[EID0] = eid & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
sid = CanId & 0x7ff;
|
||||
txbuf[SIDH] = (uint8_t)(sid >> 3);
|
||||
txbuf[SIDL] = (sid << 5) & 0xe0;
|
||||
txbuf[EID8] = 0;
|
||||
txbuf[EID0] = 0;
|
||||
}
|
||||
mcp_wrs(fd, add, txbuf, 4);
|
||||
}
|
||||
unsigned int mcp_rd_can_id(int fd, unsigned char add)
|
||||
{
|
||||
unsigned int CanId;
|
||||
unsigned char rcbuf[4];
|
||||
mcp_rds(fd, add, rcbuf, 4);
|
||||
CanId = (rcbuf[SIDL] + (rcbuf[SIDH] << 8));
|
||||
CanId >>= 5;
|
||||
CanId &= 0x7ff;
|
||||
if (rcbuf[SIDL] & (1 << 3))
|
||||
{
|
||||
unsigned int eid;
|
||||
eid = rcbuf[EID0] | (rcbuf[EID8] << 8);
|
||||
eid |= (rcbuf[SIDL] & 0x03) << 16;
|
||||
CanId <<= 18;
|
||||
CanId |= eid;
|
||||
CanId |= CAN_EFF_FLAG;
|
||||
}
|
||||
return CanId;
|
||||
}
|
||||
void mcp_reset(int fd)
|
||||
{
|
||||
mcp_cs(fd);
|
||||
spi_txbuf[0] = RESET;
|
||||
spi_write(fd, spi_txbuf, 1);
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
// 单字节写
|
||||
void mcp_wr(int fd, unsigned char add, unsigned char DAT)
|
||||
{
|
||||
spi_txbuf[0] = WRITE;
|
||||
spi_txbuf[1] = add;
|
||||
spi_txbuf[2] = DAT;
|
||||
mcp_cs(fd);
|
||||
spi_write(fd, spi_txbuf, 3);
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
// 多字节写
|
||||
void mcp_wrs(int fd, unsigned char add, unsigned char *wr_dat, unsigned char length)
|
||||
{
|
||||
spi_txbuf[0] = WRITE;
|
||||
spi_txbuf[1] = add;
|
||||
mcp_cs(fd);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
spi_txbuf[i + 2] = wr_dat[i];
|
||||
}
|
||||
spi_write(fd, spi_txbuf, length + 2);
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
// 单字节读
|
||||
unsigned char mcp_rd(int fd, unsigned char add)
|
||||
{
|
||||
spi_txbuf[0] = READ;
|
||||
spi_txbuf[1] = add;
|
||||
spi_txbuf[2] = 0;
|
||||
mcp_cs(fd);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, 3);
|
||||
mcp_ncs(fd);
|
||||
return (spi_rxbuf[2]);
|
||||
}
|
||||
// 多字节读
|
||||
void mcp_rds(int fd, unsigned char add, unsigned char *DAT, unsigned char length)
|
||||
{
|
||||
spi_txbuf[0] = READ;
|
||||
spi_txbuf[1] = add;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
spi_txbuf[2 + i] = 0;
|
||||
}
|
||||
mcp_cs(fd);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, length + 2);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
*DAT++ = spi_rxbuf[2 + i];
|
||||
}
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
// 发送请求
|
||||
void rts(int fd, unsigned char ch)
|
||||
{
|
||||
ch &= 0x7;
|
||||
ch |= 0x80;
|
||||
spi_txbuf[0] = ch;
|
||||
mcp_cs(fd);
|
||||
spi_write(fd, spi_txbuf, 1);
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
// 状态读
|
||||
unsigned char get_mcp_status(int fd)
|
||||
{
|
||||
spi_txbuf[0] = STATUS;
|
||||
spi_txbuf[1] = 0;
|
||||
mcp_cs(fd);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, 2);
|
||||
mcp_ncs(fd);
|
||||
return (spi_rxbuf[1]);
|
||||
}
|
||||
void mcp_wr_bit(int fd, unsigned char add, unsigned char DAT, unsigned char mask)
|
||||
{
|
||||
spi_txbuf[0] = 0x05;
|
||||
spi_txbuf[1] = add;
|
||||
spi_txbuf[2] = mask;
|
||||
spi_txbuf[3] = DAT;
|
||||
mcp_cs(fd);
|
||||
spi_write(fd, spi_txbuf, 4);
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
void mcp_rd_rxbuf(int fd, unsigned char buf, unsigned char *DAT, unsigned char length)
|
||||
{
|
||||
buf <<= 1;
|
||||
buf &= 0x06;
|
||||
buf |= 0x90;
|
||||
spi_txbuf[0] = buf;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
spi_txbuf[i + 1] = 0;
|
||||
}
|
||||
mcp_cs(fd);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, length + 1);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
*DAT++ = spi_rxbuf[1 + i];
|
||||
}
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
|
||||
void mcp_ld_txbuf(int fd, unsigned char buf, unsigned char *DAT, unsigned char length)
|
||||
{
|
||||
mcp_cs(fd);
|
||||
buf &= 0x07;
|
||||
buf |= 0x40;
|
||||
spi_txbuf[0] = buf;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
spi_txbuf[i + 1] = 0;
|
||||
}
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, length + 1);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
*DAT++ = spi_rxbuf[i + 1];
|
||||
}
|
||||
|
||||
mcp_ncs(fd);
|
||||
}
|
||||
unsigned char get_mcp_rxstatus(int fd)
|
||||
{
|
||||
spi_txbuf[0] = 0xb0;
|
||||
spi_txbuf[1] = 0;
|
||||
mcp_cs(fd);
|
||||
spi_write_read(fd, spi_txbuf, spi_rxbuf, 2);
|
||||
mcp_ncs(fd);
|
||||
return spi_rxbuf[1];
|
||||
}
|
||||
|
||||
int mcp_can_init(int ch, can_config_t *cfg)
|
||||
{
|
||||
// uint8_t value;
|
||||
int can_clock = 24000000;
|
||||
uint8_t brp;
|
||||
int bit_time;
|
||||
mcp_reset(ch);
|
||||
ql_rtos_task_sleep_ms(20);
|
||||
mcp_wr(ch, CANCTRL, MODE_CONFIG);
|
||||
if (mcp_rd(ch, CANCTRL) != MODE_CONFIG)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bit_time = can_clock / 2 / cfg->baud_rate;
|
||||
if (bit_time % 12 == 0) // ±ê×¼²¨ÌØÂÊ 125,250,500,10000
|
||||
{
|
||||
mcp_wr(ch, CNF2, BTLMODE_CNF3 + SEG3 * 8 + SEG5);
|
||||
mcp_wr(ch, CNF3, SEG3);
|
||||
brp = bit_time / 12 - 1;
|
||||
if (brp > 7)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
mcp_wr(ch, CNF1, SJW1 + brp);
|
||||
}
|
||||
else if (bit_time % 15 == 0) // 100,200,400,800
|
||||
{
|
||||
mcp_wr(ch, CNF2, BTLMODE_CNF3 + SEG4 * 8 + SEG6);
|
||||
mcp_wr(ch, CNF3, SEG4);
|
||||
brp = bit_time / 15 - 1;
|
||||
if (brp > 7)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
mcp_wr(ch, CNF1, SJW1 + brp);
|
||||
}
|
||||
else if (bit_time % 16 == 0) // 750,325
|
||||
{
|
||||
mcp_wr(ch, CNF2, BTLMODE_CNF3 + SEG5 * 8 + SEG6);
|
||||
mcp_wr(ch, CNF3, SEG4);
|
||||
brp = bit_time / 16 - 1;
|
||||
if (brp > 7)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
mcp_wr(ch, CNF1, SJW1 + brp);
|
||||
}
|
||||
else // ²»Ö§³ÖµÄ²¨ÌØÂÊ
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
mcp_wr(ch, RXB0CTRL, cfg->rx_ctrl[0]); // Â˲¨Æ÷0
|
||||
mcp_wr_can_id(ch, RXM0SIDH, cfg->rx_mask[0]);
|
||||
mcp_wr_can_id(ch, RXF0SIDH, cfg->rx_filter[0]);
|
||||
|
||||
mcp_wr(ch, RXB1CTRL, cfg->rx_ctrl[1]); // Â˲¨Æ÷1
|
||||
mcp_wr_can_id(ch, RXF1SIDH, cfg->rx_filter[1]);
|
||||
mcp_wr_can_id(ch, RXM1SIDH, cfg->rx_mask[1]);
|
||||
mcp_wr_can_id(ch, RXF2SIDH, cfg->rx_filter[2]);
|
||||
mcp_wr_can_id(ch, RXF3SIDH, cfg->rx_filter[3]);
|
||||
mcp_wr_can_id(ch, RXF4SIDH, cfg->rx_filter[4]);
|
||||
mcp_wr_can_id(ch, RXF5SIDH, cfg->rx_filter[5]);
|
||||
|
||||
mcp_wr(ch, CANINTE, 0x03);
|
||||
mcp_wr(ch, CANINTF, 0x00);
|
||||
|
||||
mcp_wr_bit(ch, TXRTSCTRL, 0x0, 0xff);
|
||||
mcp_wr_bit(ch, BFPCTRL, 0x3c, 0xff);
|
||||
mcp_wr(ch, CANCTRL, (cfg->can_mode & 0xf0));
|
||||
LED0_ON(ch);
|
||||
LED1_ON(ch);
|
||||
LOGD("[%s] can%d init ok", __FUNCTION__, ch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int can_read_rxbuf(int ch, CanRxMsg *RxMsg)
|
||||
{
|
||||
unsigned char status;
|
||||
uint32_t can_id;
|
||||
status = get_mcp_rxstatus(ch);
|
||||
if (status & 0x40)
|
||||
{
|
||||
RxMsg->Id = mcp_rd_can_id(ch, 0x61);
|
||||
if (RxMsg->Id & (1 << 31))
|
||||
{
|
||||
RxMsg->Id &= 0x1fffffff;
|
||||
RxMsg->IDE = CAN_Id_Extended;
|
||||
}
|
||||
else
|
||||
{
|
||||
RxMsg->Id &= 0x7ff;
|
||||
RxMsg->IDE = CAN_Id_Standard;
|
||||
}
|
||||
RxMsg->DLC = mcp_rd(ch, 0x65);
|
||||
if (RxMsg->DLC & 0x40)
|
||||
{
|
||||
RxMsg->DLC = 0;
|
||||
RxMsg->RTR = 1;
|
||||
goto ret1; // Ë͵½rtr
|
||||
}
|
||||
RxMsg->RTR = 0;
|
||||
if (RxMsg->DLC > 8)
|
||||
{
|
||||
RxMsg->DLC = 8;
|
||||
}
|
||||
mcp_rd_rxbuf(ch, 0x1, RxMsg->Data, RxMsg->DLC);
|
||||
ret1:
|
||||
mcp_wr_bit(ch, CANINTF, 0x00, 0x01);
|
||||
return 1;
|
||||
}
|
||||
if (status & 0x80)
|
||||
{
|
||||
RxMsg->Id = mcp_rd_can_id(ch, 0x71);
|
||||
if (can_id & (1 << 31))
|
||||
{
|
||||
RxMsg->Id &= 0x1fffffff;
|
||||
RxMsg->IDE = CAN_Id_Extended;
|
||||
}
|
||||
else
|
||||
{
|
||||
RxMsg->Id &= 0x7ff;
|
||||
RxMsg->IDE = CAN_Id_Standard;
|
||||
}
|
||||
RxMsg->DLC = mcp_rd(ch, 0x75);
|
||||
if (RxMsg->DLC & 0x40)
|
||||
{
|
||||
RxMsg->DLC = 0;
|
||||
RxMsg->RTR = 1;
|
||||
goto ret2; // ÊÕµ½rtr
|
||||
}
|
||||
RxMsg->RTR = 0;
|
||||
if (RxMsg->DLC > 8)
|
||||
{
|
||||
RxMsg->DLC = 8;
|
||||
}
|
||||
mcp_rd_rxbuf(ch, 0x3, RxMsg->Data, RxMsg->DLC);
|
||||
ret2:
|
||||
mcp_wr_bit(ch, CANINTF, 0x00, 0x02);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int can_tx_pack(int ch, CanTxMsg *TxPack)
|
||||
{
|
||||
// #ifdef _CAN_DEBUG_
|
||||
// char msg[256];
|
||||
// int i;
|
||||
// int n = sprintf(msg, "CAN%d Tx: Id=0x%x,IDE=%x,DLC=%d,Data=[", ch, TxPack->Id, TxPack->IDE, TxPack->DLC);
|
||||
// for (i = 0; i < TxPack->DLC; i++)
|
||||
// {
|
||||
// n += sprintf(&msg[n], "%02x ", TxPack->Data[i]);
|
||||
// }
|
||||
// msg[n - 1] = ']';
|
||||
// eat_trace(msg);
|
||||
// #endif
|
||||
can_status[0]->tx_cnt++;
|
||||
if (!(mcp_rd(ch, 0x30) & 0x08))
|
||||
{ // ·¢ËÍ»º³åÇø0¿Õ£¿
|
||||
LED1_ON(ch);
|
||||
if (TxPack->IDE == CAN_Id_Extended)
|
||||
{
|
||||
TxPack->Id |= (1 << 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
TxPack->Id &= 0x7ff;
|
||||
}
|
||||
mcp_wr_can_id(ch, 0x31, TxPack->Id);
|
||||
if (TxPack->RTR)
|
||||
{
|
||||
mcp_wr(ch, 0x35, 0x40); // ·¢ËÍRTR
|
||||
}
|
||||
else
|
||||
{
|
||||
mcp_wr(ch, 0x35, TxPack->DLC);
|
||||
mcp_ld_txbuf(ch, 0x1, (uint8_t *)&TxPack->Data[0], TxPack->DLC);
|
||||
}
|
||||
rts(ch, 1);
|
||||
LED1_OFF(ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (!(mcp_rd(ch, 0x40) & 0x08))
|
||||
{ // ·¢ËÍ»º³åÇø1¿Õ£¿
|
||||
LED1_ON(ch);
|
||||
if (TxPack->IDE == CAN_Id_Extended)
|
||||
{
|
||||
TxPack->Id |= (1 << 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
TxPack->Id &= 0x7ff;
|
||||
}
|
||||
mcp_wr_can_id(ch, 0x41, TxPack->Id);
|
||||
if (TxPack->RTR)
|
||||
{
|
||||
mcp_wr(ch, 0x45, 0x40); // ·¢ËÍRTR
|
||||
}
|
||||
else
|
||||
{
|
||||
mcp_wr(ch, 0x45, TxPack->DLC);
|
||||
mcp_ld_txbuf(ch, 0x3, (uint8_t *)&TxPack->Data[0], TxPack->DLC);
|
||||
}
|
||||
rts(ch, 2);
|
||||
LED1_OFF(ch);
|
||||
return 0;
|
||||
}
|
||||
if (!(mcp_rd(ch, 0x50) & 0x08))
|
||||
{ // ·¢ËÍ»º³åÇø2¿Õ£¿
|
||||
LED1_ON(ch);
|
||||
if (TxPack->IDE == CAN_Id_Extended)
|
||||
{
|
||||
TxPack->Id |= (1 << 31);
|
||||
}
|
||||
else
|
||||
{
|
||||
TxPack->Id &= 0x7ff;
|
||||
}
|
||||
mcp_wr_can_id(ch, 0x51, TxPack->Id);
|
||||
if (TxPack->RTR)
|
||||
{
|
||||
mcp_wr(ch, 0x55, 0x40); // ·¢ËÍRTR
|
||||
}
|
||||
else
|
||||
{
|
||||
mcp_wr(ch, 0x55, TxPack->DLC);
|
||||
mcp_ld_txbuf(ch, 0x5, (uint8_t *)&TxPack->Data[0], TxPack->DLC);
|
||||
}
|
||||
rts(ch, 4);
|
||||
LED1_OFF(ch);
|
||||
return 0;
|
||||
}
|
||||
if (mcp_rd(ch, EFLG) & (1 << 5))
|
||||
{
|
||||
mcp_wr(ch, TEC, 0);
|
||||
}
|
||||
return 1; // ·¢ËÍ»º³åÇøÂú,·¢ËÍʧ°Ü
|
||||
}
|
354
EC600U_can/mcp2515.h
Normal file
354
EC600U_can/mcp2515.h
Normal file
@ -0,0 +1,354 @@
|
||||
|
||||
#ifndef _2515_H
|
||||
#define _2515_H
|
||||
/*
|
||||
** Register offsets into the transmit buffers.
|
||||
*/
|
||||
#define TXBnCTRL 0
|
||||
#define TXBnSIDH 1
|
||||
#define TXBnSIDL 2
|
||||
#define TXBnEID8 3
|
||||
#define TXBnEID0 4
|
||||
#define TXBnDLC 5
|
||||
#define TXBnD0 6
|
||||
#define TXBnD1 7
|
||||
#define TXBnD2 8
|
||||
#define TXBnD3 9
|
||||
#define TXBnD4 10
|
||||
#define TXBnD5 11
|
||||
#define TXBnD6 12
|
||||
#define TXBnD7 13
|
||||
#define CANSTAT 14
|
||||
#define CANCTRL 15
|
||||
|
||||
#define SIDH 0
|
||||
#define SIDL 1
|
||||
#define EID8 2
|
||||
#define EID0 3
|
||||
|
||||
/*
|
||||
** Register offsets into the receive buffers.
|
||||
*/
|
||||
#define RXBnCTRL 0
|
||||
#define RXBnSIDH 1
|
||||
#define RXBnSIDL 2
|
||||
#define RXBnEID8 3
|
||||
#define RXBnEID0 4
|
||||
#define RXBnDLC 5
|
||||
#define RXBnD0 6
|
||||
#define RXBnD1 7
|
||||
#define RXBnD2 8
|
||||
#define RXBnD3 9
|
||||
#define RXBnD4 10
|
||||
#define RXBnD5 11
|
||||
#define RXBnD6 12
|
||||
#define RXBnD7 13
|
||||
|
||||
/*
|
||||
** Bits in the TXBnCTRL registers.
|
||||
*/
|
||||
#define TXB_TXBUFE_M 0x80
|
||||
#define TXB_ABTF_M 0x40
|
||||
#define TXB_MLOA_M 0x20
|
||||
#define TXB_TXERR_M 0x10
|
||||
#define TXB_TXREQ_M 0x08
|
||||
#define TXB_TXIE_M 0x04
|
||||
#define TXB_TXP10_M 0x03
|
||||
|
||||
#define DLC_MASK 0x0F
|
||||
#define RTR_MASK 0x40
|
||||
|
||||
#define TXB0CTRL 0x30
|
||||
#define TXB0SIDH 0x31
|
||||
|
||||
#define TXB1CTRL 0x40
|
||||
#define TXB1SIDH 0x41
|
||||
|
||||
#define TXB2CTRL 0x50
|
||||
#define TXB2SIDH 0x51
|
||||
|
||||
#define TXPRIOHIGH 0x03
|
||||
#define TXPRIOHIGHLOW 0x02
|
||||
#define TXPRIOLOWHIGH 0x01
|
||||
#define TXPRIOLOW 0x00
|
||||
|
||||
#define TXB_EXIDE_M 0x08 // In TXBnSIDL
|
||||
#define TXB_RTR_M 0x40 // In TXBnDLC
|
||||
|
||||
#define RXB_IDE_M 0x08 // In RXBnSIDL
|
||||
#define RXB_RTR_M 0x40 // In RXBnDLC
|
||||
|
||||
#define BFPCTRL 0x0C
|
||||
|
||||
#define B2RTS 0x20
|
||||
#define B1RTS 0x10
|
||||
#define B0RTS 0x08
|
||||
#define B2RTSM 0x04
|
||||
#define B1RTSM 0x02
|
||||
#define B0RTSM 0x01
|
||||
|
||||
#define TEC 0x1C
|
||||
#define REC 0x1D
|
||||
#define CLKCTRL CANCTRL
|
||||
|
||||
#define RXF0SIDH 0
|
||||
#define RXF0SIDL 1
|
||||
#define RXF0EID8 2
|
||||
#define RXF0EID0 3
|
||||
#define RXF1SIDH 4
|
||||
#define RXF1SIDL 5
|
||||
#define RXF1EID8 6
|
||||
#define RXF1EID0 7
|
||||
#define RXF2SIDH 8
|
||||
#define RXF2SIDL 9
|
||||
#define RXF2EID8 10
|
||||
#define RXF2EID0 11
|
||||
|
||||
#define RXF3SIDH 16
|
||||
#define RXF3SIDL 17
|
||||
#define RXF3EID8 18
|
||||
#define RXF3EID0 19
|
||||
#define RXF4SIDH 20
|
||||
#define RXF4SIDL 21
|
||||
#define RXF4EID8 22
|
||||
#define RXF4EID0 23
|
||||
#define RXF5SIDH 24
|
||||
#define RXF5SIDL 25
|
||||
#define RXF5EID8 26
|
||||
#define RXF5EID0 27
|
||||
|
||||
#define RXF_EXIDE_M 0x08
|
||||
|
||||
#define RXM0SIDH 0x20
|
||||
#define RXM1SIDH 0x24
|
||||
#define CNF3 0x28
|
||||
#define CNF2 0x29
|
||||
#define CNF1 0x2A
|
||||
#define CANINTE 0x2B
|
||||
#define CANINTF 0x2C
|
||||
#define EFLG 0x2D
|
||||
#define TXRTSCTRL 0x0D
|
||||
|
||||
#define EFLG_RX1OVR 0x80
|
||||
#define EFLG_RX0OVR 0x40
|
||||
#define EFLG_TXBO 0x20
|
||||
#define EFLG_TXEP 0x10
|
||||
#define EFLG_RXEP 0x08
|
||||
#define EFLG_TXWAR 0x04
|
||||
#define EFLG_RXWAR 0x02
|
||||
#define EFLG_EWARN 0x01
|
||||
|
||||
#define SJW1 0x00
|
||||
#define SJW2 0x40
|
||||
#define SJW3 0x80
|
||||
#define SJW4 0xC0
|
||||
|
||||
#define BTLMODE_CNF3 0x80
|
||||
|
||||
#define SAMP1 0x00
|
||||
#define SAMP3 0x40
|
||||
|
||||
#define SEG1 0x00
|
||||
#define SEG2 0x01
|
||||
#define SEG3 0x02
|
||||
#define SEG4 0x03
|
||||
#define SEG5 0x04
|
||||
#define SEG6 0x05
|
||||
#define SEG7 0x06
|
||||
#define SEG8 0x07
|
||||
|
||||
#define BRP1 0x00
|
||||
#define BRP2 0x01
|
||||
#define BRP3 0x02
|
||||
#define BRP4 0x03
|
||||
#define BRP5 0x04
|
||||
#define BRP6 0x05
|
||||
#define BRP7 0x06
|
||||
#define BRP8 0x07
|
||||
|
||||
#define IVRIE 0x80
|
||||
#define WAKIE 0x40
|
||||
#define ERRIE 0x20
|
||||
#define TX2IE 0x10
|
||||
#define TX1IE 0x08
|
||||
#define TX0IE 0x04
|
||||
#define RX1IE 0x02
|
||||
#define RX0IE 0x01
|
||||
#define NO_IE 0x00
|
||||
|
||||
#define IVRINT 0x80
|
||||
#define WAKINT 0x40
|
||||
#define ERRINT 0x20
|
||||
#define TX2INT 0x10
|
||||
#define TX1INT 0x08
|
||||
#define TX0INT 0x04
|
||||
#define RX1INT 0x02
|
||||
#define RX0INT 0x01
|
||||
#define NO_INT 0x00
|
||||
|
||||
#define RXB0CTRL 0x60
|
||||
#define RXB1CTRL 0x70
|
||||
|
||||
#define RXB_RXRDY 0x80
|
||||
#define RXB_RXM1 0x40
|
||||
#define RXB_RXM0 0x20
|
||||
#define RXB_RX_ANY 0x60
|
||||
#define RXB_RX_EXT 0x40
|
||||
#define RXB_RX_STD 0x20
|
||||
#define RXB_RX_STDEXT 0x00
|
||||
#define RXB_RXMx_M 0x60
|
||||
// #define RXB_RXIE_M 0x10
|
||||
#define RXB_RXRTR 0x08 // In RXBnCTRL
|
||||
#define RXB_BUKT 0x04
|
||||
#define RXB_BUKT_RO 0x02
|
||||
|
||||
#define RXB_FILHIT 0x01
|
||||
#define RXB_FILHIT2 0x04
|
||||
#define RXB_FILHIT1 0x02
|
||||
#define RXB_FILHIT_M 0x07
|
||||
#define RXB_RXF5 0x05
|
||||
#define RXB_RXF4 0x04
|
||||
#define RXB_RXF3 0x03
|
||||
#define RXB_RXF2 0x02
|
||||
#define RXB_RXF1 0x01
|
||||
#define RXB_RXF0 0x00
|
||||
|
||||
#define CLKEN 0x04
|
||||
|
||||
#define CLK1 0x00
|
||||
#define CLK2 0x01
|
||||
#define CLK4 0x02
|
||||
#define CLK8 0x03
|
||||
|
||||
#define MODE_NORMAL 0x00
|
||||
#define MODE_SLEEP 0x20
|
||||
#define MODE_LOOPBACK 0x40
|
||||
#define MODE_LISTENONLY 0x60
|
||||
#define MODE_CONFIG 0xE0
|
||||
#define ABORT 0x10
|
||||
|
||||
#define RECEIVE_BUFFER(x) (0x60 + 0x10 * (x))
|
||||
#define TRANSMIT_BUFFER(x) (0x30 + 0x10 * (x))
|
||||
#define RESET 0xc0 // Reset internal registers to default state, set conf mode
|
||||
#define RTS 0x80 // Trigg transmission
|
||||
#define RD_STAT 0xA0 // Start reading status
|
||||
#define BIT_MOD 0x05 // Bit modify command data == MASK, BITS
|
||||
#define READ 0x03 // Read data from memory
|
||||
#define WRITE 0x02 // Write data to memory
|
||||
#define STATUS 0xa0
|
||||
#define LED0_ON(fd) mcp_wr_bit(fd, BFPCTRL, 0Xff, 0x10)
|
||||
#define LED1_ON(fd) mcp_wr_bit(fd, BFPCTRL, 0Xff, 0x20)
|
||||
#define LED0_OFF(fd) mcp_wr_bit(fd, BFPCTRL, 0X00, 0x10)
|
||||
#define LED1_OFF(fd) mcp_wr_bit(fd, BFPCTRL, 0X00, 0x20)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Id; /*!< Specifies the standard identifier.
|
||||
This parameter can be a value between 0 to 0x7FF. */
|
||||
|
||||
uint8_t IDE; /*!< Specifies the type of identifier for the message that
|
||||
will be received. This parameter can be a value of
|
||||
@ref CAN_identifier_type */
|
||||
|
||||
uint8_t RTR; /*!< Specifies the type of frame for the received message.
|
||||
This parameter can be a value of
|
||||
@ref CAN_remote_transmission_request */
|
||||
|
||||
uint8_t DLC; /*!< Specifies the length of the frame that will be received.
|
||||
This parameter can be a value between 0 to 8 */
|
||||
|
||||
uint8_t FMI; /*!< Specifies the index of the filter the message stored in
|
||||
the mailbox passes through. This parameter can be a
|
||||
value between 0 to 0xFF */
|
||||
|
||||
uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to
|
||||
0xFF. */
|
||||
|
||||
} CanRxMsg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Id; /*!< Specifies the standard identifier.
|
||||
This parameter can be a value between 0 to 0x7FF. */
|
||||
|
||||
uint8_t IDE; /*!< Specifies the type of identifier for the message that
|
||||
will be transmitted. This parameter can be a value
|
||||
of @ref CAN_identifier_type */
|
||||
|
||||
uint8_t RTR; /*!< Specifies the type of frame for the message that will
|
||||
be transmitted. This parameter can be a value of
|
||||
@ref CAN_remote_transmission_request */
|
||||
|
||||
uint8_t DLC; /*!< Specifies the length of the frame that will be
|
||||
transmitted. This parameter can be a value between
|
||||
0 to 8 */
|
||||
uint8_t Rsv;
|
||||
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0
|
||||
to 0xFF. */
|
||||
} CanTxMsg;
|
||||
|
||||
#define CAN_Id_Standard ((uint32_t)0x00000000) /*!< Standard Id */
|
||||
#define CAN_Id_Extended ((uint32_t)0x00000004) /*!< Extended Id */
|
||||
|
||||
#define CAN_ID_STD CAN_Id_Standard
|
||||
#define CAN_ID_EXT CAN_Id_Extended
|
||||
#define CAN_EFF_FLAG 0x80000000U // 扩展帧的标识
|
||||
#define CAN_RTR_FLAG 0x40000000U // 远程帧的标识
|
||||
#define CAN_ERR_FLAG 0x20000000U // 错误帧的标识,用于错误检查
|
||||
// extern void mcp_cs(int fd);
|
||||
// extern void mcp_ncs(int fd);
|
||||
int spi_write(int fd, uint8_t *spi_txbuf, int len);
|
||||
int spi_write_read(int fd, uint8_t *spi_txbuf, uint8_t *spi_rxbuf, int len);
|
||||
// void mcp_rd_can ( unsigned char buffer, unsigned char * ext, unsigned long* can_id,unsigned char * dlc, unsigned char * rtr, unsigned char * data );
|
||||
|
||||
// void mcp_wr_can_id ( unsigned char mcp_addr,unsigned long);
|
||||
// unsigned long mcp_rd_can_id ( unsigned char mcp_addr);
|
||||
void mcp_wr_can_id(int fd, unsigned char, unsigned int);
|
||||
unsigned int mcp_rd_can_id(int fd, unsigned char);
|
||||
void mcp_reset(int fd);
|
||||
unsigned char mcp_rd(int fd, unsigned char);
|
||||
void mcp_rds(int fd, unsigned char, unsigned char *, unsigned char);
|
||||
void mcp_wr(int fd, unsigned char, unsigned char);
|
||||
void mcp_wrs(int fd, unsigned char, unsigned char *, unsigned char);
|
||||
unsigned char mcp_rd(int fd, unsigned char);
|
||||
void mcp_write_tbuf(int fd, unsigned char value);
|
||||
// void mcp_write_can (unsigned char buffer, unsigned char ext, unsigned long can_id,
|
||||
// unsigned char dlc, unsigned char rtr, const unsigned char * data );
|
||||
void mcp_transmit(int fd, unsigned char buffer);
|
||||
// void mcp_init(int fd);
|
||||
void mcp_write(int fd, unsigned char MCPaddr, const unsigned char *writedata, unsigned char length);
|
||||
void mcp_ld_txbuf(int fd, unsigned char buf, unsigned char *DAT, unsigned char length);
|
||||
|
||||
void rts(int fd, unsigned char);
|
||||
void mcp_wr_bit(int fd, unsigned char add, unsigned char DAT, unsigned char mask);
|
||||
unsigned char get_mcp_rxstatus(int fd);
|
||||
void mcp_rd_rxbuf(int fd, unsigned char buf, unsigned char *DAT, unsigned char length);
|
||||
// uint8_t spi_write(uint8_t *data, uint8_t length);
|
||||
// uint8_t spi_read(uint8_t *data, uint8_t length);
|
||||
// uint8_t spi_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, uint8_t rlen);
|
||||
|
||||
|
||||
|
||||
typedef struct can_config
|
||||
{
|
||||
uint32_t baud_rate;
|
||||
uint8_t rx_ctrl[2];
|
||||
uint16_t can_mode;
|
||||
uint32_t rx_mask[2];
|
||||
uint32_t rx_filter[6];
|
||||
} can_config_t;
|
||||
|
||||
struct can_status
|
||||
{
|
||||
uint8_t bus_status;
|
||||
uint8_t status;
|
||||
uint16_t rx_cnt;
|
||||
uint16_t tx_cnt;
|
||||
};
|
||||
|
||||
|
||||
int mcp_can_init(int ch, can_config_t *cfg);
|
||||
int can_tx_pack(int ch, CanTxMsg *TxPack);
|
||||
int can_read_rxbuf(int ch, CanRxMsg *RxMsg);
|
||||
unsigned char get_mcp_status(int fd);
|
||||
#endif
|
19
EC600U_lora/CMakeLists.txt
Normal file
19
EC600U_lora/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
set(target ec600u_lora)
|
||||
|
||||
add_library(${target} STATIC)
|
||||
set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
# target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
target_include_directories(${target} PUBLIC inc)
|
||||
include_directories(${SOURCE_TOP_DIR}/components/app/t2n/include)
|
||||
target_link_libraries(${target} PUBLIC)
|
||||
|
||||
target_sources(${target} PUBLIC
|
||||
lora_app.c
|
||||
lora_test.c
|
||||
lora_test_function.c
|
||||
user.c
|
||||
lora.c
|
||||
)
|
||||
|
||||
relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
beautify_c_code(${target} ${srcs})
|
27
EC600U_lora/inc/lora.h
Normal file
27
EC600U_lora/inc/lora.h
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*获取同步字*/
|
||||
uint16_t lora_get_syncword(void);
|
||||
|
||||
/*设置standby模式*/
|
||||
void lora_set_standby(uint8_t data);
|
||||
|
||||
/*lora模块初始化函数*/
|
||||
int lora_init(void);
|
||||
|
||||
/*启动lora通讯*/
|
||||
int lora_start(void);
|
||||
|
||||
/*设置radio参数*/
|
||||
int lora_radioConfig(void);
|
||||
|
||||
/*获取中断状态*/
|
||||
uint16_t lora_get_irq_status(void);
|
||||
|
||||
/*清除中断状态*/
|
||||
void lora_clear_irq_status(uint16_t irq_status);
|
1
EC600U_lora/inc/lora_app.h
Normal file
1
EC600U_lora/inc/lora_app.h
Normal file
@ -0,0 +1 @@
|
||||
void lora_app_init(void);
|
57
EC600U_lora/inc/lora_test.h
Normal file
57
EC600U_lora/inc/lora_test.h
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
/*!
|
||||
* \brief Represents all possible opcode understood by the radio
|
||||
*/
|
||||
|
||||
//cmd
|
||||
#define RADIO_GET_STATUS 0xC0
|
||||
#define RADIO_WRITE_REGISTER 0x0D
|
||||
#define RADIO_READ_REGISTER 0x1D
|
||||
#define RADIO_WRITE_BUFFER 0x0E
|
||||
#define RADIO_READ_BUFFER 0x1E
|
||||
#define RADIO_SET_SLEEP 0x84
|
||||
#define RADIO_SET_STANDBY 0x80
|
||||
#define RADIO_SET_FS 0xC1
|
||||
#define RADIO_SET_TX 0x83
|
||||
#define RADIO_SET_RX 0x82
|
||||
#define RADIO_SET_RXDUTYCYCLE 0x94
|
||||
#define RADIO_SET_CAD 0xC5
|
||||
#define RADIO_SET_TXCONTINUOUSWAVE 0xD1
|
||||
#define RADIO_SET_TXCONTINUOUSPREAMBLE 0xD2
|
||||
#define RADIO_SET_PACKETTYPE 0x8A
|
||||
#define RADIO_GET_PACKETTYPE 0x11
|
||||
#define RADIO_SET_RFFREQUENCY 0x86
|
||||
#define RADIO_SET_TXPARAMS 0x8E
|
||||
#define RADIO_SET_PACONFIG 0x95
|
||||
#define RADIO_SET_CADPARAMS 0x88
|
||||
#define RADIO_SET_BUFFERBASEADDRESS 0x8F
|
||||
#define RADIO_SET_MODULATIONPARAMS 0x8B
|
||||
#define RADIO_SET_PACKETPARAMS 0x8C
|
||||
#define RADIO_GET_RXBUFFERSTATUS 0x13
|
||||
#define RADIO_GET_PACKETSTATUS 0x14
|
||||
#define RADIO_GET_RSSIINST 0x15
|
||||
#define RADIO_GET_STATS 0x10
|
||||
#define RADIO_RESET_STATS 0x00
|
||||
#define RADIO_CFG_DIOIRQ 0x08
|
||||
#define RADIO_GET_IRQSTATUS 0x12
|
||||
#define RADIO_CLR_IRQSTATUS 0x02
|
||||
#define RADIO_CALIBRATE 0x89
|
||||
#define RADIO_CALIBRATEIMAGE 0x98
|
||||
#define RADIO_SET_REGULATORMODE 0x96
|
||||
#define RADIO_GET_ERROR 0x17
|
||||
#define RADIO_CLR_ERROR 0x07
|
||||
#define RADIO_SET_TCXOMODE 0x97
|
||||
#define RADIO_SET_TXFALLBACKMODE 0x93
|
||||
#define RADIO_SET_RFSWITCHMODE 0x9D
|
||||
#define RADIO_SET_STOPRXTIMERONPREAMBLE 0x9F
|
||||
#define RADIO_SET_LORASYMBTIMEOUT 0xA0
|
||||
|
||||
//寄存器地址
|
||||
#define LORA_SYNCWORD 0x0740
|
||||
|
||||
//standby mode
|
||||
#define STDBY_RC 0x00
|
||||
#define STDBY_XOSC 0x01
|
||||
|
||||
|
||||
void lora_test_init(void);
|
8
EC600U_lora/inc/lora_test_function.h
Normal file
8
EC600U_lora/inc/lora_test_function.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include "ql_api_spi.h"
|
||||
#include "lora_test.h"
|
||||
|
||||
bool wait_on_busy(void);
|
||||
void llcc68_wakeup(void);
|
||||
uint16_t llcc68_get_syncword(void);
|
||||
void llcc68_set_standby(uint8_t mode);
|
||||
void llcc68_set_rfswitchmode(uint8_t enable);
|
126
EC600U_lora/inc/user.h
Normal file
126
EC600U_lora/inc/user.h
Normal file
@ -0,0 +1,126 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ql_gpio.h"
|
||||
|
||||
|
||||
#define SPI_CLK_PIN 1
|
||||
#define SPI_CLK_IO GPIO_9
|
||||
#define SPI_MISO_PIN 2
|
||||
#define SPI_MISO_IO GPIO_12
|
||||
#define SPI_MOSI_PIN 3
|
||||
#define SPI_MOSI_IO GPIO_11
|
||||
#define SPI_CS_PIN 4
|
||||
#define SPI_CS_IO GPIO_10
|
||||
|
||||
#define SPI_RST_PIN 59 //spi2-mosi
|
||||
#define SPI_RST_IO GPIO_2
|
||||
#define SPI_INT_PIN 60 //spi2-miso
|
||||
#define SPI_INT_IO GPIO_3
|
||||
#define SPI_BUSY_PIN 61 //spi2-clk
|
||||
#define SPI_BUSY_IO GPIO_0
|
||||
|
||||
#define LORA_SYNCWORD_1 0x3444
|
||||
#define LORA_SYNCWORD_2 0x1444
|
||||
|
||||
/*cmd*/
|
||||
#define LORA_SET_REGULATORMODE 0x96
|
||||
#define LORA_SET_RFSWITCHMODE 0x9D
|
||||
#define LORA_SET_CALIBRATE 0x89
|
||||
#define LORA_SET_BUFFERBASEADDRESS 0x8F
|
||||
#define LORA_SET_PACONFIG 0x95
|
||||
#define LORA_SET_TX_PARAMS 0x8E
|
||||
#define LORA_SET_CALIBRATEIMAGE 0x98
|
||||
#define LORA_SET_RFFREQ 0x86
|
||||
#define LORA_SET_STOPRXTIMERONPREAMBLE 0x9F
|
||||
#define LORA_SET_SYMBNUMTIMEOUT 0xA0
|
||||
#define LORA_SET_PACKETTYPE 0x8A
|
||||
#define LORA_SET_MODULATIONPARAMS 0x8B
|
||||
#define LORA_SET_PACKETPARAMS 0x8C
|
||||
#define LORA_SET_DIO_IRQ_CONFIG 0x08
|
||||
#define LORA_SET_RX 0x82 //将芯片设置为接收模式
|
||||
#define LORA_GET_STATUS 0xC0 //返回设备当前状态
|
||||
#define LORA_GET_IRQSTATUS 0x12 //获取中断状态
|
||||
#define LORA_CLEAR_IRQSTATUS 0x02 //清除中断状态
|
||||
|
||||
/*register addr*/
|
||||
#define LORA_SET_OCP 0x08E7
|
||||
#define LORA_SYNCWORD 0x0740
|
||||
|
||||
/*参数宏*/
|
||||
//CALIBRATE
|
||||
#define CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled
|
||||
#define CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled
|
||||
#define CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled
|
||||
#define CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled
|
||||
#define CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled
|
||||
#define CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled
|
||||
#define CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled
|
||||
#define CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled
|
||||
#define CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled
|
||||
#define CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled
|
||||
#define CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled
|
||||
#define CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled
|
||||
#define CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled
|
||||
#define CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled
|
||||
//standby
|
||||
#define LORA_STANDBY_RC 0x00
|
||||
#define LORA_STANDBY_XOSC 0x01
|
||||
//regulator
|
||||
#define REGULATOR_DCDC 0x01
|
||||
#define REGULATOR_LDO 0x00
|
||||
//freq
|
||||
#define XTAL_FREQ (double)(32000000)
|
||||
#define FREQ_DIV (double)(33554432) //2的25次方
|
||||
#define FREQ_STEP (double)(XTAL_FREQ/FREQ_DIV)
|
||||
#define RF_FREQ (uint32_t)470000000
|
||||
//irq
|
||||
typedef enum
|
||||
{
|
||||
IRQ_RADIO_NONE = 0x0000,
|
||||
IRQ_TX_DONE = 0x0001,
|
||||
IRQ_RX_DONE = 0x0002,
|
||||
IRQ_PREAMBLE_DETECTED = 0x0004,
|
||||
IRQ_SYNCWORD_VALID = 0x0008,
|
||||
IRQ_HEADER_VALID = 0x0010,
|
||||
IRQ_HEADER_ERROR = 0x0020,
|
||||
IRQ_CRC_ERROR = 0x0040,
|
||||
IRQ_CAD_DONE = 0x0080,
|
||||
IRQ_CAD_ACTIVITY_DETECTED = 0x0100,
|
||||
IRQ_RX_TX_TIMEOUT = 0x0200,
|
||||
IRQ_RADIO_ALL = 0xFFFF,
|
||||
}RadioIrqMasks_t;
|
||||
|
||||
/*初始化spi总线*/
|
||||
int lora_spi_init(void);
|
||||
|
||||
/*初始化lora所需的gpio口*/
|
||||
int lora_gpio_init(void);
|
||||
|
||||
/*初始化收发数组内存,进行32字节对齐*/
|
||||
void transfer_buf_init(void);
|
||||
|
||||
/*复位lora模块*/
|
||||
void lora_reset(void);
|
||||
|
||||
/*等待busy被拉低*/
|
||||
int wait_busy_low(void);
|
||||
|
||||
/*写命令*/
|
||||
int lora_write_cmd(uint8_t cmd, uint8_t *data, uint8_t len);
|
||||
|
||||
/*读命令*/
|
||||
int lora_read_cmd(uint8_t cmd, uint8_t len);
|
||||
|
||||
/*写寄存器*/
|
||||
int lora_wrtie_register(uint16_t add,uint8_t *data,uint8_t len);
|
||||
|
||||
/*读寄存器*/
|
||||
int lora_read_register(uint16_t add, uint8_t size);
|
||||
|
||||
/*写buffer*/
|
||||
void lora_write_buffer(uint8_t *data, uint8_t len);
|
||||
|
||||
/*读buffer*/
|
||||
void lora_read_buffer(uint8_t offset, uint8_t len);
|
321
EC600U_lora/lora.c
Normal file
321
EC600U_lora/lora.c
Normal file
@ -0,0 +1,321 @@
|
||||
|
||||
#include "./inc/user.h"
|
||||
#include "./inc/lora.h"
|
||||
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_log.h"
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "lora", msg, ##__VA_ARGS__)
|
||||
|
||||
extern unsigned char * write_buf;
|
||||
extern unsigned char * read_buf;
|
||||
uint16_t syncword;
|
||||
uint8_t PacketParams[6] = {0};
|
||||
|
||||
uint16_t lora_get_syncword(void)
|
||||
{
|
||||
if(lora_read_register(LORA_SYNCWORD,2)){
|
||||
uint16_t syncword = read_buf[4] << 8 | read_buf[5];
|
||||
return syncword;
|
||||
}
|
||||
return 65535;
|
||||
}
|
||||
|
||||
void lora_set_standby(uint8_t data)
|
||||
{
|
||||
lora_write_cmd(0x80,&data,1);
|
||||
}
|
||||
|
||||
void lora_set_RfSwitchCtrl(uint8_t enable)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_RFSWITCHMODE,&enable,1);
|
||||
}
|
||||
|
||||
void lora_set_calibrate(uint8_t param)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_CALIBRATE,¶m,1);
|
||||
}
|
||||
|
||||
void lora_set_regulator(uint8_t param)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_REGULATORMODE,¶m,1);
|
||||
}
|
||||
|
||||
void lora_set_bufferBaseAddress(uint8_t tx_base_add,uint8_t rx_base_add)
|
||||
{
|
||||
uint8_t data[2] = {tx_base_add,rx_base_add};
|
||||
lora_write_cmd(LORA_SET_BUFFERBASEADDRESS,data,2);
|
||||
}
|
||||
|
||||
void lora_set_PaConfig(uint8_t paDutyCycle,uint8_t hpMax,uint8_t deviceSel,uint8_t paLut)
|
||||
{
|
||||
uint8_t data[4] = {paDutyCycle,hpMax,deviceSel,paLut};
|
||||
lora_write_cmd(LORA_SET_PACONFIG,data,4);
|
||||
}
|
||||
|
||||
void lora_set_OverCurrentProtection(float max_current)
|
||||
{
|
||||
if((max_current >= 0.0)&&(max_current <= 140.0)){
|
||||
uint8_t data = (uint8_t)(max_current*2/5);
|
||||
lora_wrtie_register(LORA_SET_OCP,&data,1);
|
||||
}
|
||||
}
|
||||
|
||||
void lora_set_TX(uint8_t power,uint8_t rampTime)
|
||||
{
|
||||
if(power > 22) power = 22;
|
||||
if(power < -3) power = -3;
|
||||
uint8_t data[2] = {power,rampTime};
|
||||
lora_write_cmd(LORA_SET_TX_PARAMS,data,2);
|
||||
}
|
||||
|
||||
void lora_set_calibrateImage(uint32_t freq)
|
||||
{
|
||||
uint8_t calFreq[2] = {0,0};
|
||||
if( freq > 900000000 ){
|
||||
calFreq[0] = 0xE1;
|
||||
calFreq[1] = 0xE9;
|
||||
}else if( freq > 850000000 ){
|
||||
calFreq[0] = 0xD7;
|
||||
calFreq[1] = 0xDB;
|
||||
}else if( freq > 770000000 ){
|
||||
calFreq[0] = 0xC1;
|
||||
calFreq[1] = 0xC5;
|
||||
}else if( freq > 460000000 ){
|
||||
calFreq[0] = 0x75;
|
||||
calFreq[1] = 0x81;
|
||||
}else if( freq > 425000000 ){
|
||||
calFreq[0] = 0x6B;
|
||||
calFreq[1] = 0x6F;
|
||||
}
|
||||
lora_write_cmd(LORA_SET_CALIBRATEIMAGE,calFreq,2);
|
||||
}
|
||||
|
||||
void lora_set_RfFreq(uint32_t freq)
|
||||
{
|
||||
lora_set_calibrateImage(freq);
|
||||
uint32_t frequence = (uint32_t)((double)freq/(double)FREQ_STEP);
|
||||
uint8_t data[4] = {0,0,0,0};
|
||||
data[0] = (uint8_t)((frequence>>24)&0xff);
|
||||
data[1] = (uint8_t)((frequence>>16)&0xff);
|
||||
data[2] = (uint8_t)((frequence>>8)&0xff);
|
||||
data[3] = (uint8_t)(frequence&0xff);
|
||||
lora_write_cmd(LORA_SET_RFFREQ,data,4);
|
||||
}
|
||||
|
||||
void lora_stop_rxTimerRonpreamble(uint8_t enable)
|
||||
{
|
||||
//取反
|
||||
enable = !enable;
|
||||
lora_write_cmd(LORA_SET_STOPRXTIMERONPREAMBLE,&enable,1);
|
||||
}
|
||||
|
||||
void lora_set_symbNumTimeout(uint8_t symbNum)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_SYMBNUMTIMEOUT,&symbNum,1);
|
||||
}
|
||||
|
||||
void lora_set_packetType(uint8_t type)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_PACKETTYPE,&type,1);
|
||||
}
|
||||
|
||||
void lora_set_modulationParams(uint8_t spreadingFactor,uint8_t bandwidth,uint8_t codingRate,uint8_t lowDataRateOptimize)
|
||||
{
|
||||
uint8_t data[4] = {spreadingFactor,bandwidth,codingRate,lowDataRateOptimize};
|
||||
lora_write_cmd(LORA_SET_MODULATIONPARAMS,data,4);
|
||||
}
|
||||
|
||||
uint8_t* lora_get_packetParams(uint16_t preambleLength,uint8_t payloadLen,uint8_t crcOn,uint8_t invertIrq)
|
||||
{
|
||||
|
||||
PacketParams[0] = (preambleLength >> 8)&0xFF;
|
||||
PacketParams[1] = preambleLength;
|
||||
|
||||
if(payloadLen){
|
||||
PacketParams[2] = 0x01;
|
||||
PacketParams[3] = payloadLen;
|
||||
}else{
|
||||
PacketParams[2] = 0x00;
|
||||
PacketParams[3] = 0xFF;
|
||||
}
|
||||
|
||||
if(crcOn){
|
||||
PacketParams[4] = 0x01; //inverted
|
||||
}else{
|
||||
PacketParams[4] = 0x00; //standard
|
||||
}
|
||||
|
||||
if(invertIrq){
|
||||
PacketParams[5] = 0x01;
|
||||
}else{
|
||||
PacketParams[5] = 0x00;
|
||||
}
|
||||
|
||||
return PacketParams;
|
||||
}
|
||||
|
||||
void lora_set_IQ_Polarity(uint8_t iqConfig)
|
||||
{
|
||||
//获取当前寄存器数据
|
||||
lora_read_register(0x0736,1);
|
||||
uint8_t iqConfigCurrent = read_buf[0];
|
||||
|
||||
if(iqConfig == 0x01){//inverted
|
||||
iqConfigCurrent &= 0xFB;
|
||||
}else{
|
||||
iqConfigCurrent |= 0x04; //standard
|
||||
}
|
||||
|
||||
lora_wrtie_register(0x0736,&iqConfigCurrent,1);
|
||||
}
|
||||
|
||||
void lora_set_packetParams(uint8_t * packetParams)
|
||||
{
|
||||
lora_write_cmd(LORA_SET_PACKETPARAMS,packetParams,6);
|
||||
}
|
||||
|
||||
void lora_set_DioRiqConfig(uint16_t irqMask, uint16_t dio1, uint16_t dio2, uint16_t dio3)
|
||||
{
|
||||
uint8_t buf[8] = {0};
|
||||
buf[0] = (uint8_t)((irqMask >>8)&0x00FF);
|
||||
buf[1] = (uint8_t)(irqMask & 0x00FF);
|
||||
buf[2] = (uint8_t)((dio1 >>8)&0x00FF);
|
||||
buf[3] = (uint8_t)(dio1 & 0x00FF);
|
||||
buf[4] = (uint8_t)((dio2 >>8)&0x00FF);
|
||||
buf[5] = (uint8_t)(dio2 & 0x00FF);
|
||||
buf[6] = (uint8_t)((dio3 >>8)&0x00FF);
|
||||
buf[7] = (uint8_t)(dio3 & 0x00FF);
|
||||
lora_write_cmd(LORA_SET_DIO_IRQ_CONFIG,buf,8);
|
||||
}
|
||||
|
||||
uint8_t lora_get_status(void)
|
||||
{
|
||||
lora_read_cmd(LORA_GET_STATUS,1);
|
||||
return (uint8_t)read_buf[0];
|
||||
}
|
||||
|
||||
int lora_set_Rx(uint32_t timeout)
|
||||
{
|
||||
lora_set_standby(0x00);
|
||||
uint8_t buf[3] = {0};
|
||||
buf[0] = (uint8_t)((timeout >> 16) & 0xFF);
|
||||
buf[1] = (uint8_t)((timeout >> 8) & 0xFF);
|
||||
buf[2] = (uint8_t)(timeout & 0xFF);
|
||||
lora_write_cmd(LORA_SET_RX,buf,3);
|
||||
|
||||
for(int i = 0; i < 10; i++){
|
||||
if((lora_get_status()&0x70) == 0x50){ //01110000,
|
||||
return 1; //01010000 所以状态为0x20
|
||||
}
|
||||
ql_delay_us(1000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t lora_get_irq_status(void)
|
||||
{
|
||||
lora_read_cmd(LORA_GET_IRQSTATUS,3);
|
||||
return (uint16_t)((read_buf[2] << 8) | read_buf[3]);
|
||||
}
|
||||
|
||||
void lora_clear_irq_status(uint16_t irq_status)
|
||||
{
|
||||
uint8_t buf[2] = {0};
|
||||
buf[0] = (uint8_t)((irq_status >>8)&0x00FF);
|
||||
buf[1] = (uint8_t)(irq_status & 0x00FF);
|
||||
lora_write_cmd(LORA_CLEAR_IRQSTATUS,buf,2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int lora_init(void)
|
||||
{
|
||||
transfer_buf_init();
|
||||
|
||||
int err = lora_gpio_init();
|
||||
if(err != 1){
|
||||
LOGI("lora_gpio_init fail,err = %d\n",err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = lora_spi_init();
|
||||
if(err != 1){
|
||||
LOGI("lora_spi_init fail,err = %d\n",err);
|
||||
return 0;
|
||||
}
|
||||
lora_reset();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lora_start(void)
|
||||
{
|
||||
/*获取同步字并判断*/
|
||||
syncword = lora_get_syncword();
|
||||
if(syncword != LORA_SYNCWORD_1 && syncword != LORA_SYNCWORD_2){
|
||||
LOGI("syncword 0x%02X is error\n",syncword);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*设置standby为RC模式*/
|
||||
lora_set_standby(LORA_STANDBY_RC);
|
||||
|
||||
/*启用RF开关控制*/
|
||||
lora_set_RfSwitchCtrl(1);
|
||||
|
||||
/*设置射频校准*/
|
||||
lora_set_calibrate(0b01111111);
|
||||
|
||||
/*设置电源为DCDC模式*/
|
||||
lora_set_regulator(REGULATOR_DCDC);
|
||||
|
||||
/*设置缓冲区基地址*/
|
||||
lora_set_bufferBaseAddress(0,0);
|
||||
|
||||
/*配置功率放大器*/
|
||||
lora_set_PaConfig(0x04,0x07,0x00,0x01); //+22dBM
|
||||
|
||||
/*设置过流保护*/
|
||||
lora_set_OverCurrentProtection(60.0);
|
||||
|
||||
/*设置发送参数*/
|
||||
lora_set_TX(20,0x04);//默认20发送功率,渐变200us
|
||||
|
||||
/*设置射频频率*/
|
||||
lora_set_RfFreq(RF_FREQ);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lora_radioConfig(void)
|
||||
{
|
||||
/*不禁用接收定时器*/
|
||||
lora_stop_rxTimerRonpreamble(0);
|
||||
|
||||
/*设置超时参数*/
|
||||
lora_set_symbNumTimeout(0);
|
||||
|
||||
/*设置数据包类型*/
|
||||
lora_set_packetType(0x01);//lora模式
|
||||
|
||||
/*设置射频调制参数*/
|
||||
lora_set_modulationParams(7,4,1,0);
|
||||
|
||||
/*配置数据包参数*/
|
||||
uint8_t *packetParams = lora_get_packetParams(8,0,1,0);
|
||||
|
||||
/*设置射频接收IQ极性*/
|
||||
lora_set_IQ_Polarity(packetParams[5]);
|
||||
|
||||
/*设置数据包参数*/
|
||||
lora_set_packetParams(packetParams);
|
||||
|
||||
/*配置数字输入输出中断*/
|
||||
lora_set_DioRiqConfig(1023,2,0,0);//0b1111111111,0b0000000010
|
||||
|
||||
/*设置接收模式为RX连续模式*/
|
||||
if(lora_set_Rx(0xFFFFFF) == 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
144
EC600U_lora/lora_app.c
Normal file
144
EC600U_lora/lora_app.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_api_spi.h"
|
||||
//#include "ql_gpio.h"
|
||||
#include "ql_log.h"
|
||||
#include "./inc/lora.h"
|
||||
#include "./inc/user.h"
|
||||
#include "lora_app.h"
|
||||
|
||||
/*宏定义*/
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "lora_app", msg, ##__VA_ARGS__)
|
||||
#define USE_TEST 1
|
||||
|
||||
/*全局变量*/
|
||||
int flag;
|
||||
ql_task_t lora_app_task;
|
||||
extern unsigned char *write_buf;
|
||||
extern unsigned char *read_buf;
|
||||
int count = 1;
|
||||
|
||||
/*函数*/
|
||||
#if USE_TEST
|
||||
void lora_send_test(void)
|
||||
{
|
||||
//uint16_t syncword = lora_get_syncword(); //00011101 00000111 01000000
|
||||
//LOGI("syncword = 0x%04X\n",syncword);
|
||||
//lora_set_standby(0x00);
|
||||
|
||||
LOGI("lora_send_test start");
|
||||
|
||||
if(wait_busy_low()){
|
||||
write_buf[0] = 0x1D; //00011101
|
||||
write_buf[1] = 0x07; //00000111
|
||||
write_buf[2] = 0x40; //01000000
|
||||
ql_errcode_spi_e spi_err = ql_spi_write_read(QL_SPI_PORT1, read_buf,write_buf, 3);
|
||||
LOGI("ql_spi_write_read spi_err = %d",spi_err);
|
||||
LOGI("read_buf 0 = 0x%02X, read_buf 1 = 0x%02X\n",read_buf[0],read_buf[1]);
|
||||
LOGI("read_buf 2 = 0x%02X, read_buf 3 = 0x%02X\n",read_buf[2],read_buf[3]);
|
||||
LOGI("read_buf 4 = 0x%02X, read_buf 5 = 0x%02X\n",read_buf[4],read_buf[5]);
|
||||
}
|
||||
else{
|
||||
LOGI("lora_send_test wait_busy_low outtime");
|
||||
}
|
||||
|
||||
LOGI("lora_send_test end");
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void lora_receive_mode(void)
|
||||
{
|
||||
/*获取中断状态*/
|
||||
uint16_t irq_status = lora_get_irq_status();
|
||||
|
||||
/*清除中断状态*/
|
||||
lora_clear_irq_status(irq_status);
|
||||
|
||||
/*根据中断状态进行操作*/
|
||||
if((irq_status & IRQ_TX_DONE) == IRQ_TX_DONE){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_RX_DONE ) == IRQ_RX_DONE ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_CAD_DONE ) == IRQ_CAD_DONE ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID ){
|
||||
|
||||
}
|
||||
if( ( irq_status & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR ){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void lora_app_thread(void *param)
|
||||
{
|
||||
LOGI("lora_app_thread start");
|
||||
lora_init();
|
||||
|
||||
#if !USE_TEST
|
||||
lora_start();
|
||||
lora_radioConfig();
|
||||
#endif
|
||||
|
||||
while(1){
|
||||
LOGI("enter while in %d times\n",count);
|
||||
count++;
|
||||
// wait_busy_low();
|
||||
// write_buf[0] = 0x1D; //00011101
|
||||
// write_buf[1] = ((0x0740 & 0xff00) >> 8);//00000111
|
||||
// write_buf[2] = (0x0740 & 0xff);//01000000
|
||||
// write_buf[3] = 0;
|
||||
// write_buf[4] = 0;
|
||||
// LOGI("write_buf[0] = 0x%x, write_buf[1] = 0x%02x, write_buf[2] = 0x%x, write_buf[3] = 0x%x, write_buf[4] = 0x%x",write_buf[0],write_buf[1],write_buf[2],write_buf[3],write_buf[4]);
|
||||
// LOGI("ql_spi_write_read err = %d",ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,5));
|
||||
// wait_busy_low();
|
||||
// LOGI("read_buf[0] = 0x%x, read_buf[1] = 0x%x, read_buf[2] = 0x%x, read_buf[3] = 0x%02x, read_buf[4] = 0x%02x",read_buf[0],read_buf[1],read_buf[2],read_buf[3],read_buf[4]);
|
||||
|
||||
/*唤醒*/
|
||||
write_buf[0] = 0xC0; //返回设备当前状态命令
|
||||
write_buf[1] = 0x00;
|
||||
LOGI(" write 0xC0 0x00 err = %d",ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,2));
|
||||
LOGI(" read_buf[0] = 0x%02x, read_buf[1] = 0x%02x,",read_buf[0],read_buf[1]);
|
||||
wait_busy_low();
|
||||
|
||||
ql_rtos_task_sleep_ms(5);
|
||||
}
|
||||
}
|
||||
|
||||
void lora_app_init(void)
|
||||
{
|
||||
QlOSStatus err = ql_rtos_task_create(&lora_app_task, 4096, APP_PRIORITY_NORMAL,"lora",lora_app_thread,NULL,1);
|
||||
if(err != 0){
|
||||
LOGI("create lora_demo_task failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
0001 1101
|
||||
0100 0101
|
||||
|
||||
复位
|
||||
rst推挽输出低电平10ms后改为上拉输入模式持续10ms
|
||||
|
||||
唤醒
|
||||
nss低
|
||||
传输192
|
||||
传输0
|
||||
nss高
|
||||
等待busy引脚由高变低
|
||||
*/
|
161
EC600U_lora/lora_test.c
Normal file
161
EC600U_lora/lora_test.c
Normal file
@ -0,0 +1,161 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ql_api_spi.h"
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_gpio.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#include "./inc/lora_test.h"
|
||||
#include "./inc/lora_test_function.h"
|
||||
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "lora_test", msg, ##__VA_ARGS__)
|
||||
|
||||
#define RST_PIN 59
|
||||
#define INT_PIN 60
|
||||
#define BUSY_PIN 61
|
||||
#define SWITCH_PIN 16
|
||||
|
||||
#define RST_GPIO GPIO_2
|
||||
#define INT_GPIO GPIO_3
|
||||
#define BUSY_GPIO GPIO_0
|
||||
#define SWITCH_GPIO GPIO_19
|
||||
|
||||
ql_task_t lora_test_task;
|
||||
ql_errcode_gpio gpio_err;
|
||||
|
||||
unsigned char *out_buf = NULL;
|
||||
unsigned char *out_mal_buf = NULL;
|
||||
unsigned char *in_buf = NULL;
|
||||
unsigned char *in_mal_buf = NULL;
|
||||
unsigned short buf_len = 512;
|
||||
|
||||
static void int_cb(void *ctx)
|
||||
{
|
||||
LOGI(" enter int cb");
|
||||
}
|
||||
|
||||
void lora_test_thread(void *param)
|
||||
{
|
||||
LOGI("lora_test_thread start");
|
||||
|
||||
/*初始化收发buffer,32字节对齐*/
|
||||
out_mal_buf = (unsigned char *)malloc(QL_SPI_DMA_ADDR_ALIN + buf_len);
|
||||
in_mal_buf = (unsigned char *)malloc(QL_SPI_DMA_ADDR_ALIN + buf_len);
|
||||
out_buf = (unsigned char *)OSI_ALIGN_UP(out_mal_buf, QL_SPI_DMA_ADDR_ALIN);
|
||||
in_buf = (unsigned char *)OSI_ALIGN_UP(in_mal_buf, QL_SPI_DMA_ADDR_ALIN);
|
||||
memset(out_buf, 0x00, buf_len);
|
||||
memset(in_buf, 0x00, buf_len);
|
||||
|
||||
/*初始化引脚功能*/
|
||||
LOGI("ql_pin_set_gpio(RST_PIN) err = %d", ql_pin_set_gpio(RST_PIN));
|
||||
LOGI("ql_pin_set_gpio(INT_PIN) err = %d", ql_pin_set_gpio(INT_PIN));
|
||||
LOGI("ql_pin_set_gpio(BUSY_PIN) err = %d", ql_pin_set_gpio(BUSY_PIN));
|
||||
|
||||
/*开启电平开关*/
|
||||
LOGI("ql_pin_set_gpio(16) err = %d", ql_pin_set_gpio(SWITCH_PIN));
|
||||
LOGI("GPIO_19 init err = %d", ql_gpio_init(SWITCH_GPIO, GPIO_OUTPUT, PULL_DOWN, LVL_LOW));
|
||||
|
||||
/*初始化busyIO为上拉输入*/
|
||||
LOGI("BUSY_GPIO GPIO_INPUT err = %d", ql_gpio_set_direction(BUSY_GPIO, GPIO_INPUT));
|
||||
LOGI("BUSY_GPIO PULL_UP err = %d", ql_gpio_set_pull(BUSY_GPIO, PULL_UP));
|
||||
|
||||
/*初始化SPI*/
|
||||
ql_spi_config_s lora_spi_config = {0};
|
||||
lora_spi_config.input_mode = QL_SPI_INPUT_TRUE;
|
||||
lora_spi_config.port = QL_SPI_PORT1;
|
||||
lora_spi_config.framesize = 8;
|
||||
lora_spi_config.spiclk = QL_SPI_CLK_6_25MHZ;
|
||||
lora_spi_config.cs_polarity0 = QL_SPI_CS_ACTIVE_LOW;
|
||||
lora_spi_config.cs_polarity1 = QL_SPI_CS_ACTIVE_LOW;
|
||||
lora_spi_config.cpol = QL_SPI_CPOL_LOW;
|
||||
lora_spi_config.cpha = QL_SPI_CPHA_2Edge;
|
||||
lora_spi_config.input_sel = QL_SPI_DI_1;
|
||||
lora_spi_config.transmode = QL_SPI_DMA_IRQ;
|
||||
lora_spi_config.cs = QL_SPI_CS0;
|
||||
lora_spi_config.clk_delay = QL_SPI_CLK_DELAY_0;
|
||||
lora_spi_config.release_flag = QL_SPI_NOT_RELEASE;
|
||||
LOGI("ql_spi_init_ext err = %d", ql_spi_init_ext(lora_spi_config));
|
||||
//LOGI("SPI1 cs auto err = %d", ql_spi_cs_auto(QL_SPI_PORT1));
|
||||
LOGI("SPI1 request_sys_clk err = %d", ql_spi_request_sys_clk(QL_SPI_PORT1));
|
||||
|
||||
/*复位,rst引脚推挽输出低电平20ms后拉高10ms改为上拉输入*/
|
||||
ql_delay_us(10000);
|
||||
LOGI("RST_GPIO GPIO_OUTPUT err = %d", ql_gpio_set_direction(RST_GPIO, GPIO_OUTPUT));
|
||||
LOGI("RST_GPIO LVL_LOW err = %d", ql_gpio_set_level(RST_GPIO, LVL_LOW));
|
||||
ql_delay_us(20000);
|
||||
LOGI("RST_GPIO LVL_HIGH err = %d", ql_gpio_set_level(RST_GPIO, LVL_HIGH));//官方例程中没有拉高,但是不拉高就测不到波形
|
||||
ql_delay_us(10000);
|
||||
LOGI("RST_GPIO GPIO_INPUT err = %d", ql_gpio_set_direction(RST_GPIO, GPIO_INPUT));
|
||||
LOGI("RST_GPIO PULL_UP err = %d", ql_gpio_set_pull(RST_GPIO, PULL_UP));
|
||||
|
||||
|
||||
/*配置中断,int初始化为下拉输入,上升沿中断*/
|
||||
LOGI("ql_int_register err = %d", ql_int_register(INT_GPIO, EDGE_TRIGGER, DEBOUNCE_EN, EDGE_RISING, PULL_DOWN, int_cb, NULL));
|
||||
LOGI("ql_int_enable err = %d", ql_int_enable(INT_GPIO));
|
||||
|
||||
/*唤醒*/
|
||||
//llcc68_wakeup();
|
||||
|
||||
/*获取同步字*/
|
||||
LOGI("syncword = 0x%04x",llcc68_get_syncword());
|
||||
|
||||
// llcc68_set_standby(STDBY_RC);
|
||||
// llcc68_set_rfswitchmode(true);
|
||||
|
||||
while (1)
|
||||
{
|
||||
out_buf[0] = RADIO_READ_REGISTER;
|
||||
out_buf[1] = ((LORA_SYNCWORD & 0xff00) >> 8);
|
||||
out_buf[2] = (LORA_SYNCWORD & 0xff);
|
||||
out_buf[3] = 0x00;
|
||||
out_buf[4] = 0x00;
|
||||
out_buf[5] = 0x00;
|
||||
|
||||
// LOGI("SPI1 request_sys_clk err = %d", ql_spi_request_sys_clk(QL_SPI_PORT1));
|
||||
wait_on_busy();
|
||||
LOGI("SPI1 ql_spi_cs_low err = %d",ql_spi_cs_low(QL_SPI_PORT1));
|
||||
LOGI("SPI1 ql_spi_write_read err = %d",ql_spi_write_read(QL_SPI_PORT1,in_buf,out_buf,6));
|
||||
LOGI("SPI1 ql_spi_cs_low err = %d",ql_spi_cs_high(QL_SPI_PORT1));
|
||||
wait_on_busy();
|
||||
// LOGI("SPI1 ql_spi_release_sys_clk err = %d", ql_spi_release_sys_clk(QL_SPI_PORT1));
|
||||
|
||||
LOGI("in_buf 0 = 0x%02x",in_buf[0]);
|
||||
LOGI("in_buf 1 = 0x%02x",in_buf[1]);
|
||||
LOGI("in_buf 2 = 0x%02x",in_buf[2]);
|
||||
LOGI("in_buf 3 = 0x%02x",in_buf[3]);
|
||||
LOGI("in_buf 4 = 0x%02x",in_buf[4]);
|
||||
LOGI("in_buf 5 = 0x%02x",in_buf[5]);
|
||||
|
||||
memset(out_buf, 0x00, buf_len);
|
||||
memset(in_buf, 0x00, buf_len);
|
||||
|
||||
ql_rtos_task_sleep_ms(20);
|
||||
}
|
||||
}
|
||||
|
||||
void lora_test_init(void)
|
||||
{
|
||||
QlOSStatus err = ql_rtos_task_create(&lora_test_task, 4096, APP_PRIORITY_NORMAL, "loratest", lora_test_thread, NULL, 1);
|
||||
if (err != 0)
|
||||
{
|
||||
LOGI("create lora_demo_task failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
// 测试引脚功能
|
||||
// uint8_t func = 255;
|
||||
// ql_pin_get_func(66,&func);
|
||||
// LOGI("66 func = %d",func);
|
||||
// ql_pin_get_func(RST_PIN,&func);
|
||||
// LOGI("RST_PIN func = %d",func);
|
||||
// ql_pin_get_func(INT_PIN,&func);
|
||||
// LOGI("INT_PIN func = %d",func);
|
||||
// ql_pin_get_func(BUSY_PIN,&func);
|
||||
// LOGI("BUSY_PIN func = %d",func);
|
||||
|
||||
//测试中断引脚方向
|
||||
// ql_GpioDir dir = 1;
|
||||
// LOGI("ql_gpio_get_direction err = %d",ql_gpio_get_direction(INT_GPIO,&dir));
|
||||
// LOGI("INT_GPIO dir = %d",dir);
|
78
EC600U_lora/lora_test_function.c
Normal file
78
EC600U_lora/lora_test_function.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ql_api_spi.h"
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_gpio.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#include "./inc/lora_test.h"
|
||||
#include "./inc/lora_test_function.h"
|
||||
|
||||
#define BUSY_GPIO GPIO_0
|
||||
|
||||
extern unsigned char *out_buf;
|
||||
extern unsigned char *in_buf;
|
||||
|
||||
bool wait_on_busy(void)
|
||||
{
|
||||
ql_LvlMode level = LVL_HIGH;
|
||||
for(uint32_t i = 0; i < 1000; i++){
|
||||
ql_gpio_get_level(GPIO_0,&level);
|
||||
if(level == LVL_LOW){
|
||||
return true;
|
||||
}
|
||||
ql_delay_us(1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// void llcc68_write_cmd(enum RadioCommands_e cmd)
|
||||
// {
|
||||
// out_buf[0] = cmd;
|
||||
// ql_spi_write(QL_SPI_PORT1,out_buf,1);
|
||||
// wait_on_busy();
|
||||
// }
|
||||
|
||||
void llcc68_wakeup(void)
|
||||
{
|
||||
out_buf[0] = RADIO_GET_STATUS;
|
||||
out_buf[1] = 0x00;
|
||||
ql_spi_write(QL_SPI_PORT1,out_buf,2);
|
||||
wait_on_busy();
|
||||
}
|
||||
|
||||
uint16_t llcc68_get_syncword(void)
|
||||
{
|
||||
wait_on_busy();
|
||||
ql_spi_cs_low(QL_SPI_PORT1);
|
||||
out_buf[0] = RADIO_READ_REGISTER;
|
||||
out_buf[1] = ((LORA_SYNCWORD & 0xff00) >> 8);
|
||||
out_buf[2] = (LORA_SYNCWORD & 0xff);
|
||||
out_buf[3] = 0x00;
|
||||
out_buf[4] = 0x00;
|
||||
out_buf[5] = 0x00;
|
||||
ql_spi_write_read(QL_SPI_PORT1,in_buf,out_buf,6);
|
||||
// ql_spi_write(QL_SPI_PORT1,out_buf,4);
|
||||
// ql_spi_read(QL_SPI_PORT1,in_buf,2);
|
||||
ql_spi_cs_high(QL_SPI_PORT1);
|
||||
wait_on_busy();
|
||||
return (in_buf[4] << 8 | in_buf[5]);
|
||||
}
|
||||
|
||||
void llcc68_set_standby(uint8_t mode)
|
||||
{
|
||||
out_buf[0] = RADIO_SET_STANDBY;
|
||||
out_buf[1] = mode;
|
||||
ql_spi_write(QL_SPI_PORT1,out_buf,2);
|
||||
wait_on_busy();
|
||||
}
|
||||
|
||||
void llcc68_set_rfswitchmode(uint8_t enable)
|
||||
{
|
||||
out_buf[0] = RADIO_SET_RFSWITCHMODE;
|
||||
out_buf[1] = enable;
|
||||
ql_spi_write(QL_SPI_PORT1,out_buf,2);
|
||||
wait_on_busy();
|
||||
}
|
212
EC600U_lora/user.c
Normal file
212
EC600U_lora/user.c
Normal file
@ -0,0 +1,212 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ql_gpio.h"
|
||||
#include "ql_api_spi.h"
|
||||
#include "ql_api_osi.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#include "./inc/user.h"
|
||||
|
||||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "user", msg, ##__VA_ARGS__)
|
||||
|
||||
/*全局变量*/
|
||||
ql_errcode_gpio gpio_err;
|
||||
ql_errcode_spi_e spi_err;
|
||||
ql_LvlMode busy_level = LVL_HIGH;
|
||||
unsigned char * write_buf = NULL;
|
||||
unsigned char * write_mal_buf = NULL;
|
||||
unsigned char * read_buf = NULL;
|
||||
unsigned char * read_mal_buf = NULL;
|
||||
unsigned short write_len = 512;
|
||||
unsigned short read_len = 512;
|
||||
|
||||
/*函数*/
|
||||
int wait_busy_low(void)
|
||||
{
|
||||
int retry = 10000;
|
||||
while(retry--){
|
||||
ql_gpio_get_level(SPI_BUSY_IO,&busy_level);
|
||||
if(busy_level == LVL_LOW) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lora_wrtie_register(uint16_t add,uint8_t *data,uint8_t len)
|
||||
{
|
||||
wait_busy_low();
|
||||
write_buf[0] = 0x0D;
|
||||
write_buf[1] = ((add & 0xff00) >> 8);
|
||||
write_buf[2] = (add & 0xff);
|
||||
for(int i =0;i<len;i++){
|
||||
write_buf[i+3] = data[i];
|
||||
}
|
||||
ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+3);
|
||||
return wait_busy_low();
|
||||
}
|
||||
|
||||
int lora_read_register(uint16_t add, uint8_t len)
|
||||
{
|
||||
wait_busy_low();
|
||||
write_buf[0] = 0x1D;
|
||||
write_buf[1] = ((add & 0xff00) >> 8);
|
||||
write_buf[2] = (add & 0xff);
|
||||
for(int i = 0; i <= len; i++){
|
||||
write_buf[i+1+len] = 0;
|
||||
}
|
||||
ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+4);
|
||||
|
||||
return wait_busy_low();
|
||||
}
|
||||
|
||||
int lora_write_cmd(uint8_t cmd, uint8_t *data, uint8_t len)
|
||||
{
|
||||
if(wait_busy_low() == 0) return 0;
|
||||
|
||||
write_buf[0] = cmd;
|
||||
for(int i = 0; i < len; i++){
|
||||
write_buf[i+1] = data[i];
|
||||
}
|
||||
spi_err = ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+1);
|
||||
if(spi_err !=0) return 0;
|
||||
|
||||
//if(wait_busy_low() == 0) return 0;
|
||||
return wait_busy_low();
|
||||
}
|
||||
|
||||
int lora_read_cmd(uint8_t cmd, uint8_t len)
|
||||
{
|
||||
wait_busy_low();
|
||||
write_buf[0] = cmd;
|
||||
for(int i = 0; i < len; i++){
|
||||
write_buf[i+1] = 0;
|
||||
}
|
||||
ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+1);
|
||||
return wait_busy_low();
|
||||
}
|
||||
|
||||
void lora_write_buffer(uint8_t *data, uint8_t len)
|
||||
{
|
||||
wait_busy_low();
|
||||
write_buf[0] = 0x0E;
|
||||
write_buf[1] = 0x00;
|
||||
for(int i = 0; i < len; i++){
|
||||
write_buf[i+2] = data[i];
|
||||
}
|
||||
ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+2);
|
||||
wait_busy_low();
|
||||
}
|
||||
|
||||
void lora_read_buffer(uint8_t offset, uint8_t len)
|
||||
{
|
||||
wait_busy_low();
|
||||
write_buf[0] = 0x1E;
|
||||
write_buf[1] = offset;
|
||||
for(int i = 0; i < len; i++){
|
||||
write_buf[i+2] = 0;
|
||||
}
|
||||
ql_spi_write_read(QL_SPI_PORT1,read_buf,write_buf,len+2);
|
||||
wait_busy_low();
|
||||
}
|
||||
|
||||
void transfer_buf_init(void)
|
||||
{
|
||||
write_mal_buf = (unsigned char *)malloc(QL_SPI_DMA_ADDR_ALIN+write_len);
|
||||
read_mal_buf = (unsigned char *)malloc(QL_SPI_DMA_ADDR_ALIN+read_len);
|
||||
|
||||
//32对齐
|
||||
write_buf = (unsigned char *)OSI_ALIGN_UP(write_mal_buf, QL_SPI_DMA_ADDR_ALIN);
|
||||
read_buf = (unsigned char *)OSI_ALIGN_UP(read_mal_buf, QL_SPI_DMA_ADDR_ALIN);
|
||||
|
||||
//清零
|
||||
memset(write_buf, 0x00, write_len);
|
||||
memset(read_buf, 0x00, read_len);
|
||||
}
|
||||
|
||||
void lora_reset(void)
|
||||
{
|
||||
ql_gpio_set_level(SPI_RST_IO,LVL_LOW);
|
||||
ql_delay_us(1000);
|
||||
ql_gpio_set_level(SPI_RST_IO,LVL_HIGH);
|
||||
wait_busy_low();
|
||||
}
|
||||
|
||||
int lora_spi_init(void)
|
||||
{
|
||||
ql_spi_config_s lora_spi_config = {0};
|
||||
lora_spi_config.input_mode = QL_SPI_INPUT_TRUE;
|
||||
lora_spi_config.port = QL_SPI_PORT1;
|
||||
lora_spi_config.framesize = 8;
|
||||
lora_spi_config.spiclk = QL_SPI_CLK_6_25MHZ;
|
||||
lora_spi_config.cs_polarity0 = QL_SPI_CS_ACTIVE_LOW;
|
||||
lora_spi_config.cs_polarity1 = QL_SPI_CS_ACTIVE_LOW;
|
||||
lora_spi_config.cpol = QL_SPI_CPOL_LOW;
|
||||
lora_spi_config.cpha = QL_SPI_CPHA_2Edge;
|
||||
lora_spi_config.input_sel = QL_SPI_DI_1;
|
||||
lora_spi_config.transmode = QL_SPI_DMA_IRQ;
|
||||
lora_spi_config.cs = QL_SPI_CS0;
|
||||
|
||||
lora_spi_config.clk_delay = QL_SPI_CLK_DELAY_0;
|
||||
lora_spi_config.release_flag = QL_SPI_NOT_RELEASE;
|
||||
|
||||
spi_err = ql_spi_init_ext(lora_spi_config); if(spi_err != 0) return 2;
|
||||
spi_err = ql_spi_cs_auto(QL_SPI_PORT1); if(spi_err != 0) return 3;
|
||||
spi_err = ql_spi_request_sys_clk(QL_SPI_PORT1); if(spi_err != 0) return 4;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void int_cb(void *ctx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int lora_gpio_init(void)
|
||||
{
|
||||
/*将引脚设置为spi功能*/
|
||||
gpio_err = ql_pin_set_func(SPI_CS_PIN,1); if(gpio_err != 0) return 2;
|
||||
gpio_err = ql_pin_set_func(SPI_CLK_PIN,1); if(gpio_err != 0) return 3;
|
||||
gpio_err = ql_pin_set_func(SPI_MOSI_PIN,1); if(gpio_err != 0) return 4;
|
||||
gpio_err = ql_pin_set_func(SPI_MISO_PIN,1); if(gpio_err != 0) return 5;
|
||||
|
||||
/*将busy,int,rst引脚设置为gpio功能*/
|
||||
gpio_err = ql_pin_set_gpio(SPI_BUSY_PIN); if(gpio_err != 0) return 6;
|
||||
gpio_err = ql_pin_set_gpio(SPI_RST_PIN); if(gpio_err != 0) return 7;
|
||||
gpio_err = ql_pin_set_gpio(SPI_INT_PIN); if(gpio_err != 0) return 8;
|
||||
|
||||
/*拉低电平转换器开关电平,使能B端电压*/
|
||||
gpio_err = ql_pin_set_gpio(16); if(gpio_err != 0) return 14;
|
||||
gpio_err = ql_gpio_set_direction(GPIO_19,GPIO_OUTPUT); if(gpio_err != 0) return 15;
|
||||
gpio_err = ql_gpio_set_level(GPIO_19,LVL_LOW); if(gpio_err != 0) return 16;
|
||||
|
||||
/*将busy引脚同一io口的引脚设置为非gpio功能,防止冲突*/
|
||||
gpio_err = ql_pin_set_func(66,0); if(gpio_err != 0) return 9;
|
||||
|
||||
// /*busy初始化为上拉输入*/
|
||||
// ql_gpio_set_direction(SPI_BUSY_IO,GPIO_INPUT);
|
||||
// ql_gpio_set_pull(SPI_BUSY_IO,PULL_UP);
|
||||
|
||||
// /*rst推挽输出低电平20ms后转为输入再延时10ms*/
|
||||
// ql_gpio_set_direction(SPI_RST_IO,GPIO_OUTPUT);
|
||||
// ql_gpio_set_level(SPI_RST_IO,LVL_LOW);
|
||||
// ql_rtos_task_sleep_ms(20);
|
||||
// ql_gpio_set_direction(SPI_RST_IO,GPIO_INPUT);
|
||||
// ql_rtos_task_sleep_ms(10);
|
||||
|
||||
// /*int引脚初始化为下拉输入,注册上升沿触发中断*/
|
||||
// ql_gpio_set_direction(SPI_INT_IO,GPIO_INPUT);
|
||||
// ql_gpio_set_pull(SPI_INT_IO,PULL_DOWN);
|
||||
// ql_int_register(SPI_INT_IO,EDGE_TRIGGER,DEBOUNCE_EN,EDGE_RISING,PULL_DOWN,int_cb,NULL);
|
||||
|
||||
/*设置busy,int,rst的gpio*/
|
||||
gpio_err = ql_gpio_init(SPI_BUSY_IO,GPIO_INPUT,PULL_UP,LVL_LOW); if(gpio_err != 0) return 10;
|
||||
//gpio_err = ql_gpio_set_direction(SPI_INT_IO,GPIO_INPUT); if(gpio_err != 0) return 11;
|
||||
if(ql_int_register(SPI_INT_IO,EDGE_TRIGGER,DEBOUNCE_EN,EDGE_RISING,PULL_DOWN,int_cb,NULL)!=0) return 11;
|
||||
ql_int_enable(SPI_INT_IO);
|
||||
gpio_err = ql_gpio_set_direction(SPI_RST_IO,GPIO_OUTPUT); if(gpio_err != 0) return 12;
|
||||
gpio_err = ql_gpio_set_level(SPI_RST_IO,LVL_HIGH); if(gpio_err != 0) return 13;
|
||||
|
||||
return 1;
|
||||
}
|
21
EC600U_lvgl/CMakeLists.txt
Normal file
21
EC600U_lvgl/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
set(target ql_app_lvgl)
|
||||
|
||||
add_library(${target} STATIC)
|
||||
set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_QUEC)
|
||||
target_include_directories(${target} PUBLIC inc)
|
||||
#target_link_libraries(${target} PRIVATE kernel driver hal ql_api_common lvgl)
|
||||
target_link_libraries(${target} PRIVATE lvgl)
|
||||
target_sources(${target} PRIVATE
|
||||
lvgl_demo.c
|
||||
./ui/ui.c
|
||||
./ui/ui_screen1.c
|
||||
./ui/ui_screen2.c
|
||||
./ui/ui_screen3.c
|
||||
./ui/ui_screen3_chart.c
|
||||
./ui/ui_screen4.c
|
||||
./ui/fs_function.c
|
||||
)
|
||||
|
||||
relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
beautify_c_code(${target} ${srcs})
|
42
EC600U_lvgl/inc/lvgl_demo.h
Normal file
42
EC600U_lvgl/inc/lvgl_demo.h
Normal file
@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TP_nRST_pin (137)
|
||||
#define nTP_INT_pin (62)
|
||||
|
||||
#define TP_nRST_GPIO_num GPIO_4
|
||||
#define nTP_INT_GPIO_num GPIO_5
|
||||
|
||||
#define X_RESOLUTION 480
|
||||
#define Y_RESOLUTION 320
|
||||
#define MAX_TOUCH_NUMBER 1
|
||||
|
||||
#define GT911_ADDRESS 0x5D //从机地址
|
||||
#define GT911_REG_WRITE_ADDRESS 0xBA //从机写地址
|
||||
#define GT911_REG_READ_ADDRESS 0xBB //从机读地址
|
||||
|
||||
|
||||
#define GT911_CTRL_ADDRESS 0x8040 //控制寄存器地址
|
||||
#define GT911_CFG_ADDRESS 0x8047 //配置寄存器起始地址
|
||||
#define GT911_CHECK_REG 0X80FF //校验和寄存器地址
|
||||
#define GT911_TPD_Sta 0X8150 //触摸点起始数据地址
|
||||
#define GT911_STATE_REG 0X814E //触摸状态寄存器, 第7位是触摸标志位,低4位是触摸点数个数
|
||||
|
||||
#define GT911_TP1_REG 0X8150 //第一个触摸点数据地址
|
||||
#define GT911_TP2_REG 0X8158 //第二个触摸点数据地址
|
||||
#define GT911_TP3_REG 0X8160 //第三个触摸点数据地址
|
||||
#define GT911_TP4_REG 0X8168 //第四个触摸点数据地址
|
||||
#define GT911_TP5_REG 0X8170 //第五个触摸点数据地址
|
||||
|
||||
typedef struct{
|
||||
uint16_t X_Resolution;
|
||||
uint16_t Y_Resolution;
|
||||
uint8_t Number_Of_Touch_Support;
|
||||
int ReverseX;
|
||||
int ReverseY;
|
||||
int SwithX2Y;
|
||||
int SoftwareNoiseReduction;
|
||||
}gt911_t;
|
||||
|
||||
void lvgl_demo_init(void);
|
42
EC600U_lvgl/inc/ui/fs_function.h
Normal file
42
EC600U_lvgl/inc/ui/fs_function.h
Normal file
@ -0,0 +1,42 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
#include "time.h"
|
||||
#include "ql_fs.h"
|
||||
|
||||
#define FILE_LETTER 'SD' //盘符
|
||||
#define CHAR_READ_LENGTH 80 //每次读取文件的长度
|
||||
|
||||
struct Device_Data
|
||||
{
|
||||
int id; //设备桩点号
|
||||
int start_hour;
|
||||
int start_min;
|
||||
int start_second;
|
||||
int end_hour;
|
||||
int end_min;
|
||||
int end_second;
|
||||
float max_depth; //设备所处的深度
|
||||
float max_V; //设备当前喷浆量
|
||||
float average_I; //设备在两次记录之间的平均电流
|
||||
int count; //该id出现的次数
|
||||
int offset; //该id第一次出现时的字节偏移量
|
||||
};
|
||||
|
||||
struct Return_Data {
|
||||
int id_count;
|
||||
struct Device_Data dataArr[64]; // 假设数组长度为10
|
||||
};
|
||||
|
||||
#define SAME_ID_MAX_NUM 20
|
||||
struct ChartData{
|
||||
float depth[SAME_ID_MAX_NUM];
|
||||
float V[SAME_ID_MAX_NUM];
|
||||
float I[SAME_ID_MAX_NUM];
|
||||
char time[SAME_ID_MAX_NUM][10];
|
||||
int same_id_count;
|
||||
};
|
||||
|
||||
int8_t findDataFile(uint16_t year,uint8_t month,uint8_t day);
|
||||
void dealdata(char*buffer,int last_file,int last_i,struct Return_Data *newStruct);
|
||||
void readDataFromFile(QFILE fd, struct Return_Data * data);
|
||||
void setDataToTables(struct Return_Data* dataArray,int page,int page_count);
|
||||
void setDataToChart(QFILE fd, int offset ,int current_id,struct ChartData* chart_data);
|
11
EC600U_lvgl/inc/ui/ui.h
Normal file
11
EC600U_lvgl/inc/ui/ui.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include "lvgl.h"
|
||||
//screen4
|
||||
#define TEST 0
|
||||
|
||||
extern lv_obj_t * ui_Screen4;
|
||||
extern lv_obj_t * ui_Screen4_left_btn;
|
||||
extern lv_obj_t * ui_Screen4_right_btn;
|
||||
/************************************************************************************************************/
|
||||
/************************************************************************************************************/
|
||||
/************************************************************************************************************/
|
||||
void ui_init(void);
|
133
EC600U_lvgl/inc/ui/ui_screen1.h
Normal file
133
EC600U_lvgl/inc/ui/ui_screen1.h
Normal file
@ -0,0 +1,133 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
|
||||
#define LEFT_BUTTON_X (0)
|
||||
#define LEFT_BUTTON_Y (0)
|
||||
#define RIGHT_BUTTON_X (450)
|
||||
#define RIGHT_BUTTON_Y (0)
|
||||
#define START_BUTTON_X (440)
|
||||
#define START_BUTTON_Y (190)
|
||||
#define STOP_BUTTON_X (440)
|
||||
#define STOP_BUTTON_Y (240)
|
||||
|
||||
/************************************************************************************************************/
|
||||
/* 自定义图标集合 */
|
||||
#define ICON_GRAPH_USER_14 "\xEE\xA0\x8F " // 0xe80f 曲线图图标
|
||||
#define ICON_INCLINATION_USER_14 "\xEE\x98\x88 " // 0xe608 倾角测量图标
|
||||
#define ICON_RECORD_USER_14 "\xEE\x98\xB0 " // 0xe630 记录图标
|
||||
#define ICON_OPERATION_USER_14 "\xEE\x99\x82 " // 0xe642 作业图标
|
||||
#define ICON_LIGHT_20 "\xEE\x98\x93 " // 0xe613 亮度图标
|
||||
#define ICON_SET_SYS_24 "\xEE\x98\x99 " // 0xe619 系统图标
|
||||
#define ICON_SET_ABOUT_24 "\xEE\x98\x80 " // 0xe600 关于图标
|
||||
#define ICON_SET_USER_24 "\xEE\x98\xBD " // 0xe63d 用户图标
|
||||
#define ICON_SET_FLOW_24 "\xEE\x98\xA5 " // 0xe625 流量计图标
|
||||
#define ICON_SET_DEPTH_24 "\xEE\xA2\xA9 " // 0xe8a9 深度计图标
|
||||
#define ICON_SET_CAL_24 "\xEE\x9A\x8F " // 0xe68f 校准图标
|
||||
#define ICON_INC_STATE_10 "\xEE\x9B\xA6 " // 0xe68f 倾角目标图标
|
||||
#define ICON_GPS_ON_STATE_24 "\xEE\x98\x80 " // 0xe600 GPS开启图标
|
||||
#define ICON_GPS_OFF_STATE_24 "\xEE\x98\x81 " // 0xe601 GPS关闭图标
|
||||
#define ICON_SIM_OFF_STATE_24 "\xEE\x9A\x98 " // 0xe698 sim卡未填充图标
|
||||
#define ICON_SIM_WARN_STATE_24 "\xEE\x9A\xA9 " // 0xe6a9 sim卡故障图标
|
||||
#define ICON_SIM_ON_STATE_24 "\xEE\x9A\xAA " // 0xe6aa sim卡已填充图标
|
||||
#define ICON_NET_ON_STATE_24 "\xEE\x98\xA3 " // 0xe623 连接网络图标
|
||||
#define ICON_NET_OFF_STATE_24 "\xEE\x98\xA4 " // 0xe624 断开网络图标
|
||||
#define ICON_NET_WARN_STATE_24 "\xEE\x99\x93 " // 0xe653 网络故障图标
|
||||
#define ICON_SERVER_CON_ON_STATE_24 "\xEE\x9A\xB8 " // 0xe6b8 服务器连接状态图标
|
||||
#define ICON_SERVER_CON_DOWNLOAD_STATE_24 "\xEE\x98\x82 " // 0xe602 服务器数据下载状态图标
|
||||
#define ICON_SERVER_CON_UPLOAD_STATE_24 "\xEE\x98\x83 " // 0xe603 服务器数据上传状态图标
|
||||
#define ICON_SERVER_CON_NO_STATE_24 "\xEE\x98\x84 " // 0xe604 服务器无连接连接状态图标
|
||||
#define ICON_GPS_CSQ_5_24 "\xEE\x98\xAB " // 0xe62b GPS信号5格图标
|
||||
#define ICON_GPS_CSQ_4_24 "\xEE\x98\xB4 " // 0xe634 GPS信号4格图标
|
||||
#define ICON_GPS_CSQ_3_24 "\xEE\x98\xB5 " // 0xe635 GPS信号3格图标
|
||||
#define ICON_GPS_CSQ_2_24 "\xEE\x98\xB6 " // 0xe636 GPS信号2格图标
|
||||
#define ICON_GPS_CSQ_1_24 "\xEE\x98\xB7 " // 0xe637 GPS信号1格图标
|
||||
#define ICON_GPS_CSQ_24 "\xEE\x9A\x80 " // 0xe680 GPS信号图标
|
||||
#define ICON_GNET_CSQ_4_24 "\xEE\x9A\x81 " // 0xe681 4G信号4格图标
|
||||
#define ICON_GNET_CSQ_3_24 "\xEE\x98\x93 " // 0xe613 4G信号3格图标
|
||||
#define ICON_GNET_CSQ_2_24 "\xEE\x98\x91 " // 0xe611 4G信号2格图标
|
||||
#define ICON_GNET_CSQ_1_24 "\xEE\x98\x94 " // 0xe614 4G信号1格图标
|
||||
#define ICON_GNET_CSQ_0_24 "\xEE\x98\x92 " // 0xe612 4G信号0格图标
|
||||
#define THEME_COLOR_LIGHT_MODE_DEF 0xFFFFFF
|
||||
#define THEME_COLOR_DARK_MODE_DEF 0x292831
|
||||
#define THEME_COLOR_DODER_BLUE_DEF 0x1E90FF
|
||||
#define THEME_COLOR_WHITE_DEF 0xFFFFFF
|
||||
#define THEME_COLOR_BLACK_DEF 0x000000
|
||||
#define THEME_COLOR_SLATE_GREY_DEF 0x708090
|
||||
#define THEME_COLOR_SPRING_GREEN_DEF 0x00FF7F
|
||||
#define THEME_COLOR_FIRE_BRICK1_DEF 0xFF3030
|
||||
#define THEME_COLOR_FIRE_BRICK3_DEF 0xCD2626
|
||||
#define THEME_COLOR_YELLOW_DEF 0xFFFF00
|
||||
#define THEME_COLOR_GRAY81_DEF 0xCFCFCF
|
||||
#define THEME_COLOR_SEA_GREEN1_DEF 0x54FF9F
|
||||
#define THEME_COLOR_BTN_BLUE_DEF 0x2196F3
|
||||
#define THEME_COLOR_SNOW3_DEF 0xCDC9C9
|
||||
#define THEME_COLOR_SNOW4_DEF 0x8B8989
|
||||
#define THEME_COLOR_SEAGREEN2_DEF 0x4EEE94
|
||||
#define THEME_COLOR_GOLD3_DEF 0xCDAD00
|
||||
|
||||
/************************************************************************************************************/
|
||||
// 字体合集
|
||||
extern const lv_font_t ui_font_12;
|
||||
extern const lv_font_t lv_font_montserrat_16;
|
||||
extern const lv_font_t lv_font_montserrat_20;
|
||||
extern const lv_font_t lv_font_montserrat_42;
|
||||
extern const lv_font_t system_status_icon_24;
|
||||
|
||||
extern lv_obj_t *ui_Screen1; // 用于切屏
|
||||
extern lv_obj_t *current_bar; // 显示电流的bar
|
||||
extern lv_obj_t *SIM_card_label; // sim卡状态
|
||||
extern lv_obj_t *gnet_dsc_label; // 4G描述label
|
||||
extern lv_obj_t *g_gnet_label; // 4G状态label
|
||||
extern lv_obj_t *gps_level_label; // gps状态
|
||||
extern lv_obj_t *net_connect_label; // 网络连接状态
|
||||
extern lv_obj_t *server_connect_label; // 服务器连接状态
|
||||
extern lv_obj_t *screen1_led; // 用于更改led颜色
|
||||
extern lv_obj_t *screen1_play_btn_label;
|
||||
|
||||
extern lv_obj_t *screen1_measurements_label1;
|
||||
extern lv_obj_t *screen1_measurements_label2;
|
||||
extern lv_obj_t *screen1_measurements_label3;
|
||||
extern lv_obj_t *screen1_measurements_label4;
|
||||
extern lv_obj_t *screen1_measurements_label5;
|
||||
extern lv_obj_t *screen1_measurements_label6;
|
||||
extern lv_obj_t *screen1_measurements_label7;
|
||||
extern lv_obj_t *screen1_measurements_label8;
|
||||
extern lv_obj_t *screen1_measurements_label9;
|
||||
|
||||
#pragma pack(2)
|
||||
typedef struct
|
||||
{
|
||||
short enc_val; // 编码器原始值 无效
|
||||
short ss_1; // 1通道瞬时流量
|
||||
short ss_2;
|
||||
short flow_10cm_1; // 1通道瞬时流量
|
||||
short flow_10cm_2;
|
||||
uint16_t accumulate1;
|
||||
uint16_t accumulate2;
|
||||
uint16_t one_pile_work_time;
|
||||
int ll_1; // 1通道累计流量
|
||||
int ll_2;
|
||||
short speed; // 速度
|
||||
short depth; // 深度
|
||||
unsigned short Ia; // a通道电流值
|
||||
unsigned short Ib;
|
||||
unsigned short Ic;
|
||||
unsigned short cnt; // 计数 无效
|
||||
short angle_x; // x轴角度
|
||||
short angle_y;
|
||||
short angle_z;
|
||||
int dx; // 经度
|
||||
int dy; // 维度
|
||||
unsigned short id; // 桩点号
|
||||
} user_data_t;
|
||||
#pragma pack() /*取消指定对齐,恢复缺省对齐*/
|
||||
|
||||
#pragma pack(1)
|
||||
typedef enum
|
||||
{
|
||||
WORK = 0x0200,
|
||||
PAUSE = 0x0100,
|
||||
STOP = 0x0000,
|
||||
} MACHINE_WORK_STATE;
|
||||
#pragma pack()
|
||||
|
||||
void ui_screen1_init(void);
|
144
EC600U_lvgl/inc/ui/ui_screen2.h
Normal file
144
EC600U_lvgl/inc/ui/ui_screen2.h
Normal file
@ -0,0 +1,144 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
|
||||
#define THEME_COLOR_BTN_BLUE_DEF 0x2196F3
|
||||
#define THEME_COLOR_WHITE_DEF 0xFFFFFF
|
||||
|
||||
extern const lv_font_t ui_font_16;
|
||||
extern lv_obj_t * ui_Screen2;
|
||||
|
||||
struct Dropdown_t{
|
||||
int dropdown_size[2];
|
||||
int dropdown_align[2];
|
||||
char dropdown_options[64];
|
||||
char dropdown_dsc[32];
|
||||
};
|
||||
|
||||
struct Textarea_t{
|
||||
int num;
|
||||
int label_size[14][2];
|
||||
int label_align[14][2];
|
||||
char label_text[14][32];
|
||||
int textarea_size[14][2];
|
||||
int textarea_align[14][2];
|
||||
char textarea_default_data[14][10];
|
||||
};
|
||||
|
||||
struct Btn_t{
|
||||
lv_obj_t * btn_p[3];
|
||||
int btn_align[3][2];
|
||||
void (*set_cb)(lv_event_t * e);
|
||||
void (*reset_cb)(lv_event_t * e);
|
||||
void (*default_cb)(lv_event_t * e);
|
||||
};
|
||||
|
||||
/**********************************************************************************************************/
|
||||
struct _ch
|
||||
{
|
||||
uint16_t ad_4ma;
|
||||
uint16_t ad_20ma;
|
||||
};
|
||||
|
||||
typedef struct _cal_4_20ma_t
|
||||
{
|
||||
uint16_t magic;
|
||||
struct _ch ch[2];
|
||||
}cal_4_20ma_t;
|
||||
|
||||
/**********************************************************************************************************/
|
||||
struct ad_flow_cal_t
|
||||
{
|
||||
int16_t flow_min;
|
||||
int16_t flow_max;
|
||||
}; //存储ad转换的最大流量和最小流量
|
||||
|
||||
typedef struct _flow_config_t
|
||||
{
|
||||
uint16_t magic; //可能是一个用于标识流量配置的特殊字段或标志?
|
||||
uint16_t input_type; // 1 : 4~20ma 2: 0~3.6K
|
||||
int16_t min_flow[2]; // 小流量切除
|
||||
struct ad_flow_cal_t ad_cal[2];
|
||||
uint16_t pulse_coef[2]; //可能代表了脉冲输出的系数或倍率?
|
||||
uint16_t rsv[6]; //可能是预留给未来扩展使用的保留字段?
|
||||
}flow_config_t;
|
||||
|
||||
/**********************************************************************************************************/
|
||||
typedef struct _depth_config_t
|
||||
{
|
||||
uint16_t magic;
|
||||
uint8_t input_type; // 0:正交 1:正交反向 2:方向脉冲 3:方向脉冲反向
|
||||
uint8_t port; // 编码器端口
|
||||
uint16_t N; //编码器系数分子
|
||||
uint16_t M; //编码器系数分母
|
||||
int16_t min_depth; // 最小深度 mm
|
||||
int16_t max_depth; // 最大深度 mm
|
||||
int16_t sample_depth; // 采样深度 mm
|
||||
int16_t depth_offset; // 默认深度偏移
|
||||
int16_t min_valid_depth; // 最小有效深度
|
||||
int16_t inc_pile_depth; // 允许换桩深度
|
||||
uint16_t current_on_threshold; // 行走电机开启电流
|
||||
uint16_t current_off_threshold; // 行走电机关闭电流
|
||||
uint16_t move_on_duration; // 持续时间
|
||||
uint16_t move_off_duration; // 持续时间
|
||||
uint16_t move_current_channel; //行走电流通道
|
||||
}depth_config_t;
|
||||
|
||||
typedef struct _check_t
|
||||
{
|
||||
uint8_t id;
|
||||
uint16_t addr;//该数据在modbus寄存器中的地址
|
||||
uint8_t type;//该数据类型
|
||||
uint8_t decimal_places;//如果该数据是浮点型有几位小数
|
||||
uint16_t max_num;//该数据的最大值
|
||||
int16_t min_num;
|
||||
}check_t;
|
||||
|
||||
#define TYPE_INT8 0
|
||||
#define TYPE_UINT8 1
|
||||
#define TYPE_INT16 2
|
||||
#define TYPE_UINT16 3
|
||||
#define TYPE_FLOAT 4 //数据类型为浮点型
|
||||
|
||||
#define SAVE_CMD (0x55aa)
|
||||
#define CAL_4_20MA_ADDR (384)
|
||||
#define CAL1_AD_4MA_ADDR (CAL_4_20MA_ADDR + 1)
|
||||
#define CAL1_AD_20MA_ADDR (CAL_4_20MA_ADDR + 2)
|
||||
#define CAL2_AD_4MA_ADDR (CAL_4_20MA_ADDR + 3)
|
||||
#define CAL2_AD_20MA_ADDR (CAL_4_20MA_ADDR + 4)
|
||||
|
||||
#define FLOW_CONFIG_ADDR (CAL_4_20MA_ADDR + (sizeof(cal_4_20ma_t) + 15)/16*8)
|
||||
#define FLOW_INPUT_TYPE_ADDR (FLOW_CONFIG_ADDR + 1)
|
||||
#define FLOW_MIN_FLOW1_ADDR (FLOW_CONFIG_ADDR + 2)
|
||||
#define FLOW_MIN_FLOW2_ADDR (FLOW_CONFIG_ADDR + 3)
|
||||
#define FLOW_AD_CAL1_FLOW_MIN_ADDR (FLOW_CONFIG_ADDR + 4)
|
||||
#define FLOW_AD_CAL1_FLOW_MAX_ADDR (FLOW_CONFIG_ADDR + 5)
|
||||
#define FLOW_AD_CAL2_FLOW_MIN_ADDR (FLOW_CONFIG_ADDR + 6)
|
||||
#define FLOW_AD_CAL2_FLOW_MAX_ADDR (FLOW_CONFIG_ADDR + 7)
|
||||
#define FLOW_PAUSE_COEF1_ADDR (FLOW_CONFIG_ADDR + 8)
|
||||
#define FLOW_PAUSE_COEF2_ADDR (FLOW_CONFIG_ADDR + 9)
|
||||
|
||||
#define DEPTH_CONFIG_ADDR (FLOW_CONFIG_ADDR + (sizeof(flow_config_t) + 15)/16*8)
|
||||
#define DEPTH_INPUT_TYPE_ADDR (DEPTH_CONFIG_ADDR + 1) //高八位
|
||||
#define DEPTH_PORT_ADDR (DEPTH_CONFIG_ADDR + 1) //低八位
|
||||
#define DEPTH_ENC_N_ADDR (DEPTH_CONFIG_ADDR + 2)
|
||||
#define DEPTH_ENC_M_ADDR (DEPTH_CONFIG_ADDR + 3)
|
||||
#define DEPTH_MIN_DEPTH_ADDR (DEPTH_CONFIG_ADDR + 4)
|
||||
#define DEPTH_MAX_DEPTH_ADDR (DEPTH_CONFIG_ADDR + 5)
|
||||
#define DEPTH_SAMPLE_DEPTH_ADDR (DEPTH_CONFIG_ADDR + 6)
|
||||
#define DEPTH_OFFSET_ADDR (DEPTH_CONFIG_ADDR + 7)
|
||||
#define DEPTH_MIN_VALID_ADDR (DEPTH_CONFIG_ADDR + 8)
|
||||
#define DEPTH_INC_PILE_ADDR (DEPTH_CONFIG_ADDR + 9)
|
||||
#define DEPTH_CUR_ON_ADDR (DEPTH_CONFIG_ADDR + 10)
|
||||
#define DEPTH_CUR_OFF_ADDR (DEPTH_CONFIG_ADDR + 11)
|
||||
#define DEPTH_MOVE_ON_DUR_ADDR (DEPTH_CONFIG_ADDR + 12)
|
||||
#define DEPTH_MOVE_OFF_DUR_ADDR (DEPTH_CONFIG_ADDR + 13)
|
||||
#define DEPTH_MOVE_CUR_CH_ADDR (DEPTH_CONFIG_ADDR + 14)
|
||||
|
||||
#define FLOW_INPUT_TYPE_MODE1 (1) //4-20ma
|
||||
#define FLOW_INPUT_TYPE_MODE2 (2) //0-3.6k
|
||||
|
||||
#define DEPTH_INPUT_TYPE_MODE1 (0)
|
||||
#define DEPTH_INPUT_TYPE_MODE2 (0b100000000) //1<<8
|
||||
#define DEPTH_INPUT_TYPE_MODE3 (0b1000000000) //2<<8
|
||||
#define DEPTH_INPUT_TYPE_MODE4 (0b1100000000) //3<<8
|
||||
|
||||
void ui_screen2_init(void);
|
26
EC600U_lvgl/inc/ui/ui_screen3.h
Normal file
26
EC600U_lvgl/inc/ui/ui_screen3.h
Normal file
@ -0,0 +1,26 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
|
||||
#define THEME_COLOR_WHITE_DEF 0xFFFFFF
|
||||
#define THEME_COLOR_BTN_BLUE_DEF 0x2196F3
|
||||
|
||||
extern const lv_font_t lv_font_chinese_12_name;
|
||||
extern const lv_font_t lv_font_montserrat_24;
|
||||
|
||||
extern lv_obj_t * ui_Screen3;//用来切屏
|
||||
extern lv_obj_t * screen3_calender_dsc_label;
|
||||
extern lv_obj_t * screen3_calender;
|
||||
extern lv_obj_t * screen3_spinbox_dsc_label;
|
||||
extern lv_obj_t * btn_page_plus;
|
||||
extern lv_obj_t * btn_page_reduce;
|
||||
extern lv_obj_t * screen3_spinbox;
|
||||
extern lv_obj_t * scrren3_spinbox_btn;
|
||||
|
||||
extern lv_obj_t * data_table1;
|
||||
extern lv_obj_t * data_table2;
|
||||
extern lv_obj_t * data_table3;
|
||||
extern lv_obj_t * data_table4;
|
||||
extern lv_obj_t * data_table5;
|
||||
extern lv_obj_t * data_table6;
|
||||
extern lv_obj_t * data_table7;
|
||||
extern lv_obj_t * data_table8;
|
||||
void ui_screen3_init(void);
|
5
EC600U_lvgl/inc/ui/ui_screen3_chart.h
Normal file
5
EC600U_lvgl/inc/ui/ui_screen3_chart.h
Normal file
@ -0,0 +1,5 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
|
||||
extern const lv_font_t lv_font_montserrat_24;
|
||||
|
||||
void ui_screen3_chart_init(int num);
|
53
EC600U_lvgl/inc/ui/ui_screen4.h
Normal file
53
EC600U_lvgl/inc/ui/ui_screen4.h
Normal file
@ -0,0 +1,53 @@
|
||||
#include "../../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
|
||||
#define THEME_COLOR_WHITE_DEF 0xFFFFFF
|
||||
#define THEME_COLOR_BTN_BLUE_DEF 0x2196F3
|
||||
|
||||
extern const lv_font_t lv_font_montserrat_16;
|
||||
|
||||
typedef enum{
|
||||
LEVEL_INSTUMENT_PANEL_ALL = 0,
|
||||
LEVEL_INSTUMENT_PANEL_RED,
|
||||
LEVEL_INSTUMENT_PANEL_YELLOW,
|
||||
LEVEL_INSTUMENT_PANEL_GREEN,
|
||||
LEVEL_INSTRUMENT_LED,
|
||||
LEVEL_INSTRUMENT_CROSSHAIR
|
||||
} level_instrument_part_t;
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t * red_bg;
|
||||
lv_obj_t * yellow_bg;
|
||||
lv_obj_t * green_bg;
|
||||
lv_obj_t * horizontal_line;
|
||||
lv_obj_t * vertical_line;
|
||||
}my_panel_t;
|
||||
|
||||
typedef struct {
|
||||
my_panel_t * panel;
|
||||
lv_obj_t * led;
|
||||
int size;
|
||||
int x;
|
||||
int y;
|
||||
}level_instrument_t;
|
||||
|
||||
extern level_instrument_t * level_instrument;
|
||||
|
||||
void ui_screen4_init(void);
|
||||
|
||||
//设置控件对应部件大小
|
||||
void level_instrument_set_size(level_instrument_t * level_instrument, lv_coord_t size, level_instrument_part_t part);
|
||||
|
||||
//设置光标在面板上的位置(光标以坐标轴方向为准,基于原点偏移)
|
||||
void level_instrument_set_cursor_pos(level_instrument_t * level_instrument,lv_coord_t x_offset, lv_coord_t y_offset);
|
||||
|
||||
//设置光标颜色
|
||||
void level_instrument_set_cursor_color(level_instrument_t * level_instrument,lv_color_t color);
|
||||
|
||||
//设置光标亮度
|
||||
void level_instrument_set_cursor_brightness(level_instrument_t * level_instrument,uint8_t bright);
|
||||
|
||||
//设置控件整体的对齐
|
||||
void level_instrument_set_align(level_instrument_t * level_instrument,lv_align_t align,lv_coord_t x_offset,lv_coord_t y_offset);
|
||||
|
||||
//设置面板透明度
|
||||
void level_instrument_set_opa(level_instrument_t * level_instrument,lv_opa_t opa);
|
369
EC600U_lvgl/lvgl_demo.c
Normal file
369
EC600U_lvgl/lvgl_demo.c
Normal file
@ -0,0 +1,369 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ql_api_osi.h"
|
||||
|
||||
#include "ql_lcd.h"
|
||||
#include "ql_i2c.h"
|
||||
#include "ql_gpio.h"
|
||||
#include "ql_keypad.h"
|
||||
#include "ql_log.h"
|
||||
#include "../peripheral/inc/ql_pin_cfg.h"
|
||||
#include "ql_fs.h"
|
||||
#include "../../ql-kernel/inc/ql_sdmmc.h"
|
||||
#include "../EC600U_lvgl_lib/lvgl/lvgl.h"
|
||||
#include "lvgl_demo.h"
|
||||
#include "./inc/ui/ui.h"
|
||||
#include "./inc/ui/ui_screen1.h"
|
||||
#include "./inc/ui/fs_function.h"
|
||||
#include "../../kernel/include/osi_api.h"
|
||||
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "lvgldemo", msg, ##__VA_ARGS__)
|
||||
|
||||
#define MY_DISP_HOR_RES 480
|
||||
#define MY_DISP_VER_RES 320
|
||||
|
||||
#define KEY1 QL_KEY_MAP_18 //切换到上一个屏幕
|
||||
#define KEY2 QL_KEY_MAP_19 //切换到下一个屏幕
|
||||
#define KEY3 QL_KEY_MAP_16 //开始/暂停
|
||||
#define KEY4 QL_KEY_MAP_17 //停止
|
||||
|
||||
ql_task_t lvgl_test_task;
|
||||
osiThread_t *lvgl_thread = NULL;// 后台ui事件处理线程
|
||||
static lv_color_t * buf_1 = NULL;
|
||||
static lv_disp_t * disp = NULL;
|
||||
lv_indev_t * indev_touchpad = NULL;
|
||||
lv_indev_t * indev_button = NULL;
|
||||
uint8_t act_screen_id = 1;//记录当前屏幕id
|
||||
extern user_data_t g_ui_user_data;
|
||||
|
||||
uint8_t gt911_array[184] = {
|
||||
0x81, 0x00, 0x04, 0x58, 0x02, 0x0A, 0x0C, 0x20, 0x01, 0x08, 0x28, 0x05, 0x50, // 0x8047 - 0x8053
|
||||
0x3C, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x8054 - 0x8060
|
||||
0x00, 0x89, 0x2A, 0x0B, 0x2D, 0x2B, 0x0F, 0x0A, 0x00, 0x00, 0x01, 0xA9, 0x03, // 0x8061 - 0x806D
|
||||
0x2D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, // 0x806E - 0x807A
|
||||
0x59, 0x94, 0xC5, 0x02, 0x07, 0x00, 0x00, 0x04, 0x93, 0x24, 0x00, 0x7D, 0x2C, // 0x807B - 0x8087
|
||||
0x00, 0x6B, 0x36, 0x00, 0x5D, 0x42, 0x00, 0x53, 0x50, 0x00, 0x53, 0x00, 0x00, // 0x8088 - 0x8094
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x8095 - 0x80A1
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80A2 - 0x80AD
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, // 0x80AE - 0x80BA
|
||||
0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // 0x80BB - 0x80C7
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80C8 - 0x80D4
|
||||
0x02, 0x04, 0x06, 0x08, 0x0A, 0x0F, 0x10, 0x12, 0x16, 0x18, 0x1C, 0x1D, 0x1E, // 0x80D5 - 0x80E1
|
||||
0x1F, 0x20, 0x21, 0x22, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, // 0x80E2 - 0x80EE
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80EF - 0x80FB
|
||||
0x00, 0x00, // 0x80FC - 0x80FD
|
||||
};
|
||||
|
||||
/******************************************************回调函数**********************************************************/
|
||||
static void dispflush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
|
||||
{
|
||||
LOG_INFO("dispflush area x1 = %d, x2 = %d, y1 = %d, y2 = %d",area->x1,area->x2,area->y1,area->y2);
|
||||
ql_lcd_write((uint16_t*)color_p, area->x1 , area->y1, area->x2 , area->y2);
|
||||
lv_disp_flush_ready(disp);
|
||||
}
|
||||
|
||||
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
//LOG_INFO("enter touchpad_read");
|
||||
static lv_coord_t last_x = 0;
|
||||
static lv_coord_t last_y = 0;
|
||||
|
||||
/*检测是否被触摸*/
|
||||
uint8_t state = 255;
|
||||
ql_I2cRead_16bit_addr(i2c_2,0x5D,GT911_STATE_REG,&state,1);
|
||||
|
||||
uint8_t STATE = state;
|
||||
uint8_t touch_number = (state & 0x0f);
|
||||
uint8_t touch_state = (state & 0x80);
|
||||
|
||||
/*代表被触摸了*/
|
||||
if((touch_state == 0x80) && (touch_number >= 1) && (STATE != 255)){
|
||||
|
||||
/*获取触摸坐标,lvgl只支持单点触摸,因此只读取第一个坐标数据*/
|
||||
//LOG_INFO("touch_number = %d, touch_state = %d",touch_number,touch_state);
|
||||
uint8_t low8 = 0;
|
||||
uint8_t high8 = 0;
|
||||
|
||||
ql_I2cRead_16bit_addr(i2c_2,0x5D,(GT911_TP1_REG),&low8,1);
|
||||
ql_I2cRead_16bit_addr(i2c_2,0x5D,(GT911_TP1_REG + 1),&high8,1);
|
||||
last_y = (low8 | (high8 << 8));
|
||||
|
||||
ql_I2cRead_16bit_addr(i2c_2,0x5D,(GT911_TP1_REG + 2),&low8,1);
|
||||
ql_I2cRead_16bit_addr(i2c_2,0x5D,(GT911_TP1_REG + 3),&high8,1);
|
||||
last_x = (low8 | (high8 << 8));
|
||||
|
||||
//LOG_INFO("x = %d, y = %d",last_x,320- last_y);
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
|
||||
/*Set the last pressed coordinates*/
|
||||
data->point.x = last_x;
|
||||
data->point.y = (320 - last_y);
|
||||
|
||||
//清除数据标志位
|
||||
uint8_t flag = 0;
|
||||
ql_I2cWrite_16bit_addr(i2c_2,0x5D,GT911_STATE_REG,&flag,1);
|
||||
}
|
||||
|
||||
void ql_keypad_callback(ql_keymatrix_t keymatrix)
|
||||
{
|
||||
//LOG_INFO("keymap:%d keyout:%d keyin:%d pressd:%d", keymatrix.keymap, keymatrix.keyout, keymatrix.keyin, keymatrix.keystate);
|
||||
}
|
||||
|
||||
static int8_t button_get_pressed_id(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t KEYS[4] = {KEY1,KEY2,KEY3,KEY4};
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
uint32_t press_state = 0;
|
||||
ql_keypad_state(&press_state,KEYS[i]);
|
||||
if(press_state == 1){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
|
||||
{
|
||||
//LOG_INFO("enter button_read");
|
||||
static uint8_t last_btn = 0;
|
||||
int8_t btn_act = button_get_pressed_id();
|
||||
|
||||
if((btn_act == 2) || (btn_act == 3)){//当点击按键为后两个时
|
||||
if(act_screen_id == 3){//如果当前活动屏幕id为第三个屏幕,则返回控制spinbox按键的id
|
||||
btn_act += 2;
|
||||
}
|
||||
else if((act_screen_id == 2) || (act_screen_id == 4)){//当前活动屏幕为第二个或者第四个的时候不对后两个按键做出反应
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(btn_act >= 0) {
|
||||
data->state = LV_INDEV_STATE_PR;
|
||||
last_btn = btn_act;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_REL;
|
||||
}
|
||||
data->btn_id = last_btn;
|
||||
}
|
||||
|
||||
/*************************************************************************************************************************/
|
||||
void gt911_init(void)
|
||||
{
|
||||
ql_I2cInit(i2c_2,STANDARD_MODE);
|
||||
ql_pin_set_gpio(TP_nRST_pin);
|
||||
ql_pin_set_gpio(nTP_INT_pin);
|
||||
|
||||
ql_gpio_init(TP_nRST_GPIO_num,GPIO_OUTPUT,PULL_NONE,LVL_LOW);
|
||||
ql_gpio_init(nTP_INT_GPIO_num,GPIO_OUTPUT,PULL_NONE,LVL_LOW);
|
||||
|
||||
//设置从机地址0xBA
|
||||
ql_rtos_task_sleep_ms(10);
|
||||
ql_gpio_set_level(TP_nRST_GPIO_num,LVL_HIGH);
|
||||
ql_rtos_task_sleep_ms(10);
|
||||
|
||||
//int转为悬浮输入
|
||||
ql_gpio_init(nTP_INT_GPIO_num,GPIO_INPUT,PULL_NONE,LVL_LOW);
|
||||
ql_rtos_task_sleep_ms(10);
|
||||
|
||||
//复位
|
||||
uint8_t temp = 2;
|
||||
ql_I2cWrite_16bit_addr(i2c_2,GT911_ADDRESS,GT911_CTRL_ADDRESS,&temp,1);
|
||||
|
||||
//更新配置数组
|
||||
gt911_t config = {
|
||||
.X_Resolution = X_RESOLUTION,
|
||||
.Y_Resolution = Y_RESOLUTION,
|
||||
.Number_Of_Touch_Support = MAX_TOUCH_NUMBER,
|
||||
.ReverseX = false,
|
||||
.ReverseY = false,
|
||||
.SoftwareNoiseReduction = true,
|
||||
.SwithX2Y = false,
|
||||
};
|
||||
gt911_array[1] = config.X_Resolution & 0x00FF;
|
||||
gt911_array[2] = (config.X_Resolution >> 8) & 0x00FF;
|
||||
gt911_array[3] = config.Y_Resolution & 0x00FF;
|
||||
gt911_array[4] = (config.Y_Resolution >> 8) & 0x00FF;
|
||||
gt911_array[5] = config.Number_Of_Touch_Support;
|
||||
gt911_array[6] = 0;
|
||||
gt911_array[6] |= config.ReverseY << 7;
|
||||
gt911_array[6] |= config.ReverseX << 6;
|
||||
gt911_array[6] |= config.SwithX2Y << 3;
|
||||
gt911_array[6] |= config.SoftwareNoiseReduction << 2;
|
||||
|
||||
//计算校验和
|
||||
uint8_t buf[2] = {0,0};//第一个下标是校验位,第二个是模式:0代表掉电不保存
|
||||
for(uint8_t i = 0; i < 184; i++){
|
||||
buf[0] += gt911_array[i];
|
||||
}
|
||||
buf[0] = (~buf[0])+1;
|
||||
|
||||
//往0x8047写入配置参数
|
||||
ql_I2cWrite_16bit_addr(i2c_2,GT911_ADDRESS,GT911_CFG_ADDRESS,(uint8_t*)gt911_array,184);
|
||||
|
||||
//往0x80FF写入校验和
|
||||
ql_I2cWrite_16bit_addr(i2c_2,GT911_ADDRESS,GT911_CHECK_REG,(uint8_t*)buf,2);
|
||||
|
||||
//结束复位
|
||||
temp = 0;
|
||||
ql_I2cWrite_16bit_addr(i2c_2,GT911_ADDRESS,GT911_CTRL_ADDRESS,&temp,1);
|
||||
}
|
||||
|
||||
void button_init(void)
|
||||
{
|
||||
ql_keypad_out_e row[QL_KEYPAD_ROW_LENGTH] = {QL_KP_OUT0, QL_KP_OUT1, QL_KP_OUT2, QL_KP_OUT3, QL_KP_OUT4, QL_KP_OUT5};
|
||||
ql_keypad_in_e col[QL_KEYPAD_COL_LENGTH] = {QL_KP_IN0, QL_KP_IN1,QL_KP_IN2, QL_KP_IN3, QL_KP_IN_NO_VALID, QL_KP_IN_NO_VALID};
|
||||
ql_keypad_init(ql_keypad_callback, row, col);
|
||||
}
|
||||
|
||||
/*************************************************************************************************************************/
|
||||
//接收到数据时对相关结构体进行处理
|
||||
void ui_event_process(const uint32_t event_id, const char *param)
|
||||
{
|
||||
/*判断是否为有效id*/
|
||||
if(event_id < 9){
|
||||
LOG_INFO("receive wrong event id, %d",event_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/*根据id进行处理*/
|
||||
switch (event_id)
|
||||
{
|
||||
case 9: //屏1
|
||||
{
|
||||
#if !TEST
|
||||
user_data_t * u_data = (user_data_t *)param;
|
||||
memcpy(&g_ui_user_data, u_data, sizeof(g_ui_user_data));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void lvgl_demo_thread(void *param)
|
||||
{
|
||||
/*初始化ST7796SLCD显示屏*/
|
||||
ql_lcd_init();
|
||||
|
||||
/*初始化GT911触摸屏*/
|
||||
gt911_init();
|
||||
|
||||
/*初始化EC600U按键*/
|
||||
button_init();
|
||||
|
||||
/*初始化lvgl*/
|
||||
lv_init();
|
||||
LOG_INFO("lv_init end");
|
||||
|
||||
/*注册disp驱动*/
|
||||
static lv_disp_draw_buf_t draw_buf_dsc_1;
|
||||
//static lv_color_t buf_1[MY_DISP_HOR_RES * 64];
|
||||
buf_1 = (lv_color_t*)malloc(480 * 320 * sizeof(lv_color_t));
|
||||
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 320);
|
||||
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = MY_DISP_HOR_RES;
|
||||
disp_drv.ver_res = MY_DISP_VER_RES;
|
||||
disp_drv.flush_cb = dispflush;
|
||||
disp_drv.draw_buf = &draw_buf_dsc_1;
|
||||
|
||||
disp = lv_disp_drv_register(&disp_drv);
|
||||
LOG_INFO("disp init end");
|
||||
|
||||
/*注册touchpad驱动*/
|
||||
static lv_indev_drv_t touchpad_drv;
|
||||
lv_indev_drv_init(&touchpad_drv);
|
||||
touchpad_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
touchpad_drv.read_cb = touchpad_read;
|
||||
indev_touchpad = lv_indev_drv_register(&touchpad_drv);
|
||||
LOG_INFO("touchpad init end");
|
||||
|
||||
/*注册button驱动*/
|
||||
static lv_indev_drv_t button_drv;
|
||||
lv_indev_drv_init(&button_drv);
|
||||
button_drv.type = LV_INDEV_TYPE_BUTTON;
|
||||
button_drv.read_cb = button_read;
|
||||
indev_button = lv_indev_drv_register(&button_drv);
|
||||
|
||||
/*Assign buttons to points on the screen*/
|
||||
static const lv_point_t btn_points[6] = {
|
||||
{0, 0}, //切到上一个界面
|
||||
{450, 0}, //切刀下一个界面
|
||||
{420, 170}, //screen1 开始/暂停
|
||||
{420, 240}, //screen1 停止
|
||||
{300, 0}, //screen3 减少页数btn
|
||||
{410, 0}, //screen3 增加页数btn
|
||||
};
|
||||
lv_indev_set_button_points(indev_button, btn_points);
|
||||
LOG_INFO("button init end");
|
||||
|
||||
/*demo*/
|
||||
ui_init();
|
||||
LOG_INFO("ui_init end");
|
||||
|
||||
|
||||
lvgl_thread = osiThreadCurrent();
|
||||
|
||||
while (1)
|
||||
{
|
||||
osiEvent_t waitevent;
|
||||
lv_timer_handler();
|
||||
lv_tick_inc(10);
|
||||
|
||||
if(osiEventTryWait(lvgl_thread, &waitevent,20)){
|
||||
LOG_INFO("waitevent id = %d",waitevent.id);
|
||||
char *context = (char *)waitevent.param1;
|
||||
ui_event_process(waitevent.id, context);
|
||||
}
|
||||
|
||||
ql_rtos_task_sleep_ms(10);
|
||||
}
|
||||
}
|
||||
|
||||
void lvgl_demo_init(void)
|
||||
{
|
||||
ql_pin_set_func(QL_PIN_SDMMC_CMD , QL_PIN_SDMMC_MODE_FUNC);
|
||||
ql_pin_set_func(QL_PIN_SDMMC_DATA_0 , QL_PIN_SDMMC_MODE_FUNC);
|
||||
ql_pin_set_func(QL_PIN_SDMMC_DATA_1 , QL_PIN_SDMMC_MODE_FUNC);
|
||||
ql_pin_set_func(QL_PIN_SDMMC_DATA_2 , QL_PIN_SDMMC_MODE_FUNC);
|
||||
ql_pin_set_func(QL_PIN_SDMMC_DATA_3 , QL_PIN_SDMMC_MODE_FUNC);
|
||||
ql_pin_set_func(QL_PIN_SDMMC_CLK , QL_PIN_SDMMC_MODE_FUNC);
|
||||
LOG_INFO("ql_sdmmc_mount err = %d",ql_sdmmc_mount());
|
||||
|
||||
QlOSStatus err = ql_rtos_task_create(&lvgl_test_task, 1024*10, 12, "lvgldemo", lvgl_demo_thread, NULL, 5);
|
||||
if (err != QL_OSI_SUCCESS){
|
||||
LOG_INFO("lvgl demo task created failed");
|
||||
}
|
||||
}
|
||||
|
||||
// LOG_INFO("findDataFile err = %d",findDataFile(2024,1,10));
|
||||
// LOG_INFO("findDataFile err = %d",findDataFile(2024,1,1));
|
||||
// LOG_INFO("findDataFile err = %d",findDataFile(2024,1,12));
|
||||
// LOG_INFO("findDataFile err = %d",findDataFile(2023,1,10));
|
||||
|
||||
// int fd = ql_fopen("SD:2024/01/10.txt","rb+");
|
||||
// struct Return_Data data = {0};
|
||||
// readDataFromFile(fd,&data);
|
||||
// LOG_INFO("id count = %d",data.id_count);
|
||||
// if (data.id_count > 0) {
|
||||
// for (uint8_t i = 0; i < data.id_count; i++) {
|
||||
// LOG_INFO("id = %d", data.dataArr[i].id);
|
||||
// LOG_INFO("start_time = %02d:%02d:%02d", data.dataArr[i].start_hour, data.dataArr[i].start_min, data.dataArr[i].start_second);
|
||||
// LOG_INFO("end_time = %02d:%02d:%02d", data.dataArr[i].end_hour, data.dataArr[i].end_min, data.dataArr[i].end_second);
|
||||
// LOG_INFO("max_depth = %.2f", data.dataArr[i].max_depth);
|
||||
// LOG_INFO("max_V = %.2f", data.dataArr[i].max_V);
|
||||
// LOG_INFO("average_I = %.2f", data.dataArr[i].average_I);
|
||||
// LOG_INFO("count = %d", data.dataArr[i].count);
|
||||
// LOG_INFO("offset = %d", data.dataArr[i].offset);
|
||||
// }
|
||||
// }
|
||||
// ql_fclose(fd);
|
265
EC600U_lvgl/ui/fs_function.c
Normal file
265
EC600U_lvgl/ui/fs_function.c
Normal file
@ -0,0 +1,265 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ql_log.h"
|
||||
#include "../inc/ui/ui_screen3.h"
|
||||
#include "../inc/ui/fs_function.h"
|
||||
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "fsfunction", msg, ##__VA_ARGS__)
|
||||
#define LOG 1
|
||||
struct Return_Data global_file_data_p;
|
||||
int end_count = 0;
|
||||
int current_id = 0;
|
||||
|
||||
/**
|
||||
* func:根据日期查询是否存在对应的数据文件
|
||||
*/
|
||||
int8_t findDataFile(uint16_t year,uint8_t month,uint8_t day)
|
||||
{
|
||||
/*查询目录路径*/
|
||||
char dir_path[32];
|
||||
sprintf(dir_path,"SD:%d/%02d",year,month);
|
||||
#if LOG
|
||||
LOG_INFO("dir_path = %s",dir_path);
|
||||
#endif
|
||||
QDIR *dir = ql_opendir(dir_path);
|
||||
if(dir == NULL){
|
||||
#if LOG
|
||||
LOG_INFO("ql_opendir fail");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
ql_closedir(dir);
|
||||
|
||||
/*查询文件路径*/
|
||||
char file_path[32];
|
||||
sprintf(file_path,"SD:%d/%02d/%02d.txt",year,month,day);
|
||||
#if LOG
|
||||
LOG_INFO("file_path = %s",file_path);
|
||||
#endif
|
||||
QFILE file_fd = ql_fopen(file_path,"rb");
|
||||
if(file_fd <= 0){
|
||||
#if LOG
|
||||
LOG_INFO("ql_fopen fail");
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*查询文件是否为空*/
|
||||
if(ql_fseek(file_fd,0,QL_SEEK_END) <= 0){
|
||||
#if LOG
|
||||
LOG_INFO("ql_fseek fail");
|
||||
#endif
|
||||
ql_fclose(file_fd);
|
||||
return -3;
|
||||
}
|
||||
/*存在该目录下的非空文件*/
|
||||
ql_fclose(file_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析单独的一条数据
|
||||
*/
|
||||
void dealdata(char*buffer,int last_file,int last_i,struct Return_Data *newStruct)
|
||||
{
|
||||
|
||||
int id = 0 ;
|
||||
time_t utc_time = 0;
|
||||
struct tm *tm_now;
|
||||
float max_depth = 0;
|
||||
float max_V = 0;
|
||||
float average_I = 0;
|
||||
|
||||
sscanf(buffer + last_i,"%d,%lld,%f,%f,%f",&id,&utc_time,&max_depth,&max_V,&average_I);
|
||||
#if LOG
|
||||
LOG_INFO("id = %d,utc_time = %lld,max_depth = %f,max_V = %f,average_I = %f",id,utc_time,max_depth,max_V,average_I);
|
||||
#endif
|
||||
tm_now = gmtime(&utc_time);
|
||||
|
||||
//处理数据
|
||||
if(current_id != id){
|
||||
current_id = id;
|
||||
//LV_LOG_USER("新的id\n");
|
||||
|
||||
newStruct->dataArr[end_count].count ++;
|
||||
newStruct->dataArr[end_count].id = id;
|
||||
newStruct->dataArr[end_count].max_depth = max_depth;
|
||||
newStruct->dataArr[end_count].max_V = max_V;
|
||||
newStruct->dataArr[end_count].average_I = average_I;
|
||||
|
||||
newStruct->dataArr[end_count].start_hour = tm_now ->tm_hour;
|
||||
newStruct->dataArr[end_count].start_min = tm_now ->tm_min;
|
||||
newStruct->dataArr[end_count].start_second = tm_now ->tm_sec;
|
||||
newStruct->dataArr[end_count].end_hour= tm_now ->tm_hour;
|
||||
newStruct->dataArr[end_count].end_min = tm_now ->tm_min;
|
||||
newStruct->dataArr[end_count].end_second = tm_now ->tm_sec;
|
||||
newStruct->dataArr[end_count].offset = last_file;
|
||||
//LV_LOG_USER("当前id在文件中的指针偏移量为:%d\n",newStruct->dataArr[end_count].offset);
|
||||
|
||||
newStruct->id_count = end_count+1;
|
||||
end_count++;
|
||||
}else if(current_id == id){
|
||||
//LV_LOG_USER("相同id\n");
|
||||
|
||||
newStruct->dataArr[end_count-1].max_depth = (max_depth > newStruct->dataArr[end_count-1].max_depth) ? max_depth : newStruct->dataArr[end_count-1].max_depth;
|
||||
newStruct->dataArr[end_count-1].max_V = (max_V > newStruct->dataArr[end_count-1].max_V) ? max_V : newStruct->dataArr[end_count-1].max_V;
|
||||
newStruct->dataArr[end_count-1].average_I = (newStruct->dataArr[end_count-1].average_I * newStruct->dataArr[end_count-1].count + average_I)/(newStruct->dataArr[end_count-1].count +1);
|
||||
newStruct->dataArr[end_count-1].count += 1;
|
||||
if(newStruct->dataArr[end_count-1].end_hour != tm_now ->tm_hour) newStruct->dataArr[end_count-1].end_hour = tm_now ->tm_hour;
|
||||
if(newStruct->dataArr[end_count-1].end_min != tm_now ->tm_min) newStruct->dataArr[end_count-1].end_min = tm_now ->tm_min;
|
||||
if(newStruct->dataArr[end_count-1].end_second != tm_now ->tm_sec) newStruct->dataArr[end_count-1].end_second = tm_now ->tm_sec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文件内容,将数据存储在指针指向的结构体变量中
|
||||
*/
|
||||
void readDataFromFile(QFILE fd, struct Return_Data * data)
|
||||
{
|
||||
char buffer[CHAR_READ_LENGTH];
|
||||
int last_file = 0;
|
||||
int char_length = 0;
|
||||
int last_i = 0;
|
||||
|
||||
ql_fseek(fd,0,QL_SEEK_END);
|
||||
int end_pos = ql_ftell(fd);
|
||||
ql_fseek(fd,0,QL_SEEK_SET);
|
||||
|
||||
while(1){
|
||||
ql_fread(buffer + char_length, CHAR_READ_LENGTH - char_length, 1, fd);//int br = 0; lv_fs_read(file,buffer+char_length,CHAR_READ_LENGTH-char_length,&br);
|
||||
#if LOG
|
||||
LOG_INFO("buffer: %s",buffer);
|
||||
#endif
|
||||
last_i = 0;
|
||||
|
||||
for(int i = 0; i < CHAR_READ_LENGTH; i++){
|
||||
if(buffer[i]=='\n'){
|
||||
dealdata(buffer,last_file,last_i,data);
|
||||
last_file = last_file + i - last_i + 2;//当前数据在文件中的偏移量=本身+上一行数据的数据长度
|
||||
last_i = i + 1;//下一次读取的起始位置
|
||||
}
|
||||
}
|
||||
|
||||
if(buffer[CHAR_READ_LENGTH-1] != '\n'){
|
||||
char_length = CHAR_READ_LENGTH-last_i;
|
||||
int pos = ql_ftell(fd);// int pos = 0; lv_fs_tell(file,&pos);
|
||||
last_file = pos - char_length;
|
||||
strncpy(buffer,buffer + last_i, CHAR_READ_LENGTH - last_i);
|
||||
}
|
||||
|
||||
// if (feof(file->file_d)) { // 如果已经读完文件,则退出循环
|
||||
// break;
|
||||
// }
|
||||
if(ql_ftell(fd) == end_pos){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入数据结构体,把数据设置到8个table上
|
||||
*/
|
||||
void setDataToTables(struct Return_Data* dataArray, int page, int page_count)
|
||||
{
|
||||
char max_V[10];
|
||||
char max_depth[10];
|
||||
char average_I[10];
|
||||
int end_pos = 0;
|
||||
lv_obj_t * data_tables_in_func[] = {data_table1, data_table2, data_table3, data_table4,data_table5, data_table6, data_table7, data_table8 };
|
||||
|
||||
if(page<page_count){
|
||||
end_pos = 8;
|
||||
}else if(page == page_count){
|
||||
end_pos = dataArray->id_count - 8*(page-1);
|
||||
//清空8个table
|
||||
for(int m=0;m<8;m++){
|
||||
for(int n=0;n<6;n++){
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[m],0,n,"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < end_pos; i++){
|
||||
sprintf(max_V,"%.3f",dataArray->dataArr[(page-1)*8+i].max_V);
|
||||
sprintf(max_depth,"%.3f",dataArray->dataArr[(page-1)*8+i].max_depth);
|
||||
sprintf(average_I,"%.2f",dataArray->dataArr[(page-1)*8+i].average_I);
|
||||
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,0,"%d",dataArray->dataArr[(page-1)*8+i].id);
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,1,"%s",max_V);
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,2,"%s",max_depth);
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,3,"%s",average_I);
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,4,"%d:%d:%d",
|
||||
dataArray->dataArr[(page-1)*8+i].start_hour,
|
||||
dataArray->dataArr[(page-1)*8+i].start_min,
|
||||
dataArray->dataArr[(page-1)*8+i].start_second);
|
||||
lv_table_set_cell_value_fmt(data_tables_in_func[i],0,5,"%d:%d:%d",
|
||||
dataArray->dataArr[(page-1)*8+i].end_hour,
|
||||
dataArray->dataArr[(page-1)*8+i].end_min,
|
||||
dataArray->dataArr[(page-1)*8+i].end_second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取数据设置到chart上
|
||||
*/
|
||||
void setDataToChart(QFILE fd, int offset ,int current_id,struct ChartData* chart_data)
|
||||
{
|
||||
|
||||
char buffer[CHAR_READ_LENGTH];//存储每次读到的字符串
|
||||
int char_length = 0;//记录不完整字符串的长度
|
||||
int same_id_count = 0;
|
||||
|
||||
/*获取长度*/
|
||||
ql_fseek(fd,0,QL_SEEK_END);
|
||||
int end_pos = ql_ftell(fd);
|
||||
|
||||
ql_fseek(fd,offset,LV_FS_SEEK_SET);//lv_fs_seek(file,offset,LV_FS_SEEK_SET);
|
||||
int last_i = 0;
|
||||
while(1){
|
||||
last_i = 0;
|
||||
ql_fread(buffer + char_length, CHAR_READ_LENGTH - char_length, 1, fd);//lv_fs_read(file,buffer+char_length,CHAR_READ_LENGTH-char_length,NULL);
|
||||
//buffer[CHAR_READ_LENGTH] = '\0';
|
||||
|
||||
for(int i = 0; i < CHAR_READ_LENGTH; i++){
|
||||
if(buffer[i]=='\n'){
|
||||
int id = 0 ;
|
||||
time_t utc_time = 0;
|
||||
struct tm *tm_now;
|
||||
float max_depth = 0;
|
||||
float max_V = 0;
|
||||
float average_I = 0;
|
||||
sscanf(buffer + last_i,"%d,%lld,%f,%f,%f",&id,&utc_time,&max_depth,&max_V,&average_I);
|
||||
tm_now = gmtime(&utc_time);
|
||||
|
||||
if(current_id == id){
|
||||
if(same_id_count < SAME_ID_MAX_NUM){
|
||||
|
||||
chart_data->depth[same_id_count] = max_depth;
|
||||
chart_data->V[same_id_count] = max_V;
|
||||
chart_data->I[same_id_count] = average_I;
|
||||
sprintf(chart_data->time[same_id_count], "%d:%d:%d", tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
|
||||
chart_data->same_id_count = same_id_count;
|
||||
same_id_count++;
|
||||
}
|
||||
last_i = i + 1;
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(buffer[CHAR_READ_LENGTH-1] != '\n'){
|
||||
char_length = CHAR_READ_LENGTH-last_i;
|
||||
strncpy(buffer,buffer+last_i,CHAR_READ_LENGTH-last_i);
|
||||
}
|
||||
|
||||
if(ql_ftell(fd) >= end_pos){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
255
EC600U_lvgl/ui/ui.c
Normal file
255
EC600U_lvgl/ui/ui.c
Normal file
@ -0,0 +1,255 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "time.h"
|
||||
|
||||
#include "osi_api.h"
|
||||
#include "lvgl.h"
|
||||
#include "../inc/ui/ui.h"
|
||||
#include "../inc/ui/ui_screen1.h"
|
||||
#include "../inc/ui/ui_screen2.h"
|
||||
#include "../inc/ui/ui_screen3.h"
|
||||
#include "../inc/ui/ui_screen4.h"
|
||||
#include "../inc/ui/fs_function.h"
|
||||
|
||||
#include "ql_fs.h"
|
||||
#include "ql_log.h"
|
||||
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "ui", msg, ##__VA_ARGS__)
|
||||
|
||||
extern const lv_font_t ui_font_16;
|
||||
extern struct Return_Data global_file_data_p; //存储table数据
|
||||
extern int current_id;
|
||||
extern int end_count;
|
||||
extern uint8_t act_screen_id;
|
||||
extern lv_timer_t * ui_screen1_data_timer;
|
||||
|
||||
#if !TEST
|
||||
extern user_data_t g_ui_user_data;
|
||||
#endif
|
||||
extern MACHINE_WORK_STATE current_wort_state;
|
||||
|
||||
void screen1_left_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen4 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen4, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
if(current_wort_state == WORK){
|
||||
lv_timer_pause(ui_screen1_data_timer);
|
||||
}
|
||||
act_screen_id = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void screen1_right_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen2 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen2, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
if(current_wort_state == WORK){
|
||||
lv_timer_pause(ui_screen1_data_timer);
|
||||
}
|
||||
act_screen_id = 2;
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_left_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen1 != NULL)) {
|
||||
#if !TEST
|
||||
memset(&g_ui_user_data, 0x00, sizeof(g_ui_user_data));
|
||||
#endif
|
||||
lv_scr_load_anim(ui_Screen1, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 1;
|
||||
if(current_wort_state == WORK){
|
||||
lv_timer_resume(ui_screen1_data_timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_right_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen3 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen3, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 3;
|
||||
}
|
||||
}
|
||||
|
||||
void screen3_left_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen2 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen2, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 2;
|
||||
}
|
||||
}
|
||||
|
||||
void screen3_right_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen4 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen4, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void screen4_left_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen3 != NULL)) {
|
||||
lv_scr_load_anim(ui_Screen3, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 3;
|
||||
}
|
||||
}
|
||||
|
||||
void screen4_right_btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
if((event_code == LV_EVENT_CLICKED) && (ui_Screen1 != NULL)) {
|
||||
#if !TEST
|
||||
memset(&g_ui_user_data, 0x00, sizeof(g_ui_user_data));
|
||||
#endif
|
||||
lv_scr_load_anim(ui_Screen1, LV_SCR_LOAD_ANIM_NONE, 0, 0, false);
|
||||
act_screen_id = 1;
|
||||
if(current_wort_state == WORK){
|
||||
lv_timer_resume(ui_screen1_data_timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui_screens_create(void)
|
||||
{
|
||||
ui_Screen1 = lv_obj_create(NULL);
|
||||
ui_Screen2 = lv_obj_create(NULL);
|
||||
ui_Screen3 = lv_obj_create(NULL);
|
||||
ui_Screen4 = lv_obj_create(NULL);
|
||||
lv_obj_clear_flag(ui_Screen1,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(ui_Screen2,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(ui_Screen3,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_clear_flag(ui_Screen4,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_disp_load_scr(ui_Screen4);
|
||||
|
||||
lv_obj_t * screen1_left_btn = lv_btn_create(ui_Screen1);
|
||||
lv_obj_t * screen1_right_btn = lv_btn_create(ui_Screen1);
|
||||
lv_obj_t * screen2_left_btn = lv_btn_create(ui_Screen2);
|
||||
lv_obj_t * screen2_right_btn = lv_btn_create(ui_Screen2);
|
||||
lv_obj_t * screen3_left_btn = lv_btn_create(ui_Screen3);
|
||||
lv_obj_t * screen3_right_btn = lv_btn_create(ui_Screen3);
|
||||
lv_obj_t * screen4_left_btn = lv_btn_create(ui_Screen4);
|
||||
lv_obj_t * screen4_right_btn = lv_btn_create(ui_Screen4);
|
||||
|
||||
lv_obj_t * btns[8] = {screen1_left_btn,screen1_right_btn,screen2_left_btn,screen2_right_btn,screen3_left_btn,screen3_right_btn,screen4_left_btn,screen4_right_btn};
|
||||
lv_obj_t * label = NULL;
|
||||
for(uint8_t i = 0; i < 8; i++){
|
||||
|
||||
label = lv_label_create(btns[i]);
|
||||
lv_obj_set_style_text_color(label,lv_color_hex(THEME_COLOR_WHITE_DEF),LV_PART_MAIN);
|
||||
lv_obj_center(label);
|
||||
|
||||
//设置btn
|
||||
lv_obj_set_size(btns[i],30,30);
|
||||
lv_obj_set_style_radius(btns[i], 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btns[i],lv_color_hex(THEME_COLOR_BTN_BLUE_DEF),LV_PART_MAIN);
|
||||
if(i%2){
|
||||
lv_obj_set_pos(btns[i],450,0);
|
||||
lv_label_set_text(label,LV_SYMBOL_RIGHT);
|
||||
}
|
||||
else{
|
||||
lv_obj_set_pos(btns[i],0,0);
|
||||
lv_label_set_text(label,LV_SYMBOL_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(screen1_left_btn,screen1_left_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen1_right_btn,screen1_right_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen2_left_btn,screen2_left_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen2_right_btn,screen2_right_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen3_left_btn,screen3_left_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen3_right_btn,screen3_right_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen4_left_btn,screen4_left_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
lv_obj_add_event_cb(screen4_right_btn,screen4_right_btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
|
||||
lv_obj_t * screens[4] = {ui_Screen1,ui_Screen2,ui_Screen3,ui_Screen4};
|
||||
const char * text[4] = {"作业界面","参数设置","历史数据","水平偏移"};
|
||||
for(uint8_t i = 0; i < 4; i++){
|
||||
label = lv_label_create(screens[i]);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, 0);
|
||||
lv_label_set_text(label,text[i]);
|
||||
lv_obj_align(label,LV_ALIGN_TOP_MID,0,10);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_init(void)
|
||||
{
|
||||
ui_screens_create();//创建4个活动屏幕,并添加可以切屏的btn
|
||||
ui_screen1_init();
|
||||
ui_screen2_init();
|
||||
ui_screen3_init();
|
||||
ui_screen4_init();
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////设置数据////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
/*获取当天日期,并显示到日历label上*/
|
||||
time_t t = time(NULL);
|
||||
struct tm *local_time = localtime(&t);
|
||||
uint16_t year = local_time->tm_year + 1900; // 年份需要加上1900
|
||||
uint8_t month = local_time->tm_mon + 1; // 月份从0开始,需要加1
|
||||
uint8_t day = local_time->tm_mday;
|
||||
|
||||
char calendar_text_str[32];
|
||||
sprintf(calendar_text_str,"%d.%02d.%02d",year,month,day);
|
||||
lv_label_set_text(screen3_calender_dsc_label,calendar_text_str);
|
||||
|
||||
/*将日历设置为对应日期*/
|
||||
lv_calendar_set_showed_date(screen3_calender,year,month);
|
||||
lv_calendar_set_today_date(screen3_calender,year,month,day);
|
||||
|
||||
int8_t result = findDataFile(year,month,day);
|
||||
if(result){
|
||||
/*存在该目录下的非空文件*/
|
||||
char filename[32];
|
||||
sprintf(filename,"%c:/%d/%02d/%02d.txt",FILE_LETTER,year,month,day);
|
||||
|
||||
QFILE file_fd = ql_fopen(filename,"rb");
|
||||
|
||||
readDataFromFile(file_fd, &global_file_data_p);
|
||||
|
||||
//重置全局变量“当前id”,“结束计数”, 关闭文件
|
||||
ql_fclose(file_fd);
|
||||
current_id =0;
|
||||
end_count = 0;
|
||||
|
||||
/*根据数据设置控件*/
|
||||
//计算总页数,设置spinbox页数label以及spinbox范围
|
||||
uint8_t page_count = global_file_data_p.id_count/8 + 1;
|
||||
lv_label_set_text_fmt(screen3_spinbox_dsc_label,"/ %d",page_count);
|
||||
lv_spinbox_set_range(screen3_spinbox, 1,page_count);
|
||||
//LV_LOG_USER("different id num is: %d, page_count = %d\n", global_file_data_p.id_count,page_count);
|
||||
|
||||
//根据当前页数和总页数,设置label的数据
|
||||
uint8_t current_page = lv_spinbox_get_value(screen3_spinbox);
|
||||
setDataToTables(&global_file_data_p,current_page,page_count);
|
||||
}
|
||||
else{
|
||||
LOG_INFO(" findDataFile result = %d",result);
|
||||
|
||||
//将显示最大页数的label设为NA
|
||||
lv_label_set_text_fmt(screen3_spinbox_dsc_label,"N/A");
|
||||
|
||||
//取消spinbox翻页btn和手动设置页数btn的可点击flag
|
||||
lv_obj_clear_flag(btn_page_plus,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_clear_flag(btn_page_reduce,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_clear_flag(scrren3_spinbox_btn,LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t * tables[8] = {data_table1,data_table2,data_table3,data_table4,data_table5,data_table6,data_table7,data_table8};
|
||||
for(int i = 0; i < 8; i++){
|
||||
lv_obj_clear_flag(tables[i],LV_OBJ_FLAG_CLICKABLE);
|
||||
}
|
||||
}
|
||||
#endif /*#if 1*/
|
||||
|
||||
|
||||
}
|
464
EC600U_lvgl/ui/ui_screen1.c
Normal file
464
EC600U_lvgl/ui/ui_screen1.c
Normal file
@ -0,0 +1,464 @@
|
||||
#include "../inc/ui/ui_screen1.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "osi_api.h"
|
||||
#include "../../EC600U_uart1/ModbusM.h"
|
||||
#include "ql_log.h"
|
||||
#include "time.h"
|
||||
#include "../inc/ui/ui.h"
|
||||
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "ui_screen1", msg, ##__VA_ARGS__)
|
||||
|
||||
#define DEPTH_REG_ADDR (12)
|
||||
#define gWORD_SIZE (8192)
|
||||
|
||||
lv_obj_t * ui_Screen1;//用于切屏
|
||||
lv_obj_t * current_bar; //显示电流的bar
|
||||
lv_obj_t * current_value;
|
||||
lv_obj_t * SIM_card_label; //sim卡状态
|
||||
lv_obj_t * gnet_dsc_label; //4G描述label
|
||||
lv_obj_t * g_gnet_label; //4G状态label
|
||||
lv_obj_t * gps_level_label;//gps状态
|
||||
lv_obj_t * net_connect_label;//网络连接状态
|
||||
lv_obj_t * server_connect_label;//服务器连接状态
|
||||
lv_obj_t * screen1_led;//用于更改led颜色
|
||||
lv_obj_t * screen1_play_btn_label;//用于更改按钮的图标
|
||||
|
||||
lv_obj_t * screen1_measurements_label1;//速度
|
||||
lv_obj_t * screen1_measurements_label2;//时间(未知)
|
||||
lv_obj_t * screen1_measurements_label3;//深度
|
||||
lv_obj_t * screen1_measurements_label4;//瞬时1
|
||||
lv_obj_t * screen1_measurements_label5;//瞬时2
|
||||
lv_obj_t * screen1_measurements_label6;//10cm1(未知)
|
||||
lv_obj_t * screen1_measurements_label7;//10cm2(未知)
|
||||
lv_obj_t * screen1_measurements_label8;//累计1
|
||||
lv_obj_t * screen1_measurements_label9;//累计2
|
||||
|
||||
extern lv_obj_t * ui_Screen2;
|
||||
extern lv_obj_t * ui_Screen4;
|
||||
#if !TEST
|
||||
extern uint16_t gWordVar[];
|
||||
user_data_t g_ui_user_data;
|
||||
#endif
|
||||
MACHINE_WORK_STATE current_wort_state = STOP;
|
||||
/*********************************************************************************************/
|
||||
|
||||
lv_timer_t * ui_screen1_data_timer;
|
||||
lv_timer_t * ui_screen1_led_timer;
|
||||
|
||||
int8_t led_state = 1;//1:on -1:off
|
||||
static void ui_screen1_led_timer_cb(lv_timer_t *e)
|
||||
{
|
||||
if(current_wort_state == WORK){
|
||||
lv_led_toggle(screen1_led);
|
||||
led_state = led_state * (-1);
|
||||
}
|
||||
else{
|
||||
if(led_state == -1){
|
||||
lv_led_on(screen1_led);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t test_data = 0;
|
||||
static void ui_screen1_data_timer_cb(lv_timer_t *e)
|
||||
{
|
||||
|
||||
#if TEST
|
||||
test_data ++;
|
||||
lv_label_set_text_fmt(screen1_measurements_label1, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label2, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label3, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label4, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label5, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label6, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label7, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label8, "%d", test_data);
|
||||
lv_label_set_text_fmt(screen1_measurements_label9, "%d", test_data);
|
||||
#else
|
||||
char buf[12] = {0};
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.1f", g_ui_user_data.speed / 10.0);
|
||||
lv_label_set_text_fmt(screen1_measurements_label1, "%s", buf);
|
||||
|
||||
/*时间*/
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%d", g_ui_user_data.one_pile_work_time);
|
||||
lv_label_set_text_fmt(screen1_measurements_label2, "%s", buf);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.3f", g_ui_user_data.depth / 1000.0);
|
||||
lv_label_set_text_fmt(screen1_measurements_label3, "%s", buf); // mm转换成cm
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.2f", g_ui_user_data.ss_1 / 100.0); // 1通道瞬时流量
|
||||
lv_label_set_text_fmt(screen1_measurements_label4, "%s", buf);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.2f", g_ui_user_data.ss_2 / 100.0); // 2通道瞬时流量
|
||||
lv_label_set_text_fmt(screen1_measurements_label5, "%s", buf);
|
||||
|
||||
/*10cm流量1&2*/
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.2f", g_ui_user_data.accumulate1 / 100.0); // 10cm累计流量1
|
||||
lv_label_set_text_fmt(screen1_measurements_label6, "%s", buf);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.2f", g_ui_user_data.accumulate2 / 100.0);
|
||||
lv_label_set_text_fmt(screen1_measurements_label7, "%s", buf);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.1f", g_ui_user_data.ll_1 / 100.0); //1通道累计流量
|
||||
lv_label_set_text_fmt(screen1_measurements_label8, "%s", buf);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.1f", g_ui_user_data.ll_2 / 100.0);
|
||||
lv_label_set_text_fmt(screen1_measurements_label9, "%s", buf);
|
||||
|
||||
lv_bar_set_value(current_bar,g_ui_user_data.Ia,LV_ANIM_OFF);
|
||||
|
||||
memset(buf, 0, 12);
|
||||
sprintf(buf, "%.2f", g_ui_user_data.Ia / 10.0);
|
||||
lv_label_set_text_fmt(current_value,"%s",buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
bool start_pause_flag = 0;
|
||||
void play_btn_event_cb(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("play btn clicked");
|
||||
/*stop -> work*/
|
||||
if((current_wort_state == STOP) && (start_pause_flag == 0)){
|
||||
|
||||
LOG_INFO("(current_wort_state == STOP) && (start_pause_flag == 0)");
|
||||
|
||||
/*将数据全部置0*/
|
||||
lv_obj_t * obj[9] = {
|
||||
screen1_measurements_label1,
|
||||
screen1_measurements_label2,
|
||||
screen1_measurements_label3,
|
||||
screen1_measurements_label4,
|
||||
screen1_measurements_label5,
|
||||
screen1_measurements_label6,
|
||||
screen1_measurements_label7,
|
||||
screen1_measurements_label8,
|
||||
screen1_measurements_label9,
|
||||
};
|
||||
for(uint8_t i = 0; i < 9; i++){
|
||||
lv_label_set_text(obj[i],"0");
|
||||
}
|
||||
#if !TEST
|
||||
/*发送启动命令*/
|
||||
gWordVar[DEPTH_REG_ADDR] = ((gWordVar[DEPTH_REG_ADDR] & 0x00ff) | WORK);
|
||||
LOG_INFO("zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1) res = %d",zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1));
|
||||
#else
|
||||
test_data = 0;
|
||||
#endif
|
||||
/*启动定时器,开始显示监测数据*/
|
||||
lv_timer_resume(ui_screen1_data_timer);
|
||||
|
||||
/*更新当前工作状态*/
|
||||
current_wort_state = WORK;
|
||||
|
||||
/*开始按键变成暂停按键,并更新状态*/
|
||||
start_pause_flag = 1;
|
||||
lv_led_set_color(screen1_led,lv_color_hex(THEME_COLOR_SPRING_GREEN_DEF));
|
||||
lv_label_set_text(screen1_play_btn_label,LV_SYMBOL_PAUSE);
|
||||
}
|
||||
/*stop -> pause*/
|
||||
else if((current_wort_state == STOP) && (start_pause_flag == 1)){
|
||||
/*不做反应*/
|
||||
}
|
||||
/*pause -> work*/
|
||||
else if((current_wort_state == PAUSE) && (start_pause_flag == 0)){
|
||||
LOG_INFO("(current_wort_state == PAUSE) && (start_pause_flag == 0)");
|
||||
#if !TEST
|
||||
/*发送启动命令*/
|
||||
gWordVar[DEPTH_REG_ADDR] = ((gWordVar[DEPTH_REG_ADDR] & 0x00ff) | WORK);
|
||||
LOG_INFO("zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1) res = %d",zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1));
|
||||
#endif
|
||||
/*启动定时器,继续监测数据*/
|
||||
lv_timer_resume(ui_screen1_data_timer);
|
||||
|
||||
/*更新当前工作状态*/
|
||||
current_wort_state = WORK;
|
||||
|
||||
/*开始按键变成暂停按键,并更新状态标志*/
|
||||
lv_led_set_color(screen1_led,lv_color_hex(THEME_COLOR_SPRING_GREEN_DEF));
|
||||
lv_label_set_text(screen1_play_btn_label,LV_SYMBOL_PAUSE);
|
||||
|
||||
start_pause_flag = 1;
|
||||
}
|
||||
/*pause -> pause*/
|
||||
else if((current_wort_state == PAUSE) && (start_pause_flag == 1)){
|
||||
/*不做反应*/
|
||||
}
|
||||
/*work -> pause*/
|
||||
else if((current_wort_state == WORK) && (start_pause_flag == 1)){
|
||||
LOG_INFO("(current_wort_state == WORK) && (start_pause_flag == 1)");
|
||||
#if !TEST
|
||||
/*发送暂停命令*/
|
||||
gWordVar[DEPTH_REG_ADDR] = ((gWordVar[DEPTH_REG_ADDR] & 0x00ff) | PAUSE);
|
||||
LOG_INFO("zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1) res = %d",zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1));
|
||||
#endif
|
||||
/*暂停定时器*/
|
||||
lv_timer_pause(ui_screen1_data_timer);
|
||||
|
||||
/*更新当前工作状态*/
|
||||
current_wort_state = PAUSE;
|
||||
|
||||
/*暂停按键变成开始按键,并更新状态标志*/
|
||||
lv_led_set_color(screen1_led,lv_palette_main(LV_PALETTE_YELLOW));
|
||||
lv_label_set_text(screen1_play_btn_label,LV_SYMBOL_PLAY);
|
||||
|
||||
start_pause_flag = 0;
|
||||
}
|
||||
/*work -> work*/
|
||||
else if((current_wort_state == WORK) && (start_pause_flag == 0)){
|
||||
/*不做反应*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop_btn_event_cb(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("stop btn clicked");
|
||||
|
||||
/*stop -> stop*/
|
||||
if(current_wort_state == STOP){
|
||||
/*不做处理*/
|
||||
}
|
||||
else{
|
||||
LOG_INFO("current_wort_state != STOP");
|
||||
lv_timer_pause(ui_screen1_data_timer);
|
||||
|
||||
lv_led_set_color(screen1_led,lv_palette_main(LV_PALETTE_RED));
|
||||
lv_label_set_text(screen1_play_btn_label,LV_SYMBOL_PLAY);
|
||||
start_pause_flag = 0;
|
||||
#if !TEST
|
||||
/*发送终止信号*/
|
||||
gWordVar[DEPTH_REG_ADDR] = ((gWordVar[DEPTH_REG_ADDR] & 0x00ff) | STOP);
|
||||
LOG_INFO("zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1) res = %d",zb_ModBusWordWriteHook(DEPTH_REG_ADDR,1));
|
||||
|
||||
/*清空全局变量*/
|
||||
memset(&g_ui_user_data, 0x00, sizeof(g_ui_user_data));
|
||||
#endif
|
||||
current_wort_state = STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
void ui_screen1_init(void)
|
||||
{
|
||||
#if !TEST
|
||||
memset(&g_ui_user_data, 0x00, sizeof(g_ui_user_data));
|
||||
#endif
|
||||
//sim卡标识
|
||||
SIM_card_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(SIM_card_label, &system_status_icon_24, 0);
|
||||
lv_label_set_text(SIM_card_label, ICON_SIM_OFF_STATE_24);
|
||||
lv_obj_set_pos(SIM_card_label,35,5);
|
||||
|
||||
//4G
|
||||
gnet_dsc_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(gnet_dsc_label, &lv_font_montserrat_14, 0);
|
||||
lv_label_set_text(gnet_dsc_label, "4G");
|
||||
lv_obj_set_pos(gnet_dsc_label,65,10);
|
||||
|
||||
g_gnet_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(g_gnet_label, &system_status_icon_24, 0);
|
||||
lv_label_set_text(g_gnet_label, ICON_GNET_CSQ_4_24);
|
||||
lv_obj_set_pos(g_gnet_label,90,7);
|
||||
|
||||
//网络连接
|
||||
net_connect_label = lv_label_create(ui_Screen1);
|
||||
lv_label_set_text(net_connect_label, ICON_NET_WARN_STATE_24);
|
||||
lv_obj_set_style_text_font(net_connect_label, &system_status_icon_24, 0);
|
||||
lv_obj_set_pos(net_connect_label,120,5);
|
||||
|
||||
//服务器连接
|
||||
server_connect_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(server_connect_label, &system_status_icon_24, 0);
|
||||
lv_label_set_text(server_connect_label, ICON_SERVER_CON_NO_STATE_24);
|
||||
lv_obj_set_pos(server_connect_label,345,5);
|
||||
|
||||
//gps
|
||||
gps_level_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(gps_level_label, &system_status_icon_24, 0);
|
||||
lv_label_set_text(gps_level_label, ICON_GPS_CSQ_24);
|
||||
lv_obj_set_pos(gps_level_label,415,5);
|
||||
|
||||
lv_obj_t * screen1_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(screen1_label, &lv_font_montserrat_14, 0);
|
||||
lv_label_set_text(screen1_label, "GPS");
|
||||
lv_obj_set_pos(screen1_label,380,10);
|
||||
|
||||
//电流bar
|
||||
current_bar = lv_bar_create(ui_Screen1);
|
||||
lv_obj_set_size(current_bar, 32, 234 - 50);
|
||||
lv_bar_set_mode(current_bar, LV_BAR_MODE_RANGE);
|
||||
lv_obj_align(current_bar,LV_ALIGN_LEFT_MID, 10, 0);
|
||||
lv_obj_set_style_pad_all(current_bar, 0, 0);
|
||||
lv_bar_set_range(current_bar, 0, 2000);
|
||||
lv_bar_set_value(current_bar, 150, LV_ANIM_OFF);
|
||||
|
||||
screen1_label = lv_label_create(ui_Screen1);
|
||||
lv_label_set_text(screen1_label,"电流");
|
||||
lv_obj_set_style_text_font(screen1_label, &ui_font_12, 0);
|
||||
lv_obj_align_to(screen1_label, current_bar, LV_ALIGN_OUT_TOP_MID, 0, 0);
|
||||
|
||||
current_value = lv_label_create(ui_Screen1);
|
||||
lv_label_set_text(screen1_label, "150.0");
|
||||
lv_obj_set_style_text_font(screen1_label, &lv_font_montserrat_16, 0);
|
||||
lv_obj_align_to(screen1_label, current_bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
||||
|
||||
//显示实时数据区域
|
||||
int size[9][2] = {
|
||||
{100, 67},{130,67},{130,67},
|
||||
{180,67},{180,67},
|
||||
{180,67},{180,67},
|
||||
{180,67},{180,67}
|
||||
};
|
||||
int align[9][2] = {
|
||||
{-140,33},{-22,33},{110,33},
|
||||
{-100,103},{85,103},
|
||||
{-100,173},{85,173},
|
||||
{-100,243},{85,243}
|
||||
};
|
||||
|
||||
lv_obj_t * obj_i = NULL;
|
||||
const char *g_measurements_dsc[9] = {
|
||||
"速度(m/min)", "时间(min:s)" , "深度(m)",
|
||||
"瞬时流量1(L/m)","瞬时流量2(L/m)",
|
||||
"10CM流量1(L)", "10CM流量2(L)",
|
||||
"累计流量1(L)", "累计流量2(L)"
|
||||
};
|
||||
|
||||
for(int i = 0; i < 9; i++){
|
||||
|
||||
//创建子区域
|
||||
obj_i = lv_obj_create(ui_Screen1);
|
||||
lv_obj_clear_flag(obj_i, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_align(obj_i, LV_ALIGN_TOP_MID, align[i][0], align[i][1]);
|
||||
lv_obj_set_size(obj_i,size[i][0],size[i][1]);
|
||||
|
||||
//创建描述label
|
||||
screen1_label = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_label, &ui_font_12, 0);
|
||||
lv_label_set_text(screen1_label, g_measurements_dsc[i]);
|
||||
lv_obj_align(screen1_label, LV_ALIGN_TOP_MID, 0, -12);
|
||||
|
||||
//创建数据label
|
||||
if(i == 0){
|
||||
screen1_measurements_label1 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label1, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label1, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label1, "0");
|
||||
}
|
||||
else if(i == 1){
|
||||
screen1_measurements_label2 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label2, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label2, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label2, "0");
|
||||
}
|
||||
else if(i == 2){
|
||||
screen1_measurements_label3 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label3, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label3, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label3, "0");
|
||||
}
|
||||
else if(i == 3){
|
||||
screen1_measurements_label4 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label4, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label4, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label4, "0");
|
||||
}
|
||||
else if(i == 4){
|
||||
screen1_measurements_label5 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label5, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label5, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label5, "0");
|
||||
}
|
||||
else if(i == 5){
|
||||
screen1_measurements_label6 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label6, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label6, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label6, "0");
|
||||
}
|
||||
else if(i == 6){
|
||||
screen1_measurements_label7 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label7, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label7, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label7, "0");
|
||||
}
|
||||
else if(i == 7){
|
||||
screen1_measurements_label8 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label8, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label8, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label8, "0");
|
||||
}
|
||||
else if(i == 8){
|
||||
screen1_measurements_label9 = lv_label_create(obj_i);
|
||||
lv_obj_set_style_text_font(screen1_measurements_label9, &lv_font_montserrat_42, 0);
|
||||
lv_obj_align(screen1_measurements_label9, LV_ALIGN_CENTER, 0, 12);
|
||||
lv_label_set_text(screen1_measurements_label9, "0");
|
||||
}
|
||||
}
|
||||
|
||||
//创建右侧按钮与状态灯
|
||||
screen1_led = lv_led_create(ui_Screen1);
|
||||
lv_led_set_color(screen1_led,lv_palette_main(LV_PALETTE_GREY));
|
||||
lv_obj_set_size(screen1_led,45,45);
|
||||
lv_obj_align(screen1_led,LV_ALIGN_TOP_RIGHT,0,40);
|
||||
|
||||
// 添加停止按钮
|
||||
lv_obj_t * screen1_stop_btn = lv_btn_create(ui_Screen1);
|
||||
lv_obj_set_size(screen1_stop_btn,58,58);
|
||||
lv_obj_set_style_bg_color(screen1_stop_btn,lv_color_hex(0xffffff),0);
|
||||
lv_obj_set_pos(screen1_stop_btn,420,240);
|
||||
|
||||
screen1_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(screen1_label, &lv_font_montserrat_20, 0);
|
||||
lv_label_set_text(screen1_label, LV_SYMBOL_STOP);
|
||||
lv_obj_set_pos(screen1_label,440,260);
|
||||
|
||||
// 添加play按钮
|
||||
lv_obj_t * screen1_play_btn = lv_obj_create(ui_Screen1);
|
||||
lv_obj_set_size(screen1_play_btn,58,58);
|
||||
lv_obj_set_style_bg_color(screen1_play_btn,lv_color_hex(0xffffff),0);
|
||||
lv_obj_set_pos(screen1_play_btn,420,170);
|
||||
|
||||
screen1_play_btn_label = lv_label_create(ui_Screen1);
|
||||
lv_obj_set_style_text_font(screen1_play_btn_label, &lv_font_montserrat_20, 0);
|
||||
lv_label_set_text(screen1_play_btn_label, LV_SYMBOL_PLAY);
|
||||
lv_obj_set_pos(screen1_play_btn_label,440,190);
|
||||
|
||||
//点击切换状态灯颜色
|
||||
lv_obj_add_event_cb(screen1_stop_btn, stop_btn_event_cb, LV_EVENT_ALL, NULL);//停止btn
|
||||
lv_obj_add_event_cb(screen1_play_btn, play_btn_event_cb, LV_EVENT_ALL, NULL);//开始btn
|
||||
|
||||
//创建定时器,定时刷新数据
|
||||
if (screen1_measurements_label1 && screen1_measurements_label2 &&
|
||||
screen1_measurements_label3 && screen1_measurements_label4 &&
|
||||
screen1_measurements_label5 && screen1_measurements_label6 &&
|
||||
screen1_measurements_label7 && screen1_measurements_label8 &&
|
||||
screen1_measurements_label9)
|
||||
{
|
||||
ui_screen1_data_timer = lv_timer_create(ui_screen1_data_timer_cb,100,NULL);
|
||||
lv_timer_pause(ui_screen1_data_timer);
|
||||
} else {
|
||||
LOG_INFO(" create data timer cb fail");
|
||||
}
|
||||
|
||||
/*led闪烁定时器*/
|
||||
ui_screen1_led_timer = lv_timer_create(ui_screen1_led_timer_cb,100,NULL);
|
||||
}
|
587
EC600U_lvgl/ui/ui_screen2.c
Normal file
587
EC600U_lvgl/ui/ui_screen2.c
Normal file
@ -0,0 +1,587 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../inc/ui/ui.h"
|
||||
#include "../inc/ui/ui_screen2.h"
|
||||
#include "../../EC600U_uart1/ModbusM.h"
|
||||
|
||||
#include "ql_log.h"
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "ui_screen2", msg, ##__VA_ARGS__)
|
||||
/****************************************************************************************************************************/
|
||||
lv_obj_t *ui_Screen2; // 用来切屏
|
||||
lv_obj_t *screen2_keyboard; // 用来创建btnm
|
||||
lv_obj_t *screen2_btnm_textarea; // 用来创建textarea
|
||||
|
||||
lv_obj_t *screen2_cal_textareas[4] = {NULL, NULL, NULL, NULL}; // 1通道4ma,1通道20ma,2通道4ma,2通道20ma
|
||||
|
||||
lv_obj_t *screen2_flow_input_type_dropdown; // 输入模式
|
||||
// 最小切除流量1,最小切除流量2,电流1最小AD转换流量,电流1最大AD转换流量,电流2最小AD转换流量,电流2最大AD转换流量,脉冲系数1,脉冲系数2
|
||||
lv_obj_t *screen2_flow_textareas[8];
|
||||
|
||||
// 编码器端口,编码器系数分子,编码器系数分母,最小深度mm,最大深度mm,采样深度mm,默认深度偏移,最小有效深度,允许换桩深度,行走电机开启电流,行走电机关闭电流,持续时间,持续时间,行走电流通道
|
||||
lv_obj_t *screen2_depth_textareas[14];
|
||||
lv_obj_t *screen2_depth_input_type_dropdown; // 0:正交 1:正交反向 2:方向脉冲 3:方向脉冲反向
|
||||
lv_obj_t *screen2_dropdown_list;
|
||||
|
||||
cal_4_20ma_t cal_data_struct;
|
||||
flow_config_t flow_data_struct;
|
||||
depth_config_t depth_data_struct;
|
||||
extern lv_obj_t *ui_Screen3;
|
||||
#if !TEST
|
||||
extern uint16_t gWordVar[];
|
||||
#endif
|
||||
|
||||
check_t screen2_cal_check_infos[4] = {
|
||||
{0, CAL1_AD_4MA_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{1, CAL1_AD_20MA_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{2, CAL2_AD_4MA_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{3, CAL2_AD_20MA_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
};
|
||||
|
||||
check_t screen2_flow_check_infos[8] = {
|
||||
{4, FLOW_MIN_FLOW1_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{5, FLOW_MIN_FLOW2_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{6, FLOW_AD_CAL1_FLOW_MIN_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{7, FLOW_AD_CAL1_FLOW_MAX_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{8, FLOW_AD_CAL2_FLOW_MIN_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{9, FLOW_AD_CAL2_FLOW_MAX_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{10, FLOW_PAUSE_COEF1_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{11, FLOW_PAUSE_COEF2_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
};
|
||||
|
||||
check_t screen2_depth_check_infos[14] = {
|
||||
{12, DEPTH_PORT_ADDR, TYPE_UINT8, 0, 1, 0},//深度端口只有两个
|
||||
{13, DEPTH_ENC_N_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{14, DEPTH_ENC_M_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{15, DEPTH_MIN_DEPTH_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{16, DEPTH_MAX_DEPTH_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{17, DEPTH_SAMPLE_DEPTH_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{18, DEPTH_OFFSET_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{19, DEPTH_MIN_VALID_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{20, DEPTH_INC_PILE_ADDR, TYPE_INT16, 0, 32767, -32768},
|
||||
{21, DEPTH_CUR_ON_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{22, DEPTH_CUR_OFF_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{23, DEPTH_MOVE_ON_DUR_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{24, DEPTH_MOVE_OFF_DUR_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
{25, DEPTH_MOVE_CUR_CH_ADDR, TYPE_UINT16, 0, 65535, 0},
|
||||
};
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
void screen2_cal_SAVE_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_cal_SAVE_btn_event clicked");
|
||||
#if !TEST
|
||||
/*通过modbus发送保存cal结构体的命令*/
|
||||
gWordVar[CAL_4_20MA_ADDR] = SAVE_CMD;
|
||||
zb_ModBusWordWriteHook(CAL_4_20MA_ADDR,1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_cal_DEFAULT_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_cal_DEFAULT_btn_event clicked");
|
||||
|
||||
lv_textarea_set_text(screen2_cal_textareas[0], "12740");
|
||||
lv_textarea_set_text(screen2_cal_textareas[1], "63845");
|
||||
lv_textarea_set_text(screen2_cal_textareas[2], "12760");
|
||||
lv_textarea_set_text(screen2_cal_textareas[3], "63953");
|
||||
|
||||
/*发送默认配置信息*/
|
||||
#if !TEST
|
||||
gWordVar[CAL_4_20MA_ADDR] = 0;
|
||||
gWordVar[CAL1_AD_4MA_ADDR] = 12740;
|
||||
gWordVar[CAL1_AD_20MA_ADDR] = 63845;
|
||||
gWordVar[CAL2_AD_4MA_ADDR] = 12760;
|
||||
gWordVar[CAL2_AD_20MA_ADDR] = 63953;
|
||||
zb_ModBusWordWriteHook(CAL_4_20MA_ADDR,5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
void screen2_flow_SAVE_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
// lv_obj_t * obj = lv_event_get_target(e);
|
||||
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_flow_SAVE_btn_event clicked");
|
||||
#if !TEST
|
||||
/*通过modbus发送保存flow结构体的命令*/
|
||||
gWordVar[FLOW_CONFIG_ADDR] = SAVE_CMD;
|
||||
zb_ModBusWordWriteHook(FLOW_CONFIG_ADDR,1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_flow_DEFAULT_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_flow_DEFAULT_btn_event clicked");
|
||||
char default_value[][6] = {"0", "0", "0", "10000", "0", "10000", "6944", "6944"};
|
||||
for (int i = 0; i < 8; i++){
|
||||
lv_textarea_set_text(screen2_flow_textareas[i], default_value[i]);
|
||||
}
|
||||
lv_dropdown_set_selected(screen2_flow_input_type_dropdown, 0);
|
||||
#if !TEST
|
||||
gWordVar[FLOW_CONFIG_ADDR] = 0;
|
||||
gWordVar[FLOW_INPUT_TYPE_ADDR] = FLOW_INPUT_TYPE_MODE1;
|
||||
gWordVar[FLOW_MIN_FLOW1_ADDR] = 0;
|
||||
gWordVar[FLOW_MIN_FLOW2_ADDR] = 0;
|
||||
gWordVar[FLOW_AD_CAL1_FLOW_MIN_ADDR] = 0;
|
||||
gWordVar[FLOW_AD_CAL1_FLOW_MAX_ADDR] = 10000;
|
||||
gWordVar[FLOW_AD_CAL2_FLOW_MIN_ADDR] = 0;
|
||||
gWordVar[FLOW_AD_CAL2_FLOW_MAX_ADDR] = 10000;
|
||||
gWordVar[FLOW_PAUSE_COEF1_ADDR] = 6944;
|
||||
gWordVar[FLOW_PAUSE_COEF2_ADDR] = 6944;
|
||||
zb_ModBusWordWriteHook(FLOW_CONFIG_ADDR,10);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
void screen2_depth_SAVE_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_depth_SAVE_btn_event clicked");
|
||||
#if !TEST
|
||||
/*通过modbus发送保存depth结构体的命令*/
|
||||
gWordVar[DEPTH_CONFIG_ADDR] = SAVE_CMD;
|
||||
zb_ModBusWordWriteHook(DEPTH_CONFIG_ADDR,1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_depth_DEFAULT_btn_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
LOG_INFO("screen2_depth_DEFAULT_btn_event clicked");
|
||||
|
||||
/*将当前栏目的所有文本框都设为默认值*/
|
||||
char depth_default_data[][6] = {"1", "1000", "640", "-100", "12000", "100", "-100", "1000", "-5000", "500", "100", "150", "150", "2"};
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
lv_textarea_set_text(screen2_depth_textareas[i], depth_default_data[i]);
|
||||
}
|
||||
lv_dropdown_set_selected(screen2_depth_input_type_dropdown, 0);
|
||||
|
||||
/*发送默认配置信息*/
|
||||
#if !TEST
|
||||
gWordVar[DEPTH_CONFIG_ADDR] = 0;
|
||||
gWordVar[DEPTH_INPUT_TYPE_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0x00ff) | DEPTH_INPUT_TYPE_MODE1);
|
||||
gWordVar[DEPTH_PORT_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0xff00) | 1);
|
||||
gWordVar[DEPTH_ENC_N_ADDR] = 1000;
|
||||
gWordVar[DEPTH_ENC_M_ADDR] = 640;
|
||||
gWordVar[DEPTH_MIN_DEPTH_ADDR] = -100;
|
||||
gWordVar[DEPTH_MAX_DEPTH_ADDR] = 12000;
|
||||
gWordVar[DEPTH_SAMPLE_DEPTH_ADDR] = 100;
|
||||
gWordVar[DEPTH_OFFSET_ADDR] = -100;
|
||||
gWordVar[DEPTH_MIN_VALID_ADDR] = 1000;
|
||||
gWordVar[DEPTH_INC_PILE_ADDR] = -5000;
|
||||
gWordVar[DEPTH_CUR_ON_ADDR] = 500;
|
||||
gWordVar[DEPTH_CUR_OFF_ADDR] = 100;
|
||||
gWordVar[DEPTH_MOVE_ON_DUR_ADDR] = 150;
|
||||
gWordVar[DEPTH_MOVE_OFF_DUR_ADDR] = 150;
|
||||
gWordVar[DEPTH_MOVE_CUR_CH_ADDR] = 2;
|
||||
zb_ModBusWordWriteHook(DEPTH_CONFIG_ADDR,15);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
/*选择流量输入模式,选择后modbus发送对应值*/
|
||||
void screen2_flow_input_type_dropdown_cb(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_VALUE_CHANGED){
|
||||
uint16_t id = lv_dropdown_get_selected(screen2_flow_input_type_dropdown);
|
||||
LOG_INFO("id = %d",id);
|
||||
#if !TEST
|
||||
//4-20ma
|
||||
if(id == 0){
|
||||
gWordVar[FLOW_INPUT_TYPE_ADDR] = FLOW_INPUT_TYPE_MODE1;
|
||||
}
|
||||
//0-3.6k
|
||||
else if(id == 1){
|
||||
gWordVar[FLOW_INPUT_TYPE_ADDR] = FLOW_INPUT_TYPE_MODE2;
|
||||
}
|
||||
zb_ModBusWordWriteHook(FLOW_INPUT_TYPE_ADDR,1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void list_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t *obj = lv_event_get_target(e);
|
||||
if (code == LV_EVENT_DELETE)
|
||||
{
|
||||
LV_LOG_USER("screen2_dropdown_list is deleted\n");
|
||||
lv_obj_add_flag(screen2_depth_input_type_dropdown, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_remove_event_cb(obj, list_event);
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_depth_input_type_dropdown_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t *obj = lv_event_get_target(e);
|
||||
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
lv_obj_clear_flag(screen2_depth_input_type_dropdown, LV_OBJ_FLAG_CLICKABLE);
|
||||
screen2_dropdown_list = lv_dropdown_get_list(obj);
|
||||
lv_obj_clear_flag(screen2_dropdown_list,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_style_text_font(screen2_dropdown_list, &ui_font_16, 0);
|
||||
lv_obj_add_event_cb(screen2_dropdown_list, list_event, LV_EVENT_ALL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void screen2_depth_input_type_dropdown_event2(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_VALUE_CHANGED)
|
||||
{
|
||||
uint16_t id = lv_dropdown_get_selected(screen2_depth_input_type_dropdown);
|
||||
LOG_INFO("id = %d",id);
|
||||
#if !TEST
|
||||
if(id == 0){//正交
|
||||
gWordVar[DEPTH_INPUT_TYPE_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0x00ff) | DEPTH_INPUT_TYPE_MODE1);
|
||||
}
|
||||
else if(id == 1){//正交反向
|
||||
gWordVar[DEPTH_INPUT_TYPE_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0x00ff) | DEPTH_INPUT_TYPE_MODE2);
|
||||
}
|
||||
else if(id == 2){//方向脉冲
|
||||
gWordVar[DEPTH_INPUT_TYPE_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0x00ff) | DEPTH_INPUT_TYPE_MODE3);
|
||||
}
|
||||
else if(id == 3){//方向脉冲反向
|
||||
gWordVar[DEPTH_INPUT_TYPE_ADDR] = ((gWordVar[DEPTH_INPUT_TYPE_ADDR] & 0x00ff) | DEPTH_INPUT_TYPE_MODE4);
|
||||
}
|
||||
zb_ModBusWordWriteHook(DEPTH_INPUT_TYPE_ADDR,1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
/*当点击回车时,获取显示文本框的值,*/
|
||||
void screen2_btnm_input_data(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t *keyboard = lv_event_get_target(e); // 获取键盘指针
|
||||
check_t *check_info = (check_t *)lv_event_get_user_data(e); // 获取userdata
|
||||
if (check_info != NULL)
|
||||
{
|
||||
//LOG_INFO("id = %d, addr = %d, type = %d, decimal_places = %d, max = %d, min = %d", check_info->id, check_info->addr, check_info->type, check_info->decimal_places, check_info->max_num, check_info->min_num);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_INFO("check_info = NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == LV_EVENT_VALUE_CHANGED)
|
||||
{
|
||||
|
||||
/*将键盘的值实时显示在textarea上*/
|
||||
int id = lv_btnmatrix_get_selected_btn(keyboard); // 获取点击的按钮的序号
|
||||
const char *txt = lv_btnmatrix_get_btn_text(keyboard, id); // 获取点击的按钮的文本内容
|
||||
|
||||
// 当点击回车时
|
||||
if (strcmp(txt, LV_SYMBOL_OK) == 0)
|
||||
{
|
||||
|
||||
/*获取此时显示文本框的字符串值并转为整型*/
|
||||
const char *str = lv_textarea_get_text(screen2_btnm_textarea);
|
||||
//LOG_INFO("str = %s", str);
|
||||
|
||||
int num = 0;
|
||||
if (check_info->type != TYPE_FLOAT)
|
||||
{
|
||||
num = atoi(str);
|
||||
}
|
||||
|
||||
/*判断该值是否在定义域内*/
|
||||
num = (num > check_info->max_num) ? check_info->max_num : ((num < check_info->min_num) ? check_info->min_num : num);
|
||||
char correct_str[20] = {""};
|
||||
itoa(num, correct_str, 10);
|
||||
//LOG_INFO("correct_str = %s", correct_str);
|
||||
|
||||
/*将合适的值赋值给触发事件的文本框上*/
|
||||
if ((check_info->id <= 3) && (check_info->id >= 0))
|
||||
{
|
||||
lv_textarea_set_text(screen2_cal_textareas[check_info->id], correct_str);
|
||||
}
|
||||
else if ((check_info->id >= 4) && (check_info->id <= 11))
|
||||
{
|
||||
lv_textarea_set_text(screen2_flow_textareas[check_info->id - 4], correct_str);
|
||||
}
|
||||
else if((check_info->id >= 12) && (check_info->id <= 25)){
|
||||
lv_textarea_set_text(screen2_depth_textareas[check_info->id - 12], correct_str);
|
||||
}
|
||||
|
||||
/*删除btnm和文本框的控件,并将指针置NULL*/
|
||||
lv_obj_del(screen2_btnm_textarea);
|
||||
lv_obj_del(screen2_keyboard);
|
||||
screen2_btnm_textarea = NULL;
|
||||
screen2_keyboard = NULL;
|
||||
|
||||
/*将num赋值给gWrodVar里对应的寄存器地址,并传输*/
|
||||
#if !TEST
|
||||
if(check_info->id == 12){
|
||||
gWordVar[check_info->addr] = ((gWordVar[check_info->addr] & 0xff00) | (uint8_t)num);
|
||||
}
|
||||
else{
|
||||
if(check_info->type == TYPE_INT16){
|
||||
gWordVar[check_info->addr] = (int16_t)num;
|
||||
}
|
||||
else if(check_info->type == TYPE_UINT16){
|
||||
gWordVar[check_info->addr] = (uint16_t)num;
|
||||
}
|
||||
}
|
||||
zb_ModBusWordWriteHook(check_info->addr, 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*当聚焦textarea时,创建btnm和显示文本框,关联两者,并添加事件函数*/
|
||||
void screen2_btnm_event(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
lv_obj_t *obj = lv_event_get_target(e); // 获取触发事件的文本框的指针
|
||||
check_t *check_info = lv_event_get_user_data(e);
|
||||
if (check_info != NULL)
|
||||
{
|
||||
//LOG_INFO("id = %d, addr = %d, type = %d, decimal_places = %d, max = %d, min = %d", check_info->id, check_info->addr, check_info->type, check_info->decimal_places, check_info->max_num, check_info->min_num);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_INFO("check_info = NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
// 当聚焦textarea时
|
||||
if (event_code == LV_EVENT_FOCUSED)
|
||||
{
|
||||
|
||||
// 创建键盘和textarea
|
||||
screen2_keyboard = lv_keyboard_create(ui_Screen2);
|
||||
lv_obj_clear_flag(screen2_keyboard, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
lv_obj_set_size(screen2_keyboard, 480, 220);
|
||||
lv_obj_align(screen2_keyboard, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_keyboard_set_mode(screen2_keyboard, LV_KEYBOARD_MODE_NUMBER);
|
||||
|
||||
screen2_btnm_textarea = lv_textarea_create(ui_Screen2);
|
||||
lv_obj_set_size(screen2_btnm_textarea, 480, 70);
|
||||
lv_obj_align_to(screen2_btnm_textarea, screen2_keyboard, LV_ALIGN_OUT_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_text_font(screen2_btnm_textarea, &lv_font_montserrat_42, 0);
|
||||
lv_textarea_set_max_length(screen2_btnm_textarea, 5);
|
||||
|
||||
// 关联键盘和文本框
|
||||
lv_keyboard_set_textarea(screen2_keyboard, screen2_btnm_textarea);
|
||||
|
||||
// 添加事件函数
|
||||
lv_obj_add_event_cb(screen2_keyboard, screen2_btnm_input_data, LV_EVENT_VALUE_CHANGED, (void *)check_info); // 把触发事件的控件指针作为userdata传给输入回调函数
|
||||
|
||||
// 获取触发事件的文本框的值显示到显示文本框上
|
||||
const char *textarea_value = lv_textarea_get_text(obj);
|
||||
lv_textarea_set_text(screen2_btnm_textarea, textarea_value);
|
||||
|
||||
// 给文本框添加聚焦状态,清除触发obj的聚焦状态
|
||||
lv_obj_add_state(screen2_btnm_textarea, LV_STATE_FOCUSED);
|
||||
lv_obj_clear_state(obj, LV_STATE_FOCUSED);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************************************************/
|
||||
|
||||
void ui_screen2_init(void)
|
||||
{
|
||||
lv_obj_t *screen2_tabview = lv_tabview_create(ui_Screen2, LV_DIR_TOP, 50);
|
||||
lv_obj_align(screen2_tabview, LV_ALIGN_TOP_MID, 0, 30);
|
||||
lv_obj_set_style_bg_color(screen2_tabview, lv_color_hex(0x000000), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_opa(screen2_tabview, 20, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_font(screen2_tabview, &ui_font_16, 0);
|
||||
|
||||
uint8_t btns_color[2] = {LV_PALETTE_GREEN, LV_PALETTE_BLUE};
|
||||
char btns_text[2][10] = {"保存", "默认"};
|
||||
|
||||
lv_obj_t *screen2_cal_tab = lv_tabview_add_tab(screen2_tabview, "电流");
|
||||
lv_obj_t *screen2_flow_tab = lv_tabview_add_tab(screen2_tabview, "流量");
|
||||
lv_obj_t *screen2_depth_tab = lv_tabview_add_tab(screen2_tabview, "深度");
|
||||
|
||||
// 在screen2_cal_tab上创建
|
||||
uint8_t cal_align[4][2] = {{0, 0}, {0, 45}, {0, 90}, {0, 135}};
|
||||
char cal_text[4][30] = {"1通道AD转换4ma", "1通道AD转换20ma", "2通道AD转换4ma", "2通道AD转换20ma"};
|
||||
char cal_default_value[4][10] = {"12740", "63845", "12760", "63953"};
|
||||
uint8_t textarea_size[4][2] = {{100, 40}, {100, 40}, {100, 40}, {100, 40}};
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
lv_obj_t *label = lv_label_create(screen2_cal_tab);
|
||||
lv_obj_set_size(label, 200, 40);
|
||||
lv_obj_align(label, LV_ALIGN_TOP_LEFT, cal_align[i][0], cal_align[i][1]);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, LV_PART_MAIN);
|
||||
lv_label_set_text(label, cal_text[i]);
|
||||
|
||||
screen2_cal_textareas[i] = lv_textarea_create(screen2_cal_tab);
|
||||
lv_obj_set_style_text_font(screen2_cal_textareas[i], &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
lv_obj_set_size(screen2_cal_textareas[i], textarea_size[i][0], textarea_size[i][1]);
|
||||
lv_obj_align_to(screen2_cal_textareas[i], label, LV_ALIGN_OUT_RIGHT_MID, 0, -8);
|
||||
lv_obj_clear_flag(screen2_cal_textareas[i], LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_textarea_set_text(screen2_cal_textareas[i], cal_default_value[i]);
|
||||
lv_obj_add_event_cb(screen2_cal_textareas[i], screen2_btnm_event, LV_EVENT_FOCUSED, &screen2_cal_check_infos[i]);
|
||||
}
|
||||
|
||||
lv_obj_t *cal_btns[2] = {NULL, NULL};
|
||||
int16_t cal_btns_pos[2][2] = {{290, 170}, {50, 170}};
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
{
|
||||
cal_btns[i] = lv_btn_create(screen2_cal_tab);
|
||||
lv_obj_set_size(cal_btns[i], 140, 50);
|
||||
lv_obj_set_pos(cal_btns[i], cal_btns_pos[i][0], cal_btns_pos[i][1]);
|
||||
lv_obj_set_style_bg_color(cal_btns[i], lv_palette_main(btns_color[i]), 0);
|
||||
lv_obj_set_style_opa(cal_btns[i], 150, 0);
|
||||
|
||||
lv_obj_t *label = lv_label_create(cal_btns[i]);
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, 0);
|
||||
lv_label_set_text(label, btns_text[i]);
|
||||
}
|
||||
lv_obj_add_event_cb(cal_btns[0], screen2_cal_SAVE_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_add_event_cb(cal_btns[1], screen2_cal_DEFAULT_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
// 在screen2_flow_tab创建的
|
||||
lv_obj_t *flow_dd_label = lv_label_create(screen2_flow_tab);
|
||||
lv_obj_set_size(flow_dd_label, 120, 40);
|
||||
lv_obj_align(flow_dd_label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_font(flow_dd_label, &ui_font_16, 0);
|
||||
lv_label_set_text(flow_dd_label, "输入模式");
|
||||
|
||||
screen2_flow_input_type_dropdown = lv_dropdown_create(screen2_flow_tab);
|
||||
lv_obj_set_size(screen2_flow_input_type_dropdown, 130, 40);
|
||||
lv_obj_align_to(screen2_flow_input_type_dropdown, flow_dd_label, LV_ALIGN_OUT_RIGHT_MID, 0, -10);
|
||||
lv_obj_set_style_text_font(screen2_flow_input_type_dropdown, &lv_font_montserrat_16, 0);
|
||||
lv_dropdown_set_options(screen2_flow_input_type_dropdown, "4 ~ 20ma\n0 ~ 3.6k\n");
|
||||
lv_obj_add_event_cb(screen2_flow_input_type_dropdown,screen2_flow_input_type_dropdown_cb,LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
uint16_t flow_label_align[8][2] = {{0, 45}, {0, 90}, {0, 135}, {0, 180}, {0, 225}, {0, 270}, {0, 315}, {0, 360}};
|
||||
char flow_label_text[8][35] = {"最小切除流量1", "最小切除流量2", "电流1最小AD转换流量", "电流1最大AD转换流量", "电流2最小AD转换流量", "电流2最大AD转换流量", "脉冲系数1", "脉冲系数2"};
|
||||
uint8_t flow_textarea_size[8][2] = {{80, 40}, {80, 40}, {100, 40}, {100, 40}, {100, 40}, {100, 40}, {100, 40}, {100, 40}};
|
||||
char flow_textarea_default_data[8][10] = {"0", "0", "0", "10000", "0", "10000", "6944", "6944"};
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
lv_obj_t *label = lv_label_create(screen2_flow_tab);
|
||||
lv_obj_set_size(label, 220, 40);
|
||||
lv_obj_align(label, LV_ALIGN_TOP_LEFT, flow_label_align[i][0], flow_label_align[i][1]);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, LV_PART_MAIN);
|
||||
lv_label_set_text(label, flow_label_text[i]);
|
||||
|
||||
screen2_flow_textareas[i] = lv_textarea_create(screen2_flow_tab);
|
||||
lv_obj_set_style_text_font(screen2_flow_textareas[i], &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
lv_obj_set_size(screen2_flow_textareas[i], flow_textarea_size[i][0], flow_textarea_size[i][1]);
|
||||
lv_obj_align_to(screen2_flow_textareas[i], label, LV_ALIGN_OUT_RIGHT_MID, 0, -8);
|
||||
lv_obj_clear_flag(screen2_flow_textareas[i], LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_textarea_set_text(screen2_flow_textareas[i], flow_textarea_default_data[i]);
|
||||
lv_obj_add_event_cb(screen2_flow_textareas[i], screen2_btnm_event, LV_EVENT_FOCUSED, &screen2_flow_check_infos[i]);
|
||||
}
|
||||
lv_obj_t *label = lv_label_create(screen2_flow_tab);
|
||||
lv_label_set_text(label, "");
|
||||
lv_obj_set_pos(label, 0, 465);
|
||||
|
||||
lv_obj_t *flow_btns[2] = {NULL, NULL};
|
||||
int16_t flow_btns_pos[2][2] = {{290, 405}, {50, 405}};
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
{
|
||||
flow_btns[i] = lv_btn_create(screen2_flow_tab);
|
||||
lv_obj_set_size(flow_btns[i], 140, 50);
|
||||
lv_obj_set_pos(flow_btns[i], flow_btns_pos[i][0], flow_btns_pos[i][1]);
|
||||
lv_obj_set_style_bg_color(flow_btns[i], lv_palette_main(btns_color[i]), 0);
|
||||
lv_obj_set_style_opa(flow_btns[i], 150, 0);
|
||||
|
||||
lv_obj_t *label = lv_label_create(flow_btns[i]);
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, 0);
|
||||
lv_label_set_text(label, btns_text[i]);
|
||||
}
|
||||
lv_obj_add_event_cb(flow_btns[0], screen2_flow_SAVE_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_add_event_cb(flow_btns[1], screen2_flow_DEFAULT_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
// 在screen2_depth_tab创建的
|
||||
lv_obj_t *depth_dd_label = lv_label_create(screen2_depth_tab);
|
||||
lv_obj_set_size(depth_dd_label, 120, 40);
|
||||
lv_obj_align(depth_dd_label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_font(depth_dd_label, &ui_font_16, 0);
|
||||
lv_label_set_text(depth_dd_label, "输入模式");
|
||||
|
||||
screen2_depth_input_type_dropdown = lv_dropdown_create(screen2_depth_tab);
|
||||
lv_obj_set_size(screen2_depth_input_type_dropdown, 160, 40);
|
||||
lv_obj_align_to(screen2_depth_input_type_dropdown, depth_dd_label, LV_ALIGN_OUT_RIGHT_MID, 0, -10);
|
||||
lv_obj_set_style_text_font(screen2_depth_input_type_dropdown, &ui_font_16, 0);
|
||||
lv_dropdown_set_options(screen2_depth_input_type_dropdown, "正交\n正交反向\n方向脉冲\n方向脉冲反向\n");
|
||||
lv_obj_add_event_cb(screen2_depth_input_type_dropdown, screen2_depth_input_type_dropdown_event, LV_EVENT_ALL, NULL);//让下拉列表可以显示汉字
|
||||
lv_obj_add_event_cb(screen2_depth_input_type_dropdown, screen2_depth_input_type_dropdown_event2, LV_EVENT_VALUE_CHANGED, NULL);//选择后进行参数设置
|
||||
|
||||
uint16_t depth_label_align[14][2] = {{0, 45}, {0, 90}, {0, 135}, {0, 180}, {0, 225}, {0, 270}, {0, 315}, {0, 360}, {0, 405}, {0, 450}, {0, 495}, {0, 540}, {0, 595}, {0, 640}};
|
||||
char depth_label_text[14][30] = {"编码器端口", "编码器系数分子", "编码器系数分母", "最小深度mm", "最大深度mm", "采样深度mm", "默认深度偏移", "最小有效深度", "允许换桩深度", "行走电机开启电流", "行走电机关闭电流", "moveon持续时间", "moveoff持续时间", "行走电流通道"};
|
||||
char depth_default_data[14][10] = {"1", "1000", "640", "-100", "12000", "100", "-100", "1000", "-5000", "500", "100", "150", "150", "2"};
|
||||
for (uint8_t i = 0; i < 14; i++)
|
||||
{
|
||||
lv_obj_t *label = lv_label_create(screen2_depth_tab);
|
||||
lv_obj_set_size(label, 200, 40);
|
||||
lv_obj_align(label, LV_ALIGN_TOP_LEFT, depth_label_align[i][0], depth_label_align[i][1]);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, LV_PART_MAIN);
|
||||
lv_label_set_text(label, depth_label_text[i]);
|
||||
|
||||
screen2_depth_textareas[i] = lv_textarea_create(screen2_depth_tab);
|
||||
lv_obj_set_style_text_font(screen2_depth_textareas[i], &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
lv_obj_set_size(screen2_depth_textareas[i], 100, 40);
|
||||
lv_obj_align_to(screen2_depth_textareas[i], label, LV_ALIGN_OUT_RIGHT_MID, 0, -8);
|
||||
lv_obj_clear_flag(screen2_depth_textareas[i], LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_textarea_set_text(screen2_depth_textareas[i], depth_default_data[i]);
|
||||
lv_obj_add_event_cb(screen2_depth_textareas[i], screen2_btnm_event, LV_EVENT_FOCUSED, &screen2_depth_check_infos[i]);
|
||||
}
|
||||
label = lv_label_create(screen2_depth_tab);
|
||||
lv_label_set_text(label, "");
|
||||
lv_obj_set_pos(label, 0, 745);
|
||||
|
||||
lv_obj_t *depth_btns[2] = {NULL, NULL};
|
||||
int16_t depth_btns_pos[2][2] = {{290, 685}, {50, 685}};
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
{
|
||||
depth_btns[i] = lv_btn_create(screen2_depth_tab);
|
||||
lv_obj_set_size(depth_btns[i], 140, 50);
|
||||
lv_obj_set_pos(depth_btns[i], depth_btns_pos[i][0], depth_btns_pos[i][1]);
|
||||
lv_obj_set_style_bg_color(depth_btns[i], lv_palette_main(btns_color[i]), 0);
|
||||
lv_obj_set_style_opa(depth_btns[i], 150, 0);
|
||||
|
||||
lv_obj_t *label = lv_label_create(depth_btns[i]);
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_text_font(label, &ui_font_16, 0);
|
||||
lv_label_set_text(label, btns_text[i]);
|
||||
}
|
||||
lv_obj_add_event_cb(depth_btns[0], screen2_depth_SAVE_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_add_event_cb(depth_btns[1], screen2_depth_DEFAULT_btn_event, LV_EVENT_CLICKED, NULL);
|
||||
}
|
627
EC600U_lvgl/ui/ui_screen3.c
Normal file
627
EC600U_lvgl/ui/ui_screen3.c
Normal file
@ -0,0 +1,627 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../inc/ui/ui_screen3.h"
|
||||
#include "../inc/ui/ui_screen3_chart.h"
|
||||
#include "../inc/ui/fs_function.h"
|
||||
|
||||
lv_obj_t * ui_Screen3;//用来切屏
|
||||
lv_obj_t * screen3_calender;
|
||||
lv_obj_t * screen3_calender_dsc_label; //用来设置选中日期
|
||||
lv_obj_t * btn_page_plus; //用来设置是否可选中
|
||||
lv_obj_t * btn_page_reduce;//用来设置是否可选中
|
||||
|
||||
//用来设置数据
|
||||
lv_obj_t * data_table1;
|
||||
lv_obj_t * data_table2;
|
||||
lv_obj_t * data_table3;
|
||||
lv_obj_t * data_table4;
|
||||
lv_obj_t * data_table5;
|
||||
lv_obj_t * data_table6;
|
||||
lv_obj_t * data_table7;
|
||||
lv_obj_t * data_table8;
|
||||
|
||||
lv_obj_t * screen3_spinbox;
|
||||
lv_obj_t * screen3_spinbox_dsc_label;
|
||||
lv_obj_t * screen3_spinbox_label_textarea;
|
||||
lv_obj_t * btnm;
|
||||
lv_obj_t * scrren3_spinbox_btn;
|
||||
|
||||
lv_obj_t * calendar_dropdown_year;
|
||||
lv_obj_t * calendar_dropdown_month;
|
||||
|
||||
//
|
||||
lv_obj_t * chart;
|
||||
lv_obj_t * chart_screen;
|
||||
lv_chart_series_t * ser1;
|
||||
lv_chart_series_t * ser2;
|
||||
lv_chart_series_t * ser3;
|
||||
lv_chart_series_t * ser4;
|
||||
|
||||
lv_obj_t * primary_y_label;
|
||||
lv_obj_t * secondry_y_label;
|
||||
lv_obj_t * chart_change_btn_label;
|
||||
|
||||
extern lv_obj_t * ui_Screen2;
|
||||
extern lv_obj_t * ui_Screen4;
|
||||
extern int current_id;
|
||||
extern int end_count;
|
||||
struct Return_Data global_file_data_p;
|
||||
struct ChartData chartdata;//存储chart数据
|
||||
uint8_t this_date_have_data = 0; //判断是否需要重新读取文件
|
||||
uint16_t screen3_spinbox_btnm_teatarea_flag = 0;
|
||||
uint8_t user_first_see_calendar_or_change_date = 1;
|
||||
lv_calendar_date_t highlighted_days[31];
|
||||
uint8_t highlighted_days_cnt = 0;
|
||||
|
||||
void ui_Screen3_calendar_set_highlight(void)
|
||||
{
|
||||
//通过日期获取路径
|
||||
char year[10];
|
||||
char month[10];
|
||||
char filedir[20];
|
||||
lv_dropdown_get_selected_str(calendar_dropdown_year, year, sizeof(year));
|
||||
lv_dropdown_get_selected_str(calendar_dropdown_month, month, sizeof(month));
|
||||
sprintf(filedir,"SD:/%s/%s",year,month);
|
||||
//printf("%s\n",filedir);
|
||||
|
||||
uint16_t a = atoi(year);
|
||||
int8_t b = atoi(month);
|
||||
//printf("%d.%02d\n",a,b);
|
||||
|
||||
//lv_calendar_date_t highlighted_days[30];
|
||||
for(int i = 0; i < 31; i++){
|
||||
highlighted_days[i].year = a;
|
||||
highlighted_days[i].month = b;
|
||||
highlighted_days[i].day = 0;
|
||||
}
|
||||
//printf("%d.%02d\n",highlighted_days[0].year,highlighted_days[0].month);
|
||||
|
||||
char filenames[30][7];
|
||||
for (int i = 0; i < 31; i++) {
|
||||
sprintf(filenames[i], "%02d.txt", i+1);
|
||||
}
|
||||
|
||||
//打开文件读取目录
|
||||
QDIR * dir = ql_opendir(filedir);
|
||||
if(dir != NULL){
|
||||
highlighted_days_cnt = 0;
|
||||
while(1){
|
||||
|
||||
qdirent *dirinfo = ql_readdir(dir);
|
||||
if(dirinfo == NULL){
|
||||
break;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 31; i++){
|
||||
if(strcmp(dirinfo->d_name, filenames[i]) == 0){
|
||||
highlighted_days[highlighted_days_cnt].day = atoi(filenames[i]);
|
||||
highlighted_days_cnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lv_calendar_set_highlighted_dates(screen3_calender, highlighted_days, highlighted_days_cnt);//高亮对应的日期
|
||||
ql_closedir(dir);
|
||||
}
|
||||
// else{
|
||||
// LV_LOG_USER("no date need highlight\n");
|
||||
// }
|
||||
}
|
||||
|
||||
//点击使spinbox数值+1
|
||||
void lv_spinbox_increment_event_cb(lv_event_t * e){
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_SHORT_CLICKED || code == LV_EVENT_LONG_PRESSED_REPEAT) {
|
||||
//如果可以点击进入回调函数,代表一定有数据
|
||||
LV_LOG_USER("increment the data");
|
||||
lv_spinbox_increment(screen3_spinbox);
|
||||
|
||||
//根据增加后的页数设置table数据:
|
||||
uint8_t current_page = (uint8_t)lv_spinbox_get_value(screen3_spinbox);
|
||||
if(current_page <= 0){
|
||||
return;
|
||||
}
|
||||
uint8_t page_count = global_file_data_p.id_count/8 + 1;
|
||||
LV_LOG_USER("page:%d page_count:%d\n",current_page,page_count);
|
||||
setDataToTables(&global_file_data_p,current_page,page_count);
|
||||
}
|
||||
}
|
||||
|
||||
//点击使spinbox数值-1
|
||||
void lv_spinbox_decrement_event_cb(lv_event_t * e){
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_SHORT_CLICKED || code == LV_EVENT_LONG_PRESSED_REPEAT) {
|
||||
//LV_LOG_USER("decrement the data");
|
||||
lv_spinbox_decrement(screen3_spinbox);
|
||||
|
||||
//根据增加后的页数设置table数据:
|
||||
uint8_t current_page = (uint8_t)lv_spinbox_get_value(screen3_spinbox);
|
||||
if(current_page <= 0){
|
||||
return;
|
||||
}
|
||||
uint8_t page_count = global_file_data_p.id_count/8 + 1;
|
||||
//LV_LOG_USER("page:%d page_count:%d\n",current_page,page_count);
|
||||
setDataToTables(&global_file_data_p,current_page,page_count);
|
||||
}
|
||||
}
|
||||
|
||||
//使用keyborad对textarea输入数字,按下回车按钮后隐藏textarea和keyboard并将数字设置到spinbox上
|
||||
void screen3_textarea_keyboard_event_cb(lv_event_t * e){
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * target = lv_event_get_target(e);
|
||||
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
|
||||
//当能进入这个回调,说明spinbox btn 可以点击,说明存在有用的数据
|
||||
//获取被点击的btn的id
|
||||
int id = lv_btnmatrix_get_selected_btn(target);
|
||||
// const char * txt = lv_btnmatrix_get_btn_text(target, id);
|
||||
// LV_LOG_USER("%s was pressed\n", txt);
|
||||
|
||||
uint8_t textarea_page_count = global_file_data_p.id_count/8 + 1;
|
||||
uint8_t textarea_page = 0;
|
||||
|
||||
//回车被点击
|
||||
if(id == 11){
|
||||
|
||||
//隐藏textarea和keyboard
|
||||
lv_obj_add_flag(screen3_spinbox_label_textarea,LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(btnm,LV_OBJ_FLAG_HIDDEN);
|
||||
screen3_spinbox_btnm_teatarea_flag = 0;
|
||||
|
||||
//获取此时textarea的文本值
|
||||
const char * textarea_value = lv_textarea_get_text(screen3_spinbox_label_textarea);
|
||||
|
||||
//当存在文本时
|
||||
if (textarea_value[0] != '\0'){
|
||||
uint8_t value = atoi(textarea_value);
|
||||
if(value > 0 && value <textarea_page_count){
|
||||
//代表键入的页数在范围内
|
||||
textarea_page = value;
|
||||
}else if(value == 0){
|
||||
textarea_page = 1;
|
||||
}else{
|
||||
textarea_page = textarea_page_count;
|
||||
}
|
||||
|
||||
lv_spinbox_set_value(screen3_spinbox,textarea_page);//将spinbox设置为对应的页数
|
||||
setDataToTables(&global_file_data_p,textarea_page,textarea_page_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//点击spinbox右侧显示页数的btn 显示/隐藏手动输入页数界面
|
||||
void lv_spinbox_textarea_event_cb(lv_event_t * e){
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
//lv_obj_t * target = lv_event_get_target(e);
|
||||
if(event_code == LV_EVENT_CLICKED) {
|
||||
LV_LOG_USER("page label is clicked");
|
||||
if(screen3_spinbox_btnm_teatarea_flag == 0){
|
||||
|
||||
lv_obj_clear_flag(screen3_spinbox_label_textarea,LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_clear_flag(btnm,LV_OBJ_FLAG_HIDDEN);
|
||||
LV_LOG_USER("can see spinbox_textarea and btnm");
|
||||
screen3_spinbox_btnm_teatarea_flag = 1;
|
||||
}else if(screen3_spinbox_btnm_teatarea_flag == 1){
|
||||
|
||||
lv_obj_add_flag(screen3_spinbox_label_textarea,LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(btnm,LV_OBJ_FLAG_HIDDEN);
|
||||
LV_LOG_USER("can not see spinbox_textarea and btnm");
|
||||
screen3_spinbox_btnm_teatarea_flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//当keyboard中键入数值时,同步更新到textarea中
|
||||
void screen3_btnm_event_handler(lv_event_t * e){
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
lv_obj_t * ta = lv_event_get_user_data(e);
|
||||
const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj));
|
||||
|
||||
if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) lv_textarea_del_char(ta);
|
||||
else if(strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) lv_event_send(ta, LV_EVENT_READY, NULL);
|
||||
else lv_textarea_add_text(ta, txt);
|
||||
}
|
||||
|
||||
//点击显示日期的btn可以弹出/隐藏日历界面,当弹出日历时,高亮对应日期
|
||||
uint16_t calendar_flag = 0;
|
||||
void screen3_calender_create_cb(lv_event_t *e){
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
//lv_obj_t * target = lv_event_get_target(e);
|
||||
if(event_code == LV_EVENT_CLICKED) {
|
||||
LV_LOG_USER("calender create btn clicked");
|
||||
if(calendar_flag == 0){
|
||||
LV_LOG_USER("can see calender");
|
||||
lv_obj_clear_flag(screen3_calender,LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
//当用户第一次显示日历或者切换日期时
|
||||
if(user_first_see_calendar_or_change_date){
|
||||
LV_LOG_USER("user fisrt see calendar or change date\n");
|
||||
user_first_see_calendar_or_change_date = 0;
|
||||
ui_Screen3_calendar_set_highlight();
|
||||
}else{
|
||||
lv_calendar_set_highlighted_dates(screen3_calender, highlighted_days, highlighted_days_cnt);
|
||||
}
|
||||
calendar_flag = 1;
|
||||
}else if(calendar_flag == 1){
|
||||
LV_LOG_USER("can not see calender");
|
||||
lv_obj_add_flag(screen3_calender,LV_OBJ_FLAG_HIDDEN);
|
||||
calendar_flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen3_calender_dropdown_cb(lv_event_t *e){
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
//lv_obj_t * obj = lv_event_get_target(e); //检测是哪个控件触发的事件
|
||||
|
||||
if(code == LV_EVENT_VALUE_CHANGED){
|
||||
//#if EXIST_RECORD_DATA_FILE
|
||||
ui_Screen3_calendar_set_highlight();
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
//选择日历的日期,将日历设置为选择的日期,并在显示日期的btn上同步更新
|
||||
void screen3_calender_event_cb(lv_event_t *e){
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * tables[8] = {data_table1,data_table2,data_table3,data_table4,data_table5,data_table6,data_table7,data_table8};
|
||||
|
||||
//点击相同日期也会触发
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
|
||||
//隐藏日历
|
||||
//LV_LOG_USER("calendar date value changed,hide calendar\n");
|
||||
lv_obj_add_flag(screen3_calender,LV_OBJ_FLAG_HIDDEN);
|
||||
calendar_flag = 0;
|
||||
|
||||
//获取点击的日期
|
||||
lv_calendar_date_t clicked_date;
|
||||
lv_calendar_get_pressed_date(screen3_calender, &clicked_date);
|
||||
lv_label_set_text_fmt(screen3_calender_dsc_label,"%d.%02d.%02d",clicked_date.year,clicked_date.month,clicked_date.day);
|
||||
//LV_LOG_USER("year:%d,month:%d,day:%d\n",clicked_date.year,clicked_date.month,clicked_date.day);
|
||||
|
||||
//遍历高亮日期数组,查询是否存在相同的项,如果存在相同的,则代表点击的日期有效,否则代表无该文件
|
||||
uint8_t highlight_flag = 0;
|
||||
for(int i = 0; i < 31; i++){
|
||||
if( clicked_date.year == highlighted_days[i].year &&
|
||||
clicked_date.month == highlighted_days[i].month &&
|
||||
clicked_date.day == highlighted_days[i].day)
|
||||
{
|
||||
highlight_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t different_date_flag = 1;
|
||||
char * label_date = lv_label_get_text(screen3_calender_dsc_label);
|
||||
int year,month,day;
|
||||
sscanf(label_date,"%d.%d.%d",&year,&month,&day);
|
||||
|
||||
//LV_LOG_USER("label_date:%s,year:%d,month:%d,day:%d\n",label_date,year,month,day);
|
||||
if(year == clicked_date.year && month == clicked_date.month && day == clicked_date.day) different_date_flag = 0;
|
||||
|
||||
//当既不是相同日期又存在文件时,需要从新给全局遍历赋值
|
||||
if(highlight_flag && different_date_flag){
|
||||
//LV_LOG_USER("different date and file exist\n");
|
||||
|
||||
//将结构体变量初始化为0
|
||||
lv_memset_00(&global_file_data_p,sizeof(struct Return_Data));
|
||||
|
||||
//判断文件是否可读
|
||||
this_date_have_data = findDataFile(clicked_date.year,clicked_date.month,clicked_date.day);
|
||||
if(this_date_have_data)
|
||||
{
|
||||
//LV_LOG_USER("unempty file\n");
|
||||
//生成文件路径
|
||||
char file_path[32];
|
||||
sprintf(file_path,"E:/%d/%02d/%02d.txt",(int)clicked_date.year,(int)clicked_date.month,(int)clicked_date.day);
|
||||
//LV_LOG_USER("file_path:%s,id num = %d\n",file_path,global_file_data_p.id_count);
|
||||
|
||||
//打开文件
|
||||
// lv_fs_file_t file_in_screen3_calender_event_cb = {
|
||||
// .drv = NULL,
|
||||
// .file_d = NULL
|
||||
// };
|
||||
QFILE fd = ql_fopen(file_path,"rb");// lv_fs_open(&file_in_screen3_calender_event_cb,file_path,LV_FS_MODE_RD);
|
||||
|
||||
//读取文件赋值给变量
|
||||
readDataFromFile(fd,&global_file_data_p);
|
||||
|
||||
ql_fclose(fd);//lv_fs_close(&file_in_screen3_calender_event_cb);
|
||||
current_id =0;
|
||||
end_count = 0;
|
||||
|
||||
//根据变量处理控件
|
||||
//计算总页数,设置spinbox页数label以及spinbox范围
|
||||
uint8_t page_count = global_file_data_p.id_count/8 + 1;
|
||||
lv_label_set_text_fmt(screen3_spinbox_dsc_label,"/ %d",page_count);
|
||||
lv_spinbox_set_range(screen3_spinbox, 1,page_count);
|
||||
//LV_LOG_USER("different id num is: %d, page_count = %d\n", global_file_data_p.id_count,page_count);
|
||||
|
||||
//根据当前页数和总页数,设置tabel的数据
|
||||
uint8_t current_page = lv_spinbox_get_value(screen3_spinbox);
|
||||
setDataToTables(&global_file_data_p,current_page,page_count);
|
||||
|
||||
//使能点击flag
|
||||
lv_obj_add_flag(btn_page_plus,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_flag(btn_page_reduce,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_flag(scrren3_spinbox_btn,LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t * tables[8] = {data_table1,data_table2,data_table3,data_table4,data_table5,data_table6,data_table7,data_table8};
|
||||
for(int i = 0; i < 8; i++){
|
||||
lv_obj_add_flag(tables[i],LV_OBJ_FLAG_CLICKABLE);
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
//如果文件空
|
||||
else
|
||||
{
|
||||
//LV_LOG_USER("empty file\n");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
else if(!different_date_flag)
|
||||
{
|
||||
//代表点击了相同的日期,直接返回
|
||||
//LV_LOG_USER("click same date\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//代表点了不同的日期但是日期对应没有文件
|
||||
//LV_LOG_USER("click different date but no file\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
//清空table,清除table的可点击flag
|
||||
for(int i = 0; i < 8; i++){
|
||||
lv_obj_clear_flag(tables[i],LV_OBJ_FLAG_CLICKABLE);
|
||||
for(int j = 0; j < 6; j++){
|
||||
lv_table_set_cell_value_fmt(tables[i],0,j,"");
|
||||
}
|
||||
}
|
||||
//清除spinbox的btn的可点击flag
|
||||
lv_obj_clear_flag(btn_page_plus,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_clear_flag(btn_page_reduce,LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_clear_flag(scrren3_spinbox_btn,LV_OBJ_FLAG_CLICKABLE);
|
||||
//设置spinbox的label
|
||||
lv_label_set_text(screen3_spinbox_dsc_label,"N/A");
|
||||
return;
|
||||
}
|
||||
|
||||
//当点击data_table时,创建chart界面
|
||||
void screen3_data_table_chart_create(lv_event_t * e){
|
||||
|
||||
lv_event_code_t event_code = lv_event_get_code(e);
|
||||
lv_obj_t * target = lv_event_get_target(e);
|
||||
|
||||
if(event_code == LV_EVENT_CLICKED){
|
||||
//LV_LOG_USER("get code and get target\n");
|
||||
#if 1
|
||||
/*获取id,如果id为空则直接返回,不生成chart*/
|
||||
int id = atoi(lv_table_get_cell_value(target, 0, 0));
|
||||
if(id == 0){
|
||||
LV_LOG_USER("id is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*根据id获取文件指针位置和偏移量*/
|
||||
int offset = 0;
|
||||
for( int i = 0; i < global_file_data_p.id_count; i++){
|
||||
if(id == global_file_data_p.dataArr[i].id){
|
||||
offset = global_file_data_p.dataArr[i].offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//LV_LOG_USER("id = %d, offset = %d\n",id,offset);
|
||||
|
||||
/*获取该id的chart数据*/
|
||||
//生成文件路径并打开文件
|
||||
int year,month,day;
|
||||
char file_path[18];
|
||||
sscanf(lv_label_get_text(screen3_calender_dsc_label), "%d.%d.%d", &year,&month,&day);
|
||||
sprintf(file_path,"E:/%d/%02d/%02d.txt",year,month,day);
|
||||
//LV_LOG_USER("path:%s\n",file_path);
|
||||
|
||||
// lv_fs_file_t file_in_screen3_data_table_chart_create = {
|
||||
// .drv = NULL,
|
||||
// .file_d = NULL
|
||||
// };
|
||||
// lv_fs_open(&file_in_screen3_data_table_chart_create,file_path,LV_FS_MODE_RD);
|
||||
QFILE fd = ql_fopen(file_path,"rb");
|
||||
|
||||
//读取该id的chart数据
|
||||
lv_memset_00(&chartdata,sizeof(struct ChartData));
|
||||
setDataToChart(fd,offset,id,&chartdata);
|
||||
|
||||
ql_fclose(fd);//lv_fs_close(&file_in_screen3_data_table_chart_create);
|
||||
#endif
|
||||
#if 0
|
||||
printf("same_id_count = %d\n",chartdata.same_id_count+1);
|
||||
for(int i = 0; i < chartdata.same_id_count+1; i++){
|
||||
printf("depth:%.3f\t,V:%.3f,I:%.3f,time:%s\n",
|
||||
chartdata.depth[i],
|
||||
chartdata.V[i],
|
||||
chartdata.I[i],
|
||||
chartdata.time[i]
|
||||
);
|
||||
}
|
||||
#endif
|
||||
int num = chartdata.same_id_count+1;
|
||||
if(num <= 1){
|
||||
LV_LOG_USER("too few points\n");
|
||||
return;
|
||||
}
|
||||
ui_screen3_chart_init(num);
|
||||
}
|
||||
}
|
||||
/****************************************************************************************************************************************/
|
||||
void ui_screen3_init(void)
|
||||
{
|
||||
/*****************************************************显示日期的label**********************************************************/
|
||||
lv_obj_t * screen3_calender_btn = lv_btn_create(ui_Screen3);
|
||||
lv_obj_set_size(screen3_calender_btn, 100, 34);
|
||||
lv_obj_set_pos(screen3_calender_btn,60,0);
|
||||
//点击btn显示或隐藏calendar,并高亮有文件的日期
|
||||
lv_obj_add_event_cb(screen3_calender_btn, screen3_calender_create_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
screen3_calender_dsc_label = lv_label_create(screen3_calender_btn);
|
||||
lv_obj_center(screen3_calender_dsc_label);
|
||||
/*
|
||||
// 获取当前时间戳
|
||||
time_t t = time(NULL);
|
||||
|
||||
// 使用localtime函数将时间戳转换为本地时间结构
|
||||
struct tm *local_time = localtime(&t);
|
||||
|
||||
// 从本地时间结构中提取年、月和日
|
||||
int year = local_time->tm_year + 1900; // 年份需要加上1900
|
||||
int month = local_time->tm_mon + 1; // 月份从0开始,需要加1
|
||||
int day = local_time->tm_mday;
|
||||
char calendar[11];
|
||||
sprintf(calendar,"%d.%d.%d",year,month,day);
|
||||
*/
|
||||
lv_label_set_text(screen3_calender_dsc_label,"2024.01.10");
|
||||
|
||||
/*****************************************************显示页数的spinbox**********************************************************/
|
||||
//创建承载spinbox和描述label的btn
|
||||
scrren3_spinbox_btn = lv_btn_create(ui_Screen3);
|
||||
lv_obj_set_pos(scrren3_spinbox_btn,330,0);
|
||||
lv_obj_set_size(scrren3_spinbox_btn,80,30);
|
||||
lv_obj_set_style_bg_color(scrren3_spinbox_btn,lv_color_hex(0xFFFFFFF),0);
|
||||
//点击显示输入文本框和键盘
|
||||
lv_obj_add_event_cb(scrren3_spinbox_btn, lv_spinbox_textarea_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
//创建spinbox
|
||||
screen3_spinbox = lv_spinbox_create(scrren3_spinbox_btn);
|
||||
lv_spinbox_set_digit_format(screen3_spinbox, 2, 2);
|
||||
lv_obj_set_width(screen3_spinbox, 46);
|
||||
lv_obj_align(screen3_spinbox,LV_ALIGN_CENTER,-15,0);
|
||||
lv_spinbox_set_value(screen3_spinbox,1);//设置初始为第一页
|
||||
lv_obj_set_style_border_opa(screen3_spinbox,0,0);
|
||||
lv_obj_set_style_outline_opa(screen3_spinbox,0,0);
|
||||
|
||||
//创建显示总页数的label
|
||||
screen3_spinbox_dsc_label = lv_label_create(scrren3_spinbox_btn);
|
||||
lv_obj_set_size(screen3_spinbox_dsc_label,50,34);
|
||||
lv_obj_align_to(screen3_spinbox_dsc_label,screen3_spinbox,LV_ALIGN_OUT_RIGHT_MID,0,8);
|
||||
lv_obj_set_style_text_font(screen3_spinbox_dsc_label,&lv_font_montserrat_16,0);
|
||||
lv_label_set_text(screen3_spinbox_dsc_label,"/100");
|
||||
lv_obj_set_style_border_opa(screen3_spinbox_dsc_label,0,0);
|
||||
lv_obj_set_style_outline_opa(screen3_spinbox_dsc_label,0,0);
|
||||
|
||||
/*****************************************************控制翻页的button**********************************************************/
|
||||
btn_page_plus = lv_btn_create(ui_Screen3);
|
||||
lv_obj_set_size(btn_page_plus, 30, 30);
|
||||
lv_obj_set_pos(btn_page_plus,410,0);
|
||||
lv_obj_set_style_bg_img_src(btn_page_plus, LV_SYMBOL_PLUS, 0);
|
||||
|
||||
btn_page_reduce = lv_btn_create(ui_Screen3);
|
||||
lv_obj_set_size(btn_page_reduce, 30, 30);
|
||||
lv_obj_set_pos(btn_page_reduce,300,0);
|
||||
lv_obj_set_style_bg_img_src(btn_page_reduce, LV_SYMBOL_MINUS, 0);
|
||||
|
||||
//spinbox页数+1
|
||||
lv_obj_add_event_cb(btn_page_plus, lv_spinbox_increment_event_cb, LV_EVENT_ALL,NULL);
|
||||
//spinbox页数-1
|
||||
lv_obj_add_event_cb(btn_page_reduce, lv_spinbox_decrement_event_cb, LV_EVENT_ALL,NULL);
|
||||
|
||||
/*****************************************************记录数据的table**********************************************************/
|
||||
char text[6][16] = {"桩点号","最大喷浆量","最大深度","平均电流","开始时间","结束时间"};
|
||||
int align[6] = {-210,-125,-40,35,120,210};
|
||||
int size[6] = {50,80,70,70,70,70};
|
||||
for(int i = 0; i < 6; i++){
|
||||
lv_obj_t * screen3_label = lv_label_create(ui_Screen3);
|
||||
lv_obj_set_size(screen3_label,size[i],30);
|
||||
lv_obj_align(screen3_label,LV_ALIGN_TOP_MID, align[i], 45);
|
||||
lv_obj_clear_flag(screen3_label,LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_label_set_text(screen3_label,text[i]);
|
||||
lv_obj_set_style_text_font(screen3_label, &lv_font_chinese_12_name, 0);
|
||||
}
|
||||
|
||||
data_table1 = lv_table_create(ui_Screen3);
|
||||
data_table2 = lv_table_create(ui_Screen3);
|
||||
data_table3 = lv_table_create(ui_Screen3);
|
||||
data_table4 = lv_table_create(ui_Screen3);
|
||||
data_table5 = lv_table_create(ui_Screen3);
|
||||
data_table6 = lv_table_create(ui_Screen3);
|
||||
data_table7 = lv_table_create(ui_Screen3);
|
||||
data_table8 = lv_table_create(ui_Screen3);
|
||||
|
||||
lv_obj_t*screen3_data_tables[] = {data_table1, data_table2, data_table3, data_table4,data_table5, data_table6, data_table7, data_table8};
|
||||
int align_data[] = {-224,-192,-160,-128,-96,-64,-32,0};
|
||||
for(int r=0;r<8;r++){
|
||||
lv_obj_align(screen3_data_tables[r],LV_ALIGN_BOTTOM_MID, 10, align_data[r]);//设置位置
|
||||
lv_table_set_row_cnt(screen3_data_tables[r],1);//设置行列数
|
||||
lv_table_set_col_cnt(screen3_data_tables[r],6);
|
||||
lv_obj_set_height(screen3_data_tables[r],35);
|
||||
lv_obj_set_style_border_width(screen3_data_tables[r],1,LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_top(screen3_data_tables[r],0,LV_PART_ITEMS);
|
||||
lv_obj_clear_flag(screen3_data_tables[r],LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_table_set_col_width(screen3_data_tables[r],0,75);
|
||||
lv_table_set_col_width(screen3_data_tables[r],1,87);
|
||||
lv_table_set_col_width(screen3_data_tables[r],2,75);
|
||||
lv_table_set_col_width(screen3_data_tables[r],3,80);
|
||||
lv_table_set_col_width(screen3_data_tables[r],4,100);
|
||||
lv_table_set_col_width(screen3_data_tables[r],5,100);
|
||||
//当点击table时,生成对应的chart
|
||||
lv_obj_add_event_cb(screen3_data_tables[r], screen3_data_table_chart_create, LV_EVENT_CLICKED,NULL);
|
||||
}
|
||||
|
||||
/*****************************************************calendar**********************************************************/
|
||||
screen3_calender = lv_calendar_create(ui_Screen3);
|
||||
lv_obj_set_size(screen3_calender, 480, 287);
|
||||
lv_obj_align(screen3_calender,LV_ALIGN_BOTTOM_MID,0,0);
|
||||
lv_obj_add_flag(screen3_calender,LV_OBJ_FLAG_HIDDEN);
|
||||
//选择日期,读取对应日期文件,设置table,更新label
|
||||
lv_obj_add_event_cb(screen3_calender, screen3_calender_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
lv_obj_t * calendar_dropdown_background = lv_calendar_header_dropdown_create(screen3_calender);
|
||||
calendar_dropdown_year = lv_obj_get_child(calendar_dropdown_background,0);
|
||||
calendar_dropdown_month = lv_obj_get_child(calendar_dropdown_background,1);
|
||||
//当日历的年月改变时,读取相对应的路径并高亮对应日期
|
||||
lv_obj_add_event_cb(calendar_dropdown_year, screen3_calender_dropdown_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_add_event_cb(calendar_dropdown_month, screen3_calender_dropdown_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
/*****************************************************textarea+keyboard**********************************************************/
|
||||
//创建输入文本框并隐藏
|
||||
screen3_spinbox_label_textarea = lv_textarea_create(ui_Screen3);
|
||||
lv_textarea_set_one_line(screen3_spinbox_label_textarea, true);
|
||||
lv_obj_align(screen3_spinbox_label_textarea, LV_ALIGN_TOP_MID, 0, 32);
|
||||
lv_obj_set_width(screen3_spinbox_label_textarea,480);
|
||||
lv_obj_add_state(screen3_spinbox_label_textarea, LV_STATE_FOCUSED);
|
||||
lv_obj_add_flag(screen3_spinbox_label_textarea,LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
//为输入文本框创建输入键盘
|
||||
static const char * btnm_map[] = {
|
||||
"1", "2", "3", "\n",
|
||||
"4", "5", "6", "\n",
|
||||
"7", "8", "9", "\n",
|
||||
LV_SYMBOL_BACKSPACE, "0", LV_SYMBOL_NEW_LINE, ""};
|
||||
|
||||
btnm = lv_btnmatrix_create(ui_Screen3);
|
||||
lv_obj_set_size(btnm, 480, 250);
|
||||
lv_obj_align(btnm, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
|
||||
lv_obj_clear_flag(btnm, LV_OBJ_FLAG_CLICK_FOCUSABLE); /*To keep the text area focused on button clicks*/
|
||||
lv_btnmatrix_set_map(btnm, btnm_map);
|
||||
lv_obj_add_flag(btnm,LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
//回车时设置label,隐藏ta和btnm
|
||||
lv_obj_add_event_cb(btnm, screen3_textarea_keyboard_event_cb, LV_EVENT_ALL, NULL);
|
||||
|
||||
//将键盘输入的数据键入到textarea上
|
||||
lv_obj_add_event_cb(btnm, screen3_btnm_event_handler, LV_EVENT_VALUE_CHANGED, screen3_spinbox_label_textarea);
|
||||
}
|
148
EC600U_lvgl/ui/ui_screen3_chart.c
Normal file
148
EC600U_lvgl/ui/ui_screen3_chart.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "../inc/ui/ui_screen3_chart.h"
|
||||
#include "../inc/ui/fs_function.h"
|
||||
|
||||
extern struct ChartData chartdata;;
|
||||
lv_obj_t * chart;
|
||||
lv_chart_series_t * ser_depth;
|
||||
lv_chart_series_t * ser_V;
|
||||
lv_chart_series_t * ser_I;
|
||||
|
||||
void chart_btn_event_handler(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
//struct ChartUserData * chart_user_data = (struct ChartUserData *)lv_event_get_user_data(e);
|
||||
lv_obj_t * chart_screen = (lv_obj_t*)lv_event_get_user_data(e);
|
||||
|
||||
if(code == LV_EVENT_CLICKED){
|
||||
// LV_LOG_USER("delete chart btn clicked,user data p:%p,chart p:%p,depth p:%p,V p:%p\n",
|
||||
lv_chart_remove_series(chart,ser_depth);
|
||||
lv_chart_remove_series(chart,ser_V);
|
||||
lv_chart_remove_series(chart,ser_I);
|
||||
lv_obj_del(chart_screen);
|
||||
lv_obj_del(obj);
|
||||
|
||||
ser_depth = NULL;
|
||||
ser_V = NULL;
|
||||
ser_I = NULL;
|
||||
chart = NULL;
|
||||
|
||||
lv_memset_00(&chartdata,sizeof(struct ChartData));
|
||||
}
|
||||
}
|
||||
|
||||
//在chart生成时,设置x坐标轴的单位
|
||||
void chart_x_set(lv_event_t * e)
|
||||
{
|
||||
lv_obj_draw_part_dsc_t * dsc = lv_event_get_param(e);
|
||||
if(dsc->part == LV_PART_TICKS && dsc->id == LV_CHART_AXIS_PRIMARY_X) {
|
||||
lv_snprintf(dsc->text, sizeof(dsc->text), "%s", chartdata.time[dsc->value]);
|
||||
}
|
||||
}
|
||||
|
||||
//当在chart上点击数据点时,将该横坐标对应的纵坐标值分别在各个ser的数据点旁边显示
|
||||
void chart_see_two_ser_values_after_clicked(lv_event_t * e){
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * chart = lv_event_get_target(e);
|
||||
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t * s = lv_event_get_param(e);
|
||||
*s = LV_MAX(*s, 20);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_POST_END) {
|
||||
int id = lv_chart_get_pressed_point(chart);
|
||||
if(id == LV_CHART_POINT_NONE) return;
|
||||
|
||||
LV_LOG_USER("Selected point %d", id);
|
||||
|
||||
lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL);
|
||||
while(ser) {
|
||||
lv_point_t p;
|
||||
lv_chart_get_point_pos_by_id(chart, ser, id, &p);
|
||||
|
||||
lv_coord_t * y_array = lv_chart_get_y_array(chart, ser);
|
||||
lv_coord_t value = y_array[id];
|
||||
|
||||
char buf[16];
|
||||
lv_snprintf(buf, sizeof(buf), LV_SYMBOL_DUMMY"$%d", value);
|
||||
|
||||
lv_draw_rect_dsc_t draw_rect_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_rect_dsc);
|
||||
draw_rect_dsc.bg_color = lv_color_black();
|
||||
draw_rect_dsc.bg_opa = LV_OPA_50;
|
||||
draw_rect_dsc.radius = 3;
|
||||
draw_rect_dsc.bg_img_src = buf;
|
||||
draw_rect_dsc.bg_img_recolor = lv_color_white();
|
||||
|
||||
lv_area_t a;
|
||||
a.x1 = chart->coords.x1 + p.x - 20;
|
||||
a.x2 = chart->coords.x1 + p.x + 20;
|
||||
a.y1 = chart->coords.y1 + p.y - 30;
|
||||
a.y2 = chart->coords.y1 + p.y - 10;
|
||||
|
||||
const lv_area_t * clip_area = lv_event_get_clip_area(e);
|
||||
lv_draw_rect(&a, clip_area, &draw_rect_dsc);
|
||||
|
||||
ser = lv_chart_get_series_next(chart, ser);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_RELEASED) {
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_screen3_chart_init(int num)
|
||||
{
|
||||
/*基于当前活动屏幕创建chart所在的屏*/
|
||||
lv_obj_t * chart_screen = lv_obj_create(lv_scr_act());
|
||||
lv_obj_center(chart_screen);
|
||||
lv_obj_set_size(chart_screen,480,320);
|
||||
lv_obj_clear_flag(chart_screen,LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
/*创建关闭btn*/
|
||||
lv_obj_t *chart_close_btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_center(chart_close_btn);
|
||||
lv_obj_set_size(chart_close_btn,100,40);
|
||||
lv_obj_align(chart_close_btn,LV_ALIGN_TOP_RIGHT,-40,0);
|
||||
lv_obj_t *chart_close_btn_label = lv_label_create(chart_close_btn);
|
||||
lv_label_set_text(chart_close_btn_label,LV_SYMBOL_CLOSE);
|
||||
lv_obj_center(chart_close_btn_label);
|
||||
lv_obj_set_style_text_font(chart_close_btn_label,&lv_font_montserrat_24,0);
|
||||
lv_obj_add_event_cb(chart_close_btn,chart_btn_event_handler,LV_EVENT_ALL,(void*)chart_screen);
|
||||
|
||||
chart = lv_chart_create(chart_screen);
|
||||
lv_obj_set_size(chart, 420, 250);
|
||||
lv_obj_align(chart,LV_ALIGN_BOTTOM_MID,-5,-5);
|
||||
lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /*Show lines and points too*/
|
||||
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 10);//左侧纵坐标范围,深度
|
||||
lv_chart_set_range(chart, LV_CHART_AXIS_SECONDARY_Y, 0, 1600);//右侧纵坐标范围,累计喷浆量
|
||||
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 5, 1, 6, 1, true, 50);//给坐标轴添加刻度线
|
||||
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_SECONDARY_Y, 5, 1, 6, 1, true, 50);
|
||||
lv_chart_set_zoom_x(chart, 400);//设置x轴缩进
|
||||
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 5, 1, num, 1, true, 20); //设置横坐标刻度(1个点无法生成line)
|
||||
lv_chart_set_point_count(chart, num);
|
||||
ser_depth = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y);//深度,深蓝色
|
||||
ser_V = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_SECONDARY_Y);//累计喷浆,绿色
|
||||
ser_I = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);//电流 红色
|
||||
|
||||
/*根据chart数据生成line*/
|
||||
for(int i = 0; i < num; i++){
|
||||
lv_chart_set_next_value(chart,ser_depth,chartdata.depth[i]);
|
||||
lv_chart_set_next_value(chart,ser_V,chartdata.V[i]);
|
||||
lv_chart_set_next_value(chart,ser_I,chartdata.I[i]);
|
||||
}
|
||||
lv_chart_refresh(chart);
|
||||
|
||||
//在绘图时重绘x轴坐标描述
|
||||
lv_obj_add_event_cb(chart, chart_x_set, LV_EVENT_DRAW_PART_BEGIN,NULL);
|
||||
|
||||
//点击数据点时在旁边显示值
|
||||
lv_obj_add_event_cb(chart, chart_see_two_ser_values_after_clicked, LV_EVENT_ALL, NULL);
|
||||
}
|
231
EC600U_lvgl/ui/ui_screen4.c
Normal file
231
EC600U_lvgl/ui/ui_screen4.c
Normal file
@ -0,0 +1,231 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "../inc/ui/ui_screen4.h"
|
||||
|
||||
#include "osi_api.h"
|
||||
#define SIZE 300
|
||||
|
||||
lv_obj_t * ui_Screen4;
|
||||
level_instrument_t * level_instrument;
|
||||
extern lv_obj_t * ui_Screen1;
|
||||
extern lv_obj_t * ui_Screen3;
|
||||
|
||||
/********************************************** 自定义控件创建 *****************************************/
|
||||
my_panel_t * panel_create(lv_obj_t * obj)
|
||||
{
|
||||
/*创建基础红色背景*/
|
||||
lv_obj_t * red_bg = lv_obj_create(obj);
|
||||
lv_obj_align(red_bg,LV_ALIGN_CENTER,0,20);
|
||||
lv_obj_set_size(red_bg,SIZE,SIZE);
|
||||
lv_obj_set_style_radius(red_bg,200,0);
|
||||
lv_obj_set_style_bg_color(red_bg,lv_palette_main(LV_PALETTE_RED),0);
|
||||
lv_obj_set_style_opa(red_bg,150,0);
|
||||
lv_obj_set_style_border_width(red_bg,0,0);
|
||||
lv_obj_set_style_outline_width(red_bg,0,0);
|
||||
|
||||
/*在红色背景上创建黄色背景*/
|
||||
lv_obj_t * yellow_bg = lv_obj_create(red_bg);
|
||||
lv_obj_center(yellow_bg);
|
||||
lv_obj_set_size(yellow_bg,SIZE/3*2,SIZE/3*2);
|
||||
lv_obj_set_style_radius(yellow_bg,125,0);
|
||||
lv_obj_set_style_bg_color(yellow_bg,lv_palette_main(LV_PALETTE_YELLOW),0);
|
||||
lv_obj_set_style_opa(yellow_bg,150,0);
|
||||
lv_obj_set_style_border_width(yellow_bg,0,0);
|
||||
lv_obj_set_style_outline_width(yellow_bg,0,0);
|
||||
|
||||
/*在绿色背景上创建绿色背景*/
|
||||
lv_obj_t * green_bg = lv_obj_create(yellow_bg);
|
||||
lv_obj_center(green_bg);
|
||||
lv_obj_set_size(green_bg,SIZE/3,SIZE/3);
|
||||
lv_obj_set_style_radius(green_bg,125,0);
|
||||
lv_obj_set_style_bg_color(green_bg,lv_palette_main(LV_PALETTE_GREEN),0);
|
||||
lv_obj_set_style_opa(green_bg,150,0);
|
||||
lv_obj_set_style_border_width(green_bg,0,0);
|
||||
lv_obj_set_style_outline_width(green_bg,0,0);
|
||||
|
||||
//创建十字线
|
||||
lv_obj_t * horizontal_line = lv_obj_create(obj);
|
||||
lv_obj_set_size(horizontal_line,SIZE+20,2);
|
||||
lv_obj_set_style_bg_color(horizontal_line,lv_color_hex(0x000000),0);
|
||||
lv_obj_align(horizontal_line,LV_ALIGN_CENTER,0,20);
|
||||
lv_obj_set_style_border_width(horizontal_line,0,0);
|
||||
lv_obj_set_style_outline_width(horizontal_line,0,0);
|
||||
lv_obj_set_style_shadow_width(horizontal_line,0,0);
|
||||
|
||||
lv_obj_t * vertical_line = lv_obj_create(obj);
|
||||
lv_obj_set_size(vertical_line,2,SIZE+20);
|
||||
lv_obj_set_style_bg_color(vertical_line,lv_color_hex(0x000000),0);
|
||||
lv_obj_align(vertical_line,LV_ALIGN_CENTER,0,20);
|
||||
lv_obj_set_style_border_width(vertical_line,0,0);
|
||||
lv_obj_set_style_outline_width(vertical_line,0,0);
|
||||
lv_obj_set_style_shadow_width(vertical_line,0,0);
|
||||
|
||||
my_panel_t * my_panel = (my_panel_t *)lv_mem_alloc(sizeof(my_panel_t));
|
||||
my_panel -> red_bg = red_bg;
|
||||
my_panel -> yellow_bg = yellow_bg;
|
||||
my_panel -> green_bg = green_bg;
|
||||
my_panel -> horizontal_line = horizontal_line;
|
||||
my_panel -> vertical_line = vertical_line;
|
||||
|
||||
// LV_LOG_USER(
|
||||
// "red_bg = %p\n yellow_bg = %p\n green_bg = %p\n horizontal_line = %p\n vertical_line = %p\n",
|
||||
// my_panel -> red_bg,
|
||||
// my_panel -> yellow_bg,
|
||||
// my_panel -> green_bg,
|
||||
// my_panel -> horizontal_line,
|
||||
// my_panel -> vertical_line
|
||||
// );
|
||||
|
||||
return my_panel;
|
||||
}
|
||||
|
||||
lv_obj_t* led_create(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * led = lv_led_create(obj);
|
||||
lv_obj_set_size(led, 10, 10);
|
||||
lv_obj_align(led,LV_ALIGN_CENTER,0,20);
|
||||
//LV_LOG_USER("led = %p", led);
|
||||
return led;
|
||||
}
|
||||
|
||||
level_instrument_t * level_instrument_create(lv_obj_t * obj)
|
||||
{
|
||||
level_instrument_t * level_instrument = (level_instrument_t *)lv_mem_alloc(sizeof(level_instrument_t));
|
||||
level_instrument -> panel = panel_create(obj);
|
||||
level_instrument -> led = led_create(obj);
|
||||
level_instrument ->size =270;
|
||||
level_instrument ->x = 0;
|
||||
level_instrument ->y = 0;
|
||||
return level_instrument;
|
||||
}
|
||||
|
||||
/****************************************************自定义控件功能**********************************************************/
|
||||
|
||||
//设置控件对应部件大小
|
||||
void level_instrument_set_size(level_instrument_t * level_instrument, lv_coord_t size, level_instrument_part_t part)
|
||||
{
|
||||
if(part == LEVEL_INSTUMENT_PANEL_ALL){
|
||||
lv_obj_set_size(level_instrument -> panel ->red_bg , size, size);
|
||||
lv_obj_set_size(level_instrument -> panel ->yellow_bg , size/3*2, size/3*2);
|
||||
lv_obj_set_size(level_instrument -> panel ->green_bg , size/3, size/3);
|
||||
lv_obj_set_size(level_instrument -> panel ->horizontal_line , size+10, 2);
|
||||
lv_obj_set_size(level_instrument -> panel ->vertical_line , 2, size+10);
|
||||
level_instrument->size = size;//更新大小
|
||||
}else if(part == LEVEL_INSTUMENT_PANEL_RED){
|
||||
lv_obj_set_size(level_instrument -> panel ->red_bg , size, size);
|
||||
}else if(part == LEVEL_INSTUMENT_PANEL_YELLOW){
|
||||
lv_obj_set_size(level_instrument -> panel ->yellow_bg , size/3*2, size/3*2);
|
||||
}else if(part == LEVEL_INSTUMENT_PANEL_GREEN){
|
||||
lv_obj_set_size(level_instrument -> panel ->green_bg , size/3, size/3);
|
||||
}else if(part == LEVEL_INSTRUMENT_CROSSHAIR){
|
||||
lv_obj_set_size(level_instrument->panel->horizontal_line,size,2);
|
||||
lv_obj_set_size(level_instrument->panel->vertical_line,2,size);
|
||||
}else if(part == LEVEL_INSTRUMENT_LED){
|
||||
lv_obj_set_size(level_instrument -> led , size, size);
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//设置光标在面板上的位置(光标以坐标轴方向为准,基于原点偏移)
|
||||
void level_instrument_set_cursor_pos(level_instrument_t * level_instrument,lv_coord_t x_offset, lv_coord_t y_offset)
|
||||
{
|
||||
y_offset = -y_offset;
|
||||
int size = level_instrument->size;
|
||||
//LV_LOG_USER("panel size = %d\n",size);
|
||||
|
||||
//判断坐标是否超过panel
|
||||
if (((size * size) >= x_offset * x_offset + y_offset * y_offset) &&
|
||||
LV_ABS(x_offset) <= size/2 &&
|
||||
LV_ABS(y_offset) <= size/2){
|
||||
//光标在内部
|
||||
level_instrument->x = x_offset;
|
||||
level_instrument->y = y_offset;
|
||||
lv_obj_align(level_instrument->led,LV_ALIGN_CENTER,x_offset,y_offset);
|
||||
//LV_LOG_USER("cursor is in panel\n");
|
||||
}else{
|
||||
//光标在外部
|
||||
//LV_LOG_USER("cursor is out panel\n");
|
||||
}
|
||||
}
|
||||
|
||||
//设置光标颜色
|
||||
void level_instrument_set_cursor_color(level_instrument_t * level_instrument,lv_color_t color)
|
||||
{
|
||||
lv_led_set_color(level_instrument->led,color);
|
||||
}
|
||||
|
||||
//设置光标亮度
|
||||
void level_instrument_set_cursor_brightness(level_instrument_t * level_instrument,uint8_t bright)
|
||||
{
|
||||
lv_led_set_brightness(level_instrument->led,bright);
|
||||
}
|
||||
|
||||
//设置控件整体的对齐
|
||||
void level_instrument_set_align(level_instrument_t * level_instrument,lv_align_t align,lv_coord_t x_offset,lv_coord_t y_offset)
|
||||
{
|
||||
lv_obj_align(level_instrument->panel->red_bg,align,x_offset,y_offset);
|
||||
lv_obj_align(level_instrument->panel->green_bg,align,x_offset,y_offset);
|
||||
lv_obj_align(level_instrument->panel->yellow_bg,align,x_offset,y_offset);
|
||||
lv_obj_align(level_instrument->panel->horizontal_line,align,x_offset,y_offset);
|
||||
lv_obj_align(level_instrument->panel->vertical_line,align,x_offset,y_offset);
|
||||
lv_obj_align(level_instrument->led,align,x_offset+level_instrument->x,y_offset+level_instrument->y);
|
||||
}
|
||||
|
||||
//设置面板透明度
|
||||
void level_instrument_set_opa(level_instrument_t * level_instrument,lv_opa_t opa)
|
||||
{
|
||||
lv_obj_set_style_opa(level_instrument->panel->red_bg,opa,0);
|
||||
lv_obj_set_style_opa(level_instrument->panel->green_bg,opa,0);
|
||||
lv_obj_set_style_opa(level_instrument->panel->yellow_bg,opa,0);
|
||||
lv_obj_set_style_opa(level_instrument->panel->horizontal_line,opa,0);
|
||||
lv_obj_set_style_opa(level_instrument->panel->vertical_line,opa,0);
|
||||
}
|
||||
|
||||
/********************************************************************************************************/
|
||||
extern osiThread_t *uart1_thread;
|
||||
|
||||
static void btn_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
osiEvent_t event;
|
||||
event.id = 0x3203;
|
||||
osiEventSend(uart1_thread, &event);
|
||||
}
|
||||
}
|
||||
|
||||
static void btn2_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_CLICKED)
|
||||
{
|
||||
osiEvent_t event;
|
||||
event.id = 0x3299;
|
||||
osiEventSend(uart1_thread, &event);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_screen4_init(void)
|
||||
{
|
||||
// level_instrument = level_instrument_create(ui_Screen4);
|
||||
// level_instrument_set_size(level_instrument,270,LEVEL_INSTUMENT_PANEL_ALL);
|
||||
|
||||
lv_obj_t * btn = lv_btn_create(ui_Screen4);
|
||||
lv_obj_align(btn,LV_ALIGN_CENTER,-80,0);
|
||||
lv_obj_set_size(btn,100,50);
|
||||
lv_obj_add_event_cb(btn,btn_cb,LV_EVENT_CLICKED,NULL);
|
||||
|
||||
lv_obj_t * label = lv_label_create(btn);
|
||||
lv_label_set_text(label,"flash");
|
||||
|
||||
lv_obj_t * btn2 = lv_btn_create(ui_Screen4);
|
||||
lv_obj_align(btn2,LV_ALIGN_CENTER,80,0);
|
||||
lv_obj_set_size(btn2,100,50);
|
||||
lv_obj_add_event_cb(btn2,btn2_cb,LV_EVENT_CLICKED,NULL);
|
||||
|
||||
lv_obj_t * label2 = lv_label_create(btn2);
|
||||
lv_label_set_text(label2,"download");
|
||||
}
|
203
EC600U_lvgl_lib/CMakeLists.txt
Normal file
203
EC600U_lvgl_lib/CMakeLists.txt
Normal file
@ -0,0 +1,203 @@
|
||||
# Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
|
||||
# All rights reserved.
|
||||
#
|
||||
# This software is supplied "AS IS" without any warranties.
|
||||
# RDA assumes no responsibility or liability for the use of the software,
|
||||
# conveys no license or title under any patent, copyright, or mask work
|
||||
# right to the product. RDA reserves the right to make changes in the
|
||||
# software without notification. RDA also make no representation or
|
||||
# warranty that such application will be suitable for the specified use
|
||||
# without further testing or modification.
|
||||
|
||||
#configure_file(include/lv_gui_config.h.in ${out_inc_dir}/lv_gui_config.h)
|
||||
|
||||
set(target lvgl)
|
||||
#add_app_libraries($<TARGET_FILE:${target}>)
|
||||
|
||||
add_library(${target} STATIC)
|
||||
set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${out_app_lib_dir})
|
||||
target_compile_definitions(${target} PRIVATE OSI_LOG_TAG=LOG_TAG_LVGL)
|
||||
target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_SRC_DIR} lvgl include)
|
||||
#target_link_libraries(${target} PRIVATE kernel driver hal ql_api_common)
|
||||
target_sources(${target} PRIVATE
|
||||
# core
|
||||
lvgl/src/core/lv_disp.c
|
||||
lvgl/src/core/lv_event.c
|
||||
lvgl/src/core/lv_group.c
|
||||
lvgl/src/core/lv_indev_scroll.c
|
||||
lvgl/src/core/lv_indev.c
|
||||
lvgl/src/core/lv_obj_class.c
|
||||
lvgl/src/core/lv_obj_draw.c
|
||||
lvgl/src/core/lv_obj_pos.c
|
||||
lvgl/src/core/lv_obj_scroll.c
|
||||
lvgl/src/core/lv_obj_style_gen.c
|
||||
lvgl/src/core/lv_obj_style.c
|
||||
lvgl/src/core/lv_obj_tree.c
|
||||
lvgl/src/core/lv_obj.c
|
||||
lvgl/src/core/lv_refr.c
|
||||
lvgl/src/core/lv_theme.c
|
||||
# draw
|
||||
# lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp_osa.c
|
||||
# lvgl/src/draw/nxp_pxp/lv_gpu_nxp_pxp.c
|
||||
# lvgl/src/draw/nxp_vglite/lv_gpu_nxp_vglite.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_arc.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_bg.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_composite.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_img.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_label.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_line.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_mask.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_polygon.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_rect.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl_utils.c
|
||||
# lvgl/src/draw/sdl/lv_draw_sdl.c
|
||||
# lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_arc.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_blend.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_dither.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_gradient.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_img.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_letter.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_line.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_polygon.c
|
||||
# lvgl/src/draw/sw/lv_draw_sw_rect.c
|
||||
lvgl/src/draw/lv_draw_arc.c
|
||||
lvgl/src/draw/lv_draw_blend.c
|
||||
lvgl/src/draw/lv_draw_img.c
|
||||
lvgl/src/draw/lv_draw_label.c
|
||||
lvgl/src/draw/lv_draw_line.c
|
||||
lvgl/src/draw/lv_draw_mask.c
|
||||
lvgl/src/draw/lv_draw_rect.c
|
||||
lvgl/src/draw/lv_draw_triangle.c
|
||||
# lvgl/src/draw/lv_draw.c
|
||||
lvgl/src/draw/lv_img_buf.c
|
||||
lvgl/src/draw/lv_img_cache.c
|
||||
lvgl/src/draw/lv_img_decoder.c
|
||||
# extra
|
||||
lvgl/src/extra/layouts/flex/lv_flex.c
|
||||
lvgl/src/extra/layouts/grid/lv_grid.c
|
||||
lvgl/src/extra/libs/bmp/lv_bmp.c
|
||||
# lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.c
|
||||
lvgl/src/extra/libs/freetype/lv_freetype.c
|
||||
lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c
|
||||
lvgl/src/extra/libs/fsdrv/lv_fs_posix.c
|
||||
lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c
|
||||
lvgl/src/extra/libs/fsdrv/lv_fs_win32.c
|
||||
lvgl/src/extra/libs/gif/gifdec.c
|
||||
lvgl/src/extra/libs/gif/lv_gif.c
|
||||
lvgl/src/extra/libs/png/lodepng.c
|
||||
lvgl/src/extra/libs/png/lv_png.c
|
||||
lvgl/src/extra/libs/qrcode/lv_qrcode.c
|
||||
lvgl/src/extra/libs/qrcode/qrcodegen.c
|
||||
lvgl/src/extra/libs/rlottie/lv_rlottie.c
|
||||
lvgl/src/extra/libs/sjpg/lv_sjpg.c
|
||||
lvgl/src/extra/libs/sjpg/tjpgd.c
|
||||
# lvgl/src/extra/others/gridnav/lv_gridnav.c
|
||||
# lvgl/src/extra/others/monkey/lv_monkey.c
|
||||
lvgl/src/extra/others/snapshot/lv_snapshot.c
|
||||
lvgl/src/extra/themes/basic/lv_theme_basic.c
|
||||
lvgl/src/extra/themes/default/lv_theme_default.c
|
||||
lvgl/src/extra/themes/mono/lv_theme_mono.c
|
||||
lvgl/src/extra/widgets/animimg/lv_animimg.c
|
||||
lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.c
|
||||
lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.c
|
||||
lvgl/src/extra/widgets/calendar/lv_calendar.c
|
||||
lvgl/src/extra/widgets/chart/lv_chart.c
|
||||
lvgl/src/extra/widgets/colorwheel/lv_colorwheel.c
|
||||
lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c
|
||||
lvgl/src/extra/widgets/keyboard/lv_keyboard.c
|
||||
lvgl/src/extra/widgets/led/lv_led.c
|
||||
lvgl/src/extra/widgets/list/lv_list.c
|
||||
lvgl/src/extra/widgets/meter/lv_meter.c
|
||||
lvgl/src/extra/widgets/msgbox/lv_msgbox.c
|
||||
# lvgl/src/extra/widgets/menu/lv_menu.c
|
||||
lvgl/src/extra/widgets/span/lv_span.c
|
||||
lvgl/src/extra/widgets/spinbox/lv_spinbox.c
|
||||
lvgl/src/extra/widgets/spinner/lv_spinner.c
|
||||
lvgl/src/extra/widgets/tabview/lv_tabview.c
|
||||
lvgl/src/extra/widgets/tileview/lv_tileview.c
|
||||
lvgl/src/extra/widgets/win/lv_win.c
|
||||
lvgl/src/extra/lv_extra.c
|
||||
# font
|
||||
lvgl/src/font/lv_font.c
|
||||
lvgl/src/font/lv_font_fmt_txt.c
|
||||
lvgl/src/font/lv_font_loader.c
|
||||
# lvgl/src/font/lv_font_montserrat_8.c
|
||||
# lvgl/src/font/lv_font_montserrat_10.c
|
||||
# lvgl/src/font/lv_font_montserrat_12_subpx.c
|
||||
lvgl/src/font/lv_font_montserrat_14.c
|
||||
# lvgl/src/font/lv_font_montserrat_18.c
|
||||
# lvgl/src/font/lv_font_montserrat_22.c
|
||||
lvgl/src/font/lv_font_montserrat_24.c
|
||||
# lvgl/src/font/lv_font_montserrat_26.c
|
||||
# lvgl/src/font/lv_font_montserrat_28_compressed.c
|
||||
# lvgl/src/font/lv_font_montserrat_30.c
|
||||
# lvgl/src/font/lv_font_montserrat_32.c
|
||||
# lvgl/src/font/lv_font_montserrat_34.c
|
||||
# lvgl/src/font/lv_font_montserrat_36.c
|
||||
# lvgl/src/font/lv_font_montserrat_38.c
|
||||
# lvgl/src/font/lv_font_montserrat_40.c
|
||||
# lvgl/src/font/lv_font_montserrat_44.c
|
||||
# lvgl/src/font/lv_font_montserrat_46.c
|
||||
# lvgl/src/font/lv_font_montserrat_48.c
|
||||
lvgl/src/font/ui_screen1_font_16.c
|
||||
lvgl/src/font/system_status_icon_24.c
|
||||
lvgl/src/font/lv_font_montserrat_12.c
|
||||
lvgl/src/font/lv_font_montserrat_16.c
|
||||
lvgl/src/font/lv_font_montserrat_20.c
|
||||
lvgl/src/font/lv_font_montserrat_42.c
|
||||
lvgl/src/font/ui_screen2_font_16.c
|
||||
lvgl/src/font/lv_font_chinese_12_name.c
|
||||
lvgl/src/font/ui_font_12.c
|
||||
lvgl/src/font/ui_font_16.c
|
||||
# gpu
|
||||
# hal
|
||||
lvgl/src/hal/lv_hal_disp.c
|
||||
lvgl/src/hal/lv_hal_indev.c
|
||||
lvgl/src/hal/lv_hal_tick.c
|
||||
# misc
|
||||
lvgl/src/misc/lv_anim_timeline.c
|
||||
lvgl/src/misc/lv_anim.c
|
||||
lvgl/src/misc/lv_area.c
|
||||
lvgl/src/misc/lv_async.c
|
||||
lvgl/src/misc/lv_bidi.c
|
||||
lvgl/src/misc/lv_color.c
|
||||
lvgl/src/misc/lv_fs.c
|
||||
lvgl/src/misc/lv_gc.c
|
||||
lvgl/src/misc/lv_ll.c
|
||||
lvgl/src/misc/lv_log.c
|
||||
# lvgl/src/misc/lv_lru.c
|
||||
lvgl/src/misc/lv_math.c
|
||||
lvgl/src/misc/lv_mem.c
|
||||
lvgl/src/misc/lv_printf.c
|
||||
lvgl/src/misc/lv_style_gen.c
|
||||
lvgl/src/misc/lv_style.c
|
||||
lvgl/src/misc/lv_templ.c
|
||||
lvgl/src/misc/lv_timer.c
|
||||
lvgl/src/misc/lv_tlsf.c
|
||||
lvgl/src/misc/lv_txt_ap.c
|
||||
lvgl/src/misc/lv_txt.c
|
||||
lvgl/src/misc/lv_utils.c
|
||||
# widgets
|
||||
lvgl/src/widgets/lv_arc.c
|
||||
lvgl/src/widgets/lv_bar.c
|
||||
lvgl/src/widgets/lv_btn.c
|
||||
lvgl/src/widgets/lv_btnmatrix.c
|
||||
lvgl/src/widgets/lv_canvas.c
|
||||
lvgl/src/widgets/lv_checkbox.c
|
||||
lvgl/src/widgets/lv_dropdown.c
|
||||
lvgl/src/widgets/lv_img.c
|
||||
lvgl/src/widgets/lv_label.c
|
||||
lvgl/src/widgets/lv_line.c
|
||||
lvgl/src/widgets/lv_objx_templ.c
|
||||
lvgl/src/widgets/lv_roller.c
|
||||
lvgl/src/widgets/lv_slider.c
|
||||
lvgl/src/widgets/lv_switch.c
|
||||
lvgl/src/widgets/lv_table.c
|
||||
lvgl/src/widgets/lv_textarea.c
|
||||
)
|
||||
relative_glob(srcs include/*.h src/*.c inc/*.h)
|
||||
beautify_c_code(${target} ${srcs})
|
702
EC600U_lvgl_lib/lv_conf.h
Normal file
702
EC600U_lvgl_lib/lv_conf.h
Normal file
@ -0,0 +1,702 @@
|
||||
/**
|
||||
* @file lv_conf.h
|
||||
* Configuration file for v8.0.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy this file as `lv_conf.h`
|
||||
* 1. simply next to the `lvgl` folder
|
||||
* 2. or any other places and
|
||||
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||
* - add the path as include path
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#if 1 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*====================
|
||||
COLOR SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
|
||||
#define LV_COLOR_DEPTH 16
|
||||
|
||||
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
|
||||
#define LV_COLOR_16_SWAP 0
|
||||
|
||||
/*Enable more complex drawing routines to manage screens transparency.
|
||||
*Can be used if the UI is above another layer, e.g. an OSD menu or video player.
|
||||
*Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
|
||||
#define LV_COLOR_SCREEN_TRANSP 0
|
||||
|
||||
/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
|
||||
* 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
|
||||
#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128)
|
||||
|
||||
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
|
||||
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
|
||||
|
||||
/*=========================
|
||||
MEMORY SETTINGS
|
||||
*=========================*/
|
||||
|
||||
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
|
||||
#define LV_MEM_CUSTOM 0
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
|
||||
#define LV_MEM_SIZE (1024U * 64) /*[bytes]*/
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
#define LV_MEM_ADR 0 /*0: unused*/
|
||||
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
|
||||
#if LV_MEM_ADR == 0
|
||||
//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/
|
||||
//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/
|
||||
#endif
|
||||
|
||||
#else /*LV_MEM_CUSTOM*/
|
||||
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
|
||||
#define LV_MEM_CUSTOM_ALLOC malloc
|
||||
#define LV_MEM_CUSTOM_FREE free
|
||||
#define LV_MEM_CUSTOM_REALLOC realloc
|
||||
#endif /*LV_MEM_CUSTOM*/
|
||||
|
||||
/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms.
|
||||
*You will see an error log message if there wasn't enough buffers. */
|
||||
#define LV_MEM_BUF_MAX_NUM 16
|
||||
|
||||
/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
|
||||
#define LV_MEMCPY_MEMSET_STD 0
|
||||
|
||||
/*====================
|
||||
HAL SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Default display refresh period. LVG will redraw changed areas with this period time*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*Input device read period in milliseconds*/
|
||||
#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/
|
||||
|
||||
/*Use a custom tick source that tells the elapsed time in milliseconds.
|
||||
*It removes the need to manually update the tick with `lv_tick_inc()`)*/
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#if LV_TICK_CUSTOM
|
||||
// #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
// #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
#define LV_TICK_CUSTOM_INCLUDE "ql_api_osi.h"
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (ql_rtos_up_time_ms())
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
|
||||
*(Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
/*-------------
|
||||
* Drawing
|
||||
*-----------*/
|
||||
|
||||
/*Enable complex draw engine.
|
||||
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
|
||||
#define LV_DRAW_COMPLEX 1
|
||||
#if LV_DRAW_COMPLEX != 0
|
||||
|
||||
/*Allow buffering some shadow calculation.
|
||||
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* Set number of maximally cached circle data.
|
||||
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||
* 0: to disable caching */
|
||||
#define LV_CIRCLE_CACHE_SIZE 4
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/*Default image cache size. Image caching keeps the images opened.
|
||||
*If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added)
|
||||
*With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
*However the opened images might consume additional RAM.
|
||||
*0: to disable caching*/
|
||||
#define LV_IMG_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
||||
/*Default gradient buffer size.
|
||||
*When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again.
|
||||
*LV_GRAD_CACHE_DEF_SIZE sets the size of this cache in bytes.
|
||||
*If the cache is too small the map will be allocated only while it's required for the drawing.
|
||||
*0 mean no caching.*/
|
||||
#define LV_GRAD_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display)
|
||||
*LV_DITHER_GRADIENT implies allocating one or two more lines of the object's rendering surface
|
||||
*The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */
|
||||
#define LV_DITHER_GRADIENT 0
|
||||
#if LV_DITHER_GRADIENT
|
||||
/*Add support for error diffusion dithering.
|
||||
*Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing.
|
||||
*The increase in memory consumption is (24 bits * object's width)*/
|
||||
#define LV_DITHER_ERROR_DIFFUSION 0
|
||||
#endif
|
||||
|
||||
/*Maximum buffer size to allocate for rotation.
|
||||
*Only used if software rotation is enabled in the display driver.*/
|
||||
#define LV_DISP_ROT_MAX_BUF (10*1024)
|
||||
|
||||
/*-------------
|
||||
* GPU
|
||||
*-----------*/
|
||||
|
||||
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
|
||||
#define LV_USE_GPU_STM32_DMA2D 0
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
/*Must be defined to include path of CMSIS header of target processor
|
||||
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
|
||||
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
#endif
|
||||
|
||||
/*Use NXP's PXP GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_PXP 0
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
|
||||
* and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS
|
||||
* has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
|
||||
*0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
|
||||
*/
|
||||
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||
#endif
|
||||
|
||||
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||
|
||||
/*Use SDL renderer API*/
|
||||
#define LV_USE_GPU_SDL 0
|
||||
#if LV_USE_GPU_SDL
|
||||
#define LV_GPU_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||
/*Texture cache size, 8MB by default*/
|
||||
#define LV_GPU_SDL_LRU_SIZE (1024 * 1024 * 8)
|
||||
/*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
|
||||
#define LV_GPU_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
|
||||
#endif
|
||||
|
||||
/*-------------
|
||||
* Logging
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 0
|
||||
#if LV_USE_LOG
|
||||
|
||||
/*How important log should be added:
|
||||
*LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
|
||||
*LV_LOG_LEVEL_INFO Log important events
|
||||
*LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem
|
||||
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||
*LV_LOG_LEVEL_USER Only logs added by the user
|
||||
*LV_LOG_LEVEL_NONE Do not log anything*/
|
||||
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/*1: Print the log with 'printf';
|
||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||
#define LV_LOG_PRINTF 0
|
||||
|
||||
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||
#define LV_LOG_TRACE_MEM 1
|
||||
#define LV_LOG_TRACE_TIMER 1
|
||||
#define LV_LOG_TRACE_INDEV 1
|
||||
#define LV_LOG_TRACE_DISP_REFR 1
|
||||
#define LV_LOG_TRACE_EVENT 1
|
||||
#define LV_LOG_TRACE_OBJ_CREATE 1
|
||||
#define LV_LOG_TRACE_LAYOUT 1
|
||||
#define LV_LOG_TRACE_ANIM 1
|
||||
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*-------------
|
||||
* Asserts
|
||||
*-----------*/
|
||||
|
||||
/*Enable asserts if an operation is failed or an invalid data is found.
|
||||
*If LV_USE_LOG is enabled an error message will be printed on failure*/
|
||||
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
|
||||
/*-------------
|
||||
* Others
|
||||
*-----------*/
|
||||
|
||||
/*1: Show CPU usage and FPS count*/
|
||||
#define LV_USE_PERF_MONITOR 0
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||
#endif
|
||||
|
||||
/*1: Show the used memory and the memory fragmentation
|
||||
* Requires LV_MEM_CUSTOM = 0*/
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
|
||||
#endif
|
||||
|
||||
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||
#define LV_USE_REFR_DEBUG 0
|
||||
|
||||
/*Change the built in (v)snprintf functions*/
|
||||
#define LV_SPRINTF_CUSTOM 0
|
||||
#if LV_SPRINTF_CUSTOM
|
||||
#define LV_SPRINTF_INCLUDE <stdio.h>
|
||||
#define lv_snprintf snprintf
|
||||
#define lv_vsnprintf vsnprintf
|
||||
#else /*LV_SPRINTF_CUSTOM*/
|
||||
#define LV_SPRINTF_USE_FLOAT 0
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
#define LV_USE_USER_DATA 1
|
||||
|
||||
/*Garbage Collector settings
|
||||
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
|
||||
#define LV_ENABLE_GC 0
|
||||
#if LV_ENABLE_GC != 0
|
||||
#define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
|
||||
/*=====================
|
||||
* COMPILER SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*For big endian systems set to 1*/
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||
|
||||
/*Define a custom attribute to `lv_disp_flush_ready` function*/
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/*Required alignment size for buffers*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||
|
||||
/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
|
||||
* E.g. __attribute__((aligned(4)))*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*Compiler prefix for a big array declaration in RAM*/
|
||||
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||
|
||||
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||
#define LV_ATTRIBUTE_FAST_MEM
|
||||
|
||||
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
|
||||
#define LV_ATTRIBUTE_DMA
|
||||
|
||||
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||
*should also appear on LVGL binding API such as Micropython.*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||
|
||||
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
|
||||
#define LV_USE_LARGE_COORD 0
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_12 1
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 1
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 1
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
#define LV_FONT_MONTSERRAT_24 1
|
||||
#define LV_FONT_MONTSERRAT_26 0
|
||||
#define LV_FONT_MONTSERRAT_28 0
|
||||
#define LV_FONT_MONTSERRAT_30 0
|
||||
#define LV_FONT_MONTSERRAT_32 0
|
||||
#define LV_FONT_MONTSERRAT_34 0
|
||||
#define LV_FONT_MONTSERRAT_36 0
|
||||
#define LV_FONT_MONTSERRAT_38 0
|
||||
#define LV_FONT_MONTSERRAT_40 0
|
||||
#define LV_FONT_MONTSERRAT_42 1
|
||||
#define LV_FONT_MONTSERRAT_44 0
|
||||
#define LV_FONT_MONTSERRAT_46 0
|
||||
#define LV_FONT_MONTSERRAT_48 0
|
||||
|
||||
/*Demonstrate special features*/
|
||||
#define LV_FONT_MONTSERRAT_12_SUBPX 0
|
||||
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/
|
||||
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||
|
||||
/*Pixel perfect monospace fonts*/
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/*Optionally declare custom fonts here.
|
||||
*You can use these fonts as default font too and they will be available globally.
|
||||
*E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font*/
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||
|
||||
/*Enable handling large font and/or fonts with a lot of characters.
|
||||
*The limit depends on the font size, font face and bpp.
|
||||
*Compiler error will be triggered if a font needs it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/*Enables/disables support for compressed fonts.*/
|
||||
#define LV_USE_FONT_COMPRESSED 0
|
||||
|
||||
/*Enable subpixel rendering*/
|
||||
#define LV_USE_FONT_SUBPX 0
|
||||
#if LV_USE_FONT_SUBPX
|
||||
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
|
||||
#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* TEXT SETTINGS
|
||||
*=================*/
|
||||
|
||||
/**
|
||||
* Select a character encoding for strings.
|
||||
* Your IDE or editor should have the same character encoding
|
||||
* - LV_TXT_ENC_UTF8
|
||||
* - LV_TXT_ENC_ASCII
|
||||
*/
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/*If a word is at least this long, will break wherever "prettiest"
|
||||
*To disable, set to a value <= 0*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line before a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line after a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/*The control character to use for signalling text recoloring.*/
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
/*Set the default direction. Supported values:
|
||||
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Enable Arabic/Persian processing
|
||||
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||
|
||||
/*==================
|
||||
* WIDGET USAGE
|
||||
*================*/
|
||||
|
||||
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
#define LV_USE_ANIMIMG 1
|
||||
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
#define LV_USE_BTN 1
|
||||
|
||||
#define LV_USE_BTNMATRIX 1
|
||||
|
||||
#define LV_USE_CANVAS 1
|
||||
|
||||
#define LV_USE_CHECKBOX 1
|
||||
|
||||
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMG 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL
|
||||
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
|
||||
#if LV_USE_ROLLER
|
||||
#define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||
|
||||
#define LV_USE_SWITCH 1
|
||||
|
||||
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||
#if LV_USE_TEXTAREA != 0
|
||||
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_TABLE 1
|
||||
|
||||
/*==================
|
||||
* EXTRA COMPONENTS
|
||||
*==================*/
|
||||
|
||||
/*-----------
|
||||
* Widgets
|
||||
*----------*/
|
||||
#define LV_USE_CALENDAR 1
|
||||
#if LV_USE_CALENDAR
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||
#else
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||
#endif
|
||||
|
||||
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||
#define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#define LV_USE_CHART 1
|
||||
|
||||
#define LV_USE_COLORWHEEL 1
|
||||
|
||||
#define LV_USE_IMGBTN 1
|
||||
|
||||
#define LV_USE_KEYBOARD 1
|
||||
|
||||
#define LV_USE_LED 1
|
||||
|
||||
#define LV_USE_LIST 1
|
||||
|
||||
#define LV_USE_MENU 1
|
||||
|
||||
#define LV_USE_METER 1
|
||||
|
||||
#define LV_USE_MSGBOX 1
|
||||
|
||||
#define LV_USE_SPINBOX 1
|
||||
|
||||
#define LV_USE_SPINNER 1
|
||||
|
||||
#define LV_USE_TABVIEW 1
|
||||
|
||||
#define LV_USE_TILEVIEW 1
|
||||
|
||||
#define LV_USE_WIN 1
|
||||
|
||||
#define LV_USE_SPAN 1
|
||||
#if LV_USE_SPAN
|
||||
/*A line text can contain maximum num of span descriptor */
|
||||
#define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||
#endif
|
||||
|
||||
/*-----------
|
||||
* Themes
|
||||
*----------*/
|
||||
|
||||
/*A simple, impressive and very complete theme*/
|
||||
#define LV_USE_THEME_DEFAULT 1
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
|
||||
/*0: Light mode; 1: Dark mode*/
|
||||
#define LV_THEME_DEFAULT_DARK 0
|
||||
|
||||
/*1: Enable grow on press*/
|
||||
#define LV_THEME_DEFAULT_GROW 1
|
||||
|
||||
/*Default transition time in [ms]*/
|
||||
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||
#endif /*LV_USE_THEME_DEFAULT*/
|
||||
|
||||
/*A very simple theme that is a good starting point for a custom theme*/
|
||||
#define LV_USE_THEME_BASIC 1
|
||||
|
||||
/*A theme designed for monochrome displays*/
|
||||
#define LV_USE_THEME_MONO 1
|
||||
|
||||
/*-----------
|
||||
* Layouts
|
||||
*----------*/
|
||||
|
||||
/*A layout similar to Flexbox in CSS.*/
|
||||
#define LV_USE_FLEX 1
|
||||
|
||||
/*A layout similar to Grid in CSS.*/
|
||||
#define LV_USE_GRID 1
|
||||
|
||||
/*---------------------
|
||||
* 3rd party libraries
|
||||
*--------------------*/
|
||||
|
||||
/*File system interfaces for common APIs */
|
||||
|
||||
/*API for fopen, fread, etc*/
|
||||
#define LV_USE_FS_STDIO 0
|
||||
#if LV_USE_FS_STDIO
|
||||
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for open, read, etc*/
|
||||
#define LV_USE_FS_POSIX 0
|
||||
#if LV_USE_FS_POSIX
|
||||
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for CreateFile, ReadFile, etc*/
|
||||
#define LV_USE_FS_WIN32 0
|
||||
#if LV_USE_FS_WIN32
|
||||
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
|
||||
#define LV_USE_FS_FATFS 0
|
||||
#if LV_USE_FS_FATFS
|
||||
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*PNG decoder library*/
|
||||
#define LV_USE_PNG 0
|
||||
|
||||
/*BMP decoder library*/
|
||||
#define LV_USE_BMP 0
|
||||
|
||||
/* JPG + split JPG decoder library.
|
||||
* Split JPG is a custom format optimized for embedded systems. */
|
||||
#define LV_USE_SJPG 0
|
||||
|
||||
/*GIF decoder library*/
|
||||
#define LV_USE_GIF 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
/*FreeType library*/
|
||||
#define LV_USE_FREETYPE 0
|
||||
#if LV_USE_FREETYPE
|
||||
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
|
||||
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
|
||||
/* if font size >= 256, must be configured as image cache */
|
||||
#define LV_FREETYPE_SBIT_CACHE 0
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 0
|
||||
#define LV_FREETYPE_CACHE_FT_SIZES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
#define LV_USE_RLOTTIE 0
|
||||
|
||||
/*FFmpeg library for image decoding and playing videos
|
||||
*Supports all major image formats so do not enable other image decoder with it*/
|
||||
#define LV_USE_FFMPEG 0
|
||||
#if LV_USE_FFMPEG
|
||||
/*Dump input information to stderr*/
|
||||
#define LV_FFMPEG_AV_DUMP_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*-----------
|
||||
* Others
|
||||
*----------*/
|
||||
|
||||
/*1: Enable API to take snapshot for object*/
|
||||
#define LV_USE_SNAPSHOT 0
|
||||
|
||||
/*1: Enable Monkey test*/
|
||||
#define LV_USE_MONKEY 0
|
||||
|
||||
/*1: Enable grid navigation*/
|
||||
#define LV_USE_GRIDNAV 0
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
||||
/*Enable the examples to be built with the library*/
|
||||
#define LV_BUILD_EXAMPLES 1
|
||||
|
||||
/*===================
|
||||
* DEMO USAGE
|
||||
====================*/
|
||||
|
||||
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||
#endif
|
||||
|
||||
/*Demonstrate the usage of encoder and keyboard*/
|
||||
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||
|
||||
/*Benchmark your system*/
|
||||
#define LV_USE_DEMO_BENCHMARK 0
|
||||
|
||||
/*Stress test for LVGL*/
|
||||
#define LV_USE_DEMO_STRESS 0
|
||||
|
||||
/*Music player demo*/
|
||||
#define LV_USE_DEMO_MUSIC 0
|
||||
#if LV_USE_DEMO_MUSIC
|
||||
# define LV_DEMO_MUSIC_SQUARE 0
|
||||
# define LV_DEMO_MUSIC_LANDSCAPE 0
|
||||
# define LV_DEMO_MUSIC_ROUND 0
|
||||
# define LV_DEMO_MUSIC_LARGE 0
|
||||
# define LV_DEMO_MUSIC_AUTO_PLAY 0
|
||||
#endif
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
143
EC600U_lvgl_lib/lvgl/lvgl.h
Normal file
143
EC600U_lvgl_lib/lvgl/lvgl.h
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file lvgl.h
|
||||
* Include all LVGL related headers
|
||||
*/
|
||||
|
||||
#ifndef LVGL_H
|
||||
#define LVGL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************
|
||||
* CURRENT VERSION OF LVGL
|
||||
***************************/
|
||||
#define LVGL_VERSION_MAJOR 8
|
||||
#define LVGL_VERSION_MINOR 2
|
||||
#define LVGL_VERSION_PATCH 0
|
||||
#define LVGL_VERSION_INFO ""
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "src/misc/lv_log.h"
|
||||
#include "src/misc/lv_timer.h"
|
||||
#include "src/misc/lv_math.h"
|
||||
#include "src/misc/lv_mem.h"
|
||||
#include "src/misc/lv_async.h"
|
||||
#include "src/misc/lv_anim_timeline.h"
|
||||
#include "src/misc/lv_printf.h"
|
||||
|
||||
#include "src/hal/lv_hal.h"
|
||||
|
||||
#include "src/core/lv_obj.h"
|
||||
#include "src/core/lv_group.h"
|
||||
#include "src/core/lv_indev.h"
|
||||
#include "src/core/lv_refr.h"
|
||||
#include "src/core/lv_disp.h"
|
||||
#include "src/core/lv_theme.h"
|
||||
|
||||
#include "src/font/lv_font.h"
|
||||
#include "src/font/lv_font_loader.h"
|
||||
#include "src/font/lv_font_fmt_txt.h"
|
||||
|
||||
#include "src/widgets/lv_arc.h"
|
||||
#include "src/widgets/lv_btn.h"
|
||||
#include "src/widgets/lv_img.h"
|
||||
#include "src/widgets/lv_label.h"
|
||||
#include "src/widgets/lv_line.h"
|
||||
#include "src/widgets/lv_table.h"
|
||||
#include "src/widgets/lv_checkbox.h"
|
||||
#include "src/widgets/lv_bar.h"
|
||||
#include "src/widgets/lv_slider.h"
|
||||
#include "src/widgets/lv_btnmatrix.h"
|
||||
#include "src/widgets/lv_dropdown.h"
|
||||
#include "src/widgets/lv_roller.h"
|
||||
#include "src/widgets/lv_textarea.h"
|
||||
#include "src/widgets/lv_canvas.h"
|
||||
#include "src/widgets/lv_switch.h"
|
||||
|
||||
#include "src/draw/lv_draw.h"
|
||||
|
||||
#include "src/lv_api_map.h"
|
||||
|
||||
/*-----------------
|
||||
* EXTRAS
|
||||
*----------------*/
|
||||
#include "src/extra/lv_extra.h"
|
||||
#include "src/extra/widgets/lv_widgets.h"
|
||||
#include "src/extra/layouts/lv_layouts.h"
|
||||
#include "src/extra/themes/lv_themes.h"
|
||||
#include "src/extra/others/lv_others.h"
|
||||
#include "src/extra/libs/lv_libs.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/** Gives 1 if the x.y.z version is supported in the current version
|
||||
* Usage:
|
||||
*
|
||||
* - Require v6
|
||||
* #if LV_VERSION_CHECK(6,0,0)
|
||||
* new_func_in_v6();
|
||||
* #endif
|
||||
*
|
||||
*
|
||||
* - Require at least v5.3
|
||||
* #if LV_VERSION_CHECK(5,3,0)
|
||||
* new_feature_from_v5_3();
|
||||
* #endif
|
||||
*
|
||||
*
|
||||
* - Require v5.3.2 bugfixes
|
||||
* #if LV_VERSION_CHECK(5,3,2)
|
||||
* bugfix_in_v5_3_2();
|
||||
* #endif
|
||||
*
|
||||
*/
|
||||
#define LV_VERSION_CHECK(x,y,z) (x == LVGL_VERSION_MAJOR && (y < LVGL_VERSION_MINOR || (y == LVGL_VERSION_MINOR && z <= LVGL_VERSION_PATCH)))
|
||||
|
||||
/**
|
||||
* Wrapper functions for VERSION macros
|
||||
*/
|
||||
|
||||
static inline int lv_version_major(void)
|
||||
{
|
||||
return LVGL_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
static inline int lv_version_minor(void)
|
||||
{
|
||||
return LVGL_VERSION_MINOR;
|
||||
}
|
||||
|
||||
static inline int lv_version_patch(void)
|
||||
{
|
||||
return LVGL_VERSION_PATCH;
|
||||
}
|
||||
|
||||
static inline const char *lv_version_info(void)
|
||||
{
|
||||
return LVGL_VERSION_INFO;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LVGL_H*/
|
20
EC600U_lvgl_lib/lvgl/src/core/lv_core.mk
Normal file
20
EC600U_lvgl_lib/lvgl/src/core/lv_core.mk
Normal file
@ -0,0 +1,20 @@
|
||||
CSRCS += lv_disp.c
|
||||
CSRCS += lv_group.c
|
||||
CSRCS += lv_indev.c
|
||||
CSRCS += lv_indev_scroll.c
|
||||
CSRCS += lv_obj.c
|
||||
CSRCS += lv_obj_class.c
|
||||
CSRCS += lv_obj_draw.c
|
||||
CSRCS += lv_obj_pos.c
|
||||
CSRCS += lv_obj_scroll.c
|
||||
CSRCS += lv_obj_style.c
|
||||
CSRCS += lv_obj_style_gen.c
|
||||
CSRCS += lv_obj_tree.c
|
||||
CSRCS += lv_event.c
|
||||
CSRCS += lv_refr.c
|
||||
CSRCS += lv_theme.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/core"
|
440
EC600U_lvgl_lib/lvgl/src/core/lv_disp.c
Normal file
440
EC600U_lvgl_lib/lvgl/src/core/lv_disp.c
Normal file
@ -0,0 +1,440 @@
|
||||
/**
|
||||
* @file lv_disp.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../core/lv_refr.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void scr_load_anim_start(lv_anim_t * a);
|
||||
static void opa_scale_anim(void * obj, int32_t v);
|
||||
static void set_x_anim(void * obj, int32_t v);
|
||||
static void set_y_anim(void * obj, int32_t v);
|
||||
static void scr_anim_ready(lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with a pointer to the active screen
|
||||
* @param disp pointer to display which active screen should be get. (NULL to use the default
|
||||
* screen)
|
||||
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its active screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->act_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with a pointer to the previous screen. Only used during screen transitions.
|
||||
* @param disp pointer to display which previous screen should be get. (NULL to use the default
|
||||
* screen)
|
||||
* @return pointer to the previous screen object or NULL if not used now
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered to get its previous screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->prev_scr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a screen active
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_disp_load_scr(lv_obj_t * scr)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(scr);
|
||||
if(!d) return; /*Shouldn't happen, just to be sure*/
|
||||
|
||||
if(d->act_scr) lv_event_send(d->act_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
|
||||
|
||||
d->act_scr = scr;
|
||||
|
||||
if(d->act_scr) lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL);
|
||||
|
||||
lv_obj_invalidate(scr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
|
||||
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
|
||||
* @return pointer to the top layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->top_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return with the sys. layer. (Same on every screen and it is above the normal screen and the top
|
||||
* layer)
|
||||
* @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen)
|
||||
* @return pointer to the sys layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_layer_sys: no display registered to get its sys. layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->sys_layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the theme of a display
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th)
|
||||
{
|
||||
if(disp == NULL) disp = lv_disp_get_default();
|
||||
disp->theme = th;
|
||||
|
||||
if(disp->screen_cnt == 3 &&
|
||||
lv_obj_get_child_cnt(disp->screens[0]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[1]) == 0 &&
|
||||
lv_obj_get_child_cnt(disp->screens[2]) == 0) {
|
||||
lv_theme_apply(disp->screens[0]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the theme of a display
|
||||
* @param disp pointer to a display
|
||||
* @return the display's theme (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_disp_get_theme(lv_disp_t * disp)
|
||||
{
|
||||
if(disp == NULL) disp = lv_disp_get_default();
|
||||
return disp->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background color of a display
|
||||
* @param disp pointer to a display
|
||||
* @param color color of the background
|
||||
*/
|
||||
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_color = color;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background image of a display
|
||||
* @param disp pointer to a display
|
||||
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
|
||||
*/
|
||||
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_img = img_src;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set opacity of the background
|
||||
* @param disp pointer to a display
|
||||
* @param opa opacity (0..255)
|
||||
*/
|
||||
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->bg_opa = opa;
|
||||
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
|
||||
_lv_inv_area(disp, &a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch screen with animation
|
||||
* @param scr pointer to the new screen to load
|
||||
* @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
|
||||
* @param time time of the animation
|
||||
* @param delay delay before the transition
|
||||
* @param auto_del true: automatically delete the old screen
|
||||
*/
|
||||
void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del)
|
||||
{
|
||||
|
||||
lv_disp_t * d = lv_obj_get_disp(new_scr);
|
||||
lv_obj_t * act_scr = lv_scr_act();
|
||||
|
||||
if(d->scr_to_load && act_scr != d->scr_to_load) {
|
||||
lv_disp_load_scr(d->scr_to_load);
|
||||
lv_anim_del(d->scr_to_load, NULL);
|
||||
lv_obj_set_pos(d->scr_to_load, 0, 0);
|
||||
lv_obj_remove_local_style_prop(d->scr_to_load, LV_STYLE_OPA, 0);
|
||||
|
||||
if(d->del_prev) {
|
||||
lv_obj_del(act_scr);
|
||||
}
|
||||
act_scr = d->scr_to_load;
|
||||
}
|
||||
|
||||
d->scr_to_load = new_scr;
|
||||
|
||||
if(d->prev_scr && d->del_prev) {
|
||||
lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
}
|
||||
|
||||
d->del_prev = auto_del;
|
||||
|
||||
/*Be sure there is no other animation on the screens*/
|
||||
lv_anim_del(new_scr, NULL);
|
||||
lv_anim_del(lv_scr_act(), NULL);
|
||||
|
||||
/*Be sure both screens are in a normal position*/
|
||||
lv_obj_set_pos(new_scr, 0, 0);
|
||||
lv_obj_set_pos(lv_scr_act(), 0, 0);
|
||||
lv_obj_remove_local_style_prop(new_scr, LV_STYLE_OPA, 0);
|
||||
lv_obj_remove_local_style_prop(lv_scr_act(), LV_STYLE_OPA, 0);
|
||||
|
||||
lv_anim_t a_new;
|
||||
lv_anim_init(&a_new);
|
||||
lv_anim_set_var(&a_new, new_scr);
|
||||
lv_anim_set_start_cb(&a_new, scr_load_anim_start);
|
||||
lv_anim_set_ready_cb(&a_new, scr_anim_ready);
|
||||
lv_anim_set_time(&a_new, time);
|
||||
lv_anim_set_delay(&a_new, delay);
|
||||
|
||||
lv_anim_t a_old;
|
||||
lv_anim_init(&a_old);
|
||||
lv_anim_set_var(&a_old, d->act_scr);
|
||||
lv_anim_set_time(&a_old, time);
|
||||
lv_anim_set_delay(&a_old, delay);
|
||||
|
||||
switch(anim_type) {
|
||||
case LV_SCR_LOAD_ANIM_NONE:
|
||||
/*Create a dummy animation to apply the delay*/
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, 0, 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_LEFT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
|
||||
lv_anim_set_exec_cb(&a_new, set_x_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_x_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_TOP:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
|
||||
break;
|
||||
case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
|
||||
lv_anim_set_exec_cb(&a_new, set_y_anim);
|
||||
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
|
||||
|
||||
lv_anim_set_exec_cb(&a_old, set_y_anim);
|
||||
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
|
||||
break;
|
||||
|
||||
case LV_SCR_LOAD_ANIM_FADE_ON:
|
||||
lv_anim_set_exec_cb(&a_new, opa_scale_anim);
|
||||
lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
break;
|
||||
}
|
||||
|
||||
lv_anim_start(&a_new);
|
||||
lv_anim_start(&a_old);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elapsed time since last user activity on a display (e.g. click)
|
||||
* @param disp pointer to a display (NULL to get the overall smallest inactivity)
|
||||
* @return elapsed ticks (milliseconds) since the last activity
|
||||
*/
|
||||
uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp)
|
||||
{
|
||||
if(disp) return lv_tick_elaps(disp->last_activity_time);
|
||||
|
||||
lv_disp_t * d;
|
||||
uint32_t t = UINT32_MAX;
|
||||
d = lv_disp_get_next(NULL);
|
||||
while(d) {
|
||||
uint32_t elaps = lv_tick_elaps(d->last_activity_time);
|
||||
t = LV_MIN(t, elaps);
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually trigger an activity on a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_trig_activity(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_trig_activity: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
disp->last_activity_time = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean any CPU cache that is related to the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_clean_dcache(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_clean_dcache: no display registered");
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->driver->clean_dcache_cb)
|
||||
disp->driver->clean_dcache_cb(disp->driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pointer to the screen refresher timer to
|
||||
* modify its parameters with `lv_timer_...` functions.
|
||||
* @param disp pointer to a display
|
||||
* @return pointer to the display refresher timer. (NULL on error)
|
||||
*/
|
||||
lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("lv_disp_get_refr_timer: no display registered");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return disp->refr_timer;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void scr_load_anim_start(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
d->prev_scr = lv_scr_act();
|
||||
|
||||
lv_disp_load_scr(a->var);
|
||||
}
|
||||
|
||||
static void opa_scale_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void set_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_x(obj, v);
|
||||
}
|
||||
|
||||
static void set_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_y(obj, v);
|
||||
}
|
||||
|
||||
static void scr_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_disp_t * d = lv_obj_get_disp(a->var);
|
||||
|
||||
if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
|
||||
d->prev_scr = NULL;
|
||||
d->scr_to_load = NULL;
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
}
|
244
EC600U_lvgl_lib/lvgl/src/core/lv_disp.h
Normal file
244
EC600U_lvgl_lib/lvgl/src/core/lv_disp.h
Normal file
@ -0,0 +1,244 @@
|
||||
/**
|
||||
* @file lv_disp.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DISP_H
|
||||
#define LV_DISP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../hal/lv_hal.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef enum {
|
||||
LV_SCR_LOAD_ANIM_NONE,
|
||||
LV_SCR_LOAD_ANIM_OVER_LEFT,
|
||||
LV_SCR_LOAD_ANIM_OVER_RIGHT,
|
||||
LV_SCR_LOAD_ANIM_OVER_TOP,
|
||||
LV_SCR_LOAD_ANIM_OVER_BOTTOM,
|
||||
LV_SCR_LOAD_ANIM_MOVE_LEFT,
|
||||
LV_SCR_LOAD_ANIM_MOVE_RIGHT,
|
||||
LV_SCR_LOAD_ANIM_MOVE_TOP,
|
||||
LV_SCR_LOAD_ANIM_MOVE_BOTTOM,
|
||||
LV_SCR_LOAD_ANIM_FADE_ON,
|
||||
} lv_scr_load_anim_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Return with a pointer to the active screen
|
||||
* @param disp pointer to display which active screen should be get. (NULL to use the default
|
||||
* screen)
|
||||
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Return with a pointer to the previous screen. Only used during screen transitions.
|
||||
* @param disp pointer to display which previous screen should be get. (NULL to use the default
|
||||
* screen)
|
||||
* @return pointer to the previous screen object or NULL if not used now
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Make a screen active
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_disp_load_scr(lv_obj_t * scr);
|
||||
|
||||
/**
|
||||
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
|
||||
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
|
||||
* @return pointer to the top layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Return with the sys. layer. (Same on every screen and it is above the normal screen and the top
|
||||
* layer)
|
||||
* @param disp pointer to display which sys. layer should be retrieved. (NULL to use the default screen)
|
||||
* @return pointer to the sys layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Set the theme of a display
|
||||
* @param disp pointer to a display
|
||||
*/
|
||||
void lv_disp_set_theme(lv_disp_t * disp, lv_theme_t * th);
|
||||
|
||||
/**
|
||||
* Get the theme of a display
|
||||
* @param disp pointer to a display
|
||||
* @return the display's theme (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_disp_get_theme(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Set the background color of a display
|
||||
* @param disp pointer to a display
|
||||
* @param color color of the background
|
||||
*/
|
||||
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the background image of a display
|
||||
* @param disp pointer to a display
|
||||
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
|
||||
*/
|
||||
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src);
|
||||
|
||||
/**
|
||||
* Set opacity of the background
|
||||
* @param disp pointer to a display
|
||||
* @param opa opacity (0..255)
|
||||
*/
|
||||
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Switch screen with animation
|
||||
* @param scr pointer to the new screen to load
|
||||
* @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
|
||||
* @param time time of the animation
|
||||
* @param delay delay before the transition
|
||||
* @param auto_del true: automatically delete the old screen
|
||||
*/
|
||||
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);
|
||||
|
||||
/**
|
||||
* Get elapsed time since last user activity on a display (e.g. click)
|
||||
* @param disp pointer to a display (NULL to get the overall smallest inactivity)
|
||||
* @return elapsed ticks (milliseconds) since the last activity
|
||||
*/
|
||||
uint32_t lv_disp_get_inactive_time(const lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Manually trigger an activity on a display
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_trig_activity(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Clean any CPU cache that is related to the display.
|
||||
* @param disp pointer to a display (NULL to use the default display)
|
||||
*/
|
||||
void lv_disp_clean_dcache(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Get a pointer to the screen refresher timer to
|
||||
* modify its parameters with `lv_timer_...` functions.
|
||||
* @param disp pointer to a display
|
||||
* @return pointer to the display refresher timer. (NULL on error)
|
||||
*/
|
||||
lv_timer_t * _lv_disp_get_refr_timer(lv_disp_t * disp);
|
||||
|
||||
/*------------------------------------------------
|
||||
* To improve backward compatibility
|
||||
* Recommended only if you have one display
|
||||
*------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Get the active screen of the default display
|
||||
* @return pointer to the active screen
|
||||
*/
|
||||
static inline lv_obj_t * lv_scr_act(void)
|
||||
{
|
||||
return lv_disp_get_scr_act(lv_disp_get_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top layer of the default display
|
||||
* @return pointer to the top layer
|
||||
*/
|
||||
static inline lv_obj_t * lv_layer_top(void)
|
||||
{
|
||||
return lv_disp_get_layer_top(lv_disp_get_default());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active screen of the default display
|
||||
* @return pointer to the sys layer
|
||||
*/
|
||||
static inline lv_obj_t * lv_layer_sys(void)
|
||||
{
|
||||
return lv_disp_get_layer_sys(lv_disp_get_default());
|
||||
}
|
||||
|
||||
static inline void lv_scr_load(lv_obj_t * scr)
|
||||
{
|
||||
lv_disp_load_scr(scr);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/*------------------------------------------------
|
||||
* To improve backward compatibility
|
||||
* Recommended only if you have one display
|
||||
*------------------------------------------------*/
|
||||
|
||||
#ifndef LV_HOR_RES
|
||||
/**
|
||||
* The horizontal resolution of the currently active display.
|
||||
*/
|
||||
#define LV_HOR_RES lv_disp_get_hor_res(lv_disp_get_default())
|
||||
#endif
|
||||
|
||||
#ifndef LV_VER_RES
|
||||
/**
|
||||
* The vertical resolution of the currently active display.
|
||||
*/
|
||||
#define LV_VER_RES lv_disp_get_ver_res(lv_disp_get_default())
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
|
||||
* considering the DPI of the default display.
|
||||
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
|
||||
* DPI of the display.
|
||||
* @param n the number of pixels to scale
|
||||
* @return `n x current_dpi/160`
|
||||
*/
|
||||
static inline lv_coord_t lv_dpx(lv_coord_t n)
|
||||
{
|
||||
return LV_DPX(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
|
||||
* considering the DPI of the given display.
|
||||
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
|
||||
* DPI of the display.
|
||||
* @param obj a display whose dpi should be considered
|
||||
* @param n the number of pixels to scale
|
||||
* @return `n x current_dpi/160`
|
||||
*/
|
||||
static inline lv_coord_t lv_disp_dpx(const lv_disp_t * disp, lv_coord_t n)
|
||||
{
|
||||
return _LV_DPX_CALC(lv_disp_get_dpi(disp), n);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DISP_H*/
|
480
EC600U_lvgl_lib/lvgl/src/core/lv_event.c
Normal file
480
EC600U_lvgl_lib/lvgl/src/core/lv_event.c
Normal file
@ -0,0 +1,480 @@
|
||||
/**
|
||||
* @file lv_event.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct _lv_event_dsc_t {
|
||||
lv_event_cb_t cb;
|
||||
void * user_data;
|
||||
lv_event_code_t filter : 8;
|
||||
} lv_event_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id);
|
||||
static lv_res_t event_send_core(lv_event_t * e);
|
||||
static bool event_is_bubbled(lv_event_t * e);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_event_t * event_head;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_LOG_TRACE_EVENT
|
||||
#define EVENT_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define EVENT_TRACE(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
|
||||
{
|
||||
if(obj == NULL) return LV_RES_OK;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_event_t e;
|
||||
e.target = obj;
|
||||
e.current_target = obj;
|
||||
e.code = event_code;
|
||||
e.user_data = NULL;
|
||||
e.param = param;
|
||||
e.deleted = 0;
|
||||
|
||||
|
||||
/*Build a simple linked list from the objects used in the events
|
||||
*It's important to know if an this object was deleted by a nested event
|
||||
*called from this `event_cb`.*/
|
||||
e.prev = event_head;
|
||||
event_head = &e;
|
||||
|
||||
/*Send the event*/
|
||||
lv_res_t res = event_send_core(&e);
|
||||
|
||||
/*Remove this element from the list*/
|
||||
event_head = e.prev;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
const lv_obj_class_t * base;
|
||||
if(class_p == NULL) base = e->current_target->class_p;
|
||||
else base = class_p->base_class;
|
||||
|
||||
/*Find a base in which Call the ancestor's event handler_cb is set*/
|
||||
while(base && base->event_cb == NULL) base = base->base_class;
|
||||
|
||||
if(base == NULL) return LV_RES_OK;
|
||||
if(base->event_cb == NULL) return LV_RES_OK;
|
||||
|
||||
/*Call the actual event callback*/
|
||||
e->user_data = NULL;
|
||||
base->event_cb(base, e);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) res = LV_RES_INV;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t * lv_event_get_target(lv_event_t * e)
|
||||
{
|
||||
return e->target;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_event_get_current_target(lv_event_t * e)
|
||||
{
|
||||
return e->current_target;
|
||||
}
|
||||
|
||||
lv_event_code_t lv_event_get_code(lv_event_t * e)
|
||||
{
|
||||
return e->code;
|
||||
}
|
||||
|
||||
void * lv_event_get_param(lv_event_t * e)
|
||||
{
|
||||
return e->param;
|
||||
}
|
||||
|
||||
void * lv_event_get_user_data(lv_event_t * e)
|
||||
{
|
||||
return e->user_data;
|
||||
}
|
||||
|
||||
|
||||
uint32_t lv_event_register_id(void)
|
||||
{
|
||||
static uint32_t last_id = _LV_EVENT_LAST;
|
||||
last_id ++;
|
||||
return last_id;
|
||||
}
|
||||
|
||||
void _lv_event_mark_deleted(lv_obj_t * obj)
|
||||
{
|
||||
lv_event_t * e = event_head;
|
||||
|
||||
while(e) {
|
||||
if(e->current_target == obj || e->target == obj) e->deleted = 1;
|
||||
e = e->prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
|
||||
void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
obj->spec_attr->event_dsc_cnt++;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter;
|
||||
obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data;
|
||||
|
||||
return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1];
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(event_cb == NULL || obj->spec_attr->event_dsc[i].cb == event_cb) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_event_cb_with_user_data(lv_obj_t * obj, lv_event_cb_t event_cb, const void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if((event_cb == NULL || obj->spec_attr->event_dsc[i].cb) &&
|
||||
obj->spec_attr->event_dsc[i].user_data == user_data) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool lv_obj_remove_event_dsc(lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return false;
|
||||
|
||||
int32_t i = 0;
|
||||
for(i = 0; i < obj->spec_attr->event_dsc_cnt; i++) {
|
||||
if(&obj->spec_attr->event_dsc[i] == event_dsc) {
|
||||
/*Shift the remaining event handlers forward*/
|
||||
for(; i < (obj->spec_attr->event_dsc_cnt - 1); i++) {
|
||||
obj->spec_attr->event_dsc[i] = obj->spec_attr->event_dsc[i + 1];
|
||||
}
|
||||
obj->spec_attr->event_dsc_cnt--;
|
||||
obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
|
||||
obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*No event handler found*/
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_indev_t * lv_event_get_indev(lv_event_t * e)
|
||||
{
|
||||
|
||||
if(e->code == LV_EVENT_PRESSED ||
|
||||
e->code == LV_EVENT_PRESSING ||
|
||||
e->code == LV_EVENT_PRESS_LOST ||
|
||||
e->code == LV_EVENT_SHORT_CLICKED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED ||
|
||||
e->code == LV_EVENT_LONG_PRESSED_REPEAT ||
|
||||
e->code == LV_EVENT_CLICKED ||
|
||||
e->code == LV_EVENT_RELEASED ||
|
||||
e->code == LV_EVENT_SCROLL_BEGIN ||
|
||||
e->code == LV_EVENT_SCROLL_END ||
|
||||
e->code == LV_EVENT_SCROLL ||
|
||||
e->code == LV_EVENT_GESTURE ||
|
||||
e->code == LV_EVENT_KEY ||
|
||||
e->code == LV_EVENT_FOCUSED ||
|
||||
e->code == LV_EVENT_DEFOCUSED ||
|
||||
e->code == LV_EVENT_LEAVE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_PART_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_PART_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_clip_area(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_DRAW_MAIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_MAIN_END ||
|
||||
e->code == LV_EVENT_DRAW_POST ||
|
||||
e->code == LV_EVENT_DRAW_POST_BEGIN ||
|
||||
e->code == LV_EVENT_DRAW_POST_END) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_old_size(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SIZE_CHANGED) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_event_get_key(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_KEY) {
|
||||
uint32_t * k = lv_event_get_param(e);
|
||||
if(k) return *k;
|
||||
else return 0;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_SCROLL_BEGIN) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size)
|
||||
{
|
||||
if(e->code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t * cur_size = lv_event_get_param(e);
|
||||
*cur_size = LV_MAX(*cur_size, size);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
lv_point_t * lv_event_get_self_size_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_GET_SELF_SIZE) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_HIT_TEST) {
|
||||
return lv_event_get_param(e);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
return p->area;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res)
|
||||
{
|
||||
if(e->code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * p = lv_event_get_param(e);
|
||||
if(res > p->res) p->res = res; /*Save only "stronger" results*/
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Not interpreted with this event code");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_event_dsc_t * lv_obj_get_event_dsc(const lv_obj_t * obj, uint32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!obj->spec_attr) return NULL;
|
||||
if(id >= obj->spec_attr->event_dsc_cnt) return NULL;
|
||||
|
||||
return &obj->spec_attr->event_dsc[id];
|
||||
}
|
||||
|
||||
static lv_res_t event_send_core(lv_event_t * e)
|
||||
{
|
||||
EVENT_TRACE("Sending event %d to %p with %p param", e->code, (void *)e->current_target, e->param);
|
||||
|
||||
/*Call the input device's feedback callback if set*/
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
if(indev_act) {
|
||||
if(indev_act->driver->feedback_cb) indev_act->driver->feedback_cb(indev_act->driver, e->code);
|
||||
}
|
||||
|
||||
lv_event_dsc_t * event_dsc = lv_obj_get_event_dsc(e->current_target, 0);
|
||||
lv_res_t res = LV_RES_OK;
|
||||
res = lv_obj_event_base(NULL, e);
|
||||
|
||||
uint32_t i = 0;
|
||||
while(event_dsc && res == LV_RES_OK) {
|
||||
if(event_dsc->cb && (event_dsc->filter == LV_EVENT_ALL || event_dsc->filter == e->code)) {
|
||||
e->user_data = event_dsc->user_data;
|
||||
event_dsc->cb(e);
|
||||
|
||||
/*Stop if the object is deleted*/
|
||||
if(e->deleted) return LV_RES_INV;
|
||||
}
|
||||
|
||||
i++;
|
||||
event_dsc = lv_obj_get_event_dsc(e->current_target, i);
|
||||
}
|
||||
|
||||
if(res == LV_RES_OK && e->current_target->parent && event_is_bubbled(e))
|
||||
{
|
||||
e->current_target = e->current_target->parent;
|
||||
res = event_send_core(e);
|
||||
if(res != LV_RES_OK) return LV_RES_INV;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool event_is_bubbled(lv_event_t * e)
|
||||
{
|
||||
/*Event codes that always bubble*/
|
||||
switch(e->code) {
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*Check other codes only if bubbling is enabled*/
|
||||
if(lv_obj_has_flag(e->current_target, LV_OBJ_FLAG_EVENT_BUBBLE) == false) return false;
|
||||
|
||||
switch(e->code) {
|
||||
case LV_EVENT_HIT_TEST:
|
||||
case LV_EVENT_COVER_CHECK:
|
||||
case LV_EVENT_REFR_EXT_DRAW_SIZE:
|
||||
case LV_EVENT_DRAW_MAIN_BEGIN:
|
||||
case LV_EVENT_DRAW_MAIN:
|
||||
case LV_EVENT_DRAW_MAIN_END:
|
||||
case LV_EVENT_DRAW_POST_BEGIN:
|
||||
case LV_EVENT_DRAW_POST:
|
||||
case LV_EVENT_DRAW_POST_END:
|
||||
case LV_EVENT_DRAW_PART_BEGIN:
|
||||
case LV_EVENT_DRAW_PART_END:
|
||||
case LV_EVENT_REFRESH:
|
||||
case LV_EVENT_DELETE:
|
||||
case LV_EVENT_CHILD_CREATED:
|
||||
case LV_EVENT_CHILD_DELETED:
|
||||
case LV_EVENT_CHILD_CHANGED:
|
||||
case LV_EVENT_SIZE_CHANGED:
|
||||
case LV_EVENT_STYLE_CHANGED:
|
||||
case LV_EVENT_GET_SELF_SIZE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
335
EC600U_lvgl_lib/lvgl/src/core/lv_event.h
Normal file
335
EC600U_lvgl_lib/lvgl/src/core/lv_event.h
Normal file
@ -0,0 +1,335 @@
|
||||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EVENT_H
|
||||
#define LV_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_event_dsc_t;
|
||||
|
||||
/**
|
||||
* Type of event being sent to the object.
|
||||
*/
|
||||
typedef enum {
|
||||
LV_EVENT_ALL = 0,
|
||||
|
||||
/** Input device events*/
|
||||
LV_EVENT_PRESSED, /**< The object has been pressed*/
|
||||
LV_EVENT_PRESSING, /**< The object is being pressed (called continuously while pressing)*/
|
||||
LV_EVENT_PRESS_LOST, /**< The object is still being pressed but slid cursor/finger off of the object */
|
||||
LV_EVENT_SHORT_CLICKED, /**< The object was pressed for a short period of time, then released it. Not called if scrolled.*/
|
||||
LV_EVENT_LONG_PRESSED, /**< Object has been pressed for at least `long_press_time`. Not called if scrolled.*/
|
||||
LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `long_press_time` in every `long_press_repeat_time` ms. Not called if scrolled.*/
|
||||
LV_EVENT_CLICKED, /**< Called on release if not scrolled (regardless to long press)*/
|
||||
LV_EVENT_RELEASED, /**< Called in every cases when the object has been released*/
|
||||
LV_EVENT_SCROLL_BEGIN, /**< Scrolling begins*/
|
||||
LV_EVENT_SCROLL_END, /**< Scrolling ends*/
|
||||
LV_EVENT_SCROLL, /**< Scrolling*/
|
||||
LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_get_act());` */
|
||||
LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_get_act());`*/
|
||||
LV_EVENT_FOCUSED, /**< The object is focused*/
|
||||
LV_EVENT_DEFOCUSED, /**< The object is defocused*/
|
||||
LV_EVENT_LEAVE, /**< The object is defocused but still selected*/
|
||||
LV_EVENT_HIT_TEST, /**< Perform advanced hit-testing*/
|
||||
|
||||
/** Drawing events*/
|
||||
LV_EVENT_COVER_CHECK, /**< Check if the object fully covers an area. The event parameter is `lv_cover_check_info_t *`.*/
|
||||
LV_EVENT_REFR_EXT_DRAW_SIZE, /**< Get the required extra draw area around the object (e.g. for shadow). The event parameter is `lv_coord_t *` to store the size.*/
|
||||
LV_EVENT_DRAW_MAIN_BEGIN, /**< Starting the main drawing phase*/
|
||||
LV_EVENT_DRAW_MAIN, /**< Perform the main drawing*/
|
||||
LV_EVENT_DRAW_MAIN_END, /**< Finishing the main drawing phase*/
|
||||
LV_EVENT_DRAW_POST_BEGIN, /**< Starting the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_POST, /**< Perform the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_POST_END, /**< Finishing the post draw phase (when all children are drawn)*/
|
||||
LV_EVENT_DRAW_PART_BEGIN, /**< Starting to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
|
||||
LV_EVENT_DRAW_PART_END, /**< Finishing to draw a part. The event parameter is `lv_obj_draw_dsc_t *`. */
|
||||
|
||||
/** Special events*/
|
||||
LV_EVENT_VALUE_CHANGED, /**< The object's value has changed (i.e. slider moved)*/
|
||||
LV_EVENT_INSERT, /**< A text is inserted to the object. The event data is `char *` being inserted.*/
|
||||
LV_EVENT_REFRESH, /**< Notify the object to refresh something on it (for the user)*/
|
||||
LV_EVENT_READY, /**< A process has finished*/
|
||||
LV_EVENT_CANCEL, /**< A process has been cancelled */
|
||||
|
||||
/** Other events*/
|
||||
LV_EVENT_DELETE, /**< Object is being deleted*/
|
||||
LV_EVENT_CHILD_CHANGED, /**< Child was removed, added, or its size, position were changed */
|
||||
LV_EVENT_CHILD_CREATED, /**< Child was created, always bubbles up to all parents*/
|
||||
LV_EVENT_CHILD_DELETED, /**< Child was deleted, always bubbles up to all parents*/
|
||||
LV_EVENT_SCREEN_LOADED, /**< A screen was loaded*/
|
||||
LV_EVENT_SCREEN_UNLOADED, /**< A screen was unloaded*/
|
||||
|
||||
LV_EVENT_SIZE_CHANGED, /**< Object coordinates/size have changed*/
|
||||
LV_EVENT_STYLE_CHANGED, /**< Object's style has changed*/
|
||||
LV_EVENT_LAYOUT_CHANGED, /**< The children position has changed due to a layout recalculation*/
|
||||
LV_EVENT_GET_SELF_SIZE, /**< Get the internal size of a widget*/
|
||||
|
||||
_LV_EVENT_LAST /** Number of default events*/
|
||||
} lv_event_code_t;
|
||||
|
||||
typedef struct _lv_event_t {
|
||||
struct _lv_obj_t * target;
|
||||
struct _lv_obj_t * current_target;
|
||||
lv_event_code_t code;
|
||||
void * user_data;
|
||||
void * param;
|
||||
struct _lv_event_t * prev;
|
||||
uint8_t deleted : 1;
|
||||
} lv_event_t;
|
||||
|
||||
/**
|
||||
* @brief Event callback.
|
||||
* Events are used to notify the user of some action being taken on the object.
|
||||
* For details, see ::lv_event_t.
|
||||
*/
|
||||
typedef void (*lv_event_cb_t)(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Used as the event parameter of ::LV_EVENT_HIT_TEST to check if an `point` can click the object or not.
|
||||
* `res` should be set like this:
|
||||
* - If already set to `false` an other event wants that point non clickable. If you want to respect it leave it as `false` or set `true` to overwrite it.
|
||||
* - If already set `true` and `point` shouldn't be clickable set to `false`
|
||||
* - If already set to `true` you agree that `point` can click the object leave it as `true`
|
||||
*/
|
||||
typedef struct {
|
||||
const lv_point_t * point; /**< A point relative to screen to check if it can click the object or not*/
|
||||
bool res; /**< true: `point` can click the object; false: it cannot*/
|
||||
} lv_hit_test_info_t;
|
||||
|
||||
/**
|
||||
* Used as the event parameter of ::LV_EVENT_COVER_CHECK to check if an area is covered by the object or not.
|
||||
* In the event use `const lv_area_t * area = lv_event_get_cover_area(e)` to get the area to check
|
||||
* and `lv_event_set_cover_res(e, res)` to set the result.
|
||||
*/
|
||||
typedef struct {
|
||||
lv_cover_res_t res;
|
||||
const lv_area_t * area;
|
||||
} lv_cover_check_info_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Send an event to the object
|
||||
* @param obj pointer to an object
|
||||
* @param event_code the type of the event from `lv_event_t`
|
||||
* @param param arbitrary data depending on the widget type and the event. (Usually `NULL`)
|
||||
* @return LV_RES_OK: `obj` was not deleted in the event; LV_RES_INV: `obj` was deleted in the event_code
|
||||
*/
|
||||
lv_res_t lv_event_send(struct _lv_obj_t * obj, lv_event_code_t event_code, void * param);
|
||||
|
||||
/**
|
||||
* Used by the widgets internally to call the ancestor widget types's event handler
|
||||
* @param class_p pointer to the class of the widget (NOT the ancestor class)
|
||||
* @param e pointer to the event descriptor
|
||||
* @return LV_RES_OK: the taget object was not deleted in the event; LV_RES_INV: it was deleted in the event_code
|
||||
*/
|
||||
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the object originally targeted by the event. It's the same even if the event is bubbled.
|
||||
* @param e pointer to the event descriptor
|
||||
* @return the target of the event_code
|
||||
*/
|
||||
struct _lv_obj_t * lv_event_get_target(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the current target of the event. It's the object which event handler being called.
|
||||
* If the event is not bubbled it's the same as "normal" target.
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the current target of the event_code
|
||||
*/
|
||||
struct _lv_obj_t * lv_event_get_current_target(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the event code of an event
|
||||
* @param e pointer to the event descriptor
|
||||
* @return the event code. (E.g. `LV_EVENT_CLICKED`, `LV_EVENT_FOCUSED`, etc)
|
||||
*/
|
||||
lv_event_code_t lv_event_get_code(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the parameter passed when the event was sent
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the parameter
|
||||
*/
|
||||
void * lv_event_get_param(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the user_data passed when the event was registered on the object
|
||||
* @param e pointer to the event descriptor
|
||||
* @return pointer to the user_data
|
||||
*/
|
||||
void * lv_event_get_user_data(lv_event_t * e);
|
||||
|
||||
|
||||
/**
|
||||
* Register a new, custom event ID.
|
||||
* It can be used the same way as e.g. `LV_EVENT_CLICKED` to send custom events
|
||||
* @return the new event id
|
||||
* @example
|
||||
* uint32_t LV_EVENT_MINE = 0;
|
||||
* ...
|
||||
* e = lv_event_register_id();
|
||||
* ...
|
||||
* lv_event_send(obj, LV_EVENT_MINE, &some_data);
|
||||
*/
|
||||
uint32_t lv_event_register_id(void);
|
||||
|
||||
/**
|
||||
* Nested events can be called and one of them might belong to an object that is being deleted.
|
||||
* Mark this object's `event_temp_data` deleted to know that its `lv_event_send` should return `LV_RES_INV`
|
||||
* @param obj pointer to an object to mark as deleted
|
||||
*/
|
||||
void _lv_event_mark_deleted(struct _lv_obj_t * obj);
|
||||
|
||||
|
||||
/**
|
||||
* Add an event handler function for an object.
|
||||
* Used by the user to react on event which happens with the object.
|
||||
* An object can have multiple event handler. They will be called in the same order as they were added.
|
||||
* @param obj pointer to an object
|
||||
* @param filter and event code (e.g. `LV_EVENT_CLICKED`) on which the event should be called. `LV_EVENT_ALL` can be sued the receive all the events.
|
||||
* @param event_cb the new event function
|
||||
* @param user_data custom data data will be available in `event_cb`
|
||||
* @return a pointer the event descriptor. Can be used in ::lv_obj_remove_event_dsc
|
||||
*/
|
||||
struct _lv_event_dsc_t * lv_obj_add_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* Remove an event handler function for an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_cb the event function to remove, or `NULL` to remove the the firstly added event callback
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_cb(struct _lv_obj_t * obj, lv_event_cb_t event_cb);
|
||||
|
||||
/**
|
||||
* Remove an event handler function with a specific user_data from an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_cb the event function to remove, or `NULL` only `user_data` matters.
|
||||
* @param event_user_data the user_data specified in ::lv_obj_add_event_cb
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_cb_with_user_data(struct _lv_obj_t * obj, lv_event_cb_t event_cb,
|
||||
const void * event_user_data);
|
||||
|
||||
/**
|
||||
* DEPRACTED because doesn't work if multiple event handlers are added to an object.
|
||||
* Remove an event handler function for an object.
|
||||
* @param obj pointer to an object
|
||||
* @param event_dsc pointer to an event descriptor to remove (returned by ::lv_obj_add_event_cb)
|
||||
* @return true if any event handlers were removed
|
||||
*/
|
||||
bool lv_obj_remove_event_dsc(struct _lv_obj_t * obj, struct _lv_event_dsc_t * event_dsc);
|
||||
|
||||
/**
|
||||
* Get the input device passed as parameter to indev related events.
|
||||
* @param e pointer to an event
|
||||
* @return the indev that triggered the event or NULL if called on a not indev related event
|
||||
*/
|
||||
lv_indev_t * lv_event_get_indev(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the part draw descriptor passed as parameter to `LV_EVENT_DRAW_PART_BEGIN/END`.
|
||||
* @param e pointer to an event
|
||||
* @return the part draw descriptor to hook the drawing or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_obj_draw_part_dsc_t * lv_event_get_draw_part_dsc(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the clip area passed as parameter to draw events events.
|
||||
* Namely: `LV_EVENT_DRAW_MAIN/POST`, `LV_EVENT_DRAW_MAIN/POST_BEGIN`, `LV_EVENT_DRAW_MAIN/POST_END`
|
||||
* @param e pointer to an event
|
||||
* @return the clip area to use during drawing or NULL if called on an unrelated event
|
||||
*/
|
||||
const lv_area_t * lv_event_get_clip_area(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the old area of the object before its size was changed. Can be used in `LV_EVENT_SIZE_CHANGED`
|
||||
* @param e pointer to an event
|
||||
* @return the old absolute area of the object or NULL if called on an unrelated event
|
||||
*/
|
||||
const lv_area_t * lv_event_get_old_size(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the key passed as parameter to an event. Can be used in `LV_EVENT_KEY`
|
||||
* @param e pointer to an event
|
||||
* @return the triggering key or NULL if called on an unrelated event
|
||||
*/
|
||||
uint32_t lv_event_get_key(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN`
|
||||
* @param e pointer to an event
|
||||
* @return the animation that will scroll the object. (can be modified as required)
|
||||
*/
|
||||
lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the new extra draw size. Can be used in `LV_EVENT_REFR_EXT_DRAW_SIZE`
|
||||
* @param e pointer to an event
|
||||
* @param size The new extra draw size
|
||||
*/
|
||||
void lv_event_set_ext_draw_size(lv_event_t * e, lv_coord_t size);
|
||||
|
||||
/**
|
||||
* Get a pointer to an `lv_point_t` variable in which the self size should be saved (width in `point->x` and height `point->y`).
|
||||
* Can be used in `LV_EVENT_GET_SELF_SIZE`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to `lv_point_t` or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_point_t * lv_event_get_self_size_info(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get a pointer to an `lv_hit_test_info_t` variable in which the hit test result should be saved. Can be used in `LV_EVENT_HIT_TEST`
|
||||
* @param e pointer to an event
|
||||
* @return pointer to `lv_hit_test_info_t` or NULL if called on an unrelated event
|
||||
*/
|
||||
lv_hit_test_info_t * lv_event_get_hit_test_info(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Get a pointer to an area which should be examined whether the object fully covers it or not.
|
||||
* Can be used in `LV_EVENT_HIT_TEST`
|
||||
* @param e pointer to an event
|
||||
* @return an area with absolute coordinates to check
|
||||
*/
|
||||
const lv_area_t * lv_event_get_cover_area(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Set the result of cover checking. Can be used in `LV_EVENT_COVER_CHECK`
|
||||
* @param e pointer to an event
|
||||
* @param res an element of ::lv_cover_check_info_t
|
||||
*/
|
||||
void lv_event_set_cover_res(lv_event_t * e, lv_cover_res_t res);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EVENT_H*/
|
459
EC600U_lvgl_lib/lvgl/src/core/lv_group.c
Normal file
459
EC600U_lvgl_lib/lvgl/src/core/lv_group.c
Normal file
@ -0,0 +1,459 @@
|
||||
/**
|
||||
* @file lv_group.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lv_group.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../core/lv_obj.h"
|
||||
#include "../core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *));
|
||||
static void lv_group_refocus(lv_group_t * g);
|
||||
static lv_indev_t * get_indev(const lv_group_t * g);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_group_t * default_group;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_group_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t));
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = _lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll));
|
||||
LV_ASSERT_MALLOC(group);
|
||||
if(group == NULL) return NULL;
|
||||
_lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *));
|
||||
|
||||
group->obj_focus = NULL;
|
||||
group->frozen = 0;
|
||||
group->focus_cb = NULL;
|
||||
group->editing = 0;
|
||||
group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV;
|
||||
group->wrap = 1;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
group->user_data = NULL;
|
||||
#endif
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void lv_group_del(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
_LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
_lv_ll_clear(&(group->obj_ll));
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group);
|
||||
lv_mem_free(group);
|
||||
}
|
||||
|
||||
void lv_group_set_default(lv_group_t * group)
|
||||
{
|
||||
default_group = group;
|
||||
}
|
||||
|
||||
lv_group_t * lv_group_get_default(void)
|
||||
{
|
||||
return default_group;
|
||||
}
|
||||
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
_LV_LL_READ(&group->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj) {
|
||||
LV_LOG_INFO("the object is already added to this group");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*If the object is already in a group and focused then refocus it*/
|
||||
lv_group_t * group_cur = lv_obj_get_group(obj);
|
||||
if(group_cur) {
|
||||
if(obj->spec_attr->group_p && *(obj->spec_attr->group_p->obj_focus) == obj) {
|
||||
lv_group_refocus(group_cur);
|
||||
|
||||
LV_LOG_INFO("changing object's group");
|
||||
}
|
||||
}
|
||||
|
||||
if(obj->spec_attr == NULL) lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->group_p = group;
|
||||
|
||||
lv_obj_t ** next = _lv_ll_ins_tail(&group->obj_ll);
|
||||
LV_ASSERT_MALLOC(next);
|
||||
if(next == NULL) return;
|
||||
*next = obj;
|
||||
|
||||
/*If the head and the tail is equal then there is only one object in the linked list.
|
||||
*In this case automatically activate it*/
|
||||
if(_lv_ll_get_head(&group->obj_ll) == next) {
|
||||
lv_group_refocus(group);
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_swap_obj(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
lv_group_t * g1 = lv_obj_get_group(obj1);
|
||||
lv_group_t * g2 = lv_obj_get_group(obj2);
|
||||
if(g1 != g2) return;
|
||||
if(g1 == NULL) return;
|
||||
|
||||
/*Do not add the object twice*/
|
||||
lv_obj_t ** obj_i;
|
||||
_LV_LL_READ(&g1->obj_ll, obj_i) {
|
||||
if((*obj_i) == obj1)(*obj_i) = obj2;
|
||||
else if((*obj_i) == obj2)(*obj_i) = obj1;
|
||||
}
|
||||
|
||||
if(*g1->obj_focus == obj1) lv_group_focus_obj(obj2);
|
||||
else if(*g1->obj_focus == obj2) lv_group_focus_obj(obj1);
|
||||
|
||||
}
|
||||
|
||||
void lv_group_remove_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
LV_LOG_TRACE("begin");
|
||||
|
||||
/*Focus on the next object*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
if(g->frozen) g->frozen = 0;
|
||||
|
||||
/*If this is the only object in the group then focus to nothing.*/
|
||||
if(_lv_ll_get_head(&g->obj_ll) == g->obj_focus && _lv_ll_get_tail(&g->obj_ll) == g->obj_focus) {
|
||||
lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
}
|
||||
/*If there more objects in the group then focus to the next/prev object*/
|
||||
else {
|
||||
lv_group_refocus(g);
|
||||
}
|
||||
}
|
||||
|
||||
/*If the focuses object is still the same then it was the only object in the group but it will
|
||||
*be deleted. Set the `obj_focus` to NULL to get back to the initial state of the group with
|
||||
*zero objects*/
|
||||
if(g->obj_focus && *g->obj_focus == obj) {
|
||||
g->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Search the object and remove it from its group*/
|
||||
lv_obj_t ** i;
|
||||
_LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
_lv_ll_remove(&g->obj_ll, i);
|
||||
lv_mem_free(i);
|
||||
if(obj->spec_attr) obj->spec_attr->group_p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
void lv_group_remove_all_objs(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
group->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
_LV_LL_READ(&group->obj_ll, obj) {
|
||||
if((*obj)->spec_attr)(*obj)->spec_attr->group_p = NULL;
|
||||
}
|
||||
|
||||
_lv_ll_clear(&(group->obj_ll));
|
||||
}
|
||||
|
||||
void lv_group_focus_obj(lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return;
|
||||
lv_group_t * g = lv_obj_get_group(obj);
|
||||
if(g == NULL) return;
|
||||
|
||||
if(g->frozen != 0) return;
|
||||
|
||||
/*On defocus edit mode must be leaved*/
|
||||
lv_group_set_editing(g, false);
|
||||
|
||||
lv_obj_t ** i;
|
||||
_LV_LL_READ(&g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
if(g->obj_focus != NULL && obj != *g->obj_focus) { /*Do not defocus if the same object needs to be focused again*/
|
||||
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
|
||||
g->obj_focus = i;
|
||||
|
||||
if(g->obj_focus != NULL) {
|
||||
if(g->focus_cb) g->focus_cb(g);
|
||||
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_focus_next(lv_group_t * group)
|
||||
{
|
||||
focus_next_core(group, _lv_ll_get_head, _lv_ll_get_next);
|
||||
}
|
||||
|
||||
void lv_group_focus_prev(lv_group_t * group)
|
||||
{
|
||||
focus_next_core(group, _lv_ll_get_tail, _lv_ll_get_prev);
|
||||
}
|
||||
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en)
|
||||
{
|
||||
if(en == false) group->frozen = 0;
|
||||
else group->frozen = 1;
|
||||
}
|
||||
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
|
||||
{
|
||||
lv_obj_t * act = lv_group_get_focused(group);
|
||||
if(act == NULL) return LV_RES_OK;
|
||||
return lv_event_send(act, LV_EVENT_KEY, &c);
|
||||
}
|
||||
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
|
||||
{
|
||||
group->focus_cb = focus_cb;
|
||||
}
|
||||
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
uint8_t en_val = edit ? 1 : 0;
|
||||
|
||||
if(en_val == group->editing) return; /*Do not set the same mode again*/
|
||||
|
||||
group->editing = en_val;
|
||||
lv_obj_t * focused = lv_group_get_focused(group);
|
||||
|
||||
if(focused) {
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_invalidate(focused);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)
|
||||
{
|
||||
group->refocus_policy = policy & 0x01;
|
||||
}
|
||||
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en)
|
||||
{
|
||||
group->wrap = en ? 1 : 0;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
if(group->obj_focus == NULL) return NULL;
|
||||
|
||||
return *group->obj_focus;
|
||||
}
|
||||
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
return group->focus_cb;
|
||||
}
|
||||
|
||||
bool lv_group_get_editing(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->editing ? true : false;
|
||||
}
|
||||
|
||||
bool lv_group_get_wrap(lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->wrap ? true : false;
|
||||
}
|
||||
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group)
|
||||
{
|
||||
return _lv_ll_get_len(&group->obj_ll);
|
||||
}
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_group_refocus(lv_group_t * g)
|
||||
{
|
||||
/*Refocus must temporarily allow wrapping to work correctly*/
|
||||
uint8_t temp_wrap = g->wrap;
|
||||
g->wrap = 1;
|
||||
|
||||
if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_NEXT)
|
||||
lv_group_focus_next(g);
|
||||
else if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_PREV)
|
||||
lv_group_focus_prev(g);
|
||||
/*Restore wrap property*/
|
||||
g->wrap = temp_wrap;
|
||||
}
|
||||
|
||||
static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
|
||||
void * (*move)(const lv_ll_t *, const void *))
|
||||
{
|
||||
if(group->frozen) return;
|
||||
|
||||
lv_obj_t ** obj_next = group->obj_focus;
|
||||
lv_obj_t ** obj_sentinel = NULL;
|
||||
bool can_move = true;
|
||||
bool can_begin = true;
|
||||
|
||||
for(;;) {
|
||||
if(obj_next == NULL) {
|
||||
if(group->wrap || obj_sentinel == NULL) {
|
||||
if(!can_begin) return;
|
||||
obj_next = begin(&group->obj_ll);
|
||||
can_move = false;
|
||||
can_begin = false;
|
||||
}
|
||||
else {
|
||||
/*Currently focused object is the last/first in the group, keep it that way*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(obj_sentinel == NULL) {
|
||||
obj_sentinel = obj_next;
|
||||
if(obj_sentinel == NULL) return; /*Group is empty*/
|
||||
}
|
||||
|
||||
if(can_move) {
|
||||
obj_next = move(&group->obj_ll, obj_next);
|
||||
|
||||
/*Give up if we walked the entire list and haven't found another visible object*/
|
||||
if(obj_next == obj_sentinel) return;
|
||||
}
|
||||
|
||||
can_move = true;
|
||||
|
||||
if(obj_next == NULL) continue;
|
||||
if(lv_obj_get_state(*obj_next) & LV_STATE_DISABLED) continue;
|
||||
|
||||
/*Hidden objects don't receive focus.
|
||||
*If any parent is hidden, the object is also hidden)*/
|
||||
lv_obj_t * parent = *obj_next;
|
||||
while(parent) {
|
||||
if(lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) break;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
|
||||
if(parent && lv_obj_has_flag(parent, LV_OBJ_FLAG_HIDDEN)) continue;
|
||||
|
||||
/*If we got her a good candidate is found*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(obj_next == group->obj_focus) return; /*There's only one visible object and it's already focused*/
|
||||
|
||||
if(group->obj_focus) {
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
|
||||
if(res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an indev preferably with KEYPAD or ENCOEDR type that uses the given group.
|
||||
* In other words, find an indev, that is related to the given group.
|
||||
* In the worst case simply return the latest indev
|
||||
* @param g a group the find in the indevs
|
||||
* @return the suggested indev
|
||||
*/
|
||||
static lv_indev_t * get_indev(const lv_group_t * g)
|
||||
{
|
||||
lv_indev_t * indev_encoder = NULL;
|
||||
lv_indev_t * indev_group = NULL;
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev->group == g) {
|
||||
/*Prefer KEYPAD*/
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD) return indev;
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) indev_encoder = indev;
|
||||
indev_group = indev;
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
if(indev_encoder) return indev_encoder;
|
||||
if(indev_group) return indev_group;
|
||||
|
||||
/*In lack of a better option use the first input device. (It can be NULL if there is no input device)*/
|
||||
return lv_indev_get_next(NULL);
|
||||
}
|
||||
|
246
EC600U_lvgl_lib/lvgl/src/core/lv_group.h
Normal file
246
EC600U_lvgl_lib/lvgl/src/core/lv_group.h
Normal file
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* @file lv_group.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_H
|
||||
#define LV_GROUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Predefined keys to control the focused object via lv_group_send(group, c)*/
|
||||
|
||||
enum {
|
||||
LV_KEY_UP = 17, /*0x11*/
|
||||
LV_KEY_DOWN = 18, /*0x12*/
|
||||
LV_KEY_RIGHT = 19, /*0x13*/
|
||||
LV_KEY_LEFT = 20, /*0x14*/
|
||||
LV_KEY_ESC = 27, /*0x1B*/
|
||||
LV_KEY_DEL = 127, /*0x7F*/
|
||||
LV_KEY_BACKSPACE = 8, /*0x08*/
|
||||
LV_KEY_ENTER = 10, /*0x0A, '\n'*/
|
||||
LV_KEY_NEXT = 9, /*0x09, '\t'*/
|
||||
LV_KEY_PREV = 11, /*0x0B, '*/
|
||||
LV_KEY_HOME = 2, /*0x02, STX*/
|
||||
LV_KEY_END = 3, /*0x03, ETX*/
|
||||
};
|
||||
typedef uint8_t lv_key_t;
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_group_t;
|
||||
|
||||
typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *);
|
||||
|
||||
/**
|
||||
* Groups can be used to logically hold objects so that they can be individually focused.
|
||||
* They are NOT for laying out objects on a screen (try layouts for that).
|
||||
*/
|
||||
typedef struct _lv_group_t {
|
||||
lv_ll_t obj_ll; /**< Linked list to store the objects in the group*/
|
||||
struct _lv_obj_t ** obj_focus; /**< The object in focus*/
|
||||
|
||||
lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
|
||||
uint8_t frozen : 1; /**< 1: can't focus to new object*/
|
||||
uint8_t editing : 1; /**< 1: Edit mode, 0: Navigate mode*/
|
||||
uint8_t refocus_policy : 1; /**< 1: Focus prev if focused on deletion. 0: Focus next if focused on
|
||||
deletion.*/
|
||||
uint8_t wrap : 1; /**< 1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end
|
||||
of list.*/
|
||||
} lv_group_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
LV_GROUP_REFOCUS_POLICY_NEXT = 0,
|
||||
LV_GROUP_REFOCUS_POLICY_PREV = 1
|
||||
} lv_group_refocus_policy_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init. the group module
|
||||
* @remarks Internal function, do not call directly.
|
||||
*/
|
||||
void _lv_group_init(void);
|
||||
|
||||
/**
|
||||
* Create a new object group
|
||||
* @return pointer to the new object group
|
||||
*/
|
||||
lv_group_t * lv_group_create(void);
|
||||
|
||||
/**
|
||||
* Delete a group object
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_del(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Set a default group. New object are added to this group if it's enabled in their class with `add_to_def_group = true`
|
||||
* @param group pointer to a group (can be `NULL`)
|
||||
*/
|
||||
void lv_group_set_default(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the default group
|
||||
* @return pointer to the default group
|
||||
*/
|
||||
lv_group_t * lv_group_get_default(void);
|
||||
|
||||
/**
|
||||
* Add an object to a group
|
||||
* @param group pointer to a group
|
||||
* @param obj pointer to an object to add
|
||||
*/
|
||||
void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Swap 2 object in a group. The object must be in the same group
|
||||
* @param obj1 pointer to an object
|
||||
* @param obj2 pointer to an other object
|
||||
*/
|
||||
void lv_group_swap_obj(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2);
|
||||
|
||||
/**
|
||||
* Remove an object from its group
|
||||
* @param obj pointer to an object to remove
|
||||
*/
|
||||
void lv_group_remove_obj(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Remove all objects from a group
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_remove_all_objs(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Focus on an object (defocus the current)
|
||||
* @param obj pointer to an object to focus on
|
||||
*/
|
||||
void lv_group_focus_obj(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Focus the next object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_next(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Focus the previous object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_prev(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Do not let to change the focus from the current object
|
||||
* @param group pointer to a group
|
||||
* @param en true: freeze, false: release freezing (normal mode)
|
||||
*/
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Send a control character to the focuses object of a group
|
||||
* @param group pointer to a group
|
||||
* @param c a character (use LV_KEY_.. to navigate)
|
||||
* @return result of focused object in group.
|
||||
*/
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c);
|
||||
|
||||
/**
|
||||
* Set a function for a group which will be called when a new object is focused
|
||||
* @param group pointer to a group
|
||||
* @param focus_cb the call back function or NULL if unused
|
||||
*/
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb);
|
||||
|
||||
/**
|
||||
* Set whether the next or previous item in a group is focused if the currently focused obj is
|
||||
* deleted.
|
||||
* @param group pointer to a group
|
||||
* @param policy new refocus policy enum
|
||||
*/
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy);
|
||||
|
||||
/**
|
||||
* Manually set the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @param edit true: edit mode; false: navigate mode
|
||||
*/
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit);
|
||||
|
||||
/**
|
||||
* Set whether focus next/prev will allow wrapping from first->last or last->first object.
|
||||
* @param group pointer to group
|
||||
* @param en true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Get the focused object or NULL if there isn't one
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the focused object
|
||||
*/
|
||||
struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the focus callback function of a group
|
||||
* @param group pointer to a group
|
||||
* @return the call back function or NULL if not set
|
||||
*/
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @return true: edit mode; false: navigate mode
|
||||
*/
|
||||
bool lv_group_get_editing(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get whether focus next/prev will allow wrapping from first->last or last->first object.
|
||||
* @param group pointer to group
|
||||
* @param en true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
bool lv_group_get_wrap(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the number of object in the group
|
||||
* @param group pointer to a group
|
||||
* @return number of objects in the group
|
||||
*/
|
||||
uint32_t lv_group_get_obj_count(lv_group_t * group);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GROUP_H*/
|
1123
EC600U_lvgl_lib/lvgl/src/core/lv_indev.c
Normal file
1123
EC600U_lvgl_lib/lvgl/src/core/lv_indev.c
Normal file
File diff suppressed because it is too large
Load Diff
172
EC600U_lvgl_lib/lvgl/src/core/lv_indev.h
Normal file
172
EC600U_lvgl_lib/lvgl/src/core/lv_indev.h
Normal file
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @file lv_indev.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_INDEV_H
|
||||
#define LV_INDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../hal/lv_hal_indev.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Called periodically to read the input devices
|
||||
* @param param pointer to and input device to read
|
||||
*/
|
||||
void lv_indev_read_timer_cb(lv_timer_t * timer);
|
||||
|
||||
|
||||
void lv_indev_enable(lv_indev_t * indev, bool en);
|
||||
|
||||
/**
|
||||
* Get the currently processed input device. Can be used in action functions too.
|
||||
* @return pointer to the currently processed input device or NULL if no input device processing
|
||||
* right now
|
||||
*/
|
||||
lv_indev_t * lv_indev_get_act(void);
|
||||
|
||||
/**
|
||||
* Get the type of an input device
|
||||
* @param indev pointer to an input device
|
||||
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
|
||||
*/
|
||||
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Reset one or all input devices
|
||||
* @param indev pointer to an input device to reset or NULL to reset all of them
|
||||
* @param obj pointer to an object which triggers the reset.
|
||||
*/
|
||||
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Reset the long press state of an input device
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_reset_long_press(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param cur_obj pointer to an object to be used as cursor
|
||||
*/
|
||||
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj);
|
||||
|
||||
/**
|
||||
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
|
||||
* These points will be assigned to the buttons to press a specific point on the screen
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[]);
|
||||
|
||||
/**
|
||||
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the result
|
||||
*/
|
||||
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Get the current gesture direct
|
||||
* @param indev pointer to an input device
|
||||
* @return current gesture direct
|
||||
*/
|
||||
lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @return the last pressed key (0 on error)
|
||||
*/
|
||||
uint32_t lv_indev_get_key(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Check the current scroll direction of an input device (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return LV_DIR_NONE: no scrolling now
|
||||
* LV_DIR_HOR/VER
|
||||
*/
|
||||
lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the currently scrolled object (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return pointer to the currently scrolled object or NULL if no scrolling by this indev
|
||||
*/
|
||||
lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the movement vector of an input device (for LV_INDEV_TYPE_POINTER and
|
||||
* LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the types.pointer.vector
|
||||
*/
|
||||
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Do nothing until the next release
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_wait_release(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Gets a pointer to the currently active object in the currently processed input device.
|
||||
* @return pointer to currently active object or NULL if no active object
|
||||
*/
|
||||
lv_obj_t * lv_indev_get_obj_act(void);
|
||||
|
||||
/**
|
||||
* Get a pointer to the indev read timer to
|
||||
* modify its parameters with `lv_timer_...` functions.
|
||||
* @param indev pointer to an input device
|
||||
* @return pointer to the indev read refresher timer. (NULL on error)
|
||||
*/
|
||||
lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev);
|
||||
|
||||
/**
|
||||
* Search the most top, clickable object by a point
|
||||
* @param obj pointer to a start object, typically the screen
|
||||
* @param point pointer to a point for searching the most top child
|
||||
* @return pointer to the found object or NULL if there was no suitable object
|
||||
*/
|
||||
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_INDEV_H*/
|
647
EC600U_lvgl_lib/lvgl/src/core/lv_indev_scroll.c
Normal file
647
EC600U_lvgl_lib/lvgl/src/core/lv_indev_scroll.c
Normal file
@ -0,0 +1,647 @@
|
||||
/**
|
||||
* @file lv_indev_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_indev.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define ELASTIC_SLOWNESS_FACTOR 4 /*Scrolling on elastic parts are slower by this factor*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc);
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs);
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y);
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc);
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
/*If there is no scroll object yet try to find one*/
|
||||
if(scroll_obj == NULL) {
|
||||
proc->types.pointer.scroll_sum.x += proc->types.pointer.vect.x;
|
||||
proc->types.pointer.scroll_sum.y += proc->types.pointer.vect.y;
|
||||
|
||||
scroll_obj = find_scroll_obj(proc);
|
||||
if(scroll_obj == NULL) return;
|
||||
|
||||
init_scroll_limits(proc);
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_BEGIN, NULL);
|
||||
if(proc->reset_query) return;
|
||||
}
|
||||
|
||||
/*Set new position or scroll if the vector is not zero*/
|
||||
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
|
||||
lv_coord_t diff_x = 0;
|
||||
lv_coord_t diff_y = 0;
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
diff_x = elastic_diff(scroll_obj, proc->types.pointer.vect.x, sl, sr, LV_DIR_HOR);
|
||||
}
|
||||
else {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
diff_y = elastic_diff(scroll_obj, proc->types.pointer.vect.y, st, sb, LV_DIR_VER);
|
||||
}
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(scroll_obj);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
|
||||
|
||||
/*Respect the scroll limit area*/
|
||||
scroll_limit_diff(proc, &diff_x, &diff_y);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, diff_x, diff_y, LV_ANIM_OFF);
|
||||
proc->types.pointer.scroll_sum.x += diff_x;
|
||||
proc->types.pointer.scroll_sum.y += diff_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * scroll_obj = proc->types.pointer.scroll_obj;
|
||||
if(scroll_obj == NULL) return;
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_NONE) return;
|
||||
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_MOMENTUM) == false) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t align_x = lv_obj_get_scroll_snap_x(scroll_obj);
|
||||
lv_scroll_snap_t align_y = lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
if(proc->types.pointer.scroll_dir == LV_DIR_VER) {
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.y =
|
||||
proc->types.pointer.scroll_throw_vect.y * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.y = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.y, st, sb,
|
||||
LV_DIR_VER);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, 0, proc->types.pointer.scroll_throw_vect.y, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_y = scroll_throw_predict_y(proc);
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
scroll_limit_diff(proc, NULL, &diff_y);
|
||||
lv_coord_t y = find_snap_point_y(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_y);
|
||||
lv_obj_scroll_by(scroll_obj, 0, diff_y + y, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
else if(proc->types.pointer.scroll_dir == LV_DIR_HOR) {
|
||||
proc->types.pointer.scroll_throw_vect.y = 0;
|
||||
/*If no snapping "throw"*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
proc->types.pointer.scroll_throw_vect.x =
|
||||
proc->types.pointer.scroll_throw_vect.x * (100 - scroll_throw) / 100;
|
||||
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
|
||||
proc->types.pointer.scroll_throw_vect.x = elastic_diff(scroll_obj, proc->types.pointer.scroll_throw_vect.x, sl, sr,
|
||||
LV_DIR_HOR);
|
||||
|
||||
lv_obj_scroll_by(scroll_obj, proc->types.pointer.scroll_throw_vect.x, 0, LV_ANIM_OFF);
|
||||
}
|
||||
/*With snapping find the nearest snap point and scroll there*/
|
||||
else {
|
||||
lv_coord_t diff_x = scroll_throw_predict_x(proc);
|
||||
proc->types.pointer.scroll_throw_vect.x = 0;
|
||||
scroll_limit_diff(proc, &diff_x, NULL);
|
||||
lv_coord_t x = find_snap_point_x(scroll_obj, LV_COORD_MIN, LV_COORD_MAX, diff_x);
|
||||
lv_obj_scroll_by(scroll_obj, x + diff_x, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
|
||||
/*Check if the scroll has finished*/
|
||||
if(proc->types.pointer.scroll_throw_vect.x == 0 && proc->types.pointer.scroll_throw_vect.y == 0) {
|
||||
/*Revert if scrolled in*/
|
||||
/*If vertically scrollable and not controlled by snap*/
|
||||
if(align_y == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(scroll_obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(scroll_obj);
|
||||
if(st > 0 || sb > 0) {
|
||||
if(st < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, st, LV_ANIM_ON);
|
||||
}
|
||||
else if(sb < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, 0, -sb, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*If horizontally scrollable and not controlled by snap*/
|
||||
if(align_x == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(scroll_obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(scroll_obj);
|
||||
if(sl > 0 || sr > 0) {
|
||||
if(sl < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, sl, 0, LV_ANIM_ON);
|
||||
}
|
||||
else if(sr < 0) {
|
||||
lv_obj_scroll_by(scroll_obj, -sr, 0, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv_event_send(scroll_obj, LV_EVENT_SCROLL_END, indev_act);
|
||||
if(proc->reset_query) return;
|
||||
|
||||
proc->types.pointer.scroll_dir = LV_DIR_NONE;
|
||||
proc->types.pointer.scroll_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Predict where would a scroll throw end
|
||||
* @param indev pointer to an input device
|
||||
* @param dir `LV_DIR_VER` or `LV_DIR_HOR`
|
||||
* @return the difference compared to the current position when the throw would be finished
|
||||
*/
|
||||
lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir)
|
||||
{
|
||||
if(indev == NULL) return 0;
|
||||
lv_coord_t v;
|
||||
switch(dir) {
|
||||
case LV_DIR_VER:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.y;
|
||||
break;
|
||||
case LV_DIR_HOR:
|
||||
v = indev->proc.types.pointer.scroll_throw_vect_ori.x;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv_coord_t scroll_throw = indev->driver->scroll_throw;
|
||||
lv_coord_t sum = 0;
|
||||
while(v) {
|
||||
sum += v;
|
||||
v = v * (100 - scroll_throw) / 100;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p)
|
||||
{
|
||||
p->x = find_snap_point_x(obj, obj->coords.x1, obj->coords.x2, 0);
|
||||
p->y = find_snap_point_y(obj, obj->coords.y1, obj->coords.y2, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_obj_t * find_scroll_obj(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj_candidate = NULL;
|
||||
lv_dir_t dir_candidate = LV_DIR_NONE;
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_limit = indev_act->driver->scroll_limit;
|
||||
|
||||
/*Go until find a scrollable object in the current direction
|
||||
*More precisely:
|
||||
* 1. Check the pressed object and all of its ancestors and try to find an object which is scrollable
|
||||
* 2. Scrollable means it has some content out of its area
|
||||
* 3. If an object can be scrolled into the current direction then use it ("real match"")
|
||||
* 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect)
|
||||
* 5. Use the last candidate. Always the "deepest" parent or the object from point 3*/
|
||||
lv_obj_t * obj_act = proc->types.pointer.act_obj;
|
||||
while(obj_act) {
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLLABLE) == false) {
|
||||
/*If this object don't want to chain the scroll ot the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN) == false) break;
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Decide if it's a horizontal or vertical scroll*/
|
||||
bool hor_en = false;
|
||||
bool ver_en = false;
|
||||
if(LV_ABS(proc->types.pointer.scroll_sum.x) > LV_ABS(proc->types.pointer.scroll_sum.y)) {
|
||||
hor_en = true;
|
||||
}
|
||||
else {
|
||||
ver_en = true;
|
||||
}
|
||||
|
||||
/*Consider both up-down or left/right scrollable according to the current direction*/
|
||||
bool up_en = ver_en;
|
||||
bool down_en = ver_en;
|
||||
bool left_en = hor_en;
|
||||
bool right_en = hor_en;
|
||||
|
||||
/*The object might have disabled some directions.*/
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(obj_act);
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0) left_en = false;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0) right_en = false;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0) up_en = false;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0) down_en = false;
|
||||
|
||||
/*The object is scrollable to a direction if its content overflow in that direction.*/
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj_act);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj_act);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj_act);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj_act);
|
||||
|
||||
/*If this object is scrollable into the current scroll direction then save it as a candidate.
|
||||
*It's important only to be scrollable on the current axis (hor/ver) because if the scroll
|
||||
*is propagated to this object it can show at least elastic scroll effect.
|
||||
*But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate)*/
|
||||
if((st > 0 || sb > 0) &&
|
||||
((up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_VER;
|
||||
}
|
||||
|
||||
if((sl > 0 || sr > 0) &&
|
||||
((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit))) {
|
||||
obj_candidate = obj_act;
|
||||
dir_candidate = LV_DIR_HOR;
|
||||
}
|
||||
|
||||
if(st <= 0) up_en = false;
|
||||
if(sb <= 0) down_en = false;
|
||||
if(sl <= 0) left_en = false;
|
||||
if(sr <= 0) right_en = false;
|
||||
|
||||
/*If the object really can be scrolled into the current direction the use it.*/
|
||||
if((left_en && proc->types.pointer.scroll_sum.x >= scroll_limit) ||
|
||||
(right_en && proc->types.pointer.scroll_sum.x <= - scroll_limit) ||
|
||||
(up_en && proc->types.pointer.scroll_sum.y >= scroll_limit) ||
|
||||
(down_en && proc->types.pointer.scroll_sum.y <= - scroll_limit)) {
|
||||
proc->types.pointer.scroll_dir = hor_en ? LV_DIR_HOR : LV_DIR_VER;
|
||||
break;
|
||||
}
|
||||
|
||||
/*If this object don't want to chain the scroll ot the parent stop searching*/
|
||||
if(lv_obj_has_flag(obj_act, LV_OBJ_FLAG_SCROLL_CHAIN) == false) break;
|
||||
|
||||
/*Try the parent*/
|
||||
obj_act = lv_obj_get_parent(obj_act);
|
||||
}
|
||||
|
||||
/*Use the last candidate*/
|
||||
if(obj_candidate) {
|
||||
proc->types.pointer.scroll_dir = dir_candidate;
|
||||
proc->types.pointer.scroll_obj = obj_candidate;
|
||||
proc->types.pointer.scroll_sum.x = 0;
|
||||
proc->types.pointer.scroll_sum.y = 0;
|
||||
}
|
||||
|
||||
return obj_candidate;
|
||||
}
|
||||
|
||||
static void init_scroll_limits(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * obj = proc->types.pointer.scroll_obj;
|
||||
/*If there no STOP allow scrolling anywhere*/
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ONE) == false) {
|
||||
lv_area_set(&proc->types.pointer.scroll_area, LV_COORD_MIN, LV_COORD_MIN, LV_COORD_MAX, LV_COORD_MAX);
|
||||
}
|
||||
/*With STOP limit the scrolling to the perv and next snap point*/
|
||||
else {
|
||||
switch(lv_obj_get_scroll_snap_y(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t y_mid = obj->coords.y1 + lv_area_get_height(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, y_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, y_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(lv_obj_get_scroll_snap_x(obj)) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x1, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, obj->coords.x2, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, obj->coords.x2, 0);
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER: {
|
||||
lv_coord_t x_mid = obj->coords.x1 + lv_area_get_width(&obj->coords) / 2;
|
||||
proc->types.pointer.scroll_area.x1 = find_snap_point_x(obj, x_mid + 1, LV_COORD_MAX, 0);
|
||||
proc->types.pointer.scroll_area.x2 = find_snap_point_x(obj, LV_COORD_MIN, x_mid - 1, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*Allow scrolling on the edges. It will be reverted to the edge due to snapping anyway*/
|
||||
if(proc->types.pointer.scroll_area.x1 == 0) proc->types.pointer.scroll_area.x1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.x2 == 0) proc->types.pointer.scroll_area.x2 = LV_COORD_MAX;
|
||||
if(proc->types.pointer.scroll_area.y1 == 0) proc->types.pointer.scroll_area.y1 = LV_COORD_MIN;
|
||||
if(proc->types.pointer.scroll_area.y2 == 0) proc->types.pointer.scroll_area.y2 = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful the get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_x(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_x(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t x_child = 0;
|
||||
lv_coord_t x_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
x_child = child->coords.x1;
|
||||
x_parent = obj->coords.x1 + pad_left;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
x_child = child->coords.x2;
|
||||
x_parent = obj->coords.x2 - pad_right;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
x_child = child->coords.x1 + lv_area_get_width(&child->coords) / 2;
|
||||
x_parent = obj->coords.x1 + pad_left + (lv_area_get_width(&obj->coords) - pad_left - pad_right) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
x_child += ofs;
|
||||
if(x_child >= min && x_child <= max) {
|
||||
lv_coord_t x = x_child - x_parent;
|
||||
if(LV_ABS(x) < LV_ABS(dist)) dist = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for snap point in the `min` - `max` range.
|
||||
* @param obj the object on which snap point should be found
|
||||
* @param min ignore snap points smaller than this. (Absolute coordinate)
|
||||
* @param max ignore snap points greater than this. (Absolute coordinate)
|
||||
* @param ofs offset to snap points. Useful to get a snap point in an imagined case
|
||||
* what if children are already moved by this value
|
||||
* @return the distance of the snap point.
|
||||
*/
|
||||
static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coord_t max, lv_coord_t ofs)
|
||||
{
|
||||
lv_scroll_snap_t align = lv_obj_get_scroll_snap_y(obj);
|
||||
if(align == LV_SCROLL_SNAP_NONE) return 0;
|
||||
|
||||
lv_coord_t dist = LV_COORD_MAX;
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
if(lv_obj_has_flag(child, LV_OBJ_FLAG_SNAPPABLE)) {
|
||||
lv_coord_t y_child = 0;
|
||||
lv_coord_t y_parent = 0;
|
||||
switch(align) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
y_child = child->coords.y1;
|
||||
y_parent = obj->coords.y1 + pad_top;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
y_child = child->coords.y2;
|
||||
y_parent = obj->coords.y2 - pad_bottom;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
y_child = child->coords.y1 + lv_area_get_height(&child->coords) / 2;
|
||||
y_parent = obj->coords.y1 + pad_top + (lv_area_get_height(&obj->coords) - pad_top - pad_bottom) / 2;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
y_child += ofs;
|
||||
if(y_child >= min && y_child <= max) {
|
||||
lv_coord_t y = y_child - y_parent;
|
||||
if(LV_ABS(y) < LV_ABS(dist)) dist = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||
}
|
||||
|
||||
static void scroll_limit_diff(_lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y)
|
||||
{
|
||||
if(diff_y) {
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.y + *diff_y > proc->types.pointer.scroll_area.y2) {
|
||||
*diff_y = proc->types.pointer.scroll_area.y2 - proc->types.pointer.scroll_sum.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(diff_x) {
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x < proc->types.pointer.scroll_area.x1) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x1 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
|
||||
if(proc->types.pointer.scroll_sum.x + *diff_x > proc->types.pointer.scroll_area.x2) {
|
||||
*diff_x = proc->types.pointer.scroll_area.x2 - proc->types.pointer.scroll_sum.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_y(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t y = proc->types.pointer.scroll_throw_vect.y;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(y) {
|
||||
move += y;
|
||||
y = y * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
|
||||
static lv_coord_t scroll_throw_predict_x(_lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_coord_t x = proc->types.pointer.scroll_throw_vect.x;
|
||||
lv_coord_t move = 0;
|
||||
|
||||
lv_indev_t * indev_act = lv_indev_get_act();
|
||||
lv_coord_t scroll_throw = indev_act->driver->scroll_throw;
|
||||
|
||||
while(x) {
|
||||
move += x;
|
||||
x = x * (100 - scroll_throw) / 100;
|
||||
}
|
||||
return move;
|
||||
}
|
||||
|
||||
static lv_coord_t elastic_diff(lv_obj_t * scroll_obj, lv_coord_t diff, lv_coord_t scroll_start, lv_coord_t scroll_end,
|
||||
lv_dir_t dir)
|
||||
{
|
||||
if(lv_obj_has_flag(scroll_obj, LV_OBJ_FLAG_SCROLL_ELASTIC)) {
|
||||
/*If there is snapping in the current direction don't use the elastic factor because
|
||||
*it's natural that the first and last items are scrolled (snapped) in.*/
|
||||
lv_scroll_snap_t snap;
|
||||
snap = dir == LV_DIR_HOR ? lv_obj_get_scroll_snap_x(scroll_obj) : lv_obj_get_scroll_snap_y(scroll_obj);
|
||||
|
||||
lv_obj_t * act_obj = lv_indev_get_obj_act();
|
||||
lv_coord_t snap_point = 0;
|
||||
lv_coord_t act_obj_point = 0;
|
||||
|
||||
if(dir == LV_DIR_HOR) {
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_left + (lv_area_get_width(&scroll_obj->coords) - pad_left - pad_right) / 2 + scroll_obj->coords.x1;
|
||||
act_obj_point = lv_area_get_width(&act_obj->coords) / 2 + act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.x1 + pad_left;
|
||||
act_obj_point = act_obj->coords.x1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.x2 - pad_right;
|
||||
act_obj_point = act_obj->coords.x2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(scroll_obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(scroll_obj, LV_PART_MAIN);
|
||||
|
||||
switch(snap) {
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_point = pad_top + (lv_area_get_height(&scroll_obj->coords) - pad_top - pad_bottom) / 2 + scroll_obj->coords.y1;
|
||||
act_obj_point = lv_area_get_height(&act_obj->coords) / 2 + act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_point = scroll_obj->coords.y1 + pad_top;
|
||||
act_obj_point = act_obj->coords.y1;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_point = scroll_obj->coords.y2 - pad_bottom;
|
||||
act_obj_point = act_obj->coords.y2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(scroll_end < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point > snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
else if(scroll_start < 0) {
|
||||
if(snap != LV_SCROLL_SNAP_NONE && act_obj_point < snap_point) return diff;
|
||||
|
||||
/*Rounding*/
|
||||
if(diff < 0) diff -= ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
if(diff > 0) diff += ELASTIC_SLOWNESS_FACTOR / 2;
|
||||
return diff / ELASTIC_SLOWNESS_FACTOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Scroll back to the boundary if required*/
|
||||
if(scroll_end + diff < 0) diff = - scroll_end;
|
||||
if(scroll_start - diff < 0) diff = scroll_start;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
65
EC600U_lvgl_lib/lvgl/src/core/lv_indev_scroll.h
Normal file
65
EC600U_lvgl_lib/lvgl/src/core/lv_indev_scroll.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file lv_indev_scroll.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_INDEV_SCROLL_H
|
||||
#define LV_INDEV_SCROLL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle scrolling. Called by LVGL during input device processing
|
||||
* @param proc pointer to an input device's proc field
|
||||
*/
|
||||
void _lv_indev_scroll_handler(_lv_indev_proc_t * proc);
|
||||
|
||||
/**
|
||||
* Handle throwing after scrolling. Called by LVGL during input device processing
|
||||
* @param proc pointer to an input device's proc field
|
||||
*/
|
||||
void _lv_indev_scroll_throw_handler(_lv_indev_proc_t * proc);
|
||||
|
||||
/**
|
||||
* Predict where would a scroll throw end
|
||||
* @param indev pointer to an input device
|
||||
* @param dir ` LV_DIR_VER` or `LV_DIR_HOR`
|
||||
* @return the difference compared to the current position when the throw would be finished
|
||||
*/
|
||||
lv_coord_t lv_indev_scroll_throw_predict(lv_indev_t * indev, lv_dir_t dir);
|
||||
|
||||
/**
|
||||
* Get the distance of the nearest snap point
|
||||
* @param obj the object on which snap points should be found
|
||||
* @param p save the distance of the found snap point there
|
||||
*/
|
||||
void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_INDEV_SCROLL_H*/
|
944
EC600U_lvgl_lib/lvgl/src/core/lv_obj.c
Normal file
944
EC600U_lvgl_lib/lvgl/src/core/lv_obj.c
Normal file
@ -0,0 +1,944 @@
|
||||
/**
|
||||
* @file lv_obj.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_refr.h"
|
||||
#include "lv_group.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_theme.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_async.h"
|
||||
#include "../misc/lv_fs.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../hal/lv_hal.h"
|
||||
#include "../extra/lv_extra.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
#include "../gpu/lv_gpu_stm32_dma2d.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
#include "../gpu/lv_gpu_nxp_pxp.h"
|
||||
#include "../gpu/lv_gpu_nxp_pxp_osa.h"
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
#include "../gpu/lv_gpu_sdl.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
#define LV_OBJ_DEF_WIDTH (LV_DPX(100))
|
||||
#define LV_OBJ_DEF_HEIGHT (LV_DPX(50))
|
||||
#define GRID_DEBUG 0 /*Draw rectangles on grid cells*/
|
||||
#define STYLE_TRANSITION_MAX 32
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_obj_draw(lv_event_t * e);
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area);
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc);
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool lv_initialized = false;
|
||||
const lv_obj_class_t lv_obj_class = {
|
||||
.constructor_cb = lv_obj_constructor,
|
||||
.destructor_cb = lv_obj_destructor,
|
||||
.event_cb = lv_obj_event,
|
||||
.width_def = LV_DPI_DEF,
|
||||
.height_def = LV_DPI_DEF,
|
||||
.editable = LV_OBJ_CLASS_EDITABLE_FALSE,
|
||||
.group_def = LV_OBJ_CLASS_GROUP_DEF_FALSE,
|
||||
.instance_size = (sizeof(lv_obj_t)),
|
||||
.base_class = NULL,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
bool lv_is_initialized(void)
|
||||
{
|
||||
return lv_initialized;
|
||||
}
|
||||
|
||||
void lv_init(void)
|
||||
{
|
||||
/*Do nothing if already initialized*/
|
||||
if(lv_initialized) {
|
||||
LV_LOG_WARN("lv_init: already inited");
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("begin");
|
||||
|
||||
/*Initialize the misc modules*/
|
||||
lv_mem_init();
|
||||
|
||||
_lv_timer_core_init();
|
||||
|
||||
_lv_fs_init();
|
||||
|
||||
_lv_anim_core_init();
|
||||
|
||||
_lv_group_init();
|
||||
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
/*Initialize DMA2D GPU*/
|
||||
lv_gpu_stm32_dma2d_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP && LV_USE_GPU_NXP_PXP_AUTO_INIT
|
||||
if(lv_gpu_nxp_pxp_init(&pxp_default_cfg) != LV_RES_OK) {
|
||||
LV_LOG_ERROR("PXP init error. STOP.\n");
|
||||
for(; ;) ;
|
||||
}
|
||||
#endif
|
||||
#if LV_USE_GPU_SDL
|
||||
lv_gpu_sdl_init();
|
||||
#endif
|
||||
|
||||
_lv_obj_style_init();
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t));
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t));
|
||||
|
||||
/*Initialize the screen refresh system*/
|
||||
_lv_refr_init();
|
||||
|
||||
_lv_img_decoder_init();
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE);
|
||||
#endif
|
||||
// /*Test if the IDE has UTF-8 encoding*/
|
||||
// char * txt = "Á";
|
||||
|
||||
// uint8_t * txt_u8 = (uint8_t *)txt;
|
||||
// if(txt_u8[0] != 0xc3 || txt_u8[1] != 0x81 || txt_u8[2] != 0x00) {
|
||||
// LV_LOG_WARN("The strings has no UTF-8 encoding. Non-ASCII characters won't be displayed.");
|
||||
// }
|
||||
|
||||
// uint32_t endianess_test = 0x11223344;
|
||||
// uint8_t * endianess_test_p = (uint8_t *) &endianess_test;
|
||||
// bool big_endian = endianess_test_p[0] == 0x11 ? true : false;
|
||||
|
||||
// if(big_endian) {
|
||||
// LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 1,
|
||||
// "It's a big endian system but LV_BIG_ENDIAN_SYSTEM is not enabled in lv_conf.h");
|
||||
// }
|
||||
// else {
|
||||
// LV_ASSERT_MSG(LV_BIG_ENDIAN_SYSTEM == 0,
|
||||
// "It's a little endian system but LV_BIG_ENDIAN_SYSTEM is enabled in lv_conf.h");
|
||||
// }
|
||||
|
||||
// #if LV_USE_ASSERT_MEM_INTEGRITY
|
||||
// LV_LOG_WARN("Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower");
|
||||
// #endif
|
||||
|
||||
// #if LV_USE_ASSERT_OBJ
|
||||
// LV_LOG_WARN("Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower");
|
||||
// #endif
|
||||
|
||||
// #if LV_USE_ASSERT_STYLE
|
||||
// LV_LOG_WARN("Style sanity checks are enabled that uses more RAM");
|
||||
// #endif
|
||||
|
||||
// #if LV_LOG_LEVEL == LV_LOG_LEVEL_TRACE
|
||||
// LV_LOG_WARN("Log level is set the Trace which makes LVGL much slower");
|
||||
// #endif
|
||||
|
||||
lv_extra_init();
|
||||
|
||||
lv_initialized = true;
|
||||
|
||||
LV_LOG_TRACE("finished");
|
||||
}
|
||||
|
||||
#if LV_ENABLE_GC || !LV_MEM_CUSTOM || LV_USE_GPU_SDL
|
||||
|
||||
void lv_deinit(void)
|
||||
{
|
||||
#if LV_USE_GPU_SDL
|
||||
lv_gpu_sdl_deinit();
|
||||
#endif
|
||||
_lv_gc_clear_roots();
|
||||
|
||||
lv_disp_set_default(NULL);
|
||||
lv_mem_deinit();
|
||||
lv_initialized = false;
|
||||
|
||||
LV_LOG_INFO("lv_deinit done");
|
||||
|
||||
#if LV_USE_LOG
|
||||
lv_log_register_print_cb(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*-----------------
|
||||
* Attribute set
|
||||
*----------------*/
|
||||
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) lv_obj_invalidate(obj);
|
||||
|
||||
obj->flags |= f;
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
bool was_on_layout = lv_obj_is_layout_positioned(obj);
|
||||
if(f & LV_OBJ_FLAG_SCROLLABLE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
obj->flags &= (~f);
|
||||
|
||||
if(f & LV_OBJ_FLAG_HIDDEN) {
|
||||
lv_obj_invalidate(obj);
|
||||
if(lv_obj_is_layout_positioned(obj)) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
}
|
||||
|
||||
if((was_on_layout != lv_obj_is_layout_positioned(obj)) || (f & (LV_OBJ_FLAG_LAYOUT_1 | LV_OBJ_FLAG_LAYOUT_2))) {
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state | state;
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t new_state = obj->state & (~state);
|
||||
if(obj->state != new_state) {
|
||||
lv_obj_set_state(obj, new_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) == f ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return (obj->flags & f) ? true : false;
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_get_state(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state;
|
||||
}
|
||||
|
||||
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->state & state ? true : false;
|
||||
}
|
||||
|
||||
void * lv_obj_get_group(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr) return obj->spec_attr->group_p;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
* OTHER FUNCTIONS
|
||||
*------------------*/
|
||||
|
||||
void lv_obj_allocate_spec_attr(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) {
|
||||
static uint32_t x = 0;
|
||||
x++;
|
||||
obj->spec_attr = lv_mem_alloc(sizeof(_lv_obj_spec_attr_t));
|
||||
LV_ASSERT_MALLOC(obj->spec_attr);
|
||||
if(obj->spec_attr == NULL) return;
|
||||
|
||||
lv_memset_00(obj->spec_attr, sizeof(_lv_obj_spec_attr_t));
|
||||
|
||||
obj->spec_attr->scroll_dir = LV_DIR_ALL;
|
||||
obj->spec_attr->scrollbar_mode = LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
if(obj == NULL) return false;
|
||||
return obj->class_p == class_p ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p)
|
||||
{
|
||||
const lv_obj_class_t * obj_class = obj->class_p;
|
||||
while(obj_class) {
|
||||
if(obj_class == class_p) return true;
|
||||
obj_class = obj_class->base_class;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj)
|
||||
{
|
||||
return obj->class_p;
|
||||
}
|
||||
|
||||
bool lv_obj_is_valid(const lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) return true;
|
||||
bool found = obj_valid_child(disp->screens[i], obj);
|
||||
if(found) return true;
|
||||
}
|
||||
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_obj_t * parent = obj->parent;
|
||||
if(parent) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(parent);
|
||||
lv_coord_t st = lv_obj_get_scroll_top(parent);
|
||||
|
||||
obj->coords.y1 = parent->coords.y1 + lv_obj_get_style_pad_top(parent, LV_PART_MAIN) - st;
|
||||
obj->coords.y2 = obj->coords.y1 - 1;
|
||||
obj->coords.x1 = parent->coords.x1 + lv_obj_get_style_pad_left(parent, LV_PART_MAIN) - sl;
|
||||
obj->coords.x2 = obj->coords.x1 - 1;
|
||||
}
|
||||
|
||||
/*Set attributes*/
|
||||
obj->flags = LV_OBJ_FLAG_CLICKABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SNAPPABLE;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_PRESS_LOCK;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_SCROLL_CHAIN;
|
||||
obj->flags |= LV_OBJ_FLAG_CLICK_FOCUSABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLLABLE;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_ELASTIC;
|
||||
obj->flags |= LV_OBJ_FLAG_SCROLL_MOMENTUM;
|
||||
if(parent) obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void lv_obj_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
_lv_event_mark_deleted(obj);
|
||||
|
||||
/*Remove all style*/
|
||||
lv_obj_enable_style_refresh(false); /*No need to refresh the style because the object will be deleted*/
|
||||
lv_obj_remove_style_all(obj);
|
||||
lv_obj_enable_style_refresh(true);
|
||||
|
||||
/*Remove the animations from this object*/
|
||||
lv_anim_del(obj, NULL);
|
||||
|
||||
/*Delete from the group*/
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
if(group) lv_group_remove_obj(obj);
|
||||
|
||||
if(obj->spec_attr) {
|
||||
if(obj->spec_attr->children) {
|
||||
lv_mem_free(obj->spec_attr->children);
|
||||
obj->spec_attr->children = NULL;
|
||||
}
|
||||
if(obj->spec_attr->event_dsc) {
|
||||
lv_mem_free(obj->spec_attr->event_dsc);
|
||||
obj->spec_attr->event_dsc = NULL;
|
||||
}
|
||||
|
||||
lv_mem_free(obj->spec_attr);
|
||||
obj->spec_attr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_obj_draw(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
if(code == LV_EVENT_COVER_CHECK) {
|
||||
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||
if(info->res == LV_COVER_RES_MASKED) return;
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
info->res = LV_COVER_RES_MASKED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*Most trivial test. Is the mask fully IN the object? If no it surely doesn't cover it*/
|
||||
lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
if(_lv_area_is_in(info->area, &coords, r) == false) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_blend_mode(obj, LV_PART_MAIN) != LV_BLEND_MODE_NORMAL) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(lv_obj_get_style_opa(obj, LV_PART_MAIN) < LV_OPA_MAX) {
|
||||
info->res = LV_COVER_RES_NOT_COVER;
|
||||
return;
|
||||
}
|
||||
|
||||
info->res = LV_COVER_RES_COVER;
|
||||
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||
const lv_area_t * clip_area = lv_event_get_param(e);
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
/*If the border is drawn later disable loading its properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
draw_dsc.border_post = 1;
|
||||
}
|
||||
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, clip_area);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
lv_draw_rect(&coords, clip_area, &draw_dsc);
|
||||
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
/*If the radius is 0 the parent's coordinates will clip anyway*/
|
||||
lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN);
|
||||
if(r != 0) {
|
||||
lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t));
|
||||
lv_draw_mask_radius_init(mp, &obj->coords, r, false);
|
||||
/*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/
|
||||
lv_draw_mask_add(mp, obj + 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_POST) {
|
||||
const lv_area_t * clip_area = lv_event_get_param(e);
|
||||
draw_scrollbar(obj, clip_area);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {
|
||||
lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);
|
||||
if(param) {
|
||||
lv_draw_mask_free_param(param);
|
||||
lv_mem_buf_release(param);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*If the border is drawn later disable loading other properties*/
|
||||
if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
draw_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.outline_opa = LV_OPA_TRANSP;
|
||||
draw_dsc.shadow_opa = LV_OPA_TRANSP;
|
||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);
|
||||
lv_area_t coords;
|
||||
lv_area_copy(&coords, &obj->coords);
|
||||
coords.x1 -= w;
|
||||
coords.x2 += w;
|
||||
coords.y1 -= h;
|
||||
coords.y2 += h;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, clip_area);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.draw_area = &coords;
|
||||
part_dsc.part = LV_PART_MAIN;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
|
||||
lv_draw_rect(&coords, clip_area, &draw_dsc);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_scrollbar(lv_obj_t * obj, const lv_area_t * clip_area)
|
||||
{
|
||||
|
||||
lv_area_t hor_area;
|
||||
lv_area_t ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
|
||||
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_res_t sb_res = scrollbar_init_draw_dsc(obj, &draw_dsc);
|
||||
if(sb_res != LV_RES_OK) return;
|
||||
|
||||
lv_obj_draw_part_dsc_t part_dsc;
|
||||
lv_obj_draw_dsc_init(&part_dsc, clip_area);
|
||||
part_dsc.class_p = MY_CLASS;
|
||||
part_dsc.type = LV_OBJ_DRAW_PART_SCROLLBAR;
|
||||
part_dsc.rect_dsc = &draw_dsc;
|
||||
part_dsc.part = LV_PART_SCROLLBAR;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) {
|
||||
part_dsc.draw_area = &hor_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
lv_draw_rect(&hor_area, clip_area, &draw_dsc);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
if(lv_area_get_size(&ver_area) > 0) {
|
||||
part_dsc.draw_area = &ver_area;
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);
|
||||
lv_draw_rect(&ver_area, clip_area, &draw_dsc);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the draw descriptor for the scrollbar
|
||||
* @param obj pointer to an object
|
||||
* @param dsc the draw descriptor to initialize
|
||||
* @return LV_RES_OK: the scrollbar is visible; LV_RES_INV: the scrollbar is not visible
|
||||
*/
|
||||
static lv_res_t scrollbar_init_draw_dsc(lv_obj_t * obj, lv_draw_rect_dsc_t * dsc)
|
||||
{
|
||||
lv_draw_rect_dsc_init(dsc);
|
||||
dsc->bg_opa = lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->bg_opa > LV_OPA_MIN) {
|
||||
dsc->bg_color = lv_obj_get_style_bg_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
|
||||
dsc->border_opa = lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_opa > LV_OPA_MIN) {
|
||||
dsc->border_width = lv_obj_get_style_border_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->border_width > 0) {
|
||||
dsc->border_color = lv_obj_get_style_border_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->border_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_opa > LV_OPA_MIN) {
|
||||
dsc->shadow_width = lv_obj_get_style_shadow_width(obj, LV_PART_SCROLLBAR);
|
||||
if(dsc->shadow_width > 0) {
|
||||
dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, LV_PART_SCROLLBAR);
|
||||
dsc->shadow_color = lv_obj_get_style_shadow_color(obj, LV_PART_SCROLLBAR);
|
||||
}
|
||||
else {
|
||||
dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, LV_PART_SCROLLBAR);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
dsc->bg_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->border_opa = (dsc->bg_opa * opa) >> 8;
|
||||
dsc->shadow_opa = (dsc->bg_opa * opa) >> 8;
|
||||
}
|
||||
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP || dsc->shadow_opa != LV_OPA_TRANSP) {
|
||||
dsc->radius = lv_obj_get_style_radius(obj, LV_PART_SCROLLBAR);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
#else
|
||||
if(dsc->bg_opa != LV_OPA_TRANSP || dsc->border_opa != LV_OPA_TRANSP) return LV_RES_OK;
|
||||
else return LV_RES_INV;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
if(code == LV_EVENT_PRESSED) {
|
||||
lv_obj_add_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_RELEASED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
void * param = lv_event_get_param(e);
|
||||
/*Go the checked state if enabled*/
|
||||
if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
if(!(lv_obj_get_state(obj) & LV_STATE_CHECKED)) lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
else lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_PRESS_LOST) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(code == LV_EVENT_STYLE_CHANGED) {
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(uint32_t i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_KEY) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||
lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
/*With Enter LV_EVENT_RELEASED will send VALUE_CHANGE event*/
|
||||
if(c != LV_KEY_ENTER) {
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
else if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) && !lv_obj_is_editable(obj)) {
|
||||
/*scroll by keypad or encoder*/
|
||||
lv_anim_enable_t anim_enable = LV_ANIM_OFF;
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
char c = *((char *)lv_event_get_param(e));
|
||||
if(c == LV_KEY_DOWN) {
|
||||
/*use scroll_to_x/y functions to enforce scroll limits*/
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_UP) {
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_RIGHT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) + lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) + lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT) {
|
||||
/*If the object can't be scrolled horizontally then scroll it vertically*/
|
||||
if(!((lv_obj_get_scroll_dir(obj) & LV_DIR_HOR) && (sl > 0 || sr > 0)))
|
||||
lv_obj_scroll_to_y(obj, lv_obj_get_scroll_y(obj) - lv_obj_get_height(obj) / 4, anim_enable);
|
||||
else
|
||||
lv_obj_scroll_to_x(obj, lv_obj_get_scroll_x(obj) - lv_obj_get_width(obj) / 4, anim_enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_FOCUSED) {
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS)) {
|
||||
lv_obj_scroll_to_view_recursive(obj, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
bool editing = false;
|
||||
editing = lv_group_get_editing(lv_obj_get_group(obj));
|
||||
lv_state_t state = LV_STATE_FOCUSED;
|
||||
|
||||
/* Use the indev for then indev handler.
|
||||
* But if the obj was focused manually it returns NULL so try to
|
||||
* use the indev from the event*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev == NULL) indev = lv_event_get_indev(e);
|
||||
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD || indev_type == LV_INDEV_TYPE_ENCODER) state |= LV_STATE_FOCUS_KEY;
|
||||
if(editing) {
|
||||
state |= LV_STATE_EDITED;
|
||||
lv_obj_add_state(obj, state);
|
||||
}
|
||||
else {
|
||||
lv_obj_add_state(obj, state);
|
||||
lv_obj_clear_state(obj, LV_STATE_EDITED);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_BEGIN) {
|
||||
lv_obj_add_state(obj, LV_STATE_SCROLLED);
|
||||
}
|
||||
else if(code == LV_EVENT_SCROLL_END) {
|
||||
lv_obj_clear_state(obj, LV_STATE_SCROLLED);
|
||||
if(lv_obj_get_scrollbar_mode(obj) == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
lv_area_t hor_area, ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
lv_obj_invalidate_area(obj, &hor_area);
|
||||
lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_DEFOCUSED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED | LV_STATE_FOCUS_KEY);
|
||||
}
|
||||
else if(code == LV_EVENT_SIZE_CHANGED) {
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_mark_layout_as_dirty(child);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_CHILD_CHANGED) {
|
||||
lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_MAIN);
|
||||
lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_MAIN);
|
||||
lv_coord_t align = lv_obj_get_style_align(obj, LV_PART_MAIN);
|
||||
uint16_t layout = lv_obj_get_style_layout(obj, LV_PART_MAIN);
|
||||
if(layout || align || w == LV_SIZE_CONTENT || h == LV_SIZE_CONTENT) {
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||
lv_coord_t * s = lv_event_get_param(e);
|
||||
lv_coord_t d = lv_obj_calculate_ext_draw_size(obj, LV_PART_MAIN);
|
||||
*s = LV_MAX(*s, d);
|
||||
}
|
||||
else if(code == LV_EVENT_DRAW_MAIN || code == LV_EVENT_DRAW_POST || code == LV_EVENT_COVER_CHECK) {
|
||||
lv_obj_draw(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state (fully overwrite) of an object.
|
||||
* If specified in the styles, transition animations will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the new state
|
||||
*/
|
||||
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state)
|
||||
{
|
||||
if(obj->state == new_state) return;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_state_t prev_state = obj->state;
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_style_state_cmp_t cmp_res = _lv_obj_style_state_compare(obj, prev_state, new_state);
|
||||
/*If there is no difference in styles there is nothing else to do*/
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_SAME) return;
|
||||
|
||||
_lv_obj_style_transition_dsc_t * ts = lv_mem_buf_get(sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
lv_memset_00(ts, sizeof(_lv_obj_style_transition_dsc_t) * STYLE_TRANSITION_MAX);
|
||||
uint32_t tsi = 0;
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt && tsi < STYLE_TRANSITION_MAX; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if(state_act & (~new_state)) continue; /*Skip unrelated styles*/
|
||||
if(obj_style->is_trans) continue;
|
||||
|
||||
lv_style_value_t v;
|
||||
if(lv_style_get_prop_inlined(obj_style->style, LV_STYLE_TRANSITION, &v) == false) continue;
|
||||
const lv_style_transition_dsc_t * tr = v.ptr;
|
||||
|
||||
/*Add the props to the set if not added yet or added but with smaller weight*/
|
||||
uint32_t j;
|
||||
for(j = 0; tr->props[j] != 0 && tsi < STYLE_TRANSITION_MAX; j++) {
|
||||
uint32_t t;
|
||||
for(t = 0; t < tsi; t++) {
|
||||
lv_style_selector_t selector = ts[t].selector;
|
||||
lv_state_t state_ts = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part_ts = lv_obj_style_get_selector_part(selector);
|
||||
if(ts[t].prop == tr->props[j] && part_ts == part_act && state_ts >= state_act) break;
|
||||
}
|
||||
|
||||
/*If not found add it*/
|
||||
if(t == tsi) {
|
||||
ts[tsi].time = tr->time;
|
||||
ts[tsi].delay = tr->delay;
|
||||
ts[tsi].path_cb = tr->path_xcb;
|
||||
ts[tsi].prop = tr->props[j];
|
||||
#if LV_USE_USER_DATA
|
||||
ts[tsi].user_data = tr->user_data;
|
||||
#endif
|
||||
ts[tsi].selector = obj_style->selector;
|
||||
tsi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < tsi; i++) {
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(ts[i].selector);
|
||||
_lv_obj_style_create_transition(obj, part_act, prev_state, new_state, &ts[i]);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(ts);
|
||||
|
||||
if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_REDRAW) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_LAYOUT) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
else if(cmp_res == _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD) {
|
||||
lv_obj_invalidate(obj);
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find)
|
||||
{
|
||||
/*Check all children of `parent`*/
|
||||
uint32_t child_cnt = 0;
|
||||
if(parent->spec_attr) child_cnt = parent->spec_attr->child_cnt;
|
||||
uint32_t i;
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = parent->spec_attr->children[i];
|
||||
if(child == obj_to_find) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*Check the children*/
|
||||
bool found = obj_valid_child(child, obj_to_find);
|
||||
if(found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
400
EC600U_lvgl_lib/lvgl/src/core/lv_obj.h
Normal file
400
EC600U_lvgl_lib/lvgl/src/core/lv_obj.h
Normal file
@ -0,0 +1,400 @@
|
||||
/**
|
||||
* @file lv_obj.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_H
|
||||
#define LV_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../hal/lv_hal.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
|
||||
/**
|
||||
* Possible states of a widget.
|
||||
* OR-ed values are possible
|
||||
*/
|
||||
enum {
|
||||
LV_STATE_DEFAULT = 0x0000,
|
||||
LV_STATE_CHECKED = 0x0001,
|
||||
LV_STATE_FOCUSED = 0x0002,
|
||||
LV_STATE_FOCUS_KEY = 0x0004,
|
||||
LV_STATE_EDITED = 0x0008,
|
||||
LV_STATE_HOVERED = 0x0010,
|
||||
LV_STATE_PRESSED = 0x0020,
|
||||
LV_STATE_SCROLLED = 0x0040,
|
||||
LV_STATE_DISABLED = 0x0080,
|
||||
|
||||
LV_STATE_USER_1 = 0x1000,
|
||||
LV_STATE_USER_2 = 0x2000,
|
||||
LV_STATE_USER_3 = 0x4000,
|
||||
LV_STATE_USER_4 = 0x8000,
|
||||
|
||||
LV_STATE_ANY = 0xFFFF, /**< Special value can be used in some functions to target all states*/
|
||||
};
|
||||
|
||||
typedef uint16_t lv_state_t;
|
||||
|
||||
/**
|
||||
* The possible parts of widgets.
|
||||
* The parts can be considered as the internal building block of the widgets.
|
||||
* E.g. slider = background + indicator + knob
|
||||
* Note every part is used by every widget
|
||||
*/
|
||||
enum {
|
||||
LV_PART_MAIN = 0x000000, /**< A background like rectangle*/
|
||||
LV_PART_SCROLLBAR = 0x010000, /**< The scrollbar(s)*/
|
||||
LV_PART_INDICATOR = 0x020000, /**< Indicator, e.g. for slider, bar, switch, or the tick box of the checkbox*/
|
||||
LV_PART_KNOB = 0x030000, /**< Like handle to grab to adjust the value*/
|
||||
LV_PART_SELECTED = 0x040000, /**< Indicate the currently selected option or section*/
|
||||
LV_PART_ITEMS = 0x050000, /**< Used if the widget has multiple similar elements (e.g. table cells)*/
|
||||
LV_PART_TICKS = 0x060000, /**< Ticks on scale e.g. for a chart or meter*/
|
||||
LV_PART_CURSOR = 0x070000, /**< Mark a specific place e.g. for text area's cursor or on a chart*/
|
||||
|
||||
LV_PART_CUSTOM_FIRST = 0x080000, /**< Extension point for custom widgets*/
|
||||
|
||||
LV_PART_ANY = 0x0F0000, /**< Special value can be used in some functions to target all parts*/
|
||||
};
|
||||
|
||||
typedef uint32_t lv_part_t;
|
||||
|
||||
/**
|
||||
* On/Off features controlling the object's behavior.
|
||||
* OR-ed values are possible
|
||||
*/
|
||||
enum {
|
||||
LV_OBJ_FLAG_HIDDEN = (1L << 0), /**< Make the object hidden. (Like it wasn't there at all)*/
|
||||
LV_OBJ_FLAG_CLICKABLE = (1L << 1), /**< Make the object clickable by the input devices*/
|
||||
LV_OBJ_FLAG_CLICK_FOCUSABLE = (1L << 2), /**< Add focused state to the object when clicked*/
|
||||
LV_OBJ_FLAG_CHECKABLE = (1L << 3), /**< Toggle checked state when the object is clicked*/
|
||||
LV_OBJ_FLAG_SCROLLABLE = (1L << 4), /**< Make the object scrollable*/
|
||||
LV_OBJ_FLAG_SCROLL_ELASTIC = (1L << 5), /**< Allow scrolling inside but with slower speed*/
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1L << 6), /**< Make the object scroll further when "thrown"*/
|
||||
LV_OBJ_FLAG_SCROLL_ONE = (1L << 7), /**< Allow scrolling only one snappable children*/
|
||||
LV_OBJ_FLAG_SCROLL_CHAIN = (1L << 8), /**< Allow propagating the scroll to a parent*/
|
||||
LV_OBJ_FLAG_SCROLL_ON_FOCUS = (1L << 9), /**< Automatically scroll object to make it visible when focused*/
|
||||
LV_OBJ_FLAG_SNAPPABLE = (1L << 10), /**< If scroll snap is enabled on the parent it can snap to this object*/
|
||||
LV_OBJ_FLAG_PRESS_LOCK = (1L << 11), /**< Keep the object pressed even if the press slid from the object*/
|
||||
LV_OBJ_FLAG_EVENT_BUBBLE = (1L << 12), /**< Propagate the events to the parent too*/
|
||||
LV_OBJ_FLAG_GESTURE_BUBBLE = (1L << 13), /**< Propagate the gestures to the parent*/
|
||||
LV_OBJ_FLAG_ADV_HITTEST = (1L << 14), /**< Allow performing more accurate hit (click) test. E.g. consider rounded corners.*/
|
||||
LV_OBJ_FLAG_IGNORE_LAYOUT = (1L << 15), /**< Make the object position-able by the layouts*/
|
||||
LV_OBJ_FLAG_FLOATING = (1L << 16), /**< Do not scroll the object when the parent scrolls and ignore layout*/
|
||||
|
||||
LV_OBJ_FLAG_LAYOUT_1 = (1L << 23), /**< Custom flag, free to use by layouts*/
|
||||
LV_OBJ_FLAG_LAYOUT_2 = (1L << 24), /**< Custom flag, free to use by layouts*/
|
||||
|
||||
LV_OBJ_FLAG_WIDGET_1 = (1L << 25), /**< Custom flag, free to use by widget*/
|
||||
LV_OBJ_FLAG_WIDGET_2 = (1L << 26), /**< Custom flag, free to use by widget*/
|
||||
LV_OBJ_FLAG_USER_1 = (1L << 27), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_2 = (1L << 28), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_3 = (1L << 29), /**< Custom flag, free to use by user*/
|
||||
LV_OBJ_FLAG_USER_4 = (1L << 30), /**< Custom flag, free to use by user*/
|
||||
};
|
||||
typedef uint32_t lv_obj_flag_t;
|
||||
|
||||
/**
|
||||
* `type` field in `lv_obj_draw_part_dsc_t` if `class_p = lv_obj_class`
|
||||
* Used in `LV_EVENT_DRAW_PART_BEGIN` and `LV_EVENT_DRAW_PART_END`
|
||||
*/
|
||||
typedef enum {
|
||||
LV_OBJ_DRAW_PART_RECTANGLE, /**< The main rectangle*/
|
||||
LV_OBJ_DRAW_PART_BORDER_POST,/**< The border if style_border_post = true*/
|
||||
LV_OBJ_DRAW_PART_SCROLLBAR, /**< The scrollbar*/
|
||||
} lv_obj_draw_part_type_t;
|
||||
|
||||
#include "lv_obj_tree.h"
|
||||
#include "lv_obj_pos.h"
|
||||
#include "lv_obj_scroll.h"
|
||||
#include "lv_obj_style.h"
|
||||
#include "lv_obj_draw.h"
|
||||
#include "lv_obj_class.h"
|
||||
#include "lv_event.h"
|
||||
#include "lv_group.h"
|
||||
|
||||
/**
|
||||
* Make the base object's class publicly available.
|
||||
*/
|
||||
extern const lv_obj_class_t lv_obj_class;
|
||||
|
||||
/**
|
||||
* Special, rarely used attributes.
|
||||
* They are allocated automatically if any elements is set.
|
||||
*/
|
||||
typedef struct {
|
||||
struct _lv_obj_t ** children; /**< Store the pointer of the children in an array.*/
|
||||
uint32_t child_cnt; /**< Number of children*/
|
||||
lv_group_t * group_p;
|
||||
|
||||
struct _lv_event_dsc_t * event_dsc; /**< Dynamically allocated event callback and user data array*/
|
||||
lv_point_t scroll; /**< The current X/Y scroll offset*/
|
||||
|
||||
lv_coord_t ext_click_pad; /**< Extra click padding in all direction*/
|
||||
lv_coord_t ext_draw_size; /**< EXTend the size in every direction for drawing.*/
|
||||
|
||||
lv_scrollbar_mode_t scrollbar_mode : 2; /**< How to display scrollbars*/
|
||||
lv_scroll_snap_t scroll_snap_x : 2; /**< Where to align the snappable children horizontally*/
|
||||
lv_scroll_snap_t scroll_snap_y : 2; /**< Where to align the snappable children vertically*/
|
||||
lv_dir_t scroll_dir : 4; /**< The allowed scroll direction(s)*/
|
||||
uint8_t event_dsc_cnt; /**< Number of event callbacks stored in `event_dsc` array*/
|
||||
} _lv_obj_spec_attr_t;
|
||||
|
||||
typedef struct _lv_obj_t {
|
||||
const lv_obj_class_t * class_p;
|
||||
struct _lv_obj_t * parent;
|
||||
_lv_obj_spec_attr_t * spec_attr;
|
||||
_lv_obj_style_t * styles;
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
lv_area_t coords;
|
||||
lv_obj_flag_t flags;
|
||||
lv_state_t state;
|
||||
uint16_t layout_inv : 1;
|
||||
uint16_t scr_layout_inv : 1;
|
||||
uint16_t skip_trans : 1;
|
||||
uint16_t style_cnt : 6;
|
||||
uint16_t h_layout : 1;
|
||||
uint16_t w_layout : 1;
|
||||
} lv_obj_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize LVGL library.
|
||||
* Should be called before any other LVGL related function.
|
||||
*/
|
||||
void lv_init(void);
|
||||
|
||||
#if LV_ENABLE_GC || !LV_MEM_CUSTOM || LV_USE_GPU_SDL
|
||||
|
||||
/**
|
||||
* Deinit the 'lv' library
|
||||
* Currently only implemented when not using custom allocators, or GC is enabled.
|
||||
*/
|
||||
void lv_deinit(void);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns whether the 'lv' library is currently initialized
|
||||
*/
|
||||
bool lv_is_initialized(void);
|
||||
|
||||
/**
|
||||
* Create a base object (a rectangle)
|
||||
* @param parent pointer to a parent object. If NULL then a screen will be created.
|
||||
* @return pointer to the new object
|
||||
*/
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent);
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set one or more flags
|
||||
* @param obj pointer to an object
|
||||
* @param f R-ed values from `lv_obj_flag_t` to set.
|
||||
*/
|
||||
void lv_obj_add_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Clear one or more flags
|
||||
* @param obj pointer to an object
|
||||
* @param f OR-ed values from `lv_obj_flag_t` to set.
|
||||
*/
|
||||
void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
|
||||
/**
|
||||
* Add one or more states to the object. The other state bits will remain unchanged.
|
||||
* If specified in the styles, transition animation will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
|
||||
*/
|
||||
void lv_obj_add_state(lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Remove one or more states to the object. The other state bits will remain unchanged.
|
||||
* If specified in the styles, transition animation will be started from the previous state to the current.
|
||||
* @param obj pointer to an object
|
||||
* @param state the states to add. E.g `LV_STATE_PRESSED | LV_STATE_FOCUSED`
|
||||
*/
|
||||
void lv_obj_clear_state(lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Set the user_data field of the object
|
||||
* @param obj pointer to an object
|
||||
* @param user_data pointer to the new user_data.
|
||||
*/
|
||||
#if LV_USE_USER_DATA
|
||||
static inline void lv_obj_set_user_data(lv_obj_t * obj, void * user_data)
|
||||
{
|
||||
obj->user_data = user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
/**
|
||||
* Check if a given flag or all the given flags are set on an object.
|
||||
* @param obj pointer to an object
|
||||
* @param f the flag(s) to check (OR-ed values can be used)
|
||||
* @return true: all flags are set; false: not all flags are set
|
||||
*/
|
||||
bool lv_obj_has_flag(const lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Check if a given flag or any of the flags are set on an object.
|
||||
* @param obj pointer to an object
|
||||
* @param f the flag(s) to check (OR-ed values can be used)
|
||||
* @return true: at lest one flag flag is set; false: none of the flags are set
|
||||
*/
|
||||
bool lv_obj_has_flag_any(const lv_obj_t * obj, lv_obj_flag_t f);
|
||||
|
||||
/**
|
||||
* Get the state of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the state (OR-ed values from `lv_state_t`)
|
||||
*/
|
||||
lv_state_t lv_obj_get_state(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check if the object is in a given state or not.
|
||||
* @param obj pointer to an object
|
||||
* @param state a state or combination of states to check
|
||||
* @return true: `obj` is in `state`; false: `obj` is not in `state`
|
||||
*/
|
||||
bool lv_obj_has_state(const lv_obj_t * obj, lv_state_t state);
|
||||
|
||||
/**
|
||||
* Get the group of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the pointer to group of the object
|
||||
*/
|
||||
void * lv_obj_get_group(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the user_data field of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the pointer to the user_data of the object
|
||||
*/
|
||||
#if LV_USE_USER_DATA
|
||||
static inline void * lv_obj_get_user_data(lv_obj_t * obj)
|
||||
{
|
||||
return obj->user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* Other functions
|
||||
*======================*/
|
||||
|
||||
/**
|
||||
* Allocate special data for an object if not allocated yet.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_allocate_spec_attr(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check the type of obj.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p a class to check (e.g. `lv_slider_class`)
|
||||
* @return true: `class_p` is the `obj` class.
|
||||
*/
|
||||
bool lv_obj_check_type(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Check if any object has a given class (type).
|
||||
* It checks the ancestor classes too.
|
||||
* @param obj pointer to an object
|
||||
* @param class_p a class to check (e.g. `lv_slider_class`)
|
||||
* @return true: `obj` has the given class
|
||||
*/
|
||||
bool lv_obj_has_class(const lv_obj_t * obj, const lv_obj_class_t * class_p);
|
||||
|
||||
/**
|
||||
* Get the class (type) of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the class (type) of the object
|
||||
*/
|
||||
const lv_obj_class_t * lv_obj_get_class(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check if any object is still "alive".
|
||||
* @param obj pointer to an object
|
||||
* @return true: valid
|
||||
*/
|
||||
bool lv_obj_is_valid(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Scale the given number of pixels (a distance or size) relative to a 160 DPI display
|
||||
* considering the DPI of the `obj`'s display.
|
||||
* It ensures that e.g. `lv_dpx(100)` will have the same physical size regardless to the
|
||||
* DPI of the display.
|
||||
* @param obj an object whose display's dpi should be considered
|
||||
* @param n the number of pixels to scale
|
||||
* @return `n x current_dpi/160`
|
||||
*/
|
||||
static inline lv_coord_t lv_obj_dpx(const lv_obj_t * obj, lv_coord_t n)
|
||||
{
|
||||
return _LV_DPX_CALC(lv_disp_get_dpi(lv_obj_get_disp(obj)), n);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_ASSERT_OBJ
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_class) \
|
||||
LV_ASSERT_MSG(obj_p != NULL, "The object is NULL"); \
|
||||
LV_ASSERT_MSG(lv_obj_has_class(obj_p, obj_class) == true, "Incompatible object type."); \
|
||||
LV_ASSERT_MSG(lv_obj_is_valid(obj_p) == true, "The object is invalid, deleted or corrupted?");
|
||||
|
||||
# else
|
||||
# define LV_ASSERT_OBJ(obj_p, obj_class) do{}while(0)
|
||||
#endif
|
||||
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_OBJ_CREATE
|
||||
# define LV_TRACE_OBJ_CREATE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
# define LV_TRACE_OBJ_CREATE(...)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_H*/
|
207
EC600U_lvgl_lib/lvgl/src/core/lv_obj_class.c
Normal file
207
EC600U_lvgl_lib/lvgl/src/core/lv_obj_class.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* @file lv_obj_class.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_theme.h"
|
||||
#include "ql_log.h"
|
||||
#define LOG_INFO(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "lvobjclass", msg, ##__VA_ARGS__)
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_construct(lv_obj_t * obj);
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_obj_t * lv_obj_class_create_obj(const lv_obj_class_t * class_p, lv_obj_t * parent)
|
||||
{
|
||||
LV_TRACE_OBJ_CREATE("Creating object with %p class on %p parent", (void *)class_p, (void *)parent);
|
||||
uint32_t s = get_instance_size(class_p);
|
||||
lv_obj_t * obj = lv_mem_alloc(s);
|
||||
if(obj == NULL) return NULL;
|
||||
lv_memset_00(obj, s);
|
||||
obj->class_p = class_p;
|
||||
obj->parent = parent;
|
||||
|
||||
/*Create a screen*/
|
||||
if(parent == NULL) {
|
||||
LV_TRACE_OBJ_CREATE("creating a screen");
|
||||
LOG_INFO("creating a screen");
|
||||
lv_disp_t * disp = lv_disp_get_default();
|
||||
if(!disp) {
|
||||
LV_LOG_WARN("No display created to so far. No place to assign the new screen");
|
||||
LOG_INFO("No display created to so far. No place to assign the new screen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(disp->screens == NULL) {
|
||||
LOG_INFO("disp->screens == NULL");
|
||||
disp->screens = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
disp->screens[0] = obj;
|
||||
disp->screen_cnt = 1;
|
||||
}
|
||||
else {
|
||||
LOG_INFO("disp->screens != NULL");
|
||||
disp->screen_cnt++;
|
||||
disp->screens = lv_mem_realloc(disp->screens, sizeof(lv_obj_t *) * disp->screen_cnt);
|
||||
disp->screens[disp->screen_cnt - 1] = obj;
|
||||
}
|
||||
|
||||
/*Set coordinates to full screen size*/
|
||||
obj->coords.x1 = 0;
|
||||
obj->coords.y1 = 0;
|
||||
obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
|
||||
obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
|
||||
LOG_INFO("x2 = %d, y2 = %d",obj->coords.x2,obj->coords.y2);
|
||||
}
|
||||
/*Create a normal object*/
|
||||
else {
|
||||
LV_TRACE_OBJ_CREATE("creating normal object");
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
if(parent->spec_attr == NULL) {
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
}
|
||||
|
||||
if(parent->spec_attr->children == NULL) {
|
||||
parent->spec_attr->children = lv_mem_alloc(sizeof(lv_obj_t *));
|
||||
parent->spec_attr->children[0] = obj;
|
||||
parent->spec_attr->child_cnt = 1;
|
||||
}
|
||||
else {
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
|
||||
sizeof(lv_obj_t *) * parent->spec_attr->child_cnt);
|
||||
parent->spec_attr->children[parent->spec_attr->child_cnt - 1] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void lv_obj_class_init_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
lv_obj_enable_style_refresh(false);
|
||||
|
||||
lv_theme_apply(obj);
|
||||
lv_obj_construct(obj);
|
||||
|
||||
lv_obj_enable_style_refresh(true);
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
|
||||
lv_obj_refresh_self_size(obj);
|
||||
|
||||
lv_group_t * def_group = lv_group_get_default();
|
||||
if(def_group && lv_obj_is_group_def(obj)) {
|
||||
lv_group_add_obj(def_group, obj);
|
||||
}
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) {
|
||||
/*Call the ancestor's event handler to the parent to notify it about the new child.
|
||||
*Also triggers layout update*/
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj);
|
||||
|
||||
/*Invalidate the area if not screen created*/
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void _lv_obj_destruct(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->class_p->destructor_cb) obj->class_p->destructor_cb(obj->class_p, obj);
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*Don't let the descendant methods run during destructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Call the base class's destructor too*/
|
||||
_lv_obj_destruct(obj);
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_is_editable(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which editable is set*/
|
||||
while(class_p && class_p->editable == LV_OBJ_CLASS_EDITABLE_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->editable == LV_OBJ_CLASS_EDITABLE_TRUE ? true : false;
|
||||
}
|
||||
|
||||
bool lv_obj_is_group_def(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * class_p = obj->class_p;
|
||||
|
||||
/*Find a base in which group_def is set*/
|
||||
while(class_p && class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_INHERIT) class_p = class_p->base_class;
|
||||
|
||||
if(class_p == NULL) return false;
|
||||
|
||||
return class_p->group_def == LV_OBJ_CLASS_GROUP_DEF_TRUE ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_construct(lv_obj_t * obj)
|
||||
{
|
||||
const lv_obj_class_t * original_class_p = obj->class_p;
|
||||
|
||||
if(obj->class_p->base_class) {
|
||||
/*Don't let the descendant methods run during constructing the ancestor type*/
|
||||
obj->class_p = obj->class_p->base_class;
|
||||
|
||||
/*Construct the base first*/
|
||||
lv_obj_construct(obj);
|
||||
}
|
||||
|
||||
/*Restore the original class*/
|
||||
obj->class_p = original_class_p;
|
||||
|
||||
if(obj->class_p->constructor_cb) obj->class_p->constructor_cb(obj->class_p, obj);
|
||||
}
|
||||
|
||||
static uint32_t get_instance_size(const lv_obj_class_t * class_p)
|
||||
{
|
||||
/*Find a base in which instance size is set*/
|
||||
const lv_obj_class_t * base = class_p;
|
||||
while(base && base->instance_size == 0) base = base->base_class;
|
||||
|
||||
if(base == NULL) return 0; /*Never happens: set at least in `lv_obj` class*/
|
||||
|
||||
return base->instance_size;
|
||||
}
|
94
EC600U_lvgl_lib/lvgl/src/core/lv_obj_class.h
Normal file
94
EC600U_lvgl_lib/lvgl/src/core/lv_obj_class.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file lv_obj_class.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_CLASS_H
|
||||
#define LV_OBJ_CLASS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
struct _lv_event_t;
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_CLASS_EDITABLE_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
|
||||
LV_OBJ_CLASS_EDITABLE_TRUE,
|
||||
LV_OBJ_CLASS_EDITABLE_FALSE,
|
||||
} lv_obj_class_editable_t;
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_CLASS_GROUP_DEF_INHERIT, /**< Check the base class. Must have 0 value to let zero initialized class inherit*/
|
||||
LV_OBJ_CLASS_GROUP_DEF_TRUE,
|
||||
LV_OBJ_CLASS_GROUP_DEF_FALSE,
|
||||
} lv_obj_class_group_def_t;
|
||||
|
||||
typedef void (*lv_obj_class_event_cb_t)(struct _lv_obj_class_t * class_p, struct _lv_event_t * e);
|
||||
/**
|
||||
* Describe the common methods of every object.
|
||||
* Similar to a C++ class.
|
||||
*/
|
||||
typedef struct _lv_obj_class_t {
|
||||
const struct _lv_obj_class_t * base_class;
|
||||
void (*constructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
|
||||
void (*destructor_cb)(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * obj);
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
void (*event_cb)(const struct _lv_obj_class_t * class_p,
|
||||
struct _lv_event_t * e); /**< Widget type specific event function*/
|
||||
lv_coord_t width_def;
|
||||
lv_coord_t height_def;
|
||||
uint32_t editable : 2; /**< Value from ::lv_obj_class_editable_t*/
|
||||
uint32_t group_def : 2; /**< Value from ::lv_obj_class_group_def_t*/
|
||||
uint32_t instance_size : 16;
|
||||
} lv_obj_class_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create an object form a class descriptor
|
||||
* @param class_p pointer to a class
|
||||
* @param parent pointer to an object where the new object should be created
|
||||
* @return pointer to the created object
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_class_create_obj(const struct _lv_obj_class_t * class_p, struct _lv_obj_t * parent);
|
||||
|
||||
void lv_obj_class_init_obj(struct _lv_obj_t * obj);
|
||||
|
||||
void _lv_obj_destruct(struct _lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_editable(struct _lv_obj_t * obj);
|
||||
|
||||
bool lv_obj_is_group_def(struct _lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_CLASS_H*/
|
369
EC600U_lvgl_lib/lvgl/src/core/lv_obj_draw.c
Normal file
369
EC600U_lvgl_lib/lvgl/src/core/lv_obj_draw.c
Normal file
@ -0,0 +1,369 @@
|
||||
/**
|
||||
* @file lv_obj_draw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_draw.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->radius = lv_obj_get_style_radius(obj, part);
|
||||
|
||||
lv_opa_t main_opa = part != LV_PART_MAIN ? lv_obj_get_style_opa(obj, part) : LV_OPA_COVER;
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa <= LV_OPA_MIN || main_opa <= LV_OPA_MIN) {
|
||||
draw_dsc->bg_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->border_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->shadow_opa = LV_OPA_TRANSP;
|
||||
draw_dsc->outline_opa = LV_OPA_TRANSP;
|
||||
return;
|
||||
}
|
||||
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
|
||||
if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
draw_dsc->bg_grad_dir = lv_obj_get_style_bg_grad_dir(obj, part);
|
||||
if(draw_dsc->bg_grad_dir != LV_GRAD_DIR_NONE) {
|
||||
draw_dsc->bg_grad_color = lv_obj_get_style_bg_grad_color_filtered(obj, part);
|
||||
draw_dsc->bg_main_color_stop = lv_obj_get_style_bg_main_stop(obj, part);
|
||||
draw_dsc->bg_grad_color_stop = lv_obj_get_style_bg_grad_stop(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(draw_dsc->outline_opa > LV_OPA_MIN) {
|
||||
draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->shadow_opa) {
|
||||
draw_dsc->shadow_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(draw_dsc->shadow_width) {
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(draw_dsc->shadow_opa > LV_OPA_MIN) {
|
||||
draw_dsc->shadow_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
draw_dsc->shadow_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
|
||||
draw_dsc->shadow_spread = lv_obj_get_style_shadow_spread(obj, part);
|
||||
draw_dsc->shadow_color = lv_obj_get_style_shadow_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(main_opa < LV_OPA_MAX) {
|
||||
opa = (uint16_t)((uint16_t) main_opa * opa) >> 8;
|
||||
}
|
||||
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->bg_opa = (uint16_t)((uint16_t)draw_dsc->bg_opa * opa) >> 8;
|
||||
draw_dsc->border_opa = (uint16_t)((uint16_t)draw_dsc->border_opa * opa) >> 8;
|
||||
draw_dsc->shadow_opa = (uint16_t)((uint16_t)draw_dsc->shadow_opa * opa) >> 8;
|
||||
draw_dsc->outline_opa = (uint16_t)((uint16_t)draw_dsc->outline_opa * opa) >> 8;
|
||||
}
|
||||
#else /*LV_DRAW_COMPLEX*/
|
||||
if(draw_dsc->bg_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_opa = lv_obj_get_style_bg_opa(obj, part);
|
||||
if(draw_dsc->bg_opa > LV_OPA_MIN) {
|
||||
draw_dsc->bg_color = lv_obj_get_style_bg_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->border_width = lv_obj_get_style_border_width(obj, part);
|
||||
if(draw_dsc->border_width) {
|
||||
if(draw_dsc->border_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->border_opa = lv_obj_get_style_border_opa(obj, part);
|
||||
if(draw_dsc->border_opa > LV_OPA_MIN) {
|
||||
draw_dsc->border_color = lv_obj_get_style_border_color_filtered(obj, part);
|
||||
draw_dsc->border_side = lv_obj_get_style_border_side(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_dsc->outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(draw_dsc->outline_width) {
|
||||
if(draw_dsc->outline_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(draw_dsc->outline_opa > LV_OPA_MIN) {
|
||||
draw_dsc->outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
draw_dsc->outline_color = lv_obj_get_style_outline_color_filtered(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_dsc->bg_img_opa != LV_OPA_TRANSP) {
|
||||
draw_dsc->bg_img_src = lv_obj_get_style_bg_img_src(obj, part);
|
||||
if(draw_dsc->bg_img_src) {
|
||||
draw_dsc->bg_img_opa = lv_obj_get_style_bg_img_opa(obj, part);
|
||||
if(draw_dsc->bg_img_opa > LV_OPA_MIN) {
|
||||
if(lv_img_src_get_type(draw_dsc->bg_img_src) == LV_IMG_SRC_SYMBOL) {
|
||||
draw_dsc->bg_img_symbol_font = lv_obj_get_style_text_font(obj, part);
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
}
|
||||
else {
|
||||
draw_dsc->bg_img_recolor = lv_obj_get_style_bg_img_recolor_filtered(obj, part);
|
||||
draw_dsc->bg_img_recolor_opa = lv_obj_get_style_bg_img_recolor_opa(obj, part);
|
||||
draw_dsc->bg_img_tiled = lv_obj_get_style_bg_img_tiled(obj, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_text_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_text_color_filtered(obj, part);
|
||||
draw_dsc->letter_space = lv_obj_get_style_text_letter_space(obj, part);
|
||||
draw_dsc->line_space = lv_obj_get_style_text_line_space(obj, part);
|
||||
draw_dsc->decor = lv_obj_get_style_text_decor(obj, part);
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
|
||||
draw_dsc->font = lv_obj_get_style_text_font(obj, part);
|
||||
|
||||
#if LV_USE_BIDI
|
||||
draw_dsc->bidi_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||
#endif
|
||||
|
||||
draw_dsc->align = lv_obj_get_style_text_align(obj, part);
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->opa = lv_obj_get_style_img_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa_scale = lv_obj_get_style_opa(obj, part);
|
||||
if(opa_scale < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->angle = 0;
|
||||
draw_dsc->zoom = LV_IMG_ZOOM_NONE;
|
||||
draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2;
|
||||
draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2;
|
||||
|
||||
draw_dsc->recolor_opa = lv_obj_get_style_img_recolor_opa(obj, part);
|
||||
if(draw_dsc->recolor_opa > 0) {
|
||||
draw_dsc->recolor = lv_obj_get_style_img_recolor_filtered(obj, part);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_line_dsc(lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->width = lv_obj_get_style_line_width(obj, part);
|
||||
if(draw_dsc->width == 0) return;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_line_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_line_color_filtered(obj, part);
|
||||
|
||||
draw_dsc->dash_width = lv_obj_get_style_line_dash_width(obj, part);
|
||||
if(draw_dsc->dash_width) {
|
||||
draw_dsc->dash_gap = lv_obj_get_style_line_dash_gap(obj, part);
|
||||
}
|
||||
|
||||
draw_dsc->round_start = lv_obj_get_style_line_rounded(obj, part);
|
||||
draw_dsc->round_end = draw_dsc->round_start;
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_arc_dsc(lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc)
|
||||
{
|
||||
draw_dsc->width = lv_obj_get_style_arc_width(obj, part);
|
||||
if(draw_dsc->width == 0) return;
|
||||
|
||||
draw_dsc->opa = lv_obj_get_style_arc_opa(obj, part);
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_opa_t opa = lv_obj_get_style_opa(obj, part);
|
||||
if(opa < LV_OPA_MAX) {
|
||||
draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa) >> 8;
|
||||
}
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
draw_dsc->color = lv_obj_get_style_arc_color_filtered(obj, part);
|
||||
draw_dsc->img_src = lv_obj_get_style_arc_img_src(obj, part);
|
||||
|
||||
draw_dsc->rounded = lv_obj_get_style_arc_rounded(obj, part);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
draw_dsc->blend_mode = lv_obj_get_style_blend_mode(obj, part);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_calculate_ext_draw_size(lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_coord_t s = 0;
|
||||
|
||||
lv_coord_t sh_width = lv_obj_get_style_shadow_width(obj, part);
|
||||
if(sh_width) {
|
||||
lv_opa_t sh_opa = lv_obj_get_style_shadow_opa(obj, part);
|
||||
if(sh_opa > LV_OPA_MIN) {
|
||||
sh_width = sh_width / 2 + 1; /*The blur adds only half width*/
|
||||
sh_width += lv_obj_get_style_shadow_spread(obj, part);
|
||||
lv_coord_t sh_ofs_x = lv_obj_get_style_shadow_ofs_x(obj, part);
|
||||
lv_coord_t sh_ofs_y = lv_obj_get_style_shadow_ofs_y(obj, part);
|
||||
sh_width += LV_MAX(LV_ABS(sh_ofs_x), LV_ABS(sh_ofs_y));
|
||||
s = LV_MAX(s, sh_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t outline_width = lv_obj_get_style_outline_width(obj, part);
|
||||
if(outline_width) {
|
||||
lv_opa_t outline_opa = lv_obj_get_style_outline_opa(obj, part);
|
||||
if(outline_opa > LV_OPA_MIN) {
|
||||
lv_coord_t outline_pad = lv_obj_get_style_outline_pad(obj, part);
|
||||
s = LV_MAX(s, outline_pad + outline_width);
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t w = lv_obj_get_style_transform_width(obj, part);
|
||||
lv_coord_t h = lv_obj_get_style_transform_height(obj, part);
|
||||
lv_coord_t wh = LV_MAX(w, h);
|
||||
if(wh > 0) s += wh;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, const lv_area_t * clip_area)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_obj_draw_part_dsc_t));
|
||||
dsc->clip_area = clip_area;
|
||||
}
|
||||
|
||||
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const lv_obj_class_t * class_p, uint32_t type)
|
||||
{
|
||||
if(dsc->class_p == class_p && dsc->type == type) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void lv_obj_refresh_ext_draw_size(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t s_old = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_coord_t s_new = 0;
|
||||
lv_event_send(obj, LV_EVENT_REFR_EXT_DRAW_SIZE, &s_new);
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
|
||||
/*Store the result if the special attrs already allocated*/
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
/*Allocate spec. attrs. only if the result is not zero.
|
||||
*Zero is the default value if the spec. attr. are not defined.*/
|
||||
else if(s_new != 0) {
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->ext_draw_size = s_new;
|
||||
}
|
||||
|
||||
if(s_new != s_old) lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
lv_coord_t _lv_obj_get_ext_draw_size(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->ext_draw_size;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
163
EC600U_lvgl_lib/lvgl/src/core/lv_obj_draw.h
Normal file
163
EC600U_lvgl_lib/lvgl/src/core/lv_obj_draw.h
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @file lv_obj_draw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_DRAW_H
|
||||
#define LV_OBJ_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
|
||||
/** Cover check results.*/
|
||||
typedef enum {
|
||||
LV_COVER_RES_COVER = 0,
|
||||
LV_COVER_RES_NOT_COVER = 1,
|
||||
LV_COVER_RES_MASKED = 2,
|
||||
} lv_cover_res_t;
|
||||
|
||||
typedef struct {
|
||||
const lv_area_t * clip_area; /**< The current clip area, required if you need to draw something in the event*/
|
||||
const struct _lv_obj_class_t * class_p; /**< The class that sent the event */
|
||||
uint32_t type; /**< The type if part being draw. Element of `lv_<name>_draw_part_type_t` */
|
||||
lv_area_t * draw_area; /**< The area of the part being drawn*/
|
||||
lv_draw_rect_dsc_t *
|
||||
rect_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for rectangle-like parts*/
|
||||
lv_draw_label_dsc_t *
|
||||
label_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for text-like parts*/
|
||||
lv_draw_line_dsc_t *
|
||||
line_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for line-like parts*/
|
||||
lv_draw_img_dsc_t *
|
||||
img_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for image-like parts*/
|
||||
lv_draw_arc_dsc_t *
|
||||
arc_dsc; /**< A draw descriptor that can be modified to changed what LVGL will draw. Set only for arc-like parts*/
|
||||
const lv_point_t *
|
||||
p1; /**< A point calculated during drawing. E.g. a point of chart or the center of an arc.*/
|
||||
const lv_point_t * p2; /**< A point calculated during drawing. E.g. a point of chart.*/
|
||||
char * text; /**< A text calculated during drawing. Can be modified. E.g. tick labels on a chart axis.*/
|
||||
uint32_t text_length; /**< Size of the text buffer containing null-terminated text string calculated during drawing.*/
|
||||
uint32_t part; /**< The current part for which the event is sent*/
|
||||
uint32_t id; /**< The index of the part. E.g. a button's index on button matrix or table cell index.*/
|
||||
lv_coord_t radius; /**< E.g. the radius of an arc (not the corner radius).*/
|
||||
int32_t value; /**< A value calculated during drawing. E.g. Chart's tick line value.*/
|
||||
const void * sub_part_ptr; /**< A pointer the identifies something in the part. E.g. chart series. */
|
||||
} lv_obj_draw_part_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize a rectangle draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* If an `..._opa` field is set to `LV_OPA_TRANSP` the related properties won't be initialized.
|
||||
* Should be initialized with `lv_draw_rect_dsc_init(draw_dsc)`.
|
||||
* @note Only the relevant fields will be set.
|
||||
* E.g. if `border width == 0` the other border properties won't be evaluated.
|
||||
*/
|
||||
void lv_obj_init_draw_rect_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_rect_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Initialize a label draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* If the `opa` field is set to or the property is equal to `LV_OPA_TRANSP` the rest won't be initialized.
|
||||
* Should be initialized with `lv_draw_label_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_label_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_label_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Initialize an image draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* Should be initialized with `lv_draw_image_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_img_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a line draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* Should be initialized with `lv_draw_line_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_line_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_line_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Initialize an arc draw descriptor from an object's styles in its current state
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object. E.g. `LV_PART_MAIN`, `LV_PART_SCROLLBAR`, `LV_PART_KNOB`, etc
|
||||
* @param draw_dsc the descriptor to initialize.
|
||||
* Should be initialized with `lv_draw_arc_dsc_init(draw_dsc)`.
|
||||
*/
|
||||
void lv_obj_init_draw_arc_dsc(struct _lv_obj_t * obj, uint32_t part, lv_draw_arc_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Get the required extra size (around the object's part) to draw shadow, outline, value etc.
|
||||
* @param obj pointer to an object
|
||||
* @param part part of the object
|
||||
* @return the extra size required around the object
|
||||
*/
|
||||
lv_coord_t lv_obj_calculate_ext_draw_size(struct _lv_obj_t * obj, uint32_t part);
|
||||
|
||||
/**
|
||||
* Initialize a draw descriptor used in events.
|
||||
* @param dsc pointer to a descriptor. Later it should be passed as parameter to an `LV_EEVNT_DRAW_PART_BEGIN/END` event.
|
||||
* @param clip_area the current clip area of the drawing
|
||||
*/
|
||||
void lv_obj_draw_dsc_init(lv_obj_draw_part_dsc_t * dsc, const lv_area_t * clip_area);
|
||||
|
||||
/**
|
||||
* Check the type obj a part draw descriptor
|
||||
* @param dsc the descriptor (normally the event parameter)
|
||||
* @param class_p pointer to class to which `type` is related
|
||||
* @param type element of `lv_<name>_draw_part_type_t`
|
||||
* @return true if ::dsc is related to ::class_p and ::type
|
||||
*/
|
||||
bool lv_obj_draw_part_check_type(lv_obj_draw_part_dsc_t * dsc, const struct _lv_obj_class_t * class_p, uint32_t type);
|
||||
|
||||
/**
|
||||
* Send a 'LV_EVENT_REFR_EXT_DRAW_SIZE' Call the ancestor's event handler to the object to refresh the value of the extended draw size.
|
||||
* The result will be saved in `obj`.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_refresh_ext_draw_size(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the extended draw area of an object.
|
||||
* @param obj pointer to an object
|
||||
* @return the size extended draw area around the real coordinates
|
||||
*/
|
||||
lv_coord_t _lv_obj_get_ext_draw_size(const struct _lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_DRAW_H*/
|
1083
EC600U_lvgl_lib/lvgl/src/core/lv_obj_pos.c
Normal file
1083
EC600U_lvgl_lib/lvgl/src/core/lv_obj_pos.c
Normal file
File diff suppressed because it is too large
Load Diff
405
EC600U_lvgl_lib/lvgl/src/core/lv_obj_pos.h
Normal file
405
EC600U_lvgl_lib/lvgl/src/core/lv_obj_pos.h
Normal file
@ -0,0 +1,405 @@
|
||||
/**
|
||||
* @file lv_obj_pos.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_POS_H
|
||||
#define LV_OBJ_POS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef void (*lv_layout_update_cb_t)(struct _lv_obj_t *, void * user_data);
|
||||
typedef struct {
|
||||
lv_layout_update_cb_t cb;
|
||||
void * user_data;
|
||||
} lv_layout_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Set the relative the position of an object (relative to the parent's top left corner)
|
||||
* @param obj pointer to an object
|
||||
* @param x new distance from the left side of the parent plus the parent's left padding
|
||||
* @param y new distance from the top side of the parent plus the parent's right padding
|
||||
*/
|
||||
void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the x coordinate of a object
|
||||
* @param obj pointer to an object
|
||||
* @param x new distance from the left side from the parent plus the parent's left padding
|
||||
*/
|
||||
void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x);
|
||||
|
||||
/**
|
||||
* Set the y coordinate of a object
|
||||
* @param obj pointer to an object
|
||||
* @param y new distance from the top of the parent plus the parent's top padding
|
||||
*/
|
||||
void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the size of an object.
|
||||
* @param obj pointer to an object
|
||||
* @param w the new width
|
||||
* @param h the new height
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* LV_SIZE_PCT(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Recalculate the size of the object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the size has been changed
|
||||
*/
|
||||
bool lv_obj_refr_size(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @param w the new width
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w);
|
||||
|
||||
/**
|
||||
* Set the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @param h the new height
|
||||
* @note possible values are:
|
||||
* pixel simple set the size accordingly
|
||||
* LV_SIZE_CONTENT set the size to involve all children in the given direction
|
||||
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
|
||||
* x should be in [0..1000]% range
|
||||
*/
|
||||
void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Set the width reduced by the left and right padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @param w the width without paddings in pixels
|
||||
*/
|
||||
void lv_obj_set_content_width(struct _lv_obj_t * obj, lv_coord_t w);
|
||||
|
||||
/**
|
||||
* Set the height reduced by the top and bottom padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @param h the height without paddings in pixels
|
||||
*/
|
||||
void lv_obj_set_content_height(struct _lv_obj_t * obj, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Set a layout for an object
|
||||
* @param obj pointer to an object
|
||||
* @param layout pointer to a layout descriptor to set
|
||||
*/
|
||||
void lv_obj_set_layout(struct _lv_obj_t * obj, uint32_t layout);
|
||||
|
||||
/**
|
||||
* Test whether the and object is positioned by a layout or not
|
||||
* @param obj pointer to an object to test
|
||||
* @return true: positioned by a layout; false: not positioned by a layout
|
||||
*/
|
||||
bool lv_obj_is_layout_positioned(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Mark the object for layout update.
|
||||
* @param obj pointer to an object whose children needs to be updated
|
||||
*/
|
||||
void lv_obj_mark_layout_as_dirty(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Update the layout of an object.
|
||||
* @param obj pointer to an object whose children needs to be updated
|
||||
*/
|
||||
void lv_obj_update_layout(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Regsiter a new layout
|
||||
* @param cb the layout update callback
|
||||
* @param user_data custom data that will be passed to `cb`
|
||||
* @return the ID of the new layout
|
||||
*/
|
||||
uint32_t lv_layout_register(lv_layout_update_cb_t cb, void * user_data);
|
||||
|
||||
/**
|
||||
* Change the alignment of an object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
|
||||
*/
|
||||
void lv_obj_set_align(struct _lv_obj_t * obj, lv_align_t align);
|
||||
|
||||
/**
|
||||
* Change the alignment of an object and set new coordinates.
|
||||
* Equivalent to:
|
||||
* lv_obj_set_align(obj, align);
|
||||
* lv_obj_set_pos(obj, x_ofs, y_ofs);
|
||||
* @param obj pointer to an object to align
|
||||
* @param align type of alignment (see 'lv_align_t' enum) `LV_ALIGN_OUT_...` can't be used.
|
||||
* @param x_ofs x coordinate offset after alignment
|
||||
* @param y_ofs y coordinate offset after alignment
|
||||
*/
|
||||
void lv_obj_align(struct _lv_obj_t * obj, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs);
|
||||
|
||||
/**
|
||||
* Align an object to an other object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param base pointer to an other object (if NULL `obj`s parent is used). 'obj' will be aligned to it.
|
||||
* @param align type of alignment (see 'lv_align_t' enum)
|
||||
* @param x_ofs x coordinate offset after alignment
|
||||
* @param y_ofs y coordinate offset after alignment
|
||||
* @note if the position or size of `base` changes `obj` needs to be aligned manually again
|
||||
*/
|
||||
void lv_obj_align_to(struct _lv_obj_t * obj, const struct _lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs,
|
||||
lv_coord_t y_ofs);
|
||||
|
||||
/**
|
||||
* Align an object to the center on its parent.
|
||||
* @param obj pointer to an object to align
|
||||
* @note if the parent size changes `obj` needs to be aligned manually again
|
||||
*/
|
||||
static inline void lv_obj_center(struct _lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_align(obj, LV_ALIGN_CENTER, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the coordinates of an object to an area
|
||||
* @param obj pointer to an object
|
||||
* @param coords pointer to an area to store the coordinates
|
||||
*/
|
||||
void lv_obj_get_coords(const struct _lv_obj_t * obj, lv_area_t * coords);
|
||||
|
||||
/**
|
||||
* Get the x coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the left side of its parent plus the parent's left padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the left padding of the parent, and not on the left edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the x2 coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the right side of its parent plus the parent's right padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the right padding of the parent, and not on the right edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x2(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the y coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the top side of its parent plus the parent's top padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the top padding of the parent, and not on the top edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the y2 coordinate of object.
|
||||
* @param obj pointer to an object
|
||||
* @return distance of `obj` from the bottom side of its parent plus the parent's bottom padding
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @note Zero return value means the object is on the bottom padding of the parent, and not on the bottom edge.
|
||||
* @note Scrolling of the parent doesn't change the returned value.
|
||||
* @note The returned value is always the distance from the parent even if `obj` is positioned by a layout.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y2(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the width in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_width(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the height in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_height(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the width reduced by the left and right padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the width which still fits into its parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
lv_coord_t lv_obj_get_content_width(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height reduced by the top and bottom padding and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @return the height which still fits into the parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
lv_coord_t lv_obj_get_content_height(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the area reduced by the paddings and the border width.
|
||||
* @param obj pointer to an object
|
||||
* @note The position of the object is recalculated only on the next redraw. To force coordinate recalculation
|
||||
* call `lv_obj_update_layout(obj)`.
|
||||
* @param area the area which still fits into the parent without causing overflow (making the parent scrollable)
|
||||
*/
|
||||
void lv_obj_get_content_coords(const struct _lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Get the width occupied by the "parts" of the widget. E.g. the width of all columns of a table.
|
||||
* @param obj pointer to an objects
|
||||
* @return the width of the virtually drawn content
|
||||
* @note This size independent from the real size of the widget.
|
||||
* It just tells how large the internal ("virtual") content is.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_self_width(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height occupied by the "parts" of the widget. E.g. the height of all rows of a table.
|
||||
* @param obj pointer to an objects
|
||||
* @return the width of the virtually drawn content
|
||||
* @note This size independent from the real size of the widget.
|
||||
* It just tells how large the internal ("virtual") content is.
|
||||
*/
|
||||
lv_coord_t lv_obj_get_self_height(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Handle if the size of the internal ("virtual") content of an object has changed.
|
||||
* @param obj pointer to an object
|
||||
* @return false: nothing happened; true: refresh happened
|
||||
*/
|
||||
bool lv_obj_refresh_self_size(struct _lv_obj_t * obj);
|
||||
|
||||
void lv_obj_refr_pos(struct _lv_obj_t * obj);
|
||||
|
||||
void lv_obj_move_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
|
||||
void lv_obj_move_children_by(struct _lv_obj_t * obj, lv_coord_t x_diff, lv_coord_t y_diff, bool ignore_floating);
|
||||
|
||||
/**
|
||||
* Mark an area of an object as invalid.
|
||||
* The area will be truncated to the object's area and marked for redraw.
|
||||
* @param obj pointer to an object
|
||||
* @param area the area to redraw
|
||||
*/
|
||||
void lv_obj_invalidate_area(const struct _lv_obj_t * obj, const lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Mark the object as invalid to redrawn its area
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_invalidate(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Tell whether an area of an object is visible (even partially) now or not
|
||||
* @param obj pointer to an object
|
||||
* @param area the are to check. The visible part of the area will be written back here.
|
||||
* @return true visible; false not visible (hidden, out of parent, on other screen, etc)
|
||||
*/
|
||||
bool lv_obj_area_is_visible(const struct _lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Tell whether an object is visible (even partially) now or not
|
||||
* @param obj pointer to an object
|
||||
* @return true: visible; false not visible (hidden, out of parent, on other screen, etc)
|
||||
*/
|
||||
bool lv_obj_is_visible(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set the size of an extended clickable area
|
||||
* @param obj pointer to an object
|
||||
* @param size extended clickable area in all 4 directions [px]
|
||||
*/
|
||||
void lv_obj_set_ext_click_area(struct _lv_obj_t * obj, lv_coord_t size);
|
||||
|
||||
/**
|
||||
* Get the an area where to object can be clicked.
|
||||
* It's the object's normal area plus the extended click area.
|
||||
* @param obj pointer to an object
|
||||
* @param area store the result area here
|
||||
*/
|
||||
void lv_obj_get_click_area(const struct _lv_obj_t * obj, lv_area_t * area);
|
||||
|
||||
/**
|
||||
* Hit-test an object given a particular point in screen space.
|
||||
* @param obj object to hit-test
|
||||
* @param point screen-space point (absolute coordinate)
|
||||
* @return true: if the object is considered under the point
|
||||
*/
|
||||
bool lv_obj_hit_test(struct _lv_obj_t * obj, const lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Clamp a width between min and max width. If the min/max width is in percentage value use the ref_width
|
||||
* @param width width to clamp
|
||||
* @param min_width the minimal width
|
||||
* @param max_width the maximal width
|
||||
* @param ref_width the reference width used when min/max width is in percentage
|
||||
* @return the clamped width
|
||||
*/
|
||||
lv_coord_t lv_clamp_width(lv_coord_t width, lv_coord_t min_width, lv_coord_t max_width, lv_coord_t ref_width);
|
||||
|
||||
/**
|
||||
* Clamp a height between min and max height. If the min/max height is in percentage value use the ref_height
|
||||
* @param height height to clamp
|
||||
* @param min_height the minimal height
|
||||
* @param max_height the maximal height
|
||||
* @param ref_height the reference height used when min/max height is in percentage
|
||||
* @return the clamped height
|
||||
*/
|
||||
lv_coord_t lv_clamp_height(lv_coord_t height, lv_coord_t min_height, lv_coord_t max_height, lv_coord_t ref_height);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_POS_H*/
|
758
EC600U_lvgl_lib/lvgl/src/core/lv_obj_scroll.c
Normal file
758
EC600U_lvgl_lib/lvgl/src/core/lv_obj_scroll.c
Normal file
@ -0,0 +1,758 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj_scroll.h"
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "lv_disp.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
#define SCROLL_ANIM_TIME_MIN 200 /*ms*/
|
||||
#define SCROLL_ANIM_TIME_MAX 400 /*ms*/
|
||||
#define SCROLLBAR_MIN_SIZE (LV_DPX(10))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
static void scroll_x_anim(void * obj, int32_t v);
|
||||
static void scroll_y_anim(void * obj, int32_t v);
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a);
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_set_scrollbar_mode(lv_obj_t * obj, lv_scrollbar_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(obj->spec_attr->scrollbar_mode == mode) return;
|
||||
obj->spec_attr->scrollbar_mode = mode;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_dir(lv_obj_t * obj, lv_dir_t dir)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
if(dir != obj->spec_attr->scroll_dir) {
|
||||
obj->spec_attr->scroll_dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_x(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_x = align;
|
||||
}
|
||||
|
||||
void lv_obj_set_scroll_snap_y(lv_obj_t * obj, lv_scroll_snap_t align)
|
||||
{
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
obj->spec_attr->scroll_snap_y = align;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scrollbar_mode;
|
||||
else return LV_SCROLLBAR_MODE_AUTO;
|
||||
}
|
||||
|
||||
lv_dir_t lv_obj_get_scroll_dir(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_dir;
|
||||
else return LV_DIR_ALL;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_snap_x;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr) return obj->spec_attr->scroll_snap_y;
|
||||
else return LV_SCROLL_SNAP_NONE;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_x(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_y(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj)
|
||||
{
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.y;
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.y2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.y2 - pad_bottom - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_h = lv_obj_get_self_height(obj);
|
||||
self_h = self_h - (lv_obj_get_height(obj) - pad_top - pad_bottom - 2 * border_width);
|
||||
self_h -= lv_obj_get_scroll_y(obj);
|
||||
return LV_MAX(child_res, self_h);
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*Normally can't scroll the object out on the left.
|
||||
*So simply use the current scroll position as "left size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return -obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With RTL base direction scrolling the left is normal so find the left most coordinate*/
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
lv_coord_t child_res = 0;
|
||||
|
||||
uint32_t i;
|
||||
lv_coord_t x1 = LV_COORD_MAX;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
x1 = LV_MIN(x1, child->coords.x1);
|
||||
|
||||
}
|
||||
|
||||
if(x1 != LV_COORD_MAX) {
|
||||
child_res = x1;
|
||||
child_res = (obj->coords.x1 + pad_left + border_width) - child_res;
|
||||
}
|
||||
else {
|
||||
child_res = LV_COORD_MIN;
|
||||
}
|
||||
|
||||
lv_coord_t self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w += lv_obj_get_scroll_x(obj);
|
||||
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
/*With RTL base dir can't scroll to the object out on the right.
|
||||
*So simply use the current scroll position as "right size"*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->scroll.x;
|
||||
}
|
||||
|
||||
/*With other base direction (LTR) scrolling to the right is normal so find the right most coordinate*/
|
||||
lv_coord_t child_res = LV_COORD_MIN;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
if(lv_obj_has_flag_any(child, LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
child_res = LV_MAX(child_res, child->coords.x2);
|
||||
}
|
||||
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(obj, LV_PART_MAIN);
|
||||
|
||||
if(child_res != LV_COORD_MIN) {
|
||||
child_res -= (obj->coords.x2 - pad_right - border_width);
|
||||
}
|
||||
|
||||
lv_coord_t self_w;
|
||||
self_w = lv_obj_get_self_width(obj);
|
||||
self_w = self_w - (lv_obj_get_width(obj) - pad_right - pad_left - 2 * border_width);
|
||||
self_w -= lv_obj_get_scroll_x(obj);
|
||||
return LV_MAX(child_res, self_w);
|
||||
}
|
||||
|
||||
void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end)
|
||||
{
|
||||
lv_anim_t * a;
|
||||
a = lv_anim_get(obj, scroll_x_anim);
|
||||
end->x = a ? -a->end_value : lv_obj_get_scroll_x(obj);
|
||||
|
||||
a = lv_anim_get(obj, scroll_y_anim);
|
||||
end->y = a ? -a->end_value : lv_obj_get_scroll_y(obj);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
if(x == 0 && y == 0) return;
|
||||
if(anim_en == LV_ANIM_ON) {
|
||||
lv_disp_t * d = lv_obj_get_disp(obj);
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_ready_cb(&a, scroll_anim_ready_cb);
|
||||
|
||||
if(x) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_hor_res(d) * 2) >> 2, 0, x);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_t sx = lv_obj_get_scroll_x(obj);
|
||||
lv_anim_set_values(&a, -sx, -sx + x);
|
||||
lv_anim_set_exec_cb(&a, scroll_x_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
if(y) {
|
||||
uint32_t t = lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 2) >> 2, 0, y);
|
||||
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
|
||||
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
|
||||
lv_anim_set_time(&a, t);
|
||||
lv_coord_t sy = lv_obj_get_scroll_y(obj);
|
||||
lv_anim_set_values(&a, -sy, -sy + y);
|
||||
lv_anim_set_exec_cb(&a, scroll_y_anim);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_BEGIN, &a);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Remove pending animations*/
|
||||
bool y_del = lv_anim_del(obj, scroll_y_anim);
|
||||
bool x_del = lv_anim_del(obj, scroll_x_anim);
|
||||
scroll_by_raw(obj, x, y);
|
||||
if(y_del || x_del) {
|
||||
lv_res_t res;
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_scroll_to_x(obj, x, anim_en);
|
||||
lv_obj_scroll_to_y(obj, y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_x_anim);
|
||||
|
||||
/*Don't let scroll more then naturally possible by the size of the content*/
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
if(x < 0) x = 0;
|
||||
if(x > 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x > scroll_max) x = scroll_max;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(x > 0) x = 0;
|
||||
if(x < 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_left(obj) + lv_obj_get_scroll_right(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
|
||||
if(x < -scroll_max) x = -scroll_max;
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t scroll_x = lv_obj_get_scroll_x(obj);
|
||||
lv_coord_t diff = -x + scroll_x;
|
||||
|
||||
lv_obj_scroll_by(obj, diff, 0, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_y(lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_anim_del(obj, scroll_y_anim);
|
||||
|
||||
/*Don't let scroll more then naturally possible by the size of the content*/
|
||||
if(y < 0) y = 0;
|
||||
if(y > 0) {
|
||||
lv_coord_t scroll_max = lv_obj_get_scroll_top(obj) + lv_obj_get_scroll_bottom(obj);
|
||||
if(scroll_max < 0) scroll_max = 0;
|
||||
if(y > scroll_max) y = scroll_max;
|
||||
}
|
||||
|
||||
lv_coord_t scroll_y = lv_obj_get_scroll_y(obj);
|
||||
lv_coord_t diff = -y + scroll_y;
|
||||
|
||||
lv_obj_scroll_by(obj, 0, diff, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
scroll_area_into_view(&obj->coords, obj, &p, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_scroll_to_view_recursive(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the screens layout is correct*/
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
lv_point_t p = {0, 0};
|
||||
lv_obj_t * child = obj;
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
while(parent) {
|
||||
scroll_area_into_view(&obj->coords, child, &p, anim_en);
|
||||
child = parent;
|
||||
parent = lv_obj_get_parent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_obj_is_scrolling(const lv_obj_t * obj)
|
||||
{
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) return true;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lv_obj_update_snap(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_update_layout(obj);
|
||||
lv_point_t p;
|
||||
lv_indev_scroll_get_snap_dist(obj, &p);
|
||||
lv_obj_scroll_by(obj, p.x, p.y, anim_en);
|
||||
}
|
||||
|
||||
void lv_obj_get_scrollbar_area(lv_obj_t * obj, lv_area_t * hor_area, lv_area_t * ver_area)
|
||||
{
|
||||
lv_area_set(hor_area, 0, 0, -1, -1);
|
||||
lv_area_set(ver_area, 0, 0, -1, -1);
|
||||
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_SCROLLABLE) == false) return;
|
||||
|
||||
lv_dir_t sm = lv_obj_get_scrollbar_mode(obj);
|
||||
if(sm == LV_SCROLLBAR_MODE_OFF) return;
|
||||
|
||||
/*If there is no indev scrolling this object but `mode==active` return*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
if(sm == LV_SCROLLBAR_MODE_ACTIVE) {
|
||||
while(indev) {
|
||||
if(lv_indev_get_scroll_obj(indev) == obj) break;
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
if(indev == NULL) return;
|
||||
}
|
||||
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
|
||||
lv_dir_t dir = lv_obj_get_scroll_dir(obj);
|
||||
|
||||
bool ver_draw = false;
|
||||
if((dir & LV_DIR_VER) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (st > 0 || sb > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_VER))) {
|
||||
ver_draw = true;
|
||||
}
|
||||
|
||||
|
||||
bool hor_draw = false;
|
||||
if((dir & LV_DIR_HOR) &&
|
||||
((sm == LV_SCROLLBAR_MODE_ON) ||
|
||||
(sm == LV_SCROLLBAR_MODE_AUTO && (sl > 0 || sr > 0)) ||
|
||||
(sm == LV_SCROLLBAR_MODE_ACTIVE && lv_indev_get_scroll_dir(indev) == LV_DIR_HOR))) {
|
||||
hor_draw = true;
|
||||
}
|
||||
|
||||
if(!hor_draw && !ver_draw) return;
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(obj, LV_PART_SCROLLBAR) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t end_space = lv_obj_get_style_pad_top(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t side_space = lv_obj_get_style_pad_right(obj, LV_PART_SCROLLBAR);
|
||||
lv_coord_t tickness = lv_obj_get_style_width(obj, LV_PART_SCROLLBAR);
|
||||
|
||||
lv_coord_t obj_h = lv_obj_get_height(obj);
|
||||
lv_coord_t obj_w = lv_obj_get_width(obj);
|
||||
|
||||
lv_coord_t ver_reg_space = ver_draw ? tickness + side_space : 0;
|
||||
lv_coord_t hor_req_space = hor_draw ? tickness + side_space : 0;
|
||||
lv_coord_t rem;
|
||||
|
||||
if(lv_obj_get_style_bg_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN &&
|
||||
lv_obj_get_style_border_opa(obj, LV_PART_SCROLLBAR) < LV_OPA_MIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
lv_coord_t content_h = obj_h + st + sb;
|
||||
if(ver_draw && content_h) {
|
||||
ver_area->y1 = obj->coords.y1;
|
||||
ver_area->y2 = obj->coords.y2;
|
||||
if(rtl) {
|
||||
ver_area->x1 = obj->coords.x1 + side_space;
|
||||
ver_area->x2 = ver_area->x1 + tickness - 1;
|
||||
}
|
||||
else {
|
||||
ver_area->x2 = obj->coords.x2 - side_space;
|
||||
ver_area->x1 = ver_area->x2 - tickness + 1;
|
||||
}
|
||||
|
||||
lv_coord_t sb_h = ((obj_h - end_space * 2 - hor_req_space) * obj_h) / content_h;
|
||||
sb_h = LV_MAX(sb_h, SCROLLBAR_MIN_SIZE);
|
||||
rem = (obj_h - end_space * 2 - hor_req_space) -
|
||||
sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_h <= 0) {
|
||||
ver_area->y1 = obj->coords.y1 + end_space;
|
||||
ver_area->y2 = obj->coords.y2 - end_space - hor_req_space - 1;
|
||||
}
|
||||
else {
|
||||
lv_coord_t sb_y = (rem * sb) / scroll_h;
|
||||
sb_y = rem - sb_y;
|
||||
|
||||
ver_area->y1 = obj->coords.y1 + sb_y + end_space;
|
||||
ver_area->y2 = ver_area->y1 + sb_h - 1;
|
||||
if(ver_area->y1 < obj->coords.y1 + end_space) {
|
||||
ver_area->y1 = obj->coords.y1 + end_space;
|
||||
if(ver_area->y1 + SCROLLBAR_MIN_SIZE > ver_area->y2)ver_area->y2 = ver_area->y1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
if(ver_area->y2 > obj->coords.y2 - hor_req_space - end_space) {
|
||||
ver_area->y2 = obj->coords.y2 - hor_req_space - end_space;
|
||||
if(ver_area->y2 - SCROLLBAR_MIN_SIZE < ver_area->y1)ver_area->y1 = ver_area->y2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Draw horizontal scrollbar if the mode is ON or can be scrolled in this direction*/
|
||||
lv_coord_t content_w = obj_w + sl + sr;
|
||||
if(hor_draw && content_w) {
|
||||
hor_area->y2 = obj->coords.y2 - side_space;
|
||||
hor_area->y1 = hor_area->y2 - tickness + 1;
|
||||
hor_area->x1 = obj->coords.x1;
|
||||
hor_area->x2 = obj->coords.x2;
|
||||
|
||||
lv_coord_t sb_w = ((obj_w - end_space * 2 - ver_reg_space) * obj_w) / content_w;
|
||||
sb_w = LV_MAX(sb_w, SCROLLBAR_MIN_SIZE);
|
||||
rem = (obj_w - end_space * 2 - ver_reg_space) -
|
||||
sb_w; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
|
||||
lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/
|
||||
if(scroll_w <= 0) {
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + end_space + ver_reg_space - 1;
|
||||
hor_area->x2 = obj->coords.x2 - end_space;
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + end_space;
|
||||
hor_area->x2 = obj->coords.x2 - end_space - ver_reg_space - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t sb_x = (rem * sr) / scroll_w;
|
||||
sb_x = rem - sb_x;
|
||||
|
||||
if(rtl) {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + end_space + ver_reg_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + end_space + ver_reg_space) {
|
||||
hor_area->x1 = obj->coords.x1 + end_space + ver_reg_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - end_space) {
|
||||
hor_area->x2 = obj->coords.x2 - end_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
hor_area->x1 = obj->coords.x1 + sb_x + end_space;
|
||||
hor_area->x2 = hor_area->x1 + sb_w - 1;
|
||||
if(hor_area->x1 < obj->coords.x1 + end_space) {
|
||||
hor_area->x1 = obj->coords.x1 + end_space;
|
||||
if(hor_area->x1 + SCROLLBAR_MIN_SIZE > hor_area->x2) hor_area->x2 = hor_area->x1 + SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
if(hor_area->x2 > obj->coords.x2 - ver_reg_space - end_space) {
|
||||
hor_area->x2 = obj->coords.x2 - ver_reg_space - end_space;
|
||||
if(hor_area->x2 - SCROLLBAR_MIN_SIZE < hor_area->x1) hor_area->x1 = hor_area->x2 - SCROLLBAR_MIN_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_scrollbar_invalidate(lv_obj_t * obj)
|
||||
{
|
||||
lv_area_t hor_area;
|
||||
lv_area_t ver_area;
|
||||
lv_obj_get_scrollbar_area(obj, &hor_area, &ver_area);
|
||||
|
||||
if(lv_area_get_size(&hor_area) <= 0 && lv_area_get_size(&ver_area) <= 0) return;
|
||||
|
||||
if(lv_area_get_size(&hor_area) > 0) lv_obj_invalidate_area(obj, &hor_area);
|
||||
if(lv_area_get_size(&ver_area) > 0) lv_obj_invalidate_area(obj, &ver_area);
|
||||
}
|
||||
|
||||
void lv_obj_readjust_scroll(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
/*Be sure the bottom side is not remains scrolled in*/
|
||||
/*With snapping the content can't be scrolled in*/
|
||||
if(lv_obj_get_scroll_snap_y(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t st = lv_obj_get_scroll_top(obj);
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
|
||||
if(sb < 0 && st > 0) {
|
||||
sb = LV_MIN(st, -sb);
|
||||
lv_obj_scroll_by(obj, 0, sb, anim_en);
|
||||
}
|
||||
}
|
||||
|
||||
if(lv_obj_get_scroll_snap_x(obj) == LV_SCROLL_SNAP_NONE) {
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(obj);
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(obj);
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) != LV_BASE_DIR_RTL) {
|
||||
/*Be sure the left side is not remains scrolled in*/
|
||||
if(sr < 0 && sl > 0) {
|
||||
sr = LV_MIN(sl, -sr);
|
||||
lv_obj_scroll_by(obj, sr, 0, anim_en);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Be sure the right side is not remains scrolled in*/
|
||||
if(sl < 0 && sr > 0) {
|
||||
sr = LV_MIN(sr, -sl);
|
||||
lv_obj_scroll_by(obj, sl, 0, anim_en);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void scroll_by_raw(lv_obj_t * obj, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(x == 0 && y == 0) return;
|
||||
|
||||
lv_obj_allocate_spec_attr(obj);
|
||||
|
||||
obj->spec_attr->scroll.x += x;
|
||||
obj->spec_attr->scroll.y += y;
|
||||
|
||||
lv_obj_move_children_by(obj, x, y, true);
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_SCROLL, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
static void scroll_x_anim(void * obj, int32_t v)
|
||||
{
|
||||
scroll_by_raw(obj, v + lv_obj_get_scroll_x(obj), 0);
|
||||
}
|
||||
|
||||
static void scroll_y_anim(void * obj, int32_t v)
|
||||
{
|
||||
scroll_by_raw(obj, 0, v + lv_obj_get_scroll_y(obj));
|
||||
}
|
||||
|
||||
static void scroll_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_event_send(a->var, LV_EVENT_SCROLL_END, NULL);
|
||||
}
|
||||
|
||||
static void scroll_area_into_view(const lv_area_t * area, lv_obj_t * child, lv_point_t * scroll_value,
|
||||
lv_anim_enable_t anim_en)
|
||||
{
|
||||
lv_obj_t * parent = lv_obj_get_parent(child);
|
||||
if(!lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE)) return;
|
||||
|
||||
lv_dir_t scroll_dir = lv_obj_get_scroll_dir(parent);
|
||||
lv_coord_t snap_goal = 0;
|
||||
lv_coord_t act = 0;
|
||||
const lv_area_t * area_tmp;
|
||||
|
||||
lv_coord_t y_scroll = 0;
|
||||
lv_scroll_snap_t snap_y = lv_obj_get_scroll_snap_y(parent);
|
||||
if(snap_y != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(parent, LV_PART_MAIN);
|
||||
lv_coord_t ptop = lv_obj_get_style_pad_top(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pbottom = lv_obj_get_style_pad_bottom(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t top_diff = parent->coords.y1 + ptop - area_tmp->y1 - scroll_value->y;
|
||||
lv_coord_t bottom_diff = -(parent->coords.y2 - pbottom - area_tmp->y2 - scroll_value->y);
|
||||
lv_coord_t parent_h = lv_obj_get_height(parent) - ptop - pbottom;
|
||||
if((top_diff >= 0 && bottom_diff >= 0)) y_scroll = 0;
|
||||
else if(top_diff > 0) {
|
||||
y_scroll = top_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t st = lv_obj_get_scroll_top(parent);
|
||||
if(st - y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
else if(bottom_diff > 0) {
|
||||
y_scroll = -bottom_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sb = lv_obj_get_scroll_bottom(parent);
|
||||
if(sb + y_scroll < 0) y_scroll = 0;
|
||||
}
|
||||
|
||||
switch(snap_y) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.y1 + ptop;
|
||||
act = area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.y2 - pbottom;
|
||||
act = area_tmp->y2 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.y1 + ptop + parent_h / 2;
|
||||
act = lv_area_get_height(area_tmp) / 2 + area_tmp->y1 + y_scroll;
|
||||
y_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_coord_t x_scroll = 0;
|
||||
lv_scroll_snap_t snap_x = lv_obj_get_scroll_snap_x(parent);
|
||||
if(snap_x != LV_SCROLL_SNAP_NONE) area_tmp = &child->coords;
|
||||
else area_tmp = area;
|
||||
|
||||
lv_coord_t pleft = lv_obj_get_style_pad_left(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t pright = lv_obj_get_style_pad_right(parent, LV_PART_MAIN) + border_width;
|
||||
lv_coord_t left_diff = parent->coords.x1 + pleft - area_tmp->x1 - scroll_value->x;
|
||||
lv_coord_t right_diff = -(parent->coords.x2 - pright - area_tmp->x2 - scroll_value->x);
|
||||
if((left_diff >= 0 && right_diff >= 0)) x_scroll = 0;
|
||||
else if(left_diff > 0) {
|
||||
x_scroll = left_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sl = lv_obj_get_scroll_left(parent);
|
||||
if(sl + x_scroll > 0) x_scroll = 0;
|
||||
}
|
||||
else if(right_diff > 0) {
|
||||
x_scroll = -right_diff;
|
||||
/*Do not let scrolling in*/
|
||||
lv_coord_t sr = lv_obj_get_scroll_right(parent);
|
||||
if(sr + x_scroll < 0) x_scroll = 0;
|
||||
}
|
||||
|
||||
lv_coord_t parent_w = lv_obj_get_width(parent) - pleft - pright;
|
||||
switch(snap_x) {
|
||||
case LV_SCROLL_SNAP_START:
|
||||
snap_goal = parent->coords.x1 + pleft;
|
||||
act = area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_END:
|
||||
snap_goal = parent->coords.x2 - pright;
|
||||
act = area_tmp->x2 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
case LV_SCROLL_SNAP_CENTER:
|
||||
snap_goal = parent->coords.x1 + pleft + parent_w / 2;
|
||||
act = lv_area_get_width(area_tmp) / 2 + area_tmp->x1 + x_scroll;
|
||||
x_scroll += snap_goal - act;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Remove any pending scroll animations.*/
|
||||
bool y_del = lv_anim_del(parent, scroll_y_anim);
|
||||
bool x_del = lv_anim_del(parent, scroll_x_anim);
|
||||
if(y_del || x_del) {
|
||||
lv_res_t res;
|
||||
res = lv_event_send(parent, LV_EVENT_SCROLL_END, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
|
||||
if((scroll_dir & LV_DIR_LEFT) == 0 && x_scroll < 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_RIGHT) == 0 && x_scroll > 0) x_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_TOP) == 0 && y_scroll < 0) y_scroll = 0;
|
||||
if((scroll_dir & LV_DIR_BOTTOM) == 0 && y_scroll > 0) y_scroll = 0;
|
||||
|
||||
scroll_value->x += anim_en == LV_ANIM_OFF ? 0 : x_scroll;
|
||||
scroll_value->y += anim_en == LV_ANIM_OFF ? 0 : y_scroll;
|
||||
lv_obj_scroll_by(parent, x_scroll, y_scroll, anim_en);
|
||||
}
|
284
EC600U_lvgl_lib/lvgl/src/core/lv_obj_scroll.h
Normal file
284
EC600U_lvgl_lib/lvgl/src/core/lv_obj_scroll.h
Normal file
@ -0,0 +1,284 @@
|
||||
/**
|
||||
* @file lv_obj_scroll.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_SCROLL_H
|
||||
#define LV_OBJ_SCROLL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
/** Scrollbar modes: shows when should the scrollbars be visible*/
|
||||
enum {
|
||||
LV_SCROLLBAR_MODE_OFF, /**< Never show scrollbars*/
|
||||
LV_SCROLLBAR_MODE_ON, /**< Always show scrollbars*/
|
||||
LV_SCROLLBAR_MODE_ACTIVE, /**< Show scroll bars when object is being scrolled*/
|
||||
LV_SCROLLBAR_MODE_AUTO, /**< Show scroll bars when the content is large enough to be scrolled*/
|
||||
};
|
||||
typedef uint8_t lv_scrollbar_mode_t;
|
||||
|
||||
|
||||
/** Scroll span align options. Tells where to align the snappable children when scroll stops.*/
|
||||
enum {
|
||||
LV_SCROLL_SNAP_NONE, /**< Do not align, leave where it is*/
|
||||
LV_SCROLL_SNAP_START, /**< Align to the left/top*/
|
||||
LV_SCROLL_SNAP_END, /**< Align to the right/bottom*/
|
||||
LV_SCROLL_SNAP_CENTER /**< Align to the center*/
|
||||
};
|
||||
typedef uint8_t lv_scroll_snap_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set how the scrollbars should behave.
|
||||
* @param obj pointer to an object
|
||||
* @param mode LV_SCROLL_MODE_ON/OFF/AUTO/ACTIVE
|
||||
*/
|
||||
void lv_obj_set_scrollbar_mode(struct _lv_obj_t * obj, lv_scrollbar_mode_t mode);
|
||||
|
||||
/**
|
||||
* Set the object in which directions can be scrolled
|
||||
* @param obj pointer to an object
|
||||
* @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t`
|
||||
*/
|
||||
void lv_obj_set_scroll_dir(struct _lv_obj_t * obj, lv_dir_t dir);
|
||||
|
||||
/**
|
||||
* Set where to snap the children when scrolling ends horizontally
|
||||
* @param obj pointer to an object
|
||||
* @param align the snap align to set from `lv_scroll_snap_t`
|
||||
*/
|
||||
void lv_obj_set_scroll_snap_x(struct _lv_obj_t * obj, lv_scroll_snap_t align);
|
||||
|
||||
/**
|
||||
* Set where to snap the children when scrolling ends vertically
|
||||
* @param obj pointer to an object
|
||||
* @param align the snap align to set from `lv_scroll_snap_t`
|
||||
*/
|
||||
void lv_obj_set_scroll_snap_y(struct _lv_obj_t * obj, lv_scroll_snap_t align);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current scroll mode (when to hide the scrollbars)
|
||||
* @param obj pointer to an object
|
||||
* @return the current scroll mode from `lv_scrollbar_mode_t`
|
||||
*/
|
||||
lv_scrollbar_mode_t lv_obj_get_scrollbar_mode(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the object in which directions can be scrolled
|
||||
* @param obj pointer to an object
|
||||
* @param dir the allow scroll directions. An element or OR-ed values of `lv_dir_t`
|
||||
*/
|
||||
lv_dir_t lv_obj_get_scroll_dir(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get where to snap the children when scrolling ends horizontally
|
||||
* @param obj pointer to an object
|
||||
* @return the current snap align from `lv_scroll_snap_t`
|
||||
*/
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_x(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get where to snap the children when scrolling ends vertically
|
||||
* @param obj pointer to an object
|
||||
* @return the current snap align from `lv_scroll_snap_t`
|
||||
*/
|
||||
lv_scroll_snap_t lv_obj_get_scroll_snap_y(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get current X scroll position.
|
||||
* @param obj pointer to an object
|
||||
* @return the current scroll position from the left edge.
|
||||
* If the object is not scrolled return 0
|
||||
* If scrolled return > 0
|
||||
* If scrolled in (elastic scroll) return < 0
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_x(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get current Y scroll position.
|
||||
* @param obj pointer to an object
|
||||
* @return the current scroll position from the top edge.
|
||||
* If the object is not scrolled return 0
|
||||
* If scrolled return > 0
|
||||
* If scrolled inside return < 0
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_y(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Return the height of the area above the object.
|
||||
* That is the number of pixels the object can be scrolled down.
|
||||
* Normally positive but can be negative when scrolled inside.
|
||||
* @param obj pointer to an object
|
||||
* @return the scrollable area above the object in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_top(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Return the height of the area below the object.
|
||||
* That is the number of pixels the object can be scrolled down.
|
||||
* Normally positive but can be negative when scrolled inside.
|
||||
* @param obj pointer to an object
|
||||
* @return the scrollable area below the object in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_bottom(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Return the width of the area on the left the object.
|
||||
* That is the number of pixels the object can be scrolled down.
|
||||
* Normally positive but can be negative when scrolled inside.
|
||||
* @param obj pointer to an object
|
||||
* @return the scrollable area on the left the object in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_left(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Return the width of the area on the right the object.
|
||||
* That is the number of pixels the object can be scrolled down.
|
||||
* Normally positive but can be negative when scrolled inside.
|
||||
* @param obj pointer to an object
|
||||
* @return the scrollable area on the right the object in pixels
|
||||
*/
|
||||
lv_coord_t lv_obj_get_scroll_right(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the X and Y coordinates where the scrolling will end for this object if a scrolling animation is in progress.
|
||||
* If no scrolling animation, give the current `x` or `y` scroll position.
|
||||
* @param obj pointer to an object
|
||||
* @param end pointer to store the result
|
||||
*/
|
||||
void lv_obj_get_scroll_end(struct _lv_obj_t * obj, lv_point_t * end);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Scroll by a given amount of pixels
|
||||
* @param obj pointer to an object to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param y pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
* @note > 0 value means scroll right/bottom (show the more content on the right/bottom)
|
||||
* @note
|
||||
*/
|
||||
void lv_obj_scroll_by(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to a given coordinate on an object.
|
||||
* `x` and `y` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to an object to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param y pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to a given X coordinate on an object.
|
||||
* `x` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to an object to scroll
|
||||
* @param x pixels to scroll horizontally
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_x(struct _lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to a given Y coordinate on an object
|
||||
* `y` will be limited internally to allow scrolling only on the content area.
|
||||
* @param obj pointer to an object to scroll
|
||||
* @param y pixels to scroll vertically
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_y(struct _lv_obj_t * obj, lv_coord_t y, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to an object until it becomes visible on its parent
|
||||
* @param obj pointer to an object to scroll into view
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_view(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll to an object until it becomes visible on its parent.
|
||||
* Do the same on the parent's parent, and so on.
|
||||
* Therefore the object will be scrolled into view even it has nested scrollable parents
|
||||
* @param obj pointer to an object to scroll into view
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation; LV_ANIM_OFF: scroll immediately
|
||||
*/
|
||||
void lv_obj_scroll_to_view_recursive(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Tell whether an object is being scrolled or not at this moment
|
||||
* @param obj pointer to an object
|
||||
* @return true: `obj` is being scrolled
|
||||
*/
|
||||
bool lv_obj_is_scrolling(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check the children of `obj` and scroll `obj` to fulfill the scroll_snap settings
|
||||
* @param obj an object whose children needs to checked and snapped
|
||||
* @param anim_en LV_ANIM_ON/OFF
|
||||
*/
|
||||
void lv_obj_update_snap(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Get the area of the scrollbars
|
||||
* @param obj pointer to an object
|
||||
* @param hor pointer to store the area of the horizontal scrollbar
|
||||
* @param ver pointer to store the area of the vertical scrollbar
|
||||
*/
|
||||
void lv_obj_get_scrollbar_area(struct _lv_obj_t * obj, lv_area_t * hor, lv_area_t * ver);
|
||||
|
||||
/**
|
||||
* Invalidate the area of the scrollbars
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_scrollbar_invalidate(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Checked if the content is scrolled "in" and adjusts it to a normal position.
|
||||
* @param obj pointer to an object
|
||||
* @param anim_en LV_ANIM_ON/OFF
|
||||
*/
|
||||
void lv_obj_readjust_scroll(struct _lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_SCROLL_H*/
|
825
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style.c
Normal file
825
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style.c
Normal file
@ -0,0 +1,825 @@
|
||||
/**
|
||||
* @file lv_obj_style.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "lv_disp.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t * obj;
|
||||
lv_style_prop_t prop;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_value_t start_value;
|
||||
lv_style_value_t end_value;
|
||||
} trans_t;
|
||||
|
||||
typedef enum {
|
||||
CACHE_ZERO = 0,
|
||||
CACHE_TRUE = 1,
|
||||
CACHE_UNSET = 2,
|
||||
CACHE_255 = 3,
|
||||
CACHE_NEED_CHECK = 4,
|
||||
} cache_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector);
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, uint32_t part);
|
||||
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v);
|
||||
static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v);
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj);
|
||||
static void refresh_children_style(lv_obj_t * obj);
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit);
|
||||
static void trans_anim_cb(void * _tr, int32_t v);
|
||||
static void trans_anim_start_cb(lv_anim_t * a);
|
||||
static void trans_anim_ready_cb(lv_anim_t * a);
|
||||
static void fade_anim_cb(void * obj, int32_t v);
|
||||
static void fade_in_anim_ready(lv_anim_t * a);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static bool style_refr = true;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void _lv_obj_style_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(trans_t));
|
||||
}
|
||||
|
||||
void lv_obj_add_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
trans_del(obj, selector, LV_STYLE_PROP_ANY, NULL);
|
||||
|
||||
uint32_t i;
|
||||
/*Go after the transition and local styles*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
if(obj->styles[i].is_local) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Now `i` is at the first normal style. Insert the new style before this*/
|
||||
|
||||
/*Allocate space for the new style and shift the rest of the style to the end*/
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
uint32_t j;
|
||||
for(j = obj->style_cnt - 1; j > i ; j--) {
|
||||
obj->styles[j] = obj->styles[j - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = style;
|
||||
obj->styles[i].selector = selector;
|
||||
|
||||
lv_obj_refresh_style(obj, selector, LV_STYLE_PROP_ANY);
|
||||
}
|
||||
|
||||
void lv_obj_remove_style(lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector)
|
||||
{
|
||||
lv_state_t state = lv_obj_style_get_selector_state(selector);
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
lv_style_prop_t prop = LV_STYLE_PROP_ANY;
|
||||
if(style && style->prop_cnt == 0) prop = LV_STYLE_PROP_INV;
|
||||
|
||||
uint32_t i = 0;
|
||||
bool deleted = false;
|
||||
while(i < obj->style_cnt) {
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
if((state != LV_STATE_ANY && state_act != state) ||
|
||||
(part != LV_PART_ANY && part_act != part) ||
|
||||
(style != NULL && style != obj->styles[i].style)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_trans) {
|
||||
trans_del(obj, part, LV_STYLE_PROP_ANY, NULL);
|
||||
}
|
||||
|
||||
if(obj->styles[i].is_local || obj->styles[i].is_trans) {
|
||||
lv_style_reset(obj->styles[i].style);
|
||||
lv_mem_free(obj->styles[i].style);
|
||||
obj->styles[i].style = NULL;
|
||||
}
|
||||
|
||||
/*Shift the styles after `i` by one*/
|
||||
uint32_t j;
|
||||
for(j = i; j < (uint32_t)obj->style_cnt - 1 ; j++) {
|
||||
obj->styles[j] = obj->styles[j + 1];
|
||||
}
|
||||
|
||||
obj->style_cnt--;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
deleted = true;
|
||||
/*The style from the current `i` index is removed, so `i` points to the next style.
|
||||
*Therefore it doesn't needs to be incremented*/
|
||||
}
|
||||
if(deleted && prop != LV_STYLE_PROP_INV) {
|
||||
lv_obj_refresh_style(obj, part, prop);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_report_style_change(lv_style_t * style)
|
||||
{
|
||||
if(!style_refr) return;
|
||||
lv_disp_t * d = lv_disp_get_next(NULL);
|
||||
|
||||
while(d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
report_style_change_core(style, d->screens[i]);
|
||||
}
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_refresh_style(lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(!style_refr) return;
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(selector);
|
||||
|
||||
if(prop & LV_STYLE_PROP_LAYOUT_REFR) {
|
||||
if(part == LV_PART_ANY ||
|
||||
part == LV_PART_MAIN ||
|
||||
lv_obj_get_style_height(obj, 0) == LV_SIZE_CONTENT ||
|
||||
lv_obj_get_style_width(obj, 0) == LV_SIZE_CONTENT) {
|
||||
lv_event_send(obj, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_mark_layout_as_dirty(obj);
|
||||
}
|
||||
}
|
||||
if((part == LV_PART_ANY || part == LV_PART_MAIN) && (prop == LV_STYLE_PROP_ANY ||
|
||||
(prop & LV_STYLE_PROP_PARENT_LAYOUT_REFR))) {
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent) lv_obj_mark_layout_as_dirty(parent);
|
||||
}
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY || (prop & LV_STYLE_PROP_EXT_DRAW)) {
|
||||
lv_obj_refresh_ext_draw_size(obj);
|
||||
}
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
if(prop == LV_STYLE_PROP_ANY ||
|
||||
((prop & LV_STYLE_PROP_INHERIT) && ((prop & LV_STYLE_PROP_EXT_DRAW) || (prop & LV_STYLE_PROP_LAYOUT_REFR)))) {
|
||||
if(part != LV_PART_SCROLLBAR) {
|
||||
refresh_children_style(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_enable_style_refresh(bool en)
|
||||
{
|
||||
style_refr = en;
|
||||
}
|
||||
|
||||
lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop)
|
||||
{
|
||||
lv_style_value_t value_act;
|
||||
bool inherit = prop & LV_STYLE_PROP_INHERIT ? true : false;
|
||||
bool filter = prop & LV_STYLE_PROP_FILTER ? true : false;
|
||||
if(filter) {
|
||||
prop &= ~LV_STYLE_PROP_FILTER;
|
||||
}
|
||||
bool found = false;
|
||||
while(obj) {
|
||||
found = get_prop_core(obj, part, prop, &value_act);
|
||||
if(found) break;
|
||||
if(!inherit) break;
|
||||
|
||||
/*If not found, check the `MAIN` style first*/
|
||||
if(part != LV_PART_MAIN) {
|
||||
part = LV_PART_MAIN;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check the parent too.*/
|
||||
obj = lv_obj_get_parent(obj);
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
if(part == LV_PART_MAIN && (prop == LV_STYLE_WIDTH || prop == LV_STYLE_HEIGHT)) {
|
||||
const lv_obj_class_t * cls = obj->class_p;
|
||||
while(cls) {
|
||||
if(prop == LV_STYLE_WIDTH) {
|
||||
if(cls->width_def != 0) break;
|
||||
}
|
||||
else {
|
||||
if(cls->height_def != 0) break;
|
||||
}
|
||||
cls = cls->base_class;
|
||||
}
|
||||
|
||||
value_act.num = prop == LV_STYLE_WIDTH ? cls->width_def : cls->height_def;
|
||||
}
|
||||
else {
|
||||
value_act = lv_style_prop_get_default(prop);
|
||||
}
|
||||
}
|
||||
if(filter) value_act = apply_color_filter(obj, part, value_act);
|
||||
return value_act;
|
||||
}
|
||||
|
||||
void lv_obj_set_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_t * style = get_local_style(obj, selector);
|
||||
lv_style_set_prop(style, prop, value);
|
||||
lv_obj_refresh_style(obj, selector, prop);
|
||||
}
|
||||
|
||||
|
||||
lv_res_t lv_obj_get_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return lv_style_get_prop(obj->styles[i].style, prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
bool lv_obj_remove_local_style_prop(lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
uint32_t i;
|
||||
/*Find the style*/
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The style is not found*/
|
||||
if(i == obj->style_cnt) return false;
|
||||
|
||||
return lv_style_remove_prop(obj->styles[i].style, prop);
|
||||
}
|
||||
|
||||
void _lv_obj_style_create_transition(lv_obj_t * obj, lv_part_t part, lv_state_t prev_state, lv_state_t new_state,
|
||||
const _lv_obj_style_transition_dsc_t * tr_dsc)
|
||||
{
|
||||
trans_t * tr;
|
||||
|
||||
/*Get the previous and current values*/
|
||||
obj->skip_trans = 1;
|
||||
obj->state = prev_state;
|
||||
lv_style_value_t v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
lv_style_value_t v2 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->skip_trans = 0;
|
||||
|
||||
if(v1.ptr == v2.ptr && v1.num == v2.num && v1.color.full == v2.color.full) return;
|
||||
obj->state = prev_state;
|
||||
v1 = lv_obj_get_style_prop(obj, part, tr_dsc->prop);
|
||||
obj->state = new_state;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(obj, part);
|
||||
lv_style_set_prop(style_trans->style, tr_dsc->prop, v1); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
if(tr_dsc->prop == LV_STYLE_RADIUS) {
|
||||
if(v1.num == LV_RADIUS_CIRCLE || v2.num == LV_RADIUS_CIRCLE) {
|
||||
lv_coord_t whalf = lv_obj_get_width(obj) / 2;
|
||||
lv_coord_t hhalf = lv_obj_get_width(obj) / 2;
|
||||
if(v1.num == LV_RADIUS_CIRCLE) v1.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
if(v2.num == LV_RADIUS_CIRCLE) v2.num = LV_MIN(whalf + 1, hhalf + 1);
|
||||
}
|
||||
}
|
||||
|
||||
tr = _lv_ll_ins_head(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
LV_ASSERT_MALLOC(tr);
|
||||
if(tr == NULL) return;
|
||||
tr->start_value = v1;
|
||||
tr->end_value = v2;
|
||||
|
||||
if(tr) {
|
||||
tr->obj = obj;
|
||||
tr->prop = tr_dsc->prop;
|
||||
tr->selector = part;
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, tr);
|
||||
lv_anim_set_exec_cb(&a, trans_anim_cb);
|
||||
lv_anim_set_start_cb(&a, trans_anim_start_cb);
|
||||
lv_anim_set_ready_cb(&a, trans_anim_ready_cb);
|
||||
lv_anim_set_values(&a, 0x00, 0xFF);
|
||||
lv_anim_set_time(&a, tr_dsc->time);
|
||||
lv_anim_set_delay(&a, tr_dsc->delay);
|
||||
lv_anim_set_path_cb(&a, tr_dsc->path_cb);
|
||||
lv_anim_set_early_apply(&a, false);
|
||||
#if LV_USE_USER_DATA
|
||||
a.user_data = tr_dsc->user_data;
|
||||
#endif
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
}
|
||||
|
||||
_lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t state1, lv_state_t state2)
|
||||
{
|
||||
_lv_style_state_cmp_t res = _LV_STYLE_STATE_CMP_SAME;
|
||||
|
||||
/*Are there any new styles for the new state?*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans) continue;
|
||||
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
/*The style is valid for a state but not the other*/
|
||||
bool valid1 = state_act & (~state1) ? false : true;
|
||||
bool valid2 = state_act & (~state2) ? false : true;
|
||||
if(valid1 != valid2) {
|
||||
lv_style_t * style = obj->styles[i].style;
|
||||
lv_style_value_t v;
|
||||
/*If there is layout difference on the main part, return immediately. There is no more serious difference*/
|
||||
bool layout_diff = false;
|
||||
if(lv_style_get_prop(style, LV_STYLE_PAD_TOP, &v))layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_BOTTOM, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_LEFT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_RIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_COLUMN, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_PAD_ROW, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LAYOUT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_X, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSLATE_Y, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MIN_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_MAX_HEIGHT, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_BORDER_WIDTH, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) layout_diff = true;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) layout_diff = true;
|
||||
|
||||
if(layout_diff) {
|
||||
return _LV_STYLE_STATE_CMP_DIFF_LAYOUT;
|
||||
}
|
||||
|
||||
/*Check for draw pad changes*/
|
||||
if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_HEIGHT, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ANGLE, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_TRANSFORM_ZOOM, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_PAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_OUTLINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OPA, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_X, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_OFS_Y, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_SHADOW_SPREAD, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(lv_style_get_prop(style, LV_STYLE_LINE_WIDTH, &v)) res = _LV_STYLE_STATE_CMP_DIFF_DRAW_PAD;
|
||||
else if(res == _LV_STYLE_STATE_CMP_SAME) res = _LV_STYLE_STATE_CMP_DIFF_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void lv_obj_fade_in(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_ready_cb(&a, fade_in_anim_ready);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_fade_out(lv_obj_t * obj, uint32_t time, uint32_t delay)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_TRANSP);
|
||||
lv_anim_set_exec_cb(&a, fade_anim_cb);
|
||||
lv_anim_set_time(&a, time);
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFFFF;
|
||||
}
|
||||
|
||||
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
|
||||
{
|
||||
return selector & 0xFF0000;
|
||||
}
|
||||
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt)
|
||||
{
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, part);
|
||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part);
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
return align;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the local style of an object for a given part and for a given state.
|
||||
* If the local style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param part the part in whose local style to get
|
||||
* @param state the state in whose local style to get
|
||||
* @return pointer to the local style
|
||||
*/
|
||||
static lv_style_t * get_local_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_local &&
|
||||
obj->styles[i].selector == selector) {
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
}
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
LV_ASSERT_MALLOC(obj->styles);
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
/*Copy only normal styles (not local and transition).
|
||||
*The new local style will be added as the last local style*/
|
||||
if(obj->styles[i - 1].is_local || obj->styles[i - 1].is_trans) break;
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[i], sizeof(_lv_obj_style_t));
|
||||
obj->styles[i].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[i].style);
|
||||
obj->styles[i].is_local = 1;
|
||||
obj->styles[i].selector = selector;
|
||||
return obj->styles[i].style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transition style of an object for a given part and for a given state.
|
||||
* If the transition style for the part-state pair doesn't exist allocate and return it.
|
||||
* @param obj pointer to an object
|
||||
* @param part the part in whose local style to get
|
||||
* @param state the state in whose local style to get
|
||||
* @return pointer to the transition style
|
||||
*/
|
||||
static _lv_obj_style_t * get_trans_style(lv_obj_t * obj, lv_style_selector_t selector)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == selector) break;
|
||||
}
|
||||
|
||||
/*Already have a transition style for it*/
|
||||
if(i != obj->style_cnt) return &obj->styles[i];
|
||||
|
||||
obj->style_cnt++;
|
||||
obj->styles = lv_mem_realloc(obj->styles, obj->style_cnt * sizeof(_lv_obj_style_t));
|
||||
|
||||
for(i = obj->style_cnt - 1; i > 0 ; i--) {
|
||||
obj->styles[i] = obj->styles[i - 1];
|
||||
}
|
||||
|
||||
lv_memset_00(&obj->styles[0], sizeof(_lv_obj_style_t));
|
||||
obj->styles[0].style = lv_mem_alloc(sizeof(lv_style_t));
|
||||
lv_style_init(obj->styles[0].style);
|
||||
obj->styles[0].is_trans = 1;
|
||||
obj->styles[0].selector = selector;
|
||||
return &obj->styles[0];
|
||||
}
|
||||
|
||||
|
||||
static bool get_prop_core(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, lv_style_value_t * v)
|
||||
{
|
||||
uint8_t group = 1 << _lv_style_get_prop_group(prop);
|
||||
int32_t weight = -1;
|
||||
lv_state_t state = obj->state;
|
||||
lv_state_t state_inv = ~state;
|
||||
lv_style_value_t value_tmp;
|
||||
bool skip_trans = obj->skip_trans;
|
||||
uint32_t i;
|
||||
bool found;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
if(obj_style->is_trans == false) break;
|
||||
if(skip_trans) continue;
|
||||
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
|
||||
if(part_act != part) continue;
|
||||
if((obj_style->style->has_group & group) == 0) continue;
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
if(found) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(; i < obj->style_cnt; i++) {
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_part_t part_act = lv_obj_style_get_selector_part(obj->styles[i].selector);
|
||||
lv_state_t state_act = lv_obj_style_get_selector_state(obj->styles[i].selector);
|
||||
if(part_act != part) continue;
|
||||
|
||||
if((obj_style->style->has_group & group) == 0) continue;
|
||||
|
||||
/*Be sure the style not specifies other state than the requested.
|
||||
*E.g. For HOVER+PRESS object state, HOVER style only is OK, but HOVER+FOCUS style is not*/
|
||||
if((state_act & state_inv)) continue;
|
||||
|
||||
/*Check only better candidates*/
|
||||
if(state_act <= weight) continue;
|
||||
|
||||
found = lv_style_get_prop(obj_style->style, prop, &value_tmp);
|
||||
|
||||
if(found) {
|
||||
if(state_act == state) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
if(weight < state_act) {
|
||||
weight = state_act;
|
||||
*v = value_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(weight >= 0) {
|
||||
*v = value_tmp;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
static lv_style_value_t apply_color_filter(const lv_obj_t * obj, uint32_t part, lv_style_value_t v)
|
||||
{
|
||||
if(obj == NULL) return v;
|
||||
const lv_color_filter_dsc_t * f = lv_obj_get_style_color_filter_dsc(obj, part);
|
||||
if(f && f->filter_cb) {
|
||||
lv_opa_t f_opa = lv_obj_get_style_color_filter_opa(obj, part);
|
||||
if(f_opa != 0) v.color = f->filter_cb(f, v.color, f_opa);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the style of all children of an object. (Called recursively)
|
||||
* @param style refresh objects only with this
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(style == NULL || obj->styles[i].style == style) {
|
||||
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
report_style_change_core(style, obj->spec_attr->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively refresh the style of the children. Go deeper until a not NULL style is found
|
||||
* because the NULL styles are inherited from the parent
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void refresh_children_style(lv_obj_t * obj)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_invalidate(child);
|
||||
lv_event_send(child, LV_EVENT_STYLE_CHANGED, NULL);
|
||||
lv_obj_invalidate(child);
|
||||
|
||||
refresh_children_style(child); /*Check children too*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the transition from object's part's property.
|
||||
* - Remove the transition from `_lv_obj_style_trans_ll` and free it
|
||||
* - Delete pending transitions
|
||||
* @param obj pointer to an object which transition(s) should be removed
|
||||
* @param part a part of object or 0xFF to remove from all parts
|
||||
* @param prop a property or 0xFF to remove all properties
|
||||
* @param tr_limit delete transitions only "older" than this. `NULL` if not used
|
||||
*/
|
||||
static bool trans_del(lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop, trans_t * tr_limit)
|
||||
{
|
||||
trans_t * tr;
|
||||
trans_t * tr_prev;
|
||||
bool removed = false;
|
||||
tr = _lv_ll_get_tail(&LV_GC_ROOT(_lv_obj_style_trans_ll));
|
||||
while(tr != NULL) {
|
||||
if(tr == tr_limit) break;
|
||||
|
||||
/*'tr' might be deleted, so get the next object while 'tr' is valid*/
|
||||
tr_prev = _lv_ll_get_prev(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
|
||||
if(tr->obj == obj && (part == tr->selector || part == LV_PART_ANY) && (prop == tr->prop || prop == LV_STYLE_PROP_ANY)) {
|
||||
/*Remove the transitioned property from trans. style
|
||||
*to allow changing it by normal styles*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && (part == LV_PART_ANY || obj->styles[i].selector == part)) {
|
||||
lv_style_remove_prop(obj->styles[i].style, tr->prop);
|
||||
lv_anim_del(tr, NULL);
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
tr = tr_prev;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
static void trans_anim_cb(void * _tr, int32_t v)
|
||||
{
|
||||
trans_t * tr = _tr;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans == 0 || obj->styles[i].selector != tr->selector) continue;
|
||||
|
||||
lv_style_value_t value_final;
|
||||
switch(tr->prop) {
|
||||
|
||||
case LV_STYLE_BORDER_SIDE:
|
||||
case LV_STYLE_BORDER_POST:
|
||||
case LV_STYLE_BLEND_MODE:
|
||||
if(v < 255) value_final.num = tr->start_value.num;
|
||||
else value_final.num = tr->end_value.num;
|
||||
break;
|
||||
case LV_STYLE_TRANSITION:
|
||||
case LV_STYLE_TEXT_FONT:
|
||||
if(v < 255) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_COLOR_FILTER_DSC:
|
||||
if(tr->start_value.ptr == NULL) value_final.ptr = tr->end_value.ptr;
|
||||
else if(tr->end_value.ptr == NULL) value_final.ptr = tr->start_value.ptr;
|
||||
else if(v < 128) value_final.ptr = tr->start_value.ptr;
|
||||
else value_final.ptr = tr->end_value.ptr;
|
||||
break;
|
||||
case LV_STYLE_BG_COLOR:
|
||||
case LV_STYLE_BORDER_COLOR:
|
||||
case LV_STYLE_TEXT_COLOR:
|
||||
case LV_STYLE_SHADOW_COLOR:
|
||||
case LV_STYLE_OUTLINE_COLOR:
|
||||
case LV_STYLE_IMG_RECOLOR:
|
||||
if(v <= 0) value_final.color = tr->start_value.color;
|
||||
else if(v >= 255) value_final.color = tr->end_value.color;
|
||||
else value_final.color = lv_color_mix(tr->end_value.color, tr->start_value.color, v);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(v == 0) value_final.num = tr->start_value.num;
|
||||
else if(v == 255) value_final.num = tr->end_value.num;
|
||||
else value_final.num = tr->start_value.num + ((int32_t)((int32_t)(tr->end_value.num - tr->start_value.num) * v) >> 8);
|
||||
break;
|
||||
}
|
||||
|
||||
lv_style_value_t old_value;
|
||||
bool refr = true;
|
||||
if(lv_style_get_prop(obj->styles[i].style, tr->prop, &old_value)) {
|
||||
if(value_final.ptr == old_value.ptr && value_final.color.full == old_value.color.full &&
|
||||
value_final.num == old_value.num) {
|
||||
refr = false;
|
||||
}
|
||||
}
|
||||
lv_style_set_prop(obj->styles[i].style, tr->prop, value_final);
|
||||
if(refr) lv_obj_refresh_style(tr->obj, tr->selector, tr->prop);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_start_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
|
||||
lv_part_t part = lv_obj_style_get_selector_part(tr->selector);
|
||||
tr->start_value = lv_obj_get_style_prop(tr->obj, part, tr->prop);
|
||||
|
||||
/*Init prop to an invalid values to be sure `trans_del` won't delete this added `tr`*/
|
||||
lv_style_prop_t prop_tmp = tr->prop;
|
||||
tr->prop = LV_STYLE_PROP_INV;
|
||||
|
||||
/*Delete the related transitions if any*/
|
||||
trans_del(tr->obj, part, prop_tmp, tr);
|
||||
|
||||
tr->prop = prop_tmp;
|
||||
|
||||
_lv_obj_style_t * style_trans = get_trans_style(tr->obj, tr->selector);
|
||||
lv_style_set_prop(style_trans->style, tr->prop, tr->start_value); /*Be sure `trans_style` has a valid value*/
|
||||
|
||||
}
|
||||
|
||||
static void trans_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
trans_t * tr = a->var;
|
||||
lv_obj_t * obj = tr->obj;
|
||||
lv_style_prop_t prop = tr->prop;
|
||||
|
||||
/*Remove the transitioned property from trans. style
|
||||
*if there no more transitions for this property
|
||||
*It allows changing it by normal styles*/
|
||||
bool running = false;
|
||||
trans_t * tr_i;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr_i) {
|
||||
if(tr_i != tr && tr_i->obj == tr->obj && tr_i->selector == tr->selector && tr_i->prop == tr->prop) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!running) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < obj->style_cnt; i++) {
|
||||
if(obj->styles[i].is_trans && obj->styles[i].selector == tr->selector) {
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_obj_style_trans_ll), tr);
|
||||
lv_mem_free(tr);
|
||||
|
||||
_lv_obj_style_t * obj_style = &obj->styles[i];
|
||||
lv_style_remove_prop(obj_style->style, prop);
|
||||
|
||||
if(lv_style_is_empty(obj->styles[i].style)) {
|
||||
lv_obj_remove_style(obj, obj_style->style, obj_style->selector);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fade_anim_cb(void * obj, int32_t v)
|
||||
{
|
||||
lv_obj_set_style_opa(obj, v, 0);
|
||||
}
|
||||
|
||||
static void fade_in_anim_ready(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
|
||||
}
|
||||
|
||||
|
251
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style.h
Normal file
251
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style.h
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @file lv_obj_style.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_STYLE_H
|
||||
#define LV_OBJ_STYLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
_LV_STYLE_STATE_CMP_SAME, /*The style properties in the 2 states are identical*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_REDRAW, /*The differences can be shown with a simple redraw*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_DRAW_PAD, /*The differences can be shown with a simple redraw*/
|
||||
_LV_STYLE_STATE_CMP_DIFF_LAYOUT, /*The differences can be shown with a simple redraw*/
|
||||
} _lv_style_state_cmp_t;
|
||||
|
||||
typedef uint32_t lv_style_selector_t;
|
||||
|
||||
typedef struct {
|
||||
lv_style_t * style;
|
||||
uint32_t selector : 24;
|
||||
uint32_t is_local : 1;
|
||||
uint32_t is_trans : 1;
|
||||
} _lv_obj_style_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t time;
|
||||
uint16_t delay;
|
||||
lv_style_selector_t selector;
|
||||
lv_style_prop_t prop;
|
||||
lv_anim_path_cb_t path_cb;
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
} _lv_obj_style_transition_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the object related style manager module.
|
||||
* Called by LVGL in `lv_init()`
|
||||
*/
|
||||
void _lv_obj_style_init(void);
|
||||
|
||||
/**
|
||||
* Add a style to an object.
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style to add
|
||||
* @param selector OR-ed value of parts and state to which the style should be added
|
||||
* @example lv_obj_add_style(btn, &style_btn, 0); //Default button style
|
||||
* @example lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED); //Overwrite only some colors to red when pressed
|
||||
*/
|
||||
void lv_obj_add_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Add a style to an object.
|
||||
* @param obj pointer to an object
|
||||
* @param style pointer to a style to remove. Can be NULL to check only the selector
|
||||
* @param selector OR-ed values of states and a part to remove only styles with matching selectors. LV_STATE_ANY and LV_PART_ANY can be used
|
||||
* @example lv_obj_remove_style(obj, &style, LV_PART_ANY | LV_STATE_ANY); //Remove a specific style
|
||||
* @example lv_obj_remove_style(obj, NULL, LV_PART_MAIN | LV_STATE_ANY); //Remove all styles from the main part
|
||||
* @example lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY); //Remove all styles
|
||||
*/
|
||||
void lv_obj_remove_style(struct _lv_obj_t * obj, lv_style_t * style, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Remove all styles from an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static inline void lv_obj_remove_style_all(struct _lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_remove_style(obj, NULL, LV_PART_ANY | LV_STATE_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all object if a style is modified
|
||||
* @param style pointer to a style. Only the objects with this style will be notified
|
||||
* (NULL to notify all objects)
|
||||
*/
|
||||
void lv_obj_report_style_change(lv_style_t * style);
|
||||
|
||||
/**
|
||||
* Notify an object and its children about its style is modified.
|
||||
* @param obj pointer to an object
|
||||
* @param part the part whose style was changed. E.g. `LV_PART_ANY`, `LV_PART_MAIN`
|
||||
* @param prop `LV_STYLE_PROP_ANY` or an `LV_STYLE_...` property.
|
||||
* It is used to optimize what needs to be refreshed.
|
||||
* `LV_STYLE_PROP_INV` to perform only a style cache update
|
||||
*/
|
||||
void lv_obj_refresh_style(struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* Enable or disable automatic style refreshing when a new style is added/removed to/from an object
|
||||
* or any other style change happens.
|
||||
* @param en true: enable refreshing; false: disable refreshing
|
||||
*/
|
||||
void lv_obj_enable_style_refresh(bool en);
|
||||
|
||||
/**
|
||||
* Get the value of a style property. The current state of the object will be considered.
|
||||
* Inherited properties will be inherited.
|
||||
* If a property is not set a default value will be returned.
|
||||
* @param obj pointer to an object
|
||||
* @param part a part from which the property should be get
|
||||
* @param prop the property to get
|
||||
* @return the value of the property.
|
||||
* Should be read from the correct field of the `lv_style_value_t` according to the type of the property.
|
||||
*/
|
||||
lv_style_value_t lv_obj_get_style_prop(const struct _lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop);
|
||||
|
||||
/**
|
||||
* Set local style property on an object's part and state.
|
||||
* @param obj pointer to an object
|
||||
* @param part a part to which the property should be added
|
||||
* @param state a state to which the property should be added
|
||||
* @param prop the property
|
||||
* @param value value of the property. The correct element should be set according to the type of the property
|
||||
*/
|
||||
void lv_obj_set_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t value,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
lv_res_t lv_obj_get_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_value_t * value,
|
||||
lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Remove a local style property from a part of an object with a given state.
|
||||
* @param obj pointer to an object
|
||||
* @param part the part of the object which style property should be removed.
|
||||
* @param state the state from which the property should be removed.
|
||||
* @param prop a style property to remove.
|
||||
* @return true the property was found and removed; false: the property was not found
|
||||
*/
|
||||
bool lv_obj_remove_local_style_prop(struct _lv_obj_t * obj, lv_style_prop_t prop, lv_style_selector_t selector);
|
||||
|
||||
/**
|
||||
* Used internally to create a style transition
|
||||
* @param obj
|
||||
* @param part
|
||||
* @param prev_state
|
||||
* @param new_state
|
||||
* @param tr
|
||||
*/
|
||||
void _lv_obj_style_create_transition(struct _lv_obj_t * obj, lv_part_t part, lv_state_t prev_state,
|
||||
lv_state_t new_state, const _lv_obj_style_transition_dsc_t * tr);
|
||||
|
||||
/**
|
||||
* Used internally to compare the appearance of an object in 2 states
|
||||
* @param obj
|
||||
* @param state1
|
||||
* @param state2
|
||||
* @return
|
||||
*/
|
||||
_lv_style_state_cmp_t _lv_obj_style_state_compare(struct _lv_obj_t * obj, lv_state_t state1, lv_state_t state2);
|
||||
|
||||
/**
|
||||
* Fade in an an object and all its children.
|
||||
* @param obj the object to fade in
|
||||
* @param time time of fade
|
||||
* @param delay delay to start the animation
|
||||
*/
|
||||
void lv_obj_fade_in(struct _lv_obj_t * obj, uint32_t time, uint32_t delay);
|
||||
|
||||
/**
|
||||
* Fade out an an object and all its children.
|
||||
* @param obj the object to fade out
|
||||
* @param time time of fade
|
||||
* @param delay delay to start the animation
|
||||
*/
|
||||
void lv_obj_fade_out(struct _lv_obj_t * obj, uint32_t time, uint32_t delay);
|
||||
|
||||
lv_state_t lv_obj_style_get_selector_state(lv_style_selector_t selector);
|
||||
|
||||
lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector);
|
||||
|
||||
#include "lv_obj_style_gen.h"
|
||||
|
||||
static inline void lv_obj_set_style_pad_all(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_left(obj, value, selector);
|
||||
lv_obj_set_style_pad_right(obj, value, selector);
|
||||
lv_obj_set_style_pad_top(obj, value, selector);
|
||||
lv_obj_set_style_pad_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_hor(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_left(obj, value, selector);
|
||||
lv_obj_set_style_pad_right(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_ver(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_top(obj, value, selector);
|
||||
lv_obj_set_style_pad_bottom(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_pad_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_pad_row(obj, value, selector);
|
||||
lv_obj_set_style_pad_column(obj, value, selector);
|
||||
}
|
||||
|
||||
static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_obj_set_style_width(obj, value, selector);
|
||||
lv_obj_set_style_height(obj, value, selector);
|
||||
}
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(const struct _lv_obj_t * obj, lv_part_t part, const char * txt);
|
||||
|
||||
static inline lv_coord_t lv_obj_get_x_aligned(const struct _lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_x(obj, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_y_aligned(const struct _lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_y(obj, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
715
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style_gen.c
Normal file
715
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style_gen.c
Normal file
@ -0,0 +1,715 @@
|
||||
#include "lv_obj.h"
|
||||
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MIN_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_MAX_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_HEIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSLATE_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ZOOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSFORM_ANGLE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_TOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_BOTTOM, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_LEFT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_RIGHT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_ROW, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_PAD_COLUMN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_RADIUS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_CLIP_CORNER, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_DSC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_COLOR_FILTER_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_TIME, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
|
||||
lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TRANSITION, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BLEND_MODE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LAYOUT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BASE_DIR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_DIR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_MAIN_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_GRAD_STOP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_SRC, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BG_IMG_TILED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_SIDE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_BORDER_POST, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_FONT, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LETTER_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_LINE_SPACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_DECOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_TEXT_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_IMG_RECOLOR_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_OUTLINE_PAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_X, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OFS_Y, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_SPREAD, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_SHADOW_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_DASH_GAP, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_ROUNDED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_LINE_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_WIDTH, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_ROUNDED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.color = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_COLOR_FILTERED, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_OPA, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_ARC_IMG_SRC, v, selector);
|
||||
}
|
||||
|
626
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style_gen.h
Normal file
626
EC600U_lvgl_lib/lvgl/src/core/lv_obj_style_gen.h
Normal file
@ -0,0 +1,626 @@
|
||||
static inline lv_coord_t lv_obj_get_style_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_min_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_max_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_min_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MIN_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_max_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_MAX_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_align_t lv_obj_get_style_align(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ALIGN);
|
||||
return (lv_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_height(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_HEIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_translate_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_translate_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSLATE_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_zoom(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ZOOM);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_transform_angle(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSFORM_ANGLE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_top(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_TOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_bottom(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_BOTTOM);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_left(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_LEFT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_right(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_RIGHT);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_row(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_ROW);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_pad_column(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_PAD_COLUMN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_radius(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_RADIUS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_clip_corner(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_CLIP_CORNER);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_color_filter_dsc_t * lv_obj_get_style_color_filter_dsc(const struct _lv_obj_t * obj,
|
||||
uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_DSC);
|
||||
return (const lv_color_filter_dsc_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_color_filter_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_COLOR_FILTER_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_TIME);
|
||||
return (uint32_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED);
|
||||
return (uint32_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION);
|
||||
return (const lv_style_transition_dsc_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_blend_mode_t lv_obj_get_style_blend_mode(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BLEND_MODE);
|
||||
return (lv_blend_mode_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint16_t lv_obj_get_style_layout(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LAYOUT);
|
||||
return (uint16_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_base_dir_t lv_obj_get_style_base_dir(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BASE_DIR);
|
||||
return (lv_base_dir_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_bg_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_grad_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_grad_dir_t lv_obj_get_style_bg_grad_dir(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_DIR);
|
||||
return (lv_grad_dir_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_bg_main_stop(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_MAIN_STOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_bg_grad_stop(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_STOP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline const void * lv_obj_get_style_bg_img_src(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_SRC);
|
||||
return (const void *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_bg_img_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_bg_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_bg_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_RECOLOR_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_bg_img_tiled(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMG_TILED);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_border_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_border_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_border_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_border_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_border_side_t lv_obj_get_style_border_side(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_SIDE);
|
||||
return (lv_border_side_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_border_post(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_POST);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_text_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_text_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_text_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline const lv_font_t * lv_obj_get_style_text_font(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_FONT);
|
||||
return (const lv_font_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_text_letter_space(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LETTER_SPACE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_text_line_space(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_LINE_SPACE);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_text_decor_t lv_obj_get_style_text_decor(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_DECOR);
|
||||
return (lv_text_decor_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_text_align_t lv_obj_get_style_text_align(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TEXT_ALIGN);
|
||||
return (lv_text_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_img_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_img_recolor(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_img_recolor_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_img_recolor_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_IMG_RECOLOR_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_outline_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_outline_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_outline_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_outline_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_outline_pad(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_PAD);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_ofs_x(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_X);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_ofs_y(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OFS_Y);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_shadow_spread(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_SPREAD);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_shadow_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_shadow_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_dash_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_line_dash_gap(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_DASH_GAP);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_line_rounded(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_ROUNDED);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_line_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_line_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_line_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_LINE_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_arc_width(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_WIDTH);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline bool lv_obj_get_style_arc_rounded(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_ROUNDED);
|
||||
return (bool)v.num;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_arc_color(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_color_t lv_obj_get_style_arc_color_filtered(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_COLOR_FILTERED);
|
||||
return v.color;
|
||||
}
|
||||
|
||||
static inline lv_opa_t lv_obj_get_style_arc_opa(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_OPA);
|
||||
return (lv_opa_t)v.num;
|
||||
}
|
||||
|
||||
static inline const void * lv_obj_get_style_arc_img_src(const struct _lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ARC_IMG_SRC);
|
||||
return (const void *)v.ptr;
|
||||
}
|
||||
|
||||
void lv_obj_set_style_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_min_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_max_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_min_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_max_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_align(struct _lv_obj_t * obj, lv_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_height(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_translate_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_translate_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_zoom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transform_angle(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_top(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_bottom(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_left(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_right(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_row(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_pad_column(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_radius(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_clip_corner(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_filter_dsc_t * value,
|
||||
lv_style_selector_t selector);
|
||||
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
|
||||
lv_style_selector_t selector);
|
||||
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_layout(struct _lv_obj_t * obj, uint16_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_base_dir(struct _lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_dir(struct _lv_obj_t * obj, lv_grad_dir_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_main_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_grad_stop(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_bg_img_tiled(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_side(struct _lv_obj_t * obj, lv_border_side_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_border_post(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_font(struct _lv_obj_t * obj, const lv_font_t * value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_letter_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_line_space(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_decor(struct _lv_obj_t * obj, lv_text_decor_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_text_align(struct _lv_obj_t * obj, lv_text_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_recolor(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_recolor_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_img_recolor_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_outline_pad(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_ofs_x(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_ofs_y(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_spread(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_shadow_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_dash_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_dash_gap(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_line_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_width(struct _lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_rounded(struct _lv_obj_t * obj, bool value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_color(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_color_filtered(struct _lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_arc_img_src(struct _lv_obj_t * obj, const void * value, lv_style_selector_t selector);
|
460
EC600U_lvgl_lib/lvgl/src/core/lv_obj_tree.c
Normal file
460
EC600U_lvgl_lib/lvgl/src/core/lv_obj_tree.c
Normal file
@ -0,0 +1,460 @@
|
||||
/**
|
||||
* @file lv_obj_tree.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lv_obj.h"
|
||||
#include "lv_indev.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../misc/lv_async.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define MY_CLASS &lv_obj_class
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_obj_del_async_cb(void * obj);
|
||||
static void obj_del_core(lv_obj_t * obj);
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_obj_del(lv_obj_t * obj)
|
||||
{
|
||||
LV_LOG_TRACE("begin (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * par = lv_obj_get_parent(obj);
|
||||
if(par) {
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
}
|
||||
|
||||
lv_disp_t * disp = NULL;
|
||||
bool act_scr_del = false;
|
||||
if(par == NULL) {
|
||||
disp = lv_obj_get_disp(obj);
|
||||
if(!disp) return; /*Shouldn't happen*/
|
||||
if(disp->act_scr == obj) act_scr_del = true;
|
||||
}
|
||||
|
||||
obj_del_core(obj);
|
||||
|
||||
/*Call the ancestor's event handler to the parent to notify it about the child delete*/
|
||||
if(par) {
|
||||
lv_obj_readjust_scroll(par, LV_ANIM_OFF);
|
||||
lv_obj_scrollbar_invalidate(par);
|
||||
lv_event_send(par, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_event_send(par, LV_EVENT_CHILD_DELETED, NULL);
|
||||
}
|
||||
|
||||
/*Handle if the active screen was deleted*/
|
||||
if(act_scr_del) {
|
||||
LV_LOG_WARN("the active screen was deleted");
|
||||
disp->act_scr = NULL;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_clean(lv_obj_t * obj)
|
||||
{
|
||||
LV_LOG_TRACE("begin (delete %p)", (void *)obj);
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
/*Just to remove scroll animations if any*/
|
||||
lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF);
|
||||
if(obj->spec_attr) {
|
||||
obj->spec_attr->scroll.x = 0;
|
||||
obj->spec_attr->scroll.y = 0;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
LV_LOG_TRACE("finished (delete %p)", (void *)obj);
|
||||
}
|
||||
|
||||
void lv_obj_del_delayed(lv_obj_t * obj, uint32_t delay_ms)
|
||||
{
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, obj);
|
||||
lv_anim_set_exec_cb(&a, NULL);
|
||||
lv_anim_set_time(&a, 1);
|
||||
lv_anim_set_delay(&a, delay_ms);
|
||||
lv_anim_set_ready_cb(&a, lv_obj_del_anim_ready_cb);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
void lv_obj_del_anim_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_del(a->var);
|
||||
}
|
||||
|
||||
void lv_obj_del_async(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_async_call(lv_obj_del_async_cb, obj);
|
||||
}
|
||||
|
||||
void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_ASSERT_OBJ(parent, MY_CLASS);
|
||||
|
||||
if(obj->parent == NULL) {
|
||||
LV_LOG_WARN("Can't set the parent of a screen");
|
||||
return;
|
||||
}
|
||||
|
||||
if(parent == NULL) {
|
||||
LV_LOG_WARN("Can't set parent == NULL to an object");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
lv_obj_allocate_spec_attr(parent);
|
||||
|
||||
lv_obj_t * old_parent = obj->parent;
|
||||
lv_point_t old_pos;
|
||||
old_pos.y = lv_obj_get_y(obj);
|
||||
|
||||
lv_base_dir_t new_base_dir = lv_obj_get_style_base_dir(parent, LV_PART_MAIN);
|
||||
|
||||
if(new_base_dir != LV_BASE_DIR_RTL) old_pos.x = lv_obj_get_x(obj);
|
||||
else old_pos.x = old_parent->coords.x2 - obj->coords.x2;
|
||||
|
||||
/*Remove the object from the old parent's child list*/
|
||||
int32_t i;
|
||||
for(i = lv_obj_get_index(obj); i <= (int32_t)lv_obj_get_child_cnt(old_parent) - 2; i++) {
|
||||
old_parent->spec_attr->children[i] = old_parent->spec_attr->children[i + 1];
|
||||
}
|
||||
old_parent->spec_attr->child_cnt--;
|
||||
if(old_parent->spec_attr->child_cnt) {
|
||||
old_parent->spec_attr->children = lv_mem_realloc(old_parent->spec_attr->children,
|
||||
old_parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
}
|
||||
else {
|
||||
lv_mem_free(old_parent->spec_attr->children);
|
||||
old_parent->spec_attr->children = NULL;
|
||||
}
|
||||
|
||||
/*Add the child to the new parent as the last (newest child)*/
|
||||
parent->spec_attr->child_cnt++;
|
||||
parent->spec_attr->children = lv_mem_realloc(parent->spec_attr->children,
|
||||
parent->spec_attr->child_cnt * (sizeof(lv_obj_t *)));
|
||||
parent->spec_attr->children[lv_obj_get_child_cnt(parent) - 1] = obj;
|
||||
|
||||
obj->parent = parent;
|
||||
|
||||
if(new_base_dir != LV_BASE_DIR_RTL) {
|
||||
lv_obj_set_pos(obj, old_pos.x, old_pos.y);
|
||||
}
|
||||
else {
|
||||
/*Align to the right in case of RTL base dir*/
|
||||
lv_coord_t new_x = lv_obj_get_width(parent) - old_pos.x - lv_obj_get_width(obj);
|
||||
lv_obj_set_pos(obj, new_x, old_pos.y);
|
||||
}
|
||||
|
||||
/*Notify the original parent because one of its children is lost*/
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(old_parent, LV_EVENT_CHILD_DELETED, NULL);
|
||||
|
||||
/*Notify the new parent about the child*/
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, NULL);
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_obj_move_to_index(lv_obj_t * obj, int32_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const int32_t old_index = lv_obj_get_index(obj);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
|
||||
if(index < 0) return;
|
||||
if(index >= (int32_t) lv_obj_get_child_cnt(parent)) return;
|
||||
if(index == old_index) return;
|
||||
|
||||
int32_t i = old_index;
|
||||
if(index < old_index) {
|
||||
while(i > index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i - 1];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(i < index) {
|
||||
parent->spec_attr->children[i] = parent->spec_attr->children[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
parent->spec_attr->children[index] = obj;
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, NULL);
|
||||
lv_obj_invalidate(parent);
|
||||
}
|
||||
|
||||
void lv_obj_swap(lv_obj_t * obj1, lv_obj_t * obj2)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj1, MY_CLASS);
|
||||
LV_ASSERT_OBJ(obj2, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj1);
|
||||
lv_obj_t * parent2 = lv_obj_get_parent(obj2);
|
||||
|
||||
uint_fast32_t index1 = lv_obj_get_index(obj1);
|
||||
uint_fast32_t index2 = lv_obj_get_index(obj2);
|
||||
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_DELETED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_DELETED, obj1);
|
||||
|
||||
parent->spec_attr->children[index1] = obj2;
|
||||
parent2->spec_attr->children[index2] = obj1;
|
||||
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CHANGED, obj2);
|
||||
lv_event_send(parent, LV_EVENT_CHILD_CREATED, obj2);
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_CHANGED, obj1);
|
||||
lv_event_send(parent2, LV_EVENT_CHILD_CREATED, obj1);
|
||||
|
||||
lv_obj_invalidate(parent);
|
||||
|
||||
if(parent != parent2) {
|
||||
lv_obj_invalidate(parent2);
|
||||
}
|
||||
lv_group_swap_obj(obj1, obj2);
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * par = obj;
|
||||
const lv_obj_t * act_par;
|
||||
|
||||
do {
|
||||
act_par = par;
|
||||
par = lv_obj_get_parent(act_par);
|
||||
} while(par != NULL);
|
||||
|
||||
return (lv_obj_t *)act_par;
|
||||
}
|
||||
|
||||
lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
const lv_obj_t * scr;
|
||||
|
||||
if(obj->parent == NULL) scr = obj; /*`obj` is a screen*/
|
||||
else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/
|
||||
|
||||
lv_disp_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_disp_ll), d) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < d->screen_cnt; i++) {
|
||||
if(d->screens[i] == scr) return d;
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG_WARN("No screen found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj)
|
||||
{
|
||||
if(obj == NULL) return NULL;
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return obj->parent;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, int32_t id)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
if(obj->spec_attr == NULL) return NULL;
|
||||
|
||||
uint32_t idu;
|
||||
if(id < 0) {
|
||||
id = obj->spec_attr->child_cnt + id;
|
||||
if(id < 0) return NULL;
|
||||
idu = (uint32_t) id;
|
||||
}
|
||||
else {
|
||||
idu = id;
|
||||
}
|
||||
|
||||
if(idu >= obj->spec_attr->child_cnt) return NULL;
|
||||
else return obj->spec_attr->children[id];
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_child_cnt(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
if(obj->spec_attr == NULL) return 0;
|
||||
return obj->spec_attr->child_cnt;
|
||||
}
|
||||
|
||||
uint32_t lv_obj_get_index(const lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_t * parent = lv_obj_get_parent(obj);
|
||||
if(parent == NULL) return 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(parent); i++) {
|
||||
if(lv_obj_get_child(parent, i) == obj) return i;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF; /*Shouldn't happen*/
|
||||
}
|
||||
|
||||
void lv_obj_tree_walk(lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
walk_core(start_obj, cb, user_data);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_obj_del_async_cb(void * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_obj_del(obj);
|
||||
}
|
||||
|
||||
static void obj_del_core(lv_obj_t * obj)
|
||||
{
|
||||
/*Let the user free the resources used in `LV_EVENT_DELETE`*/
|
||||
lv_res_t res = lv_event_send(obj, LV_EVENT_DELETE, NULL);
|
||||
if(res == LV_RES_INV) return;
|
||||
|
||||
/*Recursively delete the children*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, 0);
|
||||
while(child) {
|
||||
obj_del_core(child);
|
||||
child = lv_obj_get_child(obj, 0);
|
||||
}
|
||||
|
||||
lv_group_t * group = lv_obj_get_group(obj);
|
||||
|
||||
/*Reset all input devices if the object to delete is used*/
|
||||
lv_indev_t * indev = lv_indev_get_next(NULL);
|
||||
while(indev) {
|
||||
if(indev->proc.types.pointer.act_obj == obj || indev->proc.types.pointer.last_obj == obj) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
if(indev->proc.types.pointer.last_pressed == obj) {
|
||||
indev->proc.types.pointer.last_pressed = NULL;
|
||||
}
|
||||
|
||||
if(indev->group == group && obj == lv_indev_get_obj_act()) {
|
||||
lv_indev_reset(indev, obj);
|
||||
}
|
||||
indev = lv_indev_get_next(indev);
|
||||
}
|
||||
|
||||
/*All children deleted. Now clean up the object specific data*/
|
||||
_lv_obj_destruct(obj);
|
||||
|
||||
/*Remove the screen for the screen list*/
|
||||
if(obj->parent == NULL) {
|
||||
lv_disp_t * disp = lv_obj_get_disp(obj);
|
||||
uint32_t i;
|
||||
/*Find the screen in the list*/
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
if(disp->screens[i] == obj) break;
|
||||
}
|
||||
|
||||
uint32_t id = i;
|
||||
for(i = id; i < disp->screen_cnt - 1; i++) {
|
||||
disp->screens[i] = disp->screens[i + 1];
|
||||
}
|
||||
disp->screen_cnt--;
|
||||
disp->screens = lv_mem_realloc(disp->screens, disp->screen_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
/*Remove the object from the child list of its parent*/
|
||||
else {
|
||||
uint32_t id = lv_obj_get_index(obj);
|
||||
uint32_t i;
|
||||
for(i = id; i < obj->parent->spec_attr->child_cnt - 1; i++) {
|
||||
obj->parent->spec_attr->children[i] = obj->parent->spec_attr->children[i + 1];
|
||||
}
|
||||
obj->parent->spec_attr->child_cnt--;
|
||||
obj->parent->spec_attr->children = lv_mem_realloc(obj->parent->spec_attr->children,
|
||||
obj->parent->spec_attr->child_cnt * sizeof(lv_obj_t *));
|
||||
}
|
||||
|
||||
/*Free the object itself*/
|
||||
lv_mem_free(obj);
|
||||
}
|
||||
|
||||
|
||||
static lv_obj_tree_walk_res_t walk_core(lv_obj_t * obj, lv_obj_tree_walk_cb_t cb, void * user_data)
|
||||
{
|
||||
lv_obj_tree_walk_res_t res = LV_OBJ_TREE_WALK_NEXT;
|
||||
|
||||
if(obj == NULL) {
|
||||
lv_disp_t * disp = lv_disp_get_next(NULL);
|
||||
while(disp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < disp->screen_cnt; i++) {
|
||||
walk_core(disp->screens[i], cb, user_data);
|
||||
}
|
||||
disp = lv_disp_get_next(disp);
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_END; /*The value doesn't matter as it wasn't called recursively*/
|
||||
}
|
||||
|
||||
res = cb(obj, user_data);
|
||||
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
|
||||
if(res != LV_OBJ_TREE_WALK_SKIP_CHILDREN) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < lv_obj_get_child_cnt(obj); i++) {
|
||||
res = walk_core(lv_obj_get_child(obj, i), cb, user_data);
|
||||
if(res == LV_OBJ_TREE_WALK_END) return LV_OBJ_TREE_WALK_END;
|
||||
}
|
||||
}
|
||||
return LV_OBJ_TREE_WALK_NEXT;
|
||||
}
|
172
EC600U_lvgl_lib/lvgl/src/core/lv_obj_tree.h
Normal file
172
EC600U_lvgl_lib/lvgl/src/core/lv_obj_tree.h
Normal file
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @file struct _lv_obj_tree.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_TREE_H
|
||||
#define LV_OBJ_TREE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
struct _lv_obj_class_t;
|
||||
|
||||
typedef enum {
|
||||
LV_OBJ_TREE_WALK_NEXT,
|
||||
LV_OBJ_TREE_WALK_SKIP_CHILDREN,
|
||||
LV_OBJ_TREE_WALK_END,
|
||||
} lv_obj_tree_walk_res_t;
|
||||
|
||||
typedef lv_obj_tree_walk_res_t (*lv_obj_tree_walk_cb_t)(struct _lv_obj_t *, void *);
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Delete an object and all of its children.
|
||||
* Also remove the objects from their group and remove all animations (if any).
|
||||
* Send `LV_EVENT_DELETED` to deleted objects.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_del(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Delete all children of an object.
|
||||
* Also remove the objects from their group and remove all animations (if any).
|
||||
* Send `LV_EVENT_DELETED` to deleted objects.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_clean(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Delete an object after some delay
|
||||
* @param obj pointer to an object
|
||||
* @param delay_ms time to wait before delete in milliseconds
|
||||
*/
|
||||
void lv_obj_del_delayed(struct _lv_obj_t * obj, uint32_t delay_ms);
|
||||
|
||||
/**
|
||||
* A function to be easily used in animation ready callback to delete an object when the animation is ready
|
||||
* @param a pointer to the animation
|
||||
*/
|
||||
void lv_obj_del_anim_ready_cb(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Helper function for asynchronously deleting objects.
|
||||
* Useful for cases where you can't delete an object directly in an `LV_EVENT_DELETE` handler (i.e. parent).
|
||||
* @param obj object to delete
|
||||
* @see lv_async_call
|
||||
*/
|
||||
void lv_obj_del_async(struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Move the parent of an object. The relative coordinates will be kept.
|
||||
*
|
||||
* @param obj pointer to an object whose parent needs to be changed
|
||||
* @param parent pointer to the new parent
|
||||
*/
|
||||
void lv_obj_set_parent(struct _lv_obj_t * obj, struct _lv_obj_t * parent);
|
||||
|
||||
/**
|
||||
* Swap the positions of two objects.
|
||||
* When used in listboxes, it can be used to sort the listbox items.
|
||||
* @param obj1 pointer to the first object
|
||||
* @param obj2 pointer to the second object
|
||||
*/
|
||||
void lv_obj_swap(struct _lv_obj_t * obj1, struct _lv_obj_t * obj2);
|
||||
|
||||
/**
|
||||
* moves the object to the given index in its parent.
|
||||
* When used in listboxes, it can be used to sort the listbox items.
|
||||
* @param obj pointer to the object to be moved.
|
||||
* @param index new index in parent.
|
||||
* @note to move to the foreground: lv_obj_move_to_index(obj, 0)
|
||||
* @note to move forward (up): lv_obj_move_to_index(obj, lv_obj_get_index(obj) - 1)
|
||||
*/
|
||||
void lv_obj_move_to_index(struct _lv_obj_t * obj, int32_t index);
|
||||
|
||||
/**
|
||||
* Get the screen of an object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the object's screen
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_screen(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the display of the object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the object's display
|
||||
*/
|
||||
lv_disp_t * lv_obj_get_disp(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the parent of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the parent of the object. (NULL if `obj` was a screen)
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_parent(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the child of an object by the child's index.
|
||||
* @param obj pointer to an object whose child should be get
|
||||
* @param id the index of the child.
|
||||
* 0: the oldest (firstly created) child
|
||||
* 1: the second oldest
|
||||
* child count-1: the youngest
|
||||
* -1: the youngest
|
||||
* -2: the second youngest
|
||||
* @return pointer to the child or NULL if the index was invalid
|
||||
*/
|
||||
struct _lv_obj_t * lv_obj_get_child(const struct _lv_obj_t * obj, int32_t id);
|
||||
|
||||
/**
|
||||
* Get the number of children
|
||||
* @param obj pointer to an object
|
||||
* @return the number of children
|
||||
*/
|
||||
uint32_t lv_obj_get_child_cnt(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the index of a child.
|
||||
* @param obj pointer to an object
|
||||
* @return the child index of the object.
|
||||
* E.g. 0: the oldest (firstly created child)
|
||||
*/
|
||||
uint32_t lv_obj_get_index(const struct _lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Iterate through all children of any object.
|
||||
* @param start_obj start integrating from this object
|
||||
* @param cb call this callback on the objects
|
||||
* @param user_data pointer to any user related data (will be passed to `cb`)
|
||||
*/
|
||||
void lv_obj_tree_walk(struct _lv_obj_t * start_obj, lv_obj_tree_walk_cb_t cb, void * user_data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_TREE_H*/
|
976
EC600U_lvgl_lib/lvgl/src/core/lv_refr.c
Normal file
976
EC600U_lvgl_lib/lvgl/src/core/lv_refr.c
Normal file
@ -0,0 +1,976 @@
|
||||
/**
|
||||
* @file lv_refr.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_refr.h"
|
||||
#include "lv_disp.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../misc/lv_timer.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
#include "../draw/lv_draw.h"
|
||||
#include "../font/lv_font_fmt_txt.h"
|
||||
|
||||
#if LV_USE_PERF_MONITOR || LV_USE_MEM_MONITOR
|
||||
#include "../widgets/lv_label.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_refr_join_area(void);
|
||||
static void lv_refr_areas(void);
|
||||
static void lv_refr_area(const lv_area_t * area_p);
|
||||
static void lv_refr_area_part(const lv_area_t * area_p);
|
||||
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj);
|
||||
static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p);
|
||||
static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p);
|
||||
static void draw_buf_flush(void);
|
||||
static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static uint32_t px_num;
|
||||
static lv_disp_t * disp_refr; /*Display being refreshed*/
|
||||
#if LV_USE_PERF_MONITOR
|
||||
static uint32_t fps_sum_cnt;
|
||||
static uint32_t fps_sum_all;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_LOG_TRACE_DISP_REFR
|
||||
#define REFR_TRACE(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define REFR_TRACE(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void _lv_refr_init(void)
|
||||
{
|
||||
/*Nothing to do*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the invalidated areas now.
|
||||
* Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process
|
||||
* can prevent the call of `lv_timer_handler`. In this case if the GUI is updated in the process
|
||||
* (e.g. progress bar) this function can be called when the screen should be updated.
|
||||
* @param disp pointer to display to refresh. NULL to refresh all displays.
|
||||
*/
|
||||
void lv_refr_now(lv_disp_t * disp)
|
||||
{
|
||||
lv_anim_refr_now();
|
||||
|
||||
if(disp) {
|
||||
_lv_disp_refr_timer(disp->refr_timer);
|
||||
}
|
||||
else {
|
||||
lv_disp_t * d;
|
||||
d = lv_disp_get_next(NULL);
|
||||
while(d) {
|
||||
_lv_disp_refr_timer(d->refr_timer);
|
||||
d = lv_disp_get_next(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate an area on display to redraw it
|
||||
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
|
||||
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is
|
||||
* only one display)
|
||||
*/
|
||||
void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p)
|
||||
{
|
||||
if(!disp) disp = lv_disp_get_default();
|
||||
if(!disp) return;
|
||||
|
||||
/*Clear the invalidate buffer if the parameter is NULL*/
|
||||
if(area_p == NULL) {
|
||||
disp->inv_p = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t scr_area;
|
||||
scr_area.x1 = 0;
|
||||
scr_area.y1 = 0;
|
||||
scr_area.x2 = lv_disp_get_hor_res(disp) - 1;
|
||||
scr_area.y2 = lv_disp_get_ver_res(disp) - 1;
|
||||
|
||||
lv_area_t com_area;
|
||||
bool suc;
|
||||
|
||||
suc = _lv_area_intersect(&com_area, area_p, &scr_area);
|
||||
if(suc == false) return; /*Out of the screen*/
|
||||
|
||||
/*If there were at least 1 invalid area in full refresh mode, redraw the whole screen*/
|
||||
if(disp->driver->full_refresh) {
|
||||
disp->inv_areas[0] = scr_area;
|
||||
disp->inv_p = 1;
|
||||
lv_timer_resume(disp->refr_timer);
|
||||
return;
|
||||
}
|
||||
|
||||
if(disp->driver->rounder_cb) disp->driver->rounder_cb(disp->driver, &com_area);
|
||||
|
||||
/*Save only if this area is not in one of the saved areas*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < disp->inv_p; i++) {
|
||||
if(_lv_area_is_in(&com_area, &disp->inv_areas[i], 0) != false) return;
|
||||
}
|
||||
|
||||
/*Save the area*/
|
||||
if(disp->inv_p < LV_INV_BUF_SIZE) {
|
||||
lv_area_copy(&disp->inv_areas[disp->inv_p], &com_area);
|
||||
}
|
||||
else { /*If no place for the area add the screen*/
|
||||
disp->inv_p = 0;
|
||||
lv_area_copy(&disp->inv_areas[disp->inv_p], &scr_area);
|
||||
}
|
||||
disp->inv_p++;
|
||||
lv_timer_resume(disp->refr_timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display which is being refreshed
|
||||
* @return the display being refreshed
|
||||
*/
|
||||
lv_disp_t * _lv_refr_get_disp_refreshing(void)
|
||||
{
|
||||
return disp_refr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the display which is being refreshed.
|
||||
* It shouldn't be used directly by the user.
|
||||
* It can be used to trick the drawing functions about there is an active display.
|
||||
* @param the display being refreshed
|
||||
*/
|
||||
void _lv_refr_set_disp_refreshing(lv_disp_t * disp)
|
||||
{
|
||||
disp_refr = disp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to handle the refreshing
|
||||
* @param tmr pointer to the timer itself
|
||||
*/
|
||||
void _lv_disp_refr_timer(lv_timer_t * tmr)
|
||||
{
|
||||
REFR_TRACE("begin");
|
||||
|
||||
uint32_t start = lv_tick_get();
|
||||
volatile uint32_t elaps = 0;
|
||||
|
||||
disp_refr = tmr->user_data;
|
||||
|
||||
#if LV_USE_PERF_MONITOR == 0 && LV_USE_MEM_MONITOR == 0
|
||||
/**
|
||||
* Ensure the timer does not run again automatically.
|
||||
* This is done before refreshing in case refreshing invalidates something else.
|
||||
*/
|
||||
lv_timer_pause(tmr);
|
||||
#endif
|
||||
|
||||
/*Refresh the screen's layout if required*/
|
||||
lv_obj_update_layout(disp_refr->act_scr);
|
||||
if(disp_refr->prev_scr) lv_obj_update_layout(disp_refr->prev_scr);
|
||||
|
||||
lv_obj_update_layout(disp_refr->top_layer);
|
||||
lv_obj_update_layout(disp_refr->sys_layer);
|
||||
|
||||
/*Do nothing if there is no active screen*/
|
||||
if(disp_refr->act_scr == NULL) {
|
||||
disp_refr->inv_p = 0;
|
||||
LV_LOG_WARN("there is no active screen");
|
||||
REFR_TRACE("finished");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_refr_join_area();
|
||||
|
||||
lv_refr_areas();
|
||||
|
||||
/*If refresh happened ...*/
|
||||
if(disp_refr->inv_p != 0) {
|
||||
if(disp_refr->driver->full_refresh) {
|
||||
draw_buf_flush();
|
||||
}
|
||||
|
||||
/*Clean up*/
|
||||
lv_memset_00(disp_refr->inv_areas, sizeof(disp_refr->inv_areas));
|
||||
lv_memset_00(disp_refr->inv_area_joined, sizeof(disp_refr->inv_area_joined));
|
||||
disp_refr->inv_p = 0;
|
||||
|
||||
elaps = lv_tick_elaps(start);
|
||||
/*Call monitor cb if present*/
|
||||
if(disp_refr->driver->monitor_cb) {
|
||||
disp_refr->driver->monitor_cb(disp_refr->driver, elaps, px_num);
|
||||
}
|
||||
}
|
||||
|
||||
lv_mem_buf_free_all();
|
||||
_lv_font_clean_up_fmt_txt();
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
_lv_draw_mask_cleanup();
|
||||
#endif
|
||||
|
||||
#if LV_USE_PERF_MONITOR && LV_USE_LABEL
|
||||
static lv_obj_t * perf_label = NULL;
|
||||
if(perf_label == NULL) {
|
||||
perf_label = lv_label_create(lv_layer_sys());
|
||||
lv_obj_set_style_bg_opa(perf_label, LV_OPA_50, 0);
|
||||
lv_obj_set_style_bg_color(perf_label, lv_color_black(), 0);
|
||||
lv_obj_set_style_text_color(perf_label, lv_color_white(), 0);
|
||||
lv_obj_set_style_pad_top(perf_label, 3, 0);
|
||||
lv_obj_set_style_pad_bottom(perf_label, 3, 0);
|
||||
lv_obj_set_style_pad_left(perf_label, 3, 0);
|
||||
lv_obj_set_style_pad_right(perf_label, 3, 0);
|
||||
lv_obj_set_style_text_align(perf_label, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
lv_label_set_text(perf_label, "?");
|
||||
lv_obj_align(perf_label, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
}
|
||||
|
||||
static uint32_t perf_last_time = 0;
|
||||
static uint32_t elaps_sum = 0;
|
||||
static uint32_t frame_cnt = 0;
|
||||
if(lv_tick_elaps(perf_last_time) < 300) {
|
||||
if(px_num > 5000) {
|
||||
elaps_sum += elaps;
|
||||
frame_cnt ++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
perf_last_time = lv_tick_get();
|
||||
uint32_t fps_limit = 1000 / disp_refr->refr_timer->period;
|
||||
unsigned int fps;
|
||||
|
||||
if(elaps_sum == 0) elaps_sum = 1;
|
||||
if(frame_cnt == 0) fps = fps_limit;
|
||||
else fps = (1000 * frame_cnt) / elaps_sum;
|
||||
elaps_sum = 0;
|
||||
frame_cnt = 0;
|
||||
if(fps > fps_limit) fps = fps_limit;
|
||||
|
||||
fps_sum_all += fps;
|
||||
fps_sum_cnt ++;
|
||||
unsigned int cpu = 100 - lv_timer_get_idle();
|
||||
lv_label_set_text_fmt(perf_label, "%u FPS\n%u%% CPU", fps, cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LV_USE_MEM_MONITOR && LV_MEM_CUSTOM == 0 && LV_USE_LABEL
|
||||
static lv_obj_t * mem_label = NULL;
|
||||
if(mem_label == NULL) {
|
||||
mem_label = lv_label_create(lv_layer_sys());
|
||||
lv_obj_set_style_bg_opa(mem_label, LV_OPA_50, 0);
|
||||
lv_obj_set_style_bg_color(mem_label, lv_color_black(), 0);
|
||||
lv_obj_set_style_text_color(mem_label, lv_color_white(), 0);
|
||||
lv_obj_set_style_pad_top(mem_label, 3, 0);
|
||||
lv_obj_set_style_pad_bottom(mem_label, 3, 0);
|
||||
lv_obj_set_style_pad_left(mem_label, 3, 0);
|
||||
lv_obj_set_style_pad_right(mem_label, 3, 0);
|
||||
lv_label_set_text(mem_label, "?");
|
||||
lv_obj_align(mem_label, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
static uint32_t mem_last_time = 0;
|
||||
if(lv_tick_elaps(mem_last_time) > 300) {
|
||||
mem_last_time = lv_tick_get();
|
||||
lv_mem_monitor_t mon;
|
||||
lv_mem_monitor(&mon);
|
||||
uint32_t used_size = mon.total_size - mon.free_size;;
|
||||
uint32_t used_kb = used_size / 1024;
|
||||
uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102;
|
||||
lv_label_set_text_fmt(mem_label, "%d.%d kB used (%d %%)\n%d%% frag.", used_kb, used_kb_tenth, mon.used_pct,
|
||||
mon.frag_pct);
|
||||
}
|
||||
#endif
|
||||
|
||||
REFR_TRACE("finished");
|
||||
}
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
uint32_t lv_refr_get_fps_avg(void)
|
||||
{
|
||||
return fps_sum_all / fps_sum_cnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Join the areas which has got common parts
|
||||
*/
|
||||
static void lv_refr_join_area(void)
|
||||
{
|
||||
uint32_t join_from;
|
||||
uint32_t join_in;
|
||||
lv_area_t joined_area;
|
||||
for(join_in = 0; join_in < disp_refr->inv_p; join_in++) {
|
||||
if(disp_refr->inv_area_joined[join_in] != 0) continue;
|
||||
|
||||
/*Check all areas to join them in 'join_in'*/
|
||||
for(join_from = 0; join_from < disp_refr->inv_p; join_from++) {
|
||||
/*Handle only unjoined areas and ignore itself*/
|
||||
if(disp_refr->inv_area_joined[join_from] != 0 || join_in == join_from) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check if the areas are on each other*/
|
||||
if(_lv_area_is_on(&disp_refr->inv_areas[join_in], &disp_refr->inv_areas[join_from]) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_lv_area_join(&joined_area, &disp_refr->inv_areas[join_in], &disp_refr->inv_areas[join_from]);
|
||||
|
||||
/*Join two area only if the joined area size is smaller*/
|
||||
if(lv_area_get_size(&joined_area) < (lv_area_get_size(&disp_refr->inv_areas[join_in]) +
|
||||
lv_area_get_size(&disp_refr->inv_areas[join_from]))) {
|
||||
lv_area_copy(&disp_refr->inv_areas[join_in], &joined_area);
|
||||
|
||||
/*Mark 'join_form' is joined into 'join_in'*/
|
||||
disp_refr->inv_area_joined[join_from] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the joined areas
|
||||
*/
|
||||
static void lv_refr_areas(void)
|
||||
{
|
||||
px_num = 0;
|
||||
|
||||
if(disp_refr->inv_p == 0) return;
|
||||
|
||||
/*Find the last area which will be drawn*/
|
||||
int32_t i;
|
||||
int32_t last_i = 0;
|
||||
for(i = disp_refr->inv_p - 1; i >= 0; i--) {
|
||||
if(disp_refr->inv_area_joined[i] == 0) {
|
||||
last_i = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
disp_refr->driver->draw_buf->last_area = 0;
|
||||
disp_refr->driver->draw_buf->last_part = 0;
|
||||
|
||||
for(i = 0; i < disp_refr->inv_p; i++) {
|
||||
/*Refresh the unjoined areas*/
|
||||
if(disp_refr->inv_area_joined[i] == 0) {
|
||||
|
||||
if(i == last_i) disp_refr->driver->draw_buf->last_area = 1;
|
||||
disp_refr->driver->draw_buf->last_part = 0;
|
||||
lv_refr_area(&disp_refr->inv_areas[i]);
|
||||
|
||||
px_num += lv_area_get_size(&disp_refr->inv_areas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh an area if there is Virtual Display Buffer
|
||||
* @param area_p pointer to an area to refresh
|
||||
*/
|
||||
static void lv_refr_area(const lv_area_t * area_p)
|
||||
{
|
||||
/*With full refresh just redraw directly into the buffer*/
|
||||
if(disp_refr->driver->full_refresh) {
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||
draw_buf->area.x1 = 0;
|
||||
draw_buf->area.x2 = lv_disp_get_hor_res(disp_refr) - 1;
|
||||
draw_buf->area.y1 = 0;
|
||||
draw_buf->area.y2 = lv_disp_get_ver_res(disp_refr) - 1;
|
||||
disp_refr->driver->draw_buf->last_part = 1;
|
||||
lv_refr_area_part(area_p);
|
||||
return;
|
||||
}
|
||||
|
||||
/*Normal refresh: draw the area in parts*/
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||
/*Calculate the max row num*/
|
||||
lv_coord_t w = lv_area_get_width(area_p);
|
||||
lv_coord_t h = lv_area_get_height(area_p);
|
||||
lv_coord_t y2 = area_p->y2 >= lv_disp_get_ver_res(disp_refr) ?
|
||||
lv_disp_get_ver_res(disp_refr) - 1 : area_p->y2;
|
||||
|
||||
int32_t max_row = (uint32_t)draw_buf->size / w;
|
||||
|
||||
if(max_row > h) max_row = h;
|
||||
|
||||
/*Round down the lines of draw_buf if rounding is added*/
|
||||
if(disp_refr->driver->rounder_cb) {
|
||||
lv_area_t tmp;
|
||||
tmp.x1 = 0;
|
||||
tmp.x2 = 0;
|
||||
tmp.y1 = 0;
|
||||
|
||||
lv_coord_t h_tmp = max_row;
|
||||
do {
|
||||
tmp.y2 = h_tmp - 1;
|
||||
disp_refr->driver->rounder_cb(disp_refr->driver, &tmp);
|
||||
|
||||
/*If this height fits into `max_row` then fine*/
|
||||
if(lv_area_get_height(&tmp) <= max_row) break;
|
||||
|
||||
/*Decrement the height of the area until it fits into `max_row` after rounding*/
|
||||
h_tmp--;
|
||||
} while(h_tmp > 0);
|
||||
|
||||
if(h_tmp <= 0) {
|
||||
LV_LOG_WARN("Can't set draw_buf height using the round function. (Wrong round_cb or to "
|
||||
"small draw_buf)");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
max_row = tmp.y2 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*Always use the full row*/
|
||||
lv_coord_t row;
|
||||
lv_coord_t row_last = 0;
|
||||
for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
draw_buf->area.x1 = area_p->x1;
|
||||
draw_buf->area.x2 = area_p->x2;
|
||||
draw_buf->area.y1 = row;
|
||||
draw_buf->area.y2 = row + max_row - 1;
|
||||
if(draw_buf->area.y2 > y2) draw_buf->area.y2 = y2;
|
||||
row_last = draw_buf->area.y2;
|
||||
if(y2 == row_last) disp_refr->driver->draw_buf->last_part = 1;
|
||||
lv_refr_area_part(area_p);
|
||||
}
|
||||
|
||||
/*If the last y coordinates are not handled yet ...*/
|
||||
if(y2 != row_last) {
|
||||
/*Calc. the next y coordinates of draw_buf*/
|
||||
draw_buf->area.x1 = area_p->x1;
|
||||
draw_buf->area.x2 = area_p->x2;
|
||||
draw_buf->area.y1 = row;
|
||||
draw_buf->area.y2 = y2;
|
||||
|
||||
disp_refr->driver->draw_buf->last_part = 1;
|
||||
lv_refr_area_part(area_p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh a part of an area which is on the actual Virtual Display Buffer
|
||||
* @param area_p pointer to an area to refresh
|
||||
*/
|
||||
static void lv_refr_area_part(const lv_area_t * area_p)
|
||||
{
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||
|
||||
/* Below the `area_p` area will be redrawn into the draw buffer.
|
||||
* In single buffered mode wait here until the buffer is freed.*/
|
||||
if(draw_buf->buf1 && !draw_buf->buf2) {
|
||||
while(draw_buf->flushing) {
|
||||
if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver);
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t * top_act_scr = NULL;
|
||||
lv_obj_t * top_prev_scr = NULL;
|
||||
|
||||
/*Get the new mask from the original area and the act. draw_buf
|
||||
It will be a part of 'area_p'*/
|
||||
lv_area_t start_mask;
|
||||
_lv_area_intersect(&start_mask, area_p, &draw_buf->area);
|
||||
|
||||
/*Get the most top object which is not covered by others*/
|
||||
top_act_scr = lv_refr_get_top_obj(&start_mask, lv_disp_get_scr_act(disp_refr));
|
||||
if(disp_refr->prev_scr) {
|
||||
top_prev_scr = lv_refr_get_top_obj(&start_mask, disp_refr->prev_scr);
|
||||
}
|
||||
|
||||
/*Draw a display background if there is no top object*/
|
||||
if(top_act_scr == NULL && top_prev_scr == NULL) {
|
||||
if(disp_refr->bg_fn) {
|
||||
disp_refr->bg_fn(&start_mask);
|
||||
} else if(disp_refr->bg_img) {
|
||||
lv_draw_img_dsc_t dsc;
|
||||
lv_draw_img_dsc_init(&dsc);
|
||||
dsc.opa = disp_refr->bg_opa;
|
||||
lv_img_header_t header;
|
||||
lv_res_t res;
|
||||
res = lv_img_decoder_get_info(disp_refr->bg_img, &header);
|
||||
if(res == LV_RES_OK) {
|
||||
lv_area_t a;
|
||||
lv_area_set(&a, 0, 0, header.w - 1, header.h - 1);
|
||||
lv_draw_img(&a, &start_mask, disp_refr->bg_img, &dsc);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Can't draw the background image");
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_draw_rect_dsc_t dsc;
|
||||
lv_draw_rect_dsc_init(&dsc);
|
||||
dsc.bg_color = disp_refr->bg_color;
|
||||
dsc.bg_opa = disp_refr->bg_opa;
|
||||
lv_draw_rect(&start_mask, &start_mask, &dsc);
|
||||
|
||||
}
|
||||
}
|
||||
/*Refresh the previous screen if any*/
|
||||
if(disp_refr->prev_scr) {
|
||||
/*Get the most top object which is not covered by others*/
|
||||
if(top_prev_scr == NULL) {
|
||||
top_prev_scr = disp_refr->prev_scr;
|
||||
}
|
||||
/*Do the refreshing from the top object*/
|
||||
lv_refr_obj_and_children(top_prev_scr, &start_mask);
|
||||
|
||||
}
|
||||
|
||||
if(top_act_scr == NULL) {
|
||||
top_act_scr = disp_refr->act_scr;
|
||||
}
|
||||
/*Do the refreshing from the top object*/
|
||||
lv_refr_obj_and_children(top_act_scr, &start_mask);
|
||||
|
||||
/*Also refresh top and sys layer unconditionally*/
|
||||
lv_refr_obj_and_children(lv_disp_get_layer_top(disp_refr), &start_mask);
|
||||
lv_refr_obj_and_children(lv_disp_get_layer_sys(disp_refr), &start_mask);
|
||||
|
||||
/*In true double buffered mode flush only once when all areas were rendered.
|
||||
*In normal mode flush after every area*/
|
||||
if(disp_refr->driver->full_refresh == false) {
|
||||
draw_buf_flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the most top object which fully covers an area
|
||||
* @param area_p pointer to an area
|
||||
* @param obj the first object to start the searching (typically a screen)
|
||||
* @return
|
||||
*/
|
||||
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * found_p = NULL;
|
||||
|
||||
/*If this object is fully cover the draw area check the children too*/
|
||||
if(_lv_area_is_in(area_p, &obj->coords, 0) && lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN) == false) {
|
||||
lv_cover_check_info_t info;
|
||||
info.res = LV_COVER_RES_COVER;
|
||||
info.area = area_p;
|
||||
lv_event_send(obj, LV_EVENT_COVER_CHECK, &info);
|
||||
if(info.res == LV_COVER_RES_MASKED) return NULL;
|
||||
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
found_p = lv_refr_get_top_obj(area_p, child);
|
||||
|
||||
/*If a children is ok then break*/
|
||||
if(found_p != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*If no better children use this object*/
|
||||
if(found_p == NULL) {
|
||||
if(info.res == LV_COVER_RES_COVER) {
|
||||
found_p = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the refreshing from an object. Draw all its children and the youngers too.
|
||||
* @param top_p pointer to an objects. Start the drawing from it.
|
||||
* @param mask_p pointer to an area, the objects will be drawn only here
|
||||
*/
|
||||
static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p)
|
||||
{
|
||||
/*Normally always will be a top_obj (at least the screen)
|
||||
*but in special cases (e.g. if the screen has alpha) it won't.
|
||||
*In this case use the screen directly*/
|
||||
if(top_p == NULL) top_p = lv_disp_get_scr_act(disp_refr);
|
||||
if(top_p == NULL) return; /*Shouldn't happen*/
|
||||
|
||||
/*Refresh the top object and its children*/
|
||||
lv_refr_obj(top_p, mask_p);
|
||||
|
||||
/*Draw the 'younger' sibling objects because they can be on top_obj*/
|
||||
lv_obj_t * par;
|
||||
lv_obj_t * border_p = top_p;
|
||||
|
||||
par = lv_obj_get_parent(top_p);
|
||||
|
||||
/*Do until not reach the screen*/
|
||||
while(par != NULL) {
|
||||
bool go = false;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(par);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = par->spec_attr->children[i];
|
||||
if(!go) {
|
||||
if(child == border_p) go = true;
|
||||
}
|
||||
else {
|
||||
/*Refresh the objects*/
|
||||
lv_refr_obj(child, mask_p);
|
||||
}
|
||||
}
|
||||
|
||||
/*Call the post draw draw function of the parents of the to object*/
|
||||
lv_event_send(par, LV_EVENT_DRAW_POST_BEGIN, (void *)mask_p);
|
||||
lv_event_send(par, LV_EVENT_DRAW_POST, (void *)mask_p);
|
||||
lv_event_send(par, LV_EVENT_DRAW_POST_END, (void *)mask_p);
|
||||
|
||||
/*The new border will be the last parents,
|
||||
*so the 'younger' brothers of parent will be refreshed*/
|
||||
border_p = par;
|
||||
/*Go a level deeper*/
|
||||
par = lv_obj_get_parent(par);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh an object an all of its children. (Called recursively)
|
||||
* @param obj pointer to an object to refresh
|
||||
* @param mask_ori_p pointer to an area, the objects will be drawn only here
|
||||
*/
|
||||
static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
|
||||
{
|
||||
/*Do not refresh hidden objects*/
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return;
|
||||
|
||||
bool union_ok; /*Store the return value of area_union*/
|
||||
/*Truncate the original mask to the coordinates of the parent
|
||||
*because the parent and its children are visible only here*/
|
||||
lv_area_t obj_mask;
|
||||
lv_area_t obj_ext_mask;
|
||||
lv_area_t obj_area;
|
||||
lv_coord_t ext_size = _lv_obj_get_ext_draw_size(obj);
|
||||
lv_obj_get_coords(obj, &obj_area);
|
||||
obj_area.x1 -= ext_size;
|
||||
obj_area.y1 -= ext_size;
|
||||
obj_area.x2 += ext_size;
|
||||
obj_area.y2 += ext_size;
|
||||
union_ok = _lv_area_intersect(&obj_ext_mask, mask_ori_p, &obj_area);
|
||||
|
||||
/*Draw the parent and its children only if they ore on 'mask_parent'*/
|
||||
if(union_ok != false) {
|
||||
/*Redraw the object*/
|
||||
lv_event_send(obj, LV_EVENT_DRAW_MAIN_BEGIN, &obj_ext_mask);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_MAIN, &obj_ext_mask);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, &obj_ext_mask);
|
||||
|
||||
#if LV_USE_REFR_DEBUG
|
||||
lv_color_t debug_color = lv_color_make(lv_rand(0, 0xFF), lv_rand(0, 0xFF), lv_rand(0, 0xFF));
|
||||
lv_draw_rect_dsc_t draw_dsc;
|
||||
lv_draw_rect_dsc_init(&draw_dsc);
|
||||
draw_dsc.bg_color.full = debug_color.full;
|
||||
draw_dsc.bg_opa = LV_OPA_20;
|
||||
draw_dsc.border_width = 1;
|
||||
draw_dsc.border_opa = LV_OPA_30;
|
||||
draw_dsc.border_color = debug_color;
|
||||
lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &draw_dsc);
|
||||
#endif
|
||||
/*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/
|
||||
lv_obj_get_coords(obj, &obj_area);
|
||||
union_ok = _lv_area_intersect(&obj_mask, mask_ori_p, &obj_area);
|
||||
if(union_ok != false) {
|
||||
lv_area_t mask_child; /*Mask from obj and its child*/
|
||||
lv_area_t child_area;
|
||||
uint32_t i;
|
||||
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
|
||||
for(i = 0; i < child_cnt; i++) {
|
||||
lv_obj_t * child = obj->spec_attr->children[i];
|
||||
lv_obj_get_coords(child, &child_area);
|
||||
ext_size = _lv_obj_get_ext_draw_size(child);
|
||||
child_area.x1 -= ext_size;
|
||||
child_area.y1 -= ext_size;
|
||||
child_area.x2 += ext_size;
|
||||
child_area.y2 += ext_size;
|
||||
/*Get the union (common parts) of original mask (from obj)
|
||||
*and its child*/
|
||||
union_ok = _lv_area_intersect(&mask_child, &obj_mask, &child_area);
|
||||
|
||||
/*If the parent and the child has common area then refresh the child*/
|
||||
if(union_ok) {
|
||||
/*Refresh the next children*/
|
||||
lv_refr_obj(child, &mask_child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*If all the children are redrawn make 'post draw' draw*/
|
||||
lv_event_send(obj, LV_EVENT_DRAW_POST_BEGIN, &obj_ext_mask);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_POST, &obj_ext_mask);
|
||||
lv_event_send(obj, LV_EVENT_DRAW_POST_END, &obj_ext_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_buf_rotate_180(lv_disp_drv_t * drv, lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
lv_coord_t area_w = lv_area_get_width(area);
|
||||
lv_coord_t area_h = lv_area_get_height(area);
|
||||
uint32_t total = area_w * area_h;
|
||||
/*Swap the beginning and end values*/
|
||||
lv_color_t tmp;
|
||||
uint32_t i = total - 1, j = 0;
|
||||
while(i > j) {
|
||||
tmp = color_p[i];
|
||||
color_p[i] = color_p[j];
|
||||
color_p[j] = tmp;
|
||||
i--;
|
||||
j++;
|
||||
}
|
||||
lv_coord_t tmp_coord;
|
||||
tmp_coord = area->y2;
|
||||
area->y2 = drv->ver_res - area->y1 - 1;
|
||||
area->y1 = drv->ver_res - tmp_coord - 1;
|
||||
tmp_coord = area->x2;
|
||||
area->x2 = drv->hor_res - area->x1 - 1;
|
||||
area->x1 = drv->hor_res - tmp_coord - 1;
|
||||
}
|
||||
|
||||
static LV_ATTRIBUTE_FAST_MEM void draw_buf_rotate_90(bool invert_i, lv_coord_t area_w, lv_coord_t area_h,
|
||||
lv_color_t * orig_color_p, lv_color_t * rot_buf)
|
||||
{
|
||||
|
||||
uint32_t invert = (area_w * area_h) - 1;
|
||||
uint32_t initial_i = ((area_w - 1) * area_h);
|
||||
for(lv_coord_t y = 0; y < area_h; y++) {
|
||||
uint32_t i = initial_i + y;
|
||||
if(invert_i)
|
||||
i = invert - i;
|
||||
for(lv_coord_t x = 0; x < area_w; x++) {
|
||||
rot_buf[i] = *(orig_color_p++);
|
||||
if(invert_i)
|
||||
i += area_h;
|
||||
else
|
||||
i -= area_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for draw_buf_rotate_90_sqr. Given a list of four numbers, rotate the entire list to the left.
|
||||
*/
|
||||
static inline void draw_buf_rotate4(lv_color_t * a, lv_color_t * b, lv_color_t * c, lv_color_t * d)
|
||||
{
|
||||
lv_color_t tmp;
|
||||
tmp = *a;
|
||||
*a = *b;
|
||||
*b = *c;
|
||||
*c = *d;
|
||||
*d = tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a square image 90/270 degrees in place.
|
||||
* @note inspired by https://stackoverflow.com/a/43694906
|
||||
*/
|
||||
static void draw_buf_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color_p)
|
||||
{
|
||||
for(lv_coord_t i = 0; i < w / 2; i++) {
|
||||
for(lv_coord_t j = 0; j < (w + 1) / 2; j++) {
|
||||
lv_coord_t inv_i = (w - 1) - i;
|
||||
lv_coord_t inv_j = (w - 1) - j;
|
||||
if(is_270) {
|
||||
draw_buf_rotate4(
|
||||
&color_p[i * w + j],
|
||||
&color_p[inv_j * w + i],
|
||||
&color_p[inv_i * w + inv_j],
|
||||
&color_p[j * w + inv_i]
|
||||
);
|
||||
}
|
||||
else {
|
||||
draw_buf_rotate4(
|
||||
&color_p[i * w + j],
|
||||
&color_p[j * w + inv_i],
|
||||
&color_p[inv_i * w + inv_j],
|
||||
&color_p[inv_j * w + i]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the draw_buf to the display's native orientation.
|
||||
*/
|
||||
static void draw_buf_rotate(lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
lv_disp_drv_t * drv = disp_refr->driver;
|
||||
if(disp_refr->driver->full_refresh && drv->sw_rotate) {
|
||||
LV_LOG_ERROR("cannot rotate a full refreshed display!");
|
||||
return;
|
||||
}
|
||||
if(drv->rotated == LV_DISP_ROT_180) {
|
||||
draw_buf_rotate_180(drv, area, color_p);
|
||||
call_flush_cb(drv, area, color_p);
|
||||
}
|
||||
else if(drv->rotated == LV_DISP_ROT_90 || drv->rotated == LV_DISP_ROT_270) {
|
||||
/*Allocate a temporary buffer to store rotated image*/
|
||||
lv_color_t * rot_buf = NULL;
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||
lv_coord_t area_w = lv_area_get_width(area);
|
||||
lv_coord_t area_h = lv_area_get_height(area);
|
||||
/*Determine the maximum number of rows that can be rotated at a time*/
|
||||
lv_coord_t max_row = LV_MIN((lv_coord_t)((LV_DISP_ROT_MAX_BUF / sizeof(lv_color_t)) / area_w), area_h);
|
||||
lv_coord_t init_y_off;
|
||||
init_y_off = area->y1;
|
||||
if(drv->rotated == LV_DISP_ROT_90) {
|
||||
area->y2 = drv->ver_res - area->x1 - 1;
|
||||
area->y1 = area->y2 - area_w + 1;
|
||||
}
|
||||
else {
|
||||
area->y1 = area->x1;
|
||||
area->y2 = area->y1 + area_w - 1;
|
||||
}
|
||||
|
||||
/*Rotate the screen in chunks, flushing after each one*/
|
||||
lv_coord_t row = 0;
|
||||
while(row < area_h) {
|
||||
lv_coord_t height = LV_MIN(max_row, area_h - row);
|
||||
draw_buf->flushing = 1;
|
||||
if((row == 0) && (area_h >= area_w)) {
|
||||
/*Rotate the initial area as a square*/
|
||||
height = area_w;
|
||||
draw_buf_rotate_90_sqr(drv->rotated == LV_DISP_ROT_270, area_w, color_p);
|
||||
if(drv->rotated == LV_DISP_ROT_90) {
|
||||
area->x1 = init_y_off;
|
||||
area->x2 = init_y_off + area_w - 1;
|
||||
}
|
||||
else {
|
||||
area->x2 = drv->hor_res - 1 - init_y_off;
|
||||
area->x1 = area->x2 - area_w + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*Rotate other areas using a maximum buffer size*/
|
||||
if(rot_buf == NULL) rot_buf = lv_mem_buf_get(LV_DISP_ROT_MAX_BUF);
|
||||
draw_buf_rotate_90(drv->rotated == LV_DISP_ROT_270, area_w, height, color_p, rot_buf);
|
||||
|
||||
if(drv->rotated == LV_DISP_ROT_90) {
|
||||
area->x1 = init_y_off + row;
|
||||
area->x2 = init_y_off + row + height - 1;
|
||||
}
|
||||
else {
|
||||
area->x2 = drv->hor_res - 1 - init_y_off - row;
|
||||
area->x1 = area->x2 - height + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The original part (chunk of the current area) were split into more parts here.
|
||||
* Set the original last_part flag on the last part of rotation. */
|
||||
if(row + height >= area_h && draw_buf->last_area && draw_buf->last_part) {
|
||||
draw_buf->flushing_last = 1;
|
||||
}
|
||||
else {
|
||||
draw_buf->flushing_last = 0;
|
||||
}
|
||||
|
||||
/*Flush the completed area to the display*/
|
||||
call_flush_cb(drv, area, rot_buf == NULL ? color_p : rot_buf);
|
||||
/*FIXME: Rotation forces legacy behavior where rendering and flushing are done serially*/
|
||||
while(draw_buf->flushing) {
|
||||
if(drv->wait_cb) drv->wait_cb(drv);
|
||||
}
|
||||
color_p += area_w * height;
|
||||
row += height;
|
||||
}
|
||||
/*Free the allocated buffer at the end if necessary*/
|
||||
if(rot_buf != NULL) lv_mem_buf_release(rot_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the content of the draw buffer
|
||||
*/
|
||||
static void draw_buf_flush(void)
|
||||
{
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);
|
||||
lv_color_t * color_p = draw_buf->buf_act;
|
||||
|
||||
/*Flush the rendered content to the display*/
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
if(disp->driver->gpu_wait_cb) disp->driver->gpu_wait_cb(disp->driver);
|
||||
|
||||
/* In double buffered mode wait until the other buffer is freed
|
||||
* and driver is ready to receive the new buffer */
|
||||
if(draw_buf->buf1 && draw_buf->buf2) {
|
||||
while(draw_buf->flushing) {
|
||||
if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver);
|
||||
}
|
||||
}
|
||||
|
||||
draw_buf->flushing = 1;
|
||||
|
||||
if(disp_refr->driver->draw_buf->last_area && disp_refr->driver->draw_buf->last_part) draw_buf->flushing_last = 1;
|
||||
else draw_buf->flushing_last = 0;
|
||||
|
||||
if(disp->driver->flush_cb) {
|
||||
/*Rotate the buffer to the display's native orientation if necessary*/
|
||||
if(disp->driver->rotated != LV_DISP_ROT_NONE && disp->driver->sw_rotate) {
|
||||
draw_buf_rotate(&draw_buf->area, draw_buf->buf_act);
|
||||
}
|
||||
else {
|
||||
call_flush_cb(disp->driver, &draw_buf->area, color_p);
|
||||
}
|
||||
}
|
||||
if(draw_buf->buf1 && draw_buf->buf2) {
|
||||
if(draw_buf->buf_act == draw_buf->buf1)
|
||||
draw_buf->buf_act = draw_buf->buf2;
|
||||
else
|
||||
draw_buf->buf_act = draw_buf->buf1;
|
||||
}
|
||||
}
|
||||
|
||||
static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
|
||||
{
|
||||
REFR_TRACE("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", area->x1, area->y1, area->x2, area->y2,
|
||||
(void *)color_p);
|
||||
|
||||
lv_area_t offset_area = {
|
||||
.x1 = area->x1 + drv->offset_x,
|
||||
.y1 = area->y1 + drv->offset_y,
|
||||
.x2 = area->x2 + drv->offset_x,
|
||||
.y2 = area->y2 + drv->offset_y
|
||||
};
|
||||
|
||||
drv->flush_cb(drv, &offset_area, color_p);
|
||||
}
|
103
EC600U_lvgl_lib/lvgl/src/core/lv_refr.h
Normal file
103
EC600U_lvgl_lib/lvgl/src/core/lv_refr.h
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file lv_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_REFR_H
|
||||
#define LV_REFR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_REFR_TASK_PRIO LV_TASK_PRIO_MID
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void _lv_refr_init(void);
|
||||
|
||||
/**
|
||||
* Redraw the invalidated areas now.
|
||||
* Normally the redrawing is periodically executed in `lv_timer_handler` but a long blocking process
|
||||
* can prevent the call of `lv_timer_handler`. In this case if the GUI is updated in the process
|
||||
* (e.g. progress bar) this function can be called when the screen should be updated.
|
||||
* @param disp pointer to display to refresh. NULL to refresh all displays.
|
||||
*/
|
||||
void lv_refr_now(lv_disp_t * disp);
|
||||
|
||||
/**
|
||||
* Invalidate an area on display to redraw it
|
||||
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
|
||||
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is
|
||||
* only one display)
|
||||
*/
|
||||
void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p);
|
||||
|
||||
/**
|
||||
* Get the display which is being refreshed
|
||||
* @return the display being refreshed
|
||||
*/
|
||||
lv_disp_t * _lv_refr_get_disp_refreshing(void);
|
||||
|
||||
/**
|
||||
* Set the display which is being refreshed.
|
||||
* It shouldn't be used directly by the user.
|
||||
* It can be used to trick the drawing functions about there is an active display.
|
||||
* @param the display being refreshed
|
||||
*/
|
||||
void _lv_refr_set_disp_refreshing(lv_disp_t * disp);
|
||||
|
||||
#if LV_USE_PERF_MONITOR
|
||||
/**
|
||||
* Get the average FPS since start up
|
||||
* @return the average FPS
|
||||
*/
|
||||
uint32_t lv_refr_get_fps_avg(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called periodically to handle the refreshing
|
||||
* @param timer pointer to the timer itself
|
||||
*/
|
||||
void _lv_disp_refr_timer(lv_timer_t * timer);
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_REFR_H*/
|
118
EC600U_lvgl_lib/lvgl/src/core/lv_theme.c
Normal file
118
EC600U_lvgl_lib/lvgl/src/core/lv_theme.c
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file lv_theme.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_disp_t * disp = obj ? lv_obj_get_disp(obj) : lv_disp_get_default();
|
||||
return lv_disp_get_theme(disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active theme on an object
|
||||
* @param obj pointer to an object
|
||||
* @param name the name of the theme element to apply. E.g. `LV_THEME_BTN`
|
||||
*/
|
||||
void lv_theme_apply(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
if(th == NULL) return;
|
||||
|
||||
lv_obj_remove_style_all(obj);
|
||||
|
||||
apply_theme(th, obj); /*Apply the theme including the base theme(s)*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a base theme for a theme.
|
||||
* The styles from the base them will be added before the styles of the current theme.
|
||||
* Arbitrary long chain of themes can be created by setting base themes.
|
||||
* @param new_theme pointer to theme which base should be set
|
||||
* @param base pointer to the base theme
|
||||
*/
|
||||
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * base)
|
||||
{
|
||||
new_theme->parent = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback for a theme.
|
||||
* The callback is used to add styles to different objects
|
||||
* @param theme pointer to theme which callback should be set
|
||||
* @param cb pointer to the callback
|
||||
*/
|
||||
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb)
|
||||
{
|
||||
theme->apply_cb = apply_cb;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_small : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_normal : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->font_large : LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_primary : lv_palette_main(LV_PALETTE_BLUE_GREY);
|
||||
}
|
||||
|
||||
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj)
|
||||
{
|
||||
lv_theme_t * th = lv_theme_get_from_obj(obj);
|
||||
return th ? th->color_secondary : lv_palette_main(LV_PALETTE_BLUE);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void apply_theme(lv_theme_t * th, lv_obj_t * obj)
|
||||
{
|
||||
if(th->parent) apply_theme(th->parent, obj);
|
||||
if(th->apply_cb) th->apply_cb(th, obj);
|
||||
}
|
115
EC600U_lvgl_lib/lvgl/src/core/lv_theme.h
Normal file
115
EC600U_lvgl_lib/lvgl/src/core/lv_theme.h
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
*@file lv_theme.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_THEME_H
|
||||
#define LV_THEME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_theme_t;
|
||||
struct _lv_disp_t;
|
||||
|
||||
typedef void (*lv_theme_apply_cb_t)(struct _lv_theme_t *, lv_obj_t *);
|
||||
|
||||
typedef struct _lv_theme_t {
|
||||
lv_theme_apply_cb_t apply_cb;
|
||||
struct _lv_theme_t * parent; /**< Apply the current theme's style on top of this theme.*/
|
||||
void * user_data;
|
||||
struct _lv_disp_t * disp;
|
||||
lv_color_t color_primary;
|
||||
lv_color_t color_secondary;
|
||||
const lv_font_t * font_small;
|
||||
const lv_font_t * font_normal;
|
||||
const lv_font_t * font_large;
|
||||
uint32_t flags; /*Any custom flag used by the theme*/
|
||||
} lv_theme_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the theme assigned to the display of the object
|
||||
* @param obj pointer to object
|
||||
* @return the theme of the object's display (can be NULL)
|
||||
*/
|
||||
lv_theme_t * lv_theme_get_from_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Apply the active theme on an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_theme_apply(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Set a base theme for a theme.
|
||||
* The styles from the base them will be added before the styles of the current theme.
|
||||
* Arbitrary long chain of themes can be created by setting base themes.
|
||||
* @param new_theme pointer to theme which base should be set
|
||||
* @param parent pointer to the base theme
|
||||
*/
|
||||
void lv_theme_set_parent(lv_theme_t * new_theme, lv_theme_t * parent);
|
||||
|
||||
/**
|
||||
* Set an apply callback for a theme.
|
||||
* The apply callback is used to add styles to different objects
|
||||
* @param theme pointer to theme which callback should be set
|
||||
* @param apply_cb pointer to the callback
|
||||
*/
|
||||
void lv_theme_set_apply_cb(lv_theme_t * theme, lv_theme_apply_cb_t apply_cb);
|
||||
|
||||
/**
|
||||
* Get the small font of the theme
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_small(lv_obj_t * obj);
|
||||
/**
|
||||
* Get the normal font of the theme
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_normal(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the subtitle font of the theme
|
||||
* @return pointer to the font
|
||||
*/
|
||||
const lv_font_t * lv_theme_get_font_large(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the primary color of the theme
|
||||
* @return the color
|
||||
*/
|
||||
lv_color_t lv_theme_get_color_primary(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the secondary color of the theme
|
||||
* @return the color
|
||||
*/
|
||||
lv_color_t lv_theme_get_color_secondary(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_THEME_H*/
|
60
EC600U_lvgl_lib/lvgl/src/draw/lv_draw.h
Normal file
60
EC600U_lvgl_lib/lvgl/src/draw/lv_draw.h
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file lv_draw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_H
|
||||
#define LV_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "../misc/lv_style.h"
|
||||
#include "../misc/lv_txt.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_img_cache.h"
|
||||
|
||||
#include "lv_draw_rect.h"
|
||||
#include "lv_draw_label.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_draw_line.h"
|
||||
#include "lv_draw_triangle.h"
|
||||
#include "lv_draw_arc.h"
|
||||
#include "lv_draw_blend.h"
|
||||
#include "lv_draw_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* POST INCLUDES
|
||||
*********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_H*/
|
16
EC600U_lvgl_lib/lvgl/src/draw/lv_draw.mk
Normal file
16
EC600U_lvgl_lib/lvgl/src/draw/lv_draw.mk
Normal file
@ -0,0 +1,16 @@
|
||||
CSRCS += lv_draw_arc.c
|
||||
CSRCS += lv_draw_blend.c
|
||||
CSRCS += lv_draw_img.c
|
||||
CSRCS += lv_draw_label.c
|
||||
CSRCS += lv_draw_line.c
|
||||
CSRCS += lv_draw_mask.c
|
||||
CSRCS += lv_draw_rect.c
|
||||
CSRCS += lv_draw_triangle.c
|
||||
CSRCS += lv_img_buf.c
|
||||
CSRCS += lv_img_cache.c
|
||||
CSRCS += lv_img_decoder.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/draw"
|
569
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_arc.c
Normal file
569
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_arc.c
Normal file
@ -0,0 +1,569 @@
|
||||
/**
|
||||
* @file lv_draw_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_arc.h"
|
||||
#include "lv_draw_rect.h"
|
||||
#include "lv_draw_mask.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define SPLIT_RADIUS_LIMIT 10 /*With radius greater than this the arc will drawn in quarters. A quarter is drawn only if there is arc in it*/
|
||||
#define SPLIT_ANGLE_GAP_LIMIT 60 /*With small gaps in the arc don't bother with splitting because there is nothing to skip.*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_coord_t center_x;
|
||||
lv_coord_t center_y;
|
||||
lv_coord_t radius;
|
||||
uint16_t start_angle;
|
||||
uint16_t end_angle;
|
||||
uint16_t start_quarter;
|
||||
uint16_t end_quarter;
|
||||
lv_coord_t width;
|
||||
lv_draw_rect_dsc_t * draw_dsc;
|
||||
const lv_area_t * draw_area;
|
||||
const lv_area_t * clip_area;
|
||||
} quarter_draw_dsc_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void draw_quarter_0(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_1(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_2(quarter_draw_dsc_t * q);
|
||||
static void draw_quarter_3(quarter_draw_dsc_t * q);
|
||||
static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_arc_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
if(dsc->width == 0) return;
|
||||
if(start_angle == end_angle) return;
|
||||
|
||||
lv_coord_t width = dsc->width;
|
||||
if(width > radius) width = radius;
|
||||
|
||||
lv_draw_rect_dsc_t cir_dsc;
|
||||
lv_draw_rect_dsc_init(&cir_dsc);
|
||||
cir_dsc.blend_mode = dsc->blend_mode;
|
||||
if(dsc->img_src) {
|
||||
cir_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
cir_dsc.bg_img_src = dsc->img_src;
|
||||
cir_dsc.bg_img_opa = dsc->opa;
|
||||
}
|
||||
else {
|
||||
cir_dsc.bg_opa = dsc->opa;
|
||||
cir_dsc.bg_color = dsc->color;
|
||||
}
|
||||
|
||||
lv_area_t area_out;
|
||||
area_out.x1 = center_x - radius;
|
||||
area_out.y1 = center_y - radius;
|
||||
area_out.x2 = center_x + radius - 1; /*-1 because the center already belongs to the left/bottom part*/
|
||||
area_out.y2 = center_y + radius - 1;
|
||||
|
||||
lv_area_t area_in;
|
||||
lv_area_copy(&area_in, &area_out);
|
||||
area_in.x1 += dsc->width;
|
||||
area_in.y1 += dsc->width;
|
||||
area_in.x2 -= dsc->width;
|
||||
area_in.y2 -= dsc->width;
|
||||
|
||||
/*Create inner the mask*/
|
||||
int16_t mask_in_id = LV_MASK_ID_INV;
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
if(lv_area_get_width(&area_in) > 0 && lv_area_get_height(&area_in) > 0) {
|
||||
lv_draw_mask_radius_init(&mask_in_param, &area_in, LV_RADIUS_CIRCLE, true);
|
||||
mask_in_id = lv_draw_mask_add(&mask_in_param, NULL);
|
||||
}
|
||||
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &area_out, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, NULL);
|
||||
|
||||
/*Draw a full ring*/
|
||||
if(start_angle + 360 == end_angle || start_angle == end_angle + 360) {
|
||||
cir_dsc.radius = LV_RADIUS_CIRCLE;
|
||||
lv_draw_rect(&area_out, clip_area, &cir_dsc);
|
||||
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
|
||||
return;
|
||||
}
|
||||
|
||||
while(start_angle >= 360) start_angle -= 360;
|
||||
while(end_angle >= 360) end_angle -= 360;
|
||||
|
||||
lv_draw_mask_angle_param_t mask_angle_param;
|
||||
lv_draw_mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle);
|
||||
int16_t mask_angle_id = lv_draw_mask_add(&mask_angle_param, NULL);
|
||||
|
||||
int32_t angle_gap;
|
||||
if(end_angle > start_angle) {
|
||||
angle_gap = 360 - (end_angle - start_angle);
|
||||
}
|
||||
else {
|
||||
angle_gap = start_angle - end_angle;
|
||||
}
|
||||
if(angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) {
|
||||
/*Handle each quarter individually and skip which is empty*/
|
||||
quarter_draw_dsc_t q_dsc;
|
||||
q_dsc.center_x = center_x;
|
||||
q_dsc.center_y = center_y;
|
||||
q_dsc.radius = radius;
|
||||
q_dsc.start_angle = start_angle;
|
||||
q_dsc.end_angle = end_angle;
|
||||
q_dsc.start_quarter = (start_angle / 90) & 0x3;
|
||||
q_dsc.end_quarter = (end_angle / 90) & 0x3;
|
||||
q_dsc.width = width;
|
||||
q_dsc.draw_dsc = &cir_dsc;
|
||||
q_dsc.draw_area = &area_out;
|
||||
q_dsc.clip_area = clip_area;
|
||||
|
||||
draw_quarter_0(&q_dsc);
|
||||
draw_quarter_1(&q_dsc);
|
||||
draw_quarter_2(&q_dsc);
|
||||
draw_quarter_3(&q_dsc);
|
||||
}
|
||||
else {
|
||||
lv_draw_rect(&area_out, clip_area, &cir_dsc);
|
||||
}
|
||||
|
||||
lv_draw_mask_free_param(&mask_angle_param);
|
||||
lv_draw_mask_free_param(&mask_out_param);
|
||||
lv_draw_mask_free_param(&mask_in_param);
|
||||
|
||||
lv_draw_mask_remove_id(mask_angle_id);
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
if(mask_in_id != LV_MASK_ID_INV) lv_draw_mask_remove_id(mask_in_id);
|
||||
|
||||
if(dsc->rounded) {
|
||||
|
||||
lv_draw_mask_radius_param_t mask_end_param;
|
||||
|
||||
lv_area_t round_area;
|
||||
get_rounded_area(start_angle, radius, width, &round_area);
|
||||
round_area.x1 += center_x;
|
||||
round_area.x2 += center_x;
|
||||
round_area.y1 += center_y;
|
||||
round_area.y2 += center_y;
|
||||
lv_area_t clip_area2;
|
||||
if(_lv_area_intersect(&clip_area2, clip_area, &round_area)) {
|
||||
lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
|
||||
|
||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
|
||||
get_rounded_area(end_angle, radius, width, &round_area);
|
||||
round_area.x1 += center_x;
|
||||
round_area.x2 += center_x;
|
||||
round_area.y1 += center_y;
|
||||
round_area.y2 += center_y;
|
||||
if(_lv_area_intersect(&clip_area2, clip_area, &round_area)) {
|
||||
lv_draw_mask_radius_init(&mask_end_param, &round_area, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_end_id = lv_draw_mask_add(&mask_end_param, NULL);
|
||||
|
||||
lv_draw_rect(&area_out, &clip_area2, &cir_dsc);
|
||||
lv_draw_mask_remove_id(mask_end_id);
|
||||
lv_draw_mask_free_param(&mask_end_param);
|
||||
}
|
||||
}
|
||||
#else
|
||||
LV_LOG_WARN("Can't draw arc with LV_DRAW_COMPLEX == 0");
|
||||
LV_UNUSED(center_x);
|
||||
LV_UNUSED(center_y);
|
||||
LV_UNUSED(radius);
|
||||
LV_UNUSED(start_angle);
|
||||
LV_UNUSED(end_angle);
|
||||
LV_UNUSED(clip_area);
|
||||
LV_UNUSED(dsc);
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
lv_coord_t w, bool rounded, lv_area_t * area)
|
||||
{
|
||||
lv_coord_t rout = radius;
|
||||
|
||||
/*Special case: full arc invalidation */
|
||||
if(end_angle == start_angle + 360) {
|
||||
area->x1 = x - rout;
|
||||
area->y1 = y - rout;
|
||||
area->x2 = x + rout;
|
||||
area->y2 = y + rout;
|
||||
return;
|
||||
}
|
||||
|
||||
if(start_angle > 360) start_angle -= 360;
|
||||
if(end_angle > 360) end_angle -= 360;
|
||||
|
||||
lv_coord_t rin = radius - w;
|
||||
lv_coord_t extra_area = rounded ? w / 2 + 1 : 0;
|
||||
uint8_t start_quarter = start_angle / 90;
|
||||
uint8_t end_quarter = end_angle / 90;
|
||||
|
||||
/*360 deg still counts as quarter 3 (360 / 90 would be 4)*/
|
||||
if(start_quarter == 4) start_quarter = 3;
|
||||
if(end_quarter == 4) end_quarter = 3;
|
||||
|
||||
if(start_quarter == end_quarter && start_angle <= end_angle) {
|
||||
if(start_quarter == 0) {
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 1) {
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
}
|
||||
else if(start_quarter == 2) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
}
|
||||
else if(start_quarter == 0 && end_quarter == 1) {
|
||||
area->x1 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((LV_MIN(lv_trigo_sin(end_angle),
|
||||
lv_trigo_sin(start_angle)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + rout + extra_area;
|
||||
}
|
||||
else if(start_quarter == 1 && end_quarter == 2) {
|
||||
area->x1 = x - rout - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + ((LV_MAX(lv_trigo_sin(start_angle + 90),
|
||||
lv_trigo_sin(end_angle + 90)) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 2 && end_quarter == 3) {
|
||||
area->x1 = x + ((lv_trigo_sin(start_angle + 90) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y - rout - extra_area;
|
||||
area->x2 = x + ((lv_trigo_sin(end_angle + 90) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
area->y2 = y + (LV_MAX(lv_trigo_sin(end_angle) * rin,
|
||||
lv_trigo_sin(start_angle) * rin) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
}
|
||||
else if(start_quarter == 3 && end_quarter == 0) {
|
||||
area->x1 = x + ((LV_MIN(lv_trigo_sin(end_angle + 90),
|
||||
lv_trigo_sin(start_angle + 90)) * rin) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->y1 = y + ((lv_trigo_sin(start_angle) * rout) >> LV_TRIGO_SHIFT) - extra_area;
|
||||
area->x2 = x + rout + extra_area;
|
||||
area->y2 = y + ((lv_trigo_sin(end_angle) * rout) >> LV_TRIGO_SHIFT) + extra_area;
|
||||
|
||||
}
|
||||
else {
|
||||
area->x1 = x - rout;
|
||||
area->y1 = y - rout;
|
||||
area->x2 = x + rout;
|
||||
area->y2 = y + rout;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
static void draw_quarter_0(quarter_draw_dsc_t * q)
|
||||
{
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
else if(q->start_quarter == 0 || q->end_quarter == 0) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 0) {
|
||||
quarter_area.x1 = q->center_x;
|
||||
quarter_area.y2 = q->center_y + q->radius;
|
||||
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
if(q->end_quarter == 0) {
|
||||
quarter_area.x2 = q->center_x + q->radius;
|
||||
quarter_area.y1 = q->center_y;
|
||||
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 1) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 2) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 1)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center_x;
|
||||
quarter_area.y1 = q->center_y;
|
||||
quarter_area.x2 = q->center_x + q->radius;
|
||||
quarter_area.y2 = q->center_y + q->radius;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_quarter_1(quarter_draw_dsc_t * q)
|
||||
{
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
else if(q->start_quarter == 1 || q->end_quarter == 1) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 1) {
|
||||
quarter_area.x1 = q->center_x - q->radius;
|
||||
quarter_area.y1 = q->center_y;
|
||||
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
if(q->end_quarter == 1) {
|
||||
quarter_area.x2 = q->center_x - 1;
|
||||
quarter_area.y2 = q->center_y + q->radius;
|
||||
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 2) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 3 && q->end_quarter == 2)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center_x - q->radius;
|
||||
quarter_area.y1 = q->center_y;
|
||||
quarter_area.x2 = q->center_x - 1;
|
||||
quarter_area.y2 = q->center_y + q->radius;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_quarter_2(quarter_draw_dsc_t * q)
|
||||
{
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->end_angle) * q->radius) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
else if(q->start_quarter == 2 || q->end_quarter == 2) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 2) {
|
||||
quarter_area.x2 = q->center_x - 1;
|
||||
quarter_area.y1 = q->center_y - q->radius;
|
||||
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
if(q->end_quarter == 2) {
|
||||
quarter_area.x1 = q->center_x - q->radius;
|
||||
quarter_area.y2 = q->center_y - 1;
|
||||
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->end_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 3) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 0)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center_x - q->radius;
|
||||
quarter_area.y1 = q->center_y - q->radius;
|
||||
quarter_area.x2 = q->center_x - 1;
|
||||
quarter_area.y2 = q->center_y - 1;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_quarter_3(quarter_draw_dsc_t * q)
|
||||
{
|
||||
lv_area_t quarter_area;
|
||||
|
||||
if(q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) {
|
||||
/*Small arc here*/
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
else if(q->start_quarter == 3 || q->end_quarter == 3) {
|
||||
/*Start and/or end arcs here*/
|
||||
if(q->start_quarter == 3) {
|
||||
quarter_area.x2 = q->center_x + q->radius;
|
||||
quarter_area.y2 = q->center_y - 1;
|
||||
|
||||
quarter_area.x1 = q->center_x + ((lv_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y1 = q->center_y + ((lv_trigo_sin(q->start_angle) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
if(q->end_quarter == 3) {
|
||||
quarter_area.x1 = q->center_x;
|
||||
quarter_area.y1 = q->center_y - q->radius;
|
||||
|
||||
quarter_area.x2 = q->center_x + ((lv_trigo_sin(q->end_angle + 90) * (q->radius)) >> LV_TRIGO_SHIFT);
|
||||
quarter_area.y2 = q->center_y + ((lv_trigo_sin(q->end_angle) * (q->radius - q->width)) >> LV_TRIGO_SHIFT);
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
else if((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 0) ||
|
||||
(q->start_quarter == 1 && q->end_quarter == 0) ||
|
||||
(q->start_quarter == 2 && q->end_quarter == 1)) {
|
||||
/*Arc crosses here*/
|
||||
quarter_area.x1 = q->center_x;
|
||||
quarter_area.y1 = q->center_y - q->radius;
|
||||
quarter_area.x2 = q->center_x + q->radius;
|
||||
quarter_area.y2 = q->center_y - 1;
|
||||
|
||||
bool ok = _lv_area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
||||
if(ok) lv_draw_rect(q->draw_area, &quarter_area, q->draw_dsc);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_rounded_area(int16_t angle, lv_coord_t radius, uint8_t thickness, lv_area_t * res_area)
|
||||
{
|
||||
const uint8_t ps = 8;
|
||||
const uint8_t pa = 127;
|
||||
|
||||
int32_t thick_half = thickness / 2;
|
||||
uint8_t thick_corr = (thickness & 0x01) ? 0 : 1;
|
||||
|
||||
int32_t cir_x;
|
||||
int32_t cir_y;
|
||||
|
||||
cir_x = ((radius - thick_half) * lv_trigo_sin(90 - angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
cir_y = ((radius - thick_half) * lv_trigo_sin(angle)) >> (LV_TRIGO_SHIFT - ps);
|
||||
|
||||
/*Actually the center of the pixel need to be calculated so apply 1/2 px offset*/
|
||||
if(cir_x > 0) {
|
||||
cir_x = (cir_x - pa) >> ps;
|
||||
res_area->x1 = cir_x - thick_half + thick_corr;
|
||||
res_area->x2 = cir_x + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_x = (cir_x + pa) >> ps;
|
||||
res_area->x1 = cir_x - thick_half;
|
||||
res_area->x2 = cir_x + thick_half - thick_corr;
|
||||
}
|
||||
|
||||
if(cir_y > 0) {
|
||||
cir_y = (cir_y - pa) >> ps;
|
||||
res_area->y1 = cir_y - thick_half + thick_corr;
|
||||
res_area->y2 = cir_y + thick_half;
|
||||
}
|
||||
else {
|
||||
cir_y = (cir_y + pa) >> ps;
|
||||
res_area->y1 = cir_y - thick_half;
|
||||
res_area->y2 = cir_y + thick_half - thick_corr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
76
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_arc.h
Normal file
76
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_arc.h
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file lv_draw_arc.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_ARC_H
|
||||
#define LV_DRAW_ARC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_line.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_color_t color;
|
||||
lv_coord_t width;
|
||||
const void * img_src;
|
||||
lv_opa_t opa;
|
||||
lv_blend_mode_t blend_mode : 2;
|
||||
uint8_t rounded : 1;
|
||||
} lv_draw_arc_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_arc_dsc_init(lv_draw_arc_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Draw an arc. (Can draw pie too with great thickness.)
|
||||
* @param center_x the x coordinate of the center of the arc
|
||||
* @param center_y the y coordinate of the center of the arc
|
||||
* @param radius the radius of the arc
|
||||
* @param mask the arc will be drawn only in this mask
|
||||
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
|
||||
* @param end_angle the end angle of the arc
|
||||
* @param clip_area the arc will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
const lv_area_t * clip_area, const lv_draw_arc_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get an area the should be invalidated when the arcs angle changed between start_angle and end_ange
|
||||
* @param x the x coordinate of the center of the arc
|
||||
* @param y the y coordinate of the center of the arc
|
||||
* @param radius the radius of the arc
|
||||
* @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right)
|
||||
* @param end_angle the end angle of the arc
|
||||
* @param w width of the arc
|
||||
* @param rounded true: the arc is rounded
|
||||
* @param area store the area to invalidate here
|
||||
*/
|
||||
void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,
|
||||
lv_coord_t w, bool rounded, lv_area_t * area);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_ARC*/
|
1033
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_blend.c
Normal file
1033
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_blend.c
Normal file
File diff suppressed because it is too large
Load Diff
50
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_blend.h
Normal file
50
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_blend.h
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file lv_draw_blend.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_BLEND_H
|
||||
#define LV_DRAW_BLEND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_style.h"
|
||||
#include "lv_draw_mask.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
LV_ATTRIBUTE_FAST_MEM void _lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area, lv_color_t color,
|
||||
lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa, lv_blend_mode_t mode);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void _lv_blend_map(const lv_area_t * clip_area, const lv_area_t * map_area,
|
||||
const lv_color_t * map_buf,
|
||||
lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa, lv_blend_mode_t mode);
|
||||
|
||||
//! @endcond
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_BLEND_H*/
|
668
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_img.c
Normal file
668
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_img.c
Normal file
@ -0,0 +1,668 @@
|
||||
/**
|
||||
* @file lv_draw_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_img.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
#include "../gpu/lv_gpu_stm32_dma2d.h"
|
||||
#elif LV_USE_GPU_NXP_PXP
|
||||
#include "../gpu/lv_gpu_nxp_pxp.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_USE_EXTERNAL_RENDERER == 0
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const void * src,
|
||||
const lv_draw_img_dsc_t * draw_dsc);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
const uint8_t * map_p,
|
||||
const lv_draw_img_dsc_t * draw_dsc,
|
||||
bool chroma_key, bool alpha_byte);
|
||||
|
||||
static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg);
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_img_dsc_t));
|
||||
dsc->recolor = lv_color_black();
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->zoom = LV_IMG_ZOOM_NONE;
|
||||
dsc->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0;
|
||||
}
|
||||
|
||||
#if LV_USE_EXTERNAL_RENDERER == 0
|
||||
/**
|
||||
* Draw an image
|
||||
* @param coords the coordinates of the image
|
||||
* @param mask the image will be drawn only in this area
|
||||
* @param src pointer to a lv_color_t array which contains the pixels of the image
|
||||
* @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_draw_img_dsc_t * dsc)
|
||||
{
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
show_error(coords, mask, "No\ndata");
|
||||
return;
|
||||
}
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_img_draw_core(coords, mask, src, dsc);
|
||||
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
show_error(coords, mask, "No\ndata");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif //LV_USE_GPU_SDL_RENDER
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf)
|
||||
{
|
||||
uint8_t px_size = 0;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_UNKNOWN:
|
||||
case LV_IMG_CF_RAW:
|
||||
px_size = 0;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
px_size = LV_COLOR_SIZE;
|
||||
break;
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE << 3;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
px_size = 1;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
px_size = 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
px_size = 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
px_size = 8;
|
||||
break;
|
||||
default:
|
||||
px_size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return px_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color format is chroma keyed or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf)
|
||||
{
|
||||
bool is_chroma_keyed = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
case LV_IMG_CF_RAW_CHROMA_KEYED:
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
is_chroma_keyed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
is_chroma_keyed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return is_chroma_keyed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a color format has alpha channel or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf)
|
||||
{
|
||||
bool has_alpha = false;
|
||||
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
case LV_IMG_CF_RAW_ALPHA:
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
has_alpha = true;
|
||||
break;
|
||||
default:
|
||||
has_alpha = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return has_alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
* @param src pointer to an image source:
|
||||
* - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code)
|
||||
* - a path to a file (e.g. "S:/folder/image.bin")
|
||||
* - or a symbol (e.g. LV_SYMBOL_CLOSE)
|
||||
* @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
|
||||
*/
|
||||
lv_img_src_t lv_img_src_get_type(const void * src)
|
||||
{
|
||||
lv_img_src_t img_src_type = LV_IMG_SRC_UNKNOWN;
|
||||
|
||||
if(src == NULL) return img_src_type;
|
||||
const uint8_t * u8_p = src;
|
||||
|
||||
/*The first byte shows the type of the image source*/
|
||||
if(u8_p[0] >= 0x20 && u8_p[0] <= 0x7F) {
|
||||
img_src_type = LV_IMG_SRC_FILE; /*If it's an ASCII character then it's file name*/
|
||||
}
|
||||
else if(u8_p[0] >= 0x80) {
|
||||
img_src_type = LV_IMG_SRC_SYMBOL; /*Symbols begins after 0x7F*/
|
||||
}
|
||||
else {
|
||||
img_src_type = LV_IMG_SRC_VARIABLE; /*`lv_img_dsc_t` is draw to the first byte < 0x20*/
|
||||
}
|
||||
|
||||
if(LV_IMG_SRC_UNKNOWN == img_src_type) {
|
||||
LV_LOG_WARN("lv_img_src_get_type: unknown image type");
|
||||
}
|
||||
|
||||
return img_src_type;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_USE_EXTERNAL_RENDERER == 0
|
||||
LV_ATTRIBUTE_FAST_MEM static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * clip_area,
|
||||
const void * src,
|
||||
const lv_draw_img_dsc_t * draw_dsc)
|
||||
{
|
||||
if(draw_dsc->opa <= LV_OPA_MIN) return LV_RES_OK;
|
||||
|
||||
_lv_img_cache_entry_t * cdsc = _lv_img_cache_open(src, draw_dsc->recolor, draw_dsc->frame_id);
|
||||
|
||||
if(cdsc == NULL) return LV_RES_INV;
|
||||
|
||||
bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf);
|
||||
bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf);
|
||||
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
|
||||
show_error(coords, clip_area, cdsc->dec_dsc.error_msg);
|
||||
}
|
||||
/*The decoder could open the image and gave the entire uncompressed image.
|
||||
*Just draw it!*/
|
||||
else if(cdsc->dec_dsc.img_data) {
|
||||
lv_area_t map_area_rot;
|
||||
lv_area_copy(&map_area_rot, coords);
|
||||
if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) {
|
||||
int32_t w = lv_area_get_width(coords);
|
||||
int32_t h = lv_area_get_height(coords);
|
||||
|
||||
_lv_img_buf_get_transformed_area(&map_area_rot, w, h, draw_dsc->angle, draw_dsc->zoom, &draw_dsc->pivot);
|
||||
|
||||
map_area_rot.x1 += coords->x1;
|
||||
map_area_rot.y1 += coords->y1;
|
||||
map_area_rot.x2 += coords->x1;
|
||||
map_area_rot.y2 += coords->y1;
|
||||
}
|
||||
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, clip_area, &map_area_rot);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, draw_dsc, chroma_keyed, alpha_byte);
|
||||
}
|
||||
/*The whole uncompressed image is not available. Try to read it line-by-line*/
|
||||
else {
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = _lv_area_intersect(&mask_com, clip_area, coords);
|
||||
/*Out of mask. There is nothing to draw so the image is drawn successfully.*/
|
||||
if(union_ok == false) {
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
int32_t width = lv_area_get_width(&mask_com);
|
||||
|
||||
uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) *
|
||||
LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/
|
||||
|
||||
lv_area_t line;
|
||||
lv_area_copy(&line, &mask_com);
|
||||
lv_area_set_height(&line, 1);
|
||||
int32_t x = mask_com.x1 - coords->x1;
|
||||
int32_t y = mask_com.y1 - coords->y1;
|
||||
int32_t row;
|
||||
lv_res_t read_res;
|
||||
for(row = mask_com.y1; row <= mask_com.y2; row++) {
|
||||
lv_area_t mask_line;
|
||||
union_ok = _lv_area_intersect(&mask_line, clip_area, &line);
|
||||
if(union_ok == false) continue;
|
||||
|
||||
read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf);
|
||||
if(read_res != LV_RES_OK) {
|
||||
lv_img_decoder_close(&cdsc->dec_dsc);
|
||||
LV_LOG_WARN("Image draw can't read the line");
|
||||
lv_mem_buf_release(buf);
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_draw_map(&line, &mask_line, buf, draw_dsc, chroma_keyed, alpha_byte);
|
||||
line.y1++;
|
||||
line.y2++;
|
||||
y++;
|
||||
}
|
||||
lv_mem_buf_release(buf);
|
||||
}
|
||||
|
||||
draw_cleanup(cdsc);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a color map to the display (image)
|
||||
* @param cords_p coordinates the color map
|
||||
* @param mask_p the map will drawn only on this area (truncated to draw_buf area)
|
||||
* @param map_p pointer to a lv_color_t array
|
||||
* @param draw_dsc pointer to an initialized `lv_draw_img_dsc_t` variable
|
||||
* @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels
|
||||
* @param alpha_byte true: extra alpha byte is inserted for every pixel
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
const uint8_t * map_p,
|
||||
const lv_draw_img_dsc_t * draw_dsc,
|
||||
bool chroma_key, bool alpha_byte)
|
||||
{
|
||||
/*Use the clip area as draw area*/
|
||||
lv_area_t draw_area;
|
||||
lv_area_copy(&draw_area, clip_area);
|
||||
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);
|
||||
const lv_area_t * disp_area = &draw_buf->area;
|
||||
|
||||
/*Now `draw_area` has absolute coordinates.
|
||||
*Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
||||
draw_area.x1 -= disp_area->x1;
|
||||
draw_area.y1 -= disp_area->y1;
|
||||
draw_area.x2 -= disp_area->x1;
|
||||
draw_area.y2 -= disp_area->y1;
|
||||
|
||||
bool mask_any = lv_draw_mask_is_any(map_area);
|
||||
|
||||
/*The simplest case just copy the pixels into the draw_buf*/
|
||||
if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE &&
|
||||
chroma_key == false && alpha_byte == false && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
|
||||
_lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa,
|
||||
draw_dsc->blend_mode);
|
||||
}
|
||||
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
/*Simple case without masking and transformations*/
|
||||
else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false &&
|
||||
chroma_key == true && draw_dsc->recolor_opa == LV_OPA_TRANSP) { /*copy with color keying (+ alpha)*/
|
||||
lv_gpu_nxp_pxp_enable_color_key();
|
||||
_lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa,
|
||||
draw_dsc->blend_mode);
|
||||
lv_gpu_nxp_pxp_disable_color_key();
|
||||
}
|
||||
else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false &&
|
||||
chroma_key == false && draw_dsc->recolor_opa != LV_OPA_TRANSP) { /*copy with recolor (+ alpha)*/
|
||||
lv_gpu_nxp_pxp_enable_recolor(draw_dsc->recolor, draw_dsc->recolor_opa);
|
||||
_lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa,
|
||||
draw_dsc->blend_mode);
|
||||
lv_gpu_nxp_pxp_disable_recolor();
|
||||
}
|
||||
#endif
|
||||
/*In the other cases every pixel need to be checked one-by-one*/
|
||||
else {
|
||||
//#if LV_DRAW_COMPLEX
|
||||
/*The pixel size in byte is different if an alpha byte is added too*/
|
||||
uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
|
||||
|
||||
/*Go to the first displayed pixel of the map*/
|
||||
int32_t map_w = lv_area_get_width(map_area);
|
||||
const uint8_t * map_buf_tmp = map_p;
|
||||
map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte;
|
||||
map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte;
|
||||
|
||||
lv_color_t c;
|
||||
lv_color_t chroma_keyed_color = LV_COLOR_CHROMA_KEY;
|
||||
uint32_t px_i = 0;
|
||||
|
||||
const uint8_t * map_px;
|
||||
|
||||
lv_area_t blend_area;
|
||||
blend_area.x1 = draw_area.x1 + disp_area->x1;
|
||||
blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1;
|
||||
blend_area.y1 = disp_area->y1 + draw_area.y1;
|
||||
blend_area.y2 = blend_area.y1;
|
||||
|
||||
lv_coord_t draw_area_h = lv_area_get_height(&draw_area);
|
||||
lv_coord_t draw_area_w = lv_area_get_width(&draw_area);
|
||||
|
||||
bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
|
||||
/*Simple ARGB image. Handle it as special case because it's very common*/
|
||||
if(!mask_any && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) {
|
||||
#if LV_USE_GPU_STM32_DMA2D && LV_COLOR_DEPTH == 32
|
||||
/*Blend ARGB images directly*/
|
||||
if(lv_area_get_size(&draw_area) > 240) {
|
||||
int32_t disp_w = lv_area_get_width(disp_area);
|
||||
lv_color_t * disp_buf = draw_buf->buf_act;
|
||||
lv_color_t * disp_buf_first = disp_buf + disp_w * draw_area.y1 + draw_area.x1;
|
||||
lv_gpu_stm32_dma2d_blend(disp_buf_first, disp_w, (const lv_color_t *)map_buf_tmp, draw_dsc->opa, map_w, draw_area_w,
|
||||
draw_area_h);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(disp);
|
||||
uint32_t mask_buf_size = lv_area_get_size(&draw_area) > (uint32_t) hor_res ? hor_res : lv_area_get_size(&draw_area);
|
||||
lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
for(y = 0; y < draw_area_h; y++) {
|
||||
map_px = map_buf_tmp;
|
||||
for(x = 0; x < draw_area_w; x++, map_px += px_size_byte, px_i++) {
|
||||
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
mask_buf[px_i] = px_opa;
|
||||
if(px_opa) {
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
map2[px_i].full = map_px[0];
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
map2[px_i].full = map_px[0] + (map_px[1] << 8);
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
map2[px_i].full = *((uint32_t *)map_px);
|
||||
#endif
|
||||
}
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
map2[px_i].ch.alpha = 0xFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
map_buf_tmp += map_w * px_size_byte;
|
||||
if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) {
|
||||
blend_area.y2 ++;
|
||||
}
|
||||
else {
|
||||
_lv_blend_map(clip_area, &blend_area, map2, mask_buf, LV_DRAW_MASK_RES_CHANGED, draw_dsc->opa, draw_dsc->blend_mode);
|
||||
|
||||
blend_area.y1 = blend_area.y2 + 1;
|
||||
blend_area.y2 = blend_area.y1;
|
||||
|
||||
px_i = 0;
|
||||
}
|
||||
}
|
||||
/*Flush the last part*/
|
||||
if(blend_area.y1 != blend_area.y2) {
|
||||
blend_area.y2--;
|
||||
_lv_blend_map(clip_area, &blend_area, map2, mask_buf, LV_DRAW_MASK_RES_CHANGED, draw_dsc->opa, draw_dsc->blend_mode);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_mem_buf_release(map2);
|
||||
}
|
||||
/*Most complicated case: transform or other mask or chroma keyed*/
|
||||
else {
|
||||
/*Build the image and a mask line-by-line*/
|
||||
uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(disp);
|
||||
uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area);
|
||||
lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
lv_img_transform_dsc_t trans_dsc;
|
||||
lv_memset_00(&trans_dsc, sizeof(lv_img_transform_dsc_t));
|
||||
if(transform) {
|
||||
lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR;
|
||||
if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
|
||||
trans_dsc.cfg.angle = draw_dsc->angle;
|
||||
trans_dsc.cfg.zoom = draw_dsc->zoom;
|
||||
trans_dsc.cfg.src = map_p;
|
||||
trans_dsc.cfg.src_w = map_w;
|
||||
trans_dsc.cfg.src_h = lv_area_get_height(map_area);;
|
||||
trans_dsc.cfg.cf = cf;
|
||||
trans_dsc.cfg.pivot_x = draw_dsc->pivot.x;
|
||||
trans_dsc.cfg.pivot_y = draw_dsc->pivot.y;
|
||||
trans_dsc.cfg.color = draw_dsc->recolor;
|
||||
trans_dsc.cfg.antialias = draw_dsc->antialias;
|
||||
|
||||
_lv_img_buf_transform_init(&trans_dsc);
|
||||
}
|
||||
#endif
|
||||
uint16_t recolor_premult[3] = {0};
|
||||
lv_opa_t recolor_opa_inv = 255 - draw_dsc->recolor_opa;
|
||||
if(draw_dsc->recolor_opa != 0) {
|
||||
lv_color_premult(draw_dsc->recolor, draw_dsc->recolor_opa, recolor_premult);
|
||||
}
|
||||
|
||||
lv_draw_mask_res_t mask_res;
|
||||
mask_res = (alpha_byte || chroma_key || draw_dsc->angle ||
|
||||
draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
|
||||
/*Prepare the `mask_buf`if there are other masks*/
|
||||
if(mask_any) {
|
||||
lv_memset_ff(mask_buf, mask_buf_size);
|
||||
}
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
#if LV_DRAW_COMPLEX
|
||||
int32_t rot_y = disp_area->y1 + draw_area.y1 - map_area->y1;
|
||||
#endif
|
||||
for(y = 0; y < draw_area_h; y++) {
|
||||
map_px = map_buf_tmp;
|
||||
#if LV_DRAW_COMPLEX
|
||||
uint32_t px_i_start = px_i;
|
||||
int32_t rot_x = disp_area->x1 + draw_area.x1 - map_area->x1;
|
||||
#endif
|
||||
|
||||
for(x = 0; x < draw_area_w; x++, map_px += px_size_byte, px_i++) {
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(transform) {
|
||||
|
||||
/*Transform*/
|
||||
bool ret;
|
||||
ret = _lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y);
|
||||
if(ret == false) {
|
||||
mask_buf[px_i] = LV_OPA_TRANSP;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
mask_buf[px_i] = trans_dsc.res.opa;
|
||||
c.full = trans_dsc.res.color.full;
|
||||
}
|
||||
}
|
||||
/*No transform*/
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(alpha_byte) {
|
||||
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
mask_buf[px_i] = px_opa;
|
||||
if(px_opa == 0) {
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
map2[px_i].full = 0;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mask_buf[px_i] = 0xFF;
|
||||
}
|
||||
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
c.full = map_px[0];
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
c.full = map_px[0];
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
c.full = map_px[0] + (map_px[1] << 8);
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
c.full = *((uint32_t *)map_px);
|
||||
c.ch.alpha = 0xFF;
|
||||
#endif
|
||||
if(chroma_key) {
|
||||
if(c.full == chroma_keyed_color.full) {
|
||||
mask_buf[px_i] = LV_OPA_TRANSP;
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
map2[px_i].full = 0;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(draw_dsc->recolor_opa != 0) {
|
||||
c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv);
|
||||
}
|
||||
|
||||
map2[px_i].full = c.full;
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*Apply the masks if any*/
|
||||
if(mask_any) {
|
||||
lv_draw_mask_res_t mask_res_sub;
|
||||
mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + draw_buf->area.x1,
|
||||
y + draw_area.y1 + draw_buf->area.y1,
|
||||
lv_area_get_width(&draw_area));
|
||||
if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(mask_buf + px_i_start, lv_area_get_width(&draw_area));
|
||||
mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
}
|
||||
else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) {
|
||||
mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
map_buf_tmp += map_w * px_size_byte;
|
||||
if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) {
|
||||
blend_area.y2 ++;
|
||||
}
|
||||
else {
|
||||
|
||||
_lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, draw_dsc->opa, draw_dsc->blend_mode);
|
||||
|
||||
blend_area.y1 = blend_area.y2 + 1;
|
||||
blend_area.y2 = blend_area.y1;
|
||||
|
||||
px_i = 0;
|
||||
mask_res = (alpha_byte || chroma_key || draw_dsc->angle ||
|
||||
draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
|
||||
/*Prepare the `mask_buf`if there are other masks*/
|
||||
if(mask_any) {
|
||||
lv_memset_ff(mask_buf, mask_buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Flush the last part*/
|
||||
if(blend_area.y1 != blend_area.y2) {
|
||||
blend_area.y2--;
|
||||
_lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, draw_dsc->opa, draw_dsc->blend_mode);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_mem_buf_release(map2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg)
|
||||
{
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.bg_color = lv_color_white();
|
||||
lv_draw_rect(coords, clip_area, &rect_dsc);
|
||||
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_draw_label(coords, clip_area, &label_dsc, msg, NULL);
|
||||
}
|
||||
|
||||
static void draw_cleanup(_lv_img_cache_entry_t * cache)
|
||||
{
|
||||
/*Automatically close images with no caching*/
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
lv_img_decoder_close(&cache->dec_dsc);
|
||||
#else
|
||||
LV_UNUSED(cache);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //LV_USE_GPU_SDL_RENDER
|
97
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_img.h
Normal file
97
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_img.h
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file lv_draw_img.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_IMG_H
|
||||
#define LV_DRAW_IMG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_img_buf.h"
|
||||
#include "lv_draw_blend.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
|
||||
uint16_t angle;
|
||||
uint16_t zoom;
|
||||
lv_point_t pivot;
|
||||
|
||||
lv_color_t recolor;
|
||||
lv_opa_t recolor_opa;
|
||||
|
||||
lv_opa_t opa;
|
||||
lv_blend_mode_t blend_mode : 4;
|
||||
|
||||
int32_t frame_id;
|
||||
uint8_t antialias : 1;
|
||||
} lv_draw_img_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc);
|
||||
/**
|
||||
* Draw an image
|
||||
* @param coords the coordinates of the image
|
||||
* @param mask the image will be drawn only in this area
|
||||
* @param src pointer to a lv_color_t array which contains the pixels of the image
|
||||
* @param dsc pointer to an initialized `lv_draw_img_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_draw_img_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
* @param src pointer to an image source:
|
||||
* - pointer to an 'lv_img_t' variable (image stored internally and compiled into the code)
|
||||
* - a path to a file (e.g. "S:/folder/image.bin")
|
||||
* - or a symbol (e.g. LV_SYMBOL_CLOSE)
|
||||
* @return type of the image source LV_IMG_SRC_VARIABLE/FILE/SYMBOL/UNKNOWN
|
||||
*/
|
||||
lv_img_src_t lv_img_src_get_type(const void * src);
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format is chroma keyed or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format has alpha channel or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_IMG_H*/
|
878
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_label.c
Normal file
878
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_label.c
Normal file
@ -0,0 +1,878 @@
|
||||
/**
|
||||
* @file lv_draw_label.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_label.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../hal/lv_hal_disp.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
|
||||
#if LV_USE_GPU_SDL
|
||||
#include "../gpu/lv_gpu_sdl.h"
|
||||
#endif
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LABEL_RECOLOR_PAR_LENGTH 6
|
||||
#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
enum {
|
||||
CMD_STATE_WAIT,
|
||||
CMD_STATE_PAR,
|
||||
CMD_STATE_IN,
|
||||
};
|
||||
typedef uint8_t cmd_state_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_USE_EXTERNAL_RENDERER == 0
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g,
|
||||
const lv_area_t * clip_area,
|
||||
const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode);
|
||||
|
||||
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
|
||||
static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area,
|
||||
const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode);
|
||||
#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/
|
||||
#endif /*LV_USE_EXTERNAL_RENDERER*/
|
||||
|
||||
static uint8_t hex_char_to_num(char hex);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
const uint8_t _lv_bpp1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
|
||||
const uint8_t _lv_bpp2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
const uint8_t _lv_bpp3_opa_table[8] = {0, 36, 73, 109, /*Opacity mapping with bpp = 3*/
|
||||
146, 182, 219, 255
|
||||
};
|
||||
|
||||
const uint8_t _lv_bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119,
|
||||
136, 153, 170, 187,
|
||||
204, 221, 238, 255
|
||||
};
|
||||
|
||||
const uint8_t _lv_bpp8_opa_table[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
|
||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_label_dsc_t));
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
dsc->font = LV_FONT_DEFAULT;
|
||||
dsc->sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
dsc->sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
dsc->sel_color = lv_color_black();
|
||||
dsc->sel_bg_color = lv_palette_main(LV_PALETTE_BLUE);
|
||||
dsc->bidi_dir = LV_BASE_DIR_LTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a text
|
||||
* @param coords coordinates of the label
|
||||
* @param mask the label will be drawn only in this area
|
||||
* @param dsc pointer to draw descriptor
|
||||
* @param txt `\0` terminated text to write
|
||||
* @param hint pointer to a `lv_draw_label_hint_t` variable.
|
||||
* It is managed by the draw to speed up the drawing of very long texts (thousands of lines).
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask,
|
||||
const lv_draw_label_dsc_t * dsc,
|
||||
const char * txt,
|
||||
lv_draw_label_hint_t * hint)
|
||||
{
|
||||
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
const lv_font_t * font = dsc->font;
|
||||
int32_t w;
|
||||
|
||||
/*No need to waste processor time if string is empty*/
|
||||
if(txt == NULL || txt[0] == '\0')
|
||||
return;
|
||||
|
||||
lv_area_t clipped_area;
|
||||
bool clip_ok = _lv_area_intersect(&clipped_area, coords, mask);
|
||||
if(!clip_ok) return;
|
||||
|
||||
lv_text_align_t align = dsc->align;
|
||||
lv_base_dir_t base_dir = dsc->bidi_dir;
|
||||
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
|
||||
if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) {
|
||||
/*Normally use the label's width as width*/
|
||||
w = lv_area_get_width(coords);
|
||||
}
|
||||
else {
|
||||
/*If EXAPND is enabled then not limit the text's width to the object's width*/
|
||||
lv_point_t p;
|
||||
lv_txt_get_size(&p, txt, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX,
|
||||
dsc->flag);
|
||||
w = p.x;
|
||||
}
|
||||
|
||||
int32_t line_height_font = lv_font_get_line_height(font);
|
||||
int32_t line_height = line_height_font + dsc->line_space;
|
||||
|
||||
/*Init variables for the first line*/
|
||||
int32_t line_width = 0;
|
||||
lv_point_t pos;
|
||||
pos.x = coords->x1;
|
||||
pos.y = coords->y1;
|
||||
|
||||
int32_t x_ofs = 0;
|
||||
int32_t y_ofs = 0;
|
||||
x_ofs = dsc->ofs_x;
|
||||
y_ofs = dsc->ofs_y;
|
||||
pos.y += y_ofs;
|
||||
|
||||
uint32_t line_start = 0;
|
||||
int32_t last_line_start = -1;
|
||||
|
||||
/*Check the hint to use the cached info*/
|
||||
if(hint && y_ofs == 0 && coords->y1 < 0) {
|
||||
/*If the label changed too much recalculate the hint.*/
|
||||
if(LV_ABS(hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) {
|
||||
hint->line_start = -1;
|
||||
}
|
||||
last_line_start = hint->line_start;
|
||||
}
|
||||
|
||||
/*Use the hint if it's valid*/
|
||||
if(hint && last_line_start >= 0) {
|
||||
line_start = last_line_start;
|
||||
pos.y += hint->y;
|
||||
}
|
||||
|
||||
uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag);
|
||||
|
||||
/*Go the first visible line*/
|
||||
while(pos.y + line_height_font < mask->y1) {
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag);
|
||||
pos.y += line_height;
|
||||
|
||||
/*Save at the threshold coordinate*/
|
||||
if(hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && hint->line_start < 0) {
|
||||
hint->line_start = line_start;
|
||||
hint->y = pos.y - coords->y1;
|
||||
hint->coord_y = coords->y1;
|
||||
}
|
||||
|
||||
if(txt[line_start] == '\0') return;
|
||||
}
|
||||
|
||||
/*Align to middle*/
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
|
||||
lv_opa_t opa = dsc->opa;
|
||||
|
||||
uint32_t sel_start = dsc->sel_start;
|
||||
uint32_t sel_end = dsc->sel_end;
|
||||
if(sel_start > sel_end) {
|
||||
uint32_t tmp = sel_start;
|
||||
sel_start = sel_end;
|
||||
sel_end = tmp;
|
||||
}
|
||||
lv_draw_line_dsc_t line_dsc;
|
||||
|
||||
if((dsc->decor & LV_TEXT_DECOR_UNDERLINE) || (dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH)) {
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
line_dsc.color = dsc->color;
|
||||
line_dsc.width = font->underline_thickness ? font->underline_thickness : 1;
|
||||
line_dsc.opa = dsc->opa;
|
||||
line_dsc.blend_mode = dsc->blend_mode;
|
||||
}
|
||||
|
||||
cmd_state_t cmd_state = CMD_STATE_WAIT;
|
||||
uint32_t i;
|
||||
uint32_t par_start = 0;
|
||||
lv_color_t recolor;
|
||||
int32_t letter_w;
|
||||
|
||||
lv_draw_rect_dsc_t draw_dsc_sel;
|
||||
lv_draw_rect_dsc_init(&draw_dsc_sel);
|
||||
draw_dsc_sel.bg_color = dsc->sel_bg_color;
|
||||
|
||||
int32_t pos_x_start = pos.x;
|
||||
/*Write out all lines*/
|
||||
while(txt[line_start] != '\0') {
|
||||
pos.x += x_ofs;
|
||||
|
||||
/*Write all letter of a line*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = 0;
|
||||
#if LV_USE_BIDI
|
||||
char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1);
|
||||
_lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0);
|
||||
#else
|
||||
const char * bidi_txt = txt + line_start;
|
||||
#endif
|
||||
|
||||
while(i < line_end - line_start) {
|
||||
uint32_t logical_char_pos = 0;
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
#if LV_USE_BIDI
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start);
|
||||
uint32_t t = _lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL);
|
||||
#else
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
_lv_txt_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i);
|
||||
/*Handle the re-color command*/
|
||||
if((dsc->flag & LV_TEXT_FLAG_RECOLOR) != 0) {
|
||||
if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) {
|
||||
if(cmd_state == CMD_STATE_WAIT) { /*Start char*/
|
||||
par_start = i;
|
||||
cmd_state = CMD_STATE_PAR;
|
||||
continue;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
}
|
||||
else if(cmd_state == CMD_STATE_IN) { /*Command end*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*Skip the color parameter and wait the space after it*/
|
||||
if(cmd_state == CMD_STATE_PAR) {
|
||||
if(letter == ' ') {
|
||||
/*Get the parameter*/
|
||||
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
|
||||
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
|
||||
lv_memcpy_small(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
|
||||
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
|
||||
int r, g, b;
|
||||
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
|
||||
g = (hex_char_to_num(buf[2]) << 4) + hex_char_to_num(buf[3]);
|
||||
b = (hex_char_to_num(buf[4]) << 4) + hex_char_to_num(buf[5]);
|
||||
recolor = lv_color_make(r, g, b);
|
||||
}
|
||||
else {
|
||||
recolor.full = dsc->color.full;
|
||||
}
|
||||
cmd_state = CMD_STATE_IN; /*After the parameter the text is in the command*/
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
lv_color_t color = dsc->color;
|
||||
|
||||
if(cmd_state == CMD_STATE_IN) color = recolor;
|
||||
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
sel_coords.x2 = pos.x + letter_w + dsc->letter_space - 1;
|
||||
sel_coords.y2 = pos.y + line_height - 1;
|
||||
lv_draw_rect(&sel_coords, mask, &draw_dsc_sel);
|
||||
color = dsc->sel_color;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_letter(&pos, mask, font, letter, color, opa, dsc->blend_mode);
|
||||
|
||||
if(letter_w > 0) {
|
||||
pos.x += letter_w + dsc->letter_space;
|
||||
}
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + (dsc->font->line_height / 2) + line_dsc.width / 2;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
lv_draw_line(&p1, &p2, mask, &line_dsc);
|
||||
}
|
||||
|
||||
if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) {
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = pos_x_start;
|
||||
p1.y = pos.y + dsc->font->line_height - dsc->font->base_line - font->underline_position;
|
||||
p2.x = pos.x;
|
||||
p2.y = p1.y;
|
||||
lv_draw_line(&p1, &p2, mask, &line_dsc);
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
lv_mem_buf_release(bidi_txt);
|
||||
bidi_txt = NULL;
|
||||
#endif
|
||||
/*Go to next line*/
|
||||
line_start = line_end;
|
||||
line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag);
|
||||
|
||||
pos.x = coords->x1;
|
||||
/*Align to middle*/
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
|
||||
/*Go the next line position*/
|
||||
pos.y += line_height;
|
||||
|
||||
if(pos.y > mask->y2) return;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
#if LV_USE_EXTERNAL_RENDERER == 0
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw a letter in the Virtual Display Buffer
|
||||
* @param pos_p left-top coordinate of the latter
|
||||
* @param mask_p the letter will be drawn only on this area (truncated to draw_buf area)
|
||||
* @param font_p pointer to font
|
||||
* @param letter a letter to draw
|
||||
* @param color color of letter
|
||||
* @param opa opacity of letter (0..255)
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area,
|
||||
const lv_font_t * font_p,
|
||||
uint32_t letter,
|
||||
lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
if(font_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: font is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_font_glyph_dsc_t g;
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
|
||||
if(g_ret == false) {
|
||||
/*Add warning if the dsc is not found
|
||||
*but do not print warning for non printable ASCII chars (e.g. '\n')*/
|
||||
if(letter >= 0x20 &&
|
||||
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
|
||||
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
|
||||
// LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%X", (unsigned int)letter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*Don't draw anything if the character is empty. E.g. space*/
|
||||
if((g.box_h == 0) || (g.box_w == 0)) return;
|
||||
|
||||
int32_t pos_x = pos_p->x + g.ofs_x;
|
||||
int32_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
|
||||
|
||||
/*If the letter is completely out of mask don't draw it*/
|
||||
if(pos_x + g.box_w < clip_area->x1 ||
|
||||
pos_x > clip_area->x2 ||
|
||||
pos_y + g.box_h < clip_area->y1 ||
|
||||
pos_y > clip_area->y2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
if(map_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if(font_p->subpx) {
|
||||
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
|
||||
draw_letter_subpx(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode);
|
||||
#else
|
||||
LV_LOG_WARN("Can't draw sub-pixel rendered letter because LV_USE_FONT_SUBPX == 0 in lv_conf.h");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
draw_letter_normal(pos_x, pos_y, &g, clip_area, map_p, color, opa, blend_mode);
|
||||
}
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g,
|
||||
const lv_area_t * clip_area,
|
||||
const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
const uint8_t * bpp_opa_table_p;
|
||||
uint32_t bitmask_init;
|
||||
uint32_t bitmask;
|
||||
uint32_t bpp = g->bpp;
|
||||
uint32_t shades;
|
||||
if(bpp == 3) bpp = 4;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
bpp_opa_table_p = _lv_bpp1_opa_table;
|
||||
bitmask_init = 0x80;
|
||||
shades = 2;
|
||||
break;
|
||||
case 2:
|
||||
bpp_opa_table_p = _lv_bpp2_opa_table;
|
||||
bitmask_init = 0xC0;
|
||||
shades = 4;
|
||||
break;
|
||||
case 4:
|
||||
bpp_opa_table_p = _lv_bpp4_opa_table;
|
||||
bitmask_init = 0xF0;
|
||||
shades = 16;
|
||||
break;
|
||||
case 8:
|
||||
bpp_opa_table_p = _lv_bpp8_opa_table;
|
||||
bitmask_init = 0xFF;
|
||||
shades = 256;
|
||||
break; /*No opa table, pixel value will be used directly*/
|
||||
default:
|
||||
LV_LOG_WARN("lv_draw_letter: invalid bpp");
|
||||
return; /*Invalid bpp. Can't render the letter*/
|
||||
}
|
||||
|
||||
static lv_opa_t opa_table[256];
|
||||
static lv_opa_t prev_opa = LV_OPA_TRANSP;
|
||||
static uint32_t prev_bpp = 0;
|
||||
if(opa < LV_OPA_MAX) {
|
||||
if(prev_opa != opa || prev_bpp != bpp) {
|
||||
uint32_t i;
|
||||
for(i = 0; i < shades; i++) {
|
||||
opa_table[i] = bpp_opa_table_p[i] == LV_OPA_COVER ? opa : ((bpp_opa_table_p[i] * opa) >> 8);
|
||||
}
|
||||
}
|
||||
bpp_opa_table_p = opa_table;
|
||||
prev_opa = opa;
|
||||
prev_bpp = bpp;
|
||||
}
|
||||
|
||||
int32_t col, row;
|
||||
int32_t box_w = g->box_w;
|
||||
int32_t box_h = g->box_h;
|
||||
int32_t width_bit = box_w * bpp; /*Letter width in bits*/
|
||||
|
||||
/*Calculate the col/row start/end on the map*/
|
||||
int32_t col_start = pos_x >= clip_area->x1 ? 0 : clip_area->x1 - pos_x;
|
||||
int32_t col_end = pos_x + box_w <= clip_area->x2 ? box_w : clip_area->x2 - pos_x + 1;
|
||||
int32_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y;
|
||||
int32_t row_end = pos_y + box_h <= clip_area->y2 ? box_h : clip_area->y2 - pos_y + 1;
|
||||
|
||||
/*Move on the map too*/
|
||||
uint32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
|
||||
map_p += bit_ofs >> 3;
|
||||
|
||||
uint8_t letter_px;
|
||||
uint32_t col_bit;
|
||||
col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
|
||||
|
||||
lv_coord_t hor_res = lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
|
||||
uint32_t mask_buf_size = box_w * box_h > hor_res ? hor_res : box_w * box_h;
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
|
||||
int32_t mask_p = 0;
|
||||
|
||||
lv_area_t fill_area;
|
||||
fill_area.x1 = col_start + pos_x;
|
||||
fill_area.x2 = col_end + pos_x - 1;
|
||||
fill_area.y1 = row_start + pos_y;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
#if LV_DRAW_COMPLEX
|
||||
bool mask_any = lv_draw_mask_is_any(&fill_area);
|
||||
#endif
|
||||
|
||||
uint32_t col_bit_max = 8 - bpp;
|
||||
uint32_t col_bit_row_ofs = (box_w + col_start - col_end) * bpp;
|
||||
|
||||
for(row = row_start ; row < row_end; row++) {
|
||||
#if LV_DRAW_COMPLEX
|
||||
int32_t mask_p_start = mask_p;
|
||||
#endif
|
||||
bitmask = bitmask_init >> col_bit;
|
||||
for(col = col_start; col < col_end; col++) {
|
||||
/*Load the pixel's opacity into the mask*/
|
||||
letter_px = (*map_p & bitmask) >> (col_bit_max - col_bit);
|
||||
if(letter_px) {
|
||||
mask_buf[mask_p] = bpp_opa_table_p[letter_px];
|
||||
}
|
||||
else {
|
||||
mask_buf[mask_p] = 0;
|
||||
}
|
||||
|
||||
/*Go to the next column*/
|
||||
if(col_bit < col_bit_max) {
|
||||
col_bit += bpp;
|
||||
bitmask = bitmask >> bpp;
|
||||
}
|
||||
else {
|
||||
col_bit = 0;
|
||||
bitmask = bitmask_init;
|
||||
map_p++;
|
||||
}
|
||||
|
||||
/*Next mask byte*/
|
||||
mask_p++;
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*Apply masks if any*/
|
||||
if(mask_any) {
|
||||
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
|
||||
lv_area_get_width(&fill_area));
|
||||
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&fill_area));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if((uint32_t) mask_p + (col_end - col_start) < mask_buf_size) {
|
||||
fill_area.y2 ++;
|
||||
}
|
||||
else {
|
||||
_lv_blend_fill(clip_area, &fill_area,
|
||||
color, mask_buf, LV_DRAW_MASK_RES_CHANGED, LV_OPA_COVER,
|
||||
blend_mode);
|
||||
|
||||
fill_area.y1 = fill_area.y2 + 1;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
mask_p = 0;
|
||||
}
|
||||
|
||||
col_bit += col_bit_row_ofs;
|
||||
map_p += (col_bit >> 3);
|
||||
col_bit = col_bit & 0x7;
|
||||
}
|
||||
|
||||
/*Flush the last part*/
|
||||
if(fill_area.y1 != fill_area.y2) {
|
||||
fill_area.y2--;
|
||||
_lv_blend_fill(clip_area, &fill_area,
|
||||
color, mask_buf, LV_DRAW_MASK_RES_CHANGED, LV_OPA_COVER,
|
||||
blend_mode);
|
||||
mask_p = 0;
|
||||
}
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX
|
||||
static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_dsc_t * g, const lv_area_t * clip_area,
|
||||
const uint8_t * map_p, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode)
|
||||
{
|
||||
const uint8_t * bpp_opa_table;
|
||||
uint32_t bitmask_init;
|
||||
uint32_t bitmask;
|
||||
uint32_t bpp = g->bpp;
|
||||
if(bpp == 3) bpp = 4;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
bpp_opa_table = _lv_bpp1_opa_table;
|
||||
bitmask_init = 0x80;
|
||||
break;
|
||||
case 2:
|
||||
bpp_opa_table = _lv_bpp2_opa_table;
|
||||
bitmask_init = 0xC0;
|
||||
break;
|
||||
case 4:
|
||||
bpp_opa_table = _lv_bpp4_opa_table;
|
||||
bitmask_init = 0xF0;
|
||||
break;
|
||||
case 8:
|
||||
bpp_opa_table = _lv_bpp8_opa_table;
|
||||
bitmask_init = 0xFF;
|
||||
break; /*No opa table, pixel value will be used directly*/
|
||||
default:
|
||||
LV_LOG_WARN("lv_draw_letter: invalid bpp not found");
|
||||
return; /*Invalid bpp. Can't render the letter*/
|
||||
}
|
||||
|
||||
int32_t col, row;
|
||||
|
||||
int32_t box_w = g->box_w;
|
||||
int32_t box_h = g->box_h;
|
||||
int32_t width_bit = box_w * bpp; /*Letter width in bits*/
|
||||
|
||||
/*Calculate the col/row start/end on the map*/
|
||||
int32_t col_start = pos_x >= clip_area->x1 ? 0 : (clip_area->x1 - pos_x) * 3;
|
||||
int32_t col_end = pos_x + box_w / 3 <= clip_area->x2 ? box_w : (clip_area->x2 - pos_x + 1) * 3;
|
||||
int32_t row_start = pos_y >= clip_area->y1 ? 0 : clip_area->y1 - pos_y;
|
||||
int32_t row_end = pos_y + box_h <= clip_area->y2 ? box_h : clip_area->y2 - pos_y + 1;
|
||||
|
||||
/*Move on the map too*/
|
||||
int32_t bit_ofs = (row_start * width_bit) + (col_start * bpp);
|
||||
map_p += bit_ofs >> 3;
|
||||
|
||||
uint8_t letter_px;
|
||||
lv_opa_t px_opa;
|
||||
int32_t col_bit;
|
||||
col_bit = bit_ofs & 0x7; /*"& 0x7" equals to "% 8" just faster*/
|
||||
|
||||
lv_area_t map_area;
|
||||
map_area.x1 = col_start / 3 + pos_x;
|
||||
map_area.x2 = col_end / 3 + pos_x - 1;
|
||||
map_area.y1 = row_start + pos_y;
|
||||
map_area.y2 = map_area.y1;
|
||||
|
||||
if(map_area.x2 <= map_area.x1) return;
|
||||
|
||||
int32_t mask_buf_size = box_w * box_h > _LV_MASK_BUF_MAX_SIZE ? _LV_MASK_BUF_MAX_SIZE : g->box_w * g->box_h;
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
|
||||
int32_t mask_p = 0;
|
||||
|
||||
lv_color_t * color_buf = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
|
||||
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);
|
||||
|
||||
int32_t disp_buf_width = lv_area_get_width(&draw_buf->area);
|
||||
lv_color_t * disp_buf_buf_tmp = draw_buf->buf_act;
|
||||
|
||||
/*Set a pointer on draw_buf to the first pixel of the letter*/
|
||||
disp_buf_buf_tmp += ((pos_y - draw_buf->area.y1) * disp_buf_width) + pos_x - draw_buf->area.x1;
|
||||
|
||||
/*If the letter is partially out of mask the move there on draw_buf*/
|
||||
disp_buf_buf_tmp += (row_start * disp_buf_width) + col_start / 3;
|
||||
|
||||
bool mask_any = lv_draw_mask_is_any(&map_area);
|
||||
uint8_t font_rgb[3];
|
||||
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue};
|
||||
#else
|
||||
uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue};
|
||||
#endif
|
||||
|
||||
for(row = row_start ; row < row_end; row++) {
|
||||
uint32_t subpx_cnt = 0;
|
||||
bitmask = bitmask_init >> col_bit;
|
||||
int32_t mask_p_start = mask_p;
|
||||
|
||||
for(col = col_start; col < col_end; col++) {
|
||||
/*Load the pixel's opacity into the mask*/
|
||||
letter_px = (*map_p & bitmask) >> (8 - col_bit - bpp);
|
||||
if(letter_px != 0) {
|
||||
if(opa == LV_OPA_COVER) {
|
||||
px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
}
|
||||
else {
|
||||
px_opa = bpp == 8 ? (uint32_t)((uint32_t)letter_px * opa) >> 8
|
||||
: (uint32_t)((uint32_t)bpp_opa_table[letter_px] * opa) >> 8;
|
||||
}
|
||||
}
|
||||
else {
|
||||
px_opa = 0;
|
||||
}
|
||||
|
||||
font_rgb[subpx_cnt] = px_opa;
|
||||
|
||||
subpx_cnt ++;
|
||||
if(subpx_cnt == 3) {
|
||||
subpx_cnt = 0;
|
||||
|
||||
lv_color_t res_color;
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
uint8_t bg_rgb[3] = {disp_buf_buf_tmp->ch.red, disp_buf_buf_tmp->ch.green, disp_buf_buf_tmp->ch.blue};
|
||||
#else
|
||||
uint8_t bg_rgb[3] = {disp_buf_buf_tmp->ch.red,
|
||||
(disp_buf_buf_tmp->ch.green_h << 3) + disp_buf_buf_tmp->ch.green_l,
|
||||
disp_buf_buf_tmp->ch.blue
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LV_FONT_SUBPX_BGR
|
||||
res_color.ch.blue = (uint32_t)((uint32_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
|
||||
res_color.ch.red = (uint32_t)((uint32_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
|
||||
#else
|
||||
res_color.ch.red = (uint32_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
|
||||
res_color.ch.blue = (uint32_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
res_color.ch.green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
|
||||
#else
|
||||
uint8_t green = (uint32_t)((uint32_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
|
||||
res_color.ch.green_h = green >> 3;
|
||||
res_color.ch.green_l = green & 0x7;
|
||||
#endif
|
||||
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
res_color.ch.alpha = 0xff;
|
||||
#endif
|
||||
|
||||
if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) mask_buf[mask_p] = LV_OPA_TRANSP;
|
||||
else mask_buf[mask_p] = LV_OPA_COVER;
|
||||
color_buf[mask_p] = res_color;
|
||||
|
||||
/*Next mask byte*/
|
||||
mask_p++;
|
||||
disp_buf_buf_tmp++;
|
||||
}
|
||||
|
||||
/*Go to the next column*/
|
||||
if(col_bit < (int32_t)(8 - bpp)) {
|
||||
col_bit += bpp;
|
||||
bitmask = bitmask >> bpp;
|
||||
}
|
||||
else {
|
||||
col_bit = 0;
|
||||
bitmask = bitmask_init;
|
||||
map_p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*Apply masks if any*/
|
||||
if(mask_any) {
|
||||
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2,
|
||||
lv_area_get_width(&map_area));
|
||||
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&map_area));
|
||||
}
|
||||
}
|
||||
|
||||
if((int32_t) mask_p + (col_end - col_start) < mask_buf_size) {
|
||||
map_area.y2 ++;
|
||||
}
|
||||
else {
|
||||
_lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, blend_mode);
|
||||
|
||||
map_area.y1 = map_area.y2 + 1;
|
||||
map_area.y2 = map_area.y1;
|
||||
mask_p = 0;
|
||||
}
|
||||
|
||||
col_bit += ((box_w - col_end) + col_start) * bpp;
|
||||
|
||||
map_p += (col_bit >> 3);
|
||||
col_bit = col_bit & 0x7;
|
||||
|
||||
/*Next row in draw_buf*/
|
||||
disp_buf_buf_tmp += disp_buf_width - (col_end - col_start) / 3;
|
||||
}
|
||||
|
||||
/*Flush the last part*/
|
||||
if(map_area.y1 != map_area.y2) {
|
||||
map_area.y2--;
|
||||
_lv_blend_map(clip_area, &map_area, color_buf, mask_buf, LV_DRAW_MASK_RES_CHANGED, opa, blend_mode);
|
||||
}
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
lv_mem_buf_release(color_buf);
|
||||
}
|
||||
#endif /*LV_DRAW_COMPLEX && LV_USE_FONT_SUBPX*/
|
||||
|
||||
#endif /*LV_USE_EXTERNAL_RENDERER*/
|
||||
/**
|
||||
* Convert a hexadecimal characters to a number (0..15)
|
||||
* @param hex Pointer to a hexadecimal character (0..9, A..F)
|
||||
* @return the numerical value of `hex` or 0 on error
|
||||
*/
|
||||
static uint8_t hex_char_to_num(char hex)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
if(hex >= '0' && hex <= '9') {
|
||||
result = hex - '0';
|
||||
}
|
||||
else {
|
||||
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
|
||||
|
||||
switch(hex) {
|
||||
case 'A':
|
||||
result = 10;
|
||||
break;
|
||||
case 'B':
|
||||
result = 11;
|
||||
break;
|
||||
case 'C':
|
||||
result = 12;
|
||||
break;
|
||||
case 'D':
|
||||
result = 13;
|
||||
break;
|
||||
case 'E':
|
||||
result = 14;
|
||||
break;
|
||||
case 'F':
|
||||
result = 15;
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
108
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_label.h
Normal file
108
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_label.h
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file lv_draw_label.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_LABEL_H
|
||||
#define LV_DRAW_LABEL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_blend.h"
|
||||
#include "../misc/lv_bidi.h"
|
||||
#include "../misc/lv_txt.h"
|
||||
#include "../misc/lv_color.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
const lv_font_t * font;
|
||||
uint32_t sel_start;
|
||||
uint32_t sel_end;
|
||||
lv_color_t color;
|
||||
lv_color_t sel_color;
|
||||
lv_color_t sel_bg_color;
|
||||
lv_coord_t line_space;
|
||||
lv_coord_t letter_space;
|
||||
lv_coord_t ofs_x;
|
||||
lv_coord_t ofs_y;
|
||||
lv_opa_t opa;
|
||||
lv_base_dir_t bidi_dir;
|
||||
lv_text_align_t align;
|
||||
lv_text_flag_t flag;
|
||||
lv_text_decor_t decor : 3;
|
||||
lv_blend_mode_t blend_mode: 3;
|
||||
} lv_draw_label_dsc_t;
|
||||
|
||||
/** Store some info to speed up drawing of very large texts
|
||||
* It takes a lot of time to get the first visible character because
|
||||
* all the previous characters needs to be checked to calculate the positions.
|
||||
* This structure stores an earlier (e.g. at -1000 px) coordinate and the index of that line.
|
||||
* Therefore the calculations can start from here.*/
|
||||
typedef struct _lv_draw_label_hint_t {
|
||||
/** Index of the line at `y` coordinate*/
|
||||
int32_t line_start;
|
||||
|
||||
/** Give the `y` coordinate of the first letter at `line start` index. Relative to the label's coordinates*/
|
||||
int32_t y;
|
||||
|
||||
/** The 'y1' coordinate of the label when the hint was saved.
|
||||
* Used to invalidate the hint if the label has moved too much.*/
|
||||
int32_t coord_y;
|
||||
} lv_draw_label_hint_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label_dsc_init(lv_draw_label_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Write a text
|
||||
* @param coords coordinates of the label
|
||||
* @param mask the label will be drawn only in this area
|
||||
* @param dsc pointer to draw descriptor
|
||||
* @param txt `\0` terminated text to write
|
||||
* @param hint pointer to a `lv_draw_label_hint_t` variable.
|
||||
* It is managed by the draw to speed up the drawing of very long texts (thousands of lines).
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask,
|
||||
const lv_draw_label_dsc_t * dsc,
|
||||
const char * txt, lv_draw_label_hint_t * hint);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area,
|
||||
const lv_font_t * font_p,
|
||||
uint32_t letter, lv_color_t color, lv_opa_t opa, lv_blend_mode_t blend_mode);
|
||||
//! @endcond
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
extern const uint8_t _lv_bpp2_opa_table[];
|
||||
extern const uint8_t _lv_bpp3_opa_table[];
|
||||
extern const uint8_t _lv_bpp1_opa_table[];
|
||||
extern const uint8_t _lv_bpp4_opa_table[];
|
||||
extern const uint8_t _lv_bpp8_opa_table[];
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LABEL_H*/
|
495
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_line.c
Normal file
495
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_line.c
Normal file
@ -0,0 +1,495 @@
|
||||
/**
|
||||
* @file lv_draw_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "lv_draw_mask.h"
|
||||
#include "lv_draw_blend.h"
|
||||
#include "../core/lv_refr.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc);
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_draw_line_dsc_t));
|
||||
dsc->width = 1;
|
||||
dsc->opa = LV_OPA_COVER;
|
||||
dsc->color = lv_color_black();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a line
|
||||
* @param point1 first point of the line
|
||||
* @param point2 second point of the line
|
||||
* @param clip the line will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->width == 0) return;
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
if(point1->x == point2->x && point1->y == point2->y) return;
|
||||
|
||||
lv_area_t clip_line;
|
||||
clip_line.x1 = LV_MIN(point1->x, point2->x) - dsc->width / 2;
|
||||
clip_line.x2 = LV_MAX(point1->x, point2->x) + dsc->width / 2;
|
||||
clip_line.y1 = LV_MIN(point1->y, point2->y) - dsc->width / 2;
|
||||
clip_line.y2 = LV_MAX(point1->y, point2->y) + dsc->width / 2;
|
||||
|
||||
bool is_common;
|
||||
is_common = _lv_area_intersect(&clip_line, &clip_line, clip);
|
||||
if(!is_common) return;
|
||||
|
||||
if(point1->y == point2->y) draw_line_hor(point1, point2, &clip_line, dsc);
|
||||
else if(point1->x == point2->x) draw_line_ver(point1, point2, &clip_line, dsc);
|
||||
else draw_line_skew(point1, point2, &clip_line, dsc);
|
||||
|
||||
if(dsc->round_end || dsc->round_start) {
|
||||
lv_draw_rect_dsc_t cir_dsc;
|
||||
lv_draw_rect_dsc_init(&cir_dsc);
|
||||
cir_dsc.bg_color = dsc->color;
|
||||
cir_dsc.radius = LV_RADIUS_CIRCLE;
|
||||
cir_dsc.bg_opa = dsc->opa;
|
||||
|
||||
int32_t r = (dsc->width >> 1);
|
||||
int32_t r_corr = (dsc->width & 1) ? 0 : 1;
|
||||
lv_area_t cir_area;
|
||||
|
||||
if(dsc->round_start) {
|
||||
cir_area.x1 = point1->x - r;
|
||||
cir_area.y1 = point1->y - r;
|
||||
cir_area.x2 = point1->x + r - r_corr;
|
||||
cir_area.y2 = point1->y + r - r_corr ;
|
||||
lv_draw_rect(&cir_area, clip, &cir_dsc);
|
||||
}
|
||||
|
||||
if(dsc->round_end) {
|
||||
cir_area.x1 = point2->x - r;
|
||||
cir_area.y1 = point2->y - r;
|
||||
cir_area.x2 = point2->x + r - r_corr;
|
||||
cir_area.y2 = point2->y + r - r_corr ;
|
||||
lv_draw_rect(&cir_area, clip, &cir_dsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
lv_opa_t opa = dsc->opa;
|
||||
|
||||
int32_t w = dsc->width - 1;
|
||||
int32_t w_half0 = w >> 1;
|
||||
int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
|
||||
|
||||
|
||||
|
||||
lv_area_t draw_area;
|
||||
draw_area.x1 = LV_MIN(point1->x, point2->x);
|
||||
draw_area.x2 = LV_MAX(point1->x, point2->x) - 1;
|
||||
draw_area.y1 = point1->y - w_half1;
|
||||
draw_area.y2 = point1->y + w_half0;
|
||||
|
||||
bool dashed = dsc->dash_gap && dsc->dash_width ? true : false;
|
||||
bool simple_mode = true;
|
||||
if(lv_draw_mask_is_any(&draw_area)) simple_mode = false;
|
||||
else if(dashed) simple_mode = false;
|
||||
|
||||
/*If there is no mask then simply draw a rectangle*/
|
||||
if(simple_mode) {
|
||||
_lv_blend_fill(clip, &draw_area,
|
||||
dsc->color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*If there other mask apply it*/
|
||||
else {
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);
|
||||
const lv_area_t * disp_area = &draw_buf->area;
|
||||
/*Get clipped fill area which is the real draw area.
|
||||
*It is always the same or inside `fill_area`*/
|
||||
bool is_common;
|
||||
is_common = _lv_area_intersect(&draw_area, clip, &draw_area);
|
||||
if(!is_common) return;
|
||||
|
||||
/*Now `draw_area` has absolute coordinates.
|
||||
*Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
||||
draw_area.x1 -= disp_area->x1;
|
||||
draw_area.y1 -= disp_area->y1;
|
||||
draw_area.x2 -= disp_area->x1;
|
||||
draw_area.y2 -= disp_area->y1;
|
||||
|
||||
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
||||
|
||||
lv_area_t fill_area;
|
||||
fill_area.x1 = draw_area.x1 + disp_area->x1;
|
||||
fill_area.x2 = draw_area.x2 + disp_area->x1;
|
||||
fill_area.y1 = draw_area.y1 + disp_area->y1;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
|
||||
lv_coord_t dash_start = 0;
|
||||
if(dashed) {
|
||||
dash_start = (draw_buf->area.x1 + draw_area.x1) % (dsc->dash_gap + dsc->dash_width);
|
||||
}
|
||||
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w);
|
||||
int32_t h;
|
||||
for(h = draw_area.y1; h <= draw_area.y2; h++) {
|
||||
lv_memset_ff(mask_buf, draw_area_w);
|
||||
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h,
|
||||
draw_area_w);
|
||||
|
||||
if(dashed) {
|
||||
if(mask_res != LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_coord_t dash_cnt = dash_start;
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < draw_area_w; i++, dash_cnt++) {
|
||||
if(dash_cnt <= dsc->dash_width) {
|
||||
int16_t diff = dsc->dash_width - dash_cnt;
|
||||
i += diff;
|
||||
dash_cnt += diff;
|
||||
}
|
||||
else if(dash_cnt >= dsc->dash_gap + dsc->dash_width) {
|
||||
dash_cnt = 0;
|
||||
}
|
||||
else {
|
||||
mask_buf[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
mask_res = LV_DRAW_MASK_RES_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
_lv_blend_fill(clip, &fill_area,
|
||||
dsc->color, mask_buf, mask_res, dsc->opa,
|
||||
dsc->blend_mode);
|
||||
|
||||
fill_area.y1++;
|
||||
fill_area.y2++;
|
||||
}
|
||||
lv_mem_buf_release(mask_buf);
|
||||
}
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
lv_opa_t opa = dsc->opa;
|
||||
|
||||
int32_t w = dsc->width - 1;
|
||||
int32_t w_half0 = w >> 1;
|
||||
int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
|
||||
|
||||
lv_area_t draw_area;
|
||||
draw_area.x1 = point1->x - w_half1;
|
||||
draw_area.x2 = point1->x + w_half0;
|
||||
draw_area.y1 = LV_MIN(point1->y, point2->y);
|
||||
draw_area.y2 = LV_MAX(point1->y, point2->y) - 1;
|
||||
|
||||
bool dashed = dsc->dash_gap && dsc->dash_width ? true : false;
|
||||
bool simple_mode = true;
|
||||
if(lv_draw_mask_is_any(&draw_area)) simple_mode = false;
|
||||
else if(dashed) simple_mode = false;
|
||||
|
||||
/*If there is no mask then simply draw a rectangle*/
|
||||
if(simple_mode) {
|
||||
_lv_blend_fill(clip, &draw_area,
|
||||
dsc->color, NULL, LV_DRAW_MASK_RES_FULL_COVER, opa,
|
||||
dsc->blend_mode);
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*If there other mask apply it*/
|
||||
else {
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);
|
||||
const lv_area_t * disp_area = &draw_buf->area;
|
||||
/*Get clipped fill area which is the real draw area.
|
||||
*It is always the same or inside `fill_area`*/
|
||||
bool is_common;
|
||||
is_common = _lv_area_intersect(&draw_area, clip, &draw_area);
|
||||
if(!is_common) return;
|
||||
|
||||
/*Now `draw_area` has absolute coordinates.
|
||||
*Make it relative to `disp_area` to simplify draw to `disp_buf`*/
|
||||
draw_area.x1 -= draw_buf->area.x1;
|
||||
draw_area.y1 -= draw_buf->area.y1;
|
||||
draw_area.x2 -= draw_buf->area.x1;
|
||||
draw_area.y2 -= draw_buf->area.y1;
|
||||
|
||||
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
||||
|
||||
lv_area_t fill_area;
|
||||
fill_area.x1 = draw_area.x1 + disp_area->x1;
|
||||
fill_area.x2 = draw_area.x2 + disp_area->x1;
|
||||
fill_area.y1 = draw_area.y1 + disp_area->y1;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w);
|
||||
|
||||
lv_coord_t dash_start = 0;
|
||||
if(dashed) {
|
||||
dash_start = (draw_buf->area.y1 + draw_area.y1) % (dsc->dash_gap + dsc->dash_width);
|
||||
}
|
||||
|
||||
lv_coord_t dash_cnt = dash_start;
|
||||
|
||||
int32_t h;
|
||||
for(h = draw_area.y1; h <= draw_area.y2; h++) {
|
||||
lv_memset_ff(mask_buf, draw_area_w);
|
||||
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, draw_buf->area.x1 + draw_area.x1, draw_buf->area.y1 + h,
|
||||
draw_area_w);
|
||||
|
||||
if(dashed) {
|
||||
if(mask_res != LV_DRAW_MASK_RES_TRANSP) {
|
||||
if(dash_cnt > dsc->dash_width) {
|
||||
mask_res = LV_DRAW_MASK_RES_TRANSP;
|
||||
}
|
||||
|
||||
if(dash_cnt >= dsc->dash_gap + dsc->dash_width) {
|
||||
dash_cnt = 0;
|
||||
}
|
||||
}
|
||||
dash_cnt ++;
|
||||
}
|
||||
|
||||
_lv_blend_fill(clip, &fill_area,
|
||||
dsc->color, mask_buf, mask_res, dsc->opa,
|
||||
LV_BLEND_MODE_NORMAL);
|
||||
|
||||
fill_area.y1++;
|
||||
fill_area.y2++;
|
||||
}
|
||||
lv_mem_buf_release(mask_buf);
|
||||
}
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2,
|
||||
const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
/*Keep the great y in p1*/
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
if(point1->y < point2->y) {
|
||||
p1.y = point1->y;
|
||||
p2.y = point2->y;
|
||||
p1.x = point1->x;
|
||||
p2.x = point2->x;
|
||||
}
|
||||
else {
|
||||
p1.y = point2->y;
|
||||
p2.y = point1->y;
|
||||
p1.x = point2->x;
|
||||
p2.x = point1->x;
|
||||
}
|
||||
|
||||
int32_t xdiff = p2.x - p1.x;
|
||||
int32_t ydiff = p2.y - p1.y;
|
||||
bool flat = LV_ABS(xdiff) > LV_ABS(ydiff) ? true : false;
|
||||
|
||||
static const uint8_t wcorr[] = {
|
||||
128, 128, 128, 129, 129, 130, 130, 131,
|
||||
132, 133, 134, 135, 137, 138, 140, 141,
|
||||
143, 145, 147, 149, 151, 153, 155, 158,
|
||||
160, 162, 165, 167, 170, 173, 175, 178,
|
||||
181,
|
||||
};
|
||||
|
||||
int32_t w = dsc->width;
|
||||
int32_t wcorr_i = 0;
|
||||
if(flat) wcorr_i = (LV_ABS(ydiff) << 5) / LV_ABS(xdiff);
|
||||
else wcorr_i = (LV_ABS(xdiff) << 5) / LV_ABS(ydiff);
|
||||
|
||||
w = (w * wcorr[wcorr_i] + 63) >> 7; /*+ 63 for rounding*/
|
||||
int32_t w_half0 = w >> 1;
|
||||
int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/
|
||||
|
||||
lv_area_t draw_area;
|
||||
draw_area.x1 = LV_MIN(p1.x, p2.x) - w;
|
||||
draw_area.x2 = LV_MAX(p1.x, p2.x) + w;
|
||||
draw_area.y1 = LV_MIN(p1.y, p2.y) - w;
|
||||
draw_area.y2 = LV_MAX(p1.y, p2.y) + w;
|
||||
|
||||
/*Get the union of `coords` and `clip`*/
|
||||
/*`clip` is already truncated to the `draw_buf` size
|
||||
*in 'lv_refr_area' function*/
|
||||
bool is_common = _lv_area_intersect(&draw_area, &draw_area, clip);
|
||||
if(is_common == false) return;
|
||||
|
||||
lv_draw_mask_line_param_t mask_left_param;
|
||||
lv_draw_mask_line_param_t mask_right_param;
|
||||
lv_draw_mask_line_param_t mask_top_param;
|
||||
lv_draw_mask_line_param_t mask_bottom_param;
|
||||
|
||||
if(flat) {
|
||||
if(xdiff > 0) {
|
||||
lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0,
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT);
|
||||
lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT);
|
||||
}
|
||||
else {
|
||||
lv_draw_mask_line_points_init(&mask_left_param, p1.x, p1.y + w_half1, p2.x, p2.y + w_half1,
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT);
|
||||
lv_draw_mask_line_points_init(&mask_right_param, p1.x, p1.y - w_half0, p2.x, p2.y - w_half0,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_draw_mask_line_points_init(&mask_left_param, p1.x + w_half1, p1.y, p2.x + w_half1, p2.y,
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT);
|
||||
lv_draw_mask_line_points_init(&mask_right_param, p1.x - w_half0, p1.y, p2.x - w_half0, p2.y,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT);
|
||||
}
|
||||
|
||||
/*Use the normal vector for the endings*/
|
||||
|
||||
int16_t mask_left_id = lv_draw_mask_add(&mask_left_param, NULL);
|
||||
int16_t mask_right_id = lv_draw_mask_add(&mask_right_param, NULL);
|
||||
int16_t mask_top_id = LV_MASK_ID_INV;
|
||||
int16_t mask_bottom_id = LV_MASK_ID_INV;
|
||||
|
||||
if(!dsc->raw_end) {
|
||||
lv_draw_mask_line_points_init(&mask_top_param, p1.x, p1.y, p1.x - ydiff, p1.y + xdiff, LV_DRAW_MASK_LINE_SIDE_BOTTOM);
|
||||
lv_draw_mask_line_points_init(&mask_bottom_param, p2.x, p2.y, p2.x - ydiff, p2.y + xdiff, LV_DRAW_MASK_LINE_SIDE_TOP);
|
||||
mask_top_id = lv_draw_mask_add(&mask_top_param, NULL);
|
||||
mask_bottom_id = lv_draw_mask_add(&mask_bottom_param, NULL);
|
||||
}
|
||||
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);
|
||||
|
||||
const lv_area_t * disp_area = &draw_buf->area;
|
||||
|
||||
/*Store the coordinates of the `draw_a` relative to the draw_buf*/
|
||||
draw_area.x1 -= disp_area->x1;
|
||||
draw_area.y1 -= disp_area->y1;
|
||||
draw_area.x2 -= disp_area->x1;
|
||||
draw_area.y2 -= disp_area->y1;
|
||||
|
||||
/*The real draw area is around the line.
|
||||
*It's easy to calculate with steep lines, but the area can be very wide with very flat lines.
|
||||
*So deal with it only with steep lines.*/
|
||||
int32_t draw_area_w = lv_area_get_width(&draw_area);
|
||||
|
||||
/*Draw the background line by line*/
|
||||
int32_t h;
|
||||
uint32_t hor_res = (uint32_t)lv_disp_get_hor_res(disp);
|
||||
size_t mask_buf_size = LV_MIN(lv_area_get_size(&draw_area), hor_res);
|
||||
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
|
||||
|
||||
lv_area_t fill_area;
|
||||
fill_area.x1 = draw_area.x1 + disp_area->x1;
|
||||
fill_area.x2 = draw_area.x2 + disp_area->x1;
|
||||
fill_area.y1 = draw_area.y1 + disp_area->y1;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
|
||||
int32_t x = draw_buf->area.x1 + draw_area.x1;
|
||||
|
||||
uint32_t mask_p = 0;
|
||||
|
||||
lv_memset_ff(mask_buf, mask_buf_size);
|
||||
/*Fill the first row with 'color'*/
|
||||
for(h = draw_area.y1 + disp_area->y1; h <= draw_area.y2 + disp_area->y1; h++) {
|
||||
|
||||
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(&mask_buf[mask_p], x, h, draw_area_w);
|
||||
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
|
||||
lv_memset_00(&mask_buf[mask_p], draw_area_w);
|
||||
}
|
||||
|
||||
mask_p += draw_area_w;
|
||||
if((uint32_t) mask_p + draw_area_w < mask_buf_size) {
|
||||
fill_area.y2 ++;
|
||||
}
|
||||
else {
|
||||
_lv_blend_fill(&fill_area, clip,
|
||||
dsc->color, mask_buf, LV_DRAW_MASK_RES_CHANGED, dsc->opa,
|
||||
dsc->blend_mode);
|
||||
|
||||
fill_area.y1 = fill_area.y2 + 1;
|
||||
fill_area.y2 = fill_area.y1;
|
||||
mask_p = 0;
|
||||
lv_memset_ff(mask_buf, mask_buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
/*Flush the last part*/
|
||||
if(fill_area.y1 != fill_area.y2) {
|
||||
fill_area.y2--;
|
||||
_lv_blend_fill(&fill_area, clip,
|
||||
dsc->color, mask_buf, LV_DRAW_MASK_RES_CHANGED, dsc->opa,
|
||||
dsc->blend_mode);
|
||||
|
||||
}
|
||||
|
||||
lv_mem_buf_release(mask_buf);
|
||||
|
||||
lv_draw_mask_free_param(&mask_left_param);
|
||||
lv_draw_mask_free_param(&mask_right_param);
|
||||
if(mask_top_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_top_param);
|
||||
if(mask_bottom_id != LV_MASK_ID_INV) lv_draw_mask_free_param(&mask_bottom_param);
|
||||
lv_draw_mask_remove_id(mask_left_id);
|
||||
lv_draw_mask_remove_id(mask_right_id);
|
||||
lv_draw_mask_remove_id(mask_top_id);
|
||||
lv_draw_mask_remove_id(mask_bottom_id);
|
||||
#else
|
||||
LV_UNUSED(point1);
|
||||
LV_UNUSED(point2);
|
||||
LV_UNUSED(clip);
|
||||
LV_UNUSED(dsc);
|
||||
LV_LOG_WARN("Can't draw skewed line with LV_DRAW_COMPLEX == 0");
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
64
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_line.h
Normal file
64
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_line.h
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file lv_draw_line.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_LINE_H
|
||||
#define LV_DRAW_LINE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_blend.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_color_t color;
|
||||
lv_coord_t width;
|
||||
lv_coord_t dash_width;
|
||||
lv_coord_t dash_gap;
|
||||
lv_opa_t opa;
|
||||
lv_blend_mode_t blend_mode : 2;
|
||||
uint8_t round_start : 1;
|
||||
uint8_t round_end : 1;
|
||||
uint8_t raw_end : 1; /*Do not bother with perpendicular line ending if it's not visible for any reason*/
|
||||
} lv_draw_line_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
/**
|
||||
* Draw a line
|
||||
* @param point1 first point of the line
|
||||
* @param point2 second point of the line
|
||||
* @param clip the line will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_line_dsc_t` variable
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line(const lv_point_t * point1, const lv_point_t * point2, const lv_area_t * clip,
|
||||
const lv_draw_line_dsc_t * dsc);
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_line_dsc_init(lv_draw_line_dsc_t * dsc);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_LINE_H*/
|
1428
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_mask.c
Normal file
1428
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_mask.c
Normal file
File diff suppressed because it is too large
Load Diff
384
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_mask.h
Normal file
384
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_mask.h
Normal file
@ -0,0 +1,384 @@
|
||||
/**
|
||||
* @file lv_draw_mask.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_MASK_H
|
||||
#define LV_DRAW_MASK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_area.h"
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_MASK_ID_INV (-1)
|
||||
#if LV_DRAW_COMPLEX
|
||||
# define _LV_MASK_MAX_NUM 16
|
||||
# ifndef _LV_MASK_BUF_MAX_SIZE
|
||||
# define _LV_MASK_BUF_MAX_SIZE 2048 /*Should be >= than the max hor res*/
|
||||
# endif
|
||||
#else
|
||||
# define _LV_MASK_MAX_NUM 1
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_RES_TRANSP,
|
||||
LV_DRAW_MASK_RES_FULL_COVER,
|
||||
LV_DRAW_MASK_RES_CHANGED,
|
||||
LV_DRAW_MASK_RES_UNKNOWN
|
||||
};
|
||||
|
||||
typedef uint8_t lv_draw_mask_res_t;
|
||||
|
||||
typedef struct {
|
||||
void * param;
|
||||
void * custom_id;
|
||||
} _lv_draw_mask_saved_t;
|
||||
|
||||
typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM];
|
||||
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX == 0
|
||||
static inline uint8_t lv_draw_mask_get_cnt(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool lv_draw_mask_is_any(const lv_area_t * a)
|
||||
{
|
||||
LV_UNUSED(a);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_TYPE_LINE,
|
||||
LV_DRAW_MASK_TYPE_ANGLE,
|
||||
LV_DRAW_MASK_TYPE_RADIUS,
|
||||
LV_DRAW_MASK_TYPE_FADE,
|
||||
LV_DRAW_MASK_TYPE_MAP,
|
||||
};
|
||||
|
||||
typedef uint8_t lv_draw_mask_type_t;
|
||||
|
||||
enum {
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT = 0,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT,
|
||||
LV_DRAW_MASK_LINE_SIDE_TOP,
|
||||
LV_DRAW_MASK_LINE_SIDE_BOTTOM,
|
||||
};
|
||||
|
||||
/**
|
||||
* A common callback type for every mask type.
|
||||
* Used internally by the library.
|
||||
*/
|
||||
typedef lv_draw_mask_res_t (*lv_draw_mask_xcb_t)(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len,
|
||||
void * p);
|
||||
|
||||
typedef uint8_t lv_draw_mask_line_side_t;
|
||||
|
||||
typedef struct {
|
||||
lv_draw_mask_xcb_t cb;
|
||||
lv_draw_mask_type_t type;
|
||||
} _lv_draw_mask_common_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
/*First point*/
|
||||
lv_point_t p1;
|
||||
|
||||
/*Second point*/
|
||||
lv_point_t p2;
|
||||
|
||||
/*Which side to keep?*/
|
||||
lv_draw_mask_line_side_t side : 2;
|
||||
} cfg;
|
||||
|
||||
/*A point of the line*/
|
||||
lv_point_t origo;
|
||||
|
||||
/*X / (1024*Y) steepness (X is 0..1023 range). What is the change of X in 1024 Y?*/
|
||||
int32_t xy_steep;
|
||||
|
||||
/*Y / (1024*X) steepness (Y is 0..1023 range). What is the change of Y in 1024 X?*/
|
||||
int32_t yx_steep;
|
||||
|
||||
/*Helper which stores yx_steep for flat lines and xy_steep for steep (non flat) lines*/
|
||||
int32_t steep;
|
||||
|
||||
/*Steepness in 1 px in 0..255 range. Used only by flat lines.*/
|
||||
int32_t spx;
|
||||
|
||||
/*1: It's a flat line? (Near to horizontal)*/
|
||||
uint8_t flat : 1;
|
||||
|
||||
/*Invert the mask. The default is: Keep the left part.
|
||||
*It is used to select left/right/top/bottom*/
|
||||
uint8_t inv: 1;
|
||||
} lv_draw_mask_line_param_t;
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_point_t vertex_p;
|
||||
lv_coord_t start_angle;
|
||||
lv_coord_t end_angle;
|
||||
} cfg;
|
||||
|
||||
lv_draw_mask_line_param_t start_line;
|
||||
lv_draw_mask_line_param_t end_line;
|
||||
uint16_t delta_deg;
|
||||
} lv_draw_mask_angle_param_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t * buf;
|
||||
lv_opa_t * cir_opa; /*Opacity of values on the circumference of an 1/4 circle*/
|
||||
uint16_t * x_start_on_y; /*The x coordinate of the circle for each y value*/
|
||||
uint16_t * opa_start_on_y; /*The index of `cir_opa` for each y value*/
|
||||
int32_t life; /*How many times the entry way used*/
|
||||
uint32_t used_cnt; /*Like a semaphore to count the referencing masks*/
|
||||
lv_coord_t radius; /*The radius of the entry*/
|
||||
} _lv_draw_mask_radius_circle_dsc_t;
|
||||
|
||||
typedef _lv_draw_mask_radius_circle_dsc_t _lv_draw_mask_radius_circle_dsc_arr_t[LV_CIRCLE_CACHE_SIZE];
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t rect;
|
||||
lv_coord_t radius;
|
||||
/*Invert the mask. 0: Keep the pixels inside.*/
|
||||
uint8_t outer: 1;
|
||||
} cfg;
|
||||
|
||||
_lv_draw_mask_radius_circle_dsc_t * circle;
|
||||
} lv_draw_mask_radius_param_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t coords;
|
||||
lv_coord_t y_top;
|
||||
lv_coord_t y_bottom;
|
||||
lv_opa_t opa_top;
|
||||
lv_opa_t opa_bottom;
|
||||
} cfg;
|
||||
|
||||
} lv_draw_mask_fade_param_t;
|
||||
|
||||
|
||||
typedef struct _lv_draw_mask_map_param_t {
|
||||
/*The first element must be the common descriptor*/
|
||||
_lv_draw_mask_common_dsc_t dsc;
|
||||
|
||||
struct {
|
||||
lv_area_t coords;
|
||||
const lv_opa_t * map;
|
||||
} cfg;
|
||||
} lv_draw_mask_map_param_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Add a draw mask. Everything drawn after it (until removing the mask) will be affected by the mask.
|
||||
* @param param an initialized mask parameter. Only the pointer is saved.
|
||||
* @param custom_id a custom pointer to identify the mask. Used in `lv_draw_mask_remove_custom`.
|
||||
* @return the an integer, the ID of the mask. Can be used in `lv_draw_mask_remove_id`.
|
||||
*/
|
||||
int16_t lv_draw_mask_add(void * param, void * custom_id);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
* Apply the added buffers on a line. Used internally by the library's drawing routines.
|
||||
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
|
||||
* @param abs_x absolute X coordinate where the line to calculate start
|
||||
* @param abs_y absolute Y coordinate where the line to calculate start
|
||||
* @param len length of the line to calculate (in pixel count)
|
||||
* @return One of these values:
|
||||
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
|
||||
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
|
||||
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len);
|
||||
|
||||
/**
|
||||
* Apply the specified buffers on a line. Used internally by the library's drawing routines.
|
||||
* @param mask_buf store the result mask here. Has to be `len` byte long. Should be initialized with `0xFF`.
|
||||
* @param abs_x absolute X coordinate where the line to calculate start
|
||||
* @param abs_y absolute Y coordinate where the line to calculate start
|
||||
* @param len length of the line to calculate (in pixel count)
|
||||
* @param ids ID array of added buffers
|
||||
* @param ids_count number of ID array
|
||||
* @return One of these values:
|
||||
* - `LV_DRAW_MASK_RES_FULL_TRANSP`: the whole line is transparent. `mask_buf` is not set to zero
|
||||
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
|
||||
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply_ids(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y,
|
||||
lv_coord_t len, const int16_t *ids, int16_t ids_count);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
* Remove a mask with a given ID
|
||||
* @param id the ID of the mask. Returned by `lv_draw_mask_add`
|
||||
* @return the parameter of the removed mask.
|
||||
* If more masks have `custom_id` ID then the last mask's parameter will be returned
|
||||
*/
|
||||
void * lv_draw_mask_remove_id(int16_t id);
|
||||
|
||||
/**
|
||||
* Remove all mask with a given custom ID
|
||||
* @param custom_id a pointer used in `lv_draw_mask_add`
|
||||
* @return return the parameter of the removed mask.
|
||||
* If more masks have `custom_id` ID then the last mask's parameter will be returned
|
||||
*/
|
||||
void * lv_draw_mask_remove_custom(void * custom_id);
|
||||
|
||||
/**
|
||||
* Free the data from the parameter.
|
||||
* It's called inside `lv_draw_mask_remove_id` and `lv_draw_mask_remove_custom`
|
||||
* Needs to be called only in special cases when the mask is not added by `lv_draw_mask_add`
|
||||
* and not removed by `lv_draw_mask_remove_id` or `lv_draw_mask_remove_custom`
|
||||
* @param p pointer to a mask parameter
|
||||
*/
|
||||
void lv_draw_mask_free_param(void * p);
|
||||
|
||||
/**
|
||||
* Called by LVGL the rendering of a screen is ready to clean up
|
||||
* the temporal (cache) data of the masks
|
||||
*/
|
||||
void _lv_draw_mask_cleanup(void);
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
/**
|
||||
* Count the currently added masks
|
||||
* @return number of active masks
|
||||
*/
|
||||
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
|
||||
|
||||
|
||||
/**
|
||||
* Check if there is any added draw mask
|
||||
* @param a an area to test for affecting masks.
|
||||
* @return true: there is t least 1 draw mask; false: there are no draw masks
|
||||
*/
|
||||
bool lv_draw_mask_is_any(const lv_area_t * a);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
*Initialize a line mask from two points.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param p1x X coordinate of the first point of the line
|
||||
* @param p1y Y coordinate of the first point of the line
|
||||
* @param p2x X coordinate of the second point of the line
|
||||
* @param p2y y coordinate of the second point of the line
|
||||
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
|
||||
*/
|
||||
void lv_draw_mask_line_points_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t p1y, lv_coord_t p2x,
|
||||
lv_coord_t p2y, lv_draw_mask_line_side_t side);
|
||||
|
||||
/**
|
||||
*Initialize a line mask from a point and an angle.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param px X coordinate of a point of the line
|
||||
* @param py X coordinate of a point of the line
|
||||
* @param angle right 0 deg, bottom: 90
|
||||
* @param side and element of `lv_draw_mask_line_side_t` to describe which side to keep.
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_LEFT/RIGHT` and horizontal line all pixels are kept
|
||||
* With `LV_DRAW_MASK_LINE_SIDE_TOP/BOTTOM` and vertical line all pixels are kept
|
||||
*/
|
||||
void lv_draw_mask_line_angle_init(lv_draw_mask_line_param_t * param, lv_coord_t p1x, lv_coord_t py, int16_t angle,
|
||||
lv_draw_mask_line_side_t side);
|
||||
|
||||
/**
|
||||
* Initialize an angle mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param vertex_x X coordinate of the angle vertex (absolute coordinates)
|
||||
* @param vertex_y Y coordinate of the angle vertex (absolute coordinates)
|
||||
* @param start_angle start angle in degrees. 0 deg on the right, 90 deg, on the bottom
|
||||
* @param end_angle end angle
|
||||
*/
|
||||
void lv_draw_mask_angle_init(lv_draw_mask_angle_param_t * param, lv_coord_t vertex_x, lv_coord_t vertex_y,
|
||||
lv_coord_t start_angle, lv_coord_t end_angle);
|
||||
|
||||
/**
|
||||
* Initialize a fade mask.
|
||||
* @param param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param rect coordinates of the rectangle to affect (absolute coordinates)
|
||||
* @param radius radius of the rectangle
|
||||
* @param inv true: keep the pixels inside the rectangle; keep the pixels outside of the rectangle
|
||||
*/
|
||||
void lv_draw_mask_radius_init(lv_draw_mask_radius_param_t * param, const lv_area_t * rect, lv_coord_t radius, bool inv);
|
||||
|
||||
/**
|
||||
* Initialize a fade mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param coords coordinates of the area to affect (absolute coordinates)
|
||||
* @param opa_top opacity on the top
|
||||
* @param y_top at which coordinate start to change to opacity to `opa_bottom`
|
||||
* @param opa_bottom opacity at the bottom
|
||||
* @param y_bottom at which coordinate reach `opa_bottom`.
|
||||
*/
|
||||
void lv_draw_mask_fade_init(lv_draw_mask_fade_param_t * param, const lv_area_t * coords, lv_opa_t opa_top,
|
||||
lv_coord_t y_top,
|
||||
lv_opa_t opa_bottom, lv_coord_t y_bottom);
|
||||
|
||||
/**
|
||||
* Initialize a map mask.
|
||||
* @param param pointer to a `lv_draw_mask_param_t` to initialize
|
||||
* @param coords coordinates of the map (absolute coordinates)
|
||||
* @param map array of bytes with the mask values
|
||||
*/
|
||||
void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * coords, const lv_opa_t * map);
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_MASK_H*/
|
1338
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_rect.c
Normal file
1338
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_rect.c
Normal file
File diff suppressed because it is too large
Load Diff
104
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_rect.h
Normal file
104
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_rect.h
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @file lv_draw_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_RECT_H
|
||||
#define LV_DRAW_RECT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_blend.h"
|
||||
#include "../font/lv_font.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_RADIUS_CIRCLE 0x7FFF /**< A very big radius to always draw as circle*/
|
||||
LV_EXPORT_CONST_INT(LV_RADIUS_CIRCLE);
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t radius;
|
||||
lv_blend_mode_t blend_mode;
|
||||
|
||||
/*Background*/
|
||||
lv_color_t bg_color;
|
||||
lv_color_t bg_grad_color;
|
||||
uint8_t bg_main_color_stop;
|
||||
uint8_t bg_grad_color_stop;
|
||||
lv_opa_t bg_opa;
|
||||
lv_grad_dir_t bg_grad_dir : 3;
|
||||
|
||||
/*Background img*/
|
||||
const void * bg_img_src;
|
||||
const void * bg_img_symbol_font;
|
||||
lv_color_t bg_img_recolor;
|
||||
lv_opa_t bg_img_opa;
|
||||
lv_opa_t bg_img_recolor_opa;
|
||||
uint8_t bg_img_tiled;
|
||||
|
||||
/*Border*/
|
||||
lv_color_t border_color;
|
||||
lv_coord_t border_width;
|
||||
lv_opa_t border_opa;
|
||||
uint8_t border_post : 1; /*There is a border it will be drawn later.*/
|
||||
lv_border_side_t border_side : 5;
|
||||
|
||||
/*Outline*/
|
||||
lv_color_t outline_color;
|
||||
lv_coord_t outline_width;
|
||||
lv_coord_t outline_pad;
|
||||
lv_opa_t outline_opa;
|
||||
|
||||
/*Shadow*/
|
||||
lv_color_t shadow_color;
|
||||
lv_coord_t shadow_width;
|
||||
lv_coord_t shadow_ofs_x;
|
||||
lv_coord_t shadow_ofs_y;
|
||||
lv_coord_t shadow_spread;
|
||||
lv_opa_t shadow_opa;
|
||||
} lv_draw_rect_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
LV_ATTRIBUTE_FAST_MEM void lv_draw_rect_dsc_init(lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
* Draw a rectangle
|
||||
* @param coords the coordinates of the rectangle
|
||||
* @param clip the rectangle will be drawn only in this area
|
||||
* @param dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Draw a pixel
|
||||
* @param point the coordinates of the point to draw
|
||||
* @param mask the pixel will be drawn only in this mask
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
//void lv_draw_px(const lv_point_t * point, const lv_area_t * clip_area, const lv_style_t * style);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_RECT_H*/
|
216
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_triangle.c
Normal file
216
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_triangle.c
Normal file
@ -0,0 +1,216 @@
|
||||
/**
|
||||
* @file lv_draw_triangle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_triangle.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw a triangle
|
||||
* @param points pointer to an array with 3 points
|
||||
* @param clip_area the triangle will be drawn only in this area
|
||||
* @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_triangle(const lv_point_t points[], const lv_area_t * clip_area, const lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
lv_draw_polygon(points, 3, clip_area, draw_dsc);
|
||||
#else
|
||||
LV_UNUSED(points);
|
||||
LV_UNUSED(clip_area);
|
||||
LV_UNUSED(draw_dsc);
|
||||
LV_LOG_WARN("Can't draw triangle with LV_DRAW_COMPLEX == 0");
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a polygon. Only convex polygons are supported
|
||||
* @param points an array of points
|
||||
* @param point_cnt number of points
|
||||
* @param clip_area polygon will be drawn only in this area
|
||||
* @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_polygon(const lv_point_t points[], uint16_t point_cnt, const lv_area_t * clip_area,
|
||||
const lv_draw_rect_dsc_t * draw_dsc)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(point_cnt < 3) return;
|
||||
if(points == NULL) return;
|
||||
|
||||
/*Join adjacent points if they are on the same coordinate*/
|
||||
lv_point_t * p = lv_mem_buf_get(point_cnt * sizeof(lv_point_t));
|
||||
if(p == NULL) return;
|
||||
uint16_t i;
|
||||
uint16_t pcnt = 0;
|
||||
p[0] = points[0];
|
||||
for(i = 0; i < point_cnt - 1; i++) {
|
||||
if(points[i].x != points[i + 1].x || points[i].y != points[i + 1].y) {
|
||||
p[pcnt] = points[i];
|
||||
pcnt++;
|
||||
}
|
||||
}
|
||||
/*The first and the last points are also adjacent*/
|
||||
if(points[0].x != points[point_cnt - 1].x || points[0].y != points[point_cnt - 1].y) {
|
||||
p[pcnt] = points[point_cnt - 1];
|
||||
pcnt++;
|
||||
}
|
||||
|
||||
point_cnt = pcnt;
|
||||
if(point_cnt < 3) {
|
||||
lv_mem_buf_release(p);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t poly_coords = {.x1 = LV_COORD_MAX, .y1 = LV_COORD_MAX, .x2 = LV_COORD_MIN, .y2 = LV_COORD_MIN};
|
||||
|
||||
for(i = 0; i < point_cnt; i++) {
|
||||
poly_coords.x1 = LV_MIN(poly_coords.x1, p[i].x);
|
||||
poly_coords.y1 = LV_MIN(poly_coords.y1, p[i].y);
|
||||
poly_coords.x2 = LV_MAX(poly_coords.x2, p[i].x);
|
||||
poly_coords.y2 = LV_MAX(poly_coords.y2, p[i].y);
|
||||
}
|
||||
|
||||
bool is_common;
|
||||
lv_area_t poly_mask;
|
||||
is_common = _lv_area_intersect(&poly_mask, &poly_coords, clip_area);
|
||||
if(!is_common) {
|
||||
lv_mem_buf_release(p);
|
||||
return;
|
||||
}
|
||||
/*Find the lowest point*/
|
||||
lv_coord_t y_min = p[0].y;
|
||||
int16_t y_min_i = 0;
|
||||
|
||||
for(i = 1; i < point_cnt; i++) {
|
||||
if(p[i].y < y_min) {
|
||||
y_min = p[i].y;
|
||||
y_min_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_mask_line_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_line_param_t) * point_cnt);
|
||||
lv_draw_mask_line_param_t * mp_next = mp;
|
||||
|
||||
int32_t i_prev_left = y_min_i;
|
||||
int32_t i_prev_right = y_min_i;
|
||||
int32_t i_next_left;
|
||||
int32_t i_next_right;
|
||||
uint32_t mask_cnt = 0;
|
||||
|
||||
/*Get the index of the left and right points*/
|
||||
i_next_left = y_min_i - 1;
|
||||
if(i_next_left < 0) i_next_left = point_cnt + i_next_left;
|
||||
|
||||
i_next_right = y_min_i + 1;
|
||||
if(i_next_right > point_cnt - 1) i_next_right = 0;
|
||||
|
||||
/**
|
||||
* Check if the order of points is inverted or not.
|
||||
* The normal case is when the left point is on `y_min_i - 1`
|
||||
* Explanation:
|
||||
* if angle(p_left) < angle(p_right) -> inverted
|
||||
* dy_left/dx_left < dy_right/dx_right
|
||||
* dy_left * dx_right < dy_right * dx_left
|
||||
*/
|
||||
lv_coord_t dxl = p[i_next_left].x - p[y_min_i].x;
|
||||
lv_coord_t dxr = p[i_next_right].x - p[y_min_i].x;
|
||||
lv_coord_t dyl = p[i_next_left].y - p[y_min_i].y;
|
||||
lv_coord_t dyr = p[i_next_right].y - p[y_min_i].y;
|
||||
|
||||
bool inv = false;
|
||||
if(dyl * dxr < dyr * dxl) inv = true;
|
||||
|
||||
do {
|
||||
if(!inv) {
|
||||
i_next_left = i_prev_left - 1;
|
||||
if(i_next_left < 0) i_next_left = point_cnt + i_next_left;
|
||||
|
||||
i_next_right = i_prev_right + 1;
|
||||
if(i_next_right > point_cnt - 1) i_next_right = 0;
|
||||
}
|
||||
else {
|
||||
i_next_left = i_prev_left + 1;
|
||||
if(i_next_left > point_cnt - 1) i_next_left = 0;
|
||||
|
||||
i_next_right = i_prev_right - 1;
|
||||
if(i_next_right < 0) i_next_right = point_cnt + i_next_right;
|
||||
}
|
||||
|
||||
if(p[i_next_left].y >= p[i_prev_left].y) {
|
||||
if(p[i_next_left].y != p[i_prev_left].y &&
|
||||
p[i_next_left].x != p[i_prev_left].x) {
|
||||
lv_draw_mask_line_points_init(mp_next, p[i_prev_left].x, p[i_prev_left].y,
|
||||
p[i_next_left].x, p[i_next_left].y,
|
||||
LV_DRAW_MASK_LINE_SIDE_RIGHT);
|
||||
lv_draw_mask_add(mp_next, mp);
|
||||
mp_next++;
|
||||
}
|
||||
mask_cnt++;
|
||||
i_prev_left = i_next_left;
|
||||
}
|
||||
|
||||
if(mask_cnt == point_cnt) break;
|
||||
|
||||
if(p[i_next_right].y >= p[i_prev_right].y) {
|
||||
if(p[i_next_right].y != p[i_prev_right].y &&
|
||||
p[i_next_right].x != p[i_prev_right].x) {
|
||||
|
||||
lv_draw_mask_line_points_init(mp_next, p[i_prev_right].x, p[i_prev_right].y,
|
||||
p[i_next_right].x, p[i_next_right].y,
|
||||
LV_DRAW_MASK_LINE_SIDE_LEFT);
|
||||
lv_draw_mask_add(mp_next, mp);
|
||||
mp_next++;
|
||||
}
|
||||
mask_cnt++;
|
||||
i_prev_right = i_next_right;
|
||||
}
|
||||
|
||||
} while(mask_cnt < point_cnt);
|
||||
|
||||
lv_draw_rect(&poly_coords, clip_area, draw_dsc);
|
||||
|
||||
lv_draw_mask_remove_custom(mp);
|
||||
|
||||
lv_mem_buf_release(mp);
|
||||
lv_mem_buf_release(p);
|
||||
#else
|
||||
LV_UNUSED(points);
|
||||
LV_UNUSED(point_cnt);
|
||||
LV_UNUSED(clip_area);
|
||||
LV_UNUSED(draw_dsc);
|
||||
LV_LOG_WARN("Can't draw polygon with LV_DRAW_COMPLEX == 0");
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
56
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_triangle.h
Normal file
56
EC600U_lvgl_lib/lvgl/src/draw/lv_draw_triangle.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file lv_draw_triangle.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DRAW_TRIANGLE_H
|
||||
#define LV_DRAW_TRIANGLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw_rect.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Draw a triangle
|
||||
* @param points pointer to an array with 3 points
|
||||
* @param clip_area the triangle will be drawn only in this area
|
||||
* @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_triangle(const lv_point_t points[], const lv_area_t * clip, const lv_draw_rect_dsc_t * draw_dsc);
|
||||
|
||||
/**
|
||||
* Draw a polygon. Only convex polygons are supported.
|
||||
* @param points an array of points
|
||||
* @param point_cnt number of points
|
||||
* @param clip_area polygon will be drawn only in this area
|
||||
* @param draw_dsc pointer to an initialized `lv_draw_rect_dsc_t` variable
|
||||
*/
|
||||
void lv_draw_polygon(const lv_point_t points[], uint16_t point_cnt, const lv_area_t * mask,
|
||||
const lv_draw_rect_dsc_t * draw_dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_DRAW_TRIANGLE_H*/
|
772
EC600U_lvgl_lib/lvgl/src/draw/lv_img_buf.c
Normal file
772
EC600U_lvgl_lib/lvgl/src/draw/lv_img_buf.c
Normal file
@ -0,0 +1,772 @@
|
||||
/**
|
||||
* @file lv_img_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../misc/lv_math.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @param safe true: check out of bounds
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color)
|
||||
{
|
||||
lv_color_t p_color = lv_color_black();
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
#if LV_COLOR_SIZE == 32
|
||||
p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/
|
||||
#endif
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8, 16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2, 4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param safe true: check out of bounds
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
return opa_table[px_opa];
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
return buf_u8[px];
|
||||
}
|
||||
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
lv_memcpy_small(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
*so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
*so the possible real width are 4, 8 ,12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/*Get the current pixel.
|
||||
*dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
*so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c)
|
||||
{
|
||||
if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) ||
|
||||
(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) {
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(c);
|
||||
uint8_t * buf = (uint8_t *)dsc->data;
|
||||
lv_memcpy_small(&buf[id * sizeof(c32)], &c32, sizeof(c32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
/*Allocate image descriptor*/
|
||||
lv_img_dsc_t * dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
lv_memset_00(dsc, sizeof(lv_img_dsc_t));
|
||||
|
||||
/*Get image data size*/
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*Allocate raw buffer*/
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
lv_memset_00((uint8_t *)dsc->data, dsc->data_size);
|
||||
|
||||
/*Fill in header*/
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t * dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free((void *)dsc->data);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED:
|
||||
return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Initialize a descriptor to transform an image
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
dsc->tmp.pivot_x_256 = dsc->cfg.pivot_x * 256;
|
||||
dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256;
|
||||
|
||||
int32_t angle_low = dsc->cfg.angle / 10;
|
||||
int32_t angle_high = angle_low + 1;
|
||||
int32_t angle_rem = dsc->cfg.angle - (angle_low * 10);
|
||||
|
||||
int32_t s1 = lv_trigo_sin(-angle_low);
|
||||
int32_t s2 = lv_trigo_sin(-angle_high);
|
||||
|
||||
int32_t c1 = lv_trigo_sin(-angle_low + 90);
|
||||
int32_t c2 = lv_trigo_sin(-angle_high + 90);
|
||||
|
||||
dsc->tmp.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10;
|
||||
dsc->tmp.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10;
|
||||
|
||||
/*Use smaller value to avoid overflow*/
|
||||
dsc->tmp.sinma = dsc->tmp.sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
dsc->tmp.cosma = dsc->tmp.cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
|
||||
dsc->tmp.chroma_keyed = lv_img_cf_is_chroma_keyed(dsc->cfg.cf) ? 1 : 0;
|
||||
dsc->tmp.has_alpha = lv_img_cf_has_alpha(dsc->cfg.cf) ? 1 : 0;
|
||||
if(dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
dsc->tmp.native_color = 1;
|
||||
}
|
||||
else {
|
||||
dsc->tmp.native_color = 0;
|
||||
}
|
||||
|
||||
dsc->tmp.img_dsc.data = dsc->cfg.src;
|
||||
dsc->tmp.img_dsc.header.always_zero = 0;
|
||||
dsc->tmp.img_dsc.header.cf = dsc->cfg.cf;
|
||||
dsc->tmp.img_dsc.header.w = dsc->cfg.src_w;
|
||||
dsc->tmp.img_dsc.header.h = dsc->cfg.src_h;
|
||||
|
||||
/*The inverse of the zoom will be sued during the transformation
|
||||
* + dsc->cfg.zoom / 2 for rounding*/
|
||||
dsc->tmp.zoom_inv = (((256 * 256) << _LV_ZOOM_INV_UPSCALE) + dsc->cfg.zoom / 2) / dsc->cfg.zoom;
|
||||
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
dsc->res.color = dsc->cfg.color;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the area of a rectangle if its rotated and scaled
|
||||
* @param res store the coordinates here
|
||||
* @param w width of the rectangle to transform
|
||||
* @param h height of the rectangle to transform
|
||||
* @param angle angle of rotation
|
||||
* @param zoom zoom, (256 no zoom)
|
||||
* @param pivot x,y pivot coordinates of rotation
|
||||
*/
|
||||
void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
|
||||
const lv_point_t * pivot)
|
||||
{
|
||||
#if LV_DRAW_COMPLEX
|
||||
if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) {
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
res->x1 = (((int32_t)(-pivot->x) * zoom) >> 8) - 1;
|
||||
res->y1 = (((int32_t)(-pivot->y) * zoom) >> 8) - 1;
|
||||
res->x2 = (((int32_t)(w - pivot->x) * zoom) >> 8) + 2;
|
||||
res->y2 = (((int32_t)(h - pivot->y) * zoom) >> 8) + 2;
|
||||
|
||||
if(angle == 0) {
|
||||
res->x1 += pivot->x;
|
||||
res->y1 += pivot->y;
|
||||
res->x2 += pivot->x;
|
||||
res->y2 += pivot->y;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t angle_low = angle / 10;
|
||||
int32_t angle_high = angle_low + 1;
|
||||
int32_t angle_rem = angle - (angle_low * 10);
|
||||
|
||||
int32_t s1 = lv_trigo_sin(angle_low);
|
||||
int32_t s2 = lv_trigo_sin(angle_high);
|
||||
|
||||
int32_t c1 = lv_trigo_sin(angle_low + 90);
|
||||
int32_t c2 = lv_trigo_sin(angle_high + 90);
|
||||
|
||||
int32_t sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10;
|
||||
int32_t cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10;
|
||||
|
||||
/*Use smaller value to avoid overflow*/
|
||||
sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT);
|
||||
|
||||
lv_point_t lt;
|
||||
lv_point_t rt;
|
||||
lv_point_t lb;
|
||||
lv_point_t rb;
|
||||
|
||||
lv_coord_t xt;
|
||||
lv_coord_t yt;
|
||||
|
||||
xt = res->x1;
|
||||
yt = res->y1;
|
||||
lt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
lt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x2;
|
||||
yt = res->y1;
|
||||
rt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
rt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x1;
|
||||
yt = res->y2;
|
||||
lb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
lb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
xt = res->x2;
|
||||
yt = res->y2;
|
||||
rb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x;
|
||||
rb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y;
|
||||
|
||||
res->x1 = LV_MIN4(lb.x, lt.x, rb.x, rt.x);
|
||||
res->x2 = LV_MAX4(lb.x, lt.x, rb.x, rt.x);
|
||||
res->y1 = LV_MIN4(lb.y, lt.y, rb.y, rt.y);
|
||||
res->y2 = LV_MAX4(lb.y, lt.y, rb.y, rt.y);
|
||||
#else
|
||||
LV_UNUSED(angle);
|
||||
LV_UNUSED(zoom);
|
||||
LV_UNUSED(pivot);
|
||||
res->x1 = 0;
|
||||
res->y1 = 0;
|
||||
res->x2 = w - 1;
|
||||
res->y2 = h - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Get which color and opa would come to a pixel if it were rotated
|
||||
* @param dsc a descriptor initialized by `lv_img_buf_rotate_init`
|
||||
* @param x the coordinate which color and opa should be get
|
||||
* @param y the coordinate which color and opa should be get
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
const uint8_t * src_u8 = (const uint8_t *)dsc->cfg.src;
|
||||
|
||||
/*Get the target point relative coordinates to the pivot*/
|
||||
int32_t xt = x - dsc->cfg.pivot_x;
|
||||
int32_t yt = y - dsc->cfg.pivot_y;
|
||||
|
||||
int32_t xs;
|
||||
int32_t ys;
|
||||
if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) {
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
else if(dsc->cfg.angle == 0) {
|
||||
xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
xs = xt + dsc->tmp.pivot_x_256;
|
||||
ys = yt + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
else {
|
||||
xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
|
||||
xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256;
|
||||
ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256;
|
||||
}
|
||||
|
||||
/*Get the integer part of the source pixel*/
|
||||
int32_t xs_int = xs >> 8;
|
||||
int32_t ys_int = ys >> 8;
|
||||
|
||||
if(xs_int >= dsc->cfg.src_w) return false;
|
||||
else if(xs_int < 0) return false;
|
||||
|
||||
if(ys_int >= dsc->cfg.src_h) return false;
|
||||
else if(ys_int < 0) return false;
|
||||
|
||||
uint8_t px_size;
|
||||
uint32_t pxi;
|
||||
if(dsc->tmp.native_color) {
|
||||
if(dsc->tmp.has_alpha == 0) {
|
||||
px_size = LV_COLOR_SIZE >> 3;
|
||||
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size);
|
||||
}
|
||||
else {
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
|
||||
lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1);
|
||||
dsc->res.opa = src_u8[pxi + px_size - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
pxi = 0; /*unused*/
|
||||
px_size = 0; /*unused*/
|
||||
dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color);
|
||||
dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int);
|
||||
}
|
||||
|
||||
if(dsc->tmp.chroma_keyed) {
|
||||
lv_color_t ct = LV_COLOR_CHROMA_KEY;
|
||||
if(dsc->res.color.full == ct.full) return false;
|
||||
}
|
||||
|
||||
if(dsc->cfg.antialias == false) return true;
|
||||
|
||||
dsc->tmp.xs = xs;
|
||||
dsc->tmp.ys = ys;
|
||||
dsc->tmp.xs_int = xs_int;
|
||||
dsc->tmp.ys_int = ys_int;
|
||||
dsc->tmp.pxi = pxi;
|
||||
dsc->tmp.px_size = px_size;
|
||||
|
||||
bool ret;
|
||||
ret = _lv_img_buf_transform_anti_alias(dsc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue transformation by taking the neighbors into account
|
||||
* @param dsc pointer to the transformation descriptor
|
||||
*/
|
||||
bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc)
|
||||
{
|
||||
const uint8_t * src_u8 = dsc->cfg.src;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = dsc->tmp.xs & 0xff;
|
||||
int ys_fract = dsc->tmp.ys & 0xff;
|
||||
int32_t xn; /*x neighbor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
|
||||
if(xs_fract < 0x70) {
|
||||
xn = - 1;
|
||||
if(dsc->tmp.xs_int + xn < 0) xn = 0;
|
||||
xr = xs_fract + 0x80;
|
||||
}
|
||||
else if(xs_fract > 0x90) {
|
||||
xn = 1;
|
||||
if(dsc->tmp.xs_int + xn >= dsc->cfg.src_w) xn = 0;
|
||||
xr = (0xFF - xs_fract) + 0x80;
|
||||
}
|
||||
else {
|
||||
xn = 0;
|
||||
xr = 0xFF;
|
||||
}
|
||||
|
||||
int32_t yn; /*x neighbor*/
|
||||
lv_opa_t yr; /*x mix ratio*/
|
||||
|
||||
if(ys_fract < 0x70) {
|
||||
yn = - 1;
|
||||
if(dsc->tmp.ys_int + yn < 0) yn = 0;
|
||||
|
||||
yr = ys_fract + 0x80;
|
||||
}
|
||||
else if(ys_fract > 0x90) {
|
||||
yn = 1;
|
||||
if(dsc->tmp.ys_int + yn >= dsc->cfg.src_h) yn = 0;
|
||||
|
||||
yr = (0xFF - ys_fract) + 0x80;
|
||||
}
|
||||
else {
|
||||
yn = 0;
|
||||
yr = 0xFF;
|
||||
}
|
||||
|
||||
lv_color_t c00 = dsc->res.color;
|
||||
lv_color_t c01;
|
||||
lv_color_t c10;
|
||||
lv_color_t c11;
|
||||
|
||||
lv_opa_t a00 = dsc->res.opa;
|
||||
lv_opa_t a10 = 0;
|
||||
lv_opa_t a01 = 0;
|
||||
lv_opa_t a11 = 0;
|
||||
|
||||
if(dsc->tmp.native_color) {
|
||||
lv_memcpy_small(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t));
|
||||
lv_memcpy_small(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t));
|
||||
lv_memcpy_small(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn],
|
||||
sizeof(lv_color_t));
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1];
|
||||
a11 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
c01 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int, dsc->cfg.color);
|
||||
c10 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
c11 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn, dsc->cfg.color);
|
||||
|
||||
if(dsc->tmp.has_alpha) {
|
||||
a10 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int);
|
||||
a01 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn);
|
||||
a11 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn);
|
||||
}
|
||||
}
|
||||
|
||||
lv_opa_t xr0 = xr;
|
||||
lv_opa_t xr1 = xr;
|
||||
if(dsc->tmp.has_alpha) {
|
||||
lv_opa_t a0 = (a00 * xr + (a10 * (255 - xr))) >> 8;
|
||||
lv_opa_t a1 = (a01 * xr + (a11 * (255 - xr))) >> 8;
|
||||
dsc->res.opa = (a0 * yr + (a1 * (255 - yr))) >> 8;
|
||||
|
||||
if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false;
|
||||
if(a0 <= LV_OPA_MIN) yr = LV_OPA_TRANSP;
|
||||
if(a1 <= LV_OPA_MIN) yr = LV_OPA_COVER;
|
||||
if(a00 <= LV_OPA_MIN) xr0 = LV_OPA_TRANSP;
|
||||
if(a10 <= LV_OPA_MIN) xr0 = LV_OPA_COVER;
|
||||
if(a01 <= LV_OPA_MIN) xr1 = LV_OPA_TRANSP;
|
||||
if(a11 <= LV_OPA_MIN) xr1 = LV_OPA_COVER;
|
||||
}
|
||||
else {
|
||||
xr0 = xr;
|
||||
xr1 = xr;
|
||||
dsc->res.opa = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
lv_color_t c0;
|
||||
if(xr0 == LV_OPA_TRANSP) c0 = c01;
|
||||
else if(xr0 == LV_OPA_COVER) c0 = c00;
|
||||
else c0 = lv_color_mix(c00, c01, xr0);
|
||||
|
||||
lv_color_t c1;
|
||||
if(xr1 == LV_OPA_TRANSP) c1 = c11;
|
||||
else if(xr1 == LV_OPA_COVER) c1 = c10;
|
||||
else c1 = lv_color_mix(c10, c11, xr1);
|
||||
|
||||
if(yr == LV_OPA_TRANSP) dsc->res.color = c1;
|
||||
else if(yr == LV_OPA_COVER) dsc->res.color = c0;
|
||||
else dsc->res.color = lv_color_mix(c0, c1, yr);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
310
EC600U_lvgl_lib/lvgl/src/draw/lv_img_buf.h
Normal file
310
EC600U_lvgl_lib/lvgl/src/draw/lv_img_buf.h
Normal file
@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @file lv_img_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_BUF_H
|
||||
#define LV_IMG_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../misc/lv_color.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*If image pixels contains alpha we need to know how much byte is a pixel*/
|
||||
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 2
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 3
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 4
|
||||
#endif
|
||||
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
|
||||
#define _LV_TRANSFORM_TRIGO_SHIFT 10
|
||||
#define _LV_ZOOM_INV_UPSCALE 5
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Image color format*/
|
||||
enum {
|
||||
LV_IMG_CF_UNKNOWN = 0,
|
||||
|
||||
LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/
|
||||
LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder
|
||||
function*/
|
||||
LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
|
||||
custom decoder function*/
|
||||
|
||||
LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/
|
||||
LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
|
||||
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
|
||||
will be transparent*/
|
||||
|
||||
LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/
|
||||
|
||||
LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
|
||||
LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
|
||||
|
||||
LV_IMG_CF_RESERVED_15, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_16, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_17, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_18, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_19, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_20, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_21, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_22, /**< Reserved for further use.*/
|
||||
LV_IMG_CF_RESERVED_23, /**< Reserved for further use.*/
|
||||
|
||||
LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format.*/
|
||||
LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format.*/
|
||||
};
|
||||
typedef uint8_t lv_img_cf_t;
|
||||
|
||||
|
||||
/**
|
||||
* The first 8 bit is very important to distinguish the different source types.
|
||||
* For more info see `lv_img_get_src_type()` in lv_img.c
|
||||
* On big endian systems the order is reversed so cf and always_zero must be at
|
||||
* the end of the struct.
|
||||
*/
|
||||
#if LV_BIG_ENDIAN_SYSTEM
|
||||
typedef struct {
|
||||
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
|
||||
|
||||
} lv_img_header_t;
|
||||
#else
|
||||
typedef struct {
|
||||
|
||||
uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
} lv_img_header_t;
|
||||
#endif
|
||||
|
||||
/** Image header it is compatible with
|
||||
* the result from image converter utility*/
|
||||
typedef struct {
|
||||
lv_img_header_t header; /**< A header describing the basics of the image*/
|
||||
uint32_t data_size; /**< Size of the image in bytes*/
|
||||
const uint8_t * data; /**< Pointer to the data of the image*/
|
||||
} lv_img_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
const void * src; /*image source (array of pixels)*/
|
||||
lv_coord_t src_w; /*width of the image source*/
|
||||
lv_coord_t src_h; /*height of the image source*/
|
||||
lv_coord_t pivot_x; /*pivot x*/
|
||||
lv_coord_t pivot_y; /*pivot y*/
|
||||
int16_t angle; /*angle to rotate*/
|
||||
uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/
|
||||
lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/
|
||||
lv_img_cf_t cf; /*color format of the image to rotate*/
|
||||
bool antialias;
|
||||
} cfg;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_opa_t opa;
|
||||
} res;
|
||||
|
||||
struct {
|
||||
lv_img_dsc_t img_dsc;
|
||||
int32_t pivot_x_256;
|
||||
int32_t pivot_y_256;
|
||||
int32_t sinma;
|
||||
int32_t cosma;
|
||||
|
||||
uint8_t chroma_keyed : 1;
|
||||
uint8_t has_alpha : 1;
|
||||
uint8_t native_color : 1;
|
||||
|
||||
uint32_t zoom_inv;
|
||||
|
||||
/*Runtime data*/
|
||||
lv_coord_t xs;
|
||||
lv_coord_t ys;
|
||||
lv_coord_t xs_int;
|
||||
lv_coord_t ys_int;
|
||||
uint32_t pxi;
|
||||
uint8_t px_size;
|
||||
} tmp;
|
||||
} lv_img_transform_dsc_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @param safe true: check out of bounds
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param safe true: check out of bounds
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
* @param safe true: check out of bounds
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
#if LV_DRAW_COMPLEX
|
||||
/**
|
||||
* Initialize a descriptor to rotate an image
|
||||
* @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
|
||||
*/
|
||||
void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Continue transformation by taking the neighbors into account
|
||||
* @param dsc pointer to the transformation descriptor
|
||||
*/
|
||||
bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Get which color and opa would come to a pixel if it were rotated
|
||||
* @param dsc a descriptor initialized by `lv_img_buf_rotate_init`
|
||||
* @param x the coordinate which color and opa should be get
|
||||
* @param y the coordinate which color and opa should be get
|
||||
* @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
|
||||
* @note the result is written back to `dsc->res_color` and `dsc->res_opa`
|
||||
*/
|
||||
bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Get the area of a rectangle if its rotated and scaled
|
||||
* @param res store the coordinates here
|
||||
* @param w width of the rectangle to transform
|
||||
* @param h height of the rectangle to transform
|
||||
* @param angle angle of rotation
|
||||
* @param zoom zoom, (256 no zoom)
|
||||
* @param pivot x,y pivot coordinates of rotation
|
||||
*/
|
||||
void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
|
||||
const lv_point_t * pivot);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_BUF_H*/
|
215
EC600U_lvgl_lib/lvgl/src/draw/lv_img_cache.c
Normal file
215
EC600U_lvgl_lib/lvgl/src/draw/lv_img_cache.c
Normal file
@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @file lv_img_cache.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "lv_img_cache.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "../hal/lv_hal_tick.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Decrement life with this value on every open*/
|
||||
#define LV_IMG_CACHE_AGING 1
|
||||
|
||||
/*Boost life by this factor (multiply time_to_open with this value)*/
|
||||
#define LV_IMG_CACHE_LIFE_GAIN 1
|
||||
|
||||
/*Don't let life to be greater than this limit because it would require a lot of time to
|
||||
* "die" from very high values*/
|
||||
#define LV_IMG_CACHE_LIFE_LIMIT 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static uint16_t entry_cnt;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
/*Is the image cached?*/
|
||||
_lv_img_cache_entry_t * cached_src = NULL;
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
if(entry_cnt == 0) {
|
||||
LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
/*Decrement all lifes. Make the entries older*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
|
||||
cache[i].life -= LV_IMG_CACHE_AGING;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(color.full == cache[i].dec_dsc.color.full &&
|
||||
frame_id == cache[i].dec_dsc.frame_id &&
|
||||
lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
/*If opened increment its life.
|
||||
*Image difficult to open should live longer to keep avoid frequent their recaching.
|
||||
*Therefore increase `life` with `time_to_open`*/
|
||||
cached_src = &cache[i];
|
||||
cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
|
||||
if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
|
||||
LV_LOG_TRACE("image source found in the cache");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*The image is not cached then cache it now*/
|
||||
if(cached_src) return cached_src;
|
||||
|
||||
/*Find an entry to reuse. Select the entry with the least life*/
|
||||
cached_src = &cache[0];
|
||||
for(i = 1; i < entry_cnt; i++) {
|
||||
if(cache[i].life < cached_src->life) {
|
||||
cached_src = &cache[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*Close the decoder to reuse if it was opened (has a valid source)*/
|
||||
if(cached_src->dec_dsc.src) {
|
||||
lv_img_decoder_close(&cached_src->dec_dsc);
|
||||
LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
|
||||
}
|
||||
else {
|
||||
LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
|
||||
}
|
||||
#else
|
||||
cached_src = &LV_GC_ROOT(_lv_img_cache_single);
|
||||
#endif
|
||||
/*Open the image and measure the time to open*/
|
||||
uint32_t t_start = lv_tick_get();
|
||||
lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color, frame_id);
|
||||
if(open_res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw cannot open the image resource");
|
||||
lv_memset_00(cached_src, sizeof(_lv_img_cache_entry_t));
|
||||
cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its us*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cached_src->life = 0;
|
||||
|
||||
/*If `time_to_open` was not set in the open function set it here*/
|
||||
if(cached_src->dec_dsc.time_to_open == 0) {
|
||||
cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
|
||||
}
|
||||
|
||||
if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
|
||||
|
||||
return cached_src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_entry_cnt)
|
||||
{
|
||||
#if LV_IMG_CACHE_DEF_SIZE == 0
|
||||
LV_UNUSED(new_entry_cnt);
|
||||
LV_LOG_WARN("Can't change cache size because it's disabled by LV_IMG_CACHE_DEF_SIZE = 0");
|
||||
#else
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) != NULL) {
|
||||
/*Clean the cache before free it*/
|
||||
lv_img_cache_invalidate_src(NULL);
|
||||
lv_mem_free(LV_GC_ROOT(_lv_img_cache_array));
|
||||
}
|
||||
|
||||
/*Reallocate the cache*/
|
||||
LV_GC_ROOT(_lv_img_cache_array) = lv_mem_alloc(sizeof(_lv_img_cache_entry_t) * new_entry_cnt);
|
||||
LV_ASSERT_MALLOC(LV_GC_ROOT(_lv_img_cache_array));
|
||||
if(LV_GC_ROOT(_lv_img_cache_array) == NULL) {
|
||||
entry_cnt = 0;
|
||||
return;
|
||||
}
|
||||
entry_cnt = new_entry_cnt;
|
||||
|
||||
/*Clean the cache*/
|
||||
lv_memset_00(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(_lv_img_cache_entry_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src)
|
||||
{
|
||||
LV_UNUSED(src);
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
_lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < entry_cnt; i++) {
|
||||
if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) {
|
||||
if(cache[i].dec_dsc.src != NULL) {
|
||||
lv_img_decoder_close(&cache[i].dec_dsc);
|
||||
}
|
||||
|
||||
lv_memset_00(&cache[i], sizeof(_lv_img_cache_entry_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_IMG_CACHE_DEF_SIZE
|
||||
static bool lv_img_cache_match(const void * src1, const void * src2)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src1);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE)
|
||||
return src1 == src2;
|
||||
if(src_type != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE)
|
||||
return false;
|
||||
return strcmp(src1, src2) == 0;
|
||||
}
|
||||
#endif
|
78
EC600U_lvgl_lib/lvgl/src/draw/lv_img_cache.h
Normal file
78
EC600U_lvgl_lib/lvgl/src/draw/lv_img_cache.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_img_cache.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_CACHE_H
|
||||
#define LV_IMG_CACHE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* When loading images from the network it can take a long time to download and decode the image.
|
||||
*
|
||||
* To avoid repeating this heavy load images can be cached.
|
||||
*/
|
||||
typedef struct {
|
||||
lv_img_decoder_dsc_t dec_dsc; /**< Image information*/
|
||||
|
||||
/** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used.
|
||||
* Decrement all lifes by one every in every ::lv_img_cache_open.
|
||||
* If life == 0 the entry can be reused*/
|
||||
int32_t life;
|
||||
} _lv_img_cache_entry_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Open an image using the image decoder interface and cache it.
|
||||
* The image will be left open meaning if the image decoder open callback allocated memory then it will remain.
|
||||
* The image is closed if a new image is opened and the new image takes its place in the cache.
|
||||
* @param src source of the image. Path to file or pointer to an `lv_img_dsc_t` variable
|
||||
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
|
||||
* @return pointer to the cache entry or NULL if can open the image
|
||||
*/
|
||||
_lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color, int32_t frame_id);
|
||||
|
||||
/**
|
||||
* Set the number of images to be cached.
|
||||
* More cached images mean more opened image at same time which might mean more memory usage.
|
||||
* E.g. if 20 PNG or JPG images are open in the RAM they consume memory while opened in the cache.
|
||||
* @param new_entry_cnt number of image to cache
|
||||
*/
|
||||
void lv_img_cache_set_size(uint16_t new_slot_num);
|
||||
|
||||
/**
|
||||
* Invalidate an image source in the cache.
|
||||
* Useful if the image source is updated therefore it needs to be cached again.
|
||||
* @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable.
|
||||
*/
|
||||
void lv_img_cache_invalidate_src(const void * src);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_CACHE_H*/
|
704
EC600U_lvgl_lib/lvgl/src/draw/lv_img_decoder.c
Normal file
704
EC600U_lvgl_lib/lvgl/src/draw/lv_img_decoder.c
Normal file
@ -0,0 +1,704 @@
|
||||
/**
|
||||
* @file lv_img_decoder.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img_decoder.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../draw/lv_draw_img.h"
|
||||
#include "../misc/lv_ll.h"
|
||||
#include "../misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define CF_BUILT_IN_FIRST LV_IMG_CF_TRUE_COLOR
|
||||
#define CF_BUILT_IN_LAST LV_IMG_CF_ALPHA_8BIT
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
lv_fs_file_t f;
|
||||
lv_color_t * palette;
|
||||
lv_opa_t * opa;
|
||||
} lv_img_decoder_built_in_data_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the image decoder module
|
||||
*/
|
||||
void _lv_img_decoder_init(void)
|
||||
{
|
||||
_lv_ll_init(&LV_GC_ROOT(_lv_img_decoder_ll), sizeof(lv_img_decoder_t));
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
|
||||
/*Create a decoder for the built in color format*/
|
||||
decoder = lv_img_decoder_create();
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_init: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_img_decoder_set_info_cb(decoder, lv_img_decoder_built_in_info);
|
||||
lv_img_decoder_set_open_cb(decoder, lv_img_decoder_built_in_open);
|
||||
lv_img_decoder_set_read_line_cb(decoder, lv_img_decoder_built_in_read_line);
|
||||
lv_img_decoder_set_close_cb(decoder, lv_img_decoder_built_in_close);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about an image.
|
||||
* Try the created image decoder one by one. Once one is able to get info that info will be used.
|
||||
* @param src the image source. E.g. file name or variable.
|
||||
* @param header the image info will be stored here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image
|
||||
*/
|
||||
lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header)
|
||||
{
|
||||
lv_memset_00(header, sizeof(lv_img_header_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
lv_img_decoder_t * d;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), d) {
|
||||
if(d->info_cb) {
|
||||
res = d->info_cb(d, src, header);
|
||||
if(res == LV_RES_OK) break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id)
|
||||
{
|
||||
lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t));
|
||||
|
||||
if(src == NULL) return LV_RES_INV;
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = src;
|
||||
if(img_dsc->data == NULL) return LV_RES_INV;
|
||||
}
|
||||
|
||||
dsc->color = color;
|
||||
dsc->src_type = src_type;
|
||||
dsc->frame_id = frame_id;
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
size_t fnlen = strlen(src);
|
||||
dsc->src = lv_mem_alloc(fnlen + 1);
|
||||
LV_ASSERT_MALLOC(dsc->src);
|
||||
if(dsc->src == NULL) {
|
||||
LV_LOG_WARN("lv_img_decoder_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
strcpy((char *)dsc->src, src);
|
||||
}
|
||||
else {
|
||||
dsc->src = src;
|
||||
}
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
lv_img_decoder_t * decoder;
|
||||
_LV_LL_READ(&LV_GC_ROOT(_lv_img_decoder_ll), decoder) {
|
||||
/*Info and Open callbacks are required*/
|
||||
if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue;
|
||||
|
||||
res = decoder->info_cb(decoder, src, &dsc->header);
|
||||
if(res != LV_RES_OK) continue;
|
||||
|
||||
dsc->decoder = decoder;
|
||||
res = decoder->open_cb(decoder, dsc);
|
||||
|
||||
/*Opened successfully. It is a good decoder to for this image source*/
|
||||
if(res == LV_RES_OK) return res;
|
||||
|
||||
/*Prepare for the next loop*/
|
||||
lv_memset_00(&dsc->header, sizeof(lv_img_header_t));
|
||||
|
||||
dsc->error_msg = NULL;
|
||||
dsc->img_data = NULL;
|
||||
dsc->user_data = NULL;
|
||||
dsc->time_to_open = 0;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE)
|
||||
lv_mem_free((void *)dsc->src);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line from an opened image
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
* @param x start X coordinate (from left)
|
||||
* @param y start Y coordinate (from top)
|
||||
* @param len number of pixels to read
|
||||
* @param buf store the data here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: an error occurred
|
||||
*/
|
||||
lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
lv_res_t res = LV_RES_INV;
|
||||
if(dsc->decoder->read_line_cb) res = dsc->decoder->read_line_cb(dsc->decoder, dsc, x, y, len, buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a decoding session
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
*/
|
||||
void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->decoder) {
|
||||
if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc);
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_mem_free((void *)dsc->src);
|
||||
dsc->src = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image decoder
|
||||
* @return pointer to the new image decoder
|
||||
*/
|
||||
lv_img_decoder_t * lv_img_decoder_create(void)
|
||||
{
|
||||
lv_img_decoder_t * decoder;
|
||||
decoder = _lv_ll_ins_head(&LV_GC_ROOT(_lv_img_decoder_ll));
|
||||
LV_ASSERT_MALLOC(decoder);
|
||||
if(decoder == NULL) return NULL;
|
||||
|
||||
lv_memset_00(decoder, sizeof(lv_img_decoder_t));
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an image decoder
|
||||
* @param decoder pointer to an image decoder
|
||||
*/
|
||||
void lv_img_decoder_delete(lv_img_decoder_t * decoder)
|
||||
{
|
||||
_lv_ll_remove(&LV_GC_ROOT(_lv_img_decoder_ll), decoder);
|
||||
lv_mem_free(decoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback to get information about the image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct)
|
||||
*/
|
||||
void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb)
|
||||
{
|
||||
decoder->info_cb = info_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback to open an image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param open_cb a function to open an image
|
||||
*/
|
||||
void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb)
|
||||
{
|
||||
decoder->open_cb = open_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback to a decoded line of an image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param read_line_cb a function to read a line of an image
|
||||
*/
|
||||
void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb)
|
||||
{
|
||||
decoder->read_line_cb = read_line_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback to close a decoding session. E.g. close files and free other resources.
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param close_cb a function to close a decoding session
|
||||
*/
|
||||
void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb)
|
||||
{
|
||||
decoder->close_cb = close_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about a built-in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol
|
||||
* @param header store the image data here
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src);
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
lv_img_cf_t cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
if(cf < CF_BUILT_IN_FIRST || cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
|
||||
header->w = ((lv_img_dsc_t *)src)->header.w;
|
||||
header->h = ((lv_img_dsc_t *)src)->header.h;
|
||||
header->cf = ((lv_img_dsc_t *)src)->header.cf;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
|
||||
if(res == LV_FS_RES_OK) {
|
||||
uint32_t rn;
|
||||
res = lv_fs_read(&f, header, sizeof(lv_img_header_t), &rn);
|
||||
lv_fs_close(&f);
|
||||
if(res != LV_FS_RES_OK || rn != sizeof(lv_img_header_t)) {
|
||||
LV_LOG_WARN("Image get info get read file header");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
if(header->cf < CF_BUILT_IN_FIRST || header->cf > CF_BUILT_IN_LAST) return LV_RES_INV;
|
||||
}
|
||||
else if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
/*The size depend on the font but it is unknown here. It should be handled outside of the
|
||||
*function*/
|
||||
header->w = 1;
|
||||
header->h = 1;
|
||||
/*Symbols always have transparent parts. Important because of cover check in the draw
|
||||
*function. The actual value doesn't matter because lv_draw_label will draw it*/
|
||||
header->cf = LV_IMG_CF_ALPHA_1BIT;
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Image get info found unknown src type");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a built in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it.
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
/*Open the file if it's a file*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Support only "*.bin" files*/
|
||||
if(strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RES_INV;
|
||||
|
||||
lv_fs_file_t f;
|
||||
lv_fs_res_t res = lv_fs_open(&f, dsc->src, LV_FS_MODE_RD);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder can't open the file");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/*If the file was open successfully save the file descriptor*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_fs_close(&f);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_memcpy_small(&user_data->f, &f, sizeof(f));
|
||||
}
|
||||
else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*The variables should have valid data*/
|
||||
if(((lv_img_dsc_t *)dsc->src)->data == NULL) {
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
lv_img_cf_t cf = dsc->header.cf;
|
||||
/*Process true color formats*/
|
||||
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
||||
*So simply give its pointer*/
|
||||
dsc->img_data = ((lv_img_dsc_t *)dsc->src)->data;
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else {
|
||||
/*If it's a file it need to be read line by line later*/
|
||||
return LV_RES_OK;
|
||||
}
|
||||
}
|
||||
/*Process indexed images. Build a palette*/
|
||||
else if(cf == LV_IMG_CF_INDEXED_1BIT || cf == LV_IMG_CF_INDEXED_2BIT || cf == LV_IMG_CF_INDEXED_4BIT ||
|
||||
cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(cf);
|
||||
uint32_t palette_size = 1 << px_size;
|
||||
|
||||
/*Allocate the palette*/
|
||||
if(dsc->user_data == NULL) {
|
||||
dsc->user_data = lv_mem_alloc(sizeof(lv_img_decoder_built_in_data_t));
|
||||
LV_ASSERT_MALLOC(dsc->user_data);
|
||||
if(dsc->user_data == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t));
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
user_data->palette = lv_mem_alloc(palette_size * sizeof(lv_color_t));
|
||||
LV_ASSERT_MALLOC(user_data->palette);
|
||||
user_data->opa = lv_mem_alloc(palette_size * sizeof(lv_opa_t));
|
||||
LV_ASSERT_MALLOC(user_data->opa);
|
||||
if(user_data->palette == NULL || user_data->opa == NULL) {
|
||||
LV_LOG_ERROR("img_decoder_built_in_open: out of memory");
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
/*Read the palette from file*/
|
||||
lv_fs_seek(&user_data->f, 4, LV_FS_SEEK_SET); /*Skip the header*/
|
||||
lv_color32_t cur_color;
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
lv_fs_read(&user_data->f, &cur_color, sizeof(lv_color32_t), NULL);
|
||||
user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue);
|
||||
user_data->opa[i] = cur_color.ch.alpha;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*The palette begins in the beginning of the image data. Just point to it.*/
|
||||
lv_color32_t * palette_p = (lv_color32_t *)((lv_img_dsc_t *)dsc->src)->data;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < palette_size; i++) {
|
||||
user_data->palette[i] = lv_color_make(palette_p[i].ch.red, palette_p[i].ch.green, palette_p[i].ch.blue);
|
||||
user_data->opa[i] = palette_p[i].ch.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
/*Alpha indexed images.*/
|
||||
else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT ||
|
||||
cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
return LV_RES_OK; /*Nothing to process*/
|
||||
}
|
||||
/*Unknown format. Can't decode it.*/
|
||||
else {
|
||||
/*Free the potentially allocated memories*/
|
||||
lv_img_decoder_built_in_close(decoder, dsc);
|
||||
|
||||
LV_LOG_WARN("Image decoder open: unknown color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* Required only if the "open" function can't return with the whole decoded pixel array.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
* @param x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
|
||||
lv_coord_t y, lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
(void)decoder; /*Unused*/
|
||||
|
||||
lv_res_t res = LV_RES_INV;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
/*For TRUE_COLOR images read line required only for files.
|
||||
*For variables the image data was returned in `open`*/
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
res = lv_img_decoder_built_in_line_true_color(dsc, x, y, len, buf);
|
||||
}
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_alpha(dsc, x, y, len, buf);
|
||||
}
|
||||
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT || dsc->header.cf == LV_IMG_CF_INDEXED_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_INDEXED_4BIT || dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
res = lv_img_decoder_built_in_line_indexed(dsc, x, y, len, buf);
|
||||
}
|
||||
else {
|
||||
LV_LOG_WARN("Built-in image decoder read not supports the color format");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the pending decoding. Free resources etc.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
*/
|
||||
void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
|
||||
{
|
||||
(void)decoder; /*Unused*/
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
if(user_data) {
|
||||
if(dsc->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_fs_close(&user_data->f);
|
||||
}
|
||||
if(user_data->palette) lv_mem_free(user_data->palette);
|
||||
if(user_data->opa) lv_mem_free(user_data->opa);
|
||||
|
||||
lv_mem_free(user_data);
|
||||
dsc->user_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_fs_res_t res;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
|
||||
uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3;
|
||||
pos += 4; /*Skip the header*/
|
||||
res = lv_fs_seek(&user_data->f, pos, LV_FS_SEEK_SET);
|
||||
if(res != LV_FS_RES_OK) {
|
||||
LV_LOG_WARN("Built-in image decoder seek failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
uint32_t btr = len * (px_size >> 3);
|
||||
uint32_t br = 0;
|
||||
res = lv_fs_read(&user_data->f, buf, btr, &br);
|
||||
if(res != LV_FS_RES_OK || btr != br) {
|
||||
LV_LOG_WARN("Built-in image decoder read failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
const lv_opa_t alpha1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/
|
||||
const lv_opa_t alpha2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
const lv_opa_t alpha4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
/*Simply fill the buffer with the color. Later only the alpha value will be modified.*/
|
||||
lv_color_t bg_color = dsc->color;
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = bg_color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (bg_color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = bg_color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
const lv_opa_t * opa_table = NULL;
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
uint32_t ofs = 0;
|
||||
int8_t pos = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_ALPHA_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
pos = 7 - (x & 0x7);
|
||||
opa_table = alpha1_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
opa_table = alpha2_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
opa_table = alpha4_opa_table;
|
||||
break;
|
||||
case LV_IMG_CF_ALPHA_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] =
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_8BIT ? val_act : opa_table[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y,
|
||||
lv_coord_t len, uint8_t * buf)
|
||||
{
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
int8_t pos = 0;
|
||||
uint32_t ofs = 0;
|
||||
switch(dsc->header.cf) {
|
||||
case LV_IMG_CF_INDEXED_1BIT:
|
||||
w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/
|
||||
ofs += w * y + (x >> 3); /*First pixel*/
|
||||
ofs += 8; /*Skip the palette*/
|
||||
pos = 7 - (x & 0x7);
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_2BIT:
|
||||
w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 2); /*First pixel*/
|
||||
ofs += 16; /*Skip the palette*/
|
||||
pos = 6 - (x & 0x3) * 2;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_4BIT:
|
||||
w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/
|
||||
ofs += w * y + (x >> 1); /*First pixel*/
|
||||
ofs += 64; /*Skip the palette*/
|
||||
pos = 4 - (x & 0x1) * 4;
|
||||
break;
|
||||
case LV_IMG_CF_INDEXED_8BIT:
|
||||
w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/
|
||||
ofs += w * y + x; /*First pixel*/
|
||||
ofs += 1024; /*Skip the palette*/
|
||||
pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
|
||||
uint8_t * fs_buf = lv_mem_buf_get(w);
|
||||
if(fs_buf == NULL) return LV_RES_INV;
|
||||
const uint8_t * data_tmp = NULL;
|
||||
if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
const lv_img_dsc_t * img_dsc = dsc->src;
|
||||
data_tmp = img_dsc->data + ofs;
|
||||
}
|
||||
else {
|
||||
lv_fs_seek(&user_data->f, ofs + 4, LV_FS_SEEK_SET); /*+4 to skip the header*/
|
||||
lv_fs_read(&user_data->f, fs_buf, w, NULL);
|
||||
data_tmp = fs_buf;
|
||||
}
|
||||
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < len; i++) {
|
||||
uint8_t val_act = (*data_tmp >> pos) & mask;
|
||||
|
||||
lv_color_t color = user_data->palette[val_act];
|
||||
#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
/*Because of Alpha byte 16 bit color can start on odd address which can cause crash*/
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE] = color.full & 0xFF;
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + 1] = (color.full >> 8) & 0xFF;
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
*((uint32_t *)&buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE]) = color.full;
|
||||
#else
|
||||
#error "Invalid LV_COLOR_DEPTH. Check it in lv_conf.h"
|
||||
#endif
|
||||
buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = user_data->opa[val_act];
|
||||
|
||||
pos -= px_size;
|
||||
if(pos < 0) {
|
||||
pos = 8 - px_size;
|
||||
data_tmp++;
|
||||
}
|
||||
}
|
||||
lv_mem_buf_release(fs_buf);
|
||||
return LV_RES_OK;
|
||||
}
|
274
EC600U_lvgl_lib/lvgl/src/draw/lv_img_decoder.h
Normal file
274
EC600U_lvgl_lib/lvgl/src/draw/lv_img_decoder.h
Normal file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @file lv_img_decoder.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_DECODER_H
|
||||
#define LV_IMG_DECODER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "../misc/lv_fs.h"
|
||||
#include "../misc/lv_types.h"
|
||||
#include "../misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Source of image.*/
|
||||
enum {
|
||||
LV_IMG_SRC_VARIABLE, /** Binary/C variable*/
|
||||
LV_IMG_SRC_FILE, /** File in filesystem*/
|
||||
LV_IMG_SRC_SYMBOL, /** Symbol (@ref lv_symbol_def.h)*/
|
||||
LV_IMG_SRC_UNKNOWN, /** Unknown source*/
|
||||
};
|
||||
|
||||
typedef uint8_t lv_img_src_t;
|
||||
|
||||
/*Decoder function definitions*/
|
||||
struct _lv_img_decoder_dsc_t;
|
||||
struct _lv_img_decoder_t;
|
||||
|
||||
/**
|
||||
* Get info from an image and store in the `header`
|
||||
* @param src the image source. Can be a pointer to a C array or a file name (Use
|
||||
* `lv_img_src_get_type` to determine the type)
|
||||
* @param header store the info here
|
||||
* @return LV_RES_OK: info written correctly; LV_RES_INV: failed
|
||||
*/
|
||||
typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder_t * decoder, const void * src,
|
||||
lv_img_header_t * header);
|
||||
|
||||
/**
|
||||
* Open an image for decoding. Prepare it as it is required to read it later
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it.
|
||||
*/
|
||||
typedef lv_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* Required only if the "open" function can't return with the whole decoded pixel array.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
* @param x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
typedef lv_res_t (*lv_img_decoder_read_line_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc,
|
||||
lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**
|
||||
* Close the pending decoding. Free resources etc.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
*/
|
||||
typedef void (*lv_img_decoder_close_f_t)(struct _lv_img_decoder_t * decoder, struct _lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
|
||||
typedef struct _lv_img_decoder_t {
|
||||
lv_img_decoder_info_f_t info_cb;
|
||||
lv_img_decoder_open_f_t open_cb;
|
||||
lv_img_decoder_read_line_f_t read_line_cb;
|
||||
lv_img_decoder_close_f_t close_cb;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data;
|
||||
#endif
|
||||
} lv_img_decoder_t;
|
||||
|
||||
|
||||
/**Describe an image decoding session. Stores data about the decoding*/
|
||||
typedef struct _lv_img_decoder_dsc_t {
|
||||
/**The decoder which was able to open the image source*/
|
||||
lv_img_decoder_t * decoder;
|
||||
|
||||
/**The image source. A file path like "S:my_img.png" or pointer to an `lv_img_dsc_t` variable*/
|
||||
const void * src;
|
||||
|
||||
/**Color to draw the image. USed when the image has alpha channel only*/
|
||||
lv_color_t color;
|
||||
|
||||
/**Frame of the image, using with animated images*/
|
||||
int32_t frame_id;
|
||||
|
||||
/**Type of the source: file or variable. Can be set in `open` function if required*/
|
||||
lv_img_src_t src_type;
|
||||
|
||||
/**Info about the opened image: color format, size, etc. MUST be set in `open` function*/
|
||||
lv_img_header_t header;
|
||||
|
||||
/** Pointer to a buffer where the image's data (pixels) are stored in a decoded, plain format.
|
||||
* MUST be set in `open` function*/
|
||||
const uint8_t * img_data;
|
||||
|
||||
/** How much time did it take to open the image. [ms]
|
||||
* If not set `lv_img_cache` will measure and set the time to open*/
|
||||
uint32_t time_to_open;
|
||||
|
||||
/**A text to display instead of the image when the image can't be opened.
|
||||
* Can be set in `open` function or set NULL.*/
|
||||
const char * error_msg;
|
||||
|
||||
/**Store any custom data here is required*/
|
||||
void * user_data;
|
||||
} lv_img_decoder_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the image decoder module
|
||||
*/
|
||||
void _lv_img_decoder_init(void);
|
||||
|
||||
/**
|
||||
* Get information about an image.
|
||||
* Try the created image decoder one by one. Once one is able to get info that info will be used.
|
||||
* @param src the image source. Can be
|
||||
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`)
|
||||
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
|
||||
* 3) Symbol: E.g. `LV_SYMBOL_OK`
|
||||
* @param header the image info will be stored here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: wasn't able to get info about the image
|
||||
*/
|
||||
lv_res_t lv_img_decoder_get_info(const void * src, lv_img_header_t * header);
|
||||
|
||||
/**
|
||||
* Open an image.
|
||||
* Try the created image decoder one by one. Once one is able to open the image that decoder is save in `dsc`
|
||||
* @param dsc describe a decoding session. Simply a pointer to an `lv_img_decoder_dsc_t` variable.
|
||||
* @param src the image source. Can be
|
||||
* 1) File name: E.g. "S:folder/img1.png" (The drivers needs to registered via `lv_fs_add_drv()`)
|
||||
* 2) Variable: Pointer to an `lv_img_dsc_t` variable
|
||||
* 3) Symbol: E.g. `LV_SYMBOL_OK`
|
||||
* @param color The color of the image with `LV_IMG_CF_ALPHA_...`
|
||||
* @param frame_id the index of the frame. Used only with animated images, set 0 for normal images
|
||||
* @return LV_RES_OK: opened the image. `dsc->img_data` and `dsc->header` are set.
|
||||
* LV_RES_INV: none of the registered image decoders were able to open the image.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id);
|
||||
|
||||
/**
|
||||
* Read a line from an opened image
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
* @param x start X coordinate (from left)
|
||||
* @param y start Y coordinate (from top)
|
||||
* @param len number of pixels to read
|
||||
* @param buf store the data here
|
||||
* @return LV_RES_OK: success; LV_RES_INV: an error occurred
|
||||
*/
|
||||
lv_res_t lv_img_decoder_read_line(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len,
|
||||
uint8_t * buf);
|
||||
|
||||
/**
|
||||
* Close a decoding session
|
||||
* @param dsc pointer to `lv_img_decoder_dsc_t` used in `lv_img_decoder_open`
|
||||
*/
|
||||
void lv_img_decoder_close(lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Create a new image decoder
|
||||
* @return pointer to the new image decoder
|
||||
*/
|
||||
lv_img_decoder_t * lv_img_decoder_create(void);
|
||||
|
||||
/**
|
||||
* Delete an image decoder
|
||||
* @param decoder pointer to an image decoder
|
||||
*/
|
||||
void lv_img_decoder_delete(lv_img_decoder_t * decoder);
|
||||
|
||||
/**
|
||||
* Set a callback to get information about the image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param info_cb a function to collect info about an image (fill an `lv_img_header_t` struct)
|
||||
*/
|
||||
void lv_img_decoder_set_info_cb(lv_img_decoder_t * decoder, lv_img_decoder_info_f_t info_cb);
|
||||
|
||||
/**
|
||||
* Set a callback to open an image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param open_cb a function to open an image
|
||||
*/
|
||||
void lv_img_decoder_set_open_cb(lv_img_decoder_t * decoder, lv_img_decoder_open_f_t open_cb);
|
||||
|
||||
/**
|
||||
* Set a callback to a decoded line of an image
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param read_line_cb a function to read a line of an image
|
||||
*/
|
||||
void lv_img_decoder_set_read_line_cb(lv_img_decoder_t * decoder, lv_img_decoder_read_line_f_t read_line_cb);
|
||||
|
||||
/**
|
||||
* Set a callback to close a decoding session. E.g. close files and free other resources.
|
||||
* @param decoder pointer to an image decoder
|
||||
* @param close_cb a function to close a decoding session
|
||||
*/
|
||||
void lv_img_decoder_set_close_cb(lv_img_decoder_t * decoder, lv_img_decoder_close_f_t close_cb);
|
||||
|
||||
/**
|
||||
* Get info about a built-in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param src the image source: pointer to an `lv_img_dsc_t` variable, a file path or a symbol
|
||||
* @param header store the image data here
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
|
||||
|
||||
/**
|
||||
* Open a built in image
|
||||
* @param decoder the decoder where this function belongs
|
||||
* @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it.
|
||||
* @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error.
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**
|
||||
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
|
||||
* Required only if the "open" function can't return with the whole decoded pixel array.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
* @param x start x coordinate
|
||||
* @param y start y coordinate
|
||||
* @param len number of pixels to decode
|
||||
* @param buf a buffer to store the decoded pixels
|
||||
* @return LV_RES_OK: ok; LV_RES_INV: failed
|
||||
*/
|
||||
lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
|
||||
lv_coord_t y, lv_coord_t len, uint8_t * buf);
|
||||
|
||||
/**
|
||||
* Close the pending decoding. Free resources etc.
|
||||
* @param decoder pointer to the decoder the function associated with
|
||||
* @param dsc pointer to decoder descriptor
|
||||
*/
|
||||
void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_DECODER_H*/
|
30
EC600U_lvgl_lib/lvgl/src/extra/README.md
Normal file
30
EC600U_lvgl_lib/lvgl/src/extra/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Extra components
|
||||
|
||||
This directory contains extra (optional) components to lvgl.
|
||||
It's a good place for contributions as there are less strict expectations about the completeness and flexibility of the components here.
|
||||
|
||||
In other words, if you have created a complex widget from other widgets, or modified an existing widget with special events, styles or animations, or have a new feature that could work as a plugin to lvgl feel free to the share it here.
|
||||
|
||||
## How to contribute
|
||||
- Create a [Pull request](https://docs.lvgl.io/8.0/CONTRIBUTING.html#pull-request) with your new content
|
||||
- Please and follow the [Coding style](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md) of LVGL
|
||||
- Add setter/getter functions in pair
|
||||
- Update [lv_conf_template.h](https://github.com/lvgl/lvgl/blob/master/lv_conf_template.h)
|
||||
- Add description in the [docs](https://github.com/lvgl/lvgl/tree/master/docs)
|
||||
- Add [examples](https://github.com/lvgl/lvgl/tree/master/examples)
|
||||
- Update the [changelog](https://github.com/lvgl/lvgl/tree/master/docs/CHANGELOG.md)
|
||||
- Add yourself to the [Contributors](#contributors) section below.
|
||||
|
||||
## Ideas
|
||||
Here some ideas as inspiration feel free to contribute with ideas too.
|
||||
- New [Calendar headers](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/calendar)
|
||||
- Color picker with RGB and or HSV bars
|
||||
- Ruler, horizontal or vertical with major and minor ticks and labels
|
||||
- New [List items types](https://github.com/lvgl/lvgl/tree/master/src/extra/widgets/list)
|
||||
- [Preloaders](https://www.google.com/search?q=preloader&sxsrf=ALeKk01ddA4YB0WEgLLN1bZNSm8YER7pkg:1623080551559&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiwoN6d7oXxAhVuw4sKHVedBB4Q_AUoAXoECAEQAw&biw=952&bih=940)
|
||||
- Drop-down list with a container to which an content can be added
|
||||
- 9 patch button: Similar to [lv_imgbtn](https://docs.lvgl.io/8.0/widgets/extra/imgbtn.html) but 9 images for 4 corner, 4 sides and the center
|
||||
|
||||
## Contributors
|
||||
- lv_animimg: @ZhaoQiang-b45475
|
||||
- lv_span: @guoweilkd
|
1
EC600U_lvgl_lib/lvgl/src/extra/extra.mk
Normal file
1
EC600U_lvgl_lib/lvgl/src/extra/extra.mk
Normal file
@ -0,0 +1 @@
|
||||
CSRCS += $(shell find -L $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra -name \*.c)
|
595
EC600U_lvgl_lib/lvgl/src/extra/layouts/flex/lv_flex.c
Normal file
595
EC600U_lvgl_lib/lvgl/src/extra/layouts/flex/lv_flex.c
Normal file
@ -0,0 +1,595 @@
|
||||
/**
|
||||
* @file lv_flex.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_layouts.h"
|
||||
|
||||
#if LV_USE_FLEX
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_flex_align_t main_place;
|
||||
lv_flex_align_t cross_place;
|
||||
lv_flex_align_t track_place;
|
||||
uint8_t row : 1;
|
||||
uint8_t wrap : 1;
|
||||
uint8_t rev : 1;
|
||||
} flex_t;
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t * item;
|
||||
lv_coord_t min_size;
|
||||
lv_coord_t max_size;
|
||||
lv_coord_t final_size;
|
||||
uint32_t grow_value;
|
||||
uint32_t clamped : 1;
|
||||
} grow_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t track_cross_size;
|
||||
lv_coord_t track_main_size; /*For all items*/
|
||||
lv_coord_t track_fix_main_size; /*For non grow items*/
|
||||
uint32_t item_cnt;
|
||||
grow_dsc_t * grow_dsc;
|
||||
uint32_t grow_item_cnt;
|
||||
uint32_t grow_dsc_calc : 1;
|
||||
} track_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void flex_update(lv_obj_t * cont, void * user_data);
|
||||
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t item_gap,
|
||||
lv_coord_t max_main_size, track_t * t);
|
||||
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
|
||||
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t);
|
||||
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
|
||||
lv_coord_t * start_pos, lv_coord_t * gap);
|
||||
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id);
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
uint32_t LV_LAYOUT_FLEX;
|
||||
lv_style_prop_t LV_STYLE_FLEX_FLOW;
|
||||
lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
|
||||
lv_style_prop_t LV_STYLE_FLEX_GROW;
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
void lv_flex_init(void)
|
||||
{
|
||||
LV_LAYOUT_FLEX = lv_layout_register(flex_update, NULL);
|
||||
|
||||
LV_STYLE_FLEX_FLOW = lv_style_register_prop();
|
||||
LV_STYLE_FLEX_MAIN_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_FLEX_CROSS_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_FLEX_TRACK_PLACE = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow)
|
||||
{
|
||||
lv_obj_set_style_flex_flow(obj, flow, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
|
||||
lv_flex_align_t track_place)
|
||||
{
|
||||
lv_obj_set_style_flex_main_place(obj, main_place, 0);
|
||||
lv_obj_set_style_flex_cross_place(obj, cross_place, 0);
|
||||
lv_obj_set_style_flex_track_place(obj, track_place, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow)
|
||||
{
|
||||
lv_obj_set_style_flex_grow(obj, grow, 0);
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_FLOW, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_MAIN_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_CROSS_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_TRACK_PLACE, v);
|
||||
}
|
||||
|
||||
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_FLEX_GROW, v);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_FLOW, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_MAIN_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_CROSS_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_TRACK_PLACE, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flex_update(lv_obj_t * cont, void * user_data)
|
||||
{
|
||||
LV_LOG_INFO("update %p container", (void *)cont);
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
flex_t f;
|
||||
lv_flex_flow_t flow = lv_obj_get_style_flex_flow(cont, LV_PART_MAIN);
|
||||
f.row = flow & _LV_FLEX_COLUMN ? 0 : 1;
|
||||
f.wrap = flow & _LV_FLEX_WRAP ? 1 : 0;
|
||||
f.rev = flow & _LV_FLEX_REVERSE ? 1 : 0;
|
||||
f.main_place = lv_obj_get_style_flex_main_place(cont, LV_PART_MAIN);
|
||||
f.cross_place = lv_obj_get_style_flex_cross_place(cont, LV_PART_MAIN);
|
||||
f.track_place = lv_obj_get_style_flex_track_place(cont, LV_PART_MAIN);
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
lv_coord_t track_gap = !f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
|
||||
LV_PART_MAIN);
|
||||
lv_coord_t item_gap = f.row ? lv_obj_get_style_pad_column(cont, LV_PART_MAIN) : lv_obj_get_style_pad_row(cont,
|
||||
LV_PART_MAIN);
|
||||
lv_coord_t max_main_size = (f.row ? lv_obj_get_content_width(cont) : lv_obj_get_content_height(cont));
|
||||
lv_coord_t border_width = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t abs_y = cont->coords.y1 + lv_obj_get_style_pad_top(cont,
|
||||
LV_PART_MAIN) + border_width - lv_obj_get_scroll_y(cont);
|
||||
lv_coord_t abs_x = cont->coords.x1 + lv_obj_get_style_pad_left(cont,
|
||||
LV_PART_MAIN) + border_width - lv_obj_get_scroll_x(cont);
|
||||
|
||||
lv_flex_align_t track_cross_place = f.track_place;
|
||||
lv_coord_t * cross_pos = (f.row ? &abs_y : &abs_x);
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
|
||||
/*Content sized objects should squeezed the gap between the children, therefore any alignment will look like `START`*/
|
||||
if((f.row && h_set == LV_SIZE_CONTENT && cont->h_layout == 0) ||
|
||||
(!f.row && w_set == LV_SIZE_CONTENT && cont->w_layout == 0)) {
|
||||
track_cross_place = LV_FLEX_ALIGN_START;
|
||||
}
|
||||
|
||||
if(rtl && !f.row) {
|
||||
if(track_cross_place == LV_FLEX_ALIGN_START) track_cross_place = LV_FLEX_ALIGN_END;
|
||||
else if(track_cross_place == LV_FLEX_ALIGN_END) track_cross_place = LV_FLEX_ALIGN_START;
|
||||
}
|
||||
|
||||
lv_coord_t total_track_cross_size = 0;
|
||||
lv_coord_t gap = 0;
|
||||
uint32_t track_cnt = 0;
|
||||
int32_t track_first_item;
|
||||
int32_t next_track_first_item;
|
||||
|
||||
if(track_cross_place != LV_FLEX_ALIGN_START) {
|
||||
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
|
||||
track_t t;
|
||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||
/*Search the first item of the next row*/
|
||||
t.grow_dsc_calc = 0;
|
||||
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
||||
total_track_cross_size += t.track_cross_size + track_gap;
|
||||
track_cnt++;
|
||||
track_first_item = next_track_first_item;
|
||||
}
|
||||
|
||||
if(track_cnt) total_track_cross_size -= track_gap; /*No gap after the last track*/
|
||||
|
||||
/*Place the tracks to get the start position*/
|
||||
lv_coord_t max_cross_size = (f.row ? lv_obj_get_content_height(cont) : lv_obj_get_content_width(cont));
|
||||
place_content(track_cross_place, max_cross_size, total_track_cross_size, track_cnt, cross_pos, &gap);
|
||||
}
|
||||
|
||||
track_first_item = f.rev ? cont->spec_attr->child_cnt - 1 : 0;
|
||||
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos += total_track_cross_size;
|
||||
}
|
||||
|
||||
while(track_first_item < (int32_t)cont->spec_attr->child_cnt && track_first_item >= 0) {
|
||||
track_t t;
|
||||
t.grow_dsc_calc = 1;
|
||||
/*Search the first item of the next row*/
|
||||
next_track_first_item = find_track_end(cont, &f, track_first_item, max_main_size, item_gap, &t);
|
||||
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos -= t.track_cross_size;
|
||||
}
|
||||
children_repos(cont, &f, track_first_item, next_track_first_item, abs_x, abs_y, max_main_size, item_gap, &t);
|
||||
track_first_item = next_track_first_item;
|
||||
lv_mem_buf_release(t.grow_dsc);
|
||||
t.grow_dsc = NULL;
|
||||
if(rtl && !f.row) {
|
||||
*cross_pos -= gap + track_gap;
|
||||
}
|
||||
else {
|
||||
*cross_pos += t.track_cross_size + gap + track_gap;
|
||||
}
|
||||
}
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
|
||||
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
|
||||
lv_obj_refr_size(cont);
|
||||
}
|
||||
|
||||
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
|
||||
|
||||
LV_TRACE_LAYOUT("finished");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the last item of a track
|
||||
*/
|
||||
static int32_t find_track_end(lv_obj_t * cont, flex_t * f, int32_t item_start_id, lv_coord_t max_main_size,
|
||||
lv_coord_t item_gap, track_t * t)
|
||||
{
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
|
||||
/*Can't wrap if the size if auto (i.e. the size depends on the children)*/
|
||||
if(f->wrap && ((f->row && w_set == LV_SIZE_CONTENT) || (!f->row && h_set == LV_SIZE_CONTENT))) {
|
||||
f->wrap = false;
|
||||
}
|
||||
lv_coord_t(*get_main_size)(const lv_obj_t *) = (f->row ? lv_obj_get_width : lv_obj_get_height);
|
||||
lv_coord_t(*get_cross_size)(const lv_obj_t *) = (!f->row ? lv_obj_get_width : lv_obj_get_height);
|
||||
|
||||
t->track_main_size = 0;
|
||||
t->track_fix_main_size = 0;
|
||||
t->grow_item_cnt = 0;
|
||||
t->track_cross_size = 0;
|
||||
t->item_cnt = 0;
|
||||
t->grow_dsc = NULL;
|
||||
|
||||
int32_t item_id = item_start_id;
|
||||
|
||||
lv_obj_t * item = lv_obj_get_child(cont, item_id);
|
||||
while(item) {
|
||||
if(item_id != item_start_id && lv_obj_has_flag(item, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK)) break;
|
||||
|
||||
if(!lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
|
||||
uint8_t grow_value = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||
if(grow_value) {
|
||||
t->grow_item_cnt++;
|
||||
t->track_fix_main_size += item_gap;
|
||||
if(t->grow_dsc_calc) {
|
||||
grow_dsc_t * new_dsc = lv_mem_buf_get(sizeof(grow_dsc_t) * (t->grow_item_cnt));
|
||||
LV_ASSERT_MALLOC(new_dsc);
|
||||
if(new_dsc == NULL) return item_id;
|
||||
|
||||
if(t->grow_dsc) {
|
||||
lv_memcpy(new_dsc, t->grow_dsc, sizeof(grow_dsc_t) * (t->grow_item_cnt - 1));
|
||||
lv_mem_buf_release(t->grow_dsc);
|
||||
}
|
||||
new_dsc[t->grow_item_cnt - 1].item = item;
|
||||
new_dsc[t->grow_item_cnt - 1].min_size = f->row ? lv_obj_get_style_min_width(item,
|
||||
LV_PART_MAIN) : lv_obj_get_style_min_height(item, LV_PART_MAIN);
|
||||
new_dsc[t->grow_item_cnt - 1].max_size = f->row ? lv_obj_get_style_max_width(item,
|
||||
LV_PART_MAIN) : lv_obj_get_style_max_height(item, LV_PART_MAIN);
|
||||
new_dsc[t->grow_item_cnt - 1].grow_value = grow_value;
|
||||
new_dsc[t->grow_item_cnt - 1].clamped = 0;
|
||||
t->grow_dsc = new_dsc;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_coord_t item_size = get_main_size(item);
|
||||
if(f->wrap && t->track_fix_main_size + item_size > max_main_size) break;
|
||||
t->track_fix_main_size += item_size + item_gap;
|
||||
}
|
||||
|
||||
|
||||
t->track_cross_size = LV_MAX(get_cross_size(item), t->track_cross_size);
|
||||
t->item_cnt++;
|
||||
}
|
||||
|
||||
item_id += f->rev ? -1 : +1;
|
||||
if(item_id < 0) break;
|
||||
item = lv_obj_get_child(cont, item_id);
|
||||
}
|
||||
|
||||
if(t->track_fix_main_size > 0) t->track_fix_main_size -= item_gap; /*There is no gap after the last item*/
|
||||
|
||||
/*If there is at least one "grow item" the track takes the full space*/
|
||||
t->track_main_size = t->grow_item_cnt ? max_main_size : t->track_fix_main_size;
|
||||
|
||||
/*Have at least one item in a row*/
|
||||
if(item && item_id == item_start_id) {
|
||||
item = cont->spec_attr->children[item_id];
|
||||
get_next_item(cont, f->rev, &item_id);
|
||||
if(item) {
|
||||
t->track_cross_size = get_cross_size(item);
|
||||
t->track_main_size = get_main_size(item);
|
||||
t->item_cnt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return item_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Position the children in the same track
|
||||
*/
|
||||
static void children_repos(lv_obj_t * cont, flex_t * f, int32_t item_first_id, int32_t item_last_id, lv_coord_t abs_x,
|
||||
lv_coord_t abs_y, lv_coord_t max_main_size, lv_coord_t item_gap, track_t * t)
|
||||
{
|
||||
void (*area_set_main_size)(lv_area_t *, lv_coord_t) = (f->row ? lv_area_set_width : lv_area_set_height);
|
||||
lv_coord_t (*area_get_main_size)(const lv_area_t *) = (f->row ? lv_area_get_width : lv_area_get_height);
|
||||
lv_coord_t (*area_get_cross_size)(const lv_area_t *) = (!f->row ? lv_area_get_width : lv_area_get_height);
|
||||
|
||||
/*Calculate the size of grow items first*/
|
||||
uint32_t i;
|
||||
bool grow_reiterate = true;
|
||||
while(grow_reiterate) {
|
||||
grow_reiterate = false;
|
||||
lv_coord_t grow_value_sum = 0;
|
||||
lv_coord_t grow_max_size = t->track_main_size - t->track_fix_main_size;
|
||||
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||
if(t->grow_dsc[i].clamped == 0) {
|
||||
grow_value_sum += t->grow_dsc[i].grow_value;
|
||||
}
|
||||
else {
|
||||
grow_max_size -= t->grow_dsc[i].final_size;
|
||||
}
|
||||
}
|
||||
lv_coord_t grow_unit;
|
||||
|
||||
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||
if(t->grow_dsc[i].clamped == 0) {
|
||||
grow_unit = grow_max_size / grow_value_sum;
|
||||
lv_coord_t size = grow_unit * t->grow_dsc[i].grow_value;
|
||||
lv_coord_t size_clamp = LV_CLAMP(t->grow_dsc[i].min_size, size, t->grow_dsc[i].max_size);
|
||||
|
||||
if(size_clamp != size) {
|
||||
t->grow_dsc[i].clamped = 1;
|
||||
grow_reiterate = true;
|
||||
}
|
||||
t->grow_dsc[i].final_size = size_clamp;
|
||||
grow_value_sum -= t->grow_dsc[i].grow_value;
|
||||
grow_max_size -= t->grow_dsc[i].final_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool rtl = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t main_pos = 0;
|
||||
|
||||
lv_coord_t place_gap = 0;
|
||||
place_content(f->main_place, max_main_size, t->track_main_size, t->item_cnt, &main_pos, &place_gap);
|
||||
if(f->row && rtl) main_pos += lv_obj_get_content_width(cont);
|
||||
|
||||
lv_obj_t * item = lv_obj_get_child(cont, item_first_id);
|
||||
/*Reposition the children*/
|
||||
while(item && item_first_id != item_last_id) {
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) {
|
||||
item = get_next_item(cont, f->rev, &item_first_id);
|
||||
continue;
|
||||
}
|
||||
lv_coord_t grow_size = lv_obj_get_style_flex_grow(item, LV_PART_MAIN);
|
||||
if(grow_size) {
|
||||
lv_coord_t s = 0;
|
||||
for(i = 0; i < t->grow_item_cnt; i++) {
|
||||
if(t->grow_dsc[i].item == item) {
|
||||
s = t->grow_dsc[i].final_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(f->row) item->w_layout = 1;
|
||||
else item->h_layout = 1;
|
||||
|
||||
if(s != area_get_main_size(&item->coords)) {
|
||||
lv_obj_invalidate(item);
|
||||
|
||||
lv_area_t old_coords;
|
||||
lv_area_copy(&old_coords, &item->coords);
|
||||
area_set_main_size(&item->coords, s);
|
||||
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
|
||||
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
|
||||
lv_obj_invalidate(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
item->w_layout = 0;
|
||||
item->h_layout = 0;
|
||||
}
|
||||
|
||||
lv_coord_t cross_pos = 0;
|
||||
switch(f->cross_place) {
|
||||
case LV_FLEX_ALIGN_CENTER:
|
||||
/*Round up the cross size to avoid rounding error when dividing by 2
|
||||
*The issue comes up e,g, with column direction with center cross direction if an element's width changes*/
|
||||
cross_pos = (((t->track_cross_size + 1) & (~1)) - area_get_cross_size(&item->coords)) / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_END:
|
||||
cross_pos = t->track_cross_size - area_get_cross_size(&item->coords);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(f->row && rtl) main_pos -= area_get_main_size(&item->coords);
|
||||
|
||||
|
||||
/*Handle percentage value of translate*/
|
||||
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
|
||||
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_width(item);
|
||||
lv_coord_t h = lv_obj_get_height(item);
|
||||
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
|
||||
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
|
||||
|
||||
lv_coord_t diff_x = abs_x - item->coords.x1 + tr_x;
|
||||
lv_coord_t diff_y = abs_y - item->coords.y1 + tr_y;
|
||||
diff_x += f->row ? main_pos : cross_pos;
|
||||
diff_y += f->row ? cross_pos : main_pos;
|
||||
|
||||
if(diff_x || diff_y) {
|
||||
lv_obj_invalidate(item);
|
||||
item->coords.x1 += diff_x;
|
||||
item->coords.x2 += diff_x;
|
||||
item->coords.y1 += diff_y;
|
||||
item->coords.y2 += diff_y;
|
||||
lv_obj_invalidate(item);
|
||||
lv_obj_move_children_by(item, diff_x, diff_y, true);
|
||||
}
|
||||
|
||||
if(!(f->row && rtl)) main_pos += area_get_main_size(&item->coords) + item_gap + place_gap;
|
||||
else main_pos -= item_gap + place_gap;
|
||||
|
||||
item = get_next_item(cont, f->rev, &item_first_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell a start coordinate and gap for a placement type.
|
||||
*/
|
||||
static void place_content(lv_flex_align_t place, lv_coord_t max_size, lv_coord_t content_size, lv_coord_t item_cnt,
|
||||
lv_coord_t * start_pos, lv_coord_t * gap)
|
||||
{
|
||||
if(item_cnt <= 1) {
|
||||
switch(place) {
|
||||
case LV_FLEX_ALIGN_SPACE_BETWEEN:
|
||||
case LV_FLEX_ALIGN_SPACE_AROUND:
|
||||
case LV_FLEX_ALIGN_SPACE_EVENLY:
|
||||
place = LV_FLEX_ALIGN_CENTER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(place) {
|
||||
case LV_FLEX_ALIGN_CENTER:
|
||||
*gap = 0;
|
||||
*start_pos += (max_size - content_size) / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_END:
|
||||
*gap = 0;
|
||||
*start_pos += max_size - content_size;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_BETWEEN:
|
||||
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt - 1);
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_AROUND:
|
||||
*gap += (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt);
|
||||
*start_pos += *gap / 2;
|
||||
break;
|
||||
case LV_FLEX_ALIGN_SPACE_EVENLY:
|
||||
*gap = (lv_coord_t)(max_size - content_size) / (lv_coord_t)(item_cnt + 1);
|
||||
*start_pos += *gap;
|
||||
break;
|
||||
default:
|
||||
*gap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_obj_t * get_next_item(lv_obj_t * cont, bool rev, int32_t * item_id)
|
||||
{
|
||||
if(rev) {
|
||||
(*item_id)--;
|
||||
if(*item_id >= 0) return cont->spec_attr->children[*item_id];
|
||||
else return NULL;
|
||||
}
|
||||
else {
|
||||
(*item_id)++;
|
||||
if((*item_id) < (int32_t)cont->spec_attr->child_cnt) return cont->spec_attr->children[*item_id];
|
||||
else return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FLEX*/
|
153
EC600U_lvgl_lib/lvgl/src/extra/layouts/flex/lv_flex.h
Normal file
153
EC600U_lvgl_lib/lvgl/src/extra/layouts/flex/lv_flex.h
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @file lv_flex.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FLEX_H
|
||||
#define LV_FLEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../core/lv_obj.h"
|
||||
#if LV_USE_FLEX
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_OBJ_FLAG_FLEX_IN_NEW_TRACK LV_OBJ_FLAG_LAYOUT_1
|
||||
LV_EXPORT_CONST_INT(LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
|
||||
|
||||
#define _LV_FLEX_COLUMN (1 << 0)
|
||||
#define _LV_FLEX_WRAP (1 << 2)
|
||||
#define _LV_FLEX_REVERSE (1 << 3)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_END,
|
||||
LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_SPACE_EVENLY,
|
||||
LV_FLEX_ALIGN_SPACE_AROUND,
|
||||
LV_FLEX_ALIGN_SPACE_BETWEEN,
|
||||
} lv_flex_align_t;
|
||||
|
||||
typedef enum {
|
||||
LV_FLEX_FLOW_ROW = 0x00,
|
||||
LV_FLEX_FLOW_COLUMN = _LV_FLEX_COLUMN,
|
||||
LV_FLEX_FLOW_ROW_WRAP = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP,
|
||||
LV_FLEX_FLOW_ROW_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_ROW_WRAP_REVERSE = LV_FLEX_FLOW_ROW | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_COLUMN_WRAP = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP,
|
||||
LV_FLEX_FLOW_COLUMN_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_REVERSE,
|
||||
LV_FLEX_FLOW_COLUMN_WRAP_REVERSE = LV_FLEX_FLOW_COLUMN | _LV_FLEX_WRAP | _LV_FLEX_REVERSE,
|
||||
} lv_flex_flow_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
extern uint32_t LV_LAYOUT_FLEX;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_FLOW;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_MAIN_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_CROSS_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_TRACK_PLACE;
|
||||
extern lv_style_prop_t LV_STYLE_FLEX_GROW;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize a flex layout the default values
|
||||
* @param flex pointer to a flex layout descriptor
|
||||
*/
|
||||
void lv_flex_init(void);
|
||||
|
||||
/**
|
||||
* Set hot the item should flow
|
||||
* @param flex pointer to a flex layout descriptor
|
||||
* @param flow an element of `lv_flex_flow_t`.
|
||||
*/
|
||||
void lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow);
|
||||
|
||||
/**
|
||||
* Set how to place (where to align) the items and tracks
|
||||
* @param flex pointer: to a flex layout descriptor
|
||||
* @param main_place where to place the items on main axis (in their track). Any value of `lv_flex_align_t`.
|
||||
* @param cross_place where to place the item in their track on the cross axis. `LV_FLEX_ALIGN_START/END/CENTER`
|
||||
* @param track_place where to place the tracks in the cross direction. Any value of `lv_flex_align_t`.
|
||||
*/
|
||||
void lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_place, lv_flex_align_t cross_place,
|
||||
lv_flex_align_t track_cross_place);
|
||||
|
||||
/**
|
||||
* Sets the width or height (on main axis) to grow the object in order fill the free space
|
||||
* @param obj pointer to an object. The parent must have flex layout else nothing will happen.
|
||||
* @param grow a value to set how much free space to take proportionally to other growing items.
|
||||
*/
|
||||
void lv_obj_set_flex_grow(lv_obj_t * obj, uint8_t grow);
|
||||
|
||||
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value);
|
||||
void lv_style_set_flex_main_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_cross_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_track_place(lv_style_t * style, lv_flex_align_t value);
|
||||
void lv_style_set_flex_grow(lv_style_t * style, uint8_t value);
|
||||
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_cross_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_track_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_flex_grow(lv_obj_t * obj, uint8_t value, lv_style_selector_t selector);
|
||||
|
||||
static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_FLOW);
|
||||
return (lv_flex_flow_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_main_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_MAIN_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_cross_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_CROSS_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_flex_align_t lv_obj_get_style_flex_track_place(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_TRACK_PLACE);
|
||||
return (lv_flex_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline uint8_t lv_obj_get_style_flex_grow(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_FLEX_GROW);
|
||||
return (uint8_t)v.num;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FLEX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_FLEX_H*/
|
780
EC600U_lvgl_lib/lvgl/src/extra/layouts/grid/lv_grid.c
Normal file
780
EC600U_lvgl_lib/lvgl/src/extra/layouts/grid/lv_grid.c
Normal file
@ -0,0 +1,780 @@
|
||||
/**
|
||||
* @file lv_grid.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_layouts.h"
|
||||
|
||||
#if LV_USE_GRID
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/**
|
||||
* Some helper defines
|
||||
*/
|
||||
#define IS_FR(x) (x >= LV_COORD_MAX - 100)
|
||||
#define IS_CONTENT(x) (x == LV_COORD_MAX - 101)
|
||||
#define GET_FR(x) (x - (LV_COORD_MAX - 100))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
uint32_t col;
|
||||
uint32_t row;
|
||||
lv_point_t grid_abs;
|
||||
} item_repos_hint_t;
|
||||
|
||||
typedef struct {
|
||||
lv_coord_t * x;
|
||||
lv_coord_t * y;
|
||||
lv_coord_t * w;
|
||||
lv_coord_t * h;
|
||||
uint32_t col_num;
|
||||
uint32_t row_num;
|
||||
lv_coord_t grid_w;
|
||||
lv_coord_t grid_h;
|
||||
} _lv_grid_calc_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void grid_update(lv_obj_t * cont, void * user_data);
|
||||
static void calc(lv_obj_t * obj, _lv_grid_calc_t * calc);
|
||||
static void calc_free(_lv_grid_calc_t * calc);
|
||||
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c);
|
||||
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c);
|
||||
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint);
|
||||
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
|
||||
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse);
|
||||
static uint32_t count_tracks(const lv_coord_t * templ);
|
||||
|
||||
static inline const lv_coord_t * get_col_dsc(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_column_dsc_array(obj, 0);
|
||||
}
|
||||
static inline const lv_coord_t * get_row_dsc(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_row_dsc_array(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_col_pos(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_column_pos(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_row_pos(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_row_pos(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_col_span(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_column_span(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_row_span(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_row_span(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_cell_col_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_x_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_cell_row_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_cell_y_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_grid_col_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_column_align(obj, 0);
|
||||
}
|
||||
static inline uint8_t get_grid_row_align(lv_obj_t * obj)
|
||||
{
|
||||
return lv_obj_get_style_grid_row_align(obj, 0);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
uint32_t LV_LAYOUT_GRID;
|
||||
lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
|
||||
lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
|
||||
lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
|
||||
lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
void lv_grid_init(void)
|
||||
{
|
||||
LV_LAYOUT_GRID = lv_layout_register(grid_update, NULL);
|
||||
|
||||
LV_STYLE_GRID_COLUMN_DSC_ARRAY = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_ROW_DSC_ARRAY = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_COLUMN_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_ROW_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
|
||||
LV_STYLE_GRID_CELL_ROW_SPAN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_CELL_ROW_POS = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_CELL_COLUMN_SPAN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_CELL_COLUMN_POS = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_CELL_X_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
LV_STYLE_GRID_CELL_Y_ALIGN = lv_style_register_prop() | LV_STYLE_PROP_LAYOUT_REFR;
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[])
|
||||
{
|
||||
lv_obj_set_style_grid_column_dsc_array(obj, col_dsc, 0);
|
||||
lv_obj_set_style_grid_row_dsc_array(obj, row_dsc, 0);
|
||||
lv_obj_set_style_layout(obj, LV_LAYOUT_GRID, 0);
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align)
|
||||
{
|
||||
lv_obj_set_style_grid_column_align(obj, column_align, 0);
|
||||
lv_obj_set_style_grid_row_align(obj, row_align, 0);
|
||||
|
||||
}
|
||||
|
||||
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t x_align, uint8_t col_pos, uint8_t col_span,
|
||||
lv_grid_align_t y_align, uint8_t row_pos, uint8_t row_span)
|
||||
|
||||
{
|
||||
lv_obj_set_style_grid_cell_column_pos(obj, col_pos, 0);
|
||||
lv_obj_set_style_grid_cell_row_pos(obj, row_pos, 0);
|
||||
lv_obj_set_style_grid_cell_x_align(obj, x_align, 0);
|
||||
lv_obj_set_style_grid_cell_column_span(obj, col_span, 0);
|
||||
lv_obj_set_style_grid_cell_row_span(obj, row_span, 0);
|
||||
lv_obj_set_style_grid_cell_y_align(obj, y_align, 0);
|
||||
|
||||
lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[])
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_ROW_DSC_ARRAY, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[])
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (lv_grid_align_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_ROW_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (lv_grid_align_t)value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_COLUMN_ALIGN, v);
|
||||
}
|
||||
|
||||
|
||||
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_POS, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_COLUMN_SPAN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_POS, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_ROW_SPAN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_X_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_style_set_prop(style, LV_STYLE_GRID_CELL_Y_ALIGN, v);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_DSC_ARRAY, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.ptr = (const void *)value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_DSC_ARRAY, v, selector);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_ROW_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = (int32_t) value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_COLUMN_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
|
||||
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_POS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_COLUMN_SPAN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_POS, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_ROW_SPAN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_X_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector)
|
||||
{
|
||||
lv_style_value_t v = {
|
||||
.num = value
|
||||
};
|
||||
lv_obj_set_local_style_prop(obj, LV_STYLE_GRID_CELL_Y_ALIGN, v, selector);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void grid_update(lv_obj_t * cont, void * user_data)
|
||||
{
|
||||
LV_LOG_INFO("update %p container", (void *)cont);
|
||||
LV_UNUSED(user_data);
|
||||
|
||||
const lv_coord_t * col_templ = get_col_dsc(cont);
|
||||
const lv_coord_t * row_templ = get_row_dsc(cont);
|
||||
if(col_templ == NULL || row_templ == NULL) return;
|
||||
|
||||
_lv_grid_calc_t c;
|
||||
calc(cont, &c);
|
||||
|
||||
item_repos_hint_t hint;
|
||||
lv_memset_00(&hint, sizeof(hint));
|
||||
|
||||
/*Calculate the grids absolute x and y coordinates.
|
||||
*It will be used as helper during item repositioning to avoid calculating this value for every children*/
|
||||
lv_coord_t border_widt = lv_obj_get_style_border_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + border_widt;
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + border_widt;
|
||||
hint.grid_abs.x = pad_left + cont->coords.x1 - lv_obj_get_scroll_x(cont);
|
||||
hint.grid_abs.y = pad_top + cont->coords.y1 - lv_obj_get_scroll_y(cont);
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < cont->spec_attr->child_cnt; i++) {
|
||||
lv_obj_t * item = cont->spec_attr->children[i];
|
||||
item_repos(item, &c, &hint);
|
||||
}
|
||||
calc_free(&c);
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
if(w_set == LV_SIZE_CONTENT || h_set == LV_SIZE_CONTENT) {
|
||||
lv_obj_refr_size(cont);
|
||||
}
|
||||
|
||||
lv_event_send(cont, LV_EVENT_LAYOUT_CHANGED, NULL);
|
||||
|
||||
LV_TRACE_LAYOUT("finished");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the grid cells coordinates
|
||||
* @param cont an object that has a grid
|
||||
* @param calc store the calculated cells sizes here
|
||||
* @note `_lv_grid_calc_free(calc_out)` needs to be called when `calc_out` is not needed anymore
|
||||
*/
|
||||
static void calc(lv_obj_t * cont, _lv_grid_calc_t * calc_out)
|
||||
{
|
||||
if(lv_obj_get_child(cont, 0) == NULL) {
|
||||
lv_memset_00(calc_out, sizeof(_lv_grid_calc_t));
|
||||
return;
|
||||
}
|
||||
|
||||
calc_rows(cont, calc_out);
|
||||
calc_cols(cont, calc_out);
|
||||
|
||||
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
|
||||
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
|
||||
|
||||
bool rev = lv_obj_get_style_base_dir(cont, LV_PART_MAIN) == LV_BASE_DIR_RTL ? true : false;
|
||||
|
||||
lv_coord_t w_set = lv_obj_get_style_width(cont, LV_PART_MAIN);
|
||||
lv_coord_t h_set = lv_obj_get_style_height(cont, LV_PART_MAIN);
|
||||
bool auto_w = (w_set == LV_SIZE_CONTENT && !cont->w_layout) ? true : false;
|
||||
lv_coord_t cont_w = lv_obj_get_content_width(cont);
|
||||
calc_out->grid_w = grid_align(cont_w, auto_w, get_grid_col_align(cont), col_gap, calc_out->col_num, calc_out->w,
|
||||
calc_out->x, rev);
|
||||
|
||||
bool auto_h = (h_set == LV_SIZE_CONTENT && !cont->h_layout) ? true : false;
|
||||
lv_coord_t cont_h = lv_obj_get_content_height(cont);
|
||||
calc_out->grid_h = grid_align(cont_h, auto_h, get_grid_row_align(cont), row_gap, calc_out->row_num, calc_out->h,
|
||||
calc_out->y, false);
|
||||
|
||||
LV_ASSERT_MEM_INTEGRITY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the a grid calculation's data
|
||||
* @param calc pointer to the calculated gtrid cell coordinates
|
||||
*/
|
||||
static void calc_free(_lv_grid_calc_t * calc)
|
||||
{
|
||||
lv_mem_buf_release(calc->x);
|
||||
lv_mem_buf_release(calc->y);
|
||||
lv_mem_buf_release(calc->w);
|
||||
lv_mem_buf_release(calc->h);
|
||||
}
|
||||
|
||||
static void calc_cols(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
{
|
||||
const lv_coord_t * col_templ = get_col_dsc(cont);
|
||||
lv_coord_t cont_w = lv_obj_get_content_width(cont);
|
||||
|
||||
c->col_num = count_tracks(col_templ);
|
||||
c->x = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
|
||||
c->w = lv_mem_buf_get(sizeof(lv_coord_t) * c->col_num);
|
||||
|
||||
/*Set sizes for CONTENT cells*/
|
||||
uint32_t i;
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t size = LV_COORD_MIN;
|
||||
if(IS_CONTENT(col_templ[i])) {
|
||||
/*Check the size of children of this cell*/
|
||||
uint32_t ci;
|
||||
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
|
||||
lv_obj_t * item = lv_obj_get_child(cont, ci);
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
uint32_t col_span = get_col_span(item);
|
||||
if(col_span != 1) continue;
|
||||
|
||||
uint32_t col_pos = get_col_pos(item);
|
||||
if(col_pos != i) continue;
|
||||
|
||||
size = LV_MAX(size, lv_obj_get_width(item));
|
||||
}
|
||||
if(size >= 0) c->w[i] = size;
|
||||
else c->w[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t col_fr_cnt = 0;
|
||||
lv_coord_t grid_w = 0;
|
||||
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t x = col_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
col_fr_cnt += GET_FR(x);
|
||||
}
|
||||
else if(IS_CONTENT(x)) {
|
||||
grid_w += c->w[i];
|
||||
}
|
||||
else {
|
||||
c->w[i] = x;
|
||||
grid_w += x;
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t col_gap = lv_obj_get_style_pad_column(cont, LV_PART_MAIN);
|
||||
cont_w -= col_gap * (c->col_num - 1);
|
||||
lv_coord_t free_w = cont_w - grid_w;
|
||||
if(free_w < 0) free_w = 0;
|
||||
|
||||
int32_t last_fr_i = -1;
|
||||
int32_t last_fr_x = 0;
|
||||
for(i = 0; i < c->col_num; i++) {
|
||||
lv_coord_t x = col_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
lv_coord_t f = GET_FR(x);
|
||||
c->w[i] = (free_w * f) / col_fr_cnt;
|
||||
last_fr_i = i;
|
||||
last_fr_x = f;
|
||||
}
|
||||
}
|
||||
|
||||
/*To avoid rounding errors set the last FR track to the remaining size */
|
||||
if(last_fr_i >= 0) {
|
||||
c->w[last_fr_i] = free_w - ((free_w * (col_fr_cnt - last_fr_x)) / col_fr_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
static void calc_rows(lv_obj_t * cont, _lv_grid_calc_t * c)
|
||||
{
|
||||
uint32_t i;
|
||||
const lv_coord_t * row_templ = get_row_dsc(cont);
|
||||
c->row_num = count_tracks(row_templ);
|
||||
c->y = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
|
||||
c->h = lv_mem_buf_get(sizeof(lv_coord_t) * c->row_num);
|
||||
/*Set sizes for CONTENT cells*/
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t size = LV_COORD_MIN;
|
||||
if(IS_CONTENT(row_templ[i])) {
|
||||
/*Check the size of children of this cell*/
|
||||
uint32_t ci;
|
||||
for(ci = 0; ci < lv_obj_get_child_cnt(cont); ci++) {
|
||||
lv_obj_t * item = lv_obj_get_child(cont, ci);
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) continue;
|
||||
uint32_t row_span = get_row_span(item);
|
||||
if(row_span != 1) continue;
|
||||
|
||||
uint32_t row_pos = get_row_pos(item);
|
||||
if(row_pos != i) continue;
|
||||
|
||||
size = LV_MAX(size, lv_obj_get_height(item));
|
||||
}
|
||||
if(size >= 0) c->h[i] = size;
|
||||
else c->h[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t row_fr_cnt = 0;
|
||||
lv_coord_t grid_h = 0;
|
||||
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t x = row_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
row_fr_cnt += GET_FR(x);
|
||||
}
|
||||
else if(IS_CONTENT(x)) {
|
||||
grid_h += c->h[i];
|
||||
}
|
||||
else {
|
||||
c->h[i] = x;
|
||||
grid_h += x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lv_coord_t row_gap = lv_obj_get_style_pad_row(cont, LV_PART_MAIN);
|
||||
lv_coord_t cont_h = lv_obj_get_content_height(cont) - row_gap * (c->row_num - 1);
|
||||
lv_coord_t free_h = cont_h - grid_h;
|
||||
if(free_h < 0) free_h = 0;
|
||||
|
||||
int32_t last_fr_i = -1;
|
||||
int32_t last_fr_x = 0;
|
||||
for(i = 0; i < c->row_num; i++) {
|
||||
lv_coord_t x = row_templ[i];
|
||||
if(IS_FR(x)) {
|
||||
lv_coord_t f = GET_FR(x);
|
||||
c->h[i] = (free_h * f) / row_fr_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
/*To avoid rounding errors set the last FR track to the remaining size */
|
||||
if(last_fr_i >= 0) {
|
||||
c->h[last_fr_i] = free_h - ((free_h * (row_fr_cnt - last_fr_x)) / row_fr_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reposition a grid item in its cell
|
||||
* @param item a grid item to reposition
|
||||
* @param calc the calculated grid of `cont`
|
||||
* @param child_id_ext helper value if the ID of the child is know (order from the oldest) else -1
|
||||
* @param grid_abs helper value, the absolute position of the grid, NULL if unknown
|
||||
*/
|
||||
static void item_repos(lv_obj_t * item, _lv_grid_calc_t * c, item_repos_hint_t * hint)
|
||||
{
|
||||
if(lv_obj_has_flag_any(item, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_HIDDEN | LV_OBJ_FLAG_FLOATING)) return;
|
||||
uint32_t col_span = get_col_span(item);
|
||||
uint32_t row_span = get_row_span(item);
|
||||
if(row_span == 0 || col_span == 0) return;
|
||||
|
||||
uint32_t col_pos = get_col_pos(item);
|
||||
uint32_t row_pos = get_row_pos(item);
|
||||
lv_grid_align_t col_align = get_cell_col_align(item);
|
||||
lv_grid_align_t row_align = get_cell_row_align(item);
|
||||
|
||||
|
||||
lv_coord_t col_x1 = c->x[col_pos];
|
||||
lv_coord_t col_x2 = c->x[col_pos + col_span - 1] + c->w[col_pos + col_span - 1];
|
||||
lv_coord_t col_w = col_x2 - col_x1;
|
||||
|
||||
lv_coord_t row_y1 = c->y[row_pos];
|
||||
lv_coord_t row_y2 = c->y[row_pos + row_span - 1] + c->h[row_pos + row_span - 1];
|
||||
lv_coord_t row_h = row_y2 - row_y1;
|
||||
|
||||
|
||||
/*If the item has RTL base dir switch start and end*/
|
||||
if(lv_obj_get_style_base_dir(item, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
||||
if(col_align == LV_GRID_ALIGN_START) col_align = LV_GRID_ALIGN_END;
|
||||
else if(col_align == LV_GRID_ALIGN_END) col_align = LV_GRID_ALIGN_START;
|
||||
}
|
||||
|
||||
lv_coord_t x;
|
||||
lv_coord_t y;
|
||||
lv_coord_t item_w = lv_area_get_width(&item->coords);
|
||||
lv_coord_t item_h = lv_area_get_height(&item->coords);
|
||||
|
||||
switch(col_align) {
|
||||
default:
|
||||
case LV_GRID_ALIGN_START:
|
||||
x = c->x[col_pos];
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_STRETCH:
|
||||
x = c->x[col_pos];
|
||||
item_w = col_w;
|
||||
item->w_layout = 1;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
x = c->x[col_pos] + (col_w - item_w) / 2;
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
x = c->x[col_pos] + col_w - lv_obj_get_width(item);
|
||||
item->w_layout = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(row_align) {
|
||||
default:
|
||||
case LV_GRID_ALIGN_START:
|
||||
y = c->y[row_pos];
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_STRETCH:
|
||||
y = c->y[row_pos];
|
||||
item_h = row_h;
|
||||
item->h_layout = 1;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
y = c->y[row_pos] + (row_h - item_h) / 2;
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
y = c->y[row_pos] + row_h - lv_obj_get_height(item);
|
||||
item->h_layout = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Set a new size if required*/
|
||||
if(lv_obj_get_width(item) != item_w || lv_obj_get_height(item) != item_h) {
|
||||
lv_area_t old_coords;
|
||||
lv_area_copy(&old_coords, &item->coords);
|
||||
lv_obj_invalidate(item);
|
||||
lv_area_set_width(&item->coords, item_w);
|
||||
lv_area_set_height(&item->coords, item_h);
|
||||
lv_obj_invalidate(item);
|
||||
lv_event_send(item, LV_EVENT_SIZE_CHANGED, &old_coords);
|
||||
lv_event_send(lv_obj_get_parent(item), LV_EVENT_CHILD_CHANGED, item);
|
||||
|
||||
}
|
||||
|
||||
/*Handle percentage value of translate*/
|
||||
lv_coord_t tr_x = lv_obj_get_style_translate_x(item, LV_PART_MAIN);
|
||||
lv_coord_t tr_y = lv_obj_get_style_translate_y(item, LV_PART_MAIN);
|
||||
lv_coord_t w = lv_obj_get_width(item);
|
||||
lv_coord_t h = lv_obj_get_height(item);
|
||||
if(LV_COORD_IS_PCT(tr_x)) tr_x = (w * LV_COORD_GET_PCT(tr_x)) / 100;
|
||||
if(LV_COORD_IS_PCT(tr_y)) tr_y = (h * LV_COORD_GET_PCT(tr_y)) / 100;
|
||||
|
||||
x += tr_x;
|
||||
y += tr_y;
|
||||
|
||||
lv_coord_t diff_x = hint->grid_abs.x + x - item->coords.x1;
|
||||
lv_coord_t diff_y = hint->grid_abs.y + y - item->coords.y1;
|
||||
if(diff_x || diff_y) {
|
||||
lv_obj_invalidate(item);
|
||||
item->coords.x1 += diff_x;
|
||||
item->coords.x2 += diff_x;
|
||||
item->coords.y1 += diff_y;
|
||||
item->coords.y2 += diff_y;
|
||||
lv_obj_invalidate(item);
|
||||
lv_obj_move_children_by(item, diff_x, diff_y, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Place the grid track according to align methods. It keeps the track sizes but sets their position.
|
||||
* It can process both columns or rows according to the passed parameters.
|
||||
* @param cont_size size of the containers content area (width/height)
|
||||
* @param auto_size true: the container has auto size in the current direction
|
||||
* @param align align method
|
||||
* @param gap grid gap
|
||||
* @param track_num number of tracks
|
||||
* @param size_array array with the track sizes
|
||||
* @param pos_array write the positions of the tracks here
|
||||
* @return the total size of the grid
|
||||
*/
|
||||
static lv_coord_t grid_align(lv_coord_t cont_size, bool auto_size, uint8_t align, lv_coord_t gap, uint32_t track_num,
|
||||
lv_coord_t * size_array, lv_coord_t * pos_array, bool reverse)
|
||||
{
|
||||
lv_coord_t grid_size = 0;
|
||||
uint32_t i;
|
||||
|
||||
if(auto_size) {
|
||||
pos_array[0] = 0;
|
||||
}
|
||||
else {
|
||||
/*With spaced alignment gap will be calculated from the remaining space*/
|
||||
if(align == LV_GRID_ALIGN_SPACE_AROUND || align == LV_GRID_ALIGN_SPACE_BETWEEN || align == LV_GRID_ALIGN_SPACE_EVENLY) {
|
||||
gap = 0;
|
||||
if(track_num == 1) align = LV_GRID_ALIGN_CENTER;
|
||||
}
|
||||
|
||||
/*Get the full grid size with gap*/
|
||||
for(i = 0; i < track_num; i++) {
|
||||
grid_size += size_array[i] + gap;
|
||||
}
|
||||
grid_size -= gap;
|
||||
|
||||
/*Calculate the position of the first item and set gap is necessary*/
|
||||
switch(align) {
|
||||
case LV_GRID_ALIGN_START:
|
||||
pos_array[0] = 0;
|
||||
break;
|
||||
case LV_GRID_ALIGN_CENTER:
|
||||
pos_array[0] = (cont_size - grid_size) / 2;
|
||||
break;
|
||||
case LV_GRID_ALIGN_END:
|
||||
pos_array[0] = cont_size - grid_size;
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_BETWEEN:
|
||||
pos_array[0] = 0;
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num - 1);
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_AROUND:
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num);
|
||||
pos_array[0] = gap / 2;
|
||||
break;
|
||||
case LV_GRID_ALIGN_SPACE_EVENLY:
|
||||
gap = (lv_coord_t)(cont_size - grid_size) / (lv_coord_t)(track_num + 1);
|
||||
pos_array[0] = gap;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*Set the position of all tracks from the start position, gaps and track sizes*/
|
||||
for(i = 0; i < track_num - 1; i++) {
|
||||
pos_array[i + 1] = pos_array[i] + size_array[i] + gap;
|
||||
}
|
||||
|
||||
lv_coord_t total_gird_size = pos_array[track_num - 1] + size_array[track_num - 1] - pos_array[0];
|
||||
|
||||
if(reverse) {
|
||||
for(i = 0; i < track_num; i++) {
|
||||
pos_array[i] = cont_size - pos_array[i] - size_array[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*Return the full size of the grid*/
|
||||
return total_gird_size;
|
||||
}
|
||||
|
||||
static uint32_t count_tracks(const lv_coord_t * templ)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; templ[i] != LV_GRID_TEMPLATE_LAST; i++);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_GRID*/
|
194
EC600U_lvgl_lib/lvgl/src/extra/layouts/grid/lv_grid.h
Normal file
194
EC600U_lvgl_lib/lvgl/src/extra/layouts/grid/lv_grid.h
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @file lv_grid.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GRID_H
|
||||
#define LV_GRID_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../core/lv_obj.h"
|
||||
#if LV_USE_GRID
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/**
|
||||
* Can be used track size to make the track fill the free space.
|
||||
* @param x how much space to take proportionally to other FR tracks
|
||||
* @return a special track size
|
||||
*/
|
||||
#define LV_GRID_FR(x) (LV_COORD_MAX - 100 + x)
|
||||
|
||||
#define LV_GRID_CONTENT (LV_COORD_MAX - 101)
|
||||
LV_EXPORT_CONST_INT(LV_GRID_CONTENT);
|
||||
|
||||
#define LV_GRID_TEMPLATE_LAST (LV_COORD_MAX)
|
||||
LV_EXPORT_CONST_INT(LV_GRID_TEMPLATE_LAST);
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Can't include lv_obj.h because it includes this header file*/
|
||||
struct _lv_obj_t;
|
||||
|
||||
typedef enum {
|
||||
LV_GRID_ALIGN_START,
|
||||
LV_GRID_ALIGN_CENTER,
|
||||
LV_GRID_ALIGN_END,
|
||||
LV_GRID_ALIGN_STRETCH,
|
||||
LV_GRID_ALIGN_SPACE_EVENLY,
|
||||
LV_GRID_ALIGN_SPACE_AROUND,
|
||||
LV_GRID_ALIGN_SPACE_BETWEEN,
|
||||
} lv_grid_align_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
extern uint32_t LV_LAYOUT_GRID;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_DSC_ARRAY;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_COLUMN_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_ROW_DSC_ARRAY;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_ROW_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_POS;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_COLUMN_SPAN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_X_ALIGN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_POS;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_ROW_SPAN;
|
||||
extern lv_style_prop_t LV_STYLE_GRID_CELL_Y_ALIGN;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
void lv_grid_init(void);
|
||||
|
||||
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]);
|
||||
|
||||
void lv_obj_set_grid_align(lv_obj_t * obj, lv_grid_align_t column_align, lv_grid_align_t row_align);
|
||||
|
||||
/**
|
||||
* Set the cell of an object. The object's parent needs to have grid layout, else nothing will happen
|
||||
* @param obj pointer to an object
|
||||
* @param column_align the vertical alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
|
||||
* @param col_pos column ID
|
||||
* @param col_span number of columns to take (>= 1)
|
||||
* @param row_align the horizontal alignment in the cell. `LV_GRID_START/END/CENTER/STRETCH`
|
||||
* @param row_pos row ID
|
||||
* @param row_span number of rows to take (>= 1)
|
||||
*/
|
||||
void lv_obj_set_grid_cell(lv_obj_t * obj, lv_grid_align_t column_align, uint8_t col_pos, uint8_t col_span,
|
||||
lv_grid_align_t row_align, uint8_t row_pos, uint8_t row_span);
|
||||
|
||||
/**
|
||||
* Just a wrapper to `LV_GRID_FR` for bindings.
|
||||
*/
|
||||
static inline lv_coord_t lv_grid_fr(uint8_t x)
|
||||
{
|
||||
return LV_GRID_FR(x);
|
||||
}
|
||||
|
||||
void lv_style_set_grid_row_dsc_array(lv_style_t * style, const lv_coord_t value[]);
|
||||
void lv_style_set_grid_column_dsc_array(lv_style_t * style, const lv_coord_t value[]);
|
||||
void lv_style_set_grid_row_align(lv_style_t * style, lv_grid_align_t value);
|
||||
void lv_style_set_grid_column_align(lv_style_t * style, lv_grid_align_t value);
|
||||
void lv_style_set_grid_cell_column_pos(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_column_span(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_row_pos(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_row_span(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_x_align(lv_style_t * style, lv_coord_t value);
|
||||
void lv_style_set_grid_cell_y_align(lv_style_t * style, lv_coord_t value);
|
||||
|
||||
void lv_obj_set_style_grid_row_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_column_dsc_array(lv_obj_t * obj, const lv_coord_t value[], lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_row_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_column_align(lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_column_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_column_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_row_pos(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_row_span(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_x_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
void lv_obj_set_style_grid_cell_y_align(lv_obj_t * obj, lv_coord_t value, lv_style_selector_t selector);
|
||||
|
||||
static inline const lv_coord_t * lv_obj_get_style_grid_row_dsc_array(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_DSC_ARRAY);
|
||||
return (const lv_coord_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline const lv_coord_t * lv_obj_get_style_grid_column_dsc_array(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_DSC_ARRAY);
|
||||
return (const lv_coord_t *)v.ptr;
|
||||
}
|
||||
|
||||
static inline lv_grid_align_t lv_obj_get_style_grid_row_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_ROW_ALIGN);
|
||||
return (lv_grid_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_grid_align_t lv_obj_get_style_grid_column_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_COLUMN_ALIGN);
|
||||
return (lv_grid_align_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_column_pos(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_POS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_column_span(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_COLUMN_SPAN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_row_pos(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_POS);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_row_span(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_ROW_SPAN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_x_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_X_ALIGN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
static inline lv_coord_t lv_obj_get_style_grid_cell_y_align(const lv_obj_t * obj, uint32_t part)
|
||||
{
|
||||
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_GRID_CELL_Y_ALIGN);
|
||||
return (lv_coord_t)v.num;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#endif /*LV_USE_GRID*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_GRID_H*/
|
44
EC600U_lvgl_lib/lvgl/src/extra/layouts/lv_layouts.h
Normal file
44
EC600U_lvgl_lib/lvgl/src/extra/layouts/lv_layouts.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file lv_layouts.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LAYOUTS_H
|
||||
#define LV_LAYOUTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "flex/lv_flex.h"
|
||||
#include "grid/lv_grid.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_LAYOUT
|
||||
# define LV_TRACE_LAYOUT(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
# define LV_TRACE_LAYOUT(...)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_LAYOUTS_H*/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user