fix uart1 pin bug, delete and update wrong icf files, add vglite support for rt1170 in IAR environment.

This commit is contained in:
Frogrey 2023-09-20 17:00:30 +08:00 committed by guo
parent a7e210d701
commit f941dfcf13
91 changed files with 32890 additions and 236 deletions

View File

@ -8,6 +8,8 @@
#
CONFIG_RT_NAME_MAX=8
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_SMART is not set
# CONFIG_RT_USING_AMP is not set
# CONFIG_RT_USING_SMP is not set
CONFIG_RT_ALIGN_SIZE=8
# CONFIG_RT_THREAD_PRIORITY_8 is not set
@ -30,18 +32,10 @@ CONFIG_IDLE_THREAD_STACK_SIZE=256
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
# CONFIG_RT_USING_TINY_FFS is not set
# CONFIG_RT_KPRINTF_USING_LONGLONG is not set
CONFIG_RT_DEBUG=y
CONFIG_RT_DEBUG_COLOR=y
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
CONFIG_RT_USING_DEBUG=y
CONFIG_RT_DEBUGING_COLOR=y
CONFIG_RT_DEBUGING_CONTEXT=y
CONFIG_RT_DEBUGING_INIT=y
#
# Inter-Thread communication
@ -51,12 +45,12 @@ CONFIG_RT_USING_MUTEX=y
CONFIG_RT_USING_EVENT=y
CONFIG_RT_USING_MAILBOX=y
CONFIG_RT_USING_MESSAGEQUEUE=y
# CONFIG_RT_USING_MESSAGEQUEUE_PRIORITY is not set
# CONFIG_RT_USING_SIGNALS is not set
#
# Memory Management
#
CONFIG_RT_PAGE_MAX_ORDER=11
CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_SMALL_MEM is not set
# CONFIG_RT_USING_SLAB is not set
@ -83,13 +77,17 @@ CONFIG_RT_USING_DEVICE=y
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_VER_NUM=0x50000
CONFIG_RT_VER_NUM=0x50001
# CONFIG_RT_USING_STDC_ATOMIC is not set
# CONFIG_RT_USING_CACHE is not set
# CONFIG_RT_USING_HW_ATOMIC is not set
CONFIG_RT_USING_CACHE=y
CONFIG_RT_USING_HW_ATOMIC=y
# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_RT_USING_CPU_FFS=y
CONFIG_ARCH_ARM=y
CONFIG_ARCH_ARM_CORTEX_M=y
CONFIG_ARCH_ARM_CORTEX_FPU=y
CONFIG_ARCH_ARM_CORTEX_M7=y
#
# RT-Thread Components
@ -114,6 +112,10 @@ CONFIG_FINSH_USING_DESCRIPTION=y
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_ARG_MAX=10
#
# DFS: device virtual file system
#
# CONFIG_RT_USING_DFS is not set
# CONFIG_RT_USING_FAL is not set
@ -172,7 +174,19 @@ CONFIG_RT_USBD_THREAD_STACK_SZ=4096
#
# C/C++ and POSIX layer
#
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
#
# ISO-ANSI C layer
#
#
# Timezone and Daylight Saving Time
#
# CONFIG_RT_LIBC_USING_FULL_TZ_DST is not set
CONFIG_RT_LIBC_USING_LIGHT_TZ_DST=y
CONFIG_RT_LIBC_TZ_DEFAULT_HOUR=8
CONFIG_RT_LIBC_TZ_DEFAULT_MIN=0
CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
#
# POSIX (Portable Operating System Interface) layer
@ -219,9 +233,11 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_VAR_EXPORT is not set
# CONFIG_RT_USING_RESOURCE_ID is not set
# CONFIG_RT_USING_ADT is not set
# CONFIG_RT_USING_RT_LINK is not set
# CONFIG_RT_USING_VBUS is not set
# CONFIG_RT_USING_KTIME is not set
#
# RT-Thread Utestcases
@ -246,7 +262,6 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_KAWAII_MQTT is not set
# CONFIG_PKG_USING_BC28_MQTT is not set
# CONFIG_PKG_USING_WEBTERMINAL is not set
# CONFIG_PKG_USING_LIBMODBUS is not set
# CONFIG_PKG_USING_FREEMODBUS is not set
# CONFIG_PKG_USING_NANOPB is not set
@ -264,6 +279,11 @@ CONFIG_NETDEV_IPV6=0
#
# CONFIG_PKG_USING_WLAN_WICED is not set
# CONFIG_PKG_USING_RW007 is not set
#
# CYW43012 WiFi
#
# CONFIG_PKG_USING_WLAN_CYW43012 is not set
# CONFIG_PKG_USING_COAP is not set
# CONFIG_PKG_USING_NOPOLL is not set
# CONFIG_PKG_USING_NETUTILS is not set
@ -325,6 +345,7 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_ZFTP is not set
# CONFIG_PKG_USING_WOL is not set
# CONFIG_PKG_USING_ZEPHYR_POLLING is not set
# CONFIG_PKG_USING_MATTER_ADAPTATION_LAYER is not set
#
# security packages
@ -371,7 +392,6 @@ CONFIG_NETDEV_IPV6=0
# LVGL: powerful and easy-to-use embedded GUI library
#
# CONFIG_PKG_USING_LVGL is not set
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set
@ -398,6 +418,7 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_QRCODE is not set
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_PERSIMMON is not set
# CONFIG_PKG_USING_3GPP_AMRNB is not set
#
@ -446,6 +467,8 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_HASH_MATCH is not set
# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set
# CONFIG_PKG_USING_VOFA_PLUS is not set
# CONFIG_PKG_USING_RT_TRACE is not set
# CONFIG_PKG_USING_ZDEBUG is not set
#
# system packages
@ -482,6 +505,8 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_UC_COMMON is not set
# CONFIG_PKG_USING_UC_MODBUS is not set
# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set
# CONFIG_PKG_USING_LITEOS_SDK is not set
# CONFIG_PKG_USING_TZ_DATABASE is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_PARTITION is not set
@ -505,6 +530,7 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_QBOOT is not set
# CONFIG_PKG_USING_PPOOL is not set
# CONFIG_PKG_USING_OPENAMP is not set
# CONFIG_PKG_USING_RPMSG_LITE is not set
# CONFIG_PKG_USING_LPM is not set
# CONFIG_PKG_USING_TLSF is not set
# CONFIG_PKG_USING_EVENT_RECORDER is not set
@ -517,6 +543,9 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_QPC is not set
# CONFIG_PKG_USING_AGILE_UPGRADE is not set
# CONFIG_PKG_USING_FLASH_BLOB is not set
# CONFIG_PKG_USING_MLIBC is not set
# CONFIG_PKG_USING_TASK_MSG_BUS is not set
# CONFIG_PKG_USING_SFDB is not set
#
# peripheral libraries and drivers
@ -581,6 +610,7 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_BALANCE is not set
# CONFIG_PKG_USING_SHT2X is not set
# CONFIG_PKG_USING_SHT3X is not set
# CONFIG_PKG_USING_SHT4X is not set
# CONFIG_PKG_USING_AD7746 is not set
# CONFIG_PKG_USING_ADT74XX is not set
# CONFIG_PKG_USING_MAX17048 is not set
@ -601,6 +631,7 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_FT5426 is not set
# CONFIG_PKG_USING_FT6236 is not set
# CONFIG_PKG_USING_XPT2046_TOUCH is not set
# CONFIG_PKG_USING_CST816X is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_STM32_SDIO is not set
# CONFIG_PKG_USING_ESP_IDF is not set
@ -613,7 +644,6 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_LKDGUI is not set
# CONFIG_PKG_USING_NRF5X_SDK is not set
# CONFIG_PKG_USING_NRFX is not set
# CONFIG_PKG_USING_WM_LIBRARIES is not set
#
# Kendryte SDK
@ -671,14 +701,18 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
# CONFIG_PKG_USING_BL_MCU_SDK is not set
# CONFIG_PKG_USING_SOFT_SERIAL is not set
# CONFIG_PKG_USING_MB85RS16 is not set
# CONFIG_PKG_USING_RFM300 is not set
# CONFIG_PKG_USING_IO_INPUT_FILTER is not set
# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set
# CONFIG_PKG_USING_LRF_NV7LIDAR is not set
# CONFIG_PKG_USING_AIP650 is not set
# CONFIG_PKG_USING_FINGERPRINT is not set
# CONFIG_PKG_USING_BT_ECB02C is not set
# CONFIG_PKG_USING_UAT is not set
# CONFIG_PKG_USING_ST7789 is not set
# CONFIG_PKG_USING_SPI_TOOLS is not set
#
# AI packages
@ -697,7 +731,11 @@ CONFIG_NETDEV_IPV6=0
# Signal Processing and Control Algorithm Packages
#
# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
# CONFIG_PKG_USING_QPID is not set
# CONFIG_PKG_USING_UKAL is not set
# CONFIG_PKG_USING_DIGITALCTRL is not set
# CONFIG_PKG_USING_KISSFFT is not set
# CONFIG_PKG_USING_CMSIS_DSP is not set
#
# miscellaneous packages
@ -744,7 +782,6 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_DSTR is not set
# CONFIG_PKG_USING_TINYFRAME is not set
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
# CONFIG_PKG_USING_DIGITALCTRL is not set
# CONFIG_PKG_USING_UPACKER is not set
# CONFIG_PKG_USING_UPARAM is not set
# CONFIG_PKG_USING_HELLO is not set
@ -769,8 +806,9 @@ CONFIG_NETDEV_IPV6=0
# CONFIG_PKG_USING_RTDUINO is not set
#
# Projects
# Projects and Demos
#
# CONFIG_PKG_USING_ARDUINO_MSGQ_C_CPP_DEMO is not set
# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set
# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set
# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set
@ -917,14 +955,21 @@ CONFIG_NETDEV_IPV6=0
#
# Display
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_GFX_LIBRARY is not set
# CONFIG_PKG_USING_ARDUINO_U8G2 is not set
# CONFIG_PKG_USING_ARDUINO_U8GLIB_ARDUINO is not set
# CONFIG_PKG_USING_ARDUINO_TFT_ESPI is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ST7735 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SSD1306 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ILI9341 is not set
# CONFIG_PKG_USING_SEEED_TM1637 is not set
#
# Timing
#
# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set
# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set
# CONFIG_PKG_USING_ARDUINO_TICKER is not set
# CONFIG_PKG_USING_ARDUINO_TASKSCHEDULER is not set
#
# Data Processing
@ -958,7 +1003,6 @@ CONFIG_NETDEV_IPV6=0
#
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MFRC630 is not set
# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI5351 is not set
# CONFIG_PKG_USING_ARDUINO_RTCLIB is not set
#
# Signal IO
@ -975,6 +1019,7 @@ CONFIG_NETDEV_IPV6=0
#
# Uncategorized
#
CONFIG_SOC_IMXRT1170_SERIES=y
#
# Hardware Drivers Config
@ -997,6 +1042,7 @@ CONFIG_BSP_USING_LPUART1=y
# CONFIG_BSP_USING_LPUART3 is not set
# CONFIG_BSP_USING_CAN is not set
# CONFIG_BSP_USING_FLEXSPI is not set
# CONFIG_BSP_USING_VGLITE is not set
#
# Onboard Peripheral Drivers

View File

@ -141,6 +141,42 @@ menu "On-chip Peripheral Drivers"
bool "Enable FLEXSPI2"
default n
endif
menuconfig BSP_USING_VGLITE
bool "Enable VGLITE"
select RT_USING_PIN
default n
if BSP_USING_VGLITE
choice
prompt "Select lcd panel"
default VGLITE_USING_RK055AHD091
config VGLITE_USING_RK055AHD091
bool "RK055AHD091-CTG (RK055HDMIPI4M 720 * 1280)"
config VGLITE_USING_RK055IQH091
bool "RK055IQH091-CTG (540 * 960)"
config VGLITE_USING_RK055MHD091
bool "RK055MHD091A0-CTG (RK055HDMIPI4MA0 720 * 1280)"
endchoice
choice
prompt "Select display controller"
default VGLITE_USING_LCDIFV2
config VGLITE_USING_ELCDIF
bool "ELCDIF"
config VGLITE_USING_LCDIFV2
bool "LCDIFV2"
endchoice
config VGLITE_USING_ELM
bool "Enable Elementary"
default y
endif
endmenu
menu "Onboard Peripheral Drivers"

View File

@ -258,26 +258,7 @@ void imxrt_uart_pins_init(void)
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
0U); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_B0_12 PAD functional properties : */
0x10B0u); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_B0_13 PAD functional properties : */
0x10B0u); /* Slew Rate Field: Slow Slew Rate
Drive Strength Field: R0/6
Speed Field: medium(100MHz)
Open Drain Enable Field: Open Drain Disabled
Pull / Keep Enable Field: Pull/Keeper Enabled
Pull / Keep Select Field: Keeper
Pull Up / Down Config. Field: 100K Ohm Pull Down
Hyst. Enable Field: Hysteresis Disabled */
#endif
#ifdef BSP_USING_LPUART2
@ -1334,6 +1315,25 @@ void imxrt_flexspi_pins_init(void)
}
#endif
#ifdef BSP_USING_VGLITE
void imxrt_lcd_pins_init(void)
{
#ifdef BSP_USING_VGLITE
CLOCK_EnableClock(kCLOCK_Iomuxc); /* LPCG on: LPCG is ON. */
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_02_GPIO9_IO01, /* GPIO_AD_02 is configured as GPIO9_IO01 */
0U); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_30_GPIO9_IO29, /* GPIO_AD_30 is configured as GPIO9_IO29 */
0U); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux(
IOMUXC_GPIO_DISP_B2_15_GPIO11_IO16, /* GPIO_DISP_B2_15 is configured as GPIO11_IO16 */
0U); /* Software Input On Field: Input Path is determined by functionality */
#endif
}
#endif
void rt_hw_board_init()
{
BOARD_ConfigMPU();
@ -1378,5 +1378,9 @@ void rt_hw_board_init()
#ifdef BSP_USING_FLEXSPI
imxrt_flexspi_pins_init();
#endif
#ifdef BSP_USING_VGLITE
imxrt_lcd_pins_init();
#endif
}

View File

@ -1,98 +0,0 @@
/*
** ###################################################################
** Processors: MIMXRT1052CVJ5B
** MIMXRT1052CVL5B
** MIMXRT1052DVJ6B
** MIMXRT1052DVL6B
**
** Compiler: IAR ANSI C/C++ Compiler for ARM
** Reference manual: IMXRT1050RM Rev.1, 03/2018
** Version: rev. 1.0, 2018-09-21
** Build: b180921
**
** Abstract:
** Linker file for the IAR ANSI C/C++ Compiler for ARM
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
define symbol m_interrupts_start = 0x30002000;
define symbol m_interrupts_end = 0x300023FF;
define symbol m_text_start = 0x30002400;
define symbol m_text_end = 0x30FBFFFF;
define symbol m_data_start = 0x20000000;
define symbol m_data_end = 0x2003FFFF;
define symbol m_data2_start = 0x202C0000;
define symbol m_data2_end = 0x2033FFFF;
define exported symbol __NCACHE_REGION_START = m_data2_start;
define exported symbol __NCACHE_REGION_SIZE = 0x0;
define exported symbol m_boot_hdr_conf_start = 0x30000400;
define symbol m_boot_hdr_ivt_start = 0x30001000;
define symbol m_boot_hdr_boot_data_start = 0x30001020;
define symbol m_boot_hdr_dcd_data_start = 0x30001030;
/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
define symbol __size_cstack__ = __stack_size__;
} else {
define symbol __size_cstack__ = 0x0400;
}
if (isdefinedsymbol(__heap_size__)) {
define symbol __size_heap__ = __heap_size__;
} else {
define symbol __size_heap__ = 0x0400;
}
define exported symbol __VECTOR_TABLE = m_interrupts_start;
define exported symbol __VECTOR_RAM = m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = 0x0;
define exported symbol __RTT_HEAP_END = m_data2_end;
define memory mem with size = 4G;
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
| mem:[from m_text_start to m_text_end];
define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__];
define region DATA2_region = mem:[from m_data2_start to m_data2_end];
define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end];
define block CSTACK with alignment = 8, size = __size_cstack__ { };
define block HEAP with alignment = 8, size = __size_heap__ { };
define block RW { readwrite };
define block ZI { zi };
define block NCACHE_VAR { section NonCacheable , section NonCacheable.init };
initialize by copy { readwrite, section .textrw };
do not initialize { section .noinit };
place at address mem: m_interrupts_start { readonly section .intvec };
place at address mem:m_boot_hdr_conf_start { section .boot_hdr.conf };
place at address mem:m_boot_hdr_ivt_start { section .boot_hdr.ivt };
place at address mem:m_boot_hdr_boot_data_start { readonly section .boot_hdr.boot_data };
place at address mem:m_boot_hdr_dcd_data_start { readonly section .boot_hdr.dcd_data };
keep{ section .boot_hdr.conf, section .boot_hdr.ivt, section .boot_hdr.boot_data, section .boot_hdr.dcd_data };
place in TEXT_region { readonly };
place in DATA_region { block RW };
place in DATA_region { block ZI };
place in DATA_region { last block HEAP };
place in DATA_region { block NCACHE_VAR };
place in CSTACK_region { block CSTACK };

View File

@ -24,10 +24,10 @@
** ###################################################################
*/
define symbol m_interrupts_start = 0x00002000;
define symbol m_interrupts_end = 0x000023FF;
define symbol m_interrupts_start = 0x00000000;
define symbol m_interrupts_end = 0x000003FF;
define symbol m_text_start = 0x00002400;
define symbol m_text_start = 0x00000400;
define symbol m_text_end = 0x0003FFFF;
define symbol m_data_start = 0x20000000;
@ -36,8 +36,14 @@ define symbol m_data_end = 0x2003FFFF;
define symbol m_data2_start = 0x202C0000;
define symbol m_data2_end = 0x2033FFFF;
define exported symbol __NCACHE_REGION_START = m_data2_start;
define exported symbol __NCACHE_REGION_SIZE = 0x0;
define symbol m_data3_start = 0x80000000;
define symbol m_data3_end = 0x82FFFFFF;
define symbol m_ncache_start = 0x83000000;
define symbol m_ncache_end = 0x83FFFFFF;
define exported symbol __NCACHE_REGION_START = m_ncache_start;
define exported symbol __NCACHE_REGION_SIZE = m_ncache_end - m_ncache_start + 1;
/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
@ -55,19 +61,21 @@ if (isdefinedsymbol(__heap_size__)) {
define exported symbol __VECTOR_TABLE = m_interrupts_start;
define exported symbol __VECTOR_RAM = m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = 0x0;
define exported symbol __RTT_HEAP_END = m_data2_end;
define exported symbol __RTT_HEAP_END = m_data3_end-__size_cstack__;
define memory mem with size = 4G;
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
| mem:[from m_text_start to m_text_end];
define region DATA_region = mem:[from m_data_start to m_data_end-__size_cstack__];
define region DATA_region = mem:[from m_data_start to m_data_end];
define region DATA2_region = mem:[from m_data2_start to m_data2_end];
define region CSTACK_region = mem:[from m_data_end-__size_cstack__+1 to m_data_end];
define region DATA3_region = mem:[from m_data3_start to m_data3_end-__size_cstack__];
define region CSTACK_region = mem:[from m_data3_end-__size_cstack__+1 to m_data3_end];
define region NCACHE_region = mem:[from m_ncache_start to m_ncache_end];
define block CSTACK with alignment = 8, size = __size_cstack__ { };
define block HEAP with alignment = 8, size = __size_heap__ { };
define block RW { readwrite };
define block ZI { zi };
define block RW { first readwrite, section m_usb_dma_init_data };
define block ZI with alignment = 32 { first zi, section m_usb_dma_noninit_data };
define block NCACHE_VAR { section NonCacheable , section NonCacheable.init };
define block QACCESS_CODE { section CodeQuickAccess };
define block QACCESS_DATA { section DataQuickAccess };
@ -78,10 +86,14 @@ do not initialize { section .noinit };
place at address mem: m_interrupts_start { readonly section .intvec };
place in TEXT_region { readonly };
place in DATA_region { block RW };
place in DATA_region { block ZI };
place in DATA_region { last block HEAP };
place in DATA_region { block NCACHE_VAR };
place in DATA3_region { block RW };
place in DATA3_region { block ZI };
if (isdefinedsymbol(__heap_noncacheable__)) {
place in NCACHE_region { last block HEAP };
} else {
place in DATA3_region { last block HEAP };
}
place in NCACHE_region { block NCACHE_VAR };
place in TEXT_region { block QACCESS_CODE };
place in DATA_region { block QACCESS_DATA };
place in CSTACK_region { block CSTACK };

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<fileVersion>3</fileVersion>
<fileVersion>4</fileVersion>
<configuration>
<name>rtthread</name>
<toolchain>
@ -11,7 +11,7 @@
<name>C-SPY</name>
<archiveVersion>2</archiveVersion>
<data>
<version>32</version>
<version>33</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -36,7 +36,7 @@
</option>
<option>
<name>MacFile</name>
<state></state>
<state>C:\XGW\IARWorkspace\rt-thread-imxrt\bsp\imxrt\imxrt1170-nxp-evk\m7\evkbmimxrt1170_connect_cm7.mac</state>
</option>
<option>
<name>MemOverride</name>
@ -44,7 +44,7 @@
</option>
<option>
<name>MemFile</name>
<state>$TOOLKIT_DIR$\CONFIG\debugger\NXP\MIMXRT1176xxxA_M7.ddf</state>
<state>$TOOLKIT_DIR$\config\debugger\NXP\MIMXRT1176xxxA_M7.ddf</state>
</option>
<option>
<name>RunToEnable</name>
@ -84,11 +84,11 @@
</option>
<option>
<name>OCDynDriverList</name>
<state>JLINK_ID</state>
<state>CMSISDAP_ID</state>
</option>
<option>
<name>OCLastSavedByProductVersion</name>
<state>9.30.1.50052</state>
<state>9.40.1.63870</state>
</option>
<option>
<name>UseFlashLoader</name>
@ -222,6 +222,38 @@
<name>OCTpiuBaseOption</name>
<state>1</state>
</option>
<option>
<name>OCOverrideSlave</name>
<state>0</state>
</option>
<option>
<name>OCOverrideSlavePath</name>
<state></state>
</option>
<option>
<name>C_32_64Device</name>
<state>1</state>
</option>
<option>
<name>AuthEnable</name>
<state>0</state>
</option>
<option>
<name>AuthSdmSelection</name>
<state>1</state>
</option>
<option>
<name>AuthSdmManifest</name>
<state></state>
</option>
<option>
<name>AuthSdmExplicitLib</name>
<state></state>
</option>
<option>
<name>AuthEnforce</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
@ -296,7 +328,7 @@
<option>
<name>CMSISDAPResetList</name>
<version>1</version>
<state>4</state>
<state>1</state>
</option>
<option>
<name>CMSISDAPHWResetDuration</name>
@ -381,27 +413,27 @@
</option>
<option>
<name>CatchMMERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchNOCPERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchCHKERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchSTATERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchBUSERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchINTERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchSFERR</name>
@ -409,7 +441,7 @@
</option>
<option>
<name>CatchHARDERR</name>
<state>1</state>
<state>0</state>
</option>
<option>
<name>CatchDummy</name>
@ -457,6 +489,39 @@
</option>
</data>
</settings>
<settings>
<name>E2_ID</name>
<archiveVersion>2</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>E2PowerFromProbe</name>
<state>1</state>
</option>
<option>
<name>CE2UsbSerialNo</name>
<state></state>
</option>
<option>
<name>CE2IdCodeEditB</name>
<state>0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF</state>
</option>
<option>
<name>CE2LogFileCheck</name>
<state>0</state>
</option>
<option>
<name>CE2LogFileEditB</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>OCDriverInfo</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
<name>GDBSERVER_ID</name>
<archiveVersion>2</archiveVersion>
@ -1072,7 +1137,7 @@
<name>STLINK_ID</name>
<archiveVersion>2</archiveVersion>
<data>
<version>7</version>
<version>8</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -1187,9 +1252,17 @@
</option>
<option>
<name>CCSTLinkProbeList</name>
<version>1</version>
<version>2</version>
<state>2</state>
</option>
<option>
<name>CCSTLinkTargetVccEnable</name>
<state>1</state>
</option>
<option>
<name>CCSTLinkTargetVoltage</name>
<state>3.3</state>
</option>
</data>
</settings>
<settings>
@ -1417,7 +1490,7 @@
</option>
<option>
<name>CCXds100ResetList</name>
<version>0</version>
<version>1</version>
<state>0</state>
</option>
<option>

View File

@ -1,5 +1,5 @@
<project>
<fileVersion>3</fileVersion>
<fileVersion>4</fileVersion>
<configuration>
<name>rtthread</name>
<toolchain>
@ -10,7 +10,7 @@
<name>General</name>
<archiveVersion>3</archiveVersion>
<data>
<version>35</version>
<version>36</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -69,7 +69,7 @@
</option>
<option>
<name>OGLastSavedByProductVersion</name>
<state>9.30.1.50052</state>
<state>9.40.1.63870</state>
</option>
<option>
<name>OGChipSelectEditMenu</name>
@ -97,7 +97,7 @@
</option>
<option>
<name>GBECoreSlave</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -114,7 +114,7 @@
</option>
<option>
<name>CoreVariant</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -137,7 +137,7 @@
</option>
<option>
<name>GFPUCoreSlave2</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -210,13 +210,18 @@
<name>FPU64</name>
<state>1</state>
</option>
<option>
<name>OG_32_64DeviceCoreSlave</name>
<version>33</version>
<state>41</state>
</option>
</data>
</settings>
<settings>
<name>ICCARM</name>
<archiveVersion>2</archiveVersion>
<data>
<version>37</version>
<version>38</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -237,7 +242,6 @@
<state>XIP_EXTERNAL_FLASH=1</state>
<state>ARM_MATH_CM7</state>
<state>USE_SDRAM</state>
<state>SOC_IMXRT1170_SERIES</state>
<state>ENDIANNESS</state>
<state>USE_RTOS</state>
<state>__RTTHREAD__</state>
@ -367,8 +371,8 @@
<state>$PROJ_DIR$\..\..\libraries\MIMXRT1170\CMSIS\Include</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\extension\fcntl\octal</state>
<state>$PROJ_DIR$\..\..\..\..\components\drivers\usb\usbhost\include</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\io\stdio</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\io\poll</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\io\epoll</state>
<state>$PROJ_DIR$\..\..\libraries\MIMXRT1170\MIMXRT1176\drivers\cm7</state>
<state>$PROJ_DIR$\..\..\libraries\drivers</state>
<state>$PROJ_DIR$\..\..\..\..\libcpu\arm\cortex-m7</state>
@ -383,6 +387,7 @@
<state>$PROJ_DIR$\..\..\..\..\components\drivers\usb\usbhost\class</state>
<state>$PROJ_DIR$\board\ports</state>
<state>$PROJ_DIR$\applications</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\io\eventfd</state>
<state>$PROJ_DIR$\..\..\..\..\include</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\include</state>
<state>$PROJ_DIR$\..\..\..\..\components\libc\posix\ipc</state>
@ -500,13 +505,21 @@
<name>CCStackProtection</name>
<state>0</state>
</option>
<option>
<name>CCPointerAutentiction</name>
<state>0</state>
</option>
<option>
<name>CCBranchTargetIdentification</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>AARM</name>
<archiveVersion>2</archiveVersion>
<data>
<version>11</version>
<version>12</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -666,6 +679,10 @@
<name>PreInclude</name>
<state />
</option>
<option>
<name>A_32_64Device</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
@ -704,18 +721,10 @@
<data>
<extensions />
<cmdline />
<hasPrio>208</hasPrio>
<hasPrio>1</hasPrio>
<buildSequence>inputOutputBased</buildSequence>
</data>
</settings>
<settings>
<name>BUILDACTION</name>
<archiveVersion>1</archiveVersion>
<data>
<prebuild />
<postbuild />
</data>
</settings>
<settings>
<name>ILINK</name>
<archiveVersion>0</archiveVersion>
@ -797,7 +806,7 @@
</option>
<option>
<name>IlinkIcfFile</name>
<state>$PROJ_DIR$\board\linker_scripts\link.icf</state>
<state>$PROJ_DIR$\board\linker_scripts\link_ram.icf</state>
</option>
<option>
<name>IlinkIcfFileSlave</name>
@ -1111,6 +1120,11 @@
</option>
</data>
</settings>
<settings>
<name>BUILDACTION</name>
<archiveVersion>2</archiveVersion>
<data />
</settings>
</configuration>
<group>
<name>Applications</name>
@ -1126,9 +1140,6 @@
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\cctype.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\cstdio.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\cstdlib.c</name>
</file>
@ -1138,6 +1149,9 @@
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\ctime.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\cunistd.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\libc\compilers\common\cwchar.c</name>
</file>
@ -1171,6 +1185,9 @@
</group>
<group>
<name>CPU</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\libcpu\arm\common\atomic_arm.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\libcpu\arm\common\div0.c</name>
</file>
@ -1189,6 +1206,9 @@
</group>
<group>
<name>DeviceDrivers</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\drivers\core\device.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\drivers\ipc\completion.c</name>
</file>
@ -1285,9 +1305,6 @@
<file>
<name>$PROJ_DIR$\..\..\..\..\src\components.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\src\device.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\src\idle.c</name>
</file>
@ -1382,10 +1399,10 @@
<group>
<name>SAL</name>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\net\netdev\src\netdev_ipaddr.c</name>
<name>$PROJ_DIR$\..\..\..\..\components\net\netdev\src\netdev.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\components\net\netdev\src\netdev.c</name>
<name>$PROJ_DIR$\..\..\..\..\components\net\netdev\src\netdev_ipaddr.c</name>
</file>
</group>
<group>

View File

@ -20,8 +20,10 @@
/* kservice optimization */
#define RT_DEBUG
#define RT_DEBUG_COLOR
#define RT_USING_DEBUG
#define RT_DEBUGING_COLOR
#define RT_DEBUGING_CONTEXT
#define RT_DEBUGING_INIT
/* Inter-Thread communication */
@ -33,7 +35,6 @@
/* Memory Management */
#define RT_PAGE_MAX_ORDER 11
#define RT_USING_MEMPOOL
#define RT_USING_MEMHEAP
#define RT_MEMHEAP_FAST_MODE
@ -47,7 +48,14 @@
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_VER_NUM 0x50000
#define RT_VER_NUM 0x50001
#define RT_USING_CACHE
#define RT_USING_HW_ATOMIC
#define RT_USING_CPU_FFS
#define ARCH_ARM
#define ARCH_ARM_CORTEX_M
#define ARCH_ARM_CORTEX_FPU
#define ARCH_ARM_CORTEX_M7
/* RT-Thread Components */
@ -69,6 +77,9 @@
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
/* DFS: device virtual file system */
/* Device Drivers */
#define RT_USING_DEVICE_IPC
@ -87,7 +98,14 @@
/* C/C++ and POSIX layer */
#define RT_LIBC_DEFAULT_TIMEZONE 8
/* ISO-ANSI C layer */
/* Timezone and Daylight Saving Time */
#define RT_LIBC_USING_LIGHT_TZ_DST
#define RT_LIBC_TZ_DEFAULT_HOUR 8
#define RT_LIBC_TZ_DEFAULT_MIN 0
#define RT_LIBC_TZ_DEFAULT_SEC 0
/* POSIX (Portable Operating System Interface) layer */
@ -127,6 +145,9 @@
/* Wiced WiFi */
/* CYW43012 WiFi */
/* IoT Cloud */
@ -196,7 +217,7 @@
/* Arduino libraries */
/* Projects */
/* Projects and Demos */
/* Sensors */
@ -227,6 +248,8 @@
/* Uncategorized */
#define SOC_IMXRT1170_SERIES
/* Hardware Drivers Config */
#define BSP_USING_QSPIFLASH

View File

@ -24,7 +24,7 @@ elif CROSS_TOOL == 'keil':
EXEC_PATH = r'C:/Keil_v5'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iccarm'
EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.3'
EXEC_PATH = r'C:/Program Files/IAR Systems/Embedded Workbench 9.2'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
@ -145,7 +145,7 @@ elif PLATFORM == 'iccarm':
else:
CFLAGS += ' -Oh'
LFLAGS = ' --config "board/linker_scripts/link.icf"'
LFLAGS = ' --config "board/linker_scripts/link_ram.icf"'
LFLAGS += ' --redirect _Printf=_PrintfTiny'
LFLAGS += ' --redirect _Scanf=_ScanfSmall'
LFLAGS += ' --entry __iar_program_start'

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<fileVersion>3</fileVersion>
<fileVersion>4</fileVersion>
<configuration>
<name>rtthread</name>
<toolchain>
@ -11,7 +11,7 @@
<name>C-SPY</name>
<archiveVersion>2</archiveVersion>
<data>
<version>32</version>
<version>33</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -44,7 +44,7 @@
</option>
<option>
<name>MemFile</name>
<state>$TOOLKIT_DIR$\CONFIG\debugger\NXP\MIMXRT1176xxxA_M7.ddf</state>
<state>$TOOLKIT_DIR$\config\debugger\NXP\MIMXRT1176xxxA_M7.ddf</state>
</option>
<option>
<name>RunToEnable</name>
@ -88,7 +88,7 @@
</option>
<option>
<name>OCLastSavedByProductVersion</name>
<state>9.30.1.50052</state>
<state>9.40.1.63870</state>
</option>
<option>
<name>UseFlashLoader</name>
@ -222,6 +222,38 @@
<name>OCTpiuBaseOption</name>
<state>1</state>
</option>
<option>
<name>OCOverrideSlave</name>
<state>0</state>
</option>
<option>
<name>OCOverrideSlavePath</name>
<state></state>
</option>
<option>
<name>C_32_64Device</name>
<state>1</state>
</option>
<option>
<name>AuthEnable</name>
<state>0</state>
</option>
<option>
<name>AuthSdmSelection</name>
<state>1</state>
</option>
<option>
<name>AuthSdmManifest</name>
<state></state>
</option>
<option>
<name>AuthSdmExplicitLib</name>
<state></state>
</option>
<option>
<name>AuthEnforce</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
@ -457,6 +489,39 @@
</option>
</data>
</settings>
<settings>
<name>E2_ID</name>
<archiveVersion>2</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>E2PowerFromProbe</name>
<state>1</state>
</option>
<option>
<name>CE2UsbSerialNo</name>
<state></state>
</option>
<option>
<name>CE2IdCodeEditB</name>
<state>0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF</state>
</option>
<option>
<name>CE2LogFileCheck</name>
<state>0</state>
</option>
<option>
<name>CE2LogFileEditB</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>OCDriverInfo</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
<name>GDBSERVER_ID</name>
<archiveVersion>2</archiveVersion>
@ -1072,7 +1137,7 @@
<name>STLINK_ID</name>
<archiveVersion>2</archiveVersion>
<data>
<version>7</version>
<version>8</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -1187,9 +1252,17 @@
</option>
<option>
<name>CCSTLinkProbeList</name>
<version>1</version>
<version>2</version>
<state>2</state>
</option>
<option>
<name>CCSTLinkTargetVccEnable</name>
<state>1</state>
</option>
<option>
<name>CCSTLinkTargetVoltage</name>
<state>###Uninitialized###</state>
</option>
</data>
</settings>
<settings>
@ -1417,7 +1490,7 @@
</option>
<option>
<name>CCXds100ResetList</name>
<version>0</version>
<version>1</version>
<state>0</state>
</option>
<option>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<fileVersion>3</fileVersion>
<fileVersion>4</fileVersion>
<configuration>
<name>rtthread</name>
<toolchain>
@ -11,7 +11,7 @@
<name>General</name>
<archiveVersion>3</archiveVersion>
<data>
<version>35</version>
<version>36</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -70,7 +70,7 @@
</option>
<option>
<name>OGLastSavedByProductVersion</name>
<state>9.30.1.50052</state>
<state>9.40.1.63870</state>
</option>
<option>
<name>OGChipSelectEditMenu</name>
@ -98,7 +98,7 @@
</option>
<option>
<name>GBECoreSlave</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -115,7 +115,7 @@
</option>
<option>
<name>CoreVariant</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -138,7 +138,7 @@
</option>
<option>
<name>GFPUCoreSlave2</name>
<version>32</version>
<version>33</version>
<state>41</state>
</option>
<option>
@ -211,13 +211,18 @@
<name>FPU64</name>
<state>1</state>
</option>
<option>
<name>OG_32_64DeviceCoreSlave</name>
<version>33</version>
<state>41</state>
</option>
</data>
</settings>
<settings>
<name>ICCARM</name>
<archiveVersion>2</archiveVersion>
<data>
<version>37</version>
<version>38</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -459,13 +464,21 @@
<name>CCStackProtection</name>
<state>0</state>
</option>
<option>
<name>CCPointerAutentiction</name>
<state>0</state>
</option>
<option>
<name>CCBranchTargetIdentification</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>AARM</name>
<archiveVersion>2</archiveVersion>
<data>
<version>11</version>
<version>12</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
@ -625,6 +638,10 @@
<name>PreInclude</name>
<state></state>
</option>
<option>
<name>A_32_64Device</name>
<state>1</state>
</option>
</data>
</settings>
<settings>
@ -663,18 +680,10 @@
<data>
<extensions></extensions>
<cmdline></cmdline>
<hasPrio>208</hasPrio>
<hasPrio>1</hasPrio>
<buildSequence>inputOutputBased</buildSequence>
</data>
</settings>
<settings>
<name>BUILDACTION</name>
<archiveVersion>1</archiveVersion>
<data>
<prebuild></prebuild>
<postbuild></postbuild>
</data>
</settings>
<settings>
<name>ILINK</name>
<archiveVersion>0</archiveVersion>
@ -756,7 +765,7 @@
</option>
<option>
<name>IlinkIcfFile</name>
<state>$PROJ_DIR$\board\linker_scripts\link.icf</state>
<state>$PROJ_DIR$\board\linker_scripts\link_ram.icf</state>
</option>
<option>
<name>IlinkIcfFileSlave</name>
@ -1070,5 +1079,10 @@
</option>
</data>
</settings>
<settings>
<name>BUILDACTION</name>
<archiveVersion>2</archiveVersion>
<data />
</settings>
</configuration>
</project>

View File

@ -0,0 +1,681 @@
/****************************************************************************
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef ELM_H_
#define ELM_H_
#ifdef __cplusplus
extern "C" {
#endif
#define ELM_VERSION 0x00010000 /* Current Version: 1.0. */
#define ELM_NULL_HANDLE 0 /*! NULL object handle, represent a void object. */
/*!
@typedef ELM_EVO_PROP_BIT
evo property bits to control evo manipulation.
*/
typedef enum {
ELM_PROP_ROTATE_BIT = 1 << 0, /*! rotate bit of evo/ego/ebo transformation property. */
ELM_PROP_TRANSFER_BIT = 1 << 1, /*! transfer bit of evo/ego/ebo transformation property. */
ELM_PROP_SCALE_BIT = 1 << 2, /*! scale bit of evo/ego/ebo transformation property. */
ELM_PROP_BLEND_BIT = 1 << 3, /*! blending bit of evo/ebo rendering property. */
ELM_PROP_QUALITY_BIT = 1 << 4, /*! quality bit of evo/ebo rendering property. */
ELM_PROP_FILL_BIT = 1 << 5, /*! fill rule bit of evo rendering property. */
ELM_PROP_COLOR_BIT = 1 << 6, /*! fill color bit of evo rendering property. */
ELM_PROP_PAINT_BIT = 1 << 7, /*! paint type bit of evo. */
ELM_PROP_ALL_BIT = 0xFFFFFFFF, /*! all transformation property bits of evo. */
} ELM_EVO_PROP_BIT;
/*!
@typedef ELM_EVO_BLEND
The blending property of the evo object when it's drawn.
D is Destination color, S is Source color;
Da is Destination alpha, S is Source alpha.
*/
typedef enum {
ELM_BLEND_NONE = 0, /*! D = S. */
ELM_BLEND_SRC_OVER, /*! D = S + (1 - Sa) * D */
ELM_BLEND_DST_OVER, /*! D = (1 - Da) * S + D */
ELM_BLEND_SRC_IN, /*! D = Da * S */
ELM_BLEND_DST_IN, /*! D = Sa * D */
ELM_BLEND_SCR, /*! D = S + D - S * D */
ELM_BLEND_MUL, /*! D = S * (1 - Da) + D * (1 - Sa) + S * D */
ELM_BLEND_ADD, /*! S + D */
ELM_BLEND_SUB /*! D * (1 - S) */
} ELM_BLEND;
/*!
@typedef ELM_EVO_QUALITY
The drawing quality of the evo object.
*/
typedef enum {
ELM_QUALITY_LOW = 0, /*! NOAA for evo, POINT SAMPLE for ebo. */
ELM_QUALITY_MED = 1, /*! 2XAA for evo, LINEAR SAMPLE for ebo. */
ELM_QULIATY_HI = 2, /*! 4XAA for evo, BI-LINEAR SAMPLE for ebo. */
} ELM_QUALITY;
/*!
@typedef ELM_PAINT_TYPE
Those are types for evo fill paint.
COLOR means solid color fill;
PATTERN means fill with an image (evo);
GRADIENT means fill with linear gradient.
*/
typedef enum {
ELM_PAINT_COLOR = 0, /*! Paint evo with solid color */
ELM_PAINT_PATTERN = 1, /*! Paint evo with ebo */
ELM_PAINT_GRADIENT = 2, /*! Paint evo with a linear gradient built-in evo object */
ELM_PAINT_RADIAL_GRADIENT = 3, /*! Paint evo with a radial gradient built-in evo object */
ELM_PAINT_TEXT = 4, /*! Paint evo-text */
} ELM_PAINT_TYPE;
/*!
@typedef ELM_PATTERN_MODE
Those are enum types for pattern fill mode.
COLOR means fill the area outside the pattern with a solid color;
PAD means extend the border color to the area outside the pattern.
*/
typedef enum {
ELM_PATTERN_MODE_COLOR = 0,
ELM_PATTERN_MODE_PAD = 1,
} ELM_PATTERN_MODE;
/*!
@typedef ELM_EVO_FILL
The filling rule of for an evo object.
EO = EVEN_ODD;
NZ = NONE_ZERO;
*/
typedef enum {
ELM_EVO_FILL_NZ = 0, /*! none-zero fill rule */
ELM_EVO_FILL_EO = 1, /*! Even-odd fill rule */
} ELM_EVO_FILL;
/*!
@typedef ELM_EVO_TYPE
the type of an evo object. could be pathes, images, or a group which contains other EVOs.
*/
typedef enum {
ELM_OBJECT_TYPE_EVO = 0, /*! elementary vector object, representing a path object. */
ELM_OBJECT_TYPE_EGO = 1, /*! elementary group object, containing multiple path objects. */
ELM_OBJECT_TYPE_EBO = 2, /*! elementary bitmap object, representing image data. */
ELM_OBJECT_TYPE_BUF = 3, /*! rendering buffer object, created by application. */
ELM_OBJECT_TYPE_FONT = 4, /*! elementary font object, representing character data. */
ELM_OBJECT_TYPE_TEXT = 5, /*! elementary text object, representing text data. */
} ELM_OBJECT_TYPE;
/*!
@typedef ELM_BUFFER_FORMAT
Enumeration for buffer format, all format name definiton is sequenced from LSB to MSB.
*/
typedef enum {
ELM_BUFFER_FORMAT_RGBA8888, /*! 32-bit RGBA format with 8 bits per color channel. Red is in bits 7:0, green in bits 15:8, blue in
bits 23:16, and the alpha channel is in bits 31:24. */
ELM_BUFFER_FORMAT_BGRA8888, /*! 32-bit RGBA format with 8 bits per color channel. Red is in bits 23:16, green in bits 15:8, blue in
bits 7:0, and the alpha channel is in bits 31:24. */
ELM_BUFFER_FORMAT_RGBX8888, /*! 32-bit RGBX format with 8 bits per color channel. Red is in bits 7:0, green in bits 15:8, blue in
bits 23:16, and the x channel is in bits 31:24. */
ELM_BUFFER_FORMAT_BGRX8888, /*! 32-bit RGBX format with 8 bits per color channel. Red is in bits 23:16, green in bits 15:8, blue in
bits 7:0, and the x channel is in bits 31:24. */
ELM_BUFFER_FORMAT_RGB565, /*! 16-bit RGB format with 5 and 6 bits per color channel. Red is in bits 4:0, green in bits 10:5, and
the blue color channel is in bits 15:11. */
ELM_BUFFER_FORMAT_BGR565, /*! 16-bit RGB format with 5 and 6 bits per color channel. Red is in bits 15:11, green in bits 10:5,
and the blue color channel is in bits 4:0. */
ELM_BUFFER_FORMAT_RGBA4444, /*! 16-bit RGBA format with 4 bits per color channel. Red is in bits 3:0, green in bits 7:4, blue in
bits 11:8 and the alpha channel is in bits 15:12. */
ELM_BUFFER_FORMAT_BGRA4444, /*! 16-bit RGBA format with 4 bits per color channel. Red is in bits 11:8, green in bits 7:4, blue in
bits 3:0 and the alpha channel is in bits 15:12. */
ELM_BUFFER_FORMAT_BGRA5551, /*! 16-bit RGBA format with 4 bits per color channel. Red is in bits 14:10, green in bits 9:5, blue in
bits 4:0 and the alpha channel is in bit 15:15. */
ELM_BUFFER_FORMAT_INDEX_1, /*! 1-bit indexed format. */
ELM_BUFFER_FORMAT_INDEX_2, /*! 2-bits indexed format. */
ELM_BUFFER_FORMAT_INDEX_4, /*! 4-bits indexed format. */
ELM_BUFFER_FORMAT_INDEX_8, /*! 8-bits indexed format. */
} ELM_BUFFER_FORMAT;
/*!
@typedef ElmHandle
common handle type for object reference.
*/
typedef unsigned int ElmHandle;
/*!
@typedef ElmVecObj
evo object handle (elemtry vector object). Created from an external binary evo file.
*/
typedef ElmHandle ElmVecObj;
/*!
@typedef ElmBitmapObj
ebo object handle (elementry image object). Created from an external ebo file.
*/
typedef ElmHandle ElmBitmapObj;
/*!
@typedef ElmGroupObj
group object handle. Create from an external ego file.
*/
typedef ElmHandle ElmGroupObj;
/*!
@typedef ElmBuffer
render buffer object handle.
*/
typedef ElmHandle ElmBuffer;
#define TRUE 1
#define FALSE 0
/*!
@typedef BOOL
boolean type define.
*/
typedef unsigned int BOOL;
/*!
@abstract Initialize Elementary context.
@discussion
It should be called as the first function of Elemenatary libary, which initializes the library. Currently
Elementary library doesn't support context concept, neigher multi-threading. Elementary library defines
origin of coordinate system is at top-left.
@param none
@return none
*/
BOOL ElmInitialize(uint32_t width, uint32_t height);
/*!
@abstract Terminate Elementary context.
@discussion
This should be called when an app exits. It frees all the resource.
@param none
@return none
*/
void ElmTerminate(void);
/*!
@abstract Create an elementary object from an existing binary file.
@discussion
This function creates an elementary object from the file whose file name is specified by param name.
Caller must match type with the binary file, otherwise create mail fail by returning ELM_NULL_HANDLE.
@param type
Specify what type of object to be created.
@param name
The name of the binary resource file.
@return ElmHandle
An object handle depending on the corresponding type. If type mismatches, it
returns ELM_NULL_HANDLE.
*/
ElmHandle ElmCreateObjectFromFile(ELM_OBJECT_TYPE type, const char *name);
/*!
@abstract Create an elementary object from build-in data within the appplication.
@discussion
This function creates an elementar object from local data pointer, which is specially useful for environment without filesystem support.
@param type
Specify what type of object to be created.
@param data
The pointer to the binary data which has exactly same layout as external resource file.
@return ElmHandle
An object handle depending on the corresponding type. If type mismatches with the binary data, it
returns ELM_NULL_HANDLE.
*/
ElmHandle ElmCreateObjectFromData(ELM_OBJECT_TYPE type, void *data, int size);
/*!
@abstract Rotate a graphics object with centain degree
@discussion
This function sets an evo/ebo/ego object rotated with specified angle. Without reset, these setting will be
accumulated.
@param obj
The graphics object will be rotated.
@param angle
A radian value to be applied on the evo object.
@return bool
Rotate is set successfully.
*/
BOOL ElmRotate(ElmHandle obj, float angle);
/*!
@abstract Transfer an graphics object at different directions.
@discussion
This function put an evo/ebo/ego object away at different directions. Without reset, the setting will be
accumulated.
@param obj
The graphics object will be transfered.
@param x
The units in pixel of X direction.
@param y
The units in pixel of Y direction.
@return bool
Transfer is set successfully.
*/
BOOL ElmTransfer(ElmHandle obj, int x, int y);
/*!
@abstract Scale an graphics object at different directions.
@discussion
This function scale up or down an evo/ego/ebo object at different directions. Without reset, the setting will
be accumateled.
@param obj
The graphics object which is targeted to manipulate.
@param x
The scale ratio in X direction.
@param y
The scale ratio in Y direction.
@return bool
Scale is set succefully.
*/
BOOL ElmScale(ElmHandle obj, float x, float y);
/*!
@abstract Reset the attribute of a graphics object for specified property bit.
@discussion
This funcion resets specified property for an elementary object. It can be applied all types of objects.
But some properties are only valid for centain types of objects. If the function is called to reset an invalid
property for this type of object, it will be siliently ignored.
After reset, the specifed property of an evo/ebo/ego object is set to the initial state. The initial states are decided
by the binary resource file. The resource creator should set right value for all properties if they want to directly render
the object without any adjustment in application. There is one issue, at present, application has no way to query current value
of each property, is it required?
@param obj
The graphics object which is targeted to manipulate.
@param mask
Specify which property or properties need to reset to initial value.
@return bool
Reset is done successfully. If some mask is not valid for this type of object, it would return false.
*/
BOOL ElmReset(ElmHandle obj, ELM_EVO_PROP_BIT mask);
/*!
@abstract Draw a graphics object onto current render target
@discussion
This is an enssentail function to do the real job, it takes all current setting of the elementary object and
render into theb buffer target.
@param buffer
The render target that an elmentary object will be rendered into.
@param obj
The elmentary object will be draw into render target.
@return bool
The draw operation for this elmentary object is sucessful.
*/
BOOL ElmDraw(ElmBuffer buffer, ElmHandle object);
/*!
@abstract Set the rendering quality of an graphics object.
@discussion
This function sets the rendering quality of an evo/ebo object. Avaliable quality setting contains:
ELM_EVO_QUALITY_LOW, ELM_EVO_QUALITY_MED, ELM_EVO_QUALITY_HI. This function is only applied to an evo or an ebo.
Group object can't be set quality. It always use the setting from its binary.
@param obj
The elementary object.
@param quality
The quality enum.
@return bool
The operation for this object is sucessful, for group object and invalid enum, would return false.
*/
BOOL ElmSetQuality(ElmHandle obj, ELM_QUALITY quality);
/*!
@abstract Set the fill rule of an evo object.
@discussion
This function sets the fill rule of an elementary object. Avaliable quality setting contains:
ELM_EVO_EO, ELM_EVO_NZ. It only applies to evo object.
@param evo
The evo object.
@param fill
The fill rule enum.
@return bool
The operation for this evo is sucessful. For non-evo object an ENUM is not a valid enum, would return false.
*/
BOOL ElmSetFill(ElmVecObj evo, ELM_EVO_FILL fill);
/*!
@abstract Set the blending mode of an evo/ebo object.
@discussion
This function sets the blending mode of an evo/ebo object. It's not applied to group object.
@param obj
The graphics object.
@param blend
The blending mode enum.
@return bool
The operation for this evo/ebo is sucessful. If object is a group object or blend mode is not a legal one, it would return false.
*/
BOOL ElmSetBlend(ElmHandle obj, ELM_BLEND blend);
/*!
@abstract Set the solid fill color of an evo object.
@discussion
This function sets the solid fill color of an evo object.
@param evo
The evo object.
@param color
The uint32 color value in rgba order.
@return bool
The operation for this evo is sucessful. If the object is not a evo object, it would return false.
*/
BOOL ElmSetColor(ElmVecObj evo, uint32_t color);
/*!
@abstract Set the image paint fill of an evo.
@discussion
This function sets the image pattern for filling an evo. The image pattern
is a loaded ebo. The ebo's transformation is applied when drawing the evo.
@param evo
The evo object.
@param pattern
The image pattern to be set for the evo.
@return bool
The operation is successful or not.
*/
BOOL ElmSetPattern(ElmVecObj evo, ElmBitmapObj pattern);
/*!
@abstract Set the image paint fill of an evo.
@discussion
This function sets the image pattern for filling an evo. The image pattern
is a loaded ebo. The ebo's transformation is applied when drawing the evo.
@param evo
The evo object.
@param pattern
The image pattern to be set for the evo.
@return bool
The operation is successful or not.
*/
BOOL ElmSetPatternMode(ElmVecObj evo, ELM_PATTERN_MODE mode, uint32_t color);
/*!
@abstract Set the paint type of an evo.
@discussion
This function selects the paint type for evo to use. An evo may have 3 types
of paint: COLOR, PATTERN, and LINEAR GRADIENT. The Linear graident is always
a built-in resource, which can not be altered. If a binary resource doesn't
have built-in gradient paint resource, it can't be selected as the paint source.
Solid color is also a built-in attribute, but it can be changed by ElmSetColor().
Paint with a pattern always need an external ebo object, which is impossible
to be embedded in resource file,i.e. ebo object. Before select paint type to
be PATTERN, ElmSetPattern() must be called to attach an EBO to an EVO.
@param evo
The evo object.
@param type
The paint type to be set for the evo.
@return bool
The operation is successful or not.
If the corresponding type is not avaiable for the evo, it returns false and
type paint type falls back to COLOR.
*/
BOOL ElmSetPaintType(ElmVecObj evo, ELM_PAINT_TYPE type);
/*!
@abstract Create internal render buffer.
@discussion
This functiois is to create an internal render buffer for Elementary rendering, ussually it's not for direct display.
The buffer which is displayed on pannel is wrapped up by another API, whose address is managed by display controller side.
@param width
The buffer's width.
@param height
The buffer's height.
@param format
The buffer's format, check enumeration of ELM_BUFFER_FORMAT.
@return
The buffer handle.
*/
ElmBuffer ElmCreateBuffer(unsigned int width, unsigned int height, ELM_BUFFER_FORMAT format);
/*!
@abstract Wrap a customized buffer.
@discussion
The application may wrap a user created buffer by giving the information of
the buffer including the size, the memory addresses and format. E.g., the
application can wrap a system framebuffer thus ELM can directly render onto
the screen.
@return
The buffer handle.
*/
ElmBuffer ElmWrapBuffer(int width, int height, int stride,
void *logical, uint32_t physical,
ELM_BUFFER_FORMAT format);
/*!
@abstract Get buffer address.
@discussion
The function is to get the address of ElmBuffer.
@return
The buffer address.
*/
uint32_t ElmGetBufferAddress(ElmBuffer buffer);
/*!
@abstract Destroy a render buffer.
@discussion
This function is to release all internal resource inside Elementary libary belonging to this buffer.
Applicatoin need make sure the buffer is not being used by elmentary library any more when calling this function.
@param buffer
The render buffer handle
@return
If destroying is completed successfully.
*/
BOOL ElmDestroyBuffer(ElmBuffer buffer);
/*!
@abstract Save a buffer to PNG file.
@discussion
This function can save the buffer into a PNG file.
@param buffer
The render buffer handle.
@param name
The name of the PNG file to sve.
@return
Save OK or NOT.
*/
BOOL ElmSaveBuffer(ElmBuffer buffer, const char *name);
/*!
@abstract Clear a render buffer with specified color and dimension.
@discussion
This function is called to clear full or partial of the buffer. If the rectangle is out of buffer space, the intersect portion will be cleared.
@param buffer
A render buffer handle.
@param color
Clear color value.
@param x
x origin of partical clear rectangle.
@param y
y origin of partial clear rectangle.
@param width
width of partical clear rectangle.
@param height
height of partical clear rectangle.
@param full
Flag to indicate a full buffer clear. If true, the dimension parameters will be ignored.
@return bool
Indicate the clear operation is set up correctly.
*/
BOOL ElmClear(ElmBuffer buffer, uint32_t color, uint32_t x, uint32_t y, uint32_t width, uint32_t height, BOOL full);
/*!
@abstract Destroy an ELM object.
@discussion
This function is to release all internal resource inside Elementary libary belonging to this object.
Applicatoin need make sure the object is not being used by elmentary library any more when calling this function.
If an EBO is being destroyed and it's attached to one EVO, it need to guarantee that EVO is not being used by elementary library too.
@param object
The object handle
@return
If destroying is completed successfully.
*/
BOOL ElmDestroyObject(ElmHandle object);
/*!
@abstract Finish all rendering on GPU issued before this call.
@discussion
This function tells the engine that it has finished the frame data and GPU can draw it now. It's blocked until GPU rendering done.
@return
If the opeartion is successfully done or not.
*/
BOOL ElmFinish();
/*!
@abstract Flush all rendering command to GPU issued before this call.
@discussion
This function tells the engine to start kicking off command to GPU side, it will return immediately after firing off GPU.
@return
If the opeartion is successfully done or not.
*/
BOOL ElmFlush();
/*!
@abstract Query the paint color of an evo object.
*/
BOOL ElmGetColor(ElmVecObj evoHandle,uint32_t *color);
/*!
@abstract Query the vectory path count of an EGO object. If the given object
is an evo/ebo, the count is 0.
*/
uint32_t ElmGetVectorCount(ElmHandle handle);
/*!
@abstract Query the type of an object (by handle).
*/
ELM_OBJECT_TYPE ElmGetObjectType(ElmHandle handle);
/*!
@abstract Set the current vectory object index to operate on.
*/
BOOL ElmSetCurrentVector(int32_t id);
BOOL ElmScalePaint(ElmHandle handle, float sx, float sy);
BOOL ElmRotatePaint(ElmHandle handle, float degrees);
BOOL ElmTranslatePaint(ElmHandle handle, float tx, float ty);
/*!
@abstract Get handle of the framebuffer.
*/
ElmBuffer ElmGetBuffer(vg_lite_buffer_t *buffer);
#ifdef __cplusplus
}
#endif
#endif /* ELM_H_ */

View File

@ -0,0 +1,221 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "buf_reader.h"
#include "stdio.h"
#include "string.h"
#define DBG_TRACE(x) printf x
static int _is_buffered_handle_valid(bufferred_reader_t *fd)
{
if (fd == NULL)
return E_BUF_INVALID_HANDLE;
if ( fd->data_buf == NULL )
return E_BUF_INVALID_HANDLE;
if ( fd->size < 0 )
return E_BUF_INVALID_HANDLE;
if ( fd->index > fd->size )
return E_BUF_INVALID_HANDLE;
return 0;
}
/* Write buffered IO operations */
int bufferred_fopen(bufferred_reader_t *fd, char *buf, int size)
{
if (fd == NULL)
return E_BUF_INVALID_HANDLE;
fd->data_buf = buf;
fd->size = size;
fd->index = 0;
if ( _is_buffered_handle_valid(fd)) {
return E_BUF_INVALID_HANDLE;
}
fd->is_valid = 1;
return 0;
}
int bufferred_ftell(bufferred_reader_t *fd)
{
if ( _is_buffered_handle_valid(fd)) {
return E_BUF_INVALID_HANDLE;
}
return fd->index;
}
int bufferred_fread(
void *ptr,
int size,
int nmemb,
bufferred_reader_t *fd
)
{
int to_copy = 0;
char *data_ptr = NULL;
char *buff = (char *)ptr;
int byte_to_read = size * nmemb;
if ( _is_buffered_handle_valid(fd)) {
return E_BUF_INVALID_HANDLE;
}
if ( buff == NULL ) {
return E_BUF_IO_INVALID_PARAMETERS;
}
if ( byte_to_read < 0 ) {
return E_BUF_IO_INVALID_PARAMETERS;
}
to_copy = (fd->size - fd->index);
data_ptr = fd->data_buf + fd->index;
if ( to_copy > byte_to_read )
to_copy = byte_to_read;
if (to_copy <= 0)
return -1; //EOF
memcpy(buff, data_ptr, to_copy);
fd->index += to_copy;
return 0;
}
int bufferred_fseek(
bufferred_reader_t *fd,
int offset,
int direction
)
{
if ( _is_buffered_handle_valid(fd)) {
return E_BUF_INVALID_HANDLE;
}
switch(direction)
{
case SEEK_SET:
fd->index = offset;
break;
case SEEK_CUR:
fd->index += offset;
break;
case SEEK_END:
fd->index = fd->size - offset;
break;
}
/* Clamp current offset */
if ( fd->index > fd->size ) {
DBG_TRACE(("WARNING: seeking beyond buffer size\n"));
fd->index = fd->size;
}
if ( fd->index < 0 ) {
DBG_TRACE(("WARNING: seeking beyond buffer size\n"));
fd->index = 0;
}
return 0;
}
int bufferred_fclose(bufferred_reader_t *fd)
{
if ( _is_buffered_handle_valid(fd)) {
return E_BUF_INVALID_HANDLE;
}
fd->size = -1;
fd->is_valid = 0;
return 0;
}
char *bufferred_fgets(char* buff, int len, bufferred_reader_t *fd)
{
char *ptr;
int i, j, valid_bytes;
if ( buff == NULL ) {
return NULL;
}
if ( len <= 0 ) {
return NULL;
}
if ( _is_buffered_handle_valid(fd)) {
return NULL;
}
/* Check how many bytes are available to read */
valid_bytes = fd->size - fd->index;
if ( len > 0 )
len -=1; /* fgets read one character less than buffer length */
if ( len > valid_bytes )
len = valid_bytes;
if ( valid_bytes <= 0 )
return NULL;
ptr = fd->data_buf + fd->index;
for(i=0; ptr[i] != '\0' && i < len; i++)
{
if ( ptr[i] == '\n' )
break;
if ( ptr[i] == '\r' )
break;
buff[i] = ptr[i];
}
buff[i] = '\0';
j = i;
/* skip trailing newline from file buffer */
if ( ptr[i] == '\r' )
i++;
if ( ptr[i] == '\n' )
i++;
fd->index += i;
/* Trim trailing spaces from output buffer */
for (i = j-1 ; i>0; i--) {
if (buff[i] == ' ')
buff[i] = '\0';
else
break;
}
return ptr;
}

View File

@ -0,0 +1,63 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/* Bufferred reader interface */
#ifndef _BUFFERRED_READER_
#define _BUFFERRED_READER_
typedef struct buffered_reader {
char *data_buf;
int size;
int index;
int is_valid;
} bufferred_reader_t;
#define E_BUF_IO_OUT_OF_MEMORY -10
#define E_BUF_IO_READ_ERROR -11
#define E_BUF_INVALID_HANDLE -12
#define E_BUF_IO_INVALID_PARAMETERS -13
int is_buffered_handle_valid(bufferred_reader_t *fd);
int bufferred_fopen(bufferred_reader_t *fd, char *buf, int size);
int bufferred_ftell(bufferred_reader_t *fd);
int bufferred_fread(
void *ptr,
int size,
int nmemb,
bufferred_reader_t *fd
);
int bufferred_fseek(
bufferred_reader_t *fd,
int offset,
int direction
);
int bufferred_fclose(bufferred_reader_t *fd);
char *bufferred_fgets(char* buff, int len, bufferred_reader_t *fd);
#endif //!_BUFFERRED_READER_

View File

@ -0,0 +1,474 @@
/*
* Copyright 2019-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <rtthread.h>
#include "display_support.h"
#include "fsl_gpio.h"
#include "fsl_mipi_dsi.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*
* The DPHY bit clock must be fast enough to send out the pixels, it should be
* larger than:
*
* (Pixel clock * bit per output pixel) / number of MIPI data lane
*
* Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure
* it is fast enough.
*/
#define DEMO_MIPI_DPHY_BIT_CLK_ENLARGE(origin) (((origin) / 8) * 9)
/*******************************************************************************
* Prototypes
******************************************************************************/
static void BOARD_PullPanelResetPin(bool pullUp);
static void BOARD_PullPanelPowerPin(bool pullUp);
static void BOARD_InitLcdifClock(void);
static void BOARD_InitMipiDsiClock(void);
static status_t BOARD_DSI_Transfer(dsi_transfer_t *xfer);
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t mipiDsiTxEscClkFreq_Hz;
static uint32_t mipiDsiDphyBitClkFreq_Hz;
static uint32_t mipiDsiDphyRefClkFreq_Hz;
static uint32_t mipiDsiDpiClkFreq_Hz;
const MIPI_DSI_Type g_mipiDsi = {
.host = DSI_HOST,
.apb = DSI_HOST_APB_PKT_IF,
.dpi = DSI_HOST_DPI_INTFC,
.dphy = DSI_HOST_DPHY_INTFC,
};
#if defined(VGLITE_USING_RK055AHD091)
static mipi_dsi_device_t dsiDevice = {
.virtualChannel = 0,
.xferFunc = BOARD_DSI_Transfer,
};
static const rm68200_resource_t rm68200Resource = {
.dsiDevice = &dsiDevice,
.pullResetPin = BOARD_PullPanelResetPin,
.pullPowerPin = BOARD_PullPanelPowerPin,
};
static display_handle_t rm68200Handle = {
.resource = &rm68200Resource,
.ops = &rm68200_ops,
};
#elif defined(VGLITE_USING_RK055MHD091)
static mipi_dsi_device_t dsiDevice = {
.virtualChannel = 0,
.xferFunc = BOARD_DSI_Transfer,
};
static const hx8394_resource_t hx8394Resource = {
.dsiDevice = &dsiDevice,
.pullResetPin = BOARD_PullPanelResetPin,
.pullPowerPin = BOARD_PullPanelPowerPin,
};
static display_handle_t hx8394Handle = {
.resource = &hx8394Resource,
.ops = &hx8394_ops,
};
#else
static mipi_dsi_device_t dsiDevice = {
.virtualChannel = 0,
.xferFunc = BOARD_DSI_Transfer,
};
static const rm68191_resource_t rm68191Resource = {
.dsiDevice = &dsiDevice,
.pullResetPin = BOARD_PullPanelResetPin,
.pullPowerPin = BOARD_PullPanelPowerPin,
};
static display_handle_t rm68191Handle = {
.resource = &rm68191Resource,
.ops = &rm68191_ops,
};
#endif
#if defined(VGLITE_USING_LCDIFV2)
static dc_fb_lcdifv2_handle_t s_dcFbLcdifv2Handle = {0};
static const dc_fb_lcdifv2_config_t s_dcFbLcdifv2Config = {
.lcdifv2 = DEMO_LCDIF,
.width = LCD_WIDTH,
.height = LCD_HEIGHT,
.hsw = LCD_HSW,
.hfp = LCD_HFP,
.hbp = LCD_HBP,
.vsw = LCD_VSW,
.vfp = LCD_VFP,
.vbp = LCD_VBP,
.polarityFlags = DEMO_LCDIF_POL_FLAGS,
.lineOrder = kLCDIFV2_LineOrderRGB,
/* CM4 is domain 1, CM7 is domain 0. */
#if (__CORTEX_M <= 4)
.domain = 1,
#else
.domain = 0,
#endif
};
const dc_fb_t g_dc = {
.ops = &g_dcFbOpsLcdifv2,
.prvData = &s_dcFbLcdifv2Handle,
.config = &s_dcFbLcdifv2Config,
};
#else
dc_fb_elcdif_handle_t s_dcFbElcdifHandle = {0}; /* The handle must be initialized to 0. */
const dc_fb_elcdif_config_t s_dcFbElcdifConfig = {
.elcdif = DEMO_LCDIF,
.width = LCD_WIDTH,
.height = LCD_HEIGHT,
.hsw = LCD_HSW,
.hfp = LCD_HFP,
.hbp = LCD_HBP,
.vsw = LCD_VSW,
.vfp = LCD_VFP,
.vbp = LCD_VBP,
.polarityFlags = DEMO_LCDIF_POL_FLAGS,
#if (!DEMO_USE_XRGB8888) && (DEMO_USE_LUT8)
.dataBus = kELCDIF_DataBus8Bit,
#else
.dataBus = kELCDIF_DataBus24Bit,
#endif
};
const dc_fb_t g_dc = {
.ops = &g_dcFbOpsElcdif,
.prvData = &s_dcFbElcdifHandle,
.config = &s_dcFbElcdifConfig,
};
#endif
/*******************************************************************************
* Code
******************************************************************************/
static void BOARD_PullPanelResetPin(bool pullUp)
{
if (pullUp)
{
GPIO_PinWrite(BOARD_MIPI_PANEL_RST_GPIO, BOARD_MIPI_PANEL_RST_PIN, 1);
}
else
{
GPIO_PinWrite(BOARD_MIPI_PANEL_RST_GPIO, BOARD_MIPI_PANEL_RST_PIN, 0);
}
}
static void BOARD_PullPanelPowerPin(bool pullUp)
{
if (pullUp)
{
GPIO_PinWrite(BOARD_MIPI_PANEL_POWER_GPIO, BOARD_MIPI_PANEL_POWER_PIN, 1);
}
else
{
GPIO_PinWrite(BOARD_MIPI_PANEL_POWER_GPIO, BOARD_MIPI_PANEL_POWER_PIN, 0);
}
}
static status_t BOARD_DSI_Transfer(dsi_transfer_t *xfer)
{
return DSI_TransferBlocking(DEMO_MIPI_DSI, xfer);
}
static void BOARD_InitLcdifClock(void)
{
/*
* The pixel clock is (height + VSW + VFP + VBP) * (width + HSW + HFP + HBP) * frame rate.
*
* For 60Hz frame rate, the RK055IQH091 pixel clock should be 36MHz.
* the RK055AHD091 pixel clock should be 62MHz.
*/
const clock_root_config_t lcdifClockConfig = {
.clockOff = false,
.mux = 4, /*!< PLL_528. */
#if (defined(VGLITE_USING_RK055AHD091) || defined(VGLITE_USING_RK055MHD091))
.div = 9,
#else
.div = 15,
#endif
};
#if defined(VGLITE_USING_LCDIFV2)
CLOCK_SetRootClock(kCLOCK_Root_Lcdifv2, &lcdifClockConfig);
mipiDsiDpiClkFreq_Hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Lcdifv2);
#else
CLOCK_SetRootClock(kCLOCK_Root_Lcdif, &lcdifClockConfig);
mipiDsiDpiClkFreq_Hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Lcdif);
#endif
}
static void BOARD_InitMipiDsiClock(void)
{
uint32_t mipiDsiEscClkFreq_Hz;
/* RxClkEsc max 60MHz, TxClkEsc 12 to 20MHz. */
/* RxClkEsc = 528MHz / 11 = 48MHz. */
/* TxClkEsc = 528MHz / 11 / 4 = 16MHz. */
const clock_root_config_t mipiEscClockConfig = {
.clockOff = false,
.mux = 4, /*!< PLL_528. */
.div = 11,
};
CLOCK_SetRootClock(kCLOCK_Root_Mipi_Esc, &mipiEscClockConfig);
mipiDsiEscClkFreq_Hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Mipi_Esc);
const clock_group_config_t mipiEscClockGroupConfig = {
.clockOff = false, .resetDiv = 2, .div0 = 2, /* TX esc clock. */
};
CLOCK_SetGroupConfig(kCLOCK_Group_MipiDsi, &mipiEscClockGroupConfig);
mipiDsiTxEscClkFreq_Hz = mipiDsiEscClkFreq_Hz / 3;
/* DPHY reference clock, use OSC 24MHz clock. */
const clock_root_config_t mipiDphyRefClockConfig = {
.clockOff = false,
.mux = 1, /*!< OSC_24M. */
.div = 1,
};
CLOCK_SetRootClock(kCLOCK_Root_Mipi_Ref, &mipiDphyRefClockConfig);
mipiDsiDphyRefClkFreq_Hz = BOARD_XTAL0_CLK_HZ;
}
static status_t BOARD_InitLcdPanel(void)
{
status_t status;
const gpio_pin_config_t pinConfig = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
const display_config_t displayConfig = {
.resolution = FSL_VIDEO_RESOLUTION(LCD_WIDTH, LCD_HEIGHT),
.hsw = LCD_HSW,
.hfp = LCD_HFP,
.hbp = LCD_HBP,
.vsw = LCD_VSW,
.vfp = LCD_VFP,
.vbp = LCD_VBP,
.controlFlags = 0,
.dsiLanes = DEMO_MIPI_DSI_LANE_NUM,
};
GPIO_PinInit(BOARD_MIPI_PANEL_POWER_GPIO, BOARD_MIPI_PANEL_POWER_PIN, &pinConfig);
GPIO_PinInit(BOARD_MIPI_PANEL_BL_GPIO, BOARD_MIPI_PANEL_BL_PIN, &pinConfig);
GPIO_PinInit(BOARD_MIPI_PANEL_RST_GPIO, BOARD_MIPI_PANEL_RST_PIN, &pinConfig);
#if defined(VGLITE_USING_RK055AHD091)
status = RM68200_Init(&rm68200Handle, &displayConfig);
#elif defined(VGLITE_USING_RK055MHD091)
status = HX8394_Init(&hx8394Handle, &displayConfig);
#else
status = RM68191_Init(&rm68191Handle, &displayConfig);
#endif
if (status == kStatus_Success)
{
GPIO_PinWrite(BOARD_MIPI_PANEL_BL_GPIO, BOARD_MIPI_PANEL_BL_PIN, 1);
}
return status;
}
static void BOARD_SetMipiDsiConfig(void)
{
dsi_config_t dsiConfig;
dsi_dphy_config_t dphyConfig;
const dsi_dpi_config_t dpiConfig = {.pixelPayloadSize = LCD_WIDTH,
.dpiColorCoding = kDSI_Dpi24Bit,
.pixelPacket = kDSI_PixelPacket24Bit,
.videoMode = kDSI_DpiBurst,
.bllpMode = kDSI_DpiBllpLowPower,
.polarityFlags = kDSI_DpiVsyncActiveLow | kDSI_DpiHsyncActiveLow,
.hfp = LCD_HFP,
.hbp = LCD_HBP,
.hsw = LCD_HSW,
.vfp = LCD_VFP,
.vbp = LCD_VBP,
.panelHeight = LCD_HEIGHT,
.virtualChannel = 0};
/*
* dsiConfig.numLanes = 4;
* dsiConfig.enableNonContinuousHsClk = false;
* dsiConfig.autoInsertEoTp = true;
* dsiConfig.numExtraEoTp = 0;
* dsiConfig.htxTo_ByteClk = 0;
* dsiConfig.lrxHostTo_ByteClk = 0;
* dsiConfig.btaTo_ByteClk = 0;
*/
DSI_GetDefaultConfig(&dsiConfig);
dsiConfig.numLanes = DEMO_MIPI_DSI_LANE_NUM;
dsiConfig.autoInsertEoTp = true;
/* Init the DSI module. */
DSI_Init(DEMO_MIPI_DSI, &dsiConfig);
/* Init DPHY.
*
* The DPHY bit clock must be fast enough to send out the pixels, it should be
* larger than:
*
* (Pixel clock * bit per output pixel) / number of MIPI data lane
*
* Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure
* it is fast enough.
*
* Note that the DSI output pixel is 24bit per pixel.
*/
mipiDsiDphyBitClkFreq_Hz = mipiDsiDpiClkFreq_Hz * (24 / DEMO_MIPI_DSI_LANE_NUM);
mipiDsiDphyBitClkFreq_Hz = DEMO_MIPI_DPHY_BIT_CLK_ENLARGE(mipiDsiDphyBitClkFreq_Hz);
DSI_GetDphyDefaultConfig(&dphyConfig, mipiDsiDphyBitClkFreq_Hz, mipiDsiTxEscClkFreq_Hz);
mipiDsiDphyBitClkFreq_Hz = DSI_InitDphy(DEMO_MIPI_DSI, &dphyConfig, mipiDsiDphyRefClkFreq_Hz);
/* Init DPI interface. */
DSI_SetDpiConfig(DEMO_MIPI_DSI, &dpiConfig, DEMO_MIPI_DSI_LANE_NUM, mipiDsiDpiClkFreq_Hz, mipiDsiDphyBitClkFreq_Hz);
}
status_t BOARD_InitDisplayInterface(void)
{
CLOCK_EnableClock(kCLOCK_Video_Mux);
#if defined(VGLITE_USING_LCDIFV2)
/* LCDIF v2 output to MIPI DSI. */
VIDEO_MUX->VID_MUX_CTRL.SET = VIDEO_MUX_VID_MUX_CTRL_MIPI_DSI_SEL_MASK;
#else
/* ELCDIF output to MIPI DSI. */
VIDEO_MUX->VID_MUX_CTRL.CLR = VIDEO_MUX_VID_MUX_CTRL_MIPI_DSI_SEL_MASK;
#endif
/* 1. Power on and isolation off. */
PGMC_BPC4->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK | PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK);
/* 2. Assert MIPI reset. */
IOMUXC_GPR->GPR62 &=
~(IOMUXC_GPR_GPR62_MIPI_DSI_PCLK_SOFT_RESET_N_MASK | IOMUXC_GPR_GPR62_MIPI_DSI_ESC_SOFT_RESET_N_MASK |
IOMUXC_GPR_GPR62_MIPI_DSI_BYTE_SOFT_RESET_N_MASK | IOMUXC_GPR_GPR62_MIPI_DSI_DPI_SOFT_RESET_N_MASK);
/* 3. Setup clock. */
BOARD_InitMipiDsiClock();
/* 4. Deassert PCLK and ESC reset. */
IOMUXC_GPR->GPR62 |=
(IOMUXC_GPR_GPR62_MIPI_DSI_PCLK_SOFT_RESET_N_MASK | IOMUXC_GPR_GPR62_MIPI_DSI_ESC_SOFT_RESET_N_MASK);
/* 5. Configures peripheral. */
BOARD_SetMipiDsiConfig();
/* 6. Deassert BYTE and DBI reset. */
IOMUXC_GPR->GPR62 |=
(IOMUXC_GPR_GPR62_MIPI_DSI_BYTE_SOFT_RESET_N_MASK | IOMUXC_GPR_GPR62_MIPI_DSI_DPI_SOFT_RESET_N_MASK);
/* 7. Configure the panel. */
return BOARD_InitLcdPanel();
}
#if defined(VGLITE_USING_LCDIFV2)
void LCDIFv2_IRQHandler(void)
{
DC_FB_LCDIFV2_IRQHandler(&g_dc);
}
#else
void eLCDIF_IRQHandler(void)
{
DC_FB_ELCDIF_IRQHandler(&g_dc);
}
#endif
status_t BOARD_VerifyDisplayClockSource(void)
{
status_t status;
uint32_t srcClkFreq;
/*
* In this implementation, the SYSPLL2 (528M) clock is used as the source
* of LCDIFV2 pixel clock and MIPI DSI ESC clock. The OSC24M clock is used
* as the MIPI DSI DPHY PLL reference clock. This function checks the clock
* source are valid. OSC24M is always valid, so only verify the SYSPLL2.
*/
srcClkFreq = CLOCK_GetPllFreq(kCLOCK_PllSys2);
if (528 != (srcClkFreq / 1000000))
{
status = kStatus_Fail;
}
else
{
status = kStatus_Success;
}
return status;
}
status_t BOARD_PrepareDisplayController(void)
{
status_t status;
status = BOARD_VerifyDisplayClockSource();
if (status != kStatus_Success)
{
// PRINTF("Error: Invalid display clock source.\r\n");
return status;
}
BOARD_InitLcdifClock();
status = BOARD_InitDisplayInterface();
if (kStatus_Success == status)
{
#if defined(VGLITE_USING_LCDIFV2)
NVIC_ClearPendingIRQ(LCDIFv2_IRQn);
NVIC_SetPriority(LCDIFv2_IRQn, 3);
EnableIRQ(LCDIFv2_IRQn);
#else
NVIC_ClearPendingIRQ(eLCDIF_IRQn);
NVIC_SetPriority(eLCDIF_IRQn, 3);
EnableIRQ(eLCDIF_IRQn);
#endif
}
return kStatus_Success;
}

View File

@ -0,0 +1,189 @@
/*
* Copyright 2019-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _DISPLAY_SUPPORT_H_
#define _DISPLAY_SUPPORT_H_
#include <rtthread.h>
#include "fsl_dc_fb.h"
#if defined(VGLITE_USING_RK055AHD091)
#include "fsl_rm68200.h"
#elif defined(VGLITE_USING_RK055IQH091)
#include "fsl_rm68191.h"
#elif defined(VGLITE_USING_RK055MHD091)
#include "fsl_hx8394.h"
#else
#error "Please config lcd panel parameters."
#endif
#include "pin_mux.h"
#include "board.h"
#if defined(VGLITE_USING_LCDIFV2)
#include "fsl_dc_fb_lcdifv2.h"
#else
#include "fsl_dc_fb_elcdif.h"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/* @TEST_ANCHOR */
#define DEMO_BUFFER_FIXED_ADDRESS 0
#if DEMO_BUFFER_FIXED_ADDRESS
#define DEMO_BUFFER0_ADDR 0x80000000
#define DEMO_BUFFER1_ADDR 0x80200000
#endif
/*
* Use the MIPI dumb panel
*/
/* Definitions for the frame buffer. */
#define DEMO_BUFFER_COUNT 2 /* 2 is enough for DPI interface display. */
#ifndef DEMO_USE_XRGB8888
#define DEMO_USE_XRGB8888 0
#endif
/* Use LCDIF LUT (or named color palette) which is 8-bit per-pixel */
#ifndef DEMO_USE_LUT8
#define DEMO_USE_LUT8 0
#endif
#if DEMO_USE_XRGB8888
#define DEMO_BUFFER_PIXEL_FORMAT kVIDEO_PixelFormatXRGB8888
#define DEMO_BUFFER_BYTE_PER_PIXEL 4
#elif DEMO_USE_LUT8
#define DEMO_BUFFER_PIXEL_FORMAT kVIDEO_PixelFormatLUT8
#define DEMO_BUFFER_BYTE_PER_PIXEL 1
#else
#define DEMO_BUFFER_PIXEL_FORMAT kVIDEO_PixelFormatRGB565
#define DEMO_BUFFER_BYTE_PER_PIXEL 2
#endif
#if (defined(VGLITE_USING_RK055AHD091) || defined(VGLITE_USING_RK055MHD091))
#define LCD_WIDTH (720)
#define LCD_HEIGHT (1280)
#elif defined(VGLITE_USING_RK055IQH091)
#define LCD_WIDTH (540)
#define LCD_HEIGHT (960)
#endif
#define DEMO_BUFFER_WIDTH LCD_WIDTH
#define DEMO_BUFFER_HEIGHT LCD_HEIGHT
/* Where the frame buffer is shown in the screen. */
#define DEMO_BUFFER_START_X 0U
#define DEMO_BUFFER_START_Y 0U
#define DEMO_BUFFER_STRIDE_BYTE (DEMO_BUFFER_WIDTH * DEMO_BUFFER_BYTE_PER_PIXEL)
/* There is not frame buffer aligned requirement, consider the 64-bit AXI data
* bus width and 32-byte cache line size, the frame buffer alignment is set to
* 32 byte.
*/
#define FRAME_BUFFER_ALIGN 32
/*
* MIPI panel pin
*/
#define BOARD_MIPI_PANEL_RST_GPIO GPIO9
#define BOARD_MIPI_PANEL_RST_PIN 1
#define BOARD_MIPI_PANEL_POWER_GPIO GPIO11
#define BOARD_MIPI_PANEL_POWER_PIN 16
/* Back light pin. */
#define BOARD_MIPI_PANEL_BL_GPIO GPIO9
#define BOARD_MIPI_PANEL_BL_PIN 29
/*
* MIPI panel pin for RT-Thread
*/
#define GET_PIN(PORTx, PIN) (32 * (PORTx - 1) + (PIN & 31)) /* PORTx:1,2,3,4,5 */
#define LCD_RST_GPIO_PORT (3U)
#define LCD_RST_GPIO_PIN (1U)
#define LCD_RST_PIN GET_PIN(LCD_RST_GPIO_PORT, LCD_RST_GPIO_PIN)
/* Back light pin. */
#define LCD_BL_GPIO_PORT (3U)
#define LCD_BL_GPIO_PIN (29U)
#define LCD_BL_PIN GET_PIN(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN)
/*
* RK055AHD091 panel
*/
#if defined(VGLITE_USING_RK055AHD091)
#define LCD_HSW 8
#define LCD_HFP 32
#define LCD_HBP 32
#define LCD_VSW 2
#define LCD_VFP 16
#define LCD_VBP 14
#elif defined(VGLITE_USING_RK055IQH091)
#define LCD_HSW 2
#define LCD_HFP 32
#define LCD_HBP 30
#define LCD_VSW 2
#define LCD_VFP 16
#define LCD_VBP 14
#elif defined(VGLITE_USING_RK055MHD091)
#define LCD_HSW 6
#define LCD_HFP 12
#define LCD_HBP 24
#define LCD_VSW 2
#define LCD_VFP 16
#define LCD_VBP 14
#endif
#if defined(VGLITE_USING_LCDIFV2)
#define DEMO_LCDIF_POL_FLAGS \
(kLCDIFV2_DataEnableActiveHigh | kLCDIFV2_VsyncActiveLow | kLCDIFV2_HsyncActiveLow | \
kLCDIFV2_DriveDataOnFallingClkEdge)
#define DEMO_LCDIF LCDIFV2
#else
#define DEMO_LCDIF_POL_FLAGS \
(kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnFallingClkEdge)
#define DEMO_LCDIF LCDIF
#endif
/* Definitions for MIPI. */
#define DEMO_MIPI_DSI (&g_mipiDsi)
#define DEMO_MIPI_DSI_LANE_NUM 2
extern const dc_fb_t g_dc;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
status_t BOARD_PrepareDisplayController(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* _DISPLAY_SUPPORT_H_ */

View File

@ -0,0 +1,321 @@
/****************************************************************************
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "elm_precom.h"
#include "vg_lite.h"
#if !DDRLESS
static vg_lite_buffer_format_t _buffer_format_to_vglite(ELM_BUFFER_FORMAT format)
{
vg_lite_buffer_format_t fmt;
switch (format) {
case ELM_BUFFER_FORMAT_RGBA8888:
fmt = VG_LITE_RGBA8888;
break;
case ELM_BUFFER_FORMAT_RGBX8888:
fmt = VG_LITE_RGBX8888;
break;
case ELM_BUFFER_FORMAT_BGRA8888:
fmt = VG_LITE_BGRA8888;
break;
case ELM_BUFFER_FORMAT_BGRX8888:
fmt = VG_LITE_BGRX8888;
break;
case ELM_BUFFER_FORMAT_RGB565:
fmt = VG_LITE_RGB565;
break;
case ELM_BUFFER_FORMAT_BGR565:
fmt = VG_LITE_BGR565;
break;
case ELM_BUFFER_FORMAT_RGBA4444:
fmt = VG_LITE_RGBA4444;
break;
case ELM_BUFFER_FORMAT_BGRA4444:
fmt = VG_LITE_BGRA4444;
break;
default:
fmt = VG_LITE_RGBA8888;
break;
}
return fmt;
}
#endif
/*!
@abstract Create internal render buffer.
@discussion
This functiois is to create an internal render buffer for Elementary rendering, ussually it's not for direct display.
The buffer which is displayed on pannel is wrapped up by another API, whose address is managed by display controller side.
@param width
The buffer's width.
@param height
The buffer's height.
@param format
The buffer's format, check enumeration of ELM_BUFFER_FORMAT.
@return
The buffer handle.
*/
ElmBuffer ElmCreateBuffer(unsigned int width, unsigned int height, ELM_BUFFER_FORMAT format)
{
#if !DDRLESS
el_Obj_Buffer *buffer_obj;
vg_lite_buffer_t *buffer;
vg_lite_error_t error;
ElmHandle handle = ELM_NULL_HANDLE;
do {
/* Allocate ebo object. */
buffer_obj = (el_Obj_Buffer *)calloc(1,sizeof(el_Obj_Buffer));
if (buffer_obj != NULL) {
buffer_obj->object.type = ELM_OBJECT_TYPE_BUF;
/* Allocate the buffer. */
buffer = &buffer_obj->buffer;
memset(buffer, 0, sizeof(vg_lite_buffer_t));
buffer->width = width;
buffer->height = height;
buffer->format = (vg_lite_buffer_format_t)format;
error = vg_lite_allocate(buffer);
if (error)
goto error_exit;
JUMP_IF_NON_ZERO_VALUE(add_object((el_Object *)buffer_obj), error_exit);
handle = buffer_obj->object.handle;
}
} while(0);
return handle;
error_exit:
vg_lite_free(buffer);
free(buffer_obj);
return ELM_NULL_HANDLE;
#else
return ELM_NULL_HANDLE;
#endif
}
/*!
@abstract Wrap a customized buffer.
@discussion
The application may wrap a user created buffer by giving the information of
the buffer including the size, the memory addresses and format. E.g., the
application can wrap a system framebuffer thus ELM can directly render onto
the screen.
@return
The buffer handle.
*/
ElmBuffer ElmWrapBuffer(int width, int height, int stride,
void *logical, uint32_t physical,
ELM_BUFFER_FORMAT format)
{
#if !DDRLESS
el_Obj_Buffer *buffer_obj;
vg_lite_buffer_t *buffer;
ElmHandle handle = ELM_NULL_HANDLE;
do {
/* open framebuffer. */
buffer_obj = (el_Obj_Buffer *)elm_alloc(1, sizeof(el_Obj_Buffer));
if (buffer_obj != NULL) {
buffer_obj->object.type = ELM_OBJECT_TYPE_BUF;
buffer = &buffer_obj->buffer;
buffer->width = width;
buffer->height = height;
buffer->stride = stride;
buffer->memory = logical;
buffer->handle = NULL;
buffer->address = physical;
buffer->format = _buffer_format_to_vglite(format);
buffer->tiled = VG_LITE_LINEAR;
JUMP_IF_NON_ZERO_VALUE(add_object((el_Object *)buffer_obj), error_exit);
handle = buffer_obj->object.handle;
}
} while(0);
return handle;
error_exit:
free(buffer_obj);
return ELM_NULL_HANDLE;
#else
return ELM_NULL_HANDLE;
#endif
}
/*!
@abstract Get buffer address.
@discussion
The function is to get the address of ElmBuffer.
@return
The buffer address.
*/
uint32_t ElmGetBufferAddress(ElmBuffer buffer)
{
#if !DDRLESS
el_Obj_Buffer *buff_obj;
buff_obj = (el_Obj_Buffer *)get_object(buffer);
if (buff_obj == NULL)
{
return 0;
}
else
{
return buff_obj->buffer.address;
}
#else
return 0;
#endif
}
/*!
@abstract Destroy a render buffer.
@discussion
This function is to release all internal resource inside Elementary libary belonging to this buffer.
Applicatoin need make sure the buffer is not being used by elmentary library any more when calling this function.
@param buffer
The render buffer handle
@return
If destroying is completed successfully.
*/
BOOL ElmDestroyBuffer(ElmBuffer buffer)
{
#if !DDRLESS
/* Find the object. */
el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
/* If found, delete the vg_lite_buffer object. Otherwise, return FALSE. */
if (buff != NULL) {
if (buff->buffer.handle != NULL) {
/* Free the buffer memory. */
vg_lite_free(&buff->buffer);
}
remove_object((el_Object*)buff);
elm_free(buff);
return TRUE;
}
else {
return FALSE;
}
#else
return TRUE;
#endif
}
BOOL ElmSaveBuffer(ElmBuffer buffer, const char *name)
{
#if !DDRLESS
el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
/* If found, delete the vg_lite_buffer object. Otherwise, return FALSE. */
if (buff != NULL) {
#if !RTOS
/*
"vg_lite_save_png" function does not exist (anymore). Probably a left
over from an older driver.
*/
if (buff->buffer.memory != NULL) {
vg_lite_save_png(name, &buff->buffer);
}
#endif
return TRUE;
}
else {
return FALSE;
}
#else
return TRUE;
#endif
}
/*!
@abstract Convert vglite format to elm format.
*/
ELM_BUFFER_FORMAT _buffer_format_to_Elm(vg_lite_buffer_format_t format)
{
switch (format)
{
case VG_LITE_RGB565:
return ELM_BUFFER_FORMAT_RGB565;
break;
case VG_LITE_BGR565:
return ELM_BUFFER_FORMAT_BGR565;
break;
default:
return ELM_BUFFER_FORMAT_RGBA8888;
break;
}
}
/*!
@abstract Get handle of the framebuffer.
*/
ElmBuffer ElmGetBuffer(vg_lite_buffer_t *buffer)
{
elm_tls_t* elm_tls;
elm_tls = (elm_tls_t *) elm_os_get_tls();
if (elm_tls == NULL)
return ELM_NULL_HANDLE;
for (int i = 0; i < APP_BUFFER_COUNT; i++) {
if (elm_tls->gContext.elmFB[i].buffer == NULL) {
elm_tls->gContext.elmFB[i].buffer = buffer;
elm_tls->gContext.elmFB[i].handle = ElmWrapBuffer(buffer->width, buffer->height, buffer->stride, buffer->memory,
buffer->address, _buffer_format_to_Elm(buffer->format));
vg_lite_clear(buffer, NULL, 0x0);
return elm_tls->gContext.elmFB[i].handle;
}
if (elm_tls->gContext.elmFB[i].buffer == buffer)
return elm_tls->gContext.elmFB[i].handle;
}
return 0;
}

View File

@ -0,0 +1,483 @@
/****************************************************************************
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "elm_precom.h"
#if (VG_RENDER_TEXT==1)
#include "elm_text.h"
#endif /* VG_RENDER_TEXT */
static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
{
vg_lite_matrix_t temp;
int row, column;
/* Process all rows. */
for (row = 0; row < 3; row++) {
/* Process all columns. */
for (column = 0; column < 3; column++) {
/* Compute matrix entry. */
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
+ (matrix->m[row][1] * mult->m[1][column])
+ (matrix->m[row][2] * mult->m[2][column]);
}
}
memcpy(matrix, &temp, sizeof(temp));
}
static vg_lite_filter_t quality_to_filter(ELM_QUALITY quality)
{
switch (quality) {
case ELM_QULIATY_HI:
return VG_LITE_FILTER_BI_LINEAR;
break;
case ELM_QUALITY_MED:
return VG_LITE_FILTER_LINEAR;
break;
case ELM_QUALITY_LOW:
default:
return VG_LITE_FILTER_POINT;
break;
}
}
static vg_lite_pattern_mode_t pat_to_pad(ELM_PATTERN_MODE mode)
{
switch (mode) {
case ELM_PATTERN_MODE_PAD:
return VG_LITE_PATTERN_PAD;
break;
default:
return VG_LITE_PATTERN_COLOR;
break;
}
}
static vg_lite_error_t draw_evo_pattern(el_Obj_Buffer *buff, el_Obj_Group *ego,int * index)
{
el_Obj_EVO *evo;
vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
vg_lite_color_t color;
vg_lite_filter_t filter;
vg_lite_blend_t blend;
vg_lite_fill_t rule;
vg_lite_buffer_t *buffer;
vg_lite_matrix_t mat;
vg_lite_pattern_mode_t pat_mode;
int width = 0;
int height = 0;
int start = *index;
int i = start;
evo = &ego->group.objects[i];
width = (int)(evo->data.path.bounding_box[2] - evo->data.path.bounding_box[0]);
height = (int)(evo->data.path.bounding_box[3] - evo->data.path.bounding_box[1]);
buffer = (vg_lite_buffer_t *)malloc(sizeof(vg_lite_buffer_t));
memset(buffer,0,sizeof(vg_lite_buffer_t));
buffer->width = width;
buffer->height = height;
buffer->format = VG_LITE_RGBA8888;
error = vg_lite_allocate(buffer);
vg_lite_clear(buffer,NULL,0xffffffff);
i++;
evo = &ego->group.objects[i];
while(evo->is_pattern)
{
blend = (vg_lite_blend_t)evo->attribute.blend;
rule = (vg_lite_fill_t)evo->attribute.fill_rule;
color = (vg_lite_color_t)evo->attribute.paint.color;
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
error = vg_lite_draw(buffer, &evo->data.path,
rule,
&mat,
blend,
color);
if(error)
return error;
i++;
evo = &ego->group.objects[i];
}
*index = i - 1;
evo = &ego->group.objects[start];
blend = (vg_lite_blend_t)evo->attribute.blend;
rule = (vg_lite_fill_t)evo->attribute.fill_rule;
color = (vg_lite_color_t)evo->attribute.paint.color;
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
filter = VG_LITE_FILTER_POINT;
pat_mode = VG_LITE_PATTERN_COLOR;
error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path,
rule,
&mat,
buffer,
&mat,
blend,
pat_mode,
color,
filter);
vg_lite_finish();
vg_lite_free(buffer);
free(buffer);
return error;
}
static vg_lite_error_t draw_evo(el_Obj_Buffer *buff, el_Obj_EVO *evo, vg_lite_matrix_t *mat)
{
el_Obj_EBO *pattern;
vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
vg_lite_color_t color;
vg_lite_filter_t filter;
vg_lite_matrix_t mat_pattern;
ELM_PAINT_TYPE paint_type = evo->attribute.paint.type;
vg_lite_blend_t blend = (vg_lite_blend_t)evo->attribute.blend;
vg_lite_fill_t rule = (vg_lite_fill_t)evo->attribute.fill_rule;
vg_lite_pattern_mode_t pat_mode = pat_to_pad(evo->attribute.paint.pattern.mode);
switch (paint_type) {
case ELM_PAINT_GRADIENT:
memcpy(&evo->attribute.paint.grad->data.grad.matrix,
&evo->attribute.paint.grad->data.transform.matrix,
sizeof(evo->attribute.paint.grad->data.transform.matrix));
#if !DDRLESS
error = vg_lite_draw_gradient(&buff->buffer, &evo->data.path,
rule,
mat,
&evo->attribute.paint.grad->data.grad,
blend);
#else
error = vg_lite_draw_gradient(NULL, &evo->data.path,
rule,
mat,
&evo->attribute.paint.grad->data.grad,
blend);
#endif
break;
case ELM_PAINT_RADIAL_GRADIENT:
memcpy(&evo->attribute.paint.radgrad->data.rad_grad.matrix,
&evo->attribute.paint.radgrad->data.transform.matrix,
sizeof(evo->attribute.paint.radgrad->data.transform.matrix));
error = vg_lite_draw_radial_gradient(&buff->buffer, &evo->data.path,
rule,
mat,
&evo->attribute.paint.radgrad->data.rad_grad,
0,
blend,
VG_LITE_FILTER_LINEAR);
break;
case ELM_PAINT_COLOR:
color = (vg_lite_color_t)evo->attribute.paint.color;
#if !DDRLESS
error = vg_lite_draw(&buff->buffer, &evo->data.path,
rule,
mat,
blend,
color);
#else
error = vg_lite_draw(NULL, &evo->data.path,
rule,
mat,
blend,
color);
#endif
break;
case ELM_PAINT_PATTERN:
pattern = (el_Obj_EBO *)(evo->attribute.paint.pattern.pattern);
blend = (vg_lite_blend_t)(pattern->attribute.blend);
filter = quality_to_filter(evo->attribute.quality);
color = (vg_lite_color_t)pattern->attribute.paint.color;
memcpy(&mat_pattern, &pattern->attribute.transform.matrix,
sizeof(pattern->attribute.transform.matrix));
#if !DDRLESS
error = vg_lite_draw_pattern(&buff->buffer, &evo->data.path, rule, mat,
&pattern->data.buffer, &mat_pattern, blend,
pat_mode, color, filter);
#else
error = vg_lite_draw_pattern(NULL, &evo->data.path, rule, mat,
&pattern->data.buffer, &mat_pattern, blend,
pat_mode, color, filter);
#endif
break;
case ELM_PAINT_TEXT:
#if (VG_RENDER_TEXT==1)
error = draw_text(buff, evo, mat);
#endif /* VG_RENDER_TEXT */
break;
}
return error;
}
static vg_lite_error_t draw_ebo(el_Obj_Buffer *buff, el_Obj_EBO *ebo, vg_lite_matrix_t *mat)
{
vg_lite_error_t error;
vg_lite_buffer_t *image_buffer = &ebo->data.buffer;
vg_lite_blend_t blend = (vg_lite_blend_t)ebo->attribute.blend;
vg_lite_color_t color = ebo->attribute.paint.color;
vg_lite_filter_t filter = quality_to_filter(ebo->attribute.quality);
if (image_buffer->format >= VG_LITE_INDEX_1 && image_buffer->format <= VG_LITE_INDEX_8)
{
vg_lite_set_CLUT(ebo->clut_count, ebo->clut);
}
image_buffer->image_mode = VG_LITE_NORMAL_IMAGE_MODE;
#if !DDRLESS
error = vg_lite_blit(&buff->buffer, image_buffer, mat, blend, color, filter);
#else
error = vg_lite_blit(NULL, image_buffer, mat, blend, color, filter);
#endif
return error;
}
/*!
@abstract Clear a render buffer with specified color and dimension.
@discussion
This function is called to clear full or partial of the buffer. If the rectangle is out of buffer space, the intersect portion will be cleared.
@param buffer
A render buffer handle.
@param color
Clear color value.
@param x
x origin of partical clear rectangle.
@param y
y origin of partial clear rectangle.
@param width
width of partical clear rectangle.
@param height
height of partical clear rectangle.
@param full
Flag to indicate a full buffer clear. If true, the dimension parameters will be ignored.
@return bool
Indicate the clear operation is set up correctly.
*/
BOOL ElmClear(ElmBuffer buffer, uint32_t color, uint32_t x, uint32_t y, uint32_t width, uint32_t height, BOOL full)
{
#if !DDRLESS
vg_lite_error_t error = VG_LITE_SUCCESS;
el_Obj_Buffer *buff = (el_Obj_Buffer *)get_object(buffer);
vg_lite_rectangle_t rectangle;
rectangle.x = x;
rectangle.y = y;
rectangle.width = width;
rectangle.height = height;
if (full == 1)
{
error = vg_lite_clear(&buff->buffer, NULL, color);
}
else
{
error = vg_lite_clear(&buff->buffer, &rectangle, color);
}
return ((error == VG_LITE_SUCCESS) ? TRUE : FALSE);
#else
return TRUE;
#endif
}
/*!
@abstract Finish all rendering on GPU issued before this call.
@discussion
This function tells the engine that it has finished the frame data and GPU can draw it now. It's blocked until GPU rendering done.
@return
If the opeartion is successfully done or not.
*/
BOOL ElmFinish()
{
vg_lite_finish();
return TRUE;
}
/*!
@abstract Flush all rendering command to GPU issued before this call.
@discussion
This function tells the engine to start kicking off command to GPU side, it will return immediately after firing off GPU.
@return
If the opeartion is successfully done or not.
*/
BOOL ElmFlush()
{
vg_lite_flush();
return TRUE;
}
/*!
@abstract Draw a graphics object onto current render target
@discussion
This is an enssentail function to do the real job, it takes all current setting of the elementary object and
render into theb buffer target.
@param buffer
The render target that an elmentary object will be rendered into.
@param obj
The elmentary object will be draw into render target.
@return bool
The draw operation for this elmentary object is sucessful.
*/
BOOL ElmDraw(ElmBuffer buffer, ElmHandle object)
{
BOOL status = TRUE;
el_Object *elm;
el_Obj_Buffer *buff;
vg_lite_error_t error;
vg_lite_matrix_t mat;
elm = get_object(object);
if (!elm)
{
return FALSE;
}
#if !DDRLESS
buff = (el_Obj_Buffer *)get_object(buffer);
if (buff == NULL)
{
return FALSE;
}
#else
buff = NULL;
#endif
if (elm->type == ELM_OBJECT_TYPE_EGO)
{
el_Obj_EVO *evo;
el_Obj_Group *ego = (el_Obj_Group *)elm;
vg_lite_matrix_t mat_group, res_mat;
if (ego->group.count > 0)
{
int i;
memcpy(&mat_group, &(ego->transform.matrix), sizeof(ego->transform.matrix));
for (i = 0; i < ego->group.count; i++)
{
evo = &ego->group.objects[i];
/* Font objects may generate empty objects */
if (evo->object.handle == ELM_NULL_HANDLE)
continue;
if(evo->is_image)
{
ElmHandle ebo_handle;
el_Object *elm_ebo;
el_Obj_EBO *ebo;
ebo_handle = ElmCreateObjectFromFile(ELM_OBJECT_TYPE_EBO, evo->eboname);
elm_ebo = get_object(ebo_handle);
ebo = (el_Obj_EBO *)elm_ebo;
memcpy(&mat, &evo->defaultAttrib.transform.matrix, sizeof(mat));
error = draw_ebo(buff, ebo, &mat);
if (error)
{
status = FALSE;
}
continue;
}
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
memcpy(&res_mat, &mat_group, sizeof(mat_group));
multiply(&res_mat, &mat);
if(evo->has_pattern)
error = draw_evo_pattern(buff,ego,&i);
else
error = draw_evo(buff, evo, &res_mat);
if (error)
{
status = FALSE;
break;
}
}
}
}
else if (elm->type == ELM_OBJECT_TYPE_EVO)
{
el_Obj_EVO *evo = (el_Obj_EVO *)elm;
memcpy(&mat, &(evo->attribute.transform.matrix), sizeof(mat));
error = draw_evo(buff, evo, &mat);
if (error)
{
status = FALSE;
}
}
else if (elm->type == ELM_OBJECT_TYPE_EBO)
{
el_Obj_EBO *ebo = (el_Obj_EBO *)elm;
memcpy(&mat, &(ebo->attribute.transform.matrix), sizeof(mat));
error = draw_ebo(buff, ebo, &mat);
if (error)
{
status = FALSE;
}
}
else if (elm->type == ELM_OBJECT_TYPE_BUF)
{
el_Obj_Buffer *src = (el_Obj_Buffer *)elm;
vg_lite_identity(&mat);
#if !DDRLESS
if (VG_LITE_SUCCESS !=
vg_lite_blit(&buff->buffer, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
VG_LITE_FILTER_BI_LINEAR)
)
#else
if (VG_LITE_SUCCESS !=
vg_lite_blit(NULL, &src->buffer, &mat, VG_LITE_BLEND_NONE, 0,
VG_LITE_FILTER_BI_LINEAR)
)
#endif
{
status = FALSE;
}
}
return status;
}

View File

@ -0,0 +1,158 @@
/****************************************************************************
*
* Copyright 2021 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef __ELM_HEADERS_H__
#define __ELM_HEADERS_H__
#define ATTR_PACKED __attribute__((packed, aligned(4)))
typedef struct {
vg_lite_matrix_t matrix;
uint32_t reserved;
uint32_t stop_count;
uint32_t stop_offset;
uint32_t color_offset;
} el_EVO_GradData;
typedef struct {
vg_lite_radial_gradient_parameter_t params;
vg_lite_radial_gradient_spreadmode_t spread_mode;
} el_EVO_RadGradDataExt;
struct el_PaintType_t {
uint32_t paint:28;
uint32_t flags:1;
uint32_t is_image:1;
uint32_t is_pattern:1;
uint32_t has_pattern:1;
};
typedef struct ATTR_PACKED {
uint32_t type;
vg_lite_float_t min_x, min_y, max_x, max_y;
uint32_t format;
uint32_t length:31;
uint32_t arc_flag:1;
uint32_t offset;
vg_lite_matrix_t matrix;
uint32_t reserved;
uint32_t quality;
uint32_t fill_rule;
uint32_t blend;
union {
uint32_t paint_data;
struct el_PaintType_t paint_type;
};
vg_lite_color_t color;
el_EVO_GradData grad;
} el_EVO_Polygon;
typedef struct ATTR_PACKED {
uint32_t type;
uint32_t namelength;
char eboname[76];
union {
uint32_t paint_data;
struct el_PaintType_t paint_type;
};
vg_lite_matrix_t matrix;
uint32_t width;
uint32_t height;
} el_EVO_Image;
typedef struct ATTR_PACKED {
union {
el_EVO_Polygon polygon;
el_EVO_Image image;
};
} el_EVO_Header;
typedef struct ATTR_PACKED {
uint32_t type;
uint32_t size_font_block;
uint32_t num_ttf_fonts;
uint32_t num_vector_fonts;
uint32_t num_text_fonts;
uint32_t ttf_fonts_block_offset;
uint32_t ttf_fonts_block_length;
uint32_t vector_fonts_block_offset;
uint32_t vector_fonts_block_length;
uint32_t text_fonts_block_offset;
uint32_t text_fonts_block_length;
uint32_t property_block_offset;
uint32_t property_block_length;
} el_Font_Header;
struct el_TextFlags_t {
uint32_t flags1:1;
uint32_t text_anchor:2;
uint32_t flags2:29;
};
typedef struct ATTR_PACKED {
uint32_t type;
uint32_t size_text_block;
uint32_t tspan_has_dx_dy;
float x_pos;
float y_pos;
float font_size;
uint32_t font_id;
uint32_t color;
union {
uint32_t flags_data;
struct el_TextFlags_t text_flags;
};
vg_lite_matrix_t matrix;
uint32_t reserved;
uint16_t data_length;
} el_Text_Header;
typedef struct ATTR_PACKED {
uint32_t type;
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t tiled;
uint32_t format;
uint32_t data_offset;
} el_EBO_Header;
typedef struct ATTR_PACKED {
uint32_t clut_count;
uint32_t clut_data_offset;
} el_EBO_Palette;
typedef struct ATTR_PACKED {
uint32_t type;
vg_lite_matrix_t matrix;
uint32_t count;
} el_EGO_Header;
#endif /* __ELM_HEADERS_H__ */

View File

@ -0,0 +1,160 @@
/****************************************************************************
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "elm_precom.h"
#include "elm_os.h"
#include "vg_lite_os.h"
#if (VG_RENDER_TEXT==1)
#include "elm_text.h"
#endif /* VG_RENDER_TEXT */
/* Prototypes */
static int _initialize_elm(uint32_t width, uint32_t height);
/* Initialize vg_lite related. */
static int _initialize_vglite(int32_t width, int32_t height)
{
vg_lite_error_t error = VG_LITE_SUCCESS;
error = vg_lite_init(width, height);
return (error == VG_LITE_SUCCESS);
}
/* Initialize elm global objects. */
static int _initialize_elm(uint32_t width, uint32_t height)
{
vg_lite_error_t error;
elm_tls_t* elm_tls;
elm_tls = (elm_tls_t *)elm_os_get_tls();
if (elm_tls == NULL) {
elm_tls = (elm_tls_t *)vg_lite_os_malloc(sizeof(elm_tls_t));
error = elm_os_set_tls((void *) elm_tls);
if(error != VG_LITE_SUCCESS)
return error;
}
int i;
elm_tls->gContext.version = VERSION;
elm_tls->gContext.currentHandle = (ELM_NULL_HANDLE + 1); /* Reserve handle 0 for error */
elm_tls->gContext.objectCount = 0;
elm_tls->gContext.tessellation_width = width;
elm_tls->gContext.tessellation_height = height;
elm_tls->gContext.vector_id = -1;
for (i = 0; i < SLOT_COUNT; i++) {
elm_tls->gContext.object_slots[i] = NULL;
}
#if (RTOS && DDRLESS) || BAREMETAL
for (i = 0; i < sizeof(elm_tls->gContext.objmap_ebo) / 4; i++) {
elm_tls->gContext.objmap_ebo[i] = 0;
}
for (i = 0; i < sizeof(elm_tls->gContext.objmap_evo) / 4; i++) {
elm_tls->gContext.objmap_evo[i] = 0;
}
for (i = 0; i < sizeof(elm_tls->gContext.objmap_group) / 4; i++) {
elm_tls->gContext.objmap_group[i] = 0;
}
for (i = 0; i < sizeof(elm_tls->gContext.objmap_grad) / 4; i++) {
elm_tls->gContext.objmap_grad[i] = 0;
}
elm_tls->gContext.objcounter_grad = 0;
elm_tls->gContext.objcounter_evo = 0;
elm_tls->gContext.objcounter_ebo = 0;
elm_tls->gContext.objcounter_group = 0;
#endif
return 1;
}
/* Terminate vg_lite related. */
static void _terminate_vglite(void)
{
vg_lite_close();
}
/* Terminate elm global objects. */
static void _terminate_elm(void)
{
#if (VG_RENDER_TEXT==1)
_release_default_text_parameters();
#endif
elm_os_reset_tls();
}
/*!
@abstract Initialize Elementary context.
@discussion
It should be called as the first function of Elemenatary libary, which initializes the library. Currently
Elementary library doesn't support context concept, neigher multi-threading. Elementary library defines
origin of coordinate system is at top-left.
@param none
@return none
*/
BOOL ElmInitialize(uint32_t width, uint32_t height)
{
BOOL result = TRUE;
do {
result = _initialize_vglite((int32_t)width, (int32_t)height);
if (!result)
break;
result = _initialize_elm(width, height);
if (!result)
break;
}
while (0);
#if (VG_RENDER_TEXT==1)
initialize_elm_text();
#endif /* VG_RENDER_TEXT */
return result;
}
/*!
@abstract Terminate Elementary context.
@discussion
This should be called when an app exits. It frees all the resource.
@param none
@return none
*/
void ElmTerminate(void)
{
_terminate_elm();
_terminate_vglite();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
#include "elm_os.h"
#include "rtthread.h"
vg_lite_error_t elm_os_set_tls(void* tls)
{
if(tls == NULL)
return VG_LITE_INVALID_ARGUMENT;
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_uint32_t * tls_ptr = (rt_uint32_t *)rt_TCB->user_data;
*(tls_ptr + 1) = (rt_uint32_t) tls;
return VG_LITE_SUCCESS;
}
void * elm_os_get_tls(void)
{
rt_thread_t rt_TCB;
void * pvReturn = NULL;
rt_TCB = rt_thread_self();
rt_uint32_t * tls_ptr = (rt_uint32_t *)rt_TCB->user_data;
pvReturn = (void *) *(tls_ptr + 1);
return pvReturn;
}
void elm_os_reset_tls(void)
{
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_uint32_t * tls_ptr = (rt_uint32_t *)rt_TCB->user_data;
*(tls_ptr + 1) = NULL;
}

View File

@ -0,0 +1,13 @@
#ifndef ELM_OS_H_
#define ELM_OS_H_
#include<stdlib.h>
#include"vg_lite.h"
vg_lite_error_t elm_os_set_tls(void* tls);
void * elm_os_get_tls(void);
void elm_os_reset_tls(void);
#endif

View File

@ -0,0 +1,55 @@
/****************************************************************************
*
* Copyright 2012 - 2021 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef elm_precom_h
#define elm_precom_h
/* System headers. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* VGLite hdaders. */
#include "vg_lite.h"
/* Project headers. */
#include "Elm.h"
#include "velm.h"
#include "elm_os.h"
#define JUMP_IF_NON_ZERO_VALUE(x, label) { int ret = x; if ( (ret) != 1 ) { goto label; } }
#define JUMP_IF_NULL(x, label) { if (x == NULL) { goto label;} }
#define JUMP_IF_LOWER(x, y, label) {if (x < y) {goto label;} }
#define JUMP_IF_GREATER(x, y, label) {if (x > y) {goto label;} }
#define JUMP_IF_EQUAL(x, y, label) {if (x == y) {goto label;} }
#define JUMP_IF_LOWER_OR_EQUAL(x, y, label) {if (x <= y) {goto label;} }
#define JUMP_IF_GREATER_OR_EQUAL(x, y, label) {if (x => y) {goto label;} }
#define MIN(a, b) ((a) > (b) ? (b) : (a))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* elm_precom_h */

View File

@ -0,0 +1,732 @@
/****************************************************************************
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/*
ElmDrawText API
*/
/** Include Files */
#include <stdio.h> // for snprintf
#include <stdlib.h>
#include <string.h>
#include "vg_lite.h"
#include "Elm.h"
#include "velm.h"
#include "vg_lite_text.h"
#include "elm_headers.h"
#include "elm_text.h"
#include "elm_precom.h"
#include "vft_draw.h"
/** Macros */
#ifndef VECTOR_DEFAULT_FONT
#define VECTOR_DEFAULT_FONT 1
#endif
#if VECTOR_DEFAULT_FONT /* Use vector font as default font */
#define DEFAULT_FONT_NAME "SVGFreeSansASCII"
#define DEFAULT_FONT_WEIGHT eFontWeightRegular
#define DEFAULT_FONT_STRETCH eFontStretchNormal
#define DEFAULT_FONT_STYLE eFontStyleNormal
#define DEFAULT_FONT_HEIGHT 35
#define DEFAULT_TEXT_FG_COLOR 0xff000000
#define DEFAULT_TEXT_ALIGN (eTextAlignLeft)
#else /* Use raster font as default font */
#define DEFAULT_FONT_NAME "DejaVuSans_Oblique"
#define DEFAULT_FONT_WEIGHT eFontWeightRegular
#define DEFAULT_FONT_STRETCH eFontStretchNormal
#define DEFAULT_FONT_STYLE eFontStyleItalic
#define DEFAULT_FONT_HEIGHT 35
#define DEFAULT_TEXT_FG_COLOR 0xff000000
#define DEFAULT_TEXT_ALIGN (eTextAlignLeft)
#endif
/* Maximum font properties from EVO file */
#define MAX_FONT_ATTRIB_COMBINATIONS (32)
#define TRANSPARENT_VGLITE_COLOUR(a, r, g, b) \
((uint32_t)(a) << 24) | ((uint32_t)(b) << 16) | ((uint32_t)(g) << 8) | \
(uint32_t)r
#define OPAQUE_VGLITE_COLOUR(r, g, b) TRANSPARENT_VGLITE_COLOUR(0xff, r, g, b)
/** Data structures */
/** Internal or external API prototypes */
int vg_lite_is_font_valid(vg_lite_font_t font);
char *vg_lite_get_font_name(vg_lite_font_t font);
vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font);
int ref_object (el_Object *object);
/** Globals */
int g_total_system_font = 0;
static font_field_info_t g_default_font_properties[eMaxFontProperties];
static font_field_info_t g_font_properties[MAX_FONT_ATTRIB_COMBINATIONS][eMaxFontProperties];
/** Externs if any */
extern vg_lite_font_attributes_t g_font_attribs;
extern vg_lite_font_t g_last_font;
extern int g_last_font_attrib_idx;
void initialize_elm_text(void)
{
font_field_info_t *font_fields = NULL;
/* internal parameters of mcufont library */
g_font_attribs.alignment = 0;
g_font_attribs.scale = 1;
g_font_attribs.width = 1200; /* Describes drawing area */
g_font_attribs.margin = 5; /* Left margin in drawing area */
g_font_attribs.bg_color = OPAQUE_VGLITE_COLOUR(0xff,0xff,0xff); // white
g_font_attribs.last_y = 0;
g_font_attribs.last_x =0;
g_font_attribs.last_dx = 0;
/* Initialize default properties */
font_fields = &g_default_font_properties[0];
char *font_name = (char *)elm_alloc(1, strlen(DEFAULT_FONT_NAME)+1);
strcpy(font_name, DEFAULT_FONT_NAME);
font_fields[eFontNameProperty].value.data = font_name;
font_fields[eFontWeightProperty].value.i_value = DEFAULT_FONT_WEIGHT;
font_fields[eFontStretchProperty].value.i_value = DEFAULT_FONT_STRETCH;
font_fields[eFontStyleProperty].value.i_value = DEFAULT_FONT_STYLE;
font_fields[eFontHeightProperty].value.i_value = DEFAULT_FONT_HEIGHT;
font_fields[eTextColorProperty].value.i_value = DEFAULT_TEXT_FG_COLOR;
font_fields[eTextAlignProperty].value.i_value = DEFAULT_TEXT_ALIGN;
}
static int get_property(font_field_info_t *dst_font_fields, font_fields_t *src_font_fields, int num_fields)
{
int i=0;
int len;
/* Initialize default values */
dst_font_fields[eFontWeightProperty].value.i_value = DEFAULT_FONT_WEIGHT;
dst_font_fields[eFontStretchProperty].value.i_value = DEFAULT_FONT_STRETCH;
dst_font_fields[eFontStyleProperty].value.i_value = eFontStyleNormal;
dst_font_fields[eTextAlignProperty].value.i_value = DEFAULT_TEXT_ALIGN;
dst_font_fields[eFontNameProperty].value.data = NULL;
dst_font_fields[eFontHeightProperty].value.i_value = DEFAULT_FONT_HEIGHT;
dst_font_fields[eTextColorProperty].value.i_value = DEFAULT_TEXT_FG_COLOR;
for(i=0; i<num_fields; i++)
{
if(src_font_fields[i].info.eName == FONT_FAMILY ||
src_font_fields[i].info.eName == FONT_WEIGHT ||
src_font_fields[i].info.eName == FONT_STRETCH ||
src_font_fields[i].info.eName == FONT_STYLE ||
src_font_fields[i].info.eName == TEXT_ANCHOR )
{
switch(src_font_fields[i].info.eName)
{
case FONT_FAMILY:
len = strlen((char *)src_font_fields[i].data);
dst_font_fields[eFontNameProperty].eName = FONT_FAMILY;
dst_font_fields[eFontNameProperty].value.data =
(char *)elm_alloc(1, len+1);
strcpy(dst_font_fields[eFontNameProperty].value.data,
(char *)src_font_fields[i].data);
dst_font_fields[eFontNameProperty].value.data[len] = '\0';
break;
case FONT_WEIGHT:
dst_font_fields[eFontWeightProperty].eName = FONT_WEIGHT;
dst_font_fields[eFontWeightProperty].value.i_value =
(eFontWeight_t)src_font_fields[i].info.value.i_value;
break;
case FONT_STRETCH:
dst_font_fields[eFontStretchProperty].eName = FONT_STRETCH;
dst_font_fields[eFontStretchProperty].value.i_value =
(eFontStretch_t)src_font_fields[i].info.value.i_value;
break;
case FONT_STYLE:
dst_font_fields[eFontStyleProperty].eName = FONT_STYLE;
dst_font_fields[eFontStyleProperty].value.i_value =
(eFontStyle_t)src_font_fields[i].info.value.i_value;
break;
case TEXT_ANCHOR:
dst_font_fields[eTextAlignProperty].eName = TEXT_ANCHOR;
dst_font_fields[eTextAlignProperty].value.i_value =
(eTextAlign_t)src_font_fields[i].info.value.i_value;
break;
default:
break;
}
}
}
return 0;
}
vg_lite_error_t draw_text(el_Obj_Buffer *buff,
el_Obj_EVO *evo, vg_lite_matrix_t *mat)
{
vg_lite_error_t error = VG_LITE_INVALID_ARGUMENT;
el_Obj_TEXT *text = (el_Obj_TEXT *)evo;
vg_lite_blend_t blend = (vg_lite_blend_t)text->attribute.blend;
vg_lite_font_t curr_font = VG_LITE_INVALID_FONT;
int curr_font_attrib_idx = INVALID_FONT_PROPERTY_IDX;
vg_lite_font_attributes_t *font_attribs = &g_font_attribs;
font_field_info_t *font_fields = NULL;
curr_font_attrib_idx = text->font_id;
/* Single font caching can be done here (No caching for now)
Release last font object if it is different
*/
if ( vg_lite_is_font_valid(g_last_font) == 1 ) {
/* recycle font objects */
vg_lite_free_font_memory(g_last_font);
g_last_font = VG_LITE_INVALID_FONT;
}
if(curr_font_attrib_idx != INVALID_FONT_PROPERTY_IDX)
{
font_fields = &g_font_properties[curr_font_attrib_idx][0];
font_fields[eFontHeightProperty].value.i_value = text->font_size;
curr_font = vg_lite_find_font(
font_fields[eFontNameProperty].value.data,
(eFontWeight_t)font_fields[eFontWeightProperty].value.i_value,
(eFontStretch_t)font_fields[eFontStretchProperty].value.i_value,
(eFontStyle_t)font_fields[eFontStyleProperty].value.i_value,
font_fields[eFontHeightProperty].value.i_value
);
}
if (curr_font == VG_LITE_INVALID_FONT) {
//printf("ERROR: Font not found. Rendering with default configuration\n");
font_fields = &g_default_font_properties[0];
curr_font = vg_lite_find_font(
font_fields[eFontNameProperty].value.data,
(eFontWeight_t)font_fields[eFontWeightProperty].value.i_value,
(eFontStretch_t)font_fields[eFontStretchProperty].value.i_value,
(eFontStyle_t)font_fields[eFontStyleProperty].value.i_value,
font_fields[eFontHeightProperty].value.i_value);
}
if (curr_font == VG_LITE_INVALID_FONT) {
printf("Font[%s] not found\n", font_fields[eFontNameProperty].value.data);
return VG_LITE_INVALID_ARGUMENT;
}
font_attribs->is_vector_font = vg_lite_is_vector_font(curr_font);
/* Properties that changes over time */
font_attribs->text_color = text->attribute.paint.color;
font_attribs->alignment = (eTextAlign_t)text->text_anchor;
font_attribs->font_height = font_fields[eFontHeightProperty].value.i_value;
font_attribs->tspan_has_dx_dy = text->tspan_has_dx_dy;
error = vg_lite_draw_text(&buff->buffer,
(char *)text->msg,
curr_font,
text->x_pos, text->y_pos,
&text->attribute.transform.matrix,
blend,
font_attribs);
g_last_font = curr_font;
g_last_font_attrib_idx = curr_font_attrib_idx;
return error;
}
/* process font-field data */
static int _process_font_field_data( uint8_t *data_start, uint8_t *data, int num_fields, font_fields_t* fields)
{
eFontFields_t eName;
if (g_total_system_font >= MAX_FONT_ATTRIB_COMBINATIONS) {
printf("WARNING: Font property buffer overflowing...\n"
"Increase MAX_FONT_ATTRIB_COMBINATIONS\n");
return -1;
}
for(int i=0; i<num_fields; i++)
{
fields[i].info.eName = (eFontFields_t)*(uint32_t *)(data + (0 + 3*i) * 4);
fields[i].offset = *(uint32_t *)(data + (1 + 3*i)* 4);
fields[i].data = NULL;
eName = fields[i].info.eName;
if(eName == FONT_SIZE ||
eName == HORIZ_ORIGIN_X ||
eName == HORIZ_ADV_X ||
eName == ASCENT ||
eName == ALPHABETIC ||
eName == CAP_HEIGHT ||
eName == DESCENT ||
eName == SLOPE ||
eName == UNITS_PER_EM ||
eName == X_HEIGHT
)
{
fields[i].info.value.f_value = *(float *)(data + (2 + 3*i)* 4);
}
else
{
fields[i].info.value.i_value = *(uint32_t *)(data + (2 + 3*i)* 4);
}
if(fields[i].offset != 0)
{
fields[i].size = *(uint16_t *)(data_start + fields[i].offset);
fields[i].data = (uint8_t *)elm_alloc(1, fields[i].size+1);
memset(fields[i].data,0, fields[i].size+1);
memcpy(fields[i].data, (void *)(data_start + fields[i].offset + 2), fields[i].size);
}
}
memset(&g_font_properties[g_total_system_font][0], 0,
sizeof(font_fields_t)*eMaxFontProperties);
get_property(g_font_properties[g_total_system_font], fields, num_fields);
g_total_system_font++;
return 0;
}
/* process ttf-type font data */
static int _process_ttf_font_data(uint8_t *data_start, uint8_t *void_data, font_block_t *fontblockobj, int id)
{
unsigned int num_fields;
uint8_t * data = (uint8_t *) void_data;
fontblockobj->ttf_fonts[id].id = *(uint32_t *)(data);
fontblockobj->ttf_fonts[id].type = (eElemType_t)*(uint32_t *)(data + 1 * 4);
num_fields = *(uint32_t *)(data + 2 * 4);
fontblockobj->ttf_fonts[id].num_fields = num_fields;
fontblockobj->ttf_fonts[id].fields = (font_fields_t *)elm_alloc(1, num_fields * sizeof(font_fields_t));
_process_font_field_data(data_start, (uint8_t*)(data + 3 * 4), num_fields, fontblockobj->ttf_fonts[id].fields);
return 0;
}
/* process vector-type font data */
static int _process_vector_font_data(uint8_t *data_start, uint8_t *data, font_block_t *fontblockobj, int id)
{
unsigned int num_fields = 0;
fontblockobj->vector_fonts[id].id = *(uint32_t *)(data);
fontblockobj->vector_fonts[id].type = (eElemType_t)*(uint32_t *)(data + 1 * 4);
num_fields = *(uint32_t *)(data + 2 * 4);
fontblockobj->vector_fonts[id].num_fields = num_fields;
fontblockobj->vector_fonts[id].fields = (font_fields_t *)elm_alloc(1, num_fields * sizeof(font_fields_t));
_process_font_field_data(data_start, (uint8_t*)(data + 3 * 4), num_fields, fontblockobj->vector_fonts[id].fields);
return 0;
}
static int _process_text_font_data(uint8_t *data_start, uint8_t *void_data, font_block_t *fontblockobj, int id)
{
unsigned int num_fields;
uint8_t * data = (uint8_t *) void_data;
fontblockobj->text_fonts[id].id = *(uint32_t *)(data);
fontblockobj->text_fonts[id].type = (eElemType_t)*(uint32_t *)(data + 1 * 4);
num_fields = *(uint32_t *)(data + 2 * 4);
fontblockobj->text_fonts[id].num_fields = num_fields;
fontblockobj->text_fonts[id].fields = (font_fields_t *)elm_alloc(1, num_fields * sizeof(font_fields_t));
_process_font_field_data(data_start, (uint8_t*)(data + 3 * 4), num_fields, fontblockobj->text_fonts[id].fields);
return 0;
}
static uint32_t *alloc_mem(uint32_t size)
{
uint32_t *data = NULL;
data = (uint32_t *)elm_alloc(1, size);
JUMP_IF_NULL(data, error_exit);
#ifdef ENABLE_STRICT_DEBUG_MEMSET
memset(data, 0, size);
#endif
return data;
error_exit:
return NULL;
}
font_block_t *fontblockobj = NULL;
/* load font-data */
int _load_font_data(uint8_t *data)
{
el_Font_Header *font_header = (el_Font_Header *)data;
if ( fontblockobj != NULL )
{
return -1;
}
fontblockobj = (font_block_t *)elm_alloc(1, sizeof(font_block_t));
memset(fontblockobj, 0, sizeof(font_block_t));
fontblockobj->size = font_header->size_font_block;
fontblockobj->type = eElemTypeFont;
fontblockobj->num_ttf_fonts = font_header->num_ttf_fonts;
fontblockobj->num_vector_fonts = font_header->num_vector_fonts;
fontblockobj->num_text_fonts = font_header->num_text_fonts;
fontblockobj->ttf_fonts_block_offset = font_header->ttf_fonts_block_offset;
fontblockobj->ttf_fonts_block_length = font_header->ttf_fonts_block_length;
fontblockobj->vector_fonts_block_offset = font_header->vector_fonts_block_offset;
fontblockobj->vector_fonts_block_length = font_header->vector_fonts_block_length;
fontblockobj->text_fonts_block_offset = font_header->text_fonts_block_offset;
fontblockobj->text_fonts_block_length = font_header->text_fonts_block_length;
fontblockobj->property_block_offset = font_header->property_block_offset;
fontblockobj->property_block_length = font_header->property_block_length;
#ifdef ENABLE_DEBUG_TRACE
printf("size: %d(%0x)\n", fontblockobj->size, fontblockobj->size);
printf("type: %d\n", fontblockobj->type);
printf("num_ttf_fonts: %d\n", fontblockobj->num_ttf_fonts);
printf("num_vector_fonts: %d\n", fontblockobj->num_vector_fonts);
printf("num_text_fonts: %d\n", fontblockobj->num_text_fonts);
printf("ttf_fonts_block_offset: %d(%0x)\n", fontblockobj->ttf_fonts_block_offset,
fontblockobj->ttf_fonts_block_offset);
printf("ttf_fonts_block_length: %d(%0x)\n", fontblockobj->ttf_fonts_block_length,
fontblockobj->ttf_fonts_block_length);
printf("vector_fonts_block_offset: %d(%0x)\n", fontblockobj->vector_fonts_block_offset,
fontblockobj->vector_fonts_block_offset);
printf("vector_fonts_block_length: %d(%0x)\n", fontblockobj->vector_fonts_block_length,
fontblockobj->vector_fonts_block_length);
printf("text_fonts_block_offset: %d(%0x)\n", fontblockobj->text_fonts_block_offset,
fontblockobj->text_fonts_block_offset);
printf("text_fonts_block_length: %d(%0x)\n", fontblockobj->text_fonts_block_length,
fontblockobj->text_fonts_block_length);
printf("property_block_offset: %d(%0x)\n", fontblockobj->property_block_offset,
fontblockobj->property_block_offset);
printf("property_block_length: %d(%0x)\n", fontblockobj->property_block_length,
fontblockobj->property_block_length);
#endif
g_total_system_font = 0;
if ( fontblockobj->num_ttf_fonts > 0 ) {
fontblockobj->sizes_of_ttf_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_ttf_fonts);
fontblockobj->offsets_of_ttf_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_ttf_fonts);
fontblockobj->ttf_fonts = NULL;
fontblockobj->ttf_fonts = (ttf_font_t *)elm_alloc(1, fontblockobj->num_ttf_fonts * sizeof(ttf_font_t));
JUMP_IF_NULL(fontblockobj->sizes_of_ttf_data, error_exit);
JUMP_IF_NULL(fontblockobj->offsets_of_ttf_data, error_exit);
JUMP_IF_NULL(fontblockobj->ttf_fonts, error_exit);
memset(fontblockobj->ttf_fonts, 0, fontblockobj->num_ttf_fonts * sizeof(ttf_font_t));
for(int i=0; i<fontblockobj->num_ttf_fonts; i++)
{
fontblockobj->sizes_of_ttf_data[i] = *(uint32_t *)(data + (i) * 4 + fontblockobj->ttf_fonts_block_offset);
printf("ttf-DataSize: %d(%0x)\n", fontblockobj->sizes_of_ttf_data[i],
fontblockobj->sizes_of_ttf_data[i]);
fontblockobj->offsets_of_ttf_data[i] = *(uint32_t *)(data + (i + fontblockobj->num_ttf_fonts) * 4 + fontblockobj->ttf_fonts_block_offset);
printf("ttf-offset: %d(%0x)\n", fontblockobj->offsets_of_ttf_data[i],
fontblockobj->offsets_of_ttf_data[i]);
if (fontblockobj->sizes_of_ttf_data[i] == 0)
{
continue;
}
_process_ttf_font_data(data, (uint8_t *)(data + fontblockobj->offsets_of_ttf_data[i]), fontblockobj, i);
}
}
if ( fontblockobj->num_vector_fonts > 0 ) {
fontblockobj->sizes_of_vector_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_vector_fonts);
fontblockobj->offsets_of_vector_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_vector_fonts);
fontblockobj->vector_fonts = NULL;
fontblockobj->vector_fonts = (vector_font_t *)elm_alloc(1, fontblockobj->num_vector_fonts * sizeof(vector_font_t));
JUMP_IF_NULL(fontblockobj->sizes_of_vector_data, error_exit);
JUMP_IF_NULL(fontblockobj->offsets_of_vector_data, error_exit);
JUMP_IF_NULL(fontblockobj->vector_fonts, error_exit);
memset(fontblockobj->vector_fonts, 0, fontblockobj->num_vector_fonts * sizeof(vector_font_t));
for(int i=0; i<fontblockobj->num_vector_fonts; i++)
{
fontblockobj->sizes_of_vector_data[i] = *(uint32_t *)(data + (i) * 4 + fontblockobj->vector_fonts_block_offset);
#ifdef ENABLE_DEBUG_TRACE
printf("vector-DataSize: %d(%0x)\n", fontblockobj->sizes_of_vector_data[i],
fontblockobj->sizes_of_vector_data[i]);
#endif
fontblockobj->offsets_of_vector_data[i] = *(uint32_t *)(data + (i + fontblockobj->num_vector_fonts) * 4 + fontblockobj->vector_fonts_block_offset);
#ifdef ENABLE_DEBUG_TRACE
printf("vector-offset: %d(%0x)\n", fontblockobj->offsets_of_vector_data[i],
fontblockobj->offsets_of_vector_data[i]);
#endif
if (fontblockobj->sizes_of_vector_data[i] == 0)
{
continue;
}
_process_vector_font_data(data, (uint8_t *)(data + fontblockobj->offsets_of_vector_data[i]), fontblockobj, i);
}
}
if ( fontblockobj->num_text_fonts > 0 ) {
fontblockobj->sizes_of_text_font_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_text_fonts);
fontblockobj->offsets_of_text_font_data =
(unsigned int *)alloc_mem(4 * fontblockobj->num_text_fonts);
fontblockobj->text_fonts = NULL;
fontblockobj->text_fonts = (ttf_font_t *)elm_alloc(1, fontblockobj->num_text_fonts * sizeof(ttf_font_t));
JUMP_IF_NULL(fontblockobj->sizes_of_text_font_data, error_exit);
JUMP_IF_NULL(fontblockobj->offsets_of_text_font_data, error_exit);
JUMP_IF_NULL(fontblockobj->text_fonts, error_exit);
memset(fontblockobj->text_fonts, 0, fontblockobj->num_text_fonts * sizeof(ttf_font_t));
for(int i=0; i<fontblockobj->num_text_fonts; i++)
{
fontblockobj->sizes_of_text_font_data[i] = *(uint32_t *)(data + (i) * 4 + fontblockobj->text_fonts_block_offset);
#ifdef ENABLE_DEBUG_TRACE
printf("textfont-DataSize: %d(%0x)\n", fontblockobj->sizes_of_text_font_data[i],
fontblockobj->sizes_of_text_font_data[i]);
#endif
fontblockobj->offsets_of_text_font_data[i] = *(uint32_t *)(data + (i + fontblockobj->num_text_fonts) * 4 + fontblockobj->text_fonts_block_offset);
#ifdef ENABLE_DEBUG_TRACE
printf("textfont-offset: %d(%0x)\n", fontblockobj->offsets_of_text_font_data[i],
fontblockobj->offsets_of_text_font_data[i]);
#endif
if (fontblockobj->sizes_of_text_font_data[i] == 0)
{
continue;
}
_process_text_font_data(data, (uint8_t *)(data + fontblockobj->offsets_of_text_font_data[i]), fontblockobj, i);
}
}
return 0;
error_exit:
destroy_font_data();
return -1;
}
#if (defined(__ICCARM__))
/*
* Disable the unaligned structure attribute warning. Due to the packed data
* structures used to interpret ELM objects data the IAR compiler issues a
* number of warnings that certain attributes of the headers might be unaligned.
* This is not true, however, as all atributes are manually aligned to 4 bytes.
*/
#pragma diag_suppress = Pa039
#endif
#define TEXT_CONTENT_OFFSET_WITHOUT_TRANSFORM 9 * 4
#define TRANSFORM_MATRIX_LENGTH 9 * 4
ElmHandle _load_text_data(uint8_t *data, el_Obj_EVO *evo)
{
el_Obj_TEXT *evo_text = NULL;
uint8_t *text_data = NULL;
el_Text_Header *text_header = (el_Text_Header *)data;
if (evo == NULL) {
#if (RTOS && DDRLESS) || BAREMETAL
evo = alloc_evo(1);
#else
evo = (el_Obj_EVO *)elm_alloc(1, sizeof(el_Obj_TEXT));
#endif
}
JUMP_IF_NULL(evo, error_exit);
#ifdef ENABLE_STRICT_DEBUG_MEMSET
memset(evo, 0, sizeof(el_Obj_EVO));
#endif
evo_text = (el_Obj_TEXT *)evo;
/*
Default transform matrix is,
identity matrix
no-scaling
zero-translate
*/
_init_transform(&evo_text->defaultAttrib.transform);
memcpy(&evo_text->defaultAttrib.transform.matrix, &text_header->matrix,
sizeof(vg_lite_matrix_t));
text_data = (uint8_t *)elm_alloc(1, text_header->data_length);
memcpy(text_data, (void *)(data + sizeof(el_Text_Header)), text_header->data_length);
evo_text->tspan_has_dx_dy = text_header->tspan_has_dx_dy;
evo_text->x_pos = (int)text_header->x_pos;
evo_text->y_pos = (int)text_header->y_pos;
evo_text->text_anchor = text_header->text_flags.text_anchor;
evo_text->font_id = (int)text_header->font_id;
evo_text->font_size = (int)text_header->font_size;
evo_text->msg = text_data;
evo_text->defaultAttrib.quality = (ELM_QUALITY)VG_LITE_HIGH;
evo_text->defaultAttrib.fill_rule = ELM_EVO_FILL_NZ;
evo_text->defaultAttrib.blend = ELM_BLEND_SRC_OVER;
evo_text->defaultAttrib.paint.type = ELM_PAINT_TEXT;
evo_text->defaultAttrib.paint.color = text_header->color;
evo_text->object.type = ELM_OBJECT_TYPE_EVO;
evo_text->object.reference = 0;
evo_text->attribute = evo_text->defaultAttrib;
ref_object(&evo_text->object);
JUMP_IF_NON_ZERO_VALUE(add_object(&evo_text->object), error_exit);
return evo_text->object.handle;
error_exit:
if ( (evo_text) && (evo_text->msg != NULL) ) {
elm_free(evo_text->msg);
evo_text->msg = NULL;
}
if ( evo != NULL ) {
elm_free(evo);
}
return ELM_NULL_HANDLE;
}
#if (defined(__ICCARM__))
/* Restore the unaligned data structure attribute warning */
#pragma diag_default = Pa039
#endif
void _unload_text(el_Obj_EVO *evo)
{
el_Obj_TEXT *evo_text = (el_Obj_TEXT *)evo;
if(evo_text->msg != NULL)
{
elm_free(evo_text->msg);
evo_text->msg = NULL;
}
}
void destroy_font_data()
{
int i=0, j = 0;
if(fontblockobj != NULL) {
if(fontblockobj->sizes_of_ttf_data != NULL){
elm_free(fontblockobj->sizes_of_ttf_data);
fontblockobj->sizes_of_ttf_data = NULL;
}
if(fontblockobj->offsets_of_ttf_data != NULL){
elm_free(fontblockobj->offsets_of_ttf_data);
fontblockobj->offsets_of_ttf_data = NULL;
}
if(fontblockobj->sizes_of_vector_data != NULL){
elm_free(fontblockobj->sizes_of_vector_data);
fontblockobj->sizes_of_vector_data = NULL;
}
if(fontblockobj->offsets_of_vector_data != NULL){
elm_free(fontblockobj->offsets_of_vector_data);
fontblockobj->offsets_of_vector_data = NULL;
}
if(fontblockobj->sizes_of_text_font_data != NULL){
elm_free(fontblockobj->sizes_of_text_font_data);
fontblockobj->sizes_of_text_font_data = NULL;
}
if(fontblockobj->offsets_of_text_font_data != NULL){
elm_free(fontblockobj->offsets_of_text_font_data);
fontblockobj->offsets_of_text_font_data = NULL;
}
for(i=0; i<fontblockobj->num_ttf_fonts; i++)
{
if(fontblockobj->ttf_fonts[i].fields != NULL){
for(j=0; j<fontblockobj->ttf_fonts[i].num_fields; j++)
{
if(fontblockobj->ttf_fonts[i].fields[j].data != NULL) {
elm_free(fontblockobj->ttf_fonts[i].fields[j].data);
fontblockobj->ttf_fonts[i].fields[j].data = NULL;
}
}
elm_free(fontblockobj->ttf_fonts[i].fields);
fontblockobj->ttf_fonts[i].fields = NULL;
}
}
if(fontblockobj->ttf_fonts != NULL){
elm_free(fontblockobj->ttf_fonts);
fontblockobj->ttf_fonts = NULL;
}
for(i=0; i<fontblockobj->num_vector_fonts; i++)
{
if(fontblockobj->vector_fonts[i].fields != NULL){
for(j=0; j<fontblockobj->vector_fonts[i].num_fields; j++)
{
if(fontblockobj->vector_fonts[i].fields[j].data != NULL) {
elm_free(fontblockobj->vector_fonts[i].fields[j].data);
fontblockobj->vector_fonts[i].fields[j].data = NULL;
}
}
elm_free(fontblockobj->vector_fonts[i].fields);
fontblockobj->vector_fonts[i].fields = NULL;
}
}
if(fontblockobj->vector_fonts != NULL){
elm_free(fontblockobj->vector_fonts);
fontblockobj->vector_fonts = NULL;
}
for(i=0; i<fontblockobj->num_text_fonts; i++)
{
if(fontblockobj->text_fonts[i].fields != NULL){
for(j=0; j<fontblockobj->text_fonts[i].num_fields; j++)
{
if(fontblockobj->text_fonts[i].fields[j].data != NULL) {
elm_free(fontblockobj->text_fonts[i].fields[j].data);
fontblockobj->text_fonts[i].fields[j].data = NULL;
}
}
elm_free(fontblockobj->text_fonts[i].fields);
fontblockobj->text_fonts[i].fields = NULL;
}
}
if(fontblockobj->text_fonts != NULL){
elm_free(fontblockobj->text_fonts);
fontblockobj->text_fonts = NULL;
}
elm_free(fontblockobj);
fontblockobj = NULL;
}
vg_lite_unload_font_data();
for(int i=0; i<g_total_system_font; i++)
{
if(g_font_properties[i][eFontNameProperty].value.data != NULL)
{
elm_free(g_font_properties[i][eFontNameProperty].value.data);
g_font_properties[i][eFontNameProperty].value.data = NULL;
}
}
return;
}
void _release_default_text_parameters(void)
{
if(g_default_font_properties[eFontNameProperty].value.data != NULL)
{
elm_free(g_default_font_properties[eFontNameProperty].value.data);
g_default_font_properties[eFontNameProperty].value.data = NULL;
}
return;
}

View File

@ -0,0 +1,207 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "Elm.h"
#include "velm.h"
#ifndef _elm_text_h_
#define _elm_text_h_
#ifdef __cplusplus
extern "C" {
#endif
typedef enum eElemType {
eElemTypeLinearGradient = 0,
eElemTypePath = 1,
eElemTypeGroup = 2,
eElemTypeText = 3,
eElemTypeTspan = 4,
eElemTypeFont = 5,
eElemTypeTtfFont = 6,
eElemTypeVectorFont = 7,
eElemTypeTextFont = 8,
} eElemType_t;
typedef enum eFontVariant {
eFontVariantNormal = 1,
eFontVariantSmallCaps = 2,
eFontVariantInherit = 3,
} eFontVariant_t;
typedef enum eDisplayAlign {
eDisplayAlignBefore = 1,
eDisplayAlignCenter = 2,
eDisplayAlignAfter = 3,
eDisplayAlignAuto = 1,
} eDisplayAlign_t;
typedef enum eFontFields {
HORIZ_ADV_X = 0,
HORIZ_ORIGIN_X = 1,
ASCENT = 2,
ALPHABETIC = 3,
BBOX = 4,
CAP_HEIGHT = 5,
DESCENT = 6,
FONT_FAMILY = 7,
FONT_SIZE = 8,
FONT_STRETCH = 9,
FONT_STYLE = 10,
FONT_TYPE = 11,
FONT_VARIANT = 12,
FONT_WEIGHT = 13,
SLOPE = 14,
UNICODE_RANGE = 15,
UNITS_PER_EM = 16,
X_HEIGHT = 17,
TEXT_ANCHOR = 18,
MAX_FONT_ATTRIBUTES = 19,
} eFontFields_t;
typedef struct glyph {
uint8_t glyph_name;
uint8_t unicode;
uint32_t horiz_adv_x;
uint32_t path_data_length;
void *path_data;
} glyph_t;
typedef struct glyph_table {
uint32_t offset;
uint32_t size;
} glyph_table_t;
typedef union value_type {
uint32_t i_value;
float f_value;
char *data;
} value_type_t;
typedef struct font_field_info {
value_type_t value;
eFontFields_t eName;
} font_field_info_t;
typedef struct font_fields {
font_field_info_t info;
uint32_t offset;
uint32_t size;
unsigned char *data;
} font_fields_t;
typedef struct vector_font {
uint32_t id;
eElemType_t type;
uint32_t num_fields;
font_fields_t *fields;
glyph_table_t *glyph_table;
glyph_t *glyph_offset;
} vector_font_t;
typedef struct ttf_font {
uint32_t id;
eElemType_t type;
uint32_t num_fields;
font_fields_t *fields;
} ttf_font_t;
typedef struct font_prop {
uint32_t num_props;
font_fields_t *prop_values;
} font_prop_t;
typedef struct font_block {
uint32_t size;
eElemType_t type;
uint32_t num_ttf_fonts;
uint32_t num_vector_fonts;
uint32_t num_text_fonts;
uint32_t ttf_fonts_block_offset;
uint32_t ttf_fonts_block_length;
uint32_t vector_fonts_block_offset;
uint32_t vector_fonts_block_length;
uint32_t text_fonts_block_offset;
uint32_t text_fonts_block_length;
uint32_t property_block_offset;
uint32_t property_block_length;
font_prop_t *font_prop;
unsigned int *sizes_of_ttf_data;
unsigned int *offsets_of_ttf_data;
ttf_font_t *ttf_fonts;
unsigned int *sizes_of_vector_data;
unsigned int *offsets_of_vector_data;
vector_font_t *vector_fonts;
unsigned int *sizes_of_text_font_data;
unsigned int *offsets_of_text_font_data;
ttf_font_t *text_fonts;
} font_block_t;
typedef struct {
el_Object object;
el_Attribute attribute;
el_Attribute defaultAttrib;
uint32_t tspan_has_dx_dy;
uint32_t text_anchor;
uint32_t font_size;
uint32_t font_id;
uint32_t x_pos;
uint32_t y_pos;
unsigned char *msg;
} el_Obj_TEXT;
typedef enum eAppProperties {
eFontNameProperty,
eFontHeightProperty,
eFontWeightProperty,
eFontStretchProperty,
eFontStyleProperty,
eTextColorProperty,
eTextAlignProperty,
eMaxFontProperties,
} eAppProperties_t;
vg_lite_error_t draw_text(el_Obj_Buffer *buff,
el_Obj_EVO *evo, vg_lite_matrix_t *mat);
extern font_block_t *fontblockobj;
int _load_font_data(uint8_t *data);
ElmHandle _load_text_data(uint8_t *data, el_Obj_EVO *evo);
void _unload_text(el_Obj_EVO *evo);
void _init_transform(el_Transform *transform);
void initialize_elm_text(void);
void destroy_font_data();
void _release_default_text_parameters(void);
#ifdef __cplusplus
}
#endif
#endif /* _elm_text_h_ */

View File

@ -0,0 +1,30 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#define ABS_ARY(x) (void *)x, sizeof(x), 0

View File

@ -0,0 +1,81 @@
/*
* Copyright 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DC_FB_H_
#define _FSL_DC_FB_H_
#include "fsl_video_common.h"
/*!
* @addtogroup dc_fb
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief frame buffer information. */
typedef struct _dc_fb_info
{
uint16_t startX; /*!< The start position in the panel. */
uint16_t startY; /*!< The start position in the panel. */
uint16_t width; /*!< How many pixels in one line of the frame buffer.*/
uint16_t height; /*!< How many lines in one frame buffer. */
uint16_t strideBytes; /*!< Stride of the frame buffer */
video_pixel_format_t pixelFormat; /*!< Pixel format of the frame buffer */
} dc_fb_info_t;
/*! @brief Display controller frame callback. */
typedef void (*dc_fb_callback_t)(void *param, void *inactiveBuffer);
/*! @brief Display controller. */
typedef struct _dc_fb dc_fb_t;
/*! @brief Display controller operations. */
typedef struct _dc_fb_ops
{
status_t (*init)(const dc_fb_t *dc);
status_t (*deinit)(const dc_fb_t *dc);
status_t (*enableLayer)(const dc_fb_t *dc, uint8_t layer);
status_t (*disableLayer)(const dc_fb_t *dc, uint8_t layer);
status_t (*setLayerConfig)(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t (*getLayerDefaultConfig)(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t (*setFrameBuffer)(const dc_fb_t *dc, uint8_t layer, void *frameBuffer);
uint32_t (*getProperty)(const dc_fb_t *dc);
void (*setCallback)(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param);
} dc_fb_ops_t;
/*! @brief Display controller property. */
enum _dc_fb_property
{
kDC_FB_ReserveFrameBuffer = (1 << 0), /*< One frame buffer is always used as the DC active buffer. */
kDC_FB_TwoDimensionMemoryWrite = (1 << 1), /*< Support writing memory to device in two dimension way. */
};
/*! @brief Display controller driver handle. */
struct _dc_fb
{
const dc_fb_ops_t *ops; /* Display controller operations. */
void *prvData; /* Private data for the display controller. */
const void *config; /* Configuration for the display controller. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_DC_FB_H_ */

View File

@ -0,0 +1,264 @@
/*
* Copyright 2019-2020, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dc_fb_elcdif.h"
/*******************************************************************************
* Definitions
******************************************************************************/
const dc_fb_ops_t g_dcFbOpsElcdif = {
.init = DC_FB_ELCDIF_Init,
.deinit = DC_FB_ELCDIF_Deinit,
.enableLayer = DC_FB_ELCDIF_EnableLayer,
.disableLayer = DC_FB_ELCDIF_DisableLayer,
.setLayerConfig = DC_FB_ELCDIF_SetLayerConfig,
.getLayerDefaultConfig = DC_FB_ELCDIF_GetLayerDefaultConfig,
.setFrameBuffer = DC_FB_ELCDIF_SetFrameBuffer,
.getProperty = DC_FB_ELCDIF_GetProperty,
.setCallback = DC_FB_ELCDIF_SetCallback,
};
typedef struct
{
video_pixel_format_t videoFormat;
elcdif_pixel_format_t elcdifFormat;
} dc_fb_elcdif_pixel_foramt_map_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
static status_t DC_FB_ELCDIF_GetPixelFormat(video_pixel_format_t input, elcdif_pixel_format_t *output);
/*******************************************************************************
* Variables
******************************************************************************/
static const dc_fb_elcdif_pixel_foramt_map_t s_elcdifPixelFormatMap[] = {
{kVIDEO_PixelFormatLUT8, kELCDIF_PixelFormatRAW8},
{kVIDEO_PixelFormatRGB565, kELCDIF_PixelFormatRGB565},
{
kVIDEO_PixelFormatXRGB8888,
kELCDIF_PixelFormatXRGB8888,
},
{
kVIDEO_PixelFormatRGB888,
kELCDIF_PixelFormatRGB888,
}};
/*******************************************************************************
* Code
******************************************************************************/
static status_t DC_FB_ELCDIF_GetPixelFormat(video_pixel_format_t input, elcdif_pixel_format_t *output)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(s_elcdifPixelFormatMap); i++)
{
if (s_elcdifPixelFormatMap[i].videoFormat == input)
{
*output = s_elcdifPixelFormatMap[i].elcdifFormat;
return kStatus_Success;
}
}
return kStatus_InvalidArgument;
}
status_t DC_FB_ELCDIF_Init(const dc_fb_t *dc)
{
const dc_fb_elcdif_config_t *dcConfig;
elcdif_rgb_mode_config_t elcdifConfig = {0};
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
if (0U == dcHandle->initTimes++)
{
dcConfig = (const dc_fb_elcdif_config_t *)(dc->config);
elcdifConfig.panelWidth = dcConfig->width;
elcdifConfig.panelHeight = dcConfig->height;
elcdifConfig.hsw = (uint8_t)dcConfig->hsw;
elcdifConfig.hfp = (uint8_t)dcConfig->hfp;
elcdifConfig.hbp = (uint8_t)dcConfig->hbp;
elcdifConfig.vsw = (uint8_t)dcConfig->vsw;
elcdifConfig.vfp = (uint8_t)dcConfig->vfp;
elcdifConfig.vbp = (uint8_t)dcConfig->vbp;
elcdifConfig.bufferAddr = 0;
elcdifConfig.dataBus = dcConfig->dataBus;
elcdifConfig.pixelFormat = DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT_ELCDIF;
elcdifConfig.polarityFlags = dcConfig->polarityFlags;
dcHandle->height = dcConfig->height;
dcHandle->width = dcConfig->width;
dcHandle->elcdif = dcConfig->elcdif;
ELCDIF_RgbModeInit(dcHandle->elcdif, &elcdifConfig);
}
return kStatus_Success;
}
status_t DC_FB_ELCDIF_Deinit(const dc_fb_t *dc)
{
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
if (dcHandle->initTimes > 0U)
{
if ((--dcHandle->initTimes) == 0U)
{
ELCDIF_Deinit(dcHandle->elcdif);
}
}
return kStatus_Success;
}
status_t DC_FB_ELCDIF_EnableLayer(const dc_fb_t *dc, uint8_t layer)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
status_t status = kStatus_Success;
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
/* If the layer is already started. */
if (!dcHandle->layers[layer].enabled)
{
/* Must have valid frame buffer to show. */
if (dcHandle->layers[layer].activeBuffer == NULL)
{
status = kStatus_Fail;
}
else
{
ELCDIF_RgbModeStart(dcHandle->elcdif);
dcHandle->layers[layer].enabled = true;
ELCDIF_EnableInterrupts(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDoneInterruptEnable);
}
}
return status;
}
status_t DC_FB_ELCDIF_DisableLayer(const dc_fb_t *dc, uint8_t layer)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
if (dcHandle->layers[layer].enabled)
{
ELCDIF_RgbModeStop(dcHandle->elcdif);
dcHandle->layers[layer].enabled = false;
ELCDIF_DisableInterrupts(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDoneInterruptEnable);
}
return kStatus_Success;
}
status_t DC_FB_ELCDIF_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
elcdif_pixel_format_t pixelFormat;
status_t status;
dc_fb_elcdif_handle_t *dcHandle = (dc_fb_elcdif_handle_t *)(dc->prvData);
assert(fbInfo->startX == 0U);
assert(fbInfo->startY == 0U);
assert(fbInfo->width == dcHandle->width);
assert(fbInfo->height == dcHandle->height);
assert(fbInfo->strideBytes == VIDEO_GetPixelSizeBits(fbInfo->pixelFormat) * dcHandle->width / 8U);
status = DC_FB_ELCDIF_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat);
if (kStatus_Success != status)
{
return status;
}
ELCDIF_RgbModeSetPixelFormat(dcHandle->elcdif, pixelFormat);
return kStatus_Success;
}
status_t DC_FB_ELCDIF_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
dc_fb_elcdif_handle_t *dcHandle = (dc_fb_elcdif_handle_t *)(dc->prvData);
fbInfo->startX = 0;
fbInfo->startY = 0;
fbInfo->width = dcHandle->width;
fbInfo->height = dcHandle->height;
fbInfo->strideBytes = 2U * dcHandle->width;
fbInfo->pixelFormat = DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT;
return kStatus_Success;
}
status_t DC_FB_ELCDIF_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
ELCDIF_SetNextBufferAddr(dcHandle->elcdif, (uint32_t)(uint8_t *)frameBuffer);
dcHandle->layers[layer].inactiveBuffer = frameBuffer;
/*
* If the layer is not started, set the current buffer and next buffer to
* new frame buffer, there is not pending frame.
* If the layer already started, only set the next buffer, and the new frameBuffer
* is pending until current buffer switched out.
*/
if (!dcHandle->layers[layer].enabled)
{
dcHandle->elcdif->CUR_BUF = ELCDIF_ADDR_CPU_2_IP((uint32_t)(uint8_t *)frameBuffer);
dcHandle->layers[layer].activeBuffer = frameBuffer;
}
else
{
dcHandle->layers[layer].framePending = true;
}
return kStatus_Success;
}
void DC_FB_ELCDIF_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param)
{
assert(layer < DC_FB_ELCDIF_MAX_LAYER);
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
dcHandle->layers[layer].callback = callback;
dcHandle->layers[layer].cbParam = param;
}
uint32_t DC_FB_ELCDIF_GetProperty(const dc_fb_t *dc)
{
return (uint32_t)kDC_FB_ReserveFrameBuffer;
}
void DC_FB_ELCDIF_IRQHandler(const dc_fb_t *dc)
{
dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
dc_fb_elcdif_layer_t *layer;
void *oldActiveBuffer;
ELCDIF_ClearInterruptStatus(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDone);
for (uint8_t i = 0; i < DC_FB_ELCDIF_MAX_LAYER; i++)
{
if (dcHandle->layers[i].framePending)
{
layer = &dcHandle->layers[i];
oldActiveBuffer = layer->activeBuffer;
layer->activeBuffer = layer->inactiveBuffer;
dcHandle->layers[i].framePending = false;
layer->callback(layer->cbParam, oldActiveBuffer);
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DC_FB_ELCDIF_H_
#define _FSL_DC_FB_ELCDIF_H_
#include "fsl_dc_fb.h"
#include "fsl_elcdif.h"
/*
* Change log:
*
* 1.0.1
* - Fixed MISRA-C 2012 issues.
*
* 1.0.0
* - Initial version
*/
/*!
* @addtogroup dc_fb_elcdif
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#define DC_FB_ELCDIF_MAX_LAYER 1U /* Only support one layer currently. */
#define DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT kVIDEO_PixelFormatRGB565
#define DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT_ELCDIF kELCDIF_PixelFormatRGB565
/*! @brief Data for ELCDIF display controller layer. */
typedef struct _dc_fb_elcdif_layer
{
bool enabled; /*!< The layer is enabled. */
volatile bool framePending; /*!< New frame pending. */
void *activeBuffer; /*!< The frame buffer which is shown. */
void *inactiveBuffer; /*!< The frame buffer which will be shown. */
dc_fb_callback_t callback; /*!< Callback for buffer switch off. */
void *cbParam; /*!< Callback parameter. */
} dc_fb_elcdif_layer_t;
/*! @brief Data for ELCDIF display controller driver handle. */
typedef struct _dc_fb_elcdif_handle
{
LCDIF_Type *elcdif; /*!< eLCDIF peripheral. */
uint8_t initTimes; /*!< How many times the DC is initialized. */
uint16_t height; /*!< Panel height. */
uint16_t width; /*!< Panel width. */
dc_fb_elcdif_layer_t layers[DC_FB_ELCDIF_MAX_LAYER]; /*!< Information of the layer. */
} dc_fb_elcdif_handle_t;
/*! @brief Configuration for ELCDIF display controller driver handle. */
typedef struct _dc_fb_elcdif_config
{
LCDIF_Type *elcdif; /*!< ELCDIF peripheral. */
uint16_t width; /*!< Width of the panel. */
uint16_t height; /*!< Height of the panel. */
uint16_t hsw; /*!< HSYNC pulse width. */
uint16_t hfp; /*!< Horizontal front porch. */
uint16_t hbp; /*!< Horizontal back porch. */
uint16_t vsw; /*!< VSYNC pulse width. */
uint16_t vfp; /*!< Vertical front porch. */
uint16_t vbp; /*!< Vertical back porch. */
uint32_t polarityFlags; /*!< Control flags, OR'ed value of @ref _elcdif_polarity_flags. */
elcdif_lcd_data_bus_t dataBus; /*!< LCD data bus. */
} dc_fb_elcdif_config_t;
extern const dc_fb_ops_t g_dcFbOpsElcdif;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
status_t DC_FB_ELCDIF_Init(const dc_fb_t *dc);
status_t DC_FB_ELCDIF_Deinit(const dc_fb_t *dc);
status_t DC_FB_ELCDIF_EnableLayer(const dc_fb_t *dc, uint8_t layer);
status_t DC_FB_ELCDIF_DisableLayer(const dc_fb_t *dc, uint8_t layer);
status_t DC_FB_ELCDIF_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t DC_FB_ELCDIF_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t DC_FB_ELCDIF_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer);
uint32_t DC_FB_ELCDIF_GetProperty(const dc_fb_t *dc);
void DC_FB_ELCDIF_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param);
void DC_FB_ELCDIF_IRQHandler(const dc_fb_t *dc);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_DC_FB_ELCDIF_H_ */

View File

@ -0,0 +1,288 @@
/*
* Copyright (c) 2019-2020, 2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dc_fb_lcdifv2.h"
#if defined(SDK_OS_RTOS)
#include "rtthread.h"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
const dc_fb_ops_t g_dcFbOpsLcdifv2 = {
.init = DC_FB_LCDIFV2_Init,
.deinit = DC_FB_LCDIFV2_Deinit,
.enableLayer = DC_FB_LCDIFV2_EnableLayer,
.disableLayer = DC_FB_LCDIFV2_DisableLayer,
.setLayerConfig = DC_FB_LCDIFV2_SetLayerConfig,
.getLayerDefaultConfig = DC_FB_LCDIFV2_GetLayerDefaultConfig,
.setFrameBuffer = DC_FB_LCDIFV2_SetFrameBuffer,
.getProperty = DC_FB_LCDIFV2_GetProperty,
.setCallback = DC_FB_LCDIFV2_SetCallback,
};
typedef struct
{
video_pixel_format_t videoFormat;
lcdifv2_pixel_format_t lcdifv2Format;
} dc_fb_lcdifv2_pixel_foramt_map_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
static status_t DC_FB_LCDIFV2_GetPixelFormat(video_pixel_format_t input, lcdifv2_pixel_format_t *output);
/*******************************************************************************
* Variables
******************************************************************************/
static const dc_fb_lcdifv2_pixel_foramt_map_t s_lcdifv2PixelFormatMap[] = {
{kVIDEO_PixelFormatRGB565, kLCDIFV2_PixelFormatRGB565},
{kVIDEO_PixelFormatRGB888, kLCDIFV2_PixelFormatRGB888},
{kVIDEO_PixelFormatXRGB8888, kLCDIFV2_PixelFormatARGB8888},
{kVIDEO_PixelFormatXBGR8888, kLCDIFV2_PixelFormatABGR8888},
{kVIDEO_PixelFormatLUT8, kLCDIFV2_PixelFormatIndex8BPP},
{kVIDEO_PixelFormatXRGB4444, kLCDIFV2_PixelFormatARGB4444},
{kVIDEO_PixelFormatXRGB1555, kLCDIFV2_PixelFormatARGB1555}};
/*******************************************************************************
* Code
******************************************************************************/
static status_t DC_FB_LCDIFV2_GetPixelFormat(video_pixel_format_t input, lcdifv2_pixel_format_t *output)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(s_lcdifv2PixelFormatMap); i++)
{
if (s_lcdifv2PixelFormatMap[i].videoFormat == input)
{
*output = s_lcdifv2PixelFormatMap[i].lcdifv2Format;
return kStatus_Success;
}
}
return kStatus_InvalidArgument;
}
status_t DC_FB_LCDIFV2_Init(const dc_fb_t *dc)
{
status_t status = kStatus_Success;
const dc_fb_lcdifv2_config_t *dcConfig;
lcdifv2_display_config_t lcdifv2Config = {0};
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
if (0U == dcHandle->initTimes++)
{
dcConfig = (const dc_fb_lcdifv2_config_t *)(dc->config);
LCDIFV2_DisplayGetDefaultConfig(&lcdifv2Config);
lcdifv2Config.panelWidth = dcConfig->width;
lcdifv2Config.panelHeight = dcConfig->height;
lcdifv2Config.hsw = (uint8_t)dcConfig->hsw;
lcdifv2Config.hfp = (uint8_t)dcConfig->hfp;
lcdifv2Config.hbp = (uint8_t)dcConfig->hbp;
lcdifv2Config.vsw = (uint8_t)dcConfig->vsw;
lcdifv2Config.vfp = (uint8_t)dcConfig->vfp;
lcdifv2Config.vbp = (uint8_t)dcConfig->vbp;
lcdifv2Config.polarityFlags = dcConfig->polarityFlags;
lcdifv2Config.lineOrder = dcConfig->lineOrder;
dcHandle->height = dcConfig->height;
dcHandle->width = dcConfig->width;
dcHandle->lcdifv2 = dcConfig->lcdifv2;
dcHandle->domain = dcConfig->domain;
LCDIFV2_Init(dcHandle->lcdifv2);
LCDIFV2_SetDisplayConfig(dcHandle->lcdifv2, &lcdifv2Config);
LCDIFV2_EnableInterrupts(dcHandle->lcdifv2, dcHandle->domain, (uint32_t)kLCDIFV2_VerticalBlankingInterrupt);
LCDIFV2_EnableDisplay(dcHandle->lcdifv2, true);
}
return status;
}
status_t DC_FB_LCDIFV2_Deinit(const dc_fb_t *dc)
{
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
if (dcHandle->initTimes > 0U)
{
if (--dcHandle->initTimes == 0U)
{
LCDIFV2_DisableInterrupts(dcHandle->lcdifv2, dcHandle->domain,
(uint32_t)kLCDIFV2_VerticalBlankingInterrupt);
LCDIFV2_Deinit(dcHandle->lcdifv2);
}
}
return kStatus_Success;
}
status_t DC_FB_LCDIFV2_EnableLayer(const dc_fb_t *dc, uint8_t layer)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
status_t status = kStatus_Success;
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
/* If the layer is not started. */
if (!dcHandle->layers[layer].enabled)
{
LCDIFV2_SetLayerBackGroundColor(dcHandle->lcdifv2, layer, 0U);
LCDIFV2_EnableLayer(dcHandle->lcdifv2, layer, true);
LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
dcHandle->layers[layer].shadowLoadPending = true;
while (true == dcHandle->layers[layer].shadowLoadPending)
{
#if defined(SDK_OS_RTOS)
rt_thread_delay(1);
#endif
}
dcHandle->layers[layer].activeBuffer = dcHandle->layers[layer].inactiveBuffer;
dcHandle->layers[layer].enabled = true;
}
return status;
}
status_t DC_FB_LCDIFV2_DisableLayer(const dc_fb_t *dc, uint8_t layer)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
if (dcHandle->layers[layer].enabled)
{
LCDIFV2_EnableLayer(dcHandle->lcdifv2, layer, false);
LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
dcHandle->layers[layer].enabled = false;
}
return kStatus_Success;
}
status_t DC_FB_LCDIFV2_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
lcdifv2_buffer_config_t bufferConfig = {0};
lcdifv2_pixel_format_t pixelFormat;
LCDIFV2_Type *lcdifv2;
status_t status;
dc_fb_lcdifv2_handle_t *dcHandle = (dc_fb_lcdifv2_handle_t *)(dc->prvData);
lcdifv2 = dcHandle->lcdifv2;
status = DC_FB_LCDIFV2_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat);
if (kStatus_Success != status)
{
return status;
}
LCDIFV2_SetLayerSize(lcdifv2, layer, fbInfo->width, fbInfo->height);
LCDIFV2_SetLayerOffset(lcdifv2, layer, fbInfo->startX, fbInfo->startY);
bufferConfig.strideBytes = fbInfo->strideBytes;
bufferConfig.pixelFormat = pixelFormat;
LCDIFV2_SetLayerBufferConfig(lcdifv2, layer, &bufferConfig);
return kStatus_Success;
}
status_t DC_FB_LCDIFV2_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
dc_fb_lcdifv2_handle_t *dcHandle = (dc_fb_lcdifv2_handle_t *)(dc->prvData);
fbInfo->startX = 0;
fbInfo->startY = 0;
fbInfo->width = dcHandle->width;
fbInfo->height = dcHandle->height;
fbInfo->strideBytes = DC_FB_LCDIFV2_DEFAULT_BYTE_PER_PIXEL * dcHandle->width;
fbInfo->pixelFormat = DC_FB_LCDIFV2_DEFAULT_PIXEL_FORMAT;
return kStatus_Success;
}
status_t DC_FB_LCDIFV2_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
LCDIFV2_SetLayerBufferAddr(dcHandle->lcdifv2, layer, (uint32_t)(uint8_t *)frameBuffer);
dcHandle->layers[layer].inactiveBuffer = frameBuffer;
if (dcHandle->layers[layer].enabled)
{
LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
dcHandle->layers[layer].shadowLoadPending = true;
dcHandle->layers[layer].framePending = true;
}
else
{
}
return kStatus_Success;
}
void DC_FB_LCDIFV2_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param)
{
assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
dcHandle->layers[layer].callback = callback;
dcHandle->layers[layer].cbParam = param;
}
uint32_t DC_FB_LCDIFV2_GetProperty(const dc_fb_t *dc)
{
return (uint32_t)kDC_FB_ReserveFrameBuffer;
}
void DC_FB_LCDIFV2_IRQHandler(const dc_fb_t *dc)
{
uint32_t intStatus;
dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
dc_fb_lcdifv2_layer_t *layer;
void *oldActiveBuffer;
intStatus = LCDIFV2_GetInterruptStatus(dcHandle->lcdifv2, dcHandle->domain);
LCDIFV2_ClearInterruptStatus(dcHandle->lcdifv2, dcHandle->domain, intStatus);
if (0U == (intStatus & (uint32_t)kLCDIFV2_VerticalBlankingInterrupt))
{
return;
}
for (uint8_t i = 0; i < DC_FB_LCDIFV2_MAX_LAYER; i++)
{
if (dcHandle->layers[i].shadowLoadPending)
{
dcHandle->layers[i].shadowLoadPending = false;
}
if (dcHandle->layers[i].framePending)
{
layer = &dcHandle->layers[i];
oldActiveBuffer = layer->activeBuffer;
layer->activeBuffer = layer->inactiveBuffer;
dcHandle->layers[i].framePending = false;
layer->callback(layer->cbParam, oldActiveBuffer);
}
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2019-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DC_FB_LCDIFV2_H_
#define _FSL_DC_FB_LCDIFV2_H_
#include "fsl_dc_fb.h"
#include "fsl_lcdifv2.h"
/*
* Change log:
*
* 1.0.2
* - Add more pixel format support.
*
* 1.0.1
* - Fix MISRA-C 2012 issues.
*
* 1.0.0
* - Initial version
*/
/*!
* @addtogroup dc_fb_lcdifv2
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#define DC_FB_LCDIFV2_MAX_LAYER ((uint32_t)LCDIFV2_LAYER_COUNT)
#define DC_FB_LCDIFV2_DEFAULT_BUF_PER_LAYER 3U
#define DC_FB_LCDIFV2_DEFAULT_PIXEL_FORMAT kVIDEO_PixelFormatRGB565
#define DC_FB_LCDIFV2_DEFAULT_PIXEL_FORMAT_LCDIFV2 kLCDIFV2_PixelFormatRGB565
#define DC_FB_LCDIFV2_DEFAULT_BYTE_PER_PIXEL 2U
/*! @brief Data for LCDIFV2 display controller layer. */
typedef struct _dc_fb_lcdifv2_layer
{
bool enabled; /*!< The layer is enabled. */
volatile bool framePending; /*!< New frame pending. */
volatile bool shadowLoadPending; /*!< Shadow load pending. */
void *activeBuffer; /*!< The frame buffer which is shown. */
void *inactiveBuffer; /*!< The frame buffer which will be shown. */
dc_fb_callback_t callback; /*!< Callback for buffer switch off. */
void *cbParam; /*!< Callback parameter. */
} dc_fb_lcdifv2_layer_t;
/*! @brief Data for LCDIFV2 display controller driver handle. */
typedef struct _dc_fb_lcdifv2_handle
{
LCDIFV2_Type *lcdifv2; /*!< LCDIFV2 peripheral. */
uint8_t initTimes; /*!< How many times the DC is initialized. */
uint16_t height; /*!< Panel height. */
uint16_t width; /*!< Panel width. */
uint8_t domain; /*!< Domain used for interrupt. */
dc_fb_lcdifv2_layer_t layers[DC_FB_LCDIFV2_MAX_LAYER]; /*!< Information of the layer. */
} dc_fb_lcdifv2_handle_t;
/*! @brief Configuration for LCDIFV2 display controller driver handle. */
typedef struct _dc_fb_lcdifv2_config
{
LCDIFV2_Type *lcdifv2; /*!< LCDIFV2 peripheral. */
uint16_t width; /*!< Width of the panel. */
uint16_t height; /*!< Height of the panel. */
uint16_t hsw; /*!< HSYNC pulse width. */
uint16_t hfp; /*!< Horizontal front porch. */
uint16_t hbp; /*!< Horizontal back porch. */
uint16_t vsw; /*!< VSYNC pulse width. */
uint16_t vfp; /*!< Vertical front porch. */
uint16_t vbp; /*!< Vertical back porch. */
uint32_t polarityFlags; /*!< Control flags, OR'ed value of @ref _lcdifv2_polarity_flags. */
lcdifv2_line_order_t lineOrder; /*!< Line order. */
uint8_t domain; /*!< Domain used to for interrupt. */
} dc_fb_lcdifv2_config_t;
extern const dc_fb_ops_t g_dcFbOpsLcdifv2;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
status_t DC_FB_LCDIFV2_Init(const dc_fb_t *dc);
status_t DC_FB_LCDIFV2_Deinit(const dc_fb_t *dc);
status_t DC_FB_LCDIFV2_EnableLayer(const dc_fb_t *dc, uint8_t layer);
status_t DC_FB_LCDIFV2_DisableLayer(const dc_fb_t *dc, uint8_t layer);
status_t DC_FB_LCDIFV2_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t DC_FB_LCDIFV2_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo);
status_t DC_FB_LCDIFV2_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer);
uint32_t DC_FB_LCDIFV2_GetProperty(const dc_fb_t *dc);
void DC_FB_LCDIFV2_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param);
void DC_FB_LCDIFV2_IRQHandler(const dc_fb_t *dc);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_DC_FB_LCDIFV2_H_ */

View File

@ -0,0 +1,140 @@
/*
* Copyright 2017-2018 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DISPLAY_H_
#define _FSL_DISPLAY_H_
#include "fsl_video_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Display common configuration. */
typedef struct _display_common_cfg_t
{
uint16_t width;
uint16_t height;
uint16_t hsw; /*!< HSYNC pulse width. */
uint16_t hfp; /*!< Horizontal front porch. */
uint16_t hbp; /*!< Horizontal back porch. */
uint16_t vsw; /*!< VSYNC pulse width. */
uint16_t vfp; /*!< Vrtical front porch. */
uint16_t vbp; /*!< Vertical back porch. */
uint32_t clock; /* !< pixecl clock in kHz>. */
} display_common_cfg;
/*! @brief Display control flags. */
enum _display_flags
{
kDISPLAY_VsyncActiveLow = 0U, /*!< VSYNC active low. */
kDISPLAY_VsyncActiveHigh = (1U << 0U), /*!< VSYNC active high. */
kDISPLAY_HsyncActiveLow = 0U, /*!< HSYNC active low. */
kDISPLAY_HsyncActiveHigh = (1U << 1U), /*!< HSYNC active high. */
kDISPLAY_DataEnableActiveHigh = 0U, /*!< Data enable line active high. */
kDISPLAY_DataEnableActiveLow = (1U << 2U), /*!< Data enable line active low. */
kDISPLAY_DataLatchOnRisingEdge = 0U, /*!< Latch data on rising clock edge. */
kDISPLAY_DataLatchOnFallingEdge = (1U << 3U), /*!< Latch data on falling clock edge. */
};
/*! @brief Display configuration. */
typedef struct _display_config
{
uint32_t resolution; /*!< Resolution, see @ref video_resolution_t and @ref FSL_VIDEO_RESOLUTION. */
uint16_t hsw; /*!< HSYNC pulse width. */
uint16_t hfp; /*!< Horizontal front porch. */
uint16_t hbp; /*!< Horizontal back porch. */
uint16_t vsw; /*!< VSYNC pulse width. */
uint16_t vfp; /*!< Vrtical front porch. */
uint16_t vbp; /*!< Vertical back porch. */
uint32_t controlFlags; /*!< Control flags, OR'ed value of @ref _display_flags. */
uint8_t dsiLanes; /*!< MIPI DSI data lanes number. */
uint32_t pixelClock_Hz; /*!< Pixel clock in Hz. */
video_pixel_format_t pixelFormat; /*!< Pixel format. */
} display_config_t;
typedef struct _display_handle display_handle_t;
/*! @brief Display device operations. */
typedef struct _display_operations
{
status_t (*init)(display_handle_t *handle, const display_config_t *config); /*!< Init the device. */
status_t (*deinit)(display_handle_t *handle); /*!< Deinit the device. */
status_t (*start)(display_handle_t *handle); /*!< Start the device. */
status_t (*stop)(display_handle_t *handle); /*!< Stop the device. */
} display_operations_t;
/*! @brief Display handle. */
struct _display_handle
{
const void *resource;
const display_operations_t *ops;
uint16_t width;
uint16_t height;
video_pixel_format_t pixelFormat;
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Initializes the display device with user defined configuration.
*
* @param handle Display device handle.
* @param config Pointer to the user-defined configuration structure.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
static inline status_t DISPLAY_Init(display_handle_t *handle, const display_config_t *config)
{
return handle->ops->init(handle, config);
}
/*!
* @brief Deinitialize the display device.
*
* @param handle Display device handle.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
static inline status_t DISPLAY_Deinit(display_handle_t *handle)
{
return handle->ops->deinit(handle);
}
/*!
* @brief Start the display device.
*
* @param handle Display device handle.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
static inline status_t DISPLAY_Start(display_handle_t *handle)
{
return handle->ops->start(handle);
}
/*!
* @brief Stop the display device.
*
* @param handle Display device handle.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
static inline status_t DISPLAY_Stop(display_handle_t *handle)
{
return handle->ops->stop(handle);
}
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_DISPLAY_H_ */

View File

@ -0,0 +1,243 @@
/*
* Copyright 2019-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_fbdev.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
static void FBDEV_BufferSwitchOffCallback(void *param, void *switchOffBuffer);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
status_t FBDEV_Open(fbdev_t *fbdev, const dc_fb_t *dc, uint8_t layer)
{
status_t status;
assert(NULL != fbdev);
(void)memset(fbdev, 0, sizeof(fbdev_t));
fbdev->dc = dc;
(void)VIDEO_STACK_Init(&fbdev->fbManager, fbdev->buffers, FBDEV_MAX_FRAME_BUFFER);
/* Initialize the display controller. */
status = dc->ops->init(dc);
if (kStatus_Success != status)
{
return status;
}
fbdev->layer = layer;
/* Initializes the dc_fb_info_t to the display controller default setting. */
status = dc->ops->getLayerDefaultConfig(dc, layer, &fbdev->fbInfo.bufInfo);
if (kStatus_Success != status)
{
return status;
}
fbdev->semaFramePending = rt_sem_create("fsfp", 0, RT_IPC_FLAG_PRIO);
if (NULL == fbdev->semaFramePending)
{
return kStatus_Fail;
}
/* No frame pending. */
(void)rt_sem_release(fbdev->semaFramePending);
dc->ops->setCallback(dc, layer, FBDEV_BufferSwitchOffCallback, (void *)fbdev);
return kStatus_Success;
}
status_t FBDEV_Close(fbdev_t *fbdev)
{
const dc_fb_t *dc = fbdev->dc;
(void)dc->ops->deinit(dc);
if (NULL != fbdev->semaFbManager)
{
rt_sem_delete(fbdev->semaFbManager);
fbdev->semaFbManager = NULL;
}
if (NULL != fbdev->semaFramePending)
{
rt_sem_delete(fbdev->semaFramePending);
fbdev->semaFramePending = NULL;
}
return kStatus_Success;
}
status_t FBDEV_Enable(fbdev_t *fbdev)
{
status_t status = kStatus_Success;
const dc_fb_t *dc = fbdev->dc;
if (!fbdev->enabled)
{
/* Wait for frame buffer sent to display controller video memory. */
if ((dc->ops->getProperty(dc) & (uint32_t)kDC_FB_ReserveFrameBuffer) == 0U)
{
if (RT_EOK != rt_sem_take(fbdev->semaFramePending, RT_WAITING_FOREVER))
{
status = kStatus_Fail;
}
}
if (kStatus_Success == status)
{
/* No frame is pending. */
(void)rt_sem_release(fbdev->semaFramePending);
status = dc->ops->enableLayer(dc, fbdev->layer);
if (kStatus_Success == status)
{
fbdev->enabled = true;
}
}
}
return status;
}
status_t FBDEV_Disable(fbdev_t *fbdev)
{
status_t status = kStatus_Success;
const dc_fb_t *dc = fbdev->dc;
if (!fbdev->enabled)
{
/* Wait until no frame pending. */
if (RT_EOK != rt_sem_take(fbdev->semaFramePending, RT_WAITING_FOREVER))
{
status = kStatus_Fail;
}
if (kStatus_Success == status)
{
(void)rt_sem_release(fbdev->semaFramePending);
(void)dc->ops->disableLayer(dc, fbdev->layer);
fbdev->enabled = false;
}
}
return status;
}
void FBDEV_GetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info)
{
*info = fbdev->fbInfo;
}
status_t FBDEV_SetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info)
{
status_t status;
const dc_fb_t *dc = fbdev->dc;
/* Should only change the frame buffer setting before enabling the fbdev. */
if (fbdev->enabled)
{
return kStatus_Fail;
}
fbdev->fbInfo = *info;
status = dc->ops->setLayerConfig(dc, fbdev->layer, &fbdev->fbInfo.bufInfo);
if (kStatus_Success != status)
{
return status;
}
fbdev->semaFbManager = rt_sem_create("fsfm", 0, RT_IPC_FLAG_PRIO);
if (NULL == fbdev->semaFbManager)
{
return kStatus_Fail;
}
for (uint8_t i = 0; i < info->bufferCount; i++)
{
/* Don't need to disable interrupt for the FB stack operation, because
the fbdev is not working, this is the only function to access FB stack.
*/
(void)VIDEO_STACK_Push(&fbdev->fbManager, info->buffers[i]);
(void)rt_sem_release(fbdev->semaFbManager);
}
return kStatus_Success;
}
void *FBDEV_GetFrameBuffer(fbdev_t *fbdev, uint32_t flags)
{
rt_uint32_t tick;
void *fb;
tick = ((flags & (uint32_t)kFBDEV_NoWait) != 0U) ? 0U : RT_WAITING_FOREVER;
if (RT_EOK == rt_sem_take(fbdev->semaFbManager, tick))
{
/* Disable interrupt to protect the FB stack. */
rt_enter_critical();
(void)VIDEO_STACK_Pop(&fbdev->fbManager, &fb);
rt_exit_critical();
}
else
{
fb = NULL;
}
return fb;
}
status_t FBDEV_SetFrameBuffer(fbdev_t *fbdev, void *frameBuffer, uint32_t flags)
{
rt_uint32_t tick;
const dc_fb_t *dc = fbdev->dc;
tick = ((flags & (uint32_t)kFBDEV_NoWait) != 0U) ? 0U : RT_WAITING_FOREVER;
if (RT_EOK == rt_sem_take(fbdev->semaFramePending, tick))
{
return dc->ops->setFrameBuffer(dc, fbdev->layer, frameBuffer);
}
else
{
return kStatus_Fail;
}
}
static void FBDEV_BufferSwitchOffCallback(void *param, void *switchOffBuffer)
{
fbdev_t *fbdev = (fbdev_t *)param;
/* This function should only be called in ISR, so don't need to protect the FB stack */
(void)VIDEO_STACK_Push(&fbdev->fbManager, switchOffBuffer);
rt_sem_release(fbdev->semaFbManager);
rt_sem_release(fbdev->semaFramePending);
}

View File

@ -0,0 +1,227 @@
/*
* Copyright 2019-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FBDEV_H_
#define _FSL_FBDEV_H_
#include "fsl_video_common.h"
#include "fsl_dc_fb.h"
#include "rtthread.h"
/*
* Change Log:
*
* 1.0.3:
* - Bug Fixes:
* - Fixed the issue that frame buffer content changed when saved
* to free frame buffer list.
*
* 1.0.2:
* - Bug Fixes:
* - Fixed MISRA 2012 issues.
*
* 1.0.1:
* - Bug Fixes:
* - Fixed coverity warnings that return values unchedked.
*
* 1.0.0:
* - Initial version.
*/
/*!
* @addtogroup fbdev
* @{
*
* To use the fbdev, follow the workflow:
*
@code
uint8_t layer = 0;
fbdev_t fbdev;
fbdev_fb_info_t fbInfo;
extern const dc_fb_t dc;
FBDEV_Open(&fbdev, &dc, layer);
fbInfo.bufInfo.pixelFormat = DEMO_BUFFER_PIXEL_FORMAT;
fbInfo.bufInfo.width = DEMO_BUFFER_WIDTH;
fbInfo.bufInfo.height = DEMO_BUFFER_HEIGHT;
fbInfo.bufInfo.strideBytes = DEMO_BUFFER_STRIDE_BYTE;
fbInfo.buffers[0] = DEMO_BUFFER0_ADDR;
fbInfo.buffers[1] = DEMO_BUFFER1_ADDR;
FBDEV_SetFrameBufferInfo(&fbdev, &fbInfo);
buffer = FBDEV_GetFrameBuffer(&fbdev, 0);
fill the buffer here.
FBDEV_SetFrameBuffer(&fbdev, buffer, 0);
FBDEV_Enable(&fbdev);
buffer = FBDEV_GetFrameBuffer(&fbdev, 0);
fill the buffer here.
FBDEV_SetFrameBuffer(&fbdev, buffer, 0);
...
@endcode
*
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief How many frame buffers used in each fbdev. */
#ifndef FBDEV_MAX_FRAME_BUFFER
#define FBDEV_MAX_FRAME_BUFFER 3
#endif
#define FBDEV_DEFAULT_FRAME_BUFFER 2
/*! @brief Frame buffer information. */
typedef struct _fbdev_fb_info
{
uint8_t bufferCount; /*!< How many frame buffers used. */
void *buffers[FBDEV_MAX_FRAME_BUFFER]; /*!< Address of the frame buffers */
dc_fb_info_t bufInfo; /*!< Frame buffers information */
} fbdev_fb_info_t;
/*! @brief FBDEV handle, user should not touch the members directly. */
typedef struct _fbdev
{
fbdev_fb_info_t fbInfo; /*!< Frame buffer information. */
video_stack_t fbManager; /*!< Manage the framebuffers used by this device. */
void *buffers[FBDEV_MAX_FRAME_BUFFER]; /*!< Memory used by @ref fbManager, to save the free frame buffers. */
const dc_fb_t *dc; /*!< Display controller handle. */
uint8_t layer; /*!< Layer in the display controller. */
bool enabled; /*!< The fbdev is enabled or not by @ref FBDEV_Enable. */
rt_sem_t semaFbManager; /*!< Semaphore for the @ref fbManager. */
rt_sem_t semaFramePending; /*!< Semaphore for the @ref framePending. */
} fbdev_t;
/*! @brief Flags used for FBDEV operations. */
enum _fbdev_flag
{
kFBDEV_NoWait = (1 << 0), /*!< Don't wait until available, but return directly. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Open the FBDEV.
*
* @param fbdev The FBDEV handle.
* @param dc The display controller used.
* @param layer The layer in the display controller.
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_Open(fbdev_t *fbdev, const dc_fb_t *dc, uint8_t layer);
/*!
* @brief Close the FBDEV.
*
* @param fbdev The FBDEV handle.
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_Close(fbdev_t *fbdev);
/*!
* @brief Enable the FBDEV.
*
* After enabled, the FBDEV will be shown in the panel. This function should be
* called after @ref FBDEV_SetFrameBufferInfo.
*
* @param fbdev The FBDEV handle.
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_Enable(fbdev_t *fbdev);
/*!
* @brief Disable the FBDEV.
*
* After disabled, the FBDEV will not be shown in the panel. Don't call
* @ref FBDEV_SetFrameBuffer when the FBDEV is disabled.
*
* @param fbdev The FBDEV handle.
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_Disable(fbdev_t *fbdev);
/*!
* @brief Get the frame buffer information of the FBDEV.
*
* @param fbdev The FBDEV handle.
* @param info Pointer to the frame buffer information.
*/
void FBDEV_GetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info);
/*!
* @brief Set the frame buffer information of the FBDEV.
*
* This function could be used to configure the FRDEV, including set witdh, height,
* pixel format, frame buffers, and so on. This function should only be called once
* after @ref FBDEV_Open and before @ref FBDEV_Enable.
*
* @param fbdev The FBDEV handle.
* @param info Pointer to the frame buffer information.
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_SetFrameBufferInfo(fbdev_t *fbdev, fbdev_fb_info_t *info);
/*!
* @brief Get available frame buffer from the FBDEV.
*
* Upper layer could call this function to get an available frame buffer from
* the FBDEV, render send to show.
*
* @param fbdev The FBDEV handle.
* @param flags OR'ed value of @ref _fbdev_flag. If @ref kFBDEV_NoWait is used,
* the function returns NULL immediately if no available buffer. If @ref kFBDEV_NoWait
* is not used, this function waits until available.
*
* @return Returns the address of the frame buffer. If no available, returns NULL.
*/
void *FBDEV_GetFrameBuffer(fbdev_t *fbdev, uint32_t flags);
/*!
* @brief Send frame buffer to the FBDEV.
*
* Upper layer could call this function to send a frame buffer to the FBDEV. This
* function should only be used when the FBDEV is enabled.
*
* @param fbdev The FBDEV handle.
* @param flags OR'ed value of @ref _fbdev_flag. If @ref kFBDEV_NoWait is used,
* the function returns NULL immediately if the previous frame buffer is pending.
* If @ref kFBDEV_NoWait is not used, this function waits until previous frame
* buffer not pending.
*
* @return Returns @ref kStatus_Success if success, otherwise returns
* error code.
*/
status_t FBDEV_SetFrameBuffer(fbdev_t *fbdev, void *frameBuffer, uint32_t flags);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_FBDEV_H_ */

View File

@ -0,0 +1,187 @@
/*
* Copyright 2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_display.h"
#include "fsl_hx8394.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define HX8394_DelayMs VIDEO_DelayMs
typedef struct
{
const uint8_t *cmd;
uint8_t cmdLen;
} hx8394_cmd_t;
/*******************************************************************************
* Variables
******************************************************************************/
const display_operations_t hx8394_ops = {
.init = HX8394_Init,
.deinit = HX8394_Deinit,
.start = HX8394_Start,
.stop = HX8394_Stop,
};
static const hx8394_cmd_t s_hx8394Cmds[] = {
{(const uint8_t[]){0x36U, 0x02U}, 2U},
{(const uint8_t[]){0xB1U, 0x48U, 0x12U, 0x72U, 0x09U, 0x32U, 0x54U, 0x71U, 0x71U, 0x57U, 0x47U}, 11U},
{(const uint8_t[]){0xB2U, 0x00U, 0x80U, 0x64U, 0x0CU, 0x0DU, 0x2FU}, 7U},
{(const uint8_t[]){0xB4U, 0x73U, 0x74U, 0x73U, 0x74U, 0x73U, 0x74U, 0x01U, 0x0CU, 0x86U, /* 10 */
0x75U, 0x00U, 0x3FU, 0x73U, 0x74U, 0x73U, 0x74U, 0x73U, 0x74U, 0x01U, /* 20 */
0x0CU, 0x86U},
22U},
{(const uint8_t[]){0xD3U, 0x00U, 0x00U, 0x07U, 0x07U, 0x40U, 0x07U, 0x0CU, 0x00U, 0x08U, /* 10 */
0x10U, 0x08U, 0x00U, 0x08U, 0x54U, 0x15U, 0x0AU, 0x05U, 0x0AU, 0x02U, /* 20 */
0x15U, 0x06U, 0x05U, 0x06U, 0x47U, 0x44U, 0x0AU, 0x0AU, 0x4BU, 0x10U, /* 30 */
0x07U, 0x07U, 0x0CU, 0x40U},
34U},
{(const uint8_t[]){0xD5U, 0x1CU, 0x1CU, 0x1DU, 0x1DU, 0x00U, 0x01U, 0x02U, 0x03U, 0x04U, /* 10 */
0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0AU, 0x0BU, 0x24U, 0x25U, 0x18U, /* 20 */
0x18U, 0x26U, 0x27U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, /* 30 */
0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x20U, /* 40 */
0x21U, 0x18U, 0x18U, 0x18U, 0x18U},
45U},
{(const uint8_t[]){0xD6U, 0x1CU, 0x1CU, 0x1DU, 0x1DU, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, /* 10 */
0x02U, 0x01U, 0x00U, 0x0BU, 0x0AU, 0x09U, 0x08U, 0x21U, 0x20U, 0x18U, /* 20 */
0x18U, 0x27U, 0x26U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, /* 30 */
0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x18U, 0x25U, /* 40 */
0x24U, 0x18U, 0x18U, 0x18U, 0x18U},
45U},
{(const uint8_t[]){0xB6U, 0x92U, 0x92U}, 3U},
{(const uint8_t[]){0xE0U, 0x00U, 0x0AU, 0x15U, 0x1BU, 0x1EU, 0x21U, 0x24U, 0x22U, 0x47U, /* 10 */
0x56U, 0x65U, 0x66U, 0x6EU, 0x82U, 0x88U, 0x8BU, 0x9AU, 0x9DU, 0x98U, /* 20 */
0xA8U, 0xB9U, 0x5DU, 0x5CU, 0x61U, 0x66U, 0x6AU, 0x6FU, 0x7FU, 0x7FU, /* 30 */
0x00U, 0x0AU, 0x15U, 0x1BU, 0x1EU, 0x21U, 0x24U, 0x22U, 0x47U, 0x56U, /* 40 */
0x65U, 0x65U, 0x6EU, 0x81U, 0x87U, 0x8BU, 0x98U, 0x9DU, 0x99U, 0xA8U, /* 50 */
0xBAU, 0x5DU, 0x5DU, 0x62U, 0x67U, 0x6BU, 0x72U, 0x7FU, 0x7FU},
59U},
{(const uint8_t[]){0xC0U, 0x1FU, 0x31U}, 3U},
{(const uint8_t[]){0xCCU, 0x03U}, 2U},
{(const uint8_t[]){0xD4U, 0x02U}, 2U},
{(const uint8_t[]){0xBDU, 0x02U}, 2U},
{(const uint8_t[]){0xD8U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, /* 10 */
0xFFU, 0xFFU, 0xFFU},
13U},
{(const uint8_t[]){0xBDU, 0x00U}, 2U},
{(const uint8_t[]){0xBDU, 0x01U}, 2U},
{(const uint8_t[]){0xB1U, 0x00U}, 2U},
{(const uint8_t[]){0xBDU, 0x00U}, 2U},
{(const uint8_t[]){0xBFU, 0x40U, 0x81U, 0x50U, 0x00U, 0x1AU, 0xFCU, 0x01}, 8U},
{(const uint8_t[]){0xC6U, 0xEDU}, 2U},
{(const uint8_t[]){0x35U, 0x00U}, 2U},
};
/*******************************************************************************
* Code
******************************************************************************/
status_t HX8394_Init(display_handle_t *handle, const display_config_t *config)
{
uint8_t i;
status_t status = kStatus_Success;
const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
uint8_t setmipi[7] = {0xBAU, 0x60U, 0x03U, 0x68U, 0x6BU, 0xB2U, 0xC0U};
/* Only support 720 * 1280 */
if (config->resolution != FSL_VIDEO_RESOLUTION(720, 1280))
{
return kStatus_InvalidArgument;
}
/* Power on. */
resource->pullPowerPin(true);
HX8394_DelayMs(1);
/* Perform reset. */
resource->pullResetPin(false);
HX8394_DelayMs(1);
resource->pullResetPin(true);
HX8394_DelayMs(50U);
status = MIPI_DSI_GenericWrite(dsiDevice, (const uint8_t[]){0xB9U, 0xFFU, 0x83U, 0x94U}, 4);
setmipi[1] |= (config->dsiLanes - 1U);
if (kStatus_Success == status)
{
status = MIPI_DSI_GenericWrite(dsiDevice, setmipi, 7);
}
if (kStatus_Success == status)
{
for (i = 0; i < ARRAY_SIZE(s_hx8394Cmds); i++)
{
status = MIPI_DSI_GenericWrite(dsiDevice, s_hx8394Cmds[i].cmd, (int32_t)s_hx8394Cmds[i].cmdLen);
if (kStatus_Success != status)
{
break;
}
}
}
if (kStatus_Success == status)
{
status = MIPI_DSI_DCS_EnterSleepMode(dsiDevice, false);
}
if (kStatus_Success == status)
{
HX8394_DelayMs(120U);
status = MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
}
return status;
}
status_t HX8394_Deinit(display_handle_t *handle)
{
const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
(void)MIPI_DSI_DCS_EnterSleepMode(dsiDevice, true);
resource->pullResetPin(false);
resource->pullPowerPin(false);
return kStatus_Success;
}
status_t HX8394_Start(display_handle_t *handle)
{
const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
}
status_t HX8394_Stop(display_handle_t *handle)
{
const hx8394_resource_t *resource = (const hx8394_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, false);
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_HX8394_H_
#define _FSL_HX8394_H_
#include "fsl_display.h"
#include "fsl_mipi_dsi_cmd.h"
/*
* Change log:
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief HX8394 resource.
*/
typedef struct _hx8394_resource
{
mipi_dsi_device_t *dsiDevice; /*!< MIPI DSI device. */
void (*pullResetPin)(bool pullUp); /*!< Function to pull reset pin high or low. */
void (*pullPowerPin)(bool pullUp); /*!< Function to pull power pin high or low. */
} hx8394_resource_t;
extern const display_operations_t hx8394_ops;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
status_t HX8394_Init(display_handle_t *handle, const display_config_t *config);
status_t HX8394_Deinit(display_handle_t *handle);
status_t HX8394_Start(display_handle_t *handle);
status_t HX8394_Stop(display_handle_t *handle);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_HX8394_H_ */

View File

@ -0,0 +1,351 @@
/*
* Copyright 2017-2020 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_mipi_dsi_cmd.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
status_t MIPI_DSI_DCS_SoftReset(mipi_dsi_device_t *device)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData = (uint8_t)kMIPI_DCS_SoftReset;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_SetDisplayOn(mipi_dsi_device_t *device, bool on)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
if (on)
{
txData = (uint8_t)kMIPI_DCS_SetDisplayOn;
}
else
{
txData = (uint8_t)kMIPI_DCS_SetDisplayOff;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_SetPixelFormat(mipi_dsi_device_t *device,
mipi_dsc_pixel_format_t dbiFormat,
mipi_dsc_pixel_format_t dpiFormat)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData[2];
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrOneParam;
dsiXfer.txDataSize = 2;
dsiXfer.txData = txData;
txData[0] = (uint8_t)kMIPI_DCS_SetPixelFormat;
txData[1] = ((uint8_t)dbiFormat << 0U) | ((uint8_t)dpiFormat << 4U);
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_EnterSleepMode(mipi_dsi_device_t *device, bool enter)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
if (enter)
{
txData = (uint8_t)kMIPI_DCS_EnterSleepMode;
}
else
{
txData = (uint8_t)kMIPI_DCS_ExitSleepMode;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_EnterPartialMode(mipi_dsi_device_t *device, bool enter)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
if (enter)
{
txData = (uint8_t)kMIPI_DCS_EnterPartialMode;
}
else
{
txData = (uint8_t)kMIPI_DCS_EnterNormalMode;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_EnterInvertMode(mipi_dsi_device_t *device, bool enter)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
if (enter)
{
txData = (uint8_t)kMIPI_DCS_EnterInvertMode;
}
else
{
txData = (uint8_t)kMIPI_DCS_ExitInvertMode;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_EnterIdleMode(mipi_dsi_device_t *device, bool enter)
{
dsi_transfer_t dsiXfer = {0};
uint8_t txData;
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
dsiXfer.txDataSize = 1;
dsiXfer.txData = &txData;
if (enter)
{
txData = (uint8_t)kMIPI_DCS_EnterIdleMode;
}
else
{
txData = (uint8_t)kMIPI_DCS_ExitIdleMode;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_Write(mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize)
{
dsi_transfer_t dsiXfer = {0};
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataSize = (uint16_t)txDataSize;
dsiXfer.txData = txData;
if (0 == txDataSize)
{
/* For DSC command, the data size should not be 0. */
return kStatus_InvalidArgument;
}
else if (1 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataDcsShortWrNoParam;
}
else if (2 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataDcsShortWrOneParam;
}
else
{
dsiXfer.txDataType = kDSI_TxDataDcsLongWr;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_GenericWrite(mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize)
{
dsi_transfer_t dsiXfer = {0};
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataSize = (uint16_t)txDataSize;
dsiXfer.txData = txData;
if (0 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortWrNoParam;
}
else if (1 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortWrOneParam;
}
else if (2 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortWrTwoParam;
}
else
{
dsiXfer.txDataType = kDSI_TxDataGenLongWr;
}
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_DCS_SetMaxReturnPktSize(mipi_dsi_device_t *device, uint16_t sizeBytes)
{
dsi_transfer_t dsiXfer = {0};
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataSetMaxReturnPktSize;
dsiXfer.txDataSize = 2;
dsiXfer.txData = (uint8_t *)&sizeBytes;
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_GenericRead(
mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize, uint8_t *rxData, int32_t *rxDataSize)
{
status_t status;
dsi_transfer_t dsiXfer = {0};
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataSize = (uint16_t)txDataSize;
dsiXfer.txData = txData;
dsiXfer.rxDataSize = (uint16_t)*rxDataSize;
dsiXfer.rxData = rxData;
*rxDataSize = 0;
if (0 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortRdNoParam;
}
else if (1 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortRdOneParam;
}
else if (2 == txDataSize)
{
dsiXfer.txDataType = kDSI_TxDataGenShortRdTwoParam;
}
else
{
return kStatus_InvalidArgument;
}
status = device->xferFunc(&dsiXfer);
/* Return actual received size. */
*rxDataSize = (int32_t)dsiXfer.rxDataSize;
return status;
}
status_t MIPI_DSI_ReadCMD(mipi_dsi_device_t *device, enum _mipi_dcs dcsCmd, uint8_t *rxData, int32_t *rxDataSize)
{
uint8_t txData[2];
status_t status = kStatus_Fail;
txData[0] = (uint8_t)dcsCmd;
if (kStatus_Success == MIPI_DSI_DCS_SetMaxReturnPktSize(device, (uint16_t)*rxDataSize))
{
status = MIPI_DSI_GenericRead(device, txData, 1, rxData, rxDataSize);
}
return status;
}
status_t MIPI_DSI_SelectArea(mipi_dsi_device_t *device, uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY)
{
status_t status;
dsi_transfer_t dsiXfer = {0};
uint8_t txData[4];
dsiXfer.virtualChannel = device->virtualChannel;
dsiXfer.txDataType = kDSI_TxDataDcsLongWr;
dsiXfer.txDataSize = 4;
dsiXfer.txData = txData;
dsiXfer.sendDscCmd = true;
dsiXfer.dscCmd = (uint8_t)kMIPI_DCS_SetColumnAddress;
txData[0] = (uint8_t)((startX >> 8U) & 0xFFU);
txData[1] = (uint8_t)(startX & 0xFFU);
txData[2] = (uint8_t)((endX >> 8U) & 0xFFU);
txData[3] = (uint8_t)(endX & 0xFFU);
status = device->xferFunc(&dsiXfer);
if (kStatus_Success != status)
{
return status;
}
dsiXfer.dscCmd = (uint8_t)kMIPI_DCS_SetPageAddress;
txData[0] = (uint8_t)((startY >> 8U) & 0xFFU);
txData[1] = (uint8_t)(startY & 0xFFU);
txData[2] = (uint8_t)((endY >> 8U) & 0xFFU);
txData[3] = (uint8_t)(endY & 0xFFU);
return device->xferFunc(&dsiXfer);
}
status_t MIPI_DSI_WriteMemory(mipi_dsi_device_t *device, const uint8_t *data, uint32_t length)
{
return device->memWriteFunc(device->virtualChannel, data, length);
}
status_t MIPI_DSI_WriteMemory2D(
mipi_dsi_device_t *device, const uint8_t *data, uint32_t minorLoop, uint32_t minorLoopOffset, uint32_t majorLoop)
{
if (device->memWriteFunc2D != NULL)
{
return device->memWriteFunc2D(device->virtualChannel, data, minorLoop, minorLoopOffset, majorLoop);
}
else
{
return kStatus_Fail;
}
}
void MIPI_DSI_SetMemoryDoneCallback(mipi_dsi_device_t *device, mipi_dsi_mem_done_callback_t callback, void *userData)
{
device->callback = callback;
device->userData = userData;
}
void MIPI_DSI_MemoryDoneDriverCallback(status_t status, void *userData)
{
mipi_dsi_device_t *device = (mipi_dsi_device_t *)userData;
if (NULL != device->callback)
{
device->callback(status, device->userData);
}
}

View File

@ -0,0 +1,354 @@
/*
* Copyright 2017-2020 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_MIPI_DSI_CMD_H_
#define _FSL_MIPI_DSI_CMD_H_
#include "fsl_common.h"
#include "fsl_mipi_dsi.h"
/*
* Change log:
*
* 1.0.2
* - Fix MISRA-C 2012 issues.
*
* 1.0.1
* - Add more functions for panel works in command mode.
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
enum _mipi_dcs
{
kMIPI_DCS_Nop = 0x00,
kMIPI_DCS_SoftReset = 0x01,
kMIPI_DCS_GetRedChannel = 0x06,
kMIPI_DCS_GetGreenChannel = 0x07,
kMIPI_DCS_GetBlueChannel = 0x08,
kMIPI_DCS_GetPowerMode = 0x0A,
kMIPI_DCS_GetAddressMode = 0x0B,
kMIPI_DCS_GetPixelFormat = 0x0C,
kMIPI_DCS_GetDisplayMode = 0x0D,
kMIPI_DCS_GetSignalMode = 0x0E,
kMIPI_DCS_GetDiagnosticResult = 0x0F,
kMIPI_DCS_EnterSleepMode = 0x10,
kMIPI_DCS_ExitSleepMode = 0x11,
kMIPI_DCS_EnterPartialMode = 0x12,
kMIPI_DCS_EnterNormalMode = 0x13,
kMIPI_DCS_ExitInvertMode = 0x20,
kMIPI_DCS_EnterInvertMode = 0x21,
kMIPI_DCS_SetGammaCurve = 0x26,
kMIPI_DCS_SetDisplayOff = 0x28,
kMIPI_DCS_SetDisplayOn = 0x29,
kMIPI_DCS_SetColumnAddress = 0x2a,
kMIPI_DCS_SetPageAddress = 0x2b,
kMIPI_DCS_WriteMemoryStart = 0x2C,
kMIPI_DCS_WriteLUT = 0x2D,
kMIPI_DCS_ReadMemoryStart = 0x2E,
kMIPI_DCS_SetPartialRows = 0x30,
kMIPI_DCS_SetPartialColumns = 0x31,
kMIPI_DCS_SetScrollArea = 0x33,
kMIPI_DCS_SetTearOff = 0x34,
kMIPI_DCS_SetTearOn = 0x35,
kMIPI_DCS_SetAddressMode = 0x36,
kMIPI_DCS_SetScrollStart = 0x37,
kMIPI_DCS_ExitIdleMode = 0x38,
kMIPI_DCS_EnterIdleMode = 0x39,
kMIPI_DCS_SetPixelFormat = 0x3A,
kMIPI_DCS_WriteMemoryContinue = 0x3C,
kMIPI_DCS_Set3DControl = 0x3D,
kMIPI_DCS_ReadMemoryContinue = 0x3E,
kMIPI_DCS_Get3DControl = 0x3F,
kMIPI_DCS_SetVsyncTiming = 0x40,
kMIPI_DCS_SetTearScanline = 0x44,
kMIPI_DCS_GetScanline = 0x45,
kMIPI_DCS_SetDisplayBrightness = 0x51,
kMIPI_DCS_GetDisplayBrightness = 0x52,
kMIPI_DCS_WriteControlDisplay = 0x53,
kMIPI_DCS_GetControlDisplay = 0x54,
kMIPI_DCS_WritePowerSave = 0x55,
kMIPI_DCS_GetPowerSave = 0x56,
kMIPI_DCS_SetCABCMinBrightness = 0x5E,
kMIPI_DCS_GetCABCMinBrightness = 0x5F,
kMIPI_DCS_ReadDDBStart = 0xA1,
kMIPI_DCS_ReadDDBContinue = 0xA8,
};
/*!
* @brief Pixel format used by DSC command.
*/
typedef enum _mipi_dsc_pixel_format
{
kMIPI_DCS_Pixel3Bits = 1U, /*!< 3-bit per pixel. */
kMIPI_DCS_Pixel8Bits = 2U, /*!< 8-bit per pixel. */
kMIPI_DCS_Pixel12Bits = 3U, /*!< 12-bit per pixel. */
kMIPI_DCS_Pixel16Bits = 5U, /*!< 16-bit per pixel. */
kMIPI_DCS_Pixel18Bits = 6U, /*!< 18-bit per pixel. */
kMIPI_DCS_Pixel24Bits = 7U, /*!< 24-bit per pixel. */
} mipi_dsc_pixel_format_t;
/*!
* @brief Callback function when the write memory finished.
*
* If transfer done successfully, the @p status is kStatus_Success.
*/
typedef void (*mipi_dsi_mem_done_callback_t)(status_t status, void *userData);
/*! @brief MIPI DSI transfer function. */
typedef status_t (*mipi_dsi_transfer_func_t)(dsi_transfer_t *xfer);
/*! @brief MIPI DSI memory write function. */
typedef status_t (*mipi_dsi_mem_write_func_t)(uint8_t virtualChannel, const uint8_t *data, uint32_t length);
/*! @brief MIPI DSI memory write function using 2-dimensional way. */
typedef status_t (*mipi_dsi_mem_write_func_2D_t)(
uint8_t virtualChannel, const uint8_t *data, uint32_t minorLoop, uint32_t minorLoopOffset, uint32_t majorLoop);
/*! @brief MIPI DSI device. */
typedef struct _mipi_dsi_device
{
uint8_t virtualChannel;
mipi_dsi_transfer_func_t xferFunc;
mipi_dsi_mem_write_func_t memWriteFunc; /*!< Function to write display memory,
it should be non-blocking function and
notify upper layer using callback when finished.
Not used when panel works in video mode. */
mipi_dsi_mem_write_func_2D_t memWriteFunc2D; /*!< Function to write display memory using 2-dimensional way,
it should be non-blocking function and
notify upper layer using callback when finished.
Not used when panel works in video mode. */
mipi_dsi_mem_done_callback_t callback; /*!< The callback function to notify upper layer
that memory write done. Not used when panel
works in video mode. */
void *userData; /*!< Parameter for the memory write done callback.
not used when panel works in video mode. */
} mipi_dsi_device_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Send software reset to MIPI DSI device.
*
* @param device The MIPI DSI device.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_SoftReset(mipi_dsi_device_t *device);
/*!
* @brief Set display on or off.
*
* @param device The MIPI DSI device.
* @param on Set true to turn on, false to turn off.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_SetDisplayOn(mipi_dsi_device_t *device, bool on);
/*!
* @brief Enter or exit sleep mode.
*
* @param device The MIPI DSI device.
* @param enter Set true to enter sleep mode, false to exit.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_EnterSleepMode(mipi_dsi_device_t *device, bool enter);
/*!
* @brief Enter or exit partial mode.
*
* @param device The MIPI DSI device.
* @param enter Set true to enter partial mode, false to exit.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_EnterPartialMode(mipi_dsi_device_t *device, bool enter);
/*!
* @brief Enter or exit invert mode.
*
* @param device The MIPI DSI device.
* @param enter Set true to enter invert mode, false to exit.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_EnterInvertMode(mipi_dsi_device_t *device, bool enter);
/*!
* @brief Enter or exit idle mode.
*
* @param device The MIPI DSI device.
* @param enter Set true to enter idle mode, false to exit.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_EnterIdleMode(mipi_dsi_device_t *device, bool enter);
/*!
* @brief Send DCS command.
*
* @param device The MIPI DSI device.
* @param txData The data to send.
* @param txDataSize Size of the data to send (in bytes).
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_Write(mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize);
/*!
* @brief Send generic data.
*
* @param device The MIPI DSI device.
* @param txData The data to send.
* @param txDataSize Size of the data to send (in bytes).
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_GenericWrite(mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize);
/*!
* @brief Set the maximum return data length.
*
* @param device The MIPI DSI device.
* @param sizeBytes Maximum return data length.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_SetMaxReturnPktSize(mipi_dsi_device_t *device, uint16_t sizeBytes);
/*!
* @brief Generic read.
*
* @param device The MIPI DSI device.
* @param txData The data to send before read.
* @param txDataSize Size of the data to send (in bytes).
* @param rxData The data to read.
* @param rxDataSize Size of the data to read (in bytes), after this function returns,
* it is the actual read length.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_GenericRead(
mipi_dsi_device_t *device, const uint8_t *txData, int32_t txDataSize, uint8_t *rxData, int32_t *rxDataSize);
/*!
* @brief Read DCS command(read type command, such as: Get Display ID).
*
* @param device The MIPI DSI device.
* @param dcsCmd The command to send before read.
* @param rxData The data to read.
* @param rxDataSize Size of the data to read (in bytes), after this function returns,
* it is the actual read length.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_ReadCMD(mipi_dsi_device_t *device, enum _mipi_dcs dcsCmd, uint8_t *rxData, int32_t *rxDataSize);
/*!
* @brief Set the panel pixel format.
*
* @param device The MIPI DSI device.
* @param dbiFormat The DBI interface pixel format.
* @param dpiFormat The DPI interface pixel format.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_DCS_SetPixelFormat(mipi_dsi_device_t *device,
mipi_dsc_pixel_format_t dbiFormat,
mipi_dsc_pixel_format_t dpiFormat);
/*!
* @brief Select area to write or read pixels.
*
* @param device The MIPI DSI device.
* @param startX Start point X coordination.
* @param startY Start point Y coordination.
* @param endX End point X coordination.
* @param endY End point Y coordination.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_SelectArea(mipi_dsi_device_t *device, uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY);
/*!
* @brief Send pixel data to the display controller's frame memory.
*
* The pixels will be shown in the region selected by @ref MIPI_DSI_SelectArea.
* This function is non-blocking function, user should install callback function
* using @ref MIPI_DSI_SetMemoryDoneCallback to get informed when write finished.
*
* @param device The MIPI DSI device.
* @param data The pixel data to send.
* @param length Length of the data in byte.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_WriteMemory(mipi_dsi_device_t *device, const uint8_t *data, uint32_t length);
/*!
* @brief Send pixel data to the display controller's frame memory in 2-dinmensional way.
*
* The pixels will be shown in the region selected by @ref MIPI_DSI_SelectArea.
* This function is non-blocking function, user should install callback function
* using @ref MIPI_DSI_SetMemoryDoneCallback to get informed when write finished.
*
* @verbatim
* +---------------------------------------------------+
* | |
* | data |
* | +-------------------+ |
* | | minorLoop | |
* | | | |
* | | | majorLoop |
* | | | |
* | | | |
* | +-------------------+ |
* | |
* | minorLoop + minorLoopOffset |
* +---------------------------------------------------+
* @endverbatim
*
* @param device The MIPI DSI device.
* @param data The pixel data to send.
* @param minorLoop Count of the data in one line in byte.
* @param minorLoopOffset The offset between line stride and the count of one line in byte.
* @param majorLoop Count of the lines in byte.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
status_t MIPI_DSI_WriteMemory2D(
mipi_dsi_device_t *device, const uint8_t *data, uint32_t minorLoop, uint32_t minorLoopOffset, uint32_t majorLoop);
/*!
* @brief Install the callback called when write memory finished.
*
* Upper layer should install callback function using this function to
* get memory write done notification.
*
* @param device The MIPI DSI device.
* @param callback The callback function to inform upper layer that memory write done.
* @param userData Parameter used by the callback.
* @return Returns @ref kStatus_Success if success, otherwise returns error code.
*/
void MIPI_DSI_SetMemoryDoneCallback(mipi_dsi_device_t *device, mipi_dsi_mem_done_callback_t callback, void *userData);
/*!
* @brief The callback function lower layer should call when write memory finished.
*
* When implement the @ref mipi_dsi_device_t, this function should be called when
* the memory writing finished. The parameter @p userData should be pointer to the
* @ref mipi_dsi_device_t.
*
* @param status The memory writing result. @ref kStatus_Success if success.
* @param userData Must be pointer to the @ref mipi_dsi_device_t instance.
*/
void MIPI_DSI_MemoryDoneDriverCallback(status_t status, void *userData);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_MIPI_DSI_CMD_H_ */

View File

@ -0,0 +1,251 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_display.h"
#include "fsl_rm68191.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define RM68191_DelayMs VIDEO_DelayMs
typedef struct _rm68191_setting
{
const uint8_t *value;
uint8_t len;
} rm68191_setting_t;
#define RM68191_MAKE_SETTING_ITEM(setting) \
{ \
(setting), (uint8_t)sizeof(setting) \
}
/*******************************************************************************
* Variables
******************************************************************************/
static const uint8_t s_rm68191Cmd0[] = {0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03};
static const uint8_t s_rm68191Cmd1[] = {0x90, 0x05, 0x16, 0x09, 0x03, 0xCD, 0x00, 0x00, 0x00, 0x00};
static const uint8_t s_rm68191Cmd2[] = {0x91, 0x05, 0x16, 0x0B, 0x03, 0xCF, 0x00, 0x00, 0x00, 0x00};
static const uint8_t s_rm68191Cmd3[] = {0x92, 0x40, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x8F, 0x00, 0x00, 0x04, 0x08};
static const uint8_t s_rm68191Cmd4[] = {0x94, 0x00, 0x08, 0x0C, 0x03, 0xD1, 0x03, 0xD2, 0x0C};
static const uint8_t s_rm68191Cmd5[] = {0x95, 0x40, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13,
0x00, 0x8F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08};
static const uint8_t s_rm68191Cmd6[] = {0x99, 0x00, 0x00};
static const uint8_t s_rm68191Cmd7[] = {0x9A, 0x80, 0x10, 0x03, 0xD5, 0x03, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x50};
static const uint8_t s_rm68191Cmd8[] = {0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t s_rm68191Cmd9[] = {0x9C, 0x00, 0x00};
static const uint8_t s_rm68191Cmd10[] = {0x9D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00};
static const uint8_t s_rm68191Cmd11[] = {0x9E, 0x00, 0x00};
static const uint8_t s_rm68191Cmd12[] = {0xA0, 0x84, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x0A, 0x1F};
static const uint8_t s_rm68191Cmd13[] = {0xA1, 0x1F, 0x1F, 0x1F, 0x1F, 0x0C, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F};
static const uint8_t s_rm68191Cmd14[] = {0xA2, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x02, 0x1F, 0x06, 0x1F};
static const uint8_t s_rm68191Cmd15[] = {0xA3, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
static const uint8_t s_rm68191Cmd16[] = {0xA4, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x07, 0x1F, 0x03, 0x1F, 0x0F};
static const uint8_t s_rm68191Cmd17[] = {0xA5, 0x1F, 0x0D, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0B, 0x1F, 0x09};
static const uint8_t s_rm68191Cmd18[] = {0xA6, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x01, 0x05};
static const uint8_t s_rm68191Cmd19[] = {0xA7, 0x03, 0x07, 0x1F, 0x1F, 0x1F, 0x1F, 0x0B, 0x1F, 0x09, 0x1F};
static const uint8_t s_rm68191Cmd20[] = {0xA8, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x1F, 0x0D, 0x1F, 0x1F, 0x1F};
static const uint8_t s_rm68191Cmd21[] = {0xA9, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05, 0x1F, 0x01, 0x1F};
static const uint8_t s_rm68191Cmd22[] = {0xAA, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
static const uint8_t s_rm68191Cmd23[] = {0xAB, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x1F, 0x04, 0x1F, 0x0C};
static const uint8_t s_rm68191Cmd24[] = {0xAC, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x0A};
static const uint8_t s_rm68191Cmd25[] = {0xAD, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x06, 0x02};
static const uint8_t s_rm68191Cmd26[] = {0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02};
static const uint8_t s_rm68191Cmd27[] = {0xEA, 0x7D};
static const uint8_t s_rm68191Cmd28[] = {0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00};
static const uint8_t s_rm68191Cmd29[] = {0xBC, 0x00, 0x00, 0x00};
static const uint8_t s_rm68191Cmd30[] = {0xB8, 0x01, 0xAF, 0x8F, 0x8F};
static const uint8_t s_rm68191Cmd31[] = {0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01};
static const uint8_t s_rm68191Cmd32[] = {0xD1, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd33[] = {0xD2, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd34[] = {0xD3, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd35[] = {0xD4, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd36[] = {0xD5, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd37[] = {0xD6, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd38[] = {0xD7, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd39[] = {0xD8, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd40[] = {0xD9, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd41[] = {0xDD, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd42[] = {0xDE, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd43[] = {0xDF, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd44[] = {0xE0, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd45[] = {0xE1, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd46[] = {0xE2, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd47[] = {0xE3, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd48[] = {0xE4, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd49[] = {0xE5, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd50[] = {0xE6, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd51[] = {0xE7, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd52[] = {0xE8, 0x00, 0x00, 0x00, 0x26, 0x00, 0x5E, 0x00, 0x88,
0x00, 0xA8, 0x00, 0xDB, 0x01, 0x02, 0x01, 0x3D};
static const uint8_t s_rm68191Cmd53[] = {0xE9, 0x01, 0x67, 0x01, 0xA6, 0x01, 0xD3, 0x02, 0x16,
0x02, 0x49, 0x02, 0x4B, 0x02, 0x7B, 0x02, 0xB3};
static const uint8_t s_rm68191Cmd54[] = {0xEA, 0x02, 0xD9, 0x03, 0x0E, 0x03, 0x31, 0x03, 0x61,
0x03, 0x80, 0x03, 0xA5, 0x03, 0xBD, 0x03, 0xD2};
static const uint8_t s_rm68191Cmd55[] = {0xEB, 0x03, 0xE5, 0x03, 0xFF};
static const uint8_t s_rm68191Cmd56[] = {0xB0, 0x07, 0x07, 0x07};
static const uint8_t s_rm68191Cmd57[] = {0xB1, 0x07, 0x07, 0x07};
static const uint8_t s_rm68191Cmd58[] = {0xB3, 0x11, 0x11, 0x11};
static const uint8_t s_rm68191Cmd59[] = {0xB4, 0x09, 0x09, 0x09};
static const uint8_t s_rm68191Cmd60[] = {0xB6, 0x44, 0x44, 0x44};
static const uint8_t s_rm68191Cmd61[] = {0xB7, 0x34, 0x34, 0x34};
static const uint8_t s_rm68191Cmd62[] = {0xB9, 0x34, 0x34, 0x34};
static const uint8_t s_rm68191Cmd63[] = {0xBA, 0x14, 0x14, 0x14};
static const uint8_t s_rm68191Cmd64[] = {0xBC, 0x00, 0x98, 0x00};
static const uint8_t s_rm68191Cmd65[] = {0xBD, 0x00, 0x98, 0x00};
static const uint8_t s_rm68191Cmd66[] = {0xBE, 0x1D};
static const uint8_t s_rm68191Cmd67[] = {0x35, 0x00};
static const rm68191_setting_t s_rm68191InitSetting[] = {
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd0), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd1),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd2), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd3),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd4), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd5),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd6), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd7),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd8), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd9),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd10), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd11),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd12), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd13),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd14), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd15),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd16), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd17),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd18), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd19),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd20), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd21),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd22), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd23),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd24), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd25),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd26), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd27),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd28), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd29),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd30), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd31),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd32), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd33),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd34), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd35),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd36), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd37),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd38), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd39),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd40), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd41),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd42), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd43),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd44), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd45),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd46), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd47),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd48), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd49),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd50), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd51),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd52), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd53),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd54), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd55),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd56), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd57),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd58), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd59),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd60), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd61),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd62), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd63),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd64), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd65),
RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd66), RM68191_MAKE_SETTING_ITEM(s_rm68191Cmd67),
};
const display_operations_t rm68191_ops = {
.init = RM68191_Init,
.deinit = RM68191_Deinit,
.start = RM68191_Start,
.stop = RM68191_Stop,
};
/*******************************************************************************
* Code
******************************************************************************/
status_t RM68191_Init(display_handle_t *handle, const display_config_t *config)
{
uint32_t i;
status_t status = kStatus_Success;
const rm68191_resource_t *resource = (const rm68191_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
/* Only support 540 * 960 */
if (config->resolution != FSL_VIDEO_RESOLUTION(540, 960))
{
return kStatus_InvalidArgument;
}
/* Power on. */
resource->pullPowerPin(true);
RM68191_DelayMs(1);
/* Perform reset. */
resource->pullResetPin(false);
RM68191_DelayMs(1);
resource->pullResetPin(true);
RM68191_DelayMs(5);
/* Set the LCM init settings. */
for (i = 0; i < ARRAY_SIZE(s_rm68191InitSetting); i++)
{
status = MIPI_DSI_DCS_Write(dsiDevice, s_rm68191InitSetting[i].value, (int32_t)s_rm68191InitSetting[i].len);
if (kStatus_Success != status)
{
return status;
}
}
/* Exit sleep mode */
status = MIPI_DSI_DCS_EnterSleepMode(dsiDevice, false);
if (kStatus_Success != status)
{
return status;
}
RM68191_DelayMs(200);
/* Set display on. */
status = MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
if (kStatus_Success != status)
{
return status;
}
RM68191_DelayMs(200);
return kStatus_Success;
}
status_t RM68191_Deinit(display_handle_t *handle)
{
const rm68191_resource_t *resource = (const rm68191_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
(void)MIPI_DSI_DCS_EnterSleepMode(dsiDevice, true);
resource->pullResetPin(false);
resource->pullPowerPin(false);
return kStatus_Success;
}
status_t RM68191_Start(display_handle_t *handle)
{
const rm68191_resource_t *resource = (const rm68191_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
}
status_t RM68191_Stop(display_handle_t *handle)
{
const rm68191_resource_t *resource = (const rm68191_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, false);
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_RM68191_H_
#define _FSL_RM68191_H_
#include "fsl_display.h"
#include "fsl_mipi_dsi_cmd.h"
/*
* Change log:
*
* 1.1.0
* - Fix MISRA-C 2012 issues.
* - Change rm68191_resource_t structure.
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief RM68191 resource.
*/
typedef struct _rm68191_resource
{
mipi_dsi_device_t *dsiDevice; /*!< MIPI DSI device. */
void (*pullResetPin)(bool pullUp); /*!< Function to pull reset pin high or low. */
void (*pullPowerPin)(bool pullUp); /*!< Function to pull power pin high or low. */
} rm68191_resource_t;
extern const display_operations_t rm68191_ops;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
status_t RM68191_Init(display_handle_t *handle, const display_config_t *config);
status_t RM68191_Deinit(display_handle_t *handle);
status_t RM68191_Start(display_handle_t *handle);
status_t RM68191_Stop(display_handle_t *handle);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_RM68191_H_ */

View File

@ -0,0 +1,409 @@
/*
* Copyright 2019-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_display.h"
#include "fsl_rm68200.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define RM68200_DelayMs VIDEO_DelayMs
/*******************************************************************************
* Variables
******************************************************************************/
uint8_t RM68200_DDB_START[5] = {0x00, 0x00, 0x00, 0x00, 0xff};
static const uint8_t lcmInitPage0Setting[][2] = {
{0xFE, 0x01}, {0x24, 0xC0}, {0x25, 0x53}, {0x26, 0x00}, {0x2B, 0xE5}, {0x27, 0x0A},
{0x29, 0x0A}, {0x16, 0x52}, {0x2F, 0x53}, {0x34, 0x5A}, {0x1B, 0x00}, {0x12, 0x0A},
{0x1A, 0x06}, {0x46, 0x56}, {0x52, 0xA0}, {0x53, 0x00}, {0x54, 0xA0}, {0x55, 0x00},
};
static const uint8_t lcmInitSetting[][2] = {
{0xFE, 0x03},
{0x00, 0x05},
{0x02, 0x0B},
{0x03, 0x0F},
{0x04, 0x7D},
{0x05, 0x00},
{0x06, 0x50},
{0x07, 0x05},
{0x08, 0x16},
{0x09, 0x0D},
{0x0A, 0x11},
{0x0B, 0x7D},
{0x0C, 0x00},
{0x0D, 0x50},
{0x0E, 0x07},
{0x0F, 0x08},
{0x10, 0x01},
{0x11, 0x02},
{0x12, 0x00},
{0x13, 0x7D},
{0x14, 0x00},
{0x15, 0x85},
{0x16, 0x08},
{0x17, 0x03},
{0x18, 0x04},
{0x19, 0x05},
{0x1A, 0x06},
{0x1B, 0x00},
{0x1C, 0x7D},
{0x1D, 0x00},
{0x1E, 0x85},
{0x1F, 0x08},
{0x20, 0x00},
{0x21, 0x00},
{0x22, 0x00},
{0x23, 0x00},
{0x24, 0x00},
{0x25, 0x00},
{0x26, 0x00},
{0x27, 0x00},
{0x28, 0x00},
{0x29, 0x00},
{0x2A, 0x07},
{0x2B, 0x08},
{0x2D, 0x01},
{0x2F, 0x02},
{0x30, 0x00},
{0x31, 0x40},
{0x32, 0x05},
{0x33, 0x08},
{0x34, 0x54},
{0x35, 0x7D},
{0x36, 0x00},
{0x37, 0x03},
{0x38, 0x04},
{0x39, 0x05},
{0x3A, 0x06},
{0x3B, 0x00},
{0x3D, 0x40},
{0x3F, 0x05},
{0x40, 0x08},
{0x41, 0x54},
{0x42, 0x7D},
{0x43, 0x00},
{0x44, 0x00},
{0x45, 0x00},
{0x46, 0x00},
{0x47, 0x00},
{0x48, 0x00},
{0x49, 0x00},
{0x4A, 0x00},
{0x4B, 0x00},
{0x4C, 0x00},
{0x4D, 0x00},
{0x4E, 0x00},
{0x4F, 0x00},
{0x50, 0x00},
{0x51, 0x00},
{0x52, 0x00},
{0x53, 0x00},
{0x54, 0x00},
{0x55, 0x00},
{0x56, 0x00},
{0x58, 0x00},
{0x59, 0x00},
{0x5A, 0x00},
{0x5B, 0x00},
{0x5C, 0x00},
{0x5D, 0x00},
{0x5E, 0x00},
{0x5F, 0x00},
{0x60, 0x00},
{0x61, 0x00},
{0x62, 0x00},
{0x63, 0x00},
{0x64, 0x00},
{0x65, 0x00},
{0x66, 0x00},
{0x67, 0x00},
{0x68, 0x00},
{0x69, 0x00},
{0x6A, 0x00},
{0x6B, 0x00},
{0x6C, 0x00},
{0x6D, 0x00},
{0x6E, 0x00},
{0x6F, 0x00},
{0x70, 0x00},
{0x71, 0x00},
{0x72, 0x20},
{0x73, 0x00},
{0x74, 0x08},
{0x75, 0x08},
{0x76, 0x08},
{0x77, 0x08},
{0x78, 0x08},
{0x79, 0x08},
{0x7A, 0x00},
{0x7B, 0x00},
{0x7C, 0x00},
{0x7D, 0x00},
{0x7E, 0xBF},
{0x7F, 0x02},
{0x80, 0x06},
{0x81, 0x14},
{0x82, 0x10},
{0x83, 0x16},
{0x84, 0x12},
{0x85, 0x08},
{0x86, 0x3F},
{0x87, 0x3F},
{0x88, 0x3F},
{0x89, 0x3F},
{0x8A, 0x3F},
{0x8B, 0x0C},
{0x8C, 0x0A},
{0x8D, 0x0E},
{0x8E, 0x3F},
{0x8F, 0x3F},
{0x90, 0x00},
{0x91, 0x04},
{0x92, 0x3F},
{0x93, 0x3F},
{0x94, 0x3F},
{0x95, 0x3F},
{0x96, 0x05},
{0x97, 0x01},
{0x98, 0x3F},
{0x99, 0x3F},
{0x9A, 0x0F},
{0x9B, 0x0B},
{0x9C, 0x0D},
{0x9D, 0x3F},
{0x9E, 0x3F},
{0x9F, 0x3F},
{0xA0, 0x3F},
{0xA2, 0x3F},
{0xA3, 0x09},
{0xA4, 0x13},
{0xA5, 0x17},
{0xA6, 0x11},
{0xA7, 0x15},
{0xA9, 0x07},
{0xAA, 0x03},
{0xAB, 0x3F},
{0xAC, 0x3F},
{0xAD, 0x05},
{0xAE, 0x01},
{0xAF, 0x17},
{0xB0, 0x13},
{0xB1, 0x15},
{0xB2, 0x11},
{0xB3, 0x0F},
{0xB4, 0x3F},
{0xB5, 0x3F},
{0xB6, 0x3F},
{0xB7, 0x3F},
{0xB8, 0x3F},
{0xB9, 0x0B},
{0xBA, 0x0D},
{0xBB, 0x09},
{0xBC, 0x3F},
{0xBD, 0x3F},
{0xBE, 0x07},
{0xBF, 0x03},
{0xC0, 0x3F},
{0xC1, 0x3F},
{0xC2, 0x3F},
{0xC3, 0x3F},
{0xC4, 0x02},
{0xC5, 0x06},
{0xC6, 0x3F},
{0xC7, 0x3F},
{0xC8, 0x08},
{0xC9, 0x0C},
{0xCA, 0x0A},
{0xCB, 0x3F},
{0xCC, 0x3F},
{0xCD, 0x3F},
{0xCE, 0x3F},
{0xCF, 0x3F},
{0xD0, 0x0E},
{0xD1, 0x10},
{0xD2, 0x14},
{0xD3, 0x12},
{0xD4, 0x16},
{0xD5, 0x00},
{0xD6, 0x04},
{0xD7, 0x3F},
{0xDC, 0x02},
{0xDE, 0x12},
{0xFE, 0x0E},
{0x01, 0x75},
/* Gamma Settings */
{0xFE, 0x04},
{0x60, 0x00},
{0x61, 0x0C},
{0x62, 0x12},
{0x63, 0x0E},
{0x64, 0x06},
{0x65, 0x12},
{0x66, 0x0E},
{0x67, 0x0B},
{0x68, 0x15},
{0x69, 0x0B},
{0x6A, 0x10},
{0x6B, 0x07},
{0x6C, 0x0F},
{0x6D, 0x12},
{0x6E, 0x0C},
{0x6F, 0x00},
{0x70, 0x00},
{0x71, 0x0C},
{0x72, 0x12},
{0x73, 0x0E},
{0x74, 0x06},
{0x75, 0x12},
{0x76, 0x0E},
{0x77, 0x0B},
{0x78, 0x15},
{0x79, 0x0B},
{0x7A, 0x10},
{0x7B, 0x07},
{0x7C, 0x0F},
{0x7D, 0x12},
{0x7E, 0x0C},
{0x7F, 0x00},
/* Page 0. */
{0xFE, 0x00},
{0x11, 0x00},
};
const display_operations_t rm68200_ops = {
.init = RM68200_Init,
.deinit = RM68200_Deinit,
.start = RM68200_Start,
.stop = RM68200_Stop,
};
/*******************************************************************************
* Code
******************************************************************************/
status_t RM68200_Init(display_handle_t *handle, const display_config_t *config)
{
uint32_t i;
uint8_t param[2];
status_t status = kStatus_Success;
const rm68200_resource_t *resource = (const rm68200_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
/* Only support 720 * 1280 */
if (config->resolution != FSL_VIDEO_RESOLUTION(720, 1280))
{
return kStatus_InvalidArgument;
}
/* Power on. */
resource->pullPowerPin(true);
RM68200_DelayMs(1);
/* Perform reset. */
resource->pullResetPin(false);
RM68200_DelayMs(1);
resource->pullResetPin(true);
RM68200_DelayMs(5);
/* Set the LCM page0 init settings. */
for (i = 0; i < ARRAY_SIZE(lcmInitPage0Setting); i++)
{
status = MIPI_DSI_GenericWrite(dsiDevice, lcmInitPage0Setting[i], 2);
if (kStatus_Success != status)
{
return status;
}
}
/* Data lane number selection. */
param[0] = 0x5FU;
param[1] = 0x10U | (config->dsiLanes - 1U);
status = MIPI_DSI_GenericWrite(dsiDevice, param, 2);
if (kStatus_Success != status)
{
return status;
}
/* Set the LCM init settings. */
for (i = 0; i < ARRAY_SIZE(lcmInitSetting); i++)
{
status = MIPI_DSI_GenericWrite(dsiDevice, lcmInitSetting[i], 2);
if (kStatus_Success != status)
{
return status;
}
}
RM68200_DelayMs(200);
param[0] = 0x29;
param[1] = 0x00;
status = MIPI_DSI_GenericWrite(dsiDevice, param, 2);
if (kStatus_Success != status)
{
return status;
}
RM68200_DelayMs(100);
param[0] = 0x2c;
status = MIPI_DSI_GenericWrite(dsiDevice, param, 1);
if (kStatus_Success != status)
{
return status;
}
param[0] = 0x35;
param[1] = 0x00;
status = MIPI_DSI_GenericWrite(dsiDevice, param, 2);
if (kStatus_Success != status)
{
return status;
}
RM68200_DelayMs(200);
return kStatus_Success;
}
status_t RM68200_Deinit(display_handle_t *handle)
{
const rm68200_resource_t *resource = (const rm68200_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
(void)MIPI_DSI_DCS_EnterSleepMode(dsiDevice, true);
resource->pullResetPin(false);
resource->pullPowerPin(false);
return kStatus_Success;
}
status_t RM68200_Start(display_handle_t *handle)
{
const rm68200_resource_t *resource = (const rm68200_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, true);
}
status_t RM68200_Stop(display_handle_t *handle)
{
const rm68200_resource_t *resource = (const rm68200_resource_t *)(handle->resource);
mipi_dsi_device_t *dsiDevice = resource->dsiDevice;
return MIPI_DSI_DCS_SetDisplayOn(dsiDevice, false);
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2019-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_RM68200_H_
#define _FSL_RM68200_H_
#include "fsl_display.h"
#include "fsl_mipi_dsi_cmd.h"
/*
* Change log:
*
* 1.1.1
* - Support 1 lane to 4 lanes, previously only support 2 lanes.
*
* 1.1.0
* - Fix MISRA-C 2012 issues.
* - Change rm68200_resource_t structure.
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief RM68200 resource.
*/
typedef struct _rm68200_resource
{
mipi_dsi_device_t *dsiDevice; /*!< MIPI DSI device. */
void (*pullResetPin)(bool pullUp); /*!< Function to pull reset pin high or low. */
void (*pullPowerPin)(bool pullUp); /*!< Function to pull power pin high or low. */
} rm68200_resource_t;
extern const display_operations_t rm68200_ops;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
extern uint8_t RM68200_DDB_START[5];
status_t RM68200_Init(display_handle_t *handle, const display_config_t *config);
status_t RM68200_Deinit(display_handle_t *handle);
status_t RM68200_Start(display_handle_t *handle);
status_t RM68200_Stop(display_handle_t *handle);
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_RM68200_H_ */

View File

@ -0,0 +1,301 @@
/*
* Copyright 2017, 2020-2021, 2023 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_video_common.h"
#if defined(SDK_OS_RTOS)
#include "rtthread.h"
#endif
/*******************************************************************************
* Code
******************************************************************************/
bool VIDEO_IsYUV(video_pixel_format_t format)
{
if ((kVIDEO_PixelFormatYUYV == format) || (kVIDEO_PixelFormatYVYU == format) ||
(kVIDEO_PixelFormatUYVY == format) || (kVIDEO_PixelFormatVYUY == format) ||
(kVIDEO_PixelFormatXYVU == format) || (kVIDEO_PixelFormatXYUV == format))
{
return true;
}
else
{
return false;
}
}
void VIDEO_DelayMs(uint32_t ms)
{
#if defined(SDK_OS_RTOS)
rt_thread_mdelay(ms);
#else
while (0U != (ms--))
{
SDK_DelayAtLeastUs(1000U, SystemCoreClock);
}
#endif
}
uint8_t VIDEO_GetPixelSizeBits(video_pixel_format_t pixelFormat)
{
uint8_t ret;
switch (pixelFormat)
{
case kVIDEO_PixelFormatXRGB8888:
case kVIDEO_PixelFormatRGBX8888:
case kVIDEO_PixelFormatXBGR8888:
case kVIDEO_PixelFormatBGRX8888:
case kVIDEO_PixelFormatXYUV:
case kVIDEO_PixelFormatXYVU:
ret = 32;
break;
case kVIDEO_PixelFormatRGB888:
case kVIDEO_PixelFormatBGR888:
ret = 24;
break;
case kVIDEO_PixelFormatRGB565:
case kVIDEO_PixelFormatBGR565:
case kVIDEO_PixelFormatXRGB1555:
case kVIDEO_PixelFormatRGBX5551:
case kVIDEO_PixelFormatXBGR1555:
case kVIDEO_PixelFormatBGRX5551:
case kVIDEO_PixelFormatXRGB4444:
case kVIDEO_PixelFormatRGBX4444:
case kVIDEO_PixelFormatXBGR4444:
case kVIDEO_PixelFormatBGRX4444:
case kVIDEO_PixelFormatYUYV:
case kVIDEO_PixelFormatYVYU:
case kVIDEO_PixelFormatUYVY:
case kVIDEO_PixelFormatVYUY:
ret = 16;
break;
case kVIDEO_PixelFormatRAW8:
case kVIDEO_PixelFormatLUT8:
ret = 8;
break;
default:
ret = 0;
break;
}
return ret;
}
status_t VIDEO_RINGBUF_Init(video_ringbuf_t *ringbuf, void **buf, uint32_t size)
{
assert(ringbuf != NULL);
ringbuf->rear = 0;
ringbuf->front = 0;
ringbuf->size = size;
ringbuf->buf = buf;
return kStatus_Success;
}
status_t VIDEO_RINGBUF_Get(video_ringbuf_t *ringbuf, void **item)
{
uint32_t front_next;
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
if (rear != front)
{
*item = ringbuf->buf[ringbuf->front];
/*
* Here don't use ringbuf->front = (ringbuf->front + 1) % ringbuf->size,
* because mod operation might be slow.
*/
front_next = (ringbuf->front + 1U);
/* Use two steps to make sure ringbuf->front is always a valid value. */
ringbuf->front = (front_next == ringbuf->size) ? 0UL : front_next;
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}
status_t VIDEO_RINGBUF_Put(video_ringbuf_t *ringbuf, void *item)
{
/*
* Here don't use ringbuf->rear = (ringbuf->rear + 1) % ringbuf->size,
* because mod operation might be slow.
*/
uint32_t rear_next = ringbuf->rear + 1U;
rear_next = (rear_next == ringbuf->size) ? 0U : rear_next;
if (rear_next != ringbuf->front)
{
ringbuf->buf[ringbuf->rear] = item;
ringbuf->rear = rear_next;
return kStatus_Success;
}
/* No room. */
else
{
return kStatus_Fail;
}
}
uint32_t VIDEO_RINGBUF_GetLength(video_ringbuf_t *ringbuf)
{
uint32_t ret;
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
ret = (rear + ringbuf->size) - front;
if (ret >= ringbuf->size)
{
ret -= ringbuf->size;
}
return ret;
}
bool VIDEO_RINGBUF_IsEmpty(video_ringbuf_t *ringbuf)
{
/* To fix IAR Pa082 warning. */
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
if (rear == front)
{
return true;
}
else
{
return false;
}
}
bool VIDEO_RINGBUF_IsFull(video_ringbuf_t *ringbuf)
{
uint32_t rear = ringbuf->rear;
uint32_t front = ringbuf->front;
rear++;
if (rear >= ringbuf->size)
{
rear = 0;
}
if (rear == front)
{
return true;
}
else
{
return false;
}
}
status_t VIDEO_MEMPOOL_Init(video_mempool_t *mempool, void *initMem, uint32_t size, uint32_t count)
{
(void)memset(mempool, 0, sizeof(video_mempool_t));
while (0U != (count--))
{
VIDEO_MEMPOOL_Put(mempool, initMem);
initMem = &((uint8_t *)initMem)[size];
}
return kStatus_Success;
}
void VIDEO_MEMPOOL_InitEmpty(video_mempool_t *mempool)
{
mempool->pool = NULL;
mempool->cnt = 0;
}
void VIDEO_MEMPOOL_Put(video_mempool_t *mempool, void *mem)
{
*(void **)mem = mempool->pool;
mempool->pool = mem;
mempool->cnt++;
}
void *VIDEO_MEMPOOL_Get(video_mempool_t *mempool)
{
void *mem = mempool->pool;
if (NULL != mem)
{
mempool->cnt--;
mempool->pool = *(void **)mem;
}
return mem;
}
uint32_t VIDEO_MEMPOOL_GetCount(video_mempool_t *mempool)
{
return mempool->cnt;
}
status_t VIDEO_STACK_Init(video_stack_t *stack, void **buf, uint32_t size)
{
stack->buf = buf;
stack->maxCount = size;
stack->top = 0U;
return kStatus_Success;
}
status_t VIDEO_STACK_Pop(video_stack_t *stack, void **item)
{
status_t status;
if (stack->top > 0U)
{
*item = stack->buf[--stack->top];
status = kStatus_Success;
}
else
{
*item = NULL;
status = kStatus_Fail;
}
return status;
}
status_t VIDEO_STACK_Push(video_stack_t *stack, void *item)
{
status_t status;
if (stack->top < (stack->maxCount))
{
stack->buf[stack->top++] = item;
status = kStatus_Success;
}
else
{
status = kStatus_Fail;
}
return status;
}

View File

@ -0,0 +1,364 @@
/*
* Copyright 2017, 2020-2021, 2023 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_VIDEO_COMMON_H_
#define _FSL_VIDEO_COMMON_H_
#include "fsl_common.h"
/*
* Change log:
*
* 1.1.0
* - Add stack function which supports LIFO item management.
*
* 1.0.5
* - Fix IAR Pa082 warning.
*
* 1.0.4
* - Add LUT8 definition.
*
* 1.0.3
* - Add RAW8 definition.
*
* 1.0.2
* - Fixed MISRA-C 2012 issues.
*
* 1.0.1
* - Update the VIDEO_DelayMs for bare metal.
*
* 1.0.0
* - Initial version
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Pixel format FOURCC. */
#define FSL_VIDEO_FOURCC(a, b, c, d) \
((uint32_t)(a) | ((uint32_t)(b) << 8U) | ((uint32_t)(c) << 16U) | ((uint32_t)(d) << 24U))
/*! @brief Macro to define resolution. */
#define FSL_VIDEO_RESOLUTION(width, height) ((uint32_t)(width) | ((uint32_t)(height) << 16U))
#define FSL_VIDEO_EXTRACT_WIDTH(resolution) ((uint16_t)((resolution)&0xFFFFU))
#define FSL_VIDEO_EXTRACT_HEIGHT(resolution) ((uint16_t)((resolution) >> 16U))
/*! @brief Pixel format definition. */
typedef enum _video_pixel_format
{
/* RAW */
kVIDEO_PixelFormatRAW8 = FSL_VIDEO_FOURCC('G', 'R', 'B', 'G'), /*!< RAW8, GRBG. */
/* LUT/palette */
kVIDEO_PixelFormatLUT8 = FSL_VIDEO_FOURCC('L', 'U', 'T', '8'), /*!< 8-bit Indexed Color. */
/* RGB */
kVIDEO_PixelFormatXRGB8888 = FSL_VIDEO_FOURCC('X', 'R', '2', '4'), /*!< 32-bit XRGB8888. */
kVIDEO_PixelFormatRGBX8888 = FSL_VIDEO_FOURCC('R', 'X', '2', '4'), /*!< 32-bit RGBX8888. */
kVIDEO_PixelFormatXBGR8888 = FSL_VIDEO_FOURCC('X', 'B', '2', '4'), /*!< 32-bit XBGR8888. */
kVIDEO_PixelFormatBGRX8888 = FSL_VIDEO_FOURCC('B', 'X', '2', '4'), /*!< 32-bit BGRX8888. */
kVIDEO_PixelFormatRGB888 = FSL_VIDEO_FOURCC('R', 'G', '2', '4'), /*!< 24-bit RGB888. */
kVIDEO_PixelFormatBGR888 = FSL_VIDEO_FOURCC('B', 'G', '2', '4'), /*!< 24-bit BGR888. */
kVIDEO_PixelFormatRGB565 = FSL_VIDEO_FOURCC('R', 'G', '1', '6'), /*!< 16-bit RGB565. */
kVIDEO_PixelFormatBGR565 = FSL_VIDEO_FOURCC('B', 'G', '1', '6'), /*!< 16-bit BGR565. */
kVIDEO_PixelFormatXRGB1555 = FSL_VIDEO_FOURCC('X', 'R', '1', '5'), /*!< 16-bit XRGB1555. */
kVIDEO_PixelFormatRGBX5551 = FSL_VIDEO_FOURCC('R', 'X', '1', '5'), /*!< 16-bit RGBX5551. */
kVIDEO_PixelFormatXBGR1555 = FSL_VIDEO_FOURCC('X', 'B', '1', '5'), /*!< 16-bit XBGR1555. */
kVIDEO_PixelFormatBGRX5551 = FSL_VIDEO_FOURCC('B', 'X', '1', '5'), /*!< 16-bit BGRX5551. */
kVIDEO_PixelFormatXRGB4444 = FSL_VIDEO_FOURCC('X', 'R', '1', '2'), /*!< 16-bit XRGB4444. */
kVIDEO_PixelFormatRGBX4444 = FSL_VIDEO_FOURCC('R', 'X', '1', '2'), /*!< 16-bit RGBX4444. */
kVIDEO_PixelFormatXBGR4444 = FSL_VIDEO_FOURCC('X', 'B', '1', '2'), /*!< 16-bit XBGR4444. */
kVIDEO_PixelFormatBGRX4444 = FSL_VIDEO_FOURCC('B', 'X', '1', '2'), /*!< 16-bit BGRX4444. */
/* YUV. */
kVIDEO_PixelFormatYUYV = FSL_VIDEO_FOURCC('Y', 'U', 'Y', 'V'), /*!< YUV422, Y-U-Y-V. */
kVIDEO_PixelFormatYVYU = FSL_VIDEO_FOURCC('Y', 'V', 'Y', 'U'), /*!< YUV422, Y-V-Y-U. */
kVIDEO_PixelFormatUYVY = FSL_VIDEO_FOURCC('U', 'Y', 'V', 'Y'), /*!< YUV422, U-Y-V-Y. */
kVIDEO_PixelFormatVYUY = FSL_VIDEO_FOURCC('V', 'Y', 'U', 'Y'), /*!< YUV422, V-Y-U-Y. */
kVIDEO_PixelFormatXYUV = FSL_VIDEO_FOURCC('X', 'Y', 'U', 'V'), /*!< YUV444, X-Y-U-V. */
kVIDEO_PixelFormatXYVU = FSL_VIDEO_FOURCC('X', 'Y', 'V', 'U'), /*!< YUV444, X-Y-V-U. */
} video_pixel_format_t;
/*! @brief Resolution definition. */
typedef enum _video_resolution
{
kVIDEO_ResolutionVGA = FSL_VIDEO_RESOLUTION(640, 480), /*!< VGA, 640 * 480 */
kVIDEO_ResolutionQVGA = FSL_VIDEO_RESOLUTION(320, 240), /*!< QVGA, 320 * 240 */
kVIDEO_ResolutionQQVGA = FSL_VIDEO_RESOLUTION(160, 120), /*!< QQVGA, 160 * 120 */
kVIDEO_ResolutionCIF = FSL_VIDEO_RESOLUTION(352, 288), /*!< CIF, 352 * 288 */
kVIDEO_ResolutionQCIF = FSL_VIDEO_RESOLUTION(176, 144), /*!< QCIF, 176 * 144 */
kVIDEO_ResolutionQQCIF = FSL_VIDEO_RESOLUTION(88, 72), /*!< QQCIF, 88 * 72 */
kVIDEO_Resolution720P = FSL_VIDEO_RESOLUTION(1280, 720), /*!< 720P, 1280 * 720 */
kVIDEO_Resolution1080P = FSL_VIDEO_RESOLUTION(1920, 1080), /*!< 1080P, 1920 * 1280*/
kVIDEO_ResolutionWXGA = FSL_VIDEO_RESOLUTION(1280, 800), /*!< WXGA, 1280 * 800 */
} video_resolution_t;
/*!
* @brief Ring buffer structure.
*
* There is one empty room reserved in the ring buffer, used to distinguish
* whether the ring buffer is full or empty. When rear equals front, it is empty;
* when rear+1 equals front, it is full.
*/
typedef struct
{
volatile uint32_t rear; /*!< Pointer to save the incoming item. */
volatile uint32_t front; /*!< Pointer to read out the item. */
void *volatile *buf; /*!< Memory to the ring buffer. */
uint32_t size; /*!< Ring buffer total size. */
} video_ringbuf_t;
/*!
* @brief Memory pool structure.
*/
typedef struct
{
void *volatile pool; /*!< Pointer to the pool. */
volatile uint32_t cnt; /*!< Count of memory blocks in the pool. */
} video_mempool_t;
/*!
* @brief Stack structure.
*/
typedef struct
{
void **buf; /*!< Pointer to the memory to store the items. */
volatile uint32_t top; /*!< Current top stack top. */
uint32_t maxCount; /*!< Maximal count of items can be stored in the stack. */
} video_stack_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Common
* @{
*/
/*!
* @brief Check the pixel format is YUV or not.
*
* @param format Pixel format.
*/
bool VIDEO_IsYUV(video_pixel_format_t format);
/*!
* @brief Delay the specific time.
*
* @param ms How many milli-second to delay.
*/
void VIDEO_DelayMs(uint32_t ms);
/*!
* @brief Get the pixel size in bits.
*
* @param pixelFormat The pixel format.
* @return Bits per pixel.
*/
uint8_t VIDEO_GetPixelSizeBits(video_pixel_format_t pixelFormat);
/* @} */
/*!
* @name Ring buffer.
* @{
*/
/*!
* @brief Initializes ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param buf Memory to save the items.
* @param size Size of the @p buf.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Init(video_ringbuf_t *ringbuf, void **buf, uint32_t size);
/*!
* @brief Get one item from the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param item Memory to save the item.
* @return Returns @ref kStatus_Success if get success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Get(video_ringbuf_t *ringbuf, void **item);
/*!
* @brief Put one item to the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @param item The new item to save.
* @return Returns @ref kStatus_Success if put success, otherwise returns
* error code.
*/
status_t VIDEO_RINGBUF_Put(video_ringbuf_t *ringbuf, void *item);
/*!
* @brief Get current count of items in the ring buffer.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns the item count.
*/
uint32_t VIDEO_RINGBUF_GetLength(video_ringbuf_t *ringbuf);
/*!
* @brief Check whether the ring buffer is empty.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns true if the ring buffer is empty, otherwise returns false.
*/
bool VIDEO_RINGBUF_IsEmpty(video_ringbuf_t *ringbuf);
/*!
* @brief Check whether the ring buffer is full.
*
* @param ringbuf Pointer to the ring buffer handle.
* @return Returns true if the ring buffer is full, otherwise returns false.
*/
bool VIDEO_RINGBUF_IsFull(video_ringbuf_t *ringbuf);
/* @} */
/*!
* @name Memory Pool
*
* User can put memory block to the pool, or get memory block from the pool.
* There is no count limitation to put memory block in to the pool. The memory
* content in the pool might be modified.
*
* The memory block should be 4-byte aligned, and the dividable by 4-byte.
*
* @{
*/
/*!
* @brief Initializes memory pool.
*
* Initializes memory pool. Initial memory blocks in the memory pool is optional.
* If initial blocks are used, user should specify the initial block size and count.
*
* @param mempool Pointer to the memory pool handle.
* @param initMem Initial memory blocks to saved in the pool.
* @param size Every memory block's size (bytes) in the @p initMem.
* @param count Number of memory blocks @p initMem.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
status_t VIDEO_MEMPOOL_Init(video_mempool_t *mempool, void *initMem, uint32_t size, uint32_t count);
/*!
* @brief Create an empty memory pool.
*
* @param mempool Pointer to the memory pool handle.
*/
void VIDEO_MEMPOOL_InitEmpty(video_mempool_t *mempool);
/*!
* @brief Put memory block in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @param mem Pointer to the memory block.
*/
void VIDEO_MEMPOOL_Put(video_mempool_t *mempool, void *mem);
/*!
* @brief Get memory block in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @return The memory block get from pool. If the pool is empty, returns NULL.
*/
void *VIDEO_MEMPOOL_Get(video_mempool_t *mempool);
/*!
* @brief How many memory blocks in the pool.
*
* @param mempool Pointer to the memory pool handle.
* @return The memory block count in the pool
*/
uint32_t VIDEO_MEMPOOL_GetCount(video_mempool_t *mempool);
/* @} */
/*!
* @name Stack which supports LIFO item management.
* @{
*/
/*!
* @brief Initializes stack.
*
* @param stack Pointer to the stack handle.
* @param buf Memory to save the items.
* @param size Size of the @p buf.
* @return Returns @ref kStatus_Success if initialize success, otherwise returns
* error code.
*/
status_t VIDEO_STACK_Init(video_stack_t *stack, void **buf, uint32_t size);
/*!
* @brief Pop one item from the stack.
*
* @param stack Pointer to the stack handle.
* @param item Memory to save the item.
* @return Returns @ref kStatus_Success if get success, returns
* kStatus_Fail if the stack is empty.
*/
status_t VIDEO_STACK_Pop(video_stack_t *stack, void **item);
/*!
* @brief Put one item to the stack.
*
* @param stack Pointer to the stack handle.
* @param item The new item to save.
* @return Returns @ref kStatus_Success if put success, returns
* kStatus_Fail if the stack is full.
*/
status_t VIDEO_STACK_Push(video_stack_t *stack, void *item);
/*!
* @brief Get current count of items in the stack.
*
* @param stack Pointer to the stack handle.
* @return Returns the item count.
*/
static inline uint32_t VIDEO_STACK_GetCount(video_stack_t *stack)
{
return stack->top;
}
/*!
* @brief Get maxiumal count of items in the stack.
*
* @param stack Pointer to the stack handle.
* @return Returns the maxiumal count of items in the stack.
*/
static inline uint32_t VIDEO_STACK_GetMaxCount(video_stack_t *stack)
{
return stack->maxCount;
}
/* @} */
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_VIDEO_COMMON_H_ */

View File

@ -0,0 +1,14 @@
/* Tiny library for rendering compressed bitmap fonts on microcontrollers. */
#ifndef _MCUFONT_H_
#define _MCUFONT_H_
#include "mf_config.h"
#include "mf_encoding.h"
#include "mf_justify.h"
#include "mf_kerning.h"
#include "mf_rlefont.h"
#include "mf_scaledfont.h"
#include "mf_wordwrap.h"
#endif

View File

@ -0,0 +1,134 @@
#include "mf_bwfont.h"
#include <stdbool.h>
/* Find the character range and index that contains a given glyph.. */
static const struct mf_bwfont_char_range_s *find_char_range(
const struct mf_bwfont_s *font, uint16_t character, uint16_t *index_ret)
{
unsigned i, index;
const struct mf_bwfont_char_range_s *range;
for (i = 0; i < font->char_range_count; i++)
{
range = &font->char_ranges[i];
index = character - range->first_char;
if (character >= range->first_char && index < range->char_count)
{
*index_ret = index;
return range;
}
}
return 0;
}
static uint8_t get_width(const struct mf_bwfont_char_range_s *r, uint16_t index)
{
if (r->width)
{
return r->width + r->offset_x;
}
else
{
return r->glyph_widths[index];
}
}
static uint8_t render_char(const struct mf_bwfont_char_range_s *r,
int16_t x0, int16_t y0, uint16_t index,
mf_pixel_callback_t callback,
void *state)
{
const uint8_t *data, *p;
uint8_t stride, runlen;
uint8_t x, y, height, num_cols;
uint8_t bit, byte, mask;
bool oldstate, newstate;
if (r->width)
{
data = r->glyph_data + r->width * index * r->height_bytes;
num_cols = r->width;
}
else
{
data = r->glyph_data + r->glyph_offsets[index] * r->height_bytes;
num_cols = r->glyph_offsets[index + 1] - r->glyph_offsets[index];
}
stride = r->height_bytes;
height = r->height_pixels;
y0 += r->offset_y;
x0 += r->offset_x;
bit = 0;
byte = 0;
for (y = 0; y < height; y++)
{
mask = (1 << bit);
oldstate = false;
runlen = 0;
p = data + byte;
for (x = 0; x < num_cols; x++, p += stride)
{
newstate = pgm_read_byte(p) & mask;
if (newstate != oldstate)
{
if (oldstate && runlen)
{
callback(x0 + x - runlen, y0 + y, runlen, 255, state);
}
oldstate = newstate;
runlen = 0;
}
runlen++;
}
if (oldstate && runlen)
{
callback(x0 + x - runlen, y0 + y, runlen, 255, state);
}
bit++;
if (bit > 7)
{
bit = 0;
byte++;
}
}
return get_width(r, index);
}
uint8_t mf_bwfont_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
uint16_t character,
mf_pixel_callback_t callback,
void *state)
{
const struct mf_bwfont_s *bwfont = (const struct mf_bwfont_s*)font;
const struct mf_bwfont_char_range_s *range;
uint16_t index;
range = find_char_range(bwfont, character, &index);
if (!range)
return 0;
return render_char(range, x0, y0, index, callback, state);
}
uint8_t mf_bwfont_character_width(const struct mf_font_s *font,
uint16_t character)
{
const struct mf_bwfont_s *bwfont = (const struct mf_bwfont_s*)font;
const struct mf_bwfont_char_range_s *range;
uint16_t index;
range = find_char_range(bwfont, character, &index);
if (!range)
return 0;
return get_width(range, index);
}

View File

@ -0,0 +1,77 @@
/* Uncompressed font format for storing black & white fonts. Very efficient
* to decode and works well for small font sizes.
*/
#ifndef _MF_BWFONT_H_
#define _MF_BWFONT_H_
#include "mf_font.h"
/* Versions of the BW font format that are supported. */
#define MF_BWFONT_VERSION_4_SUPPORTED 1
/* Structure for a range of characters. */
struct mf_bwfont_char_range_s
{
/* The number of the first character in this range. */
uint16_t first_char;
/* The total count of characters in this range. */
uint16_t char_count;
/* The left and top skips of the characters in this range.
* This is the number of empty rows at left and at top. */
uint8_t offset_x;
uint8_t offset_y;
/* Column height for glyphs in this range, in bytes and pixels. */
uint8_t height_bytes;
uint8_t height_pixels;
/* Positive value if the width of all glyphs in this range is the
* same, or zero if it is not. */
uint8_t width;
/* Lookup table for the character widths. NULL if width is specified. */
uint8_t *glyph_widths;
/* Lookup table for the character offsets. Multiply by height_bytes
* to get the byte offset. Also allows lookup of the number of columns.
* NULL if width is specified. */
uint16_t *glyph_offsets;
/* Table for the glyph data.
* The data for each glyph is column-by-column, with N bytes per each
* column. The LSB of the first byte is the top left pixel.
*/
uint8_t *glyph_data;
};
/* Structure for the font */
struct mf_bwfont_s
{
struct mf_font_s font;
/* Version of the font format. */
uint8_t version;
/* Number of character ranges. */
uint8_t char_range_count;
/* Array of the character ranges */
struct mf_bwfont_char_range_s *char_ranges;
};
#ifdef MF_BWFONT_INTERNALS
/* Internal functions, don't use these directly. */
MF_EXTERN uint8_t mf_bwfont_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state);
MF_EXTERN uint8_t mf_bwfont_character_width(const struct mf_font_s *font,
mf_char character);
#endif
#endif

View File

@ -0,0 +1,144 @@
/* Configuration constants for mcufont. */
#ifndef _MF_CONFIG_H_
#define _MF_CONFIG_H_
#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include <pgmspace.h>
#else
#include <stdint.h>
#define PROGMEM
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const uint16_t *)(addr))
#endif /* __AVR__ */
/*******************************************************
* Configuration settings related to build environment *
*******************************************************/
/* Name of the file that contains all the included fonts. */
#ifndef MF_FONT_FILE_NAME
#define MF_FONT_FILE_NAME "fonts.h"
#endif
/*****************************************
* Configuration settings related to API *
*****************************************/
/* Encoding for the input data.
* With the unicode encodings, the library supports the range of unicode
* characters 0x0000-0xFFFF (the Basic Multilingual Plane).
*
* ASCII: Plain ascii (somewhat works with ISO8859-1 also)
* UTF8: UTF8 encoding (variable number of bytes)
* UTF16: UTF16 encoding (2 bytes per character, compatible with UCS-2)
* WCHAR: Use compiler's wchar_t (usually same as UTF16)
*/
#define MF_ENCODING_ASCII 0
#define MF_ENCODING_UTF8 1
#define MF_ENCODING_UTF16 2
#define MF_ENCODING_WCHAR 3
#ifndef MF_ENCODING
#define MF_ENCODING MF_ENCODING_UTF8
#endif
/************************************************************************
* Configuration settings related to visual appearance of rendered text *
************************************************************************/
/* Minimum space between characters, in percents of the glyph width.
* Increasing this causes the kerning module to leave more space between
* characters.
*/
#ifndef MF_KERNING_SPACE_PERCENT
#define MF_KERNING_SPACE_PERCENT 15
#endif
/* Minimum space between characters, in pixels. Added to the percentual
* spacing. This pixel-based value guarantees enough space even with small
* fonts.
*/
#ifndef MF_KERNING_SPACE_PIXELS
#define MF_KERNING_SPACE_PIXELS 3
#endif
/* Maximum adjustment done by the kerning algorithm, as percent of the
* glyph width.
*/
#ifndef MF_KERNING_LIMIT
#define MF_KERNING_LIMIT 20
#endif
/* Spacing of tabulator stops. The value is multiplied by the width of the
* 'm' character in the current font.
*/
#ifndef MF_TABSIZE
#define MF_TABSIZE 8
#endif
/*************************************************************************
* Configuration settings to strip down library to reduce resource usage *
*************************************************************************/
/* Enable or disable the kerning module.
* Disabling it saves some code size and run time, but causes the spacing
* between characters to be less consistent.
*/
#ifndef MF_USE_KERNING
#define MF_USE_KERNING 1
#endif
/* Enable or disable the advanced word wrap algorithm.
* If disabled, uses a simpler algorithm.
*/
#ifndef MF_USE_ADVANCED_WORDWRAP
#define MF_USE_ADVANCED_WORDWRAP 1
#endif
/* Enable of disable the justification algorithm.
* If disabled, mf_render_justified renders just left-aligned.
*/
#ifndef MF_USE_JUSTIFY
#define MF_USE_JUSTIFY 1
#endif
/* Enable or disable the center and right alignment code.
* If disabled, any alignment results in MF_ALIGN_LEFT.
*/
#ifndef MF_USE_ALIGN
#define MF_USE_ALIGN 1
#endif
/* Enable or disable the support for tab alignment.
* If disabled, tabs will be rendered as regular space character.
*/
#ifndef MF_USE_TABS
#define MF_USE_TABS 1
#endif
/* Number of vertical zones to use when computing kerning.
* Larger values give more accurate kerning, but are slower and use somewhat
* more memory. There is no point to increase this beyond the height of the
* font.
*/
#ifndef MF_KERNING_ZONES
#define MF_KERNING_ZONES 16
#endif
/* Add extern "C" when used from C++. */
#ifdef __cplusplus
#define MF_EXTERN extern "C"
#else
#define MF_EXTERN extern
#endif
#endif

View File

@ -0,0 +1,84 @@
#include "mf_encoding.h"
#if MF_ENCODING == MF_ENCODING_UTF8
mf_char mf_getchar(mf_str *str)
{
uint8_t c;
uint8_t tmp, seqlen;
uint16_t result;
c = **str;
if (!c)
return 0;
(*str)++;
if ((c & 0x80) == 0)
{
/* Just normal ASCII character. */
return c;
}
else if ((c & 0xC0) == 0x80)
{
/* Dangling piece of corrupted multibyte sequence.
* Did you cut the string in the wrong place?
*/
return c;
}
else if ((**str & 0xC0) == 0xC0)
{
/* Start of multibyte sequence without any following bytes.
* Silly. Maybe you are using the wrong encoding.
*/
return c;
}
else
{
/* Beginning of a multi-byte sequence.
* Find out how many characters and combine them.
*/
seqlen = 2;
tmp = 0x20;
result = 0;
while ((c & tmp) && (seqlen < 5))
{
seqlen++;
tmp >>= 1;
result = (result << 6) | (**str & 0x3F);
(*str)++;
}
result = (result << 6) | (**str & 0x3F);
(*str)++;
result |= (c & (tmp - 1)) << ((seqlen - 1) * 6);
return result;
}
}
void mf_rewind(mf_str *str)
{
(*str)--;
while ((**str & 0x80) != 0x00 && (**str & 0xC0) != 0xC0)
(*str)--;
}
#else
mf_char mf_getchar(mf_str *str)
{
if (!(**str))
return 0;
else
return *(*str)++;
}
void mf_rewind(mf_str *str)
{
(*str)--;
}
#endif

View File

@ -0,0 +1,45 @@
/* Simple UTF-8 decoder. Also implements the much simpler ASCII and UTF16
* input encodings.
*/
#ifndef _MF_ENCODING_H_
#define _MF_ENCODING_H_
#include "mf_config.h"
#include <stdint.h>
/* Type used to represent characters internally. */
#if MF_ENCODING == MF_ENCODING_ASCII
typedef char mf_char;
#else
typedef uint16_t mf_char;
#endif
/* Type used to represent input strings. */
#if MF_ENCODING == MF_ENCODING_ASCII
typedef const char * mf_str;
#elif MF_ENCODING == MF_ENCODING_UTF8
typedef const char * mf_str;
#elif MF_ENCODING == MF_ENCODING_UTF16
typedef const uint16_t * mf_str;
#elif MF_ENCODING == MF_ENCODING_WCHAR
#include <stddef.h>
typedef const wchar_t * mf_str;
#endif
/* Returns the next character in the string and advances the pointer.
* When the string ends, returns 0 and leaves the pointer at the 0 byte.
*
* str: Pointer to variable holding current location in string.
* Initialize it to the start of the string.
*
* Returns: The next character, as unicode codepoint.
*/
MF_EXTERN mf_char mf_getchar(mf_str *str);
/* Moves back the pointer to the beginning of the previous character.
* Be careful not to go beyond the start of the string.
*/
MF_EXTERN void mf_rewind(mf_str *str);
#endif

View File

@ -0,0 +1,122 @@
#include "mf_font.h"
#include <stdbool.h>
/* This will be made into a list of included fonts using macro magic. */
#define MF_INCLUDED_FONTS 0
/* Included fonts begin here */
#include MF_FONT_FILE_NAME
/* Include fonts end here */
uint8_t mf_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state)
{
uint8_t width;
width = font->render_character(font, x0, y0, character, callback, state);
if (!width)
{
width = font->render_character(font, x0, y0, font->fallback_character,
callback, state);
}
return width;
}
uint8_t mf_character_width(const struct mf_font_s *font,
mf_char character)
{
uint8_t width;
width = font->character_width(font, character);
if (!width)
{
width = font->character_width(font, font->fallback_character);
}
return width;
}
struct whitespace_state
{
uint8_t min_x, min_y;
uint8_t max_x, max_y;
};
static void whitespace_callback(int16_t x, int16_t y, uint8_t count,
uint8_t alpha, void *state)
{
struct whitespace_state *s = state;
if (alpha > 7)
{
if (s->min_x > x) s->min_x = x;
if (s->min_y > y) s->min_y = y;
x += count - 1;
if (s->max_x < x) s->max_x = x;
if (s->max_y < y) s->max_y = y;
}
}
MF_EXTERN void mf_character_whitespace(const struct mf_font_s *font,
mf_char character,
uint8_t *left, uint8_t *top,
uint8_t *right, uint8_t *bottom)
{
struct whitespace_state state = {255, 255, 0, 0};
mf_render_character(font, 0, 0, character, whitespace_callback, &state);
if (state.min_x == 255 && state.min_y == 255)
{
/* Character is whitespace */
if (left) *left = font->width;
if (top) *top = font->height;
if (right) *right = 0;
if (bottom) *bottom = 0;
}
else
{
if (left) *left = state.min_x;
if (top) *top = state.min_y;
if (right) *right = font->width - state.max_x - 1;
if (bottom) *bottom = font->height - state.max_y - 1;
}
}
/* Avoids a dependency on libc */
static bool strequals(const char *a, const char *b)
{
while (*a)
{
if (*a++ != *b++)
return false;
}
return (!*b);
}
const struct mf_font_s *mf_find_font(const char *name)
{
const struct mf_font_list_s *f;
f = MF_INCLUDED_FONTS;
while (f)
{
if (strequals(f->font->full_name, name) ||
strequals(f->font->short_name, name))
{
return f->font;
}
f = f->next;
}
return 0;
}
const struct mf_font_list_s *mf_get_font_list()
{
return MF_INCLUDED_FONTS;
}

View File

@ -0,0 +1,137 @@
/* Generic font type that supports fonts with multiple kinds of compression.
* Provides an interface for decoding and rendering single characters.
*/
#ifndef _MF_FONT_H_
#define _MF_FONT_H_
#include "mf_encoding.h"
/* Callback function that writes pixels to screen / buffer / whatever.
*
* x: X coordinate of the first pixel to write.
* y: Y coordinate of the first pixel to write.
* count: Number of pixels to fill (horizontally).
* alpha: The "opaqueness" of the pixels, 0 for background, 255 for text.
* state: Free variable that was passed to render_character().
*/
typedef void (*mf_pixel_callback_t) (int16_t x, int16_t y, uint8_t count,
uint8_t alpha, void *state);
/* General information about a font. */
struct mf_font_s
{
/* Full name of the font, comes from the original font file. */
char *full_name;
/* Short name of the font, comes from file name. */
char *short_name;
/* Width and height of the character bounding box. */
uint8_t width;
uint8_t height;
/* Minimum and maximum tracking width of characters. */
uint8_t min_x_advance;
uint8_t max_x_advance;
/* Location of the text baseline relative to character. */
int8_t baseline_x;
uint8_t baseline_y;
/* Line height of the font (vertical advance). */
uint8_t line_height;
/* Flags identifying various aspects of the font. */
uint8_t flags;
/* Fallback character to use for missing glyphs. */
mf_char fallback_character;
/* Function to get character width. Should return 0 if character is
* not found. */
uint8_t (*character_width)(const struct mf_font_s *font, mf_char character);
/* Function to render a character. Returns the character width or 0 if
* character is not found. */
uint8_t (*render_character)(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state);
};
/* The flag definitions for the font.flags field. */
#define MF_FONT_FLAG_MONOSPACE 0x01
#define MF_FONT_FLAG_BW 0x02
/* Lookup structure for searching fonts by name. */
struct mf_font_list_s
{
const struct mf_font_list_s *next;
const struct mf_font_s *font;
};
/* Function to decode and render a single character.
*
* font: Pointer to the font definition.
* x0, y0: Upper left corner of the target area.
* character: The character code (unicode) to render.
* callback: Callback function to write out the pixels.
* state: Free variable for caller to use (can be NULL).
*
* Returns width of the character.
*/
MF_EXTERN uint8_t mf_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state);
/* Function to get the width of a single character.
* This is not necessarily the bounding box of the character
* data, but rather the tracking width.
*
* font: Pointer to the font definition.
* character: The character code (unicode) to check width of.
*
* Returns width of the character in pixels.
*/
MF_EXTERN uint8_t mf_character_width(const struct mf_font_s *font,
mf_char character);
/* Count the amount of white space at the borders of a character.
*
* E.g. if the font->width and font->height are 10x20, but the character
* is only a thin line at the very left edge, this function will return
* (0, 0, 9, 0). If the character is fully whitespace, the function will
* return (10, 20, 0, 0).
*
* font: Pointer to the font definition.
* character: The character code (unicode) to check white space of.
* left: Number of empty rows at left edge. Can be NULL.
* top: Number of empty rows at top edge. Can be NULL.
* right: Number of empty rows at right edge. Can be NULL.
* bottom: Number of empty rows at bottom edge. Can be NULL.
*/
MF_EXTERN void mf_character_whitespace(const struct mf_font_s *font,
mf_char character,
uint8_t *left, uint8_t *top,
uint8_t *right, uint8_t *bottom);
/* Find a font based on name. The name can be either short name or full name.
* Note: You can pass MF_INCLUDED_FONTS to search among all the included .h
* files.
*
* name: Font name to search for.
* fonts: Pointer to the first font search entry.
*
* Returns a pointer to the font or NULL if not found.
*/
MF_EXTERN const struct mf_font_s *mf_find_font(const char *name);
/* Get the list of included fonts */
MF_EXTERN const struct mf_font_list_s *mf_get_font_list();
#endif

View File

@ -0,0 +1,332 @@
#include "mf_justify.h"
#include "mf_kerning.h"
#if MF_USE_TABS
/* Round the X coordinate up to the nearest tab stop. */
static int16_t mf_round_to_tab(const struct mf_font_s *font,
int16_t x0, int16_t x)
{
int16_t tabw, dx;
tabw = mf_character_width(font, 'm') * MF_TABSIZE;
/* Always atleast 1 space */
x += mf_character_width(font, ' ');
/* Round to next tab stop */
dx = x - x0 + font->baseline_x;
x += tabw - (dx % tabw);
return x;
}
/* Round the X coordinate down to the nearest tab stop. */
static int16_t mf_round_to_prev_tab(const struct mf_font_s *font,
int16_t x0, int16_t x)
{
int16_t tabw, dx;
tabw = mf_character_width(font, 'm') * MF_TABSIZE;
/* Always atleast 1 space */
x -= mf_character_width(font, ' ');
/* Round to previous tab stop */
dx = x0 - x + font->baseline_x;
x -= tabw - (dx % tabw);
return x;
}
#endif
int16_t mf_get_string_width(const struct mf_font_s *font, mf_str text,
uint16_t count, bool kern)
{
int16_t result = 0;
uint16_t c1 = 0, c2;
if (!count)
count = 0xFFFF;
while (count-- && *text)
{
c2 = mf_getchar(&text);
if (c2 == '\t')
{
#if MF_USE_TABS
result = mf_round_to_tab(font, 0, result);
c1 = ' ';
continue;
#else
c2 = ' ';
#endif
}
if (kern && c1 != 0)
result += mf_compute_kerning(font, c1, c2);
result += mf_character_width(font, c2);
c1 = c2;
}
return result;
}
/* Return the length of the string without trailing spaces. */
static uint16_t strip_spaces(mf_str text, uint16_t count, mf_char *last_char)
{
uint16_t i = 0, result = 0;
mf_char tmp = 0;
if (!count)
count = 0xFFFF;
while (count-- && *text)
{
i++;
tmp = mf_getchar(&text);
if (tmp != ' ' && tmp != 0xA0 && tmp != '\n' &&
tmp != '\r' && tmp != '\t')
{
result = i;
}
}
if (last_char)
{
if (!*text)
*last_char = 0;
else
*last_char = tmp;
}
return result;
}
/* Render left-aligned string, left edge at x0. */
static void render_left(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
int16_t x;
mf_char c1 = 0, c2;
x = x0 - font->baseline_x;
while (count--)
{
c2 = mf_getchar(&text);
if (c2 == '\t')
{
#if MF_USE_TABS
x = mf_round_to_tab(font, x0, x);
c1 = ' ';
continue;
#else
c2 = ' ';
#endif
}
if (c1 != 0)
x += mf_compute_kerning(font, c1, c2);
x += callback(x, y0, c2, state);
c1 = c2;
}
}
#if !MF_USE_ALIGN
void mf_render_aligned(const struct mf_font_s *font,
int16_t x0, int16_t y0,
enum mf_align_t align,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
int16_t string_width;
count = strip_spaces(text, count, 0);
render_left(font, x0, y0, text, count, callback, state);
}
#else
/* Render right-aligned string, right edge at x0. */
static void render_right(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
int16_t x;
uint16_t i;
mf_char c1, c2 = 0;
mf_str tmp;
/* Go to the end of the line. */
for (i = 0; i < count; i++)
mf_getchar(&text);
x = x0 - font->baseline_x;
for (i = 0; i < count; i++)
{
mf_rewind(&text);
tmp = text;
c1 = mf_getchar(&tmp);
/* Perform tab alignment */
if (c1 == '\t')
{
#if MF_USE_TABS
x = mf_round_to_prev_tab(font, x0, x);
c2 = ' ';
continue;
#else
c1 = ' ';
#endif
}
/* Apply the nominal character width */
x -= mf_character_width(font, c1);
/* Apply kerning */
if (c2 != 0)
x -= mf_compute_kerning(font, c1, c2);
callback(x, y0, c1, state);
c2 = c1;
}
}
void mf_render_aligned(const struct mf_font_s *font,
int16_t x0, int16_t y0,
enum mf_align_t align,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
int16_t string_width;
count = strip_spaces(text, count, 0);
if (align == MF_ALIGN_LEFT)
{
render_left(font, x0, y0, text, count, callback, state);
}
if (align == MF_ALIGN_CENTER)
{
string_width = mf_get_string_width(font, text, count, false);
x0 -= string_width / 2;
render_left(font, x0, y0, text, count, callback, state);
}
else if (align == MF_ALIGN_RIGHT)
{
render_right(font, x0, y0, text, count, callback, state);
}
}
#endif
#if !MF_USE_JUSTIFY
void mf_render_justified(const struct mf_font_s *font,
int16_t x0, int16_t y0, int16_t width,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
mf_render_aligned(font, x0, y0, MF_ALIGN_LEFT, text, count, callback, state);
}
#else
/* Returns true if the character is a justification point, i.e. expands
* when the text is being justified. */
static bool is_justify_space(uint16_t c)
{
return c == ' ' || c == 0xA0;
}
/* Count the number of space characters in string */
static uint16_t count_spaces(mf_str text, uint16_t count)
{
uint16_t spaces = 0;
while (count-- && *text)
{
if (is_justify_space(mf_getchar(&text)))
spaces++;
}
return spaces;
}
void mf_render_justified(const struct mf_font_s *font,
int16_t x0, int16_t y0, int16_t width,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state)
{
int16_t string_width, adjustment;
uint16_t num_spaces;
mf_char last_char;
count = strip_spaces(text, count, &last_char);
if (last_char == '\n' || last_char == 0)
{
/* Line ends in linefeed, do not justify. */
render_left(font, x0, y0, text, count, callback, state);
return;
}
string_width = mf_get_string_width(font, text, count, false);
adjustment = width - string_width;
num_spaces = count_spaces(text, count);
{
int16_t x, tmp;
uint16_t c1 = 0, c2;
x = x0 - font->baseline_x;
while (count--)
{
c2 = mf_getchar(&text);
if (c2 == '\t')
{
#if MF_USE_TABS
tmp = x;
x = mf_round_to_tab(font, x0, x);
adjustment -= x - tmp - mf_character_width(font, '\t');
c1 = c2;
continue;
#else
c2 = ' ';
#endif
}
if (is_justify_space(c2))
{
tmp = (adjustment + num_spaces / 2) / num_spaces;
adjustment -= tmp;
num_spaces--;
x += tmp;
}
if (c1 != 0)
{
tmp = mf_compute_kerning(font, c1, c2);
x += tmp;
adjustment -= tmp;
}
x += callback(x, y0, c2, state);
c1 = c2;
}
}
}
#endif

View File

@ -0,0 +1,74 @@
/* Text alignment and justification algorithm. Supports left, right, center
* alignment and justify. Supports tab stops and kerning.
*/
#ifndef _MF_JUSTIFY_H_
#define _MF_JUSTIFY_H_
#include "mf_rlefont.h"
#include <stdbool.h>
enum mf_align_t
{
MF_ALIGN_LEFT = 0,
MF_ALIGN_CENTER,
MF_ALIGN_RIGHT
};
/* Callback for rendering a single character.
* x0: Left edge of the target position of character.
* y0: Upper edge of the target position of character.
* character: Character to render.
* state: Free state variable for use by the callback.
* Returns the width of the character.
*/
typedef uint8_t (*mf_character_callback_t) (int16_t x0, int16_t y0,
mf_char character, void *state);
/* Get width of a string in pixels.
*
* font: Pointer to the font definition.
* text: Pointer to start of the text to measure.
* count: Number of characters on the line or 0 to read until end of string.
* kern: True to consider kerning (slower).
*/
MF_EXTERN int16_t mf_get_string_width(const struct mf_font_s *font,
mf_str text, uint16_t count, bool kern);
/* Render a single line of aligned text.
*
* font: Pointer to the font definition.
* x0: Depending on aligned, either left, center or right edge of target.
* y0: Upper edge of the target area.
* align: Type of alignment.
* text: Pointer to start of the text to render.
* count: Number of characters on the line or 0 to read until end of string.
* callback: Callback to call for each character.
* state: Free variable for use in the callback.
*/
MF_EXTERN void mf_render_aligned(const struct mf_font_s *font,
int16_t x0, int16_t y0,
enum mf_align_t align,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state);
/* Render a single line of justified text.
*
* font: Pointer to the font definition.
* x0: Left edge of the target area.
* y0: Upper edge of the target area.
* width: Width of the target area.
* text: Pointer to start of the text to render.
* count: Number of characters on the line or 0 to read until end of string.
* callback: Callback to call for each character.
* state: Free variable for use in the callback.
*/
MF_EXTERN void mf_render_justified(const struct mf_font_s *font,
int16_t x0, int16_t y0, int16_t width,
mf_str text, uint16_t count,
mf_character_callback_t callback,
void *state);
#endif

View File

@ -0,0 +1,118 @@
#include "mf_kerning.h"
#include <stdbool.h>
#if MF_USE_KERNING
/* Structure for keeping track of the edge of the glyph as it is rendered. */
struct kerning_state_s
{
uint8_t edgepos[MF_KERNING_ZONES];
uint8_t zoneheight;
};
/* Pixel callback for analyzing the left edge of a glyph. */
static void fit_leftedge(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
void *state)
{
struct kerning_state_s *s = state;
if (alpha > 7)
{
uint8_t zone = y / s->zoneheight;
if (x < s->edgepos[zone])
s->edgepos[zone] = x;
}
}
/* Pixel callback for analyzing the right edge of a glyph. */
static void fit_rightedge(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
void *state)
{
struct kerning_state_s *s = state;
if (alpha > 7)
{
uint8_t zone = y / s->zoneheight;
x += count - 1;
if (x > s->edgepos[zone])
s->edgepos[zone] = x;
}
}
/* Should kerning be done against this character? */
static bool do_kerning(mf_char c)
{
/* Just a speed optimization, spaces would be ignored anyway. */
if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
return false;
/* Do not kern against digits, in order to keep values in tables nicely
* aligned. Most fonts have constant width for digits. */
if (c >= '0' && c <= '9')
return false;
return true;
}
/*static int16_t min16(int16_t a, int16_t b) { return (a < b) ? a : b; }*/
static int16_t max16(int16_t a, int16_t b) { return (a > b) ? a : b; }
static int16_t avg16(int16_t a, int16_t b) { return (a + b) / 2; }
int8_t mf_compute_kerning(const struct mf_font_s *font,
mf_char c1, mf_char c2)
{
struct kerning_state_s leftedge, rightedge;
uint8_t w1, w2, i, min_space;
int16_t normal_space, adjust, max_adjust;
if (font->flags & MF_FONT_FLAG_MONOSPACE)
return 0; /* No kerning for monospace fonts */
if (!do_kerning(c1) || !do_kerning(c2))
return 0;
/* Compute the height of one kerning zone in pixels */
i = (font->height + MF_KERNING_ZONES - 1) / MF_KERNING_ZONES;
if (i < 1) i = 1;
/* Initialize structures */
leftedge.zoneheight = rightedge.zoneheight = i;
for (i = 0; i < MF_KERNING_ZONES; i++)
{
leftedge.edgepos[i] = 255;
rightedge.edgepos[i] = 0;
}
/* Analyze the edges of both glyphs. */
w1 = mf_render_character(font, 0, 0, c1, fit_rightedge, &rightedge);
w2 = mf_render_character(font, 0, 0, c2, fit_leftedge, &leftedge);
/* Find the minimum horizontal space between the glyphs. */
min_space = 255;
for (i = 0; i < MF_KERNING_ZONES; i++)
{
uint8_t space;
if (leftedge.edgepos[i] == 255 || rightedge.edgepos[i] == 0)
continue; /* Outside glyph area. */
space = w1 - rightedge.edgepos[i] + leftedge.edgepos[i];
if (space < min_space)
min_space = space;
}
if (min_space == 255)
return 0; /* One of the characters is space, or both are punctuation. */
/* Compute the adjustment of the glyph position. */
normal_space = avg16(w1, w2) * MF_KERNING_SPACE_PERCENT / 100;
normal_space += MF_KERNING_SPACE_PIXELS;
adjust = normal_space - min_space;
max_adjust = -max16(w1, w2) * MF_KERNING_LIMIT / 100;
if (adjust > 0) adjust = 0;
if (adjust < max_adjust) adjust = max_adjust;
return adjust;
}
#endif

View File

@ -0,0 +1,27 @@
/* Automatic kerning for font rendering. This solves the issue where some
* fonts (especially serif fonts) have too much space between specific
* character pairs, like WA or L'.
*/
#ifndef _MF_KERNING_H_
#define _MF_KERNING_H_
#include "mf_config.h"
#include "mf_rlefont.h"
/* Compute the kerning adjustment when c1 is followed by c2.
*
* font: Pointer to the font definition.
* c1: The previous character.
* c2: The next character to render.
*
* Returns the offset to add to the x position for c2.
*/
#if MF_USE_KERNING
MF_EXTERN int8_t mf_compute_kerning(const struct mf_font_s *font,
mf_char c1, mf_char c2);
#else
#define mf_compute_kerning(f,c1,c2) (0)
#endif
#endif

View File

@ -0,0 +1,286 @@
#include "mf_rlefont.h"
/* Number of reserved codes before the dictionary entries. */
#define DICT_START 24
/* Special reference to mean "fill with zeros to the end of the glyph" */
#define REF_FILLZEROS 16
/* RLE codes */
#define RLE_CODEMASK 0xC0
#define RLE_VALMASK 0x3F
#define RLE_ZEROS 0x00
#define RLE_64ZEROS 0x40
#define RLE_ONES 0x80
#define RLE_SHADE 0xC0
/* Dictionary "fill entries" for encoding bits directly. */
#define DICT_START7BIT 4
#define DICT_START6BIT 132
#define DICT_START5BIT 196
#define DICT_START4BIT 228
#define DICT_START3BIT 244
#define DICT_START2BIT 252
/* Find a pointer to the glyph matching a given character by searching
* through the character ranges. If the character is not found, return
* pointer to the default glyph.
*/
static const uint8_t *find_glyph(const struct mf_rlefont_s *font,
uint16_t character)
{
unsigned i, index;
const struct mf_rlefont_char_range_s *range;
for (i = 0; i < font->char_range_count; i++)
{
range = &font->char_ranges[i];
index = character - range->first_char;
if (character >= range->first_char && index < range->char_count)
{
uint16_t offset = pgm_read_word(range->glyph_offsets + index);
return &range->glyph_data[offset];
}
}
return 0;
}
/* Structure to keep track of coordinates of the next pixel to be written,
* and also the bounds of the character. */
struct renderstate_r
{
int16_t x_begin;
int16_t x_end;
int16_t x;
int16_t y;
int16_t y_end;
mf_pixel_callback_t callback;
void *state;
};
/* Call the callback to write one pixel to screen, and advance to next
* pixel position. */
static void write_pixels(struct renderstate_r *rstate, uint16_t count,
uint8_t alpha)
{
uint8_t rowlen;
/* Write row-by-row if the run spans multiple rows. */
while (rstate->x + count >= rstate->x_end)
{
rowlen = rstate->x_end - rstate->x;
rstate->callback(rstate->x, rstate->y, rowlen, alpha, rstate->state);
count -= rowlen;
rstate->x = rstate->x_begin;
rstate->y++;
}
/* Write the remaining part */
if (count)
{
rstate->callback(rstate->x, rstate->y, count, alpha, rstate->state);
rstate->x += count;
}
}
/* Skip the given number of pixels (0 alpha) */
static void skip_pixels(struct renderstate_r *rstate, uint16_t count)
{
rstate->x += count;
while (rstate->x >= rstate->x_end)
{
rstate->x -= rstate->x_end - rstate->x_begin;
rstate->y++;
}
}
/* Decode and write out a RLE-encoded dictionary entry. */
static void write_rle_dictentry(const struct mf_rlefont_s *font,
struct renderstate_r *rstate,
uint8_t index)
{
uint16_t offset = pgm_read_word(font->dictionary_offsets + index);
uint16_t length = pgm_read_word(font->dictionary_offsets + index + 1) - offset;
uint16_t i;
for (i = 0; i < length; i++)
{
uint8_t code = pgm_read_byte(font->dictionary_data + offset + i);
if ((code & RLE_CODEMASK) == RLE_ZEROS)
{
skip_pixels(rstate, code & RLE_VALMASK);
}
else if ((code & RLE_CODEMASK) == RLE_64ZEROS)
{
skip_pixels(rstate, ((code & RLE_VALMASK) + 1) * 64);
}
else if ((code & RLE_CODEMASK) == RLE_ONES)
{
write_pixels(rstate, (code & RLE_VALMASK) + 1, 255);
}
else if ((code & RLE_CODEMASK) == RLE_SHADE)
{
uint8_t count, alpha;
count = ((code & RLE_VALMASK) >> 4) + 1;
alpha = ((code & RLE_VALMASK) & 0xF) * 0x11;
write_pixels(rstate, count, alpha);
}
}
}
/* Get bit count for the "fill entries" */
static uint8_t fillentry_bitcount(uint8_t index)
{
if (index >= DICT_START2BIT)
return 2;
else if (index >= DICT_START3BIT)
return 3;
else if (index >= DICT_START4BIT)
return 4;
else if (index >= DICT_START5BIT)
return 5;
else if (index >= DICT_START6BIT)
return 6;
else
return 7;
}
/* Decode and write out a direct binary codeword */
static void write_bin_codeword(const struct mf_rlefont_s *font,
struct renderstate_r *rstate,
uint8_t code)
{
uint8_t bitcount = fillentry_bitcount(code);
uint8_t byte = code - DICT_START7BIT;
uint8_t runlen = 0;
while (bitcount--)
{
if (byte & 1)
{
runlen++;
}
else
{
if (runlen)
{
write_pixels(rstate, runlen, 255);
runlen = 0;
}
skip_pixels(rstate, 1);
}
byte >>= 1;
}
if (runlen)
write_pixels(rstate, runlen, 255);
}
/* Decode and write out a reference codeword */
static void write_ref_codeword(const struct mf_rlefont_s *font,
struct renderstate_r *rstate,
uint8_t code)
{
if (code == 0)
{
skip_pixels(rstate, 1);
}
else if (code <= 15)
{
write_pixels(rstate, 1, 0x11 * code);
}
else if (code == REF_FILLZEROS)
{
/* Fill with zeroes to end */
rstate->y = rstate->y_end;
}
else if (code < DICT_START)
{
/* Reserved */
}
else if (code < DICT_START + font->rle_entry_count)
{
write_rle_dictentry(font, rstate, code - DICT_START);
}
else
{
write_bin_codeword(font, rstate, code);
}
}
/* Decode and write out a reference encoded dictionary entry. */
static void write_ref_dictentry(const struct mf_rlefont_s *font,
struct renderstate_r *rstate,
uint8_t index)
{
uint16_t offset = pgm_read_word(font->dictionary_offsets + index);
uint16_t length = pgm_read_word(font->dictionary_offsets + index + 1) - offset;
uint16_t i;
for (i = 0; i < length; i++)
{
uint8_t code = pgm_read_byte(font->dictionary_data + offset + i);
write_ref_codeword(font, rstate, code);
}
}
/* Decode and write out an arbitrary glyph codeword */
static void write_glyph_codeword(const struct mf_rlefont_s *font,
struct renderstate_r *rstate,
uint8_t code)
{
if (code >= DICT_START + font->rle_entry_count &&
code < DICT_START + font->dict_entry_count)
{
write_ref_dictentry(font, rstate, code - DICT_START);
}
else
{
write_ref_codeword(font, rstate, code);
}
}
uint8_t mf_rlefont_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
uint16_t character,
mf_pixel_callback_t callback,
void *state)
{
const uint8_t *p;
uint8_t width;
struct renderstate_r rstate;
rstate.x_begin = x0;
rstate.x_end = x0 + font->width;
rstate.x = x0;
rstate.y = y0;
rstate.y_end = y0 + font->height;
rstate.callback = callback;
rstate.state = state;
p = find_glyph((struct mf_rlefont_s*)font, character);
if (!p)
return 0;
width = pgm_read_byte(p++);
while (rstate.y < rstate.y_end)
{
write_glyph_codeword((struct mf_rlefont_s*)font, &rstate, pgm_read_byte(p++));
}
return width;
}
uint8_t mf_rlefont_character_width(const struct mf_font_s *font,
uint16_t character)
{
const uint8_t *p;
p = find_glyph((struct mf_rlefont_s*)font, character);
if (!p)
return 0;
return pgm_read_byte(p);
}

View File

@ -0,0 +1,82 @@
/* A compressed font format based on run length encoding and dictionary
* compression.
*/
#ifndef _MF_RLEFONT_H_
#define _MF_RLEFONT_H_
#include "mf_font.h"
/* Versions of the RLE font format that are supported. */
#define MF_RLEFONT_VERSION_4_SUPPORTED 1
/* Structure for a range of characters. This implements a sparse storage of
* character indices, so that you can e.g. pick a 100 characters in the middle
* of the UTF16 range and just store them. */
struct mf_rlefont_char_range_s
{
/* The number of the first character in this range. */
uint16_t first_char;
/* The total count of characters in this range. */
uint16_t char_count;
/* Lookup table with the start indices into glyph_data. */
uint16_t *glyph_offsets;
uint32_t glyph_offsets_size;
uint32_t glyph_offsets_fp_offset;
/* The encoded glyph data for glyphs in this range. */
uint8_t *glyph_data;
uint32_t glyph_data_size;
uint32_t glyph_data_fp_offset;
};
/* Structure for a single encoded font. */
struct mf_rlefont_s
{
struct mf_font_s font;
/* Version of the font definition used. */
uint8_t version;
/* Big array of the data for all the dictionary entries. */
uint8_t *dictionary_data;
uint32_t dictionary_data_size;
uint32_t dictionary_data_fp_offset;
/* Lookup table with the start indices into dictionary_data.
* Contains N+1 entries, so that the length of the entry can
* be determined by subtracting from the next offset. */
uint16_t *dictionary_offsets;
uint32_t dictionary_offsets_size;
uint32_t dictionary_offsets_fp_offset;
/* Number of dictionary entries using the RLE encoding.
* Entries starting at this index use the dictionary encoding. */
uint8_t rle_entry_count;
/* Total number of dictionary entries.
* Entries after this are nonexistent. */
uint8_t dict_entry_count;
/* Number of discontinuous character ranges */
uint8_t char_range_count;
/* Array of the character ranges */
struct mf_rlefont_char_range_s *char_ranges;
};
#ifdef MF_RLEFONT_INTERNALS
/* Internal functions, don't use these directly. */
MF_EXTERN uint8_t mf_rlefont_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state);
MF_EXTERN uint8_t mf_rlefont_character_width(const struct mf_font_s *font,
mf_char character);
#endif
#endif

View File

@ -0,0 +1,83 @@
#include "mf_scaledfont.h"
struct scaled_renderstate
{
mf_pixel_callback_t orig_callback;
void *orig_state;
uint8_t x_scale;
uint8_t y_scale;
int16_t x0;
int16_t y0;
};
static void scaled_pixel_callback(int16_t x, int16_t y, uint8_t count,
uint8_t alpha, void *state)
{
struct scaled_renderstate *rstate = state;
uint8_t dy;
count *= rstate->x_scale;
x = rstate->x0 + x * rstate->x_scale;
y = rstate->y0 + y * rstate->y_scale;
for (dy = 0; dy < rstate->y_scale; dy++)
{
rstate->orig_callback(x, y + dy, count, alpha, rstate->orig_state);
}
}
static uint8_t scaled_character_width(const struct mf_font_s *font,
mf_char character)
{
struct mf_scaledfont_s *sfont = (struct mf_scaledfont_s*)font;
uint8_t basewidth;
basewidth = sfont->basefont->character_width(sfont->basefont, character);
return sfont->x_scale * basewidth;
}
static uint8_t scaled_render_character(const struct mf_font_s *font,
int16_t x0, int16_t y0,
mf_char character,
mf_pixel_callback_t callback,
void *state)
{
struct mf_scaledfont_s *sfont = (struct mf_scaledfont_s*)font;
struct scaled_renderstate rstate;
uint8_t basewidth;
rstate.orig_callback = callback;
rstate.orig_state = state;
rstate.x_scale = sfont->x_scale;
rstate.y_scale = sfont->y_scale;
rstate.x0 = x0;
rstate.y0 = y0;
basewidth = sfont->basefont->render_character(sfont->basefont, 0, 0,
character, scaled_pixel_callback, &rstate);
return sfont->x_scale * basewidth;
}
void mf_scale_font(struct mf_scaledfont_s *newfont,
const struct mf_font_s *basefont,
uint8_t x_scale, uint8_t y_scale)
{
newfont->font = *basefont;
newfont->basefont = basefont;
newfont->font.width *= x_scale;
newfont->font.height *= y_scale;
newfont->font.baseline_x *= x_scale;
newfont->font.baseline_y *= y_scale;
newfont->font.min_x_advance *= x_scale;
newfont->font.max_x_advance *= x_scale;
newfont->font.line_height *= y_scale;
newfont->font.character_width = &scaled_character_width;
newfont->font.render_character = &scaled_render_character;
newfont->x_scale = x_scale;
newfont->y_scale = y_scale;
}

View File

@ -0,0 +1,23 @@
/* Generate scaled (nearest-neighbor) fonts. This can be used for displaying
* larger text without spending the memory required for including larger fonts.
*/
#ifndef _MF_SCALEDFONT_H_
#define _MF_SCALEDFONT_H_
#include "mf_font.h"
struct mf_scaledfont_s
{
struct mf_font_s font;
const struct mf_font_s *basefont;
uint8_t x_scale;
uint8_t y_scale;
};
MF_EXTERN void mf_scale_font(struct mf_scaledfont_s *newfont,
const struct mf_font_s *basefont,
uint8_t x_scale, uint8_t y_scale);
#endif

View File

@ -0,0 +1,357 @@
#include "mf_wordwrap.h"
/* Returns true if the line can be broken at this character. */
static bool is_wrap_space(uint16_t c)
{
return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '-';
}
#if MF_USE_ADVANCED_WORDWRAP
/* Represents a single word and the whitespace after it. */
struct wordlen_s
{
int16_t word; /* Length of the word in pixels. */
int16_t space; /* Length of the whitespace in pixels. */
uint16_t chars; /* Number of characters in word + space, combined. */
};
/* Take the next word from the string and compute its width.
* Returns true if the word ends in a linebreak. */
static bool get_wordlen(const struct mf_font_s *font, mf_str *text,
struct wordlen_s *result)
{
mf_char c;
mf_str prev = *text;
result->word = 0;
result->space = 0;
result->chars = 0;
c = mf_getchar(text);
while (c && !is_wrap_space(c))
{
result->chars++;
result->word += mf_character_width(font, c);
prev = *text;
c = mf_getchar(text);
}
while (c && is_wrap_space(c))
{
result->chars++;
if (c == ' ' || c == '-')
result->space += mf_character_width(font, c);
else if (c == '\t')
result->space += mf_character_width(font, 'm') * MF_TABSIZE;
else if (c == '\n') {
/* Special case for newlines, skip the character then break. */
prev = *text;
break;
}
prev = *text;
c = mf_getchar(text);
}
/* The last loop reads the first character of next word, put it back. */
if (c)
*text = prev;
return (c == '\0' || c == '\n');
}
/* Represents the rendered length for a single line. */
struct linelen_s
{
mf_str start; /* Start of the text for line. */
uint16_t chars; /* Total number of characters on the line. */
int16_t width; /* Total length of all words + whitespace on the line in pixels. */
bool linebreak; /* True if line ends in a linebreak */
struct wordlen_s last_word; /* Last word on the line. */
struct wordlen_s last_word_2; /* Second to last word on the line. */
};
/* Append word onto the line if it fits. If it would overflow, don't add and
* return false. */
static bool append_word(const struct mf_font_s *font, int16_t width,
struct linelen_s *current, mf_str *text)
{
mf_str tmp = *text;
struct wordlen_s wordlen;
bool linebreak;
linebreak = get_wordlen(font, &tmp, &wordlen);
if (current->width + wordlen.word <= width)
{
*text = tmp;
current->last_word_2 = current->last_word;
current->last_word = wordlen;
current->linebreak = linebreak;
current->chars += wordlen.chars;
current->width += wordlen.word + wordlen.space;
return true;
}
else
{
return false;
}
}
/* Append a character to the line if it fits. */
static bool append_char(const struct mf_font_s *font, int16_t width,
struct linelen_s *current, mf_str *text)
{
mf_str tmp = *text;
mf_char c;
uint16_t w;
c = mf_getchar(&tmp);
w = mf_character_width(font, c);
if (current->width + w <= width)
{
*text = tmp;
current->chars++;
current->width += w;
return true;
}
else
{
return false;
}
}
/*static int16_t abs16(int16_t x) { return (x > 0) ? x : -x; }*/
static int32_t sq16(int16_t x) { return (int32_t)x * x; }
/* Try to balance the lines by potentially moving one word from the previous
* line to the the current one. */
static void tune_lines(struct linelen_s *current, struct linelen_s *previous,
int16_t max_width)
{
int16_t curw1, prevw1;
int16_t curw2, prevw2;
int32_t delta1, delta2;
/* If the lines are rendered as is */
curw1 = current->width - current->last_word.space;
prevw1 = previous->width - previous->last_word.space;
delta1 = sq16(max_width - prevw1) + sq16(max_width - curw1);
/* If the last word is moved */
curw2 = current->width + previous->last_word.word;
prevw2 = previous->width - previous->last_word.word
- previous->last_word.space
- previous->last_word_2.space;
delta2 = sq16(max_width - prevw2) + sq16(max_width - curw2);
if (delta1 > delta2 && curw2 <= max_width)
{
/* Do the change. */
uint16_t chars;
chars = previous->last_word.chars;
previous->chars -= chars;
current->chars += chars;
previous->width -= previous->last_word.word + previous->last_word.space;
current->width += previous->last_word.word + previous->last_word.space;
previous->last_word = previous->last_word_2;
while (chars--) mf_rewind(&current->start);
}
}
void mf_wordwrap(const struct mf_font_s *font, int16_t width,
mf_str text, mf_line_callback_t callback, void *state)
{
struct linelen_s current = { 0 };
struct linelen_s previous = { 0 };
bool full;
current.start = text;
while (*text)
{
full = !append_word(font, width, &current, &text);
if (full || current.linebreak)
{
if (!current.chars)
{
/* We have a very long word. We must just cut it off at some
* point. */
while (append_char(font, width, &current, &text));
}
if (previous.chars)
{
/* Tune the length and dispatch the previous line. */
if (!previous.linebreak && !current.linebreak)
tune_lines(&current, &previous, width);
if (!callback(previous.start, previous.chars, state))
return;
}
previous = current;
current.start = text;
current.chars = 0;
current.width = 0;
current.linebreak = false;
current.last_word.word = 0;
current.last_word.space = 0;
current.last_word.chars = 0;
}
}
/* Dispatch the last lines. */
if (previous.chars)
{
if (!callback(previous.start, previous.chars, state))
return;
}
if (current.chars)
callback(current.start, current.chars, state);
}
void mf_text_draw_area(const struct mf_font_s *font, int16_t width,
mf_str text,
int *total_height_in_rows,
int *max_pixels_per_row)
{
struct linelen_s current = { 0 };
struct linelen_s previous = { 0 };
bool full;
current.start = text;
*total_height_in_rows = 0;
*max_pixels_per_row = 0;
while (*text)
{
full = !append_word(font, width, &current, &text);
if (full || current.linebreak)
{
if (!current.chars)
{
/* We have a very long word. We must just cut it off at some
* point. */
while (append_char(font, width, &current, &text));
}
if (previous.chars)
{
/* Tune the length and dispatch the previous line. */
if (!previous.linebreak && !current.linebreak)
tune_lines(&current, &previous, width);
*total_height_in_rows += 1;
}
if ( *max_pixels_per_row < current.width )
*max_pixels_per_row = current.width;
previous = current;
current.start = text;
current.chars = 0;
current.width = 0;
current.linebreak = false;
current.last_word.word = 0;
current.last_word.space = 0;
current.last_word.chars = 0;
}
}
/* Dispatch the last lines. */
if (previous.chars)
{
if ( *max_pixels_per_row < previous.width )
*max_pixels_per_row = previous.width;
*total_height_in_rows += 1;
}
if (current.chars) {
if ( *max_pixels_per_row < current.width )
*max_pixels_per_row = current.width;
*total_height_in_rows += 1;
}
}
#else
void mf_wordwrap(const struct mf_font_s *font, int16_t width,
mf_str text, mf_line_callback_t callback, void *state)
{
mf_str orig = text;
mf_str linestart;
/* Current line width and character count */
int16_t lw_cur = 0, cc_cur = 0;
/* Previous wrap point */
int16_t cc_prev;
mf_str ls_prev;
linestart = text;
while (*text)
{
cc_prev = 0;
ls_prev = text;
while (*text)
{
mf_char c;
int16_t new_width;
mf_str tmp;
tmp = text;
c = mf_getchar(&text);
new_width = lw_cur + mf_character_width(font, c);
if (c == '\n')
{
cc_prev = cc_cur + 1;
ls_prev = text;
break;
}
if (new_width > width)
{
text = tmp;
break;
}
cc_cur++;
lw_cur = new_width;
if (is_wrap_space(c))
{
cc_prev = cc_cur;
ls_prev = text;
}
}
/* Handle unbreakable words */
if (cc_prev == 0)
{
cc_prev = cc_cur;
ls_prev = text;
}
if (!callback(linestart, cc_prev, state))
return;
linestart = ls_prev;
text = linestart;
lw_cur = 0;
cc_cur = 0;
}
}
#endif

View File

@ -0,0 +1,35 @@
/* Word wrapping algorithm with UTF-8 support. More than just a basic greedy
* word-wrapper: it attempts to balance consecutive lines as pairs.
*/
#ifndef _MF_WORDWRAP_H_
#define _MF_WORDWRAP_H_
#include "mf_rlefont.h"
#include <stdbool.h>
/* Callback function for handling each line.
*
* line: Pointer to the beginning of the string for this line.
* count: Number of characters on the line.
* state: Free variable that was passed to wordwrap().
*
* Returns: true to continue, false to stop after this line.
*/
typedef bool (*mf_line_callback_t) (mf_str line, uint16_t count,
void *state);
/* Word wrap a piece of text. Calls the callback function for each line.
*
* font: Font to use for metrics.
* width: Maximum line width in pixels.
* text: Pointer to the start of the text to process.
* state: Free variable for caller to use (can be NULL).
*/
MF_EXTERN void mf_wordwrap(const struct mf_font_s *font, int16_t width,
mf_str text, mf_line_callback_t callback, void *state);
void mf_text_draw_area(const struct mf_font_s *font, int16_t width,
mf_str text, int *total_height_in_rows,
int *max_pixels_per_row);
#endif

View File

@ -0,0 +1,716 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/** Include Files */
#include <mcufont.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "vg_lite.h"
#include "buf_reader.h"
#include "vg_lite_text.h"
#include "vft_draw.h"
#include "vft_debug.h"
/** Macros */
#define __COUNTOF(x) (sizeof(x)/sizeof(x[0]))
#define MAX_SYSTEM_FONTS (8)
#define RCD_ALLOC(x) _mem_allocate(x)
#define RCD_FREE(x) _mem_free(x)
#ifdef ENABLE_DEBUG_TRACE
static int g_id;
#define DBG_ID() (g_id)
#define DBG_INC_ID() (g_id++)
#define DBG_SET_ID(x) g_id = x
#else
#define DBG_ID() (0)
#define DBG_INC_ID() (0)
#define DBG_SET_ID(x)
#endif
#if APP_ENABLE_SDCARD
#define sprintf_s snprintf
#endif
/** Data structures */
typedef struct font_height_list {
const char font_height;
const char ref_font_height;
const char ref_font_scale;
} font_height_list_t;
typedef struct font_info_internal {
/* Variable shared between user and driver */
vg_lite_font_params_t font_params;
/* any additional variables internal to driver */
int valid;
/* Internal loaded raster font */
struct mf_font_s *_raster_font;
/* Internal loaded vector font */
font_face_desc_t *_vector_font;
}font_info_internal_t;
/** Internal or external API prototypes */
/** Globals */
static font_info_internal_t s_device_fonts[MAX_SYSTEM_FONTS];
/** Local function prototypes */
int read_rle_font_header(bufferred_reader_t *f, struct mf_font_s* font);
int read_rle_font_from_buffer(char *buf, int size, struct mf_font_s* font);
int load_raster_font(char *data, int data_len, struct mf_font_s** font);
int read_8b(bufferred_reader_t *f, uint8_t* pdata);
int read_16b(bufferred_reader_t *f, uint16_t* pword);
int read_32b(bufferred_reader_t *f, uint32_t* pword);
int read_16b_blob(bufferred_reader_t *f, uint16_t** ary, uint32_t* ary_len);
int read_8b_blob(bufferred_reader_t *f, uint8_t** ary, uint32_t* ary_len);
int free_rle_font_memory(struct mf_font_s** font);
vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font);
vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height);
/** Externs if any */
/** Code section */
vg_lite_font_t vg_lite_find_font(
char *font_name,
eFontWeight_t font_weight,
eFontStretch_t font_stretch,
eFontStyle_t font_style,
int font_height);
vg_lite_error_t vg_lite_register_font(vg_lite_font_t *font,
vg_lite_font_params_t *params)
{
int i;
int free_entry = VG_LITE_INVALID_FONT;
if (font != NULL)
*font = VG_LITE_INVALID_FONT;
/* Check if font is already registered */
for (i=0; i<MAX_SYSTEM_FONTS; i++) {
/* Is entry is valid ? */
if ( s_device_fonts[i].valid == 0 ) {
/* Grab free entry in list for new font */
if (free_entry == -1 ) {
free_entry = i;
}
} else if (s_device_fonts[i].valid == 1 ) {
/* Does font.name matches */
if ( strncmp(s_device_fonts[i].font_params.name,
params->name,
strlen(s_device_fonts[i].font_params.name)) == 0)
{
return VG_LITE_ALREADY_EXISTS;
}
} else {
printf("Corrupt font table\n");
return VG_LITE_INVALID_ARGUMENT;
}
}
/* Check if list is completely full or not */
if ( i == MAX_SYSTEM_FONTS && free_entry == VG_LITE_INVALID_FONT) {
/* Font List descriptor exhausted */
return VG_LITE_OUT_OF_RESOURCES;
} else {
/* Add new font in global table */
memcpy(&s_device_fonts[free_entry].font_params, params, sizeof(vg_lite_font_params_t));
s_device_fonts[free_entry].valid = 1;
/*
Loading font here leads to low run-time memory, we may need to characterize memory usage
e.g. pure path test don't require font, eventhrough application registers them
*/
#if 0
error = vg_lite_load_font_data(free_entry, params->font_height);
if ( error != 0 ) {
s_device_fonts[free_entry].valid = 0;
return error;
}
#endif
}
if (font != NULL)
*font = free_entry;
return VG_LITE_SUCCESS;
}
int vg_lite_is_font_valid(vg_lite_font_t font)
{
if (font < MAX_SYSTEM_FONTS) {
if (s_device_fonts[font].valid == 1)
return 0;
}
return VG_LITE_INVALID_ARGUMENT;
}
int vg_lite_is_vector_font(vg_lite_font_t font)
{
if (font < MAX_SYSTEM_FONTS) {
if (s_device_fonts[font].valid == 1)
return (s_device_fonts[font].font_params.font_type ==
eFontTypeVector);
else
return 0;
}
return VG_LITE_INVALID_ARGUMENT;;
}
vg_lite_error_t vg_lite_unregister_font(vg_lite_font_t font)
{
if (vg_lite_is_font_valid(font) != 0 ) {
/* Font not found */
return VG_LITE_INVALID_ARGUMENT;;
}
vg_lite_free_font_memory(font);
s_device_fonts[font].valid = 0;
return VG_LITE_SUCCESS;
}
char *vg_lite_get_font_name(vg_lite_font_t font)
{
if ( vg_lite_is_font_valid(font) != 0 ) {
return NULL;
}
return (char *)s_device_fonts[font].font_params.name;
}
vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font)
{
if ( vg_lite_is_font_valid(font) != 0 ) {
/* Font not found */
return VG_LITE_INVALID_ARGUMENT;
}
switch (s_device_fonts[font].font_params.font_type) {
case eFontTypeVector:
if ( s_device_fonts[font]._vector_font != NULL ) {
vft_unload(s_device_fonts[font]._vector_font);
s_device_fonts[font]._vector_font = NULL;
}
break;
case eFontTypeRaster:
if ( s_device_fonts[font]._raster_font != NULL ) {
free_rle_font_memory(&s_device_fonts[font]._raster_font);
s_device_fonts[font]._raster_font = NULL;
}
break;
}
return VG_LITE_SUCCESS;
}
font_face_desc_t *_vg_lite_get_vector_font(vg_lite_font_t font)
{
if ( vg_lite_is_font_valid(font) != 0 ) {
return NULL;
}
return s_device_fonts[font]._vector_font;
}
struct mf_font_s *_vg_lite_get_raster_font(vg_lite_font_t font)
{
if ( vg_lite_is_font_valid(font) != 0 ) {
return NULL;
}
return s_device_fonts[font]._raster_font;
}
vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height)
{
if ( vg_lite_is_font_valid(font) != 0 ) {
/* Font not found */
return VG_LITE_INVALID_ARGUMENT;
}
switch (s_device_fonts[font].font_params.font_type) {
case eFontTypeVector:
if (s_device_fonts[font]._vector_font == NULL ) {
//printf("Loading vector font : [%s]\n",
// s_device_fonts[font].font_params.name);
s_device_fonts[font]._vector_font =
vft_load_from_buffer(
s_device_fonts[font].font_params.data,
s_device_fonts[font].font_params.data_len);
if ( s_device_fonts[font]._vector_font == NULL ) {
return VG_LITE_INVALID_ARGUMENT;
}
}
return VG_LITE_SUCCESS;
case eFontTypeRaster:
if (s_device_fonts[font]._raster_font == NULL ) {
//printf("Loading raster font : [%s]\n",
// s_device_fonts[font].font_params.name);
/* Raster fonts height should match */
if ( font_height == s_device_fonts[font].font_params.font_height &&
load_raster_font(
s_device_fonts[font].font_params.data,
s_device_fonts[font].font_params.data_len,
&s_device_fonts[font]._raster_font) != 0)
{
return VG_LITE_INVALID_ARGUMENT;
}
}
return VG_LITE_SUCCESS;
}
return VG_LITE_INVALID_ARGUMENT;
}
vg_lite_font_t vg_lite_find_font(
char *font_name_list,
eFontWeight_t font_weight,
eFontStretch_t font_stretch,
eFontStyle_t font_style,
int font_height)
{
int i;
char tmp_data;
int font_found = 0;
int end_pos = 0; /* End position of font name */
char *font_name;
/*
printf("Font params: [%s],%d, %d, %d, %d\n",
font_name_list,
font_weight,
font_stretch,
font_style,
font_height);
*/
/* While probing font, if required font is found, then
only keep that name in supplied font list */
/* Split and extract font name one-by-one */
font_name = font_name_list;
while (font_found == 0 &&
font_name[end_pos] != '\0')
{
tmp_data = '\0';
/* Scan for seperator */
while (font_name[end_pos] != '\0') {
if (font_name[end_pos] == ',' || font_name[end_pos] == ' ' ||
font_name[end_pos] == '\t')
{
tmp_data = font_name[end_pos];
font_name[end_pos] = '\0';
break;
}
end_pos++;
}
/* Search for exact font-name match */
for (i=0; i<__COUNTOF(s_device_fonts); i++) {
if (s_device_fonts[i].valid == 0)
continue;
/* For vector font only compare name */
if (s_device_fonts[i].font_params.font_type == eFontTypeVector ) {
if ( strlen(font_name) > 0 &&
strcmp(font_name,
s_device_fonts[i].font_params.name) == 0)
{
font_name[end_pos] = tmp_data; /* Restor delimeter */
return i;
}
} else {
/* For raster font compare all properties */
if (s_device_fonts[i].font_params.font_weight == font_weight &&
s_device_fonts[i].font_params.font_stretch == font_stretch &&
s_device_fonts[i].font_params.font_style == font_style )
{
if ( strlen(font_name) > 0 &&
strcmp(font_name,
s_device_fonts[i].font_params.name) == 0)
{
font_name[end_pos] = tmp_data; /* Restor delimeter */
if (s_device_fonts[i].font_params.font_height == font_height)
{
return i;
}
/* Update font_name_list to improve future searches */
strncpy(font_name_list, font_name, strlen(font_name)+1);
}
}
}
}
/* Continue searching for other font entries */
font_name[end_pos] = tmp_data;
font_name += (end_pos + 1);
end_pos = 0;
}
printf("WARNING: [%s] Font not found\r\n",font_name_list);
return VG_LITE_INVALID_FONT;
}
void vg_lite_text_init(void)
{
static int font_table_ready = 0;
if (font_table_ready)
return;
/* Initialize font table */
memset(s_device_fonts, 0, MAX_SYSTEM_FONTS * sizeof(font_info_internal_t));
font_table_ready = 1;
}
/* Read-Write 8-bit unsigned int data */
int read_8b(bufferred_reader_t * f, uint8_t* pdata)
{
bufferred_fread(pdata, 1, 1, f);
TRACE_DBG(("%d) 8b: fp=%08x %d %d\r\n", DBG_INC_ID(),
bufferred_ftell(f) - 1, 1, *pdata));
return 1;
}
/* Read-Write 16-bit unsigned int data */
int read_16b(bufferred_reader_t * f, uint16_t* pword)
{
uint8_t buf[4];
uint16_t word;
bufferred_fread(buf, 2, 1, f);
word = 0; word += buf[1];
word <<= 8; word += buf[0];
TRACE_DBG(("%d) 16b: fp=%08x %d %d\r\n", DBG_INC_ID(),
bufferred_ftell(f)-2, 2, word));
*pword = word;
return 2;
}
/* Read-write 32-bit unsigned int data */
int read_32b(bufferred_reader_t * f, uint32_t* pword)
{
uint8_t buf[4];
uint32_t word;
bufferred_fread(buf, 4, 1, f);
word = 0; word += buf[3];
word <<= 8; word += buf[2];
word <<= 8; word += buf[1];
word <<= 8; word += buf[0];
*pword = word;
TRACE_DBG(("%d) 32b: fp=%08x %d %d\r\n", DBG_INC_ID(),
bufferred_ftell(f) - 4, 4,
word));
return 4;
}
int read_16b_blob(bufferred_reader_t * f, uint16_t** ary, uint32_t* ary_len)
{
uint16_t blob_len = 0;
*ary_len = 0;
bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
*ary = (uint16_t *)RCD_ALLOC(blob_len * sizeof(uint16_t)); /* Malloc must be aligned on 2 byte boundary */
if (*ary == NULL) {
TRACE_ERR(("ERROR: malloc failed\n"));;
return VG_LITE_OUT_OF_MEMORY;
}
if ((((unsigned long)*ary) & 0x1) != 0) {
TRACE_ERR(("ERROR: malloc pointer not 2 byte aligned\n"));;
return VG_LITE_NOT_ALIGNED;
}
TRACE_DBG(("%d ) 16b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
(int)blob_len));
bufferred_fread(*ary, 2, blob_len, f);
*ary_len = blob_len * 2;
return blob_len + 2; /* Actual bytes read from file */
}
int read_8b_blob(bufferred_reader_t * f, uint8_t** ary, uint32_t *ary_len)
{
uint16_t blob_len = 0;
uint8_t* p_tmp = (uint8_t *)NULL;
bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
//TRACE_DBG(("%d) 8b_blob: %d\r\n", DBG_INC_ID(), blob_len));
p_tmp = (uint8_t *)RCD_ALLOC(blob_len+1);
if (p_tmp == NULL) {
TRACE_ERR(("ERROR: malloc failed\n"));;
return VG_LITE_OUT_OF_MEMORY;
}
TRACE_DBG(("%d ) 8b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
(int)blob_len));
bufferred_fread(p_tmp, 1, blob_len, f);
p_tmp[blob_len] = 0;
*ary = p_tmp;
return blob_len + 2; /* Actual bytes read from file */
}
#define EXIT_IF_NEGATIVE(param) if ((ret = param) < 0) return ret;
int read_rle_font_header(bufferred_reader_t * f, struct mf_font_s* font)
{
int raw_header_offset = 0;
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
uint32_t size = 0;
int ret = 0;
TRACE_DBG(("** %s\r\n", __FUNCTION__));
DBG_SET_ID(0);
EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->full_name, &size));
raw_header_offset += ret; /* font.full_name */
EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->short_name, &size));
raw_header_offset += ret; /* font.short_name */
EXIT_IF_NEGATIVE(read_8b(f, &font->width));
raw_header_offset += 1; /* font.width */
EXIT_IF_NEGATIVE(read_8b(f, &font->height));
raw_header_offset += 1; /* font.height */
EXIT_IF_NEGATIVE(read_8b(f, &font->min_x_advance));
raw_header_offset += 1; /* font.min_x_advance */
EXIT_IF_NEGATIVE(read_8b(f, &font->max_x_advance));
raw_header_offset += 1; /* font.max_x_advance */
EXIT_IF_NEGATIVE(read_8b(f, (uint8_t *)&font->baseline_x));
raw_header_offset += 1; /* font.baseline_x */
EXIT_IF_NEGATIVE(read_8b(f, &font->baseline_y));
raw_header_offset += 1; /* font.baseline_y */
EXIT_IF_NEGATIVE(read_8b(f, &font->line_height));
raw_header_offset += 1; /* font.line_height */
EXIT_IF_NEGATIVE(read_8b(f, &font->flags));
raw_header_offset += 1; /* font.flags */
EXIT_IF_NEGATIVE(read_16b(f, &font->fallback_character));
raw_header_offset += 2; /* font.fallback_character */
EXIT_IF_NEGATIVE(read_8b(f, &(mfont->version)));
raw_header_offset += 1; /* mf_rlefont_s.version */
/* Other mf_rlefont_s variables */
uint16_t value = 0;
EXIT_IF_NEGATIVE(read_16b(f, &value)); //&mfont->dictionary_data_size));
mfont->dictionary_data_size = value;
raw_header_offset += 2; /* mf_rlefont_s.dictionary_data_size */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_data_fp_offset));
raw_header_offset += 4; /* mf_rlefont_s.dictionary_data_fp_offset */
value = 0;
EXIT_IF_NEGATIVE(read_16b(f, &value)); //mfont->dictionary_offsets_size));
mfont->dictionary_offsets_size = value;
raw_header_offset += 2; /* mf_rlefont_s.dictionary_data_size */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_offsets_fp_offset));
raw_header_offset += 4; /* mf_rlefont_s.dictionary_data_fp_offset */
EXIT_IF_NEGATIVE(read_8b(f, &mfont->rle_entry_count));
raw_header_offset += 1; /* mf_rlefont_s.rle_entry_count */
EXIT_IF_NEGATIVE(read_8b(f, &mfont->dict_entry_count));
raw_header_offset += 1; /* mf_rlefont_s.dict_entry_count */
EXIT_IF_NEGATIVE(read_8b(f, &mfont->char_range_count));
raw_header_offset += 1; /* mf_rlefont_s.char_range_count */
mfont->char_ranges = (struct mf_rlefont_char_range_s *)RCD_ALLOC(sizeof(struct mf_rlefont_char_range_s)* mfont->char_range_count);
memset(mfont->char_ranges, 0, sizeof(struct mf_rlefont_char_range_s) * mfont->char_range_count);
/* Skip size of ranges */
for (int r = 0; r < mfont->char_range_count; r++) {
EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].first_char));
raw_header_offset += 2; /* mf_rlefont_s.char_ranges[r].first_char */
EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].char_count));
raw_header_offset += 2; /* mf_rlefont_s.char_ranges[r].char_count */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_fp_offset));
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_size));
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_fp_offset));
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_size));
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
}
return raw_header_offset;
}
/* Writes a BMP file. The data is assumed to be 8-bit grayscale. */
int read_rle_font_from_buffer(char *buff, int size, struct mf_font_s* font)
{
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
bufferred_reader_t f_obj;
bufferred_reader_t * f = &f_obj;
int raw_header_offset = 0;
int fp_offset;
int ret;
DBG_SET_ID(0);
/* No need to dynamically allocate small descriptor */
if ( bufferred_fopen(f, buff, size) < 0 ) {
/* Font file open failed */
return VG_LITE_INVALID_ARGUMENT;
}
raw_header_offset = read_rle_font_header(f, font);
if (mfont->dictionary_data_fp_offset != raw_header_offset) {
TRACE_ERR(("ERROR: dictonary offset is different"));
}
TRACE_DBG(("** %s\r\n", __FUNCTION__));
DBG_SET_ID(0);
/* Skip header portion */
bufferred_fseek(f, raw_header_offset, SEEK_SET);
/* Write dictionary entries */
fp_offset = raw_header_offset;
TRACE_DBG(("dictionary_data_fp_offset=%08x %08x\r\n",
mfont->dictionary_data_fp_offset, bufferred_ftell(f)));
//mfont->dictionary_data_fp_offset = fp_offset;
EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->dictionary_data,
&mfont->dictionary_data_size));
fp_offset += mfont->dictionary_data_size + 2;
//mfont->dictionary_offsets_fp_offset = fp_offset;
TRACE_DBG(("dictionary_offsets_fp_offset=%08x %08x\r\n",
mfont->dictionary_offsets_fp_offset, bufferred_ftell(f)));
EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->dictionary_offsets,
&mfont->dictionary_offsets_size));
fp_offset += mfont->dictionary_offsets_size + 2;
/* Write range entries */
for (int r = 0; r < mfont->char_range_count; r++) {
//mfont->char_ranges[r].glyph_offsets_fp_offset = fp_offset;
TRACE_DBG(("mfont->char_ranges[%d].glyph_offsets=%08x %08x\r\n", r,
mfont->char_ranges[r].glyph_offsets_fp_offset, bufferred_ftell(f)));
EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->char_ranges[r].glyph_offsets,
&mfont->char_ranges[r].glyph_offsets_size));
fp_offset += mfont->char_ranges[r].glyph_offsets_size + 2;
//mfont->char_ranges[r].glyph_data_fp_offset = fp_offset;
TRACE_DBG(("mfont->char_ranges[%d].glyph_data_fp_offset=%08x %08x\r\n",
r,
mfont->char_ranges[r].glyph_data_fp_offset, bufferred_ftell(f)));
EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->char_ranges[r].glyph_data,\
&mfont->char_ranges[r].glyph_data_size));
fp_offset += mfont->char_ranges[r].glyph_data_size + 2;
}
bufferred_fclose(f);
return 0;
}
int load_raster_font(char *data, int data_len, struct mf_font_s** font)
{
int ret;
/* Allocate font memory */
*font = (struct mf_font_s*)RCD_ALLOC(sizeof(struct mf_rlefont_s));
if (*font == NULL) {
return VG_LITE_OUT_OF_MEMORY;
}
memset(*font, 0, sizeof(struct mf_rlefont_s));
/* Load font from file */
ret = read_rle_font_from_buffer(data,
data_len, *font);
if (ret < 0) {
return ret;
}
/* Update generic char width pointers of mculib */
uint8_t mf_rlefont_character_width(const struct mf_font_s* font,
uint16_t character);
uint8_t mf_rlefont_render_character(const struct mf_font_s* font,
int16_t x0, int16_t y0,
uint16_t character,
mf_pixel_callback_t callback,
void* state);
(*font)->character_width = &mf_rlefont_character_width;
(*font)->render_character = &mf_rlefont_render_character;
return 0;
}
int free_rle_font_memory(struct mf_font_s** font)
{
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)(*font);
RCD_FREE(mfont->font.full_name);
RCD_FREE(mfont->font.short_name);
RCD_FREE(mfont->dictionary_data);
RCD_FREE(mfont->dictionary_offsets);
for (int r = 0; r < mfont->char_range_count; r++) {
RCD_FREE(mfont->char_ranges[r].glyph_offsets);
RCD_FREE(mfont->char_ranges[r].glyph_data);
}
#ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
memset(mfont->char_ranges);
#endif
RCD_FREE(mfont->char_ranges);
#ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
memset(mfont);
#endif
RCD_FREE(mfont);
*font = NULL;
return 0;
}
void vg_lite_unload_font_data(void)
{
for(int i=0; i<MAX_SYSTEM_FONTS; i++)
{
vg_lite_free_font_memory(i);
}
return;
}

View File

@ -0,0 +1,351 @@
/****************************************************************************
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef VELM_H_
#define VELM_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
*/
#define VERSION 0x00000001
#define SLOT_COUNT 256/*16*/
#define OBJECT_SLOT(id) \
elm_tls->gContext.object_slots[id % SLOT_COUNT]
/*
VGLite releated configurations.
*/
#define TS_WIDTH 64
#define TS_HEIGHT 64
#define RTOS 1
#define APP_BUFFER_COUNT 2
#if (RTOS && DDRLESS) || BAREMETAL
#define OBJCOUNT_GRAD 16
#define OBJCOUNT_EVO 128
#define OBJCOUNT_EBO 64
#define OBJCOUNT_GROUP 16
#endif
#if RTOS
#include "rtthread.h"
#define elm_alloc(num_objects, object_size) rt_malloc(num_objects * object_size)
#define elm_free rt_free
#else
#define elm_alloc calloc
#define elm_free free
#endif
typedef enum {
ELEMENT_LINEARGRADIENT = 0, /*! linear gradient element */
ELEMENT_PATH = 1, /*! path element */
ELEMENT_GROUP = 2, /*! group element */
ELEMENT_TEXT = 3, /*! text element */
ELEMENT_TSPAN = 4, /*! tspan element */
ELEMENT_FONT = 5, /*! font element */
ELEMENT_TTF_FONT = 6, /*! ttf-type font */
ELEMENT_VECTOR_FONT = 7, /*! vector fonts */
ELEMENT_TEXT_FONT = 8, /*! text fonts */
} ELM_ELEMENT_TYPE;
#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
/*
System definitions.
*/
#define DEBUG_ASSERT(a, message) \
if (!a) \
printf("%s: ASSERT failed @ %s, %d.\n", message, __FILE__, __LINE__)
/*!
@typedef el_Object
common object type definition shared by all EVO object to identify its handle,
object type, and ELM version info.
for reference purpose, handle = 0 is reserved.
*/
typedef struct {
ElmHandle handle;
ELM_OBJECT_TYPE type;
unsigned int reference; // Reference count by other objects.
#if (RTOS && DDRLESS) || BAREMETAL
int index; /* The index of the object in pool. */
#endif
} el_Object;
/*!
@typedef el_Transform
The transformation attribute for an EVO/EBO/Group object.
*/
typedef struct {
float rotate;
float translate[2];
float scale[2];
BOOL dirty;
BOOL identity;
vg_lite_matrix_t matrix;
} el_Transform;
/*!
@typedef el_GradData
Linear gradient definition.
!grad the native vg_lite gradient data;
!gransform the grad's transformation. matrix is synced to grad's.
*/
typedef struct {
vg_lite_linear_gradient_t grad;
el_Transform transform;
} el_GradData;
/*!
@typedef el_RadgradData
Radial gradient definition.
!rad_grad the native vg_lite_radial_gradient data;
!gransform the grad's transformation. matrix is synced to grad's.
*/
typedef struct {
vg_lite_radial_gradient_t rad_grad;
el_Transform transform;
} el_RadgradData;
/*!
@typedef el_Obj_Grad
The linear gradient object definition.
*/
typedef struct {
el_Object object;
el_GradData data;
} el_Obj_Grad;
/*!
@typedef el_Obj_Radgrad
The radial gradient object definition.
*/
typedef struct {
el_Object object;
el_RadgradData data;
} el_Obj_Radgrad;
/*!
@typedef el_Obj_Pattern
The pattern paint object definition.
pattern: it should be an pointer to an el_Obj_EVO;
mode: the pattern fill mode.
color: the color value if pattern mode is COLOR
*/
typedef struct {
void *pattern;
ELM_PATTERN_MODE mode;
uint32_t color;
} el_Obj_Pattern;
/*!
@typedef el_Paint
The paint object definition.
color: for solid fill;
grad: for linear gradient fill;
pattern: for image fill.
*/
typedef struct {
ELM_PAINT_TYPE type;
uint32_t color;
el_Obj_Grad * grad;
el_Obj_Radgrad * radgrad;
el_Obj_Pattern pattern;
} el_Paint;
/*!
@typedef el_Attribute
The rendering attribute definition.
*/
typedef struct {
ELM_QUALITY quality;
ELM_BLEND blend;
ELM_EVO_FILL fill_rule;
el_Paint paint;
el_Transform transform;
} el_Attribute;
/*!
@typedef el_EVOData
The data definition for EVO (vector object).
*/
typedef struct {
vg_lite_path_t path;
} el_EVOData;
/*!
@typedef el_Obj_EVO
EVO (Elementry Vector Object) type definition.
*/
typedef struct {
el_Object object;
el_Attribute attribute;
el_Attribute defaultAttrib;
el_EVOData data;
uint32_t has_pattern;
uint32_t is_pattern;
uint32_t is_image;
char eboname[20];
uint32_t img_width;
uint32_t img_height;
} el_Obj_EVO;
/*!
@typedef el_EBOData
The data definition for EBO (bitmap object).
*/
typedef struct {
vg_lite_buffer_t buffer;
} el_EBOData;
/*!
@typedef el_Obj_EBO
EBO (Elementry Buffer Object) type definition.
*/
typedef struct {
el_Object object;
el_Attribute attribute;
el_Attribute defaultAttrib;
el_EBOData data;
uint32_t clut_count;
uint32_t clut[256];
} el_Obj_EBO;
/*!
@typedef el_GroupData
The group object data definition.
*/
typedef struct {
unsigned int count;
el_Obj_EVO * objects;
} el_GroupData;
/*!
@typedef el_Obj_Group
Group object type definition.
*/
typedef struct {
el_Object object;
el_Transform transform;
el_Transform defaultTrans;
el_GroupData group;
} el_Obj_Group;
/*!
@typedef el_Obj_Buffer
The render buffer object definition.
*/
typedef struct {
el_Object object;
vg_lite_buffer_t buffer;
} el_Obj_Buffer;
/*!
@typedef el_ObjList
List to organize objects.
*/
typedef struct _object_list{
el_Object *object;
struct _object_list *next;
} el_ObjList;
/*!
@typedef ElmRenderBuffer
The ElmRenderBuffer definition.
*/
typedef struct elm_render_buffer {
ElmBuffer handle;
vg_lite_buffer_t *buffer;
} ElmRenderBuffer;
/*!
@typedef el_Context
The context object for global data management.
!version UXDK version
!currentHandle The current handle for new object
!objectCount Count of all objects
!object_slots List array to manage objects
*/
typedef struct {
uint32_t version;
int reference;
ElmHandle currentHandle;
unsigned int objectCount;
el_ObjList *object_slots[SLOT_COUNT];
ElmRenderBuffer elmFB[APP_BUFFER_COUNT];
/* VGLite related states. */
uint32_t tessellation_width;
uint32_t tessellation_height;
/* The current vector index (within a group). */
int32_t vector_id;
#if (RTOS && DDRLESS) || BAREMETAL
/* Static object pools. */
el_Obj_Grad objpool_grad[OBJCOUNT_GRAD];
el_Obj_EVO objpool_evo[OBJCOUNT_EVO];
el_Obj_EBO objpool_ebo[OBJCOUNT_EBO];
el_Obj_Group objpool_group[OBJCOUNT_GROUP];
/* The allocation map table.
* Each bit in the element maps to the usage of the object.
* 0 means free, 1 means allocated.
* The mapping order is 01234567...31 (hi -> low) in big endian systems.
* */
int32_t objmap_grad[(OBJCOUNT_GRAD + 31) / 32];
int32_t objmap_evo[(OBJCOUNT_EVO + 31) / 32];
int32_t objmap_ebo[(OBJCOUNT_EBO + 31) / 32];
int32_t objmap_group[(OBJCOUNT_GROUP + 31) / 32];
int objcounter_grad;
int objcounter_evo;
int objcounter_ebo;
int objcounter_group;
#endif
} el_Context;
/*!
@typedef elm_tls_t
The elm_tls_t definition.
*/
typedef struct vglite_elm_tls {
el_Context gContext;
} elm_tls_t;
/*
API function prototypes.
*/
int add_object (el_Object *object);
int remove_object (el_Object *object);
el_Object *get_object (ElmHandle handle);
#ifdef __cplusplus
}
#endif
#endif /* VELM_H_ */

View File

@ -0,0 +1,317 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/** Include Files */
#include <stdio.h>
#include <stdlib.h>
#include "vg_lite_text.h"
#include "vft_draw.h"
#include "vft_debug.h"
#ifdef ENABLE_DEBUG_TRACE
/** Macros */
/** Data structures */
typedef enum path_type {
PATH_DONE,
PATH_CLOSE,
MOVE_TO,
MOVE_TO_REL,
LINE_TO,
LINE_TO_REL,
QUAD_TO,
QUAD_TO_REL,
CUBI_TO,
CUBI_TO_REL,
NUM_PATH_CMD
} path_type_t;
/** Internal or external API prototypes */
/** Globals */
static const int data_count[] =
{
0,
0,
2,
2,
2,
2,
4,
4,
6,
6
};
static char s_cmd_name[][16] =
{
{"PATH_DONE" },
{"PATH_CLOSE" },
{"MOVE_TO" },
{"MOVE_TO_REL" },
{"LINE_TO" },
{"LINE_TO_REL" },
{"QUAD_TO" },
{"QUAD_TO_REL" },
{"CUBI_TO" },
{"CUBI_TO_REL" },
{"NUM_PATH_CMD"},
};
/** Externs if any */
/** Code section */
void vfg_dbg_path_data(path_desc_t* path_data_desc, int offset)
{
float* draw_cmds;
draw_cmds = &path_data_desc->draw_cmds[0];
for (int i = 0; i < path_data_desc->num_draw_cmds; i++) {
uint32_t cmd, j;
cmd = *((uint32_t*)(&draw_cmds[i]));
if (cmd < NUM_PATH_CMD) {
TRACE_BIN(("BIN: %08x: %s(%d) [",
offset + i * 4,
s_cmd_name[cmd], cmd));
for (j = 0; j < data_count[cmd]; j++) {
TRACE_BIN((" %.2f", draw_cmds[i + j + 1]));
}
i += j;
TRACE_BIN(("]\n"));
}
}
}
void vft_dbg_path(char *prefix, void *draw_cmds_args, int num_draw_cmds)
{
float* draw_cmds;
draw_cmds = draw_cmds_args;
int offset = 0;
for (int i = 0; i < num_draw_cmds; i++) {
uint32_t cmd, j;
cmd = *((uint32_t*)(&draw_cmds[i]));
if (cmd < NUM_PATH_CMD) {
printf("BIN: %08x: %s(%d) [",
offset + i * 4,
s_cmd_name[cmd], cmd);
for (j = 0; j < data_count[cmd]; j++) {
printf(" %.2f", draw_cmds[i + j + 1]);
}
i += j;
printf("]\n");
}
}
}
void vft_dbg_path_bounds(char *name, float *ary, int num_elements)
{
float* array_data;
array_data = ary;
printf("%s [",name);
for (int i = 0; i < num_elements; i++) {
printf(" %.2f", array_data[i]);
}
printf("]\n");
}
void vft_dbg_kern_desc(kern_desc_t* kern_desc, int num_kern_entries, int offset)
{
for (int i = 0; i < num_kern_entries; i++) {
TRACE_BIN(("BIN: %08x: [%d] (u,k)=(%hu, %hu)\n",
(int)(offset + i * sizeof(kern_desc_t)),
i,
kern_desc[i].unicode,
kern_desc[i].kern));
}
}
void vft_dbg_glyph_desc(glyph_desc_t* g, int offset)
{
glyph_desc_t _desc = *g; /* Temporary copy descriptor*/
TRACE_BIN_FIELD_UINT16(unicode);
TRACE_BIN_FIELD_UINT16(horiz_adv_x);
TRACE_BIN_FIELD_UINT32(kern_num_entries);
TRACE_BIN_FIELD_UINT32(kern_table_offset);
TRACE_BIN_FIELD_FLOAT(path.bounds[0]);
TRACE_BIN_FIELD_FLOAT(path.bounds[1]);
TRACE_BIN_FIELD_FLOAT(path.bounds[2]);
TRACE_BIN_FIELD_FLOAT(path.bounds[3]);
TRACE_BIN_FIELD_UINT32(path.num_draw_cmds);
TRACE_BIN_FIELD_UINT32(path.draw_cmds_offset);
}
/* TRACE values for debugging purpose */
void vft_dbg_font_face_desc(font_face_desc_t* font_face, int offset)
{
font_face_desc_t _desc = *font_face; /* Temporary copy descriptor*/
TRACE_INFO(("font-face-block\n"));
TRACE_BIN_FIELD_STR(font_family_name); offset += sizeof(_desc.font_family_name);
TRACE_BIN_FIELD_UINT16(units_per_em);
TRACE_BIN_FIELD_UINT16(ascent);
TRACE_BIN_FIELD_UINT16(descent);
TRACE_BIN_FIELD_UINT16(vg_font);
TRACE_BIN_FIELD_UINT32(num_glyphs);
}
void vft_dbg_matrix(char *name, vg_lite_matrix_t *mat)
{
printf("%s\n",name);
printf(" %0.3f %0.3f %0.3f\n",
mat->m[0][0],mat->m[0][1],mat->m[0][2]);
printf(" %0.3f %0.3f %0.3f\n",
mat->m[1][0],mat->m[1][1],mat->m[1][2]);
printf(" %0.3f %0.3f %0.3f\n",
mat->m[2][0],mat->m[1][1],mat->m[2][2]);
}
void vft_dbg_path_table(font_face_desc_t* font_face, int offset)
{
TRACE_INFO(("path-block\n"));
for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
glyph_desc_t* g = &font_face->glyphs[i];
TRACE_BIN(("Glyph - path: '%c' unicode = %d\n", g->unicode, g->unicode));
offset = g->path.draw_cmds_offset;
vfg_dbg_path_data(&g->path, offset);
}
}
void vft_dbg_kern_table(font_face_desc_t* font_face, int offset)
{
TRACE_INFO(("kern-block\n"));
for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
glyph_desc_t* g = &font_face->glyphs[i];
TRACE_INFO(("Kern: '%c' unicode=%hu\n", g->unicode, g->unicode));
vft_dbg_kern_desc(&g->kern_table[0],
g->kern_num_entries,
offset);
offset += (g->kern_num_entries * sizeof(kern_desc_t));
}
}
void vft_dbg_glyph_table(font_face_desc_t* font_face, int offset)
{
TRACE_INFO(("glyph-block\n"));
for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
glyph_desc_t* g = &font_face->glyphs[i];
TRACE_INFO(("Glyph: '%c'\n", g->unicode));
vft_dbg_glyph_desc(g, offset);
offset += sizeof(glyph_desc_t);
}
}
int g_offset = 0;
void dbg_float_ary(char *name, float *ary, int count, int *disk_offset)
{
int i;
int offset = *disk_offset;
for (i=0; i<count; i++) {
DBG_TRACE(("DBG: %s[%d]=%f offset=%d\n", \
name, \
i, \
ary[i], offset));
offset+= 4;
}
*disk_offset = offset;
}
void dbg_int_ary(char *name, uint32_t *ary, int count, int *disk_offset)
{
int i;
int offset = *disk_offset;
for (i=0; i<count; i++) {
DBG_TRACE(("DBG: %s[%d]=%d offset=%d\n", \
name, \
i, \
ary[i], offset));
offset+= 4;
}
*disk_offset = offset;
}
void dbg_int_param(char *name, uint32_t value, int *disk_offset)
{
int offset = *disk_offset;
DBG_TRACE(("DBG: %s=%d offset=%d\n", \
name, \
value, offset));
offset+= 4;
*disk_offset = offset;
}
void dbg_float_ary_no_offset_update(char *name, float *ary,
int count, int disk_offset)
{
int i;
int offset = disk_offset;
for (i=0; i<count; i++) {
DBG_TRACE(("DBG: %s[%d]=%f offset=%d\n", \
name, \
i, \
ary[i], offset));
offset+= 4;
}
}
void dbg_int_ary_no_offset_update(char *name, uint32_t *ary,
int count, int disk_offset)
{
int i;
int offset = disk_offset;
for (i=0; i<count; i++) {
DBG_TRACE(("DBG: %s[%d]=%d offset=%d\n", \
name, \
i, \
ary[i], offset));
offset+= 4;
}
}
void dbg_int_param_no_offset_update(char *name, uint32_t value, int disk_offset)
{
int offset = disk_offset;
DBG_TRACE(("DBG: %s=%d offset=%d\n", \
name, \
value, offset));
offset+= 4;
}
#endif

View File

@ -0,0 +1,111 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
//#define ENABLE_DEBUG_TRACE
#ifdef ENABLE_DEBUG_TRACE
/* With debug configuration */
/* Macros */
#define TRACE_DBG(x) printf x
#define TRACE_BIN(x) // printf x /* Tracer for binary layout */
#define TRACE_WRN(x) printf x
#define TRACE_INFO(x) printf x
#define TRACE_ERR(x) printf x
#define DBG_ARY(obj, param, count) \
dbg_float_ary(#param, &obj->param[0], count, &g_offset);
#define DBG_INT_ARY(obj, param, count) \
dbg_int_ary(#param, obj->param, count, &g_offset);
#define DBG_FIELD(obj, param) \
dbg_int_param(#param, obj->param, &g_offset)
#define DBG_READ_32B(name, value, offset) \
dbg_int_param_no_offset_update(name, value, offset)
extern int g_offset;
#define VFT_DBG_FONT_FACE_DESC(a,b) vft_dbg_font_face_desc(a,b)
#define VFT_DBG_GLYPH_TABLE(a,b) vft_dbg_glyph_table(a,b)
#define VFT_DBG_KERN_TABLE(a,b) vft_dbg_kern_table(a,b)
#define VFT_DBG_PATH_TABLE(a,b) vft_dbg_path_table(a,b)
static int g_offset = 0; /* Dummy just to solve build errors */
#define DBG_TRACE(x)
#define DBG_INC_OFFSET(x) g_offset += (x);
#define DBG_OFFSET() (g_offset)
/* Prorotypes */
void vft_dbg_font_face_desc(font_face_desc_t* font_face, int offset);
void vft_dbg_glyph_desc(glyph_desc_t* g, int offset);
void vft_dbg_kern_desc(kern_desc_t* kern_desc, int num_kern_entries, int offset);
void vfg_dbg_path_data(path_desc_t* path_data_desc, int offset);
void vft_dbg_matrix(char *name, vg_lite_matrix_t *mat);
void vft_dbg_path_table(font_face_desc_t* font_face, int offset);
void vft_dbg_kern_table(font_face_desc_t* font_face, int offset);
void vft_dbg_glyph_table(font_face_desc_t* font_face, int offset);
void dbg_float_ary_no_offset_update(char *name, float *ary,
int count, int disk_offset);
void dbg_int_ary_no_offset_update(char *name, uint32_t *ary,
int count, int disk_offset);
void dbg_int_param_no_offset_update(char *name, uint32_t value, int disk_offset);
#else
/** Without -debug configuration */
/* Macros */
#define TRACE_DBG(x)
#define TRACE_BIN(x)
#define TRACE_WRN(x) printf x
#define TRACE_INFO(x)
#define TRACE_ERR(x) printf x
#define DBG_READ_32B(a,b,c)
#define DBG_TRACE(x)
#define vft_dbg_glyph_desc(g,offset)
#define dbg_float_ary_no_offset_update(a, b, c,d)
#define dbg_int_ary_no_offset_update(a, b, c,d)
#define vft_dbg_path_bounds(a,b,c)
#define vft_dbg_path(a,b,c)
#define VFT_DBG_FONT_FACE_DESC(a,b)
#define VFT_DBG_GLYPH_TABLE(a,b)
#define VFT_DBG_KERN_TABLE(a,b)
#define VFT_DBG_PATH_TABLE(a,b)
#define DBG_INC_OFFSET(x)
#define DBG_OFFSET() (0)
#endif
#define TRACE_BIN_FIELD_STR(x) TRACE_BIN(("BIN: %08x: "#x"=%s\n",offset,_desc.x));
#define TRACE_BIN_FIELD_UINT16(x) TRACE_BIN(("BIN: %08x: "#x"=%hu\n",offset,_desc.x)); offset += 2;
#define TRACE_BIN_FIELD_UINT32(x) TRACE_BIN(("BIN: %08x: "#x"=%u\n",offset,_desc.x)); offset += 4;
#define TRACE_BIN_FIELD_FLOAT(x) TRACE_BIN(("BIN: %08x: "#x"=%f\n",offset,_desc.x)); offset += 4;

View File

@ -0,0 +1,463 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/** Include Files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vg_lite.h"
#include "vg_lite_text.h"
#include "vft_draw.h"
#include "vft_debug.h"
#include "rtthread.h"
/** Macros */
#define VFT_ALLOC(x) _mem_allocate(x)
#define VFT_FREE(x) _mem_free(x)
#define READ_BIN_FIELD(x) memcpy(&g->x, (buf + offset), sizeof(g->x)); offset += sizeof(g->x)
#define READ_BIN_FIELD_STR(x) READ_BIN_FIELD(x)
#define READ_BIN_FIELD_UINT16(x) READ_BIN_FIELD(x)
#define READ_BIN_FIELD_UINT32(x) READ_BIN_FIELD(x)
#define READ_BIN_FIELD_FLOAT(x) READ_BIN_FIELD(x)
#define READ_BIN_FIELD_DUMMY_POINTER(x) offset += 4;
#define GLYPH_CACHE_SIZE 16
#define ENABLE_TEXT_WRAP 0
#define HALT_ALLOCATOR_ERROR 1
/** Data structures */
typedef struct glyph_cache_desc {
vg_lite_path_t *h_path;
glyph_desc_t *g;
uint32_t use_count;
}glyph_cache_desc_t;
/** Internal or external API prototypes */
/** Globals */
static int g_glyph_cache_init_done = 0;
static glyph_cache_desc_t g_glyph_cache[GLYPH_CACHE_SIZE];
int g_total_bytes = 0;
/** Externs if any */
/* Internal API, not published to user */
font_face_desc_t *_vg_lite_get_vector_font(vg_lite_font_t font_idx);
void matrix_multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t *mult);
void *_mem_allocate(int size)
{
char *buf = NULL;
if ( size == 0 ) {
printf("ERROR: HALT: Why allocating %d bytes\n", size);
#if HALT_ALLOCATOR_ERROR
while(1);
#else
return NULL;
#endif
}
buf = rt_malloc(size);
if (buf == NULL) {
printf("ERROR: HALT: allocating %d bytes \"system out of memory\"\n", size);
#if HALT_ALLOCATOR_ERROR
while(1);
#else
return NULL;
#endif
}
g_total_bytes += size;
return buf;
}
void _mem_free(void *buf)
{
rt_free(buf);
}
/** GLYPH CACHING Code */
void glyph_cache_init(void)
{
if ( g_glyph_cache_init_done == 0 ) {
memset(g_glyph_cache,0,sizeof(g_glyph_cache));
g_glyph_cache_init_done = 1;
}
}
void glyph_cache_free(void)
{
int i;
for (i=0; i<GLYPH_CACHE_SIZE; i++) {
if ( g_glyph_cache[i].h_path != NULL ) {
/* For non-mapped path this resetting is sufficient */
vg_lite_clear_path(g_glyph_cache[i].h_path);
/* Release path handle */
VFT_FREE(g_glyph_cache[i].h_path);
/* Reset pointer */
g_glyph_cache[i].h_path = NULL;
}
}
/* Next time font init will be required */
g_glyph_cache_init_done = 0;
}
vg_lite_path_t *vft_cache_lookup(glyph_desc_t *g)
{
int i;
int unused_idx = 0;
/* Not present caching code does not handle multiple font-face */
glyph_cache_init();
/* Check if path object for given glyph exists */
for (i=0; i<GLYPH_CACHE_SIZE; i++) {
if ( g_glyph_cache[i].g != NULL && g->unicode ==
g_glyph_cache[i].g->unicode )
{
g_glyph_cache[i].use_count++;
return g_glyph_cache[i].h_path;
}
}
/* Find least used descriptor */
unused_idx = 0;
for (i=1; i<GLYPH_CACHE_SIZE; i++) {
if ( g_glyph_cache[i].use_count <
g_glyph_cache[unused_idx].use_count ) {
unused_idx = i;
}
}
/* Re-cycle descriptor */
if ( g_glyph_cache[unused_idx].h_path != NULL ) {
/* For non-mapped path this resetting is sufficient */
vg_lite_clear_path(g_glyph_cache[unused_idx].h_path);
} else {
/* Allocate new path object */
g_glyph_cache[unused_idx].h_path =
(vg_lite_path_t *)VFT_ALLOC(sizeof(vg_lite_path_t));
}
/* Allocate new path */
vg_lite_init_path(g_glyph_cache[unused_idx].h_path,
VG_LITE_FP32, VG_LITE_HIGH,
g->path.num_draw_cmds*4,
g->path.draw_cmds,
g->path.bounds[0],
g->path.bounds[1],
g->path.bounds[2],
g->path.bounds[3]);
g_glyph_cache[unused_idx].g = g;
g_glyph_cache[unused_idx].use_count = 1;
return g_glyph_cache[unused_idx].h_path;
}
/** Render text using vector fonts */
int vg_lite_vtf_draw_text(vg_lite_buffer_t *rt, int x, int y,
vg_lite_blend_t blend,
vg_lite_font_t font,
vg_lite_matrix_t *matrix,
vg_lite_font_attributes_t * attributes,
char *text)
{
font_face_desc_t *font_face;
glyph_desc_t* g1 = NULL;
glyph_desc_t* g2;
int error = 0;
float font_scale = 1.0;
int text_wrap = 0;
font_face = (font_face_desc_t *)_vg_lite_get_vector_font(font);
attributes->last_dx = 0;
font_scale = ((1.0*attributes->font_height)/font_face->units_per_em);
vg_lite_matrix_t mat;
vg_lite_fill_t fill_rule = VG_LITE_FILL_NON_ZERO;
vg_lite_color_t color = attributes->text_color;
/* Compute size of tex in pixels
* For center alignment adjust x position
* Present parser has bug in encoding alignment value,
* Once it is fixed following code will align text in center
*/
if ( attributes->alignment == eTextAlignCenter ||
attributes->alignment == eTextAlignRight ) {
char *t2 = text;
int dx = 0;
uint16_t ug2; /* Unicode glyph */
int kx;
/* Case of center alignement */
while (*t2 != '\0') {
ug2 = *t2;
kx = 0;
g2 = vft_find_glyph(font_face, ug2);
if (g1 != NULL && g2 != NULL) {
kx = vft_glyph_distance(g1, g2);
}
dx += ((g2->horiz_adv_x + kx )* font_scale);
t2++;
}
if ( attributes->alignment == eTextAlignCenter) {
x -= (dx/2);
} else if ( attributes->alignment == eTextAlignRight) {
x -= (dx);
}
}
/* Compute pixels that will cover this vector path */
while (*text != '\0') {
uint16_t ug2; /* Unicode glyph */
int kx;
if (text_wrap == 0) {
vg_lite_identity(&mat);
matrix_multiply(&mat, matrix);
vg_lite_translate(x,y, &mat);
vg_lite_scale(font_scale,font_scale, &mat); // 0.35 = height/units_per_em
vg_lite_scale(-1.0,1.0, &mat);
vg_lite_scale(-1.0,-1.0, &mat);
text_wrap = 1;
}
/* Read unicode character */
kx = 0;
ug2 = *text;
g2 = vft_find_glyph(font_face, ug2);
if (g1 != NULL && g2 != NULL) {
kx = vft_glyph_distance(g1, g2);
}
#if (ENABLE_TEXT_WRAP==1)
/* Wrap text */
if ( (x + attributes->last_dx + ((g2->horiz_adv_x + kx )* font_scale))
>= (720 - 5) )
{
text_wrap = 0;
attributes->last_dx = 0;
y += (attributes->font_height + 1);
continue;
}
#endif /* ENABLE_TEXT_WRAP */
/* Compute glyph size in horizontal dimension */
g1 = g2;
text++;
error = vg_lite_draw(rt, vft_cache_lookup(g2),
fill_rule,
&mat,
blend,
color);
if ( error != VG_LITE_SUCCESS ) {
break;
}
vg_lite_translate(g2->horiz_adv_x + kx, 0, &mat);
attributes->last_dx += ((g2->horiz_adv_x + kx )* font_scale);
}
attributes->last_dx += 2; /* Space between 2 text strings */
return 0;
}
void load_font_face(font_face_desc_t* font_face, uint8_t* buf, int font_face_offset)
{
font_face_desc_t* g = font_face;
int offset = font_face_offset;
READ_BIN_FIELD_STR(font_family_name);
READ_BIN_FIELD_UINT16(units_per_em);
READ_BIN_FIELD_UINT16(ascent);
READ_BIN_FIELD_UINT16(descent);
READ_BIN_FIELD_UINT16(vg_font);
READ_BIN_FIELD_UINT32(num_glyphs);
}
void load_glyph_table(font_face_desc_t* font_face, uint8_t* buf, int glyph_table_offset)
{
int offset = glyph_table_offset;
for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
glyph_desc_t* g = &font_face->glyphs[i];
memset(g, 0, sizeof(glyph_desc_t));
READ_BIN_FIELD_UINT16(unicode);
READ_BIN_FIELD_UINT16(horiz_adv_x);
READ_BIN_FIELD_UINT32(kern_num_entries);
READ_BIN_FIELD_UINT32(kern_table_offset);
READ_BIN_FIELD_DUMMY_POINTER();
READ_BIN_FIELD_FLOAT(path.bounds[0]);
READ_BIN_FIELD_FLOAT(path.bounds[1]);
READ_BIN_FIELD_FLOAT(path.bounds[2]);
READ_BIN_FIELD_FLOAT(path.bounds[3]);
READ_BIN_FIELD_UINT32(path.num_draw_cmds);
READ_BIN_FIELD_UINT32(path.draw_cmds_offset);
READ_BIN_FIELD_DUMMY_POINTER();
font_face->glyphs[i].kern_table = (kern_desc_t *)(buf + font_face->glyphs[i].kern_table_offset);
font_face->glyphs[i].path.draw_cmds = (float *)(buf + font_face->glyphs[i].path.draw_cmds_offset);
TRACE_INFO(("Glyph: '%c'\n", g->unicode));
vft_dbg_glyph_desc(g, d_offset);
}
}
/* Load vector font ROM table from file */
font_face_desc_t* vft_load_from_buffer(char* buf_base, int file_size)
{
font_face_desc_t* font_face = NULL;
uint32_t* blk_hdr;
//int error = 0;
/* Setup internal memory pointers of font_face_desc_t */
int font_face_offset = 0;
int glyph_table_offset = 0;
//int kern_table_offset = 0;
//int path_data_offset = 0;
int offset = 0;
/* May be we can avoid this lookup */
while (offset < file_size) {
blk_hdr = (uint32_t*)(buf_base + offset);
eFontBlock_t eType = (eFontBlock_t)((*blk_hdr) >> 24);
int size = ((*blk_hdr) & ((1<<24)-1));
TRACE_BIN(("BIN: %08x: block(%hu, %hu)\n",
offset, eType, size));
offset += BLK_HDR_SIZE;
/* Check integrity of block and then only proceed */
switch (eType) {
case eFontFaceDesc:
font_face_offset = offset;
break;
case eGlyphTableDesc:
glyph_table_offset = offset;
break;
case eKernTableDesc:
//kern_table_offset = offset;
break;
case eGlyphData:
//path_data_offset = offset;
break;
default:
case eUnkBlock:
case eMaxBlock:
return NULL;;
}
offset += size;
}
if (offset < 0 || offset > file_size) {
printf("ERROR: Vector font file integrity error aborting..\n");
return NULL;
}
/* Make structure binary compliant to reduce loading time */
font_face = (font_face_desc_t*)(buf_base + font_face_offset);
font_face->glyphs = (glyph_desc_t*)(buf_base + glyph_table_offset);
VFT_DBG_FONT_FACE_DESC(font_face, font_face_offset);
for (uint32_t i = 0; i < font_face->num_glyphs; i++) {
/* Update internal pointer from memory mapped file */
font_face->glyphs[i].kern_table =
(kern_desc_t*)(buf_base + font_face->glyphs[i].kern_table_offset);
font_face->glyphs[i].path.draw_cmds =
(float*)(buf_base +
font_face->glyphs[i].path.draw_cmds_offset);
/* Try to get these paramters from Binary object or attributes */
//vg_lite_format_t data_format = VG_LITE_FP32; //VG_LITE_S16;
//vg_lite_quality_t quality = VG_LITE_HIGH;
}
VFT_DBG_GLYPH_TABLE(font_face, glyph_table_offset);
VFT_DBG_KERN_TABLE(font_face, kern_table_offset);
VFT_DBG_PATH_TABLE(font_face, path_data_offset);
return font_face;
}
/* Find glyph of given character from glyph table */
glyph_desc_t* vft_find_glyph(font_face_desc_t* font_face, uint16_t ug2)
{
const int num_glyphs = font_face->num_glyphs;
glyph_desc_t* glyphs = font_face->glyphs;
/*
* Present approach is slow linear search, this is ok in 1st prototype
* Since glyph table is already sorted, we can have binary search
*/
for (int i = 0; i < num_glyphs; i++) {
if (glyphs[i].unicode == ug2) {
return (glyph_desc_t*)&glyphs[i];
}
}
return (glyph_desc_t*)&glyphs[0];;
}
/* Find distance between 2 glyph symbols */
int vft_glyph_distance(glyph_desc_t* g1, glyph_desc_t* g2)
{
signed short kx = 0;
uint16_t ug2 = g2->unicode;
kern_desc_t* kern_table = &g1->kern_table[0];
for (int i = 0; i < g1->kern_num_entries; i++) {
if (kern_table[i].unicode == ug2) {
signed short *pkx = (signed short *)&kern_table[i].kern;
kx = *pkx;
break;
}
}
return kx;
}
/*
* Get internal vector path of given glyph
* This is internal function
*/
path_desc_t* vft_get_glyph_path(glyph_desc_t* g2)
{
return &g2->path;
}
/* Unload font face descriptor and all glyphs */
void vft_unload(font_face_desc_t* font_face)
{
glyph_cache_free();
//VFT_FREE(font_face);
}

View File

@ -0,0 +1,119 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _VFT_DRAW_H
#define _VFT_DRAW_H
#include <stdint.h>
typedef enum eFontBlkType {
eUnkBlock,
eFontFaceDesc,
eGlyphTableDesc,
eKernTableDesc,
eGlyphData,
eMaxBlock
}eFontBlock_t;
static const int32_t BLK_HDR_SIZE = 4;
typedef struct path_descriptor {
float bounds[4];
uint32_t num_draw_cmds;
uint32_t draw_cmds_offset;
float* draw_cmds; /* NOTE: this will be used while loading table, DONT REMOVE */
}path_desc_t;
typedef struct kern_desc {
uint16_t unicode;
uint16_t kern;
}kern_desc_t;
typedef struct glyph_descriptor {
uint16_t unicode; /* unicode name */
uint16_t horiz_adv_x; /* Short to align to 32-bit boundry */
uint32_t kern_num_entries;
uint32_t kern_table_offset;
kern_desc_t* kern_table; /* NOTE: this will be used while loading table, DONT REMOVE */
path_desc_t path;
}glyph_desc_t;
typedef struct font_face_info {
int8_t font_family_name[64];
uint16_t units_per_em;
uint16_t ascent;
uint16_t descent;
uint16_t vg_font;
uint32_t num_glyphs;
glyph_desc_t* glyphs; /* NOTE: this will be used while loading table, DONT REMOVE */
}font_face_desc_t;
//NOTE: No glyph caching at this time
/* Load vector font ROM table from file */
font_face_desc_t* vft_load(char* vcft_file_path);
/* Find glyph of given character from glyph table */
glyph_desc_t* vft_find_glyph(font_face_desc_t* font_face, uint16_t ug2);
/* Find distance between 2 glyph symbols */
int vft_glyph_distance(glyph_desc_t* g1, glyph_desc_t* g2);
/*
* Get internal vector path of given glyph
* This is internal function
*/
path_desc_t* vft_get_glyph_path(glyph_desc_t* g2);
/* Draw vector font based glyph on given x,y co-ordinate */
void vft_draw_glyph(int x, int y, glyph_desc_t* g2);
/* Compute horizotal pixels coverted by this path */
int vft_compute_dx(glyph_desc_t* g2);
/* Unload font face descriptor and all glyphs */
void vft_unload(font_face_desc_t*);
/* Draw string with vector font s*/
int vg_lite_vtf_draw_text(vg_lite_buffer_t *rt, int x, int y,
vg_lite_blend_t blend,
vg_lite_font_t font,
vg_lite_matrix_t *matrix,
vg_lite_font_attributes_t * attributes,
char *text);
/* Internal memory allocator API */
void *_mem_allocate(int size);
void _mem_free(void *buf);
vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height);
font_face_desc_t* vft_load_from_buffer(char* buf_base, int file_size);
void vg_lite_unload_font_data(void);
#endif //!_VFT_DRAW_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,535 @@
/****************************************************************************
*
* Copyright Raph Levien 2022
* Copyright Nicolas Silva 2022
* Copyright NXP 2022
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include <math.h>
#include "vg_lite_flat.h"
/*
* Stop IAR compiler from warning about implicit conversions from float to
* double
*/
#if (defined(__ICCARM__))
#pragma diag_suppress = Pa205
#endif
#ifndef VG_CURVE_FLATTENING_TOLERANCE
#define VG_CURVE_FLATTENING_TOLERANCE 0.25
#endif /* defined(VG_CURVE_FLATTENING_TOLERANCE) */
#define FABSF(x) ((vg_lite_float_t) fabs(x))
#define SQRTF(x) ((vg_lite_float_t) sqrt(x))
#define CEILF(x) ((vg_lite_float_t) ceil(x))
#define VG_LITE_ERROR_HANDLER(func) \
if ((error = func) != VG_LITE_SUCCESS) \
goto ErrorHandler
/* Point flatten type for flattened line segments. */
#define vgcFLATTEN_NO 0
#define vgcFLATTEN_START 1
#define vgcFLATTEN_MIDDLE 2
#define vgcFLATTEN_END 3
/*
* Algorithm originally created by Raph Levien:
* https://raphlinus.github.io/graphics/curves/2019/12/23/flatten-quadbez.html
*/
#define FHYPOTF(x, y) ((vg_lite_float_t) hypotf(x, y))
#define FPOWF(x, y) ((vg_lite_float_t) powf(x, y))
/*
* Contains the fields that are used to represent the quadratic Bezier curve
* as a 'y = x^2' parabola.
*/
typedef struct parabola_approx {
vg_lite_float_t x0;
vg_lite_float_t x2;
vg_lite_float_t scale;
vg_lite_float_t cross;
} parabola_approx_t;
/*
* Keeps the quadratic Bezier's control points. This makes life easier when
* passing quadratics as parameters, so we don't have to give 6 floats every
* time.
*/
typedef struct quad_bezier {
vg_lite_float_t X0;
vg_lite_float_t Y0;
vg_lite_float_t X1;
vg_lite_float_t Y1;
vg_lite_float_t X2;
vg_lite_float_t Y2;
} quad_bezier_t;
/*
* Parameters which are used by the flattening algorithm.
*/
typedef struct quad_bezier_flatten_params {
vg_lite_float_t a0;
vg_lite_float_t a2;
int num_points;
vg_lite_float_t u0;
vg_lite_float_t u2;
} quad_bezier_flatten_params_t;
/*
* Keeps the cubic Bezier's control points.
*/
typedef struct cubic_bezier {
vg_lite_float_t X0;
vg_lite_float_t Y0;
vg_lite_float_t X1;
vg_lite_float_t Y1;
vg_lite_float_t X2;
vg_lite_float_t Y2;
vg_lite_float_t X3;
vg_lite_float_t Y3;
} cubic_bezier_t;
vg_lite_error_t _add_point_to_point_list(
vg_lite_stroke_conversion_t * stroke_conversion,
vg_lite_float_t X,
vg_lite_float_t Y,
uint8_t flatten_flag);
vg_lite_error_t _add_point_to_point_list_wdelta(
vg_lite_stroke_conversion_t * stroke_conversion,
vg_lite_float_t X,
vg_lite_float_t Y,
vg_lite_float_t DX,
vg_lite_float_t DY,
uint8_t flatten_flag);
/*
* Evaluates the Bernstein polynomial that represents the curve, at 't'.
* 't' should be a value between 0.0 and 1.0 (though it can be any float, but
* the relevant values are between 0 and 1).
* 'x' and 'y' will contain the coordinates of the evaluated point.
*/
static void quad_bezier_eval(
const quad_bezier_t *q,
vg_lite_float_t t,
vg_lite_float_t *x,
vg_lite_float_t *y
)
{
const vg_lite_float_t omt = 1.0 - t;
*x = q->X0 * omt * omt + 2.0 * q->X1 * t * omt + q->X2 * t * t;
*y = q->Y0 * omt * omt + 2.0 * q->Y1 * t * omt + q->Y2 * t * t;
}
/*
* Approximates the integral which uses the arclength and curvature of the
* parabola.
*/
static vg_lite_float_t approx_integral(vg_lite_float_t x)
{
const vg_lite_float_t D = 0.67;
return x / (1.0 - D + FPOWF(FPOWF(D, 4) + 0.25 * x * x, 0.25));
}
/*
* Approximates the inverse of the previous integral.
*/
static vg_lite_float_t approx_inverse_integral(vg_lite_float_t x)
{
const vg_lite_float_t B = 0.39;
return x * (1.0 - B + SQRTF(B * B + 0.25 * x * x));
}
/*
* Represents a quadratic Bezier curve as a parabola.
*/
static parabola_approx_t map_to_parabola(const quad_bezier_t *q)
{
const vg_lite_float_t ddx = 2 * q->X1 - q->X0 - q->X2;
const vg_lite_float_t ddy = 2 * q->Y1 - q->Y0 - q->Y2;
const vg_lite_float_t u0 = (q->X1 - q->X0) * ddx + (q->Y1 - q->Y0) * ddy;
const vg_lite_float_t u2 = (q->X2 - q->X1) * ddx + (q->Y2 - q->Y1) * ddy;
const vg_lite_float_t cross = (q->X2 - q->X0) * ddy - (q->Y2 - q->Y0) * ddx;
const vg_lite_float_t x0 = u0 / cross;
const vg_lite_float_t x2 = u2 / cross;
const vg_lite_float_t scale = FABSF(cross) / (FHYPOTF(ddx, ddy) * FABSF(x2 - x0));
return (parabola_approx_t) {
.x0 = x0,
.x2 = x2,
.scale = scale,
.cross = cross
};
}
/*
* Tolerance influences the number of lines generated. The lower the tolerance,
* the more lines it generates, thus the flattening will have a higher quality,
* but it will also consume more memory. The bigger the tolerance, the less lines
* will be generated, so the quality will be worse, but the memory consumption
* will be better.
*
* A good default value could be 0.25.
*/
static quad_bezier_flatten_params_t quad_bezier_flatten_params_init(
const quad_bezier_t *q,
vg_lite_float_t tolerance
)
{
const parabola_approx_t params = map_to_parabola(q);
const vg_lite_float_t a0 = approx_integral(params.x0);
const vg_lite_float_t a2 = approx_integral(params.x2);
const vg_lite_float_t count = 0.5 * FABSF(a2 - a0) * SQRTF(params.scale / tolerance);
const int num_points = (int)CEILF(count);
const vg_lite_float_t u0 = approx_inverse_integral(a0);
const vg_lite_float_t u2 = approx_inverse_integral(a2);
return (quad_bezier_flatten_params_t) {
.a0 = a0,
.a2 = a2,
.num_points = num_points,
.u0 = u0,
.u2 = u2
};
}
/*
* Puts into (x, y) the coordinate to which a line should be drawn given the step.
* This should be used in a loop to flatten a curve, like this:
* ```
* params = quad_bezier_flatten_params_init(&q, tolerance);
* for (int i = 1; i < params.num_points; ++i) {
* vg_lite_float_t x, y;
* quad_bezier_flatten_at(&q, &params, i, &x, &y);
* draw_line_to(x, y);
* }
* ```
*/
static void quad_bezier_flatten_at(
const quad_bezier_t *q,
const quad_bezier_flatten_params_t *params,
int step,
vg_lite_float_t *x,
vg_lite_float_t *y
)
{
const vg_lite_float_t a0 = params->a0, a2 = params->a2, u0 = params->u0, u2 = params->u2;
const int num_points = params->num_points;
const vg_lite_float_t u = approx_inverse_integral(a0 + ((a2 - a0) * step) / num_points);
const vg_lite_float_t t = (u - u0) / (u2 - u0);
quad_bezier_eval(q, t, x, y);
}
vg_lite_error_t
_flatten_quad_bezier(
vg_lite_stroke_conversion_t *stroke_conversion,
vg_lite_float_t X0,
vg_lite_float_t Y0,
vg_lite_float_t X1,
vg_lite_float_t Y1,
vg_lite_float_t X2,
vg_lite_float_t Y2
)
{
vg_lite_error_t error = VG_LITE_SUCCESS;
vg_lite_path_point_ptr point0, point1;
vg_lite_float_t x, y;
const vg_lite_float_t tolerance = VG_CURVE_FLATTENING_TOLERANCE;
const quad_bezier_t q = {
.X0 = X0,
.Y0 = Y0,
.X1 = X1,
.Y1 = Y1,
.X2 = X2,
.Y2 = Y2
};
const quad_bezier_flatten_params_t params = quad_bezier_flatten_params_init(&q, tolerance);
if(!stroke_conversion)
return VG_LITE_INVALID_ARGUMENT;
/* Add extra P0 for incoming tangent. */
point0 = stroke_conversion->path_last_point;
/* First add P1 to calculate incoming tangent, which is saved in P0. */
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
point1 = stroke_conversion->path_last_point;
/* Change the point1's coordinates back to P0. */
point1->x = X0;
point1->y = Y0;
point0->length = 0.0f;
for (int i = 1; i < params.num_points; ++i) {
quad_bezier_flatten_at(&q, &params, i, &x, &y);
_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE);
}
/* Add point 2 separately to avoid cumulative errors. */
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_END));
/* Add extra P2 for outgoing tangent. */
/* First change P2(point0)'s coordinates to P1. */
point0 = stroke_conversion->path_last_point;
point0->x = X1;
point0->y = Y1;
/* Add P2 to calculate outgoing tangent. */
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_NO));
point1 = stroke_conversion->path_last_point;
/* Change point0's coordinates back to P2. */
point0->x = X2;
point0->y = Y2;
point0->length = 0.0f;
ErrorHandler:
return error;
}
/*
* Like eval_quad_bezier, computes the coordinates of the point which resides at
* `t` for the cubic.
*/
static void cubic_bezier_eval(
const cubic_bezier_t *c,
vg_lite_float_t t,
vg_lite_float_t *x,
vg_lite_float_t *y
)
{
const vg_lite_float_t omt = 1.0 - t;
const vg_lite_float_t omt2 = omt * omt;
const vg_lite_float_t omt3 = omt * omt2;
const vg_lite_float_t t2 = t * t;
const vg_lite_float_t t3 = t * t2;
*x = omt3 * c->X0 + 3.0 * t * omt2 * c->X1 + 3.0 * t2 * omt * c->X2 + t3 * c->X3;
*y = omt3 * c->Y0 + 3.0 * t * omt2 * c->Y1 + 3.0 * t2 * omt * c->Y2 + t3 * c->Y3;
}
static quad_bezier_t cubic_bezier_derivative(const cubic_bezier_t *c)
{
const vg_lite_float_t x0 = 3.0 * (c->X1 - c->X0);
const vg_lite_float_t y0 = 3.0 * (c->Y1 - c->Y0);
const vg_lite_float_t x1 = 3.0 * (c->X2 - c->X1);
const vg_lite_float_t y1 = 3.0 * (c->Y2 - c->Y1);
const vg_lite_float_t x2 = 3.0 * (c->X3 - c->X2);
const vg_lite_float_t y2 = 3.0 * (c->Y3 - c->Y2);
return (quad_bezier_t) {
.X0 = x0,
.Y0 = y0,
.X1 = x1,
.Y1 = y1,
.X2 = x2,
.Y2 = y2
};
}
/*
* Returns the cubic bezier that is between t0 and t1 of c.
*/
static cubic_bezier_t cubic_bezier_split_at(
const cubic_bezier_t *c,
vg_lite_float_t t0,
vg_lite_float_t t1
)
{
vg_lite_float_t p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, d1x, d1y, d2x, d2y;
vg_lite_float_t scale;
quad_bezier_t derivative;
cubic_bezier_eval(c, t0, &p0x, &p0y);
cubic_bezier_eval(c, t1, &p3x, &p3y);
derivative = cubic_bezier_derivative(c);
scale = (t1 - t0) * (1.0 / 3.0);
quad_bezier_eval(&derivative, t0, &d1x, &d1y);
quad_bezier_eval(&derivative, t1, &d2x, &d2y);
p1x = p0x + scale * d1x;
p1y = p0y + scale * d1y;
p2x = p3x - scale * d2x;
p2y = p3y - scale * d2y;
return (cubic_bezier_t) {
.X0 = p0x,
.Y0 = p0y,
.X1 = p1x,
.Y1 = p1y,
.X2 = p2x,
.Y2 = p2y,
.X3 = p3x,
.Y3 = p3y
};
}
/*
* This function returns the number of quadratic Bezier curves that are needed to
* represent the given cubic, respecting the tolerance.
*
* As with the flattening of quadratics, the lower the tolerance, the better the
* quality. The higher the tolerance, the worse the quality, but better performance
* or memory consumption.
*
* The algorithm comes from:
* https://web.archive.org/web/20210108052742/http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
*
* Implementation adapted from:
* https://github.com/linebender/kurbo/blob/master/src/cubicbez.rs
* and:
* https://scholarsarchive.byu.edu/cgi/viewcontent.cgi?article=1000&context=facpub#section.10.6
*/
static int cubic_bezier_get_flatten_count(
const cubic_bezier_t *c,
vg_lite_float_t tolerance
)
{
const vg_lite_float_t x = c->X0 - 3.0 * c->X1 + 3.0 * c->X2 - c->X3;
const vg_lite_float_t y = c->Y0 - 3.0 * c->Y1 + 3.0 * c->Y2 - c->Y3;
const vg_lite_float_t err = x * x + y * y;
vg_lite_float_t result;
result = FPOWF(err / (432.0 * tolerance * tolerance), 1.0 / 6.0);
result = CEILF(result);
return result > 1.0 ? (int)result : 1;
}
vg_lite_error_t
_flatten_cubic_bezier(
vg_lite_stroke_conversion_t * stroke_conversion,
vg_lite_float_t X0,
vg_lite_float_t Y0,
vg_lite_float_t X1,
vg_lite_float_t Y1,
vg_lite_float_t X2,
vg_lite_float_t Y2,
vg_lite_float_t X3,
vg_lite_float_t Y3
)
{
vg_lite_error_t error = VG_LITE_SUCCESS;
vg_lite_path_point_ptr point0, point1;
const cubic_bezier_t c = {
.X0 = X0,
.Y0 = Y0,
.X1 = X1,
.Y1 = Y1,
.X2 = X2,
.Y2 = Y2,
.X3 = X3,
.Y3 = Y3
};
const vg_lite_float_t tolerance = VG_CURVE_FLATTENING_TOLERANCE;
int num_curves = cubic_bezier_get_flatten_count(&c, tolerance);
vg_lite_float_t fnum_curves = (vg_lite_float_t)num_curves;
vg_lite_float_t fi, t0, t1, p1x, p1y, p2x, p2y, x, y;
cubic_bezier_t subsegment;
quad_bezier_t current_curve;
quad_bezier_flatten_params_t params;
if(!stroke_conversion)
return VG_LITE_INVALID_ARGUMENT;
/* Add extra P0 for incoming tangent. */
point0 = stroke_conversion->path_last_point;
/* First add P1/P2/P3 to calculate incoming tangent, which is saved in P0. */
if (X0 != X1 || Y0 != Y1)
{
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X1, Y1, vgcFLATTEN_START));
}
else if (X0 != X2 || Y0 != Y2)
{
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X2, Y2, vgcFLATTEN_START));
}
else
{
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_START));
}
point1 = stroke_conversion->path_last_point;
/* Change the point1's coordinates back to P0. */
point1->x = X0;
point1->y = Y0;
point0->length = 0.0f;
for (int i = 0; i < num_curves; ++i) {
fi = (vg_lite_float_t)i;
t0 = fi / fnum_curves;
t1 = (fi + 1.0) / fnum_curves;
subsegment = cubic_bezier_split_at(&c, t0, t1);
p1x = 3.0 * subsegment.X1 - subsegment.X0;
p1y = 3.0 * subsegment.Y1 - subsegment.Y0;
p2x = 3.0 * subsegment.X2 - subsegment.X3;
p2y = 3.0 * subsegment.Y2 - subsegment.Y3;
current_curve = (quad_bezier_t) {
.X0 = subsegment.X0,
.Y0 = subsegment.Y0,
.X1 = (p1x + p2x) / 4.0,
.Y1 = (p1y + p2y) / 4.0,
.X2 = subsegment.X3,
.Y2 = subsegment.Y3
};
params = quad_bezier_flatten_params_init(&current_curve, tolerance);
for (int j = 0; j < params.num_points; ++j) {
quad_bezier_flatten_at(&current_curve, &params, j, &x, &y);
_add_point_to_point_list(stroke_conversion, x, y, vgcFLATTEN_MIDDLE);
}
}
/* Add point 3 separately to avoid cumulative errors. */
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_END));
/* Add extra P3 for outgoing tangent. */
/* First change P3(point0)'s coordinates to P0/P1/P2. */
point0 = stroke_conversion->path_last_point;
if (X3 != X2 || Y3 != Y2)
{
point0->x = X2;
point0->y = Y2;
}
else if (X3 != X1 || Y3 != Y1)
{
point0->x = X1;
point0->y = Y1;
}
else
{
point0->x = X0;
point0->y = Y0;
}
/* Add P3 to calculate outgoing tangent. */
VG_LITE_ERROR_HANDLER(_add_point_to_point_list(stroke_conversion, X3, Y3, vgcFLATTEN_NO));
point1 = stroke_conversion->path_last_point;
/* Change point0's coordinates back to P3. */
point0->x = X3;
point0->y = Y3;
point0->length = 0.0f;
ErrorHandler:
return error;
}

View File

@ -0,0 +1,55 @@
/****************************************************************************
*
* Copyright Raph Levien 2022
* Copyright Nicolas Silva 2022
* Copyright NXP 2022
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#ifndef _vg_lite_flat_h_
#define _vg_lite_flat_h_
#include "vg_lite.h"
#ifdef __cplusplus
extern "C" {
#endif
vg_lite_error_t _flatten_quad_bezier(
vg_lite_stroke_conversion_t *stroke_conversion,
vg_lite_float_t X0,
vg_lite_float_t Y0,
vg_lite_float_t X1,
vg_lite_float_t Y1,
vg_lite_float_t X2,
vg_lite_float_t Y2);
vg_lite_error_t _flatten_cubic_bezier(
vg_lite_stroke_conversion_t * stroke_conversion,
vg_lite_float_t X0,
vg_lite_float_t Y0,
vg_lite_float_t X1,
vg_lite_float_t Y1,
vg_lite_float_t X2,
vg_lite_float_t Y2,
vg_lite_float_t X3,
vg_lite_float_t Y3);
#ifdef __cplusplus
}
#endif
#endif /* _vg_lite_flat_h_ */

View File

@ -0,0 +1,499 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2020 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "vg_lite_platform.h"
#include "vg_lite_kernel.h"
#include "vg_lite_hal.h"
#include "vg_lite_hw.h"
#include "vg_lite_os.h"
#if !_BAREMETAL
#include "rtthread.h"
#else
#include "xil_cache.h"
#endif
#if _BAREMETAL
/* The followings should be configured by FPGA. */
static uint32_t registerMemBase = 0x43c80000;
#else
static uint32_t registerMemBase = 0x40240000;
#endif
#define HEAP_NODE_USED 0xABBAF00D
volatile void* contiguousMem = NULL;
uint32_t gpuMemBase = 0;
/* Default heap size is 16MB. */
static int heap_size = MAX_CONTIGUOUS_SIZE;
void vg_lite_init_mem(uint32_t register_mem_base,
uint32_t gpu_mem_base,
volatile void * contiguous_mem_base,
uint32_t contiguous_mem_size)
{
registerMemBase = register_mem_base;
gpuMemBase = gpu_mem_base;
contiguousMem = contiguous_mem_base;
heap_size = contiguous_mem_size;
}
/* Implementation of list. ****************************************/
typedef struct list_head {
struct list_head *next;
struct list_head *prev;
}list_head_t;
#define INIT_LIST_HEAD(entry) \
(entry)->next = (entry);\
(entry)->prev = (entry);
/* Add the list item in front of "head". */
static inline void add_list(list_head_t *to_add, list_head_t *head)
{
/* Link the new item. */
to_add->next = head;
to_add->prev = head->prev;
/* Modify the neighbor. */
head->prev = to_add;
if (to_add->prev != NULL) {
to_add->prev->next = to_add;
}
}
/* Remove an entry out of the list. */
static inline void delete_list(list_head_t *entry)
{
if (entry->prev != NULL) {
entry->prev->next = entry->next;
}
if (entry->next != NULL) {
entry->next->prev = entry->prev;
}
}
/* End of list implementation. ***********/
static inline void _memset(void *mem, unsigned char value, int size)
{
int i;
for (i = 0; i < size; i++) {
((unsigned char*)mem)[i] = value;
}
}
typedef struct heap_node {
list_head_t list; /* TODO: Linux specific, needs to rewrite. */
uint32_t offset;
unsigned long size;
uint32_t status;
}heap_node_t;
struct memory_heap {
uint32_t free;
list_head_t list;
};
struct mapped_memory {
void * logical;
uint32_t physical;
int page_count;
struct page ** pages;
};
struct vg_lite_device {
/* void * gpu; */
uint32_t gpu; /* Always use physical for register access in RTOS. */
/* struct page * pages; */
volatile void * contiguous;
unsigned int order;
unsigned int heap_size;
void * virtual;
uint32_t physical;
uint32_t size;
struct memory_heap heap;
int irq_enabled;
#if defined(VG_DRIVER_SINGLE_THREAD)
volatile uint32_t int_flags;
#if _BAREMETAL
/* wait_queue_head_t int_queue; */
xSemaphoreHandle int_queue;
#else
/* wait_queue_head_t int_queue; */
rt_sem_t int_queue;
#endif
#endif /* VG_DRIVER_SINGLE_THREAD */
void * device;
int registered;
int major;
struct class * class;
int created;
};
struct client_data {
struct vg_lite_device * device;
struct vm_area_struct * vm;
void * contiguous_mapped;
};
static struct vg_lite_device Device, * device;
void vg_lite_hal_delay(uint32_t ms)
{
vg_lite_os_sleep(ms);
}
void vg_lite_hal_barrier(void)
{
/*Memory barrier. */
#if _BAREMETAL
Xil_DCacheFlush();
#else
__asm("DSB");
#endif
}
static int vg_lite_init(void);
vg_lite_error_t vg_lite_hal_initialize(void)
{
int32_t error = VG_LITE_SUCCESS;
/* TODO: Turn on the power. */
vg_lite_init();
/* TODO: Turn on the clock. */
error = vg_lite_os_initialize();
return (vg_lite_error_t)error;
}
void vg_lite_hal_deinitialize(void)
{
/* TODO: Remove clock. */
vg_lite_os_deinitialize();
/* TODO: Remove power. */
}
static int split_node(heap_node_t * node, unsigned long size)
{
/* TODO: the original is linux specific list based, needs rewrite.
*/
heap_node_t * split;
/*
* If the newly allocated object fits exactly the size of the free
* node, there is no need to split.
*/
if (node->size - size == 0)
return 0;
/* Allocate a new node. */
split = (heap_node_t *)vg_lite_os_malloc(sizeof(heap_node_t));
if (split == NULL)
return -1;
/* Fill in the data of this node of the remaning size. */
split->offset = node->offset + size;
split->size = node->size - size;
split->status = 0;
/* Add the new node behind the current node. */
add_list(&split->list, &node->list);
/* Adjust the size of the current node. */
node->size = size;
return 0;
}
vg_lite_error_t vg_lite_hal_allocate_contiguous(unsigned long size, void ** logical, uint32_t * physical,void ** node)
{
unsigned long aligned_size;
heap_node_t * pos;
/* Align the size to 64 bytes. */
aligned_size = (size + 63) & ~63;
/* Check if there is enough free memory available. */
if (aligned_size > device->heap.free) {
return VG_LITE_OUT_OF_MEMORY;
}
/* Walk the heap backwards. */
for (pos = (heap_node_t*)device->heap.list.prev;
&pos->list != &device->heap.list;
pos = (heap_node_t*) pos->list.prev) {
/* Check if the current node is free and is big enough. */
if (pos->status == 0 && pos->size >= aligned_size) {
/* See if we the current node is big enough to split. */
if (0 != split_node(pos, aligned_size))
{
return VG_LITE_OUT_OF_RESOURCES;
}
/* Mark the current node as used. */
pos->status = HEAP_NODE_USED;
/* Return the logical/physical address. */
/* *logical = (uint8_t *) private_data->contiguous_mapped + pos->offset; */
*logical = (uint8_t *)device->virtual + pos->offset;
*physical = gpuMemBase + (uint32_t)(*logical);/* device->physical + pos->offset; */
device->heap.free -= aligned_size;
*node = pos;
return VG_LITE_SUCCESS;
}
}
/* Out of memory. */
return VG_LITE_OUT_OF_MEMORY;
}
void vg_lite_hal_free_contiguous(void * memory_handle)
{
/* TODO: no list available in RTOS. */
heap_node_t * pos, * node;
/* Get pointer to node. */
node = memory_handle;
if (node->status != HEAP_NODE_USED) {
return;
}
/* Mark node as free. */
node->status = 0;
/* Add node size to free count. */
device->heap.free += node->size;
/* Check if next node is free. */
pos = node;
for (pos = (heap_node_t *)pos->list.next;
&pos->list != &device->heap.list;
pos = (heap_node_t *)pos->list.next) {
if (pos->status == 0) {
/* Merge the nodes. */
node->size += pos->size;
if(node->offset > pos->offset)
node->offset = pos->offset;
/* Delete the next node from the list. */
delete_list(&pos->list);
vg_lite_os_free(pos);
}
break;
}
/* Check if the previous node is free. */
pos = node;
for (pos = (heap_node_t *)pos->list.prev;
&pos->list != &device->heap.list;
pos = (heap_node_t *)pos->list.prev) {
if (pos->status == 0) {
/* Merge the nodes. */
pos->size += node->size;
if(pos->offset > node->offset)
pos->offset = node->offset;
/* Delete the current node from the list. */
delete_list(&node->list);
vg_lite_os_free(node);
}
break;
}
/* when release command buffer node and ts buffer node to exit,release the linked list*/
if(device->heap.list.next == device->heap.list.prev) {
delete_list(&pos->list);
vg_lite_os_free(pos);
}
}
void vg_lite_hal_free_os_heap(void)
{
struct heap_node *pos, *n;
/* Check for valid device. */
if (device != NULL) {
/* Process each node. */
for (pos = (heap_node_t *)device->heap.list.next,
n = (heap_node_t *)pos->list.next;
&pos->list != &device->heap.list;
pos = n, n = (heap_node_t *)n->list.next) {
/* Remove it from the linked list. */
delete_list(&pos->list);
/* Free up the memory. */
vg_lite_os_free(pos);
}
}
}
/* Portable: read register value. */
uint32_t vg_lite_hal_peek(uint32_t address)
{
/* Read data from the GPU register. */
return (uint32_t) (*(volatile uint32_t *) (device->gpu + address));
}
/* Portable: write register. */
void vg_lite_hal_poke(uint32_t address, uint32_t data)
{
/* Write data to the GPU register. */
uint32_t *LocalAddr = (uint32_t *)(device->gpu + address);
*LocalAddr = data;
}
vg_lite_error_t vg_lite_hal_query_mem(vg_lite_kernel_mem_t *mem)
{
if(device != NULL){
mem->bytes = device->heap.free;
return VG_LITE_SUCCESS;
}
mem->bytes = 0;
return VG_LITE_NO_CONTEXT;
}
void vg_lite_IRQHandler(void)
{
vg_lite_os_IRQHandler();
}
int32_t vg_lite_hal_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value)
{
return vg_lite_os_wait_interrupt(timeout,mask,value);
}
void * vg_lite_hal_map(unsigned long bytes, void * logical, uint32_t physical, uint32_t * gpu)
{
(void) bytes;
(void) logical;
(void) physical;
(void) gpu;
return (void *)0;
}
void vg_lite_hal_unmap(void * handle)
{
(void) handle;
}
#if !defined(VG_DRIVER_SINGLE_THREAD)
vg_lite_error_t vg_lite_hal_submit(uint32_t context,uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event)
{
return (vg_lite_error_t)vg_lite_os_submit(context,physical,offset,size,event);
}
vg_lite_error_t vg_lite_hal_wait(uint32_t timeout, vg_lite_os_async_event_t *event)
{
return (vg_lite_error_t)vg_lite_os_wait(timeout,event);
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
static void vg_lite_exit(void)
{
heap_node_t * pos;
heap_node_t * n;
/* Check for valid device. */
if (device != NULL) {
/* TODO: unmap register mem should be unnecessary. */
device->gpu = 0;
/* Process each node. */
for (pos = (heap_node_t *)device->heap.list.next, n = (heap_node_t *)pos->list.next;
&pos->list != &device->heap.list;
pos = n, n = (heap_node_t *)n->list.next) {
/* Remove it from the linked list. */
delete_list(&pos->list);
/* Free up the memory. */
vg_lite_os_free(pos);
}
/* Free up the device structure. */
vg_lite_os_free(device);
}
}
static int vg_lite_init(void)
{
heap_node_t * node;
/* Initialize memory and objects ***************************************/
/* Create device structure. */
device = &Device;
/* Zero out the enture structure. */
_memset(device, 0, sizeof(struct vg_lite_device));
/* Setup register memory. **********************************************/
device->gpu = registerMemBase;
/* Initialize contiguous memory. ***************************************/
/* Allocate the contiguous memory. */
device->heap_size = heap_size;
device->contiguous = (volatile void *)contiguousMem;
_memset((void *)device->contiguous, 0, heap_size);
/* Make 64byte aligned. */
while ((((uint32_t)device->contiguous) & 63) != 0)
{
device->contiguous = ((unsigned char*) device->contiguous) + 4;
device->heap_size -= 4;
}
/* Check if we allocated any contiguous memory or not. */
if (device->contiguous == NULL) {
vg_lite_exit();
return -1;
}
device->virtual = (void *)device->contiguous;
device->physical = gpuMemBase + (uint32_t)device->virtual;
device->size = device->heap_size;
/* Create the heap. */
INIT_LIST_HEAD(&device->heap.list);
device->heap.free = device->size;
node = (heap_node_t *)vg_lite_os_malloc(sizeof(heap_node_t));
if (node == NULL) {
vg_lite_exit();
return -1;
}
node->offset = 0;
node->size = device->size;
node->status = 0;
add_list(&node->list, &device->heap.list);
#if defined(VG_DRIVER_SINGLE_THREAD)
#if !_BAREMETAL /*for rt500*/
device->int_queue = rt_sem_create("diq", 0, RT_IPC_FLAG_PRIO);
device->int_flags = 0;
#endif
#endif /* VG_DRIVER_SINGLE_THREAD */
/* Success. */
return 0;
}

View File

@ -0,0 +1,272 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _vg_lite_hal_h_
#define _vg_lite_hal_h_
#include "vg_lite_platform.h"
#include "vg_lite_os.h"
#include "vg_lite_kernel.h"
#define VGLITE_MEM_ALIGNMENT 128
#define THREAD_LENGTH 8
#ifdef __cplusplus
extern "C" {
#endif
/*!
@brief Wait a number of milliseconds.
@discussion
The VGLite hardware requires some waiting when changing clock frequencies or issuing a reset. This is the wrapper function
for the delay function.
@param milliseconds
The number of milliseconds to wait.
*/
void vg_lite_hal_delay(uint32_t milliseconds);
/*!
@brief Initialize the hardware.
@discussion
The VGLite kernel knows how to program its own hardware, but in any SOC there might be additional control required for
turning on the power or initializing the clocks. This function gets called by the VGLite kernel before the VGLite graphics
hardware gets initialized by the VGLite kernel itself and allows for SOC power management control.
The implementer should make sure that on exit of this function the power and clock to the VGLite graphics hardware is
turned on and stable.
*/
vg_lite_error_t vg_lite_hal_initialize(void);
/*!
@brief Uninitialize the hardware.
@discussion
The VGLite kernel knows how to program its own hardware, but in any SOC there might be additional control required for
turning off the power or uninitializing the clocks. This function gets called by the VGLite kernel after the VGLite
graphics hardware gets uninitialized by the VGLite kernel itself and allows for SOC power management control.
On exit of this function it is okay to have the power and/or clock to the VGLite graphics hardware turned off.
*/
void vg_lite_hal_deinitialize(void);
/*!
@brief Allocate contiguous video memory.
@discussion
Any memory the VGLite graphics hardware will see should be allocated as contiguous memory. Any allocated memory will be
addressed through an opaque handle, usually a pointer to an opaque structure. The porting layer can put any information it
needs inside this structure.
@param size
The number of bytes to allocate.
@param logical
A pointer to a variable that will receive the logical address of the allocated memory for the CPU.
@param gpu
A pointer to a variable that will receive the physical address of the allocated memory for the VGLite graphics hardware.
@result
A pointer to an opaque structure that will be used as the memory handle. <code>NULL</code> should be returned if there is not
enough memory.
*/
vg_lite_error_t vg_lite_hal_allocate_contiguous(unsigned long size, void ** logical, uint32_t * physical,void ** node);
/*!
@brief Free contiguous video memory.
@discussion
Free the memory allocated by {@link vg_lite_hal_allocate_contiguous}. After this function returns, the associated memory
handle is no longer a valid handle.
@param memory_handle
A pointer to an opaque structure returned by {@link vg_lite_hal_allocate_contiguous}.
*/
void vg_lite_hal_free_contiguous(void * memory_handle);
/*!
@brief remove unfree node when continuously allocate buffer without free buffer.
@discussion
Free the node allocated by {@link kmalloc}. After this function returns, the associated memory
handle is no longer a valid handle.
*/
void vg_lite_hal_free_os_heap(void);
/*!
@brief Map contiguous logical or physical memory into the VGLite graphics hardware space.
@discussion
Any memory, like a frame buffer or some pre-allocated image or path data, needs to be mapped into the VGLite graphics
hardware address space and wrapped by a memory handle. This allows the VGLite graphics hardware access that memory
directly.
Either a logical or a physical address should be passed in to map.
@param size
The number of bytes to map.
@param logical
The logical address of the memory region to map or <code>NULL</code> if the logical address is not known.
@param physical
The physical address of the memory region to map if <code>logical</code> is <code>NULL</code>.
@param gpu
A pointer to a variable that will receive the VGLite graphics hardware addressable address of the mapped region.
@result
A pointer to an opaque structure that will be used as the memory handle. <code>NULL</code> should be returned if there is
not enough system resources to map the region.
*/
void * vg_lite_hal_map(unsigned long size, void * logical, uint32_t physical, uint32_t * gpu);
/*!
@brief Unmap a previously mapped region.
@discussion
If a mapped region by {@link vg_lite_hal_map} is no longer needed, it should be unmapped to free up any allocated system
resources used when mapping the region.
@param memory_handle
A pointer to an opaque structure returned by {@link vg_lite_hal_map}.
*/
void vg_lite_hal_unmap(void * memory_handle);
/*!
@brief Execute a memory barrier.
@discussion
Some systems require a a memory barrier to make sure all store operations in the CPU have been handled. This is the wrapper
function for a memory barrier.
*/
void vg_lite_hal_barrier(void);
/*!
@brief Read data from a register from the VGLite graphics hardware.
@discussion
In order to communicate with the VGLite graphics hardware, the kernel needs to read and write to some hardware registers.
In each SOC those registers could be allocated at a different space in the physical memory map.
@param address
The relative address of the VGLite graphics hardware register to read from.
@result
The 32-bit value returned from reading the register.
*/
uint32_t vg_lite_hal_peek(uint32_t address);
/*!
@brief Write data to a register from the VGLite graphics hardware.
@discussion
In order to communicate with the VGLite graphics hardware, the kernel needs to read and write to some hardware registers.
In each SOC those registers could be allocated at a different space in the physical memory map.
@param address
The relative address of the VGLite graphics hardware register to write to.
@param data
The data to write to the VGLite graphics hardware register.
*/
void vg_lite_hal_poke(uint32_t address, uint32_t data);
/*!
@brief query the remaining allocate contiguous video memory.
@param data
The data to get the remaining allocate contiguous video memory bytes.
*/
vg_lite_error_t vg_lite_hal_query_mem(vg_lite_kernel_mem_t *mem);
/*!
@brief Wait until an interrupt from the VGLite graphics hardware has been received.
@discussion
Currently, the VGLite API is synchronous. This means that after each call it will wait until the VGLite graphics hardware
has completed. The VGLite graphics hardware will send an interrupt when it is finished, and this function will wait until
that interrupt has been received by the operating system.
A timeout value is specified in order if the kernel wants to wait for a specific number of milliseconds fir the interrupt to
occur. If the interrupt does not occur in the specified timeout, a timeout error will be returned.
@param timeout
The number of milliseconds to wait for the interrupt before returning a timeout error. If <code>timeout = 0xFFFFFFFF</code>
then {@link vg_lite_hal_wait_interrupt} will wait forever for the interrupt.
@param mask
Irq event mask to wait for.
@result
A boolean value indicating whether the interrupt was received (1) or not (0).
*/
int32_t vg_lite_hal_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value);
#if !defined(VG_DRIVER_SINGLE_THREAD)
/*!
@brief Submit the current command buffer to the command queue.
@param context
Address of kernel context.
@param physical
Current command buffer physical address.
@param offset
Current command buffer offset.
@param size
Current command buffer size.
@param event
The async event to use to track the response for this request.
*/
vg_lite_error_t vg_lite_hal_submit(uint32_t context,uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event);
/*!
@brief Wait for the current command buffer to be executed.
@param timeout
Timeout in milliseconds.
@param event
The async event to wait for. If the event's signal is 1, the current command
buffer has been executed.
*/
vg_lite_error_t vg_lite_hal_wait(uint32_t timeout, vg_lite_os_async_event_t *event);
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
#ifdef __cplusplus
}
#endif
#endif /* _vg_lite_hal_h_ */

View File

@ -0,0 +1,64 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2020 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _vg_lite_hw_h
#define _vg_lite_hw_h
#define VG_LITE_HW_CLOCK_CONTROL 0x000
#define VG_LITE_HW_IDLE 0x004
#define VG_LITE_INTR_STATUS 0x010
#define VG_LITE_INTR_ENABLE 0x014
#define VG_LITE_HW_CHIP_ID 0x020
#define VG_LITE_HW_CMDBUF_ADDRESS 0x500
#define VG_LITE_HW_CMDBUF_SIZE 0x504
#define VG_LITE_HW_POWER_CONTROL 0x100
#define VG_LITE_HW_POWER_MODULE_CONTROL 0x104
#define VG_LITE_EXT_WORK_CONTROL 0x520
#define VG_LITE_EXT_VIDEO_SIZE 0x524
#define VG_LITE_EXT_CLEAR_VALUE 0x528
#define VG_LITE_EXT_VIDEO_CONTROL 0x51C
typedef struct clock_control {
uint32_t reserved0 : 1;
uint32_t clock_gate : 1;
uint32_t scale : 7;
uint32_t scale_load : 1;
uint32_t reserved10 : 2;
uint32_t soft_reset : 1;
uint32_t reserved13 : 6;
uint32_t isolate : 1;
} clock_control_t;
typedef union vg_lite_hw_clock_control {
clock_control_t control;
uint32_t data;
} vg_lite_hw_clock_control_t;
#define VG_LITE_HW_IDLE_STATE 0x0B05
#endif /* defined(_vg_lite_hw_h) */

View File

@ -0,0 +1,160 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include <string.h>
#include "vg_lite.h"
static void _memcpy(void *dst, void *src, int size) {
int i;
for (i = 0; i < size; i++) {
((unsigned char*)dst)[i] = ((unsigned char*)src)[i];
}
}
/* Get the plane memory pointer and strides info. */
static uint32_t get_buffer_planes(vg_lite_buffer_t *buffer,
uint8_t **memory,
uint32_t *strides)
{
uint32_t count = 1;
switch (buffer->format) {
case VG_LITE_RGBA8888:
case VG_LITE_BGRA8888:
case VG_LITE_RGBX8888:
case VG_LITE_BGRX8888:
case VG_LITE_RGB565:
case VG_LITE_BGR565:
case VG_LITE_RGBA4444:
case VG_LITE_BGRA4444:
case VG_LITE_BGRA5551:
case VG_LITE_A8:
case VG_LITE_L8:
case VG_LITE_A4:
case VG_LITE_INDEX_1:
case VG_LITE_INDEX_2:
case VG_LITE_INDEX_4:
case VG_LITE_INDEX_8:
case VG_LITE_YUYV:
case VG_LITE_YUY2:
case VG_LITE_RGBA2222:
count = 1;
memory[0] = (uint8_t *)buffer->memory;
memory[1] = memory[2] = ((uint8_t*)0);
strides[0] = buffer->stride;
strides[1] = strides[2] = 0;
break;
case VG_LITE_NV12:
case VG_LITE_NV16:
count = 2;
memory[0] = (uint8_t *)buffer->memory;
memory[1] = (uint8_t *)buffer->yuv.uv_memory;
memory[2] = 0;
strides[0] = buffer->stride;
strides[1] = buffer->yuv.uv_stride;
strides[2] = 0;
break;
case VG_LITE_AYUY2:
count = 2;
memory[0] = (uint8_t *)buffer->memory;
memory[1] = 0;
memory[2] = (uint8_t *)buffer->yuv.v_memory;
strides[0] = buffer->stride;
strides[1] = 0;
strides[2] = buffer->yuv.alpha_stride;
break;
case VG_LITE_ANV12:
count = 3;
memory[0] = (uint8_t *)buffer->memory;
memory[1] = (uint8_t *)buffer->yuv.uv_memory;
memory[2] = (uint8_t *)buffer->yuv.v_memory;
strides[0] = buffer->stride;
strides[1] = buffer->yuv.uv_stride;
strides[2] = buffer->yuv.alpha_stride;
break;
case VG_LITE_YV12:
case VG_LITE_YV24:
case VG_LITE_YV16:
count = 3;
memory[0] = (uint8_t *)buffer->memory;
memory[1] = (uint8_t *)buffer->yuv.uv_memory;
memory[2] = (uint8_t *)buffer->yuv.v_memory;
strides[0] = buffer->stride;
strides[1] = buffer->yuv.uv_stride;
strides[2] = buffer->yuv.v_stride;
break;
case VG_LITE_YUY2_TILED:
case VG_LITE_NV12_TILED:
case VG_LITE_ANV12_TILED:
case VG_LITE_AYUY2_TILED:
default:
count = 0;
break;
}
return count;
}
vg_lite_error_t vg_lite_buffer_upload(vg_lite_buffer_t *buffer,
uint8_t *data[3],
uint32_t stride[3])
{
vg_lite_error_t error = VG_LITE_SUCCESS;
int32_t plane_count;
uint8_t *buffer_memory[3] = {((uint8_t*)0)};
uint32_t buffer_strides[3] = {0};
uint8_t *pdata;
int32_t i, j;
/* Get buffer memory info. */
plane_count = get_buffer_planes(buffer, buffer_memory, buffer_strides);
if (plane_count > 0 && plane_count <= 3) {
/* Copy the data to buffer. */
for (i = 0; i < plane_count; i++) {
pdata = data[i];
for (j = 0; j < buffer->height; j++) {
_memcpy(buffer_memory[i], pdata, buffer_strides[i]);
buffer_memory[i] += buffer_strides[i];
pdata += stride[i];
}
}
}
else {
error = VG_LITE_INVALID_ARGUMENT;
}
return error;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,444 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2020 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _vg_lite_kernel_h_
#define _vg_lite_kernel_h_
#include "vg_lite_os.h"
/* Interrupt IDs from GPU. */
#define EVENT_UNEXPECTED_MESH 0x80000000
#define EVENT_CMD_BAD_WRITE 0x40000000
#define EVENT_ERROR_RECOVER 0x20000000
#define EVENT_CMD_SWITCH 0x10000000
#define EVENT_MCU_BAD_WRITE 0x08000000
#define EVENT_END 0
#define MAX_CONTIGUOUS_SIZE 0x02000000
#define VG_LITE_INFINITE 0xFFFFFFFF
#define VG_LITE_MAX_WAIT_TIME 0x130000
#define CMDBUF_COUNT 2
#define VG_LITE_ALIGN(number, alignment) \
(((number) + ((alignment) - 1)) & ~((alignment) - 1))
/* Available function optimization levels */
#if (defined(__ICCARM__))
#define VG_LITE_ATTR_OPTIMIZE_LOW _Pragma("optimize=none")
#define VG_LITE_ATTR_OPTIMIZE_MEDIUM _Pragma("optimize=medium")
#define VG_LITE_ATTR_OPTIMIZE_HIGH _Pragma("optimize=high")
#else /* ARMGCC */
#define VG_LITE_ATTR_OPTIMIZE_LOW __attribute__((optimize(1)))
#define VG_LITE_ATTR_OPTIMIZE_MEDIUM __attribute__((optimize(2)))
#define VG_LITE_ATTR_OPTIMIZE_HIGH __attribute__((optimize(3)))
#endif /* defined(__ICCARM__) */
/* Allow develpers to force a function optimization level */
#define VG_LITE_OPTIMIZE(level) VG_LITE_ATTR_OPTIMIZE_##level
#define VG_LITE_KERNEL_IS_GPU_IDLE() \
((vg_lite_hal_peek(VG_LITE_HW_IDLE) & VG_LITE_HW_IDLE_STATE) == VG_LITE_HW_IDLE_STATE)
/* Hardware chip Ids */
#define GPU_CHIP_ID_GCNanoliteV 0x255
#define GPU_CHIP_ID_GC355 0x355
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VG_LITE_ERROR
#define VG_LITE_ERROR 1
/*!
@abstract Error codes that the vg_lite functions can return.
@discussion
All API functions return a status code. On success, <code>VG_LITE_SUCCESS</code> will be returned when a function is
successful. This value is set to zero, so if any function returns a non-zero value, an error has occured.
*/
typedef enum vg_lite_error
{
VG_LITE_SUCCESS = 0, /*! Success. */
VG_LITE_INVALID_ARGUMENT, /*! An invalid argument was specified. */
VG_LITE_OUT_OF_MEMORY, /*! Out of memory. */
VG_LITE_NO_CONTEXT, /*! No context or an unintialized context specified. */
VG_LITE_TIMEOUT, /*! A timeout has occured during a wait. */
VG_LITE_OUT_OF_RESOURCES, /*! Out of system resources. */
VG_LITE_GENERIC_IO, /*! Cannot communicate with the kernel driver. */
VG_LITE_NOT_SUPPORT, /*! Function call not supported. */
VG_LITE_MULTI_THREAD_FAIL, /*! Multi-thread/tasks fail. */
VG_LITE_ALREADY_EXISTS, /*! Object already exists */
VG_LITE_NOT_ALIGNED, /*! Data alignment error */
}
vg_lite_error_t;
#endif
#if !defined(VG_DRIVER_SINGLE_THREAD)
typedef enum vg_lite_buffer_signal
{
VG_LITE_IDLE = 0, /*! Buffer available. */
VG_LITE_HW_FINISHED, /*! HW has completed command buffer. */
VG_LITE_IN_QUEUE, /*! Buffer has been send to queue. */
}
vg_lite_buffer_signal_t;
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
typedef enum vg_lite_kernel_counter
{
/* Dont't touch the counter. */
VG_LITE_NONE,
/* Turn the counter on. */
VG_LITE_ON,
/* Turn the counter off. */
VG_LITE_OFF,
/* Query the counter and reset its values. */
VG_LITE_QUERY,
}
vg_lite_kernel_counter_t;
typedef enum vg_lite_kernel_command
{
/* Initialize the GPU. */
VG_LITE_INITIALIZE,
/* Terminate the GPU. */
VG_LITE_TERMINATE,
/* Allocate memory. */
VG_LITE_ALLOCATE,
/* Free memory. */
VG_LITE_FREE,
/* Submit a command buffer to the GPU. */
VG_LITE_SUBMIT,
/* Wait for the GPU to be completed. */
VG_LITE_WAIT,
/* Reset the GPU. */
VG_LITE_RESET,
/* Debug commands. */
VG_LITE_DEBUG,
/* Map memory. */
VG_LITE_MAP,
/* Unmap memory. */
VG_LITE_UNMAP,
/* Check info. */
VG_LITE_CHECK,
/* Query mem. */
VG_LITE_QUERY_MEM,
#if !defined(VG_DRIVER_SINGLE_THREAD)
/* Mutex lock. */
VG_LITE_LOCK,
/* Mutex unlock. */
VG_LITE_UNLOCK,
/* query context switch. */
VG_LITE_QUERY_CONTEXT_SWITCH,
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
}
vg_lite_kernel_command_t;
struct vg_lite_kernel_context {
/* Command buffer. */
void * command_buffer[CMDBUF_COUNT];
void * command_buffer_logical[CMDBUF_COUNT];
uint32_t command_buffer_physical[CMDBUF_COUNT];
#if !defined(VG_DRIVER_SINGLE_THREAD)
vg_lite_os_async_event_t async_event[CMDBUF_COUNT];
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/* Tessellation buffer. */
void * tessellation_buffer;
void * tessellation_buffer_logical;
uint32_t tessellation_buffer_physical;
#if !defined(VG_DRIVER_SINGLE_THREAD)
/* context buffer. */
void * context_buffer[CMDBUF_COUNT];
void * context_buffer_logical[CMDBUF_COUNT];
uint32_t context_buffer_physical[CMDBUF_COUNT];
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
};
/* Context structure. */
typedef struct vg_lite_kernel_context vg_lite_kernel_context_t;
typedef struct capabilities
{
uint32_t tiled : 2;
uint32_t l2_cache : 1;
}
capabilities_t;
typedef union vg_lite_capabilities
{
capabilities_t cap;
uint32_t data;
}
vg_lite_capabilities_t;
typedef struct vg_lite_kernel_initialize
{
/* Command buffer size. */
uint32_t command_buffer_size;
#if !defined(VG_DRIVER_SINGLE_THREAD)
/* Context buffer size. */
uint32_t context_buffer_size;
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/* Tessellation buffer width. */
int32_t tessellation_width;
/* Tessellation buffer height. */
int32_t tessellation_height;
/* OUTPUT */
/* Context pointer. */
vg_lite_kernel_context_t * context;
/* Capabilities. */
vg_lite_capabilities_t capabilities;
/* Allocated command buffer. */
void * command_buffer[CMDBUF_COUNT];
/* GPU address for command buffer. */
uint32_t command_buffer_gpu[CMDBUF_COUNT];
#if !defined(VG_DRIVER_SINGLE_THREAD)
/* Allocated context buffer. */
void * context_buffer[CMDBUF_COUNT];
/* GPU address for context buffer. */
uint32_t context_buffer_gpu[CMDBUF_COUNT];
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/* GPU addresses for tesselation buffers. */
uint32_t tessellation_buffer_gpu[3];
/* Logic addresses for tessellation buffers: used by SW Tessellator. */
uint8_t *tessellation_buffer_logic[3];
/* Size of each level of the tesselation buffer. */
uint32_t tessellation_buffer_size[3];
/* Stride of the tessellation buffer. */
uint32_t tessellation_stride;
/* Width and height of tessellation buffer. */
uint32_t tessellation_width_height;
/* Tessellation config: shift. */
uint32_t tessellation_shift;
}
vg_lite_kernel_initialize_t;
typedef struct vg_lite_kernel_terminate
{
/* Context to terminate. */
vg_lite_kernel_context_t * context;
}
vg_lite_kernel_terminate_t;
typedef struct vg_lite_kernel_allocate
{
/* Number of bytes to allocate. */
uint32_t bytes;
/* Flag to indicate whether the allocated memory is contiguous or not. */
int32_t contiguous;
/* OUTPUT */
/* Memory handle. */
void * memory_handle;
/* Allocated memory. */
void * memory;
/* GPU address of allocated memory. */
uint32_t memory_gpu;
}
vg_lite_kernel_allocate_t;
typedef struct vg_lite_kernel_free
{
/* Memory handle to free. */
void * memory_handle;
}
vg_lite_kernel_free_t;
typedef struct vg_lite_kernel_submit
{
/* Context to submit to. */
vg_lite_kernel_context_t * context;
/* Pointer to command buffer. */
void * commands;
/* Number of bytes in command buffer. */
uint32_t command_size;
/* Command Buffer ID. */
uint32_t command_id;
}
vg_lite_kernel_submit_t;
typedef struct vg_lite_kernel_wait
{
/* Context to wait for. */
vg_lite_kernel_context_t * context;
/* Timeout in milliseconds. */
uint32_t timeout_ms;
#if defined(VG_DRIVER_SINGLE_THREAD)
/* The event to wait. */
uint32_t event_mask;
/* The event(s) got after waiting. */
uint32_t event_got;
#else
/* Command Buffer ID. */
uint32_t command_id;
#endif /* VG_DRIVER_SINGLE_THREAD */
}
vg_lite_kernel_wait_t;
typedef struct vg_lite_kernel_reset
{
/* Context to reset. */
vg_lite_kernel_context_t * context;
}
vg_lite_kernel_reset_t;
typedef struct vg_lite_kernel_debug
{
/* Context to debug. */
vg_lite_kernel_context_t * context;
/* Bandwidth counter enabler. */
vg_lite_kernel_counter_t bandwidth_counter;
/* Pixel counter enabler. */
vg_lite_kernel_counter_t pixel_counters;
/* OUTPUT */
/* Bandwidth counters:
* [0] - burst of 8.
* [1] - burst of 16.
* [2] - burst of 32.
* [3] - burst of 64.
*/
uint32_t bandwidth[4];
/* Pixel counters:.
* [0] - Number of tessellated pixels.
* [1] - Number of imaged pixels.
* [2] - Number of rendered pixels.
*/
uint32_t pixels[3];
}
vg_lite_kernel_debug_t;
typedef struct vg_lite_kernel_map
{
/* Number of bytes to map. */
uint32_t bytes;
/* Logical memory address or NULL. */
void * logical;
/* Physical memory address or 0. */
uint32_t physical;
/* OUTPUT */
/* Memory handle for mapped memory. */
void * memory_handle;
/* GPU address of mapped memory. */
uint32_t memory_gpu;
}
vg_lite_kernel_map_t;
typedef struct vg_lite_kernel_unmap
{
/* Memory handle to unmap. */
void * memory_handle;
}
vg_lite_kernel_unmap_t;
typedef struct vg_lite_kernel_info
{
/* Register's address. */
uint32_t addr;
/* Check register info. */
uint32_t reg;
}
vg_lite_kernel_info_t;
typedef struct vg_lite_kernel_mem
{
uint32_t bytes;
}
vg_lite_kernel_mem_t;
#if !defined(VG_DRIVER_SINGLE_THREAD)
typedef struct vg_lite_kernel_context_switch
{
uint8_t isContextSwitched;
uint32_t context;
}
vg_lite_kernel_context_switch_t;
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
vg_lite_error_t vg_lite_kernel(vg_lite_kernel_command_t command, void * data);
#ifdef __cplusplus
}
#endif
#endif /* _vg_lite_kernel_h_ */

View File

@ -0,0 +1,113 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include <math.h>
#include <string.h>
#include "vg_lite.h"
void vg_lite_identity(vg_lite_matrix_t * matrix)
{
/* Set identify matrix. */
matrix->m[0][0] = 1.0f;
matrix->m[0][1] = 0.0f;
matrix->m[0][2] = 0.0f;
matrix->m[1][0] = 0.0f;
matrix->m[1][1] = 1.0f;
matrix->m[1][2] = 0.0f;
matrix->m[2][0] = 0.0f;
matrix->m[2][1] = 0.0f;
matrix->m[2][2] = 1.0f;
}
static void multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
{
vg_lite_matrix_t temp;
int row, column;
/* Process all rows. */
for (row = 0; row < 3; row++) {
/* Process all columns. */
for (column = 0; column < 3; column++) {
/* Compute matrix entry. */
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
+ (matrix->m[row][1] * mult->m[1][column])
+ (matrix->m[row][2] * mult->m[2][column]);
}
}
/* Copy temporary matrix into result. */
memcpy(matrix, &temp, sizeof(temp));
}
void vg_lite_translate(vg_lite_float_t x, vg_lite_float_t y, vg_lite_matrix_t * matrix)
{
/* Set translation matrix. */
vg_lite_matrix_t t = { { {1.0f, 0.0f, x},
{0.0f, 1.0f, y},
{0.0f, 0.0f, 1.0f}
} };
/* Multiply with current matrix. */
multiply(matrix, &t);
}
void vg_lite_scale(vg_lite_float_t scale_x, vg_lite_float_t scale_y, vg_lite_matrix_t * matrix)
{
/* Set scale matrix. */
vg_lite_matrix_t s = { { {scale_x, 0.0f, 0.0f},
{0.0f, scale_y, 0.0f},
{0.0f, 0.0f, 1.0f}
} };
/* Multiply with current matrix. */
multiply(matrix, &s);
}
void vg_lite_rotate(vg_lite_float_t degrees, vg_lite_matrix_t * matrix)
{
#ifndef M_PI
#define M_PI 3.1415926f
#endif
/* Convert degrees into radians. */
vg_lite_float_t angle = degrees / 180.0f * M_PI;
/* Compuet cosine and sine values. */
vg_lite_float_t cos_angle = cosf(angle);
vg_lite_float_t sin_angle = sinf(angle);
/* Set rotation matrix. */
vg_lite_matrix_t r = { { {cos_angle, -sin_angle, 0.0f},
{sin_angle, cos_angle, 0.0f},
{0.0f, 0.0f, 1.0f}
} };
/* Multiply with current matrix. */
multiply(matrix, &r);
}

View File

@ -0,0 +1,473 @@
#include "vg_lite_os.h"
#include "rtthread.h"
#include "vg_lite_hw.h"
#include "vg_lite_hal.h"
/* If bit31 is activated this indicates a bus error */
#define IS_AXI_BUS_ERR(x) ((x)&(1U << 31))
#if !defined(VG_DRIVER_SINGLE_THREAD)
#define ISR_WAIT_TIME 0x1FFFF
#define MAX_MUTEX_TIME 100
#define THREAD_WAIT_TIME 20
/* command queue task parameter */
#define QUEUE_THREAD_NAME "queue_thread"
#ifndef QUEUE_THREAD_PRIO
// #define QUEUE_THREAD_PRIO (configMAX_PRIORITIES - 1)
#define QUEUE_THREAD_PRIO 0
#endif /* QUEUE_THREAD_PRIO */
#define QUEUE_THREAD_SIZE 1024
#define QUEUE_LENGTH 8
#define MAX_QUEUE_WAIT_NUM 10
/* The array stores one or more tlss, which is pointed by user_data of current thread. Set it to 1 when only vglite is used, otherwise set it to 2 if elementary is applied. */
#define TLS_ARRAY_LENGTH 2
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TURE
#define TURE 1
#endif
typedef struct vg_lite_queue{
uint32_t cmd_physical;
uint32_t cmd_offset;
uint32_t cmd_size;
vg_lite_os_async_event_t *event;
}
vg_lite_queue_t;
rt_uint32_t tls_array[TLS_ARRAY_LENGTH] = {NULL};
typedef struct vg_lite_os{
rt_thread_t task_hanlde;
rt_mq_t queue_handle;
}
vg_lite_os_t;
static rt_mutex_t mutex;
static vg_lite_os_t os_obj = {0};
rt_sem_t semaphore[THREAD_LENGTH] = {NULL};
rt_sem_t command_semaphore = NULL;
uint32_t curContext;
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
rt_sem_t int_queue;
volatile uint32_t int_flags;
void __attribute__((weak)) vg_lite_bus_error_handler()
{
/*
* Default implementation of the bus error handler does nothing. Application
* should override this handler if it requires to be notified when a bus
* error event occurs.
*/
return;
}
#if !defined(VG_DRIVER_SINGLE_THREAD)
/* command queue function */
void command_queue(void * parameters)
{
vg_lite_queue_t* peek_queue;
uint32_t even_got;
uint32_t len;
os_obj.queue_handle = rt_mq_create("queue_vglite", sizeof(vg_lite_queue_t * ), QUEUE_LENGTH, RT_IPC_FLAG_PRIO);
if(os_obj.queue_handle == RT_NULL)
{
/*command queue create fail, delete queue task */
rt_thread_delete(rt_thread_self());
}
command_semaphore = rt_sem_create("cs", 0, RT_IPC_FLAG_PRIO);
while(1)
{
even_got = 0;
if (rt_sem_take((rt_sem_t)command_semaphore, RT_WAITING_FOREVER) == RT_EOK) {
if(os_obj.queue_handle->entry)
{
len = rt_mq_recv(os_obj.queue_handle, (void*) &peek_queue, os_obj.queue_handle->msg_size, (rt_int32_t) ((rt_int64_t)THREAD_WAIT_TIME * RT_TICK_PER_SECOND / 1000));
if(len != 0)
{
#if defined(PRINT_COMMAND_BUFFER)
int i = 0;
for(i=0;i < (peek_queue->cmd_size + 3) / 4; i++)
{
if(i % 4 == 0)
printf("\r\n");
printf("0x%08x ",((uint32_t*)(peek_queue->cmd_physical + peek_queue->cmd_offset))[i]);
}
#endif
vg_lite_hal_poke(VG_LITE_HW_CMDBUF_ADDRESS, peek_queue->cmd_physical + peek_queue->cmd_offset);
vg_lite_hal_poke(VG_LITE_HW_CMDBUF_SIZE, (peek_queue->cmd_size +7)/8 );
if(vg_lite_hal_wait_interrupt(ISR_WAIT_TIME, (uint32_t)~0, &even_got))
peek_queue->event->signal = VG_LITE_HW_FINISHED;
else
#if defined(PRINT_DEBUG_REGISTER)
{
unsigned int debug;
unsigned int iter;
for(iter =0; iter < 16 ; iter ++)
{
vg_lite_hal_poke(0x470, iter);
debug = vg_lite_hal_peek(0x450);
printf("0x450[%d] = 0x%x\n", iter,debug);
}
for(iter =0; iter < 16 ; iter ++)
{
vg_lite_hal_poke(0x470, iter <<16);
debug = vg_lite_hal_peek(0x454);
printf("0x454[%d] = 0x%x\n", iter,debug);
}
for(iter =0; iter < 16 ; iter ++)
{
vg_lite_hal_poke(0x478, iter);
debug = vg_lite_hal_peek(0x468);
printf("0x468[%d] = 0x%x\n", iter,debug);
}
for(iter =0; iter < 16 ; iter ++)
{
vg_lite_hal_poke(0x478, iter);
debug = vg_lite_hal_peek(0x46C);
printf("0x46C[%d] = 0x%x\n", iter,debug);
}
#endif
/* wait timeout */
peek_queue->event->signal = VG_LITE_IDLE;
#if defined(PRINT_DEBUG_REGISTER)
}
#endif
if(semaphore[peek_queue->event->semaphore_id]){
rt_sem_release(semaphore[peek_queue->event->semaphore_id]);
}
vg_lite_os_free((void *) peek_queue);
}
}
}
}
}
int32_t vg_lite_os_init_tls_array(void)
{
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_TCB->user_data = (rt_uint32_t) tls_array;
return VG_LITE_SUCCESS;
}
void vg_lite_os_deinit_tls_array(void)
{
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_TCB->user_data = NULL;
}
int32_t vg_lite_os_set_tls(void* tls)
{
if(tls == NULL)
return VG_LITE_INVALID_ARGUMENT;
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
*tls_ptr = (rt_uint32_t) tls;
return VG_LITE_SUCCESS;
}
void * vg_lite_os_get_tls( )
{
rt_thread_t rt_TCB;
void * pvReturn = NULL;
rt_TCB = rt_thread_self();
rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
pvReturn = (void *) (*tls_ptr);
return pvReturn;
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
void * vg_lite_os_malloc(uint32_t size)
{
return rt_malloc((rt_size_t)size);
}
void vg_lite_os_free(void * memory)
{
rt_free(memory);
}
#if !defined(VG_DRIVER_SINGLE_THREAD)
void vg_lite_os_reset_tls()
{
rt_thread_t rt_TCB;
rt_TCB = rt_thread_self();
RT_ASSERT( rt_TCB != NULL );
rt_uint32_t * tls_ptr = (rt_uint32_t *) rt_TCB->user_data;
*tls_ptr = NULL;
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
void vg_lite_os_sleep(uint32_t msec)
{
rt_thread_mdelay(msec);
}
int32_t vg_lite_os_initialize(void)
{
#if !defined(VG_DRIVER_SINGLE_THREAD)
static int task_number = 0;
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
int_queue = rt_sem_create("iq", 0, RT_IPC_FLAG_PRIO);
int_flags = 0;
#if !defined(VG_DRIVER_SINGLE_THREAD)
if(mutex == NULL)
{
mutex = rt_mutex_create("mut", RT_IPC_FLAG_PRIO);
if(mutex == NULL)
return VG_LITE_MULTI_THREAD_FAIL;
}
if(task_number == 0)
{
if(rt_mutex_take(mutex, (rt_int32_t) ((rt_int64_t)THREAD_WAIT_TIME * RT_TICK_PER_SECOND / 1000)) == RT_EOK)
{
if(os_obj.task_hanlde == NULL)
{
os_obj.task_hanlde = rt_thread_create(QUEUE_THREAD_NAME, command_queue, NULL, QUEUE_THREAD_SIZE, QUEUE_THREAD_PRIO, 1);
if(os_obj.task_hanlde == RT_NULL)
{
/* command queue task create fail */
rt_mutex_release(mutex);
return VG_LITE_MULTI_THREAD_FAIL;
}
else
rt_thread_startup(os_obj.task_hanlde);
}
task_number++;
rt_mutex_release(mutex);
return VG_LITE_SUCCESS;
}
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
return VG_LITE_SUCCESS;
}
void vg_lite_os_deinitialize(void)
{
/* TODO: Remove clock. */
#if !defined(VG_DRIVER_SINGLE_THREAD)
rt_mutex_delete(mutex);
mutex = 0;
#endif /* VG_DRIVER_SINGLE_THREAD */
rt_sem_delete(int_queue);
/* TODO: Remove power. */
}
#if !defined(VG_DRIVER_SINGLE_THREAD)
int32_t vg_lite_os_lock()
{
if(mutex == NULL)
return VG_LITE_NOT_SUPPORT;
if(rt_mutex_take(mutex, (rt_int32_t) ((rt_int64_t)MAX_MUTEX_TIME * RT_TICK_PER_SECOND / 1000)) != RT_EOK)
return VG_LITE_MULTI_THREAD_FAIL;
return VG_LITE_SUCCESS;
}
int32_t vg_lite_os_unlock()
{
if(rt_mutex_release(mutex) != RT_EOK)
return VG_LITE_MULTI_THREAD_FAIL;
return VG_LITE_SUCCESS;
}
int32_t vg_lite_os_submit(uint32_t context, uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event)
{
vg_lite_queue_t* queue_node;
if(os_obj.queue_handle == RT_NULL)
return VG_LITE_NOT_SUPPORT;
queue_node = (vg_lite_queue_t*) vg_lite_os_malloc(sizeof(vg_lite_queue_t));
if(queue_node == NULL)
return VG_LITE_MULTI_THREAD_FAIL;
queue_node->cmd_physical = physical;
queue_node->cmd_offset = offset;
queue_node->cmd_size = size;
queue_node->event = event;
/* Current command buffer has been sent to the command queue. */
event->signal = VG_LITE_IN_QUEUE;
if(rt_mq_send_wait(os_obj.queue_handle, (void *) &queue_node, os_obj.queue_handle->msg_size, (rt_int32_t) ((rt_int64_t)ISR_WAIT_TIME * RT_TICK_PER_SECOND / 1000)) != RT_EOK)
return VG_LITE_MULTI_THREAD_FAIL;
curContext = context;
if (vg_lite_os_wait_event(event) == VG_LITE_SUCCESS) {
if(rt_sem_release(command_semaphore) != RT_EOK)
return VG_LITE_MULTI_THREAD_FAIL;
return VG_LITE_SUCCESS;
}
return VG_LITE_MULTI_THREAD_FAIL;
}
int32_t vg_lite_os_wait(uint32_t timeout, vg_lite_os_async_event_t *event)
{
if (semaphore[event->semaphore_id]) {
if (rt_sem_take(semaphore[event->semaphore_id], RT_WAITING_FOREVER) == RT_EOK) {
if(event->signal == VG_LITE_HW_FINISHED){
rt_sem_release(semaphore[event->semaphore_id]);
return VG_LITE_SUCCESS;
}
else{
rt_sem_release(semaphore[event->semaphore_id]);
return VG_LITE_TIMEOUT;
}
}
}
return VG_LITE_TIMEOUT;
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
void vg_lite_os_IRQHandler(void)
{
uint32_t flags = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
if (flags) {
/* Combine with current interrupt flags. */
int_flags |= flags;
/* Wake up any waiters. */
if(int_queue){
rt_sem_release(int_queue);
}
}
}
int32_t vg_lite_os_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value)
{
#if _BAREMETAL
uint32_t int_status=0;
int_status = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
(void)value;
while (int_status==0){
int_status = vg_lite_hal_peek(VG_LITE_INTR_STATUS);
usleep(1);
}
if (IS_AXI_BUS_ERR(*value))
{
vg_lite_bus_error_handler();
}
return 1;
#else /*for rt500*/
if(int_queue) {
if (rt_sem_take(int_queue, (rt_int32_t) ((rt_int64_t)timeout * RT_TICK_PER_SECOND / 1000)) == RT_EOK) {
if (value != NULL) {
*value = int_flags & mask;
if (IS_AXI_BUS_ERR(*value))
{
vg_lite_bus_error_handler();
}
}
int_flags = 0;
return 1;
}
}
return 0;
#endif
}
#if !defined(VG_DRIVER_SINGLE_THREAD)
int32_t vg_lite_os_init_event(vg_lite_os_async_event_t *event,
uint32_t semaphore_id,
int32_t state)
{
if (event->semaphore_id >= THREAD_LENGTH)
return VG_LITE_INVALID_ARGUMENT;
if (semaphore[semaphore_id])
return VG_LITE_ALREADY_EXISTS;
char name[RT_NAME_MAX] = {0};
rt_snprintf(name, RT_NAME_MAX, "s%d", semaphore_id);
semaphore[semaphore_id] = rt_sem_create(name, 0, RT_IPC_FLAG_PRIO);
if (!semaphore[semaphore_id])
return VG_LITE_OUT_OF_MEMORY;
rt_sem_release(semaphore[semaphore_id]);
event->semaphore_id = semaphore_id;
event->signal = state;
return VG_LITE_SUCCESS;
}
int32_t vg_lite_os_delete_event(vg_lite_os_async_event_t *event)
{
if (event->semaphore_id >= THREAD_LENGTH)
return VG_LITE_INVALID_ARGUMENT;
if (semaphore[event->semaphore_id]){
rt_sem_delete(semaphore[event->semaphore_id]);
semaphore[event->semaphore_id] = NULL;
}
return VG_LITE_SUCCESS;
}
int32_t vg_lite_os_wait_event(vg_lite_os_async_event_t *event)
{
if (event->semaphore_id >= THREAD_LENGTH)
return VG_LITE_INVALID_ARGUMENT;
if (rt_sem_take(semaphore[event->semaphore_id], RT_WAITING_FOREVER) != RT_EOK)
return VG_LITE_MULTI_THREAD_FAIL;
return VG_LITE_SUCCESS;
}
int32_t vg_lite_os_signal_event(vg_lite_os_async_event_t *event)
{
if (event->semaphore_id >= THREAD_LENGTH)
return VG_LITE_INVALID_ARGUMENT;
rt_sem_release(semaphore[event->semaphore_id]);
return VG_LITE_SUCCESS;
}
int8_t vg_lite_os_query_context_switch(uint32_t context)
{
if(!curContext || curContext == context)
return FALSE;
return TURE;
}
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */

View File

@ -0,0 +1,134 @@
#ifndef _VG_LITE_OS_H
#define _VG_LITE_OS_H
#include <stdint.h>
#if !defined(VG_DRIVER_SINGLE_THREAD)
#define vg_lite_os_set_event_state(event, state) (event)->signal = state
#define vg_lite_os_event_state(event) (event)->signal
#define vg_lite_os_config_event(event, sem_id, state) \
{ \
(event)->semaphore_id = sem_id; \
(event)->signal = state; \
}
typedef struct vg_lite_os_async_event
{
uint32_t semaphore_id; /*! The Id of the semaphore assigned to this event */
int32_t signal; /*! The command buffer status */
}
vg_lite_os_async_event_t;
int32_t vg_lite_os_init_tls_array(void);
void vg_lite_os_deinit_tls_array(void);
/*!
@brief Set the value in a tasks thread local storage array.
*/
int32_t vg_lite_os_set_tls(void* tls);
/*!
@brief Get the current tasks thread local storage array.
*/
void * vg_lite_os_get_tls( );
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/*!
@brief Memory allocate.
*/
void * vg_lite_os_malloc(uint32_t size);
/*!
@brief Memory free.
*/
void vg_lite_os_free(void * memory);
#if !defined(VG_DRIVER_SINGLE_THREAD)
/*!
@brief Reset the value in a tasks thread local storage array.
*/
void vg_lite_os_reset_tls();
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/*!
@brief sleep a number of milliseconds.
*/
void vg_lite_os_sleep(uint32_t msec);
/*!
@brief initialize the os parameters.
*/
int32_t vg_lite_os_initialize();
/*!
@brief deinitialize the os parameters.
*/
void vg_lite_os_deinitialize();
#if !defined(VG_DRIVER_SINGLE_THREAD)
/*!
@brief Mutex semaphore take.
*/
int32_t vg_lite_os_lock();
/*!
@brief Mutex semaphore give.
*/
int32_t vg_lite_os_unlock();
/*!
@brief Submit the current command buffer to the command queue.
*/
int32_t vg_lite_os_submit(uint32_t context, uint32_t physical, uint32_t offset, uint32_t size, vg_lite_os_async_event_t *event);
/*!
@brief Wait for the current command buffer to be executed.
*/
int32_t vg_lite_os_wait(uint32_t timeout, vg_lite_os_async_event_t *event);
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
/*!
@brief IRQ Handler.
*/
void vg_lite_os_IRQHandler(void);
/*!
@brief Wait until an interrupt from the VGLite graphics hardware has been received.
*/
int32_t vg_lite_os_wait_interrupt(uint32_t timeout, uint32_t mask, uint32_t * value);
#if !defined(VG_DRIVER_SINGLE_THREAD)
/*!
@brief
*/
int32_t vg_lite_os_init_event(vg_lite_os_async_event_t *event,
uint32_t semaphore_id,
int32_t state);
/*!
@brief
*/
int32_t vg_lite_os_delete_event(vg_lite_os_async_event_t *event);
/*!
@brief
*/
int32_t vg_lite_os_wait_event(vg_lite_os_async_event_t *event);
/*!
@brief
*/
int32_t vg_lite_os_signal_event(vg_lite_os_async_event_t *event);
/*!
@brief
*/
int8_t vg_lite_os_query_context_switch(uint32_t context);
#endif /* not defined(VG_DRIVER_SINGLE_THREAD) */
#endif

View File

@ -0,0 +1,353 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2012 - 2020 Vivante Corporation, Santa Clara, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "vg_lite.h"
vg_lite_error_t vg_lite_upload_path(vg_lite_path_t * path)
{
uint32_t bytes;
vg_lite_buffer_t Buf, *buffer;
buffer = &Buf;
/* Compute the number of bytes required for path + command buffer prefix/postfix. */
bytes = (8 + path->path_length + 7 + 8) & ~7;
/* Allocate GPU memory. */
buffer->width = bytes;
buffer->height = 1;
buffer->stride = 0;
buffer->format = VG_LITE_A8;
if (vg_lite_allocate(buffer) != VG_LITE_SUCCESS) {
return VG_LITE_OUT_OF_MEMORY;
}
/* Initialize command buffer prefix. */
((uint32_t *) buffer->memory)[0] = 0x40000000 | ((path->path_length + 7) / 8);
((uint32_t *) buffer->memory)[1] = 0;
/* Copy the path data. */
memcpy((uint32_t *) buffer->memory + 2, path->path, path->path_length);
/* Initialize command buffer postfix. */
((uint32_t *) buffer->memory)[bytes / 4 - 2] = 0x70000000;
((uint32_t *) buffer->memory)[bytes / 4 - 1] = 0;
/* Mark path as uploaded. */
path->uploaded.handle = buffer->handle;
path->uploaded.address = buffer->address;
path->uploaded.memory = buffer->memory;
path->uploaded.bytes = bytes;
path->path_changed = 0;
VLM_PATH_ENABLE_UPLOAD(*path); /* Implicitly enable path uploading. */
/* Return pointer to vg_lite_buffer structure. */
return VG_LITE_SUCCESS;
}
/* Path data operations. */
#define CDALIGN(value, by) (((value) + (by) - 1) & ~((by) - 1))
#define CDMIN(x, y) ((x) > (y) ? (y) : (x))
#define CDMAX(x, y) ((x) > (y) ? (x) : (y))
static int32_t get_data_count(uint8_t cmd)
{
static int32_t count[] = {
0,
0,
2,
2,
2,
2,
4,
4,
6,
6,
5,
5,
5,
5,
5,
5,
5,
5
};
if (cmd > VLC_OP_LCWARC_REL) {
return -1;
}
else {
return count[cmd];
}
}
static void compute_pathbounds(float *xmin, float *ymin, float *xmax, float *ymax, float x, float y)
{
if (xmin != NULL)
{
*xmin = *xmin < x ? *xmin : x;
}
if (xmax != NULL)
{
*xmax = *xmax > x ? *xmax : x;
}
if (ymin != NULL)
{
*ymin = *ymin < y ? *ymin : y;
}
if (ymax != NULL)
{
*ymax = *ymax > y ? *ymax : y;
}
}
static int32_t get_data_size(vg_lite_format_t format)
{
int32_t data_size = 0;
switch (format) {
case VG_LITE_S8:
data_size = sizeof(int8_t);
break;
case VG_LITE_S16:
data_size = sizeof(int16_t);
break;
case VG_LITE_S32:
data_size = sizeof(int32_t);
break;
default:
data_size = sizeof(vg_lite_float_t);
break;
}
return data_size;
}
int32_t vg_lite_path_calc_length(uint8_t *cmd, uint32_t count, vg_lite_format_t format)
{
int32_t size = 0;
int32_t dCount = 0;
uint32_t i = 0;
int32_t data_size = 0;
data_size = get_data_size(format);
for (i = 0; i < count; i++) {
size++; /* OP CODE. */
dCount = get_data_count(cmd[i]);
if (dCount > 0) {
size = CDALIGN(size, data_size);
size += dCount * data_size;
}
}
return size;
}
vg_lite_error_t vg_lite_path_append(vg_lite_path_t *path,
uint8_t *cmd,
void *data,
uint32_t seg_count)
{
vg_lite_error_t error = VG_LITE_SUCCESS;
uint32_t i;
int32_t j;
int32_t offset = 0;
int32_t dataCount = 0;
float *dataf = (float*) data;
float *pathf = NULL;
int32_t *data_s32 = (int32_t*) data;
int32_t *path_s32 = NULL;
int16_t *data_s16 = (int16_t*) data;
int16_t *path_s16 = NULL;
int8_t *data_s8 = (int8_t*) data;
int8_t *path_s8 = NULL;
uint8_t *pathc = NULL;
int32_t data_size;
uint8_t arc_path = 0;
float px = 0.0f, py = 0.0f, cx = 0.0f, cy = 0.0f;
int rel = 0;
if(cmd == NULL || data == NULL || path == NULL || path->path == NULL)
return VG_LITE_INVALID_ARGUMENT;
for(i = 0; i < seg_count; i++) {
if(cmd[i] > VLC_OP_LCWARC_REL)
return VG_LITE_INVALID_ARGUMENT;
}
data_size = get_data_size(path->format);
path->path_changed= 1;
pathf = (float *)path->path;
path_s32 = (int32_t *)path->path;
path_s16 = (int16_t *)path->path;
path_s8 = (int8_t *)path->path;
pathc = (uint8_t *)path->path;
/* Loop to fill path data. */
for (i = 0; i < seg_count; i++) {
*(pathc + offset) = cmd[i];
offset++;
dataCount = get_data_count(cmd[i]);
if (dataCount > 0) {
offset = CDALIGN(offset, data_size);
if ((cmd[i] > VLC_OP_CLOSE) &&
((cmd[i] & 0x01) == 1)){
rel = 1;
}
else {
rel = 0;
}
if(cmd[i] < VLC_OP_SCCWARC) {
for (j = 0; j < dataCount / 2; j++) {
switch (path->format) {
case VG_LITE_S8:
path_s8 = (int8_t *)(pathc + offset);
path_s8[j * 2] = *data_s8++;
path_s8[j * 2 + 1] = *data_s8++;
if (rel) {
cx = px + path_s8[j * 2];
cy = py + path_s8[j * 2 + 1];
}
else {
cx = path_s8[j * 2];
cy = path_s8[j * 2 + 1];
}
break;
case VG_LITE_S16:
path_s16 = (int16_t *)(pathc + offset);
path_s16[j * 2] = *data_s16++;
path_s16[j * 2 + 1] = *data_s16++;
if (rel) {
cx = px + path_s16[j * 2];
cy = py + path_s16[j * 2 + 1];
}
else {
cx = path_s16[j * 2];
cy = path_s16[j * 2 + 1];
}
break;
case VG_LITE_S32:
path_s32 = (int32_t *)(pathc + offset);
path_s32[j * 2] = *data_s32++;
path_s32[j * 2 + 1] = *data_s32++;
if (rel) {
cx = px + path_s32[j * 2];
cy = py + path_s32[j * 2 + 1];
}
else {
cx = path_s32[j * 2];
cy = path_s32[j * 2 + 1];
}
break;
case VG_LITE_FP32:
pathf = (float *)(pathc + offset);
pathf[j * 2] = *dataf++;
pathf[j * 2 + 1] = *dataf++;
if (rel) {
cx = px + pathf[j * 2];
cy = py + pathf[j * 2 + 1];
}
else {
cx = pathf[j * 2];
cy = pathf[j * 2 + 1];
}
break;
default:
return VG_LITE_INVALID_ARGUMENT;
}
/* Update path bounds. */
path->bounding_box[0] = CDMIN(path->bounding_box[0], cx);
path->bounding_box[2] = CDMAX(path->bounding_box[2], cx);
path->bounding_box[1] = CDMIN(path->bounding_box[1], cy);
path->bounding_box[3] = CDMAX(path->bounding_box[3], cy);
}
}
else {
arc_path = 1;
pathf = (float *)(pathc + offset);
pathf[0] = *dataf++;
pathf[1] = *dataf++;
pathf[2] = *dataf++;
pathf[3] = *dataf++;
pathf[4] = *dataf++;
if (rel) {
cx = px + pathf[3];
cy = py + pathf[4];
}
else {
cx = pathf[3];
cy = pathf[4];
}
/* Update path bounds. */
compute_pathbounds(&path->bounding_box[0], &path->bounding_box[1], &path->bounding_box[2], &path->bounding_box[3],cx + 2 * pathf[0],cy + 2 * pathf[1]);
compute_pathbounds(&path->bounding_box[0], &path->bounding_box[1], &path->bounding_box[2], &path->bounding_box[3],px + 2 * pathf[1],py + 2 * pathf[1]);
compute_pathbounds(&path->bounding_box[0], &path->bounding_box[1], &path->bounding_box[2], &path->bounding_box[3],cx - 2 * pathf[0],cy - 2 * pathf[1]);
compute_pathbounds(&path->bounding_box[0], &path->bounding_box[1], &path->bounding_box[2], &path->bounding_box[3],px - 2 * pathf[1],py - 2 * pathf[1]);
}
px = cx;
py = cy;
offset += dataCount * data_size;
}
}
path->path_length = offset;
if(arc_path) {
error = vg_lite_init_arc_path(path,
VG_LITE_FP32,
path->quality,
path->path_length,
path->path,
path->bounding_box[0], path->bounding_box[1],
path->bounding_box[2], path->bounding_box[3]);
}
return error;
}

View File

@ -0,0 +1,48 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2020 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _VG_LITE_PLATFORM_H
#define _VG_LITE_PLATFORM_H
#include "stdint.h"
#include "stdlib.h"
#define _BAREMETAL 0
/*!
@brief Initialize the hardware mem setting.
*/
void vg_lite_init_mem(uint32_t register_mem_base,
uint32_t gpu_mem_base,
volatile void * contiguous_mem_base,
uint32_t contiguous_mem_size);
/*!
@brief The hardware IRQ handler.
*/
void vg_lite_IRQHandler(void);
#endif

View File

@ -0,0 +1,359 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/** Include Files */
#include "vg_lite.h"
#include "vg_lite_text.h"
#include <stdio.h>
#include <string.h>
#include <mcufont.h>
#include "vft_draw.h"
/** Macros */
/** Data structures */
typedef struct {
/* Font related parameters */
vg_lite_font_attributes_t *attributes;
vg_lite_buffer_t buffer;
uint16_t width;
uint16_t height;
uint16_t y;
const struct mf_font_s *rcd_font;
} text_context_t;
/** Internal or external API prototypes */
struct mf_font_s *_vg_lite_get_raster_font(vg_lite_font_t font_idx);
int vg_lite_is_font_valid(vg_lite_font_t font);
/** Globals */
vg_lite_font_attributes_t g_font_attribs;
vg_lite_font_t g_last_font = VG_LITE_INVALID_FONT;
int g_last_font_attrib_idx;
/** Externs if any */
/* Capture unique values of alpha */
static unsigned int g_index_table[257];
/* text_color is in ARGB8888 format */
int init_256pallet_color_table(unsigned int bg_color, unsigned int fg_color)
{
int i;
g_index_table[0] = 0; /* Background color */
int fg_r = ((fg_color>>0)&0xff);
int fg_g = ((fg_color>>8)&0xff);
int fg_b = ((fg_color>>16)&0xff);
int bg_r = ((bg_color>>0)&0xff);
int bg_g = ((bg_color>>8)&0xff);
int bg_b = ((bg_color>>16)&0xff);
for (i=1; i<256; i++) {
int r, g, b;
int a = 0xff;
register int mult, mult2;
mult = ((i*1024)/256);
mult2 = (((256-i)*1024)/256);
/* Blend with white bg */
r = ( ((bg_r * mult2)>>10) +((fg_r * mult)>>10) );
g = ( ((bg_g * mult2)>>10) +((fg_g * mult)>>10) );
b = ( ((bg_b * mult2)>>10) +((fg_b * mult)>>10) );
g_index_table[i] = ((a) + (r<<8) + (g<<16)+(b<<24));
}
return 0;
}
/* Callback to write to a memory buffer. */
static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
void *state)
{
text_context_t *s = (text_context_t*)state;
uint32_t pos;
uint32_t value;
uint32_t *raw_pixel_buffer = (uint32_t *)s->buffer.memory;
int stride = s->buffer.stride;
if (y < 0 || y >= s->height) return;
if (x < 0 || x + count >= s->width) return;
while (count--)
{
pos = (uint32_t)stride * y + x;
value = g_index_table[alpha];
raw_pixel_buffer[pos] = value;
x++;
}
}
/* Callback to render characters. */
static uint8_t character_callback(int16_t x, int16_t y, mf_char character,
void *state)
{
text_context_t *s = (text_context_t*)state;
return mf_render_character(s->rcd_font, x, y, character, pixel_callback, state);
}
/* Callback to render lines. */
static bool line_callback(const char *line, uint16_t count, void *state)
{
text_context_t *s = (text_context_t*)state;
if (s->attributes->justify)
{
mf_render_justified(s->rcd_font, s->attributes->anchor, s->y,
s->width - s->attributes->margin * 2,
line, count, character_callback, state);
}
else
{
mf_render_aligned(s->rcd_font, s->attributes->anchor, s->y,
(enum mf_align_t)s->attributes->alignment, line, count,
character_callback, state);
}
s->y += s->rcd_font->line_height;
return true;
}
/* Callback to just count the lines.
* Used to decide the image height */
bool count_lines(const char *line, uint16_t count, void *state)
{
int *linecount = (int*)state;
(*linecount)++;
return true;
}
vg_lite_error_t alloc_font_buffer(vg_lite_buffer_t *buffer, int width , int height)
{
vg_lite_error_t error;
/* Align width to 16 pixels, heigh to 16 pixels */
width = ((width+15)&(~15));
height = ((height+15)&(~15));
/* Allocate memory from VGLITE space */
buffer->width = width;
buffer->height = height;
buffer->format = VG_LITE_ARGB8888;
buffer->stride = 0;
error = vg_lite_allocate(buffer);
buffer->stride = width;
buffer->tiled = VG_LITE_LINEAR;
return error;
}
static vg_lite_error_t free_font_buffer(vg_lite_buffer_t *buffer)
{
vg_lite_error_t error;
error = vg_lite_free(buffer);
return error;
}
void matrix_multiply(vg_lite_matrix_t * matrix, vg_lite_matrix_t * mult)
{
vg_lite_matrix_t temp;
int row, column;
/* Process all rows. */
for (row = 0; row < 3; row++) {
/* Process all columns. */
for (column = 0; column < 3; column++) {
/* Compute matrix entry. */
temp.m[row][column] = (matrix->m[row][0] * mult->m[0][column])
+ (matrix->m[row][1] * mult->m[1][column])
+ (matrix->m[row][2] * mult->m[2][column]);
}
}
/* Copy temporary matrix into result. */
memcpy(matrix, &temp, sizeof(temp));
}
vg_lite_error_t vg_lite_draw_text(vg_lite_buffer_t *target,
char *text,
vg_lite_font_t font,
int x,
int y,
vg_lite_matrix_t *matrix,
vg_lite_blend_t blend,
vg_lite_font_attributes_t *attributes)
{
vg_lite_error_t error;
int height;
text_context_t ctx_text;
vg_lite_matrix_t m_text;
int text_img_size = 0;
font_face_desc_t* font_face = NULL;
int text_width_in_pixels = 0;
int tmpX;
memset(&ctx_text, 0, sizeof(ctx_text));
ctx_text.attributes = attributes;
if ( vg_lite_is_font_valid(font) != 0 ) {
return VG_LITE_INVALID_ARGUMENT;
}
error = vg_lite_load_font_data(font,
attributes->font_height);
if ( error != 0 ) {
return VG_LITE_INVALID_ARGUMENT;
}
if(attributes->tspan_has_dx_dy != 0)
{
if ( x < 0 )
x = attributes->last_x + attributes->last_dx;
if ( y < 0 )
y = attributes->last_y;
}
// Dynamic decision
if ( attributes->is_vector_font == 0 ) {
init_256pallet_color_table(attributes->bg_color, attributes->text_color);
/* Application specifies actual font by reading proper rcd file */
ctx_text.rcd_font = _vg_lite_get_raster_font(font);
/* Count number of lines to decide font buffer size. */
height = 0;
mf_text_draw_area(ctx_text.rcd_font, attributes->width - 2 * attributes->margin,
text, &height, &text_width_in_pixels);
height *= attributes->font_height;
height += 4;
if( attributes->tspan_has_dx_dy == 0) {
y -= attributes->font_height;
}
tmpX = x;
if(attributes->alignment == eTextAlignCenter) {
tmpX -= text_width_in_pixels/2;
} else if(attributes->alignment == eTextAlignRight) {
tmpX -= text_width_in_pixels;
}
/* Manually calculate X-offset for text-alignemnt; mcufont just
* doesn't render half part(left-part) for center alignment and
* full string skipped for right-alignment, So again set it to
* left-alignment for font-attrib, as offsets are already
* calculated and alignment handled in other way */
attributes->alignment = 0;
/* Allocate and initialize vg_lite_buffer that can hold font text
* Note: ctx_text.width and ctx_text.height get used by internal
* state of MF rendering engine. Based on amount of text to render
* This buffer gets allocated, and buffer width gets aligned to
* 16 pixel boundary
*/
ctx_text.width = attributes->width;
/* Memory optimization */
ctx_text.width = text_width_in_pixels;
/* Align width to 16 pixel boundary */
if (ctx_text.width & 15) {
ctx_text.width += 15;
ctx_text.width &= (~15);
}
ctx_text.height = height;
error = alloc_font_buffer(&ctx_text.buffer, ctx_text.width, ctx_text.height);
if ( error != VG_LITE_SUCCESS) {
printf("WARNING: alloc_font_buffer failed(%d).\r\n",error);
}
ctx_text.y = 2;
/* Initialize vg_lite buffer with transperant color */
/* Due to alignment requirement of vg_lite, font buffer can be larger */
if ( ctx_text.buffer.format == VG_LITE_ARGB8888 )
text_img_size = ctx_text.buffer.width * ctx_text.buffer.height * 4;
else
text_img_size = ctx_text.buffer.width * ctx_text.buffer.height;
memset(ctx_text.buffer.memory, 0,
text_img_size);
/* Render font text into vg_lite_buffer */
mf_wordwrap(ctx_text.rcd_font, attributes->width - 2 * attributes->margin,
text, line_callback, &ctx_text);
/* Draw font bitmap on render target */
vg_lite_identity(&m_text);
matrix_multiply(&m_text, matrix);
vg_lite_translate(x, y, &m_text);
vg_lite_scale(1.0, 1.0, &m_text);
if ( ctx_text.buffer.format == VG_LITE_ARGB8888 )
ctx_text.buffer.stride = ctx_text.width*4;
error = vg_lite_blit(target, &ctx_text.buffer, &m_text, blend,
0, VG_LITE_FILTER_POINT);
if ( error != VG_LITE_SUCCESS) {
printf("WARNING: vg_lite_blit failed(%d).\r\n",error);
}
error = vg_lite_finish();
if ( error != VG_LITE_SUCCESS) {
printf("WARNING: vg_lite_finish failed(%d).\r\n",error);
}
error = free_font_buffer(&ctx_text.buffer);
if ( error != VG_LITE_SUCCESS) {
printf("WARNING: vg_lite_finish failed(%d).\r\n",error);
}
attributes->last_dx = text_width_in_pixels;
} else {
error = (vg_lite_error_t)vg_lite_vtf_draw_text(target,
x, y,
blend,
font,
matrix,
attributes,
text);
/* Note: vg_lite_vtf_draw_text updates attributes->last_dx internally
This assignment is just to keep code similar to rcd code */
attributes->last_dx = attributes->last_dx;
error = vg_lite_finish();
if ( error != VG_LITE_SUCCESS) {
printf("WARNING: vg_lite_finish failed(%d).\r\n",error);
}
vft_unload(font_face);
}
attributes->last_x = x;
attributes->last_y = y;
return error;
}

View File

@ -0,0 +1,372 @@
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright 2020 NXP
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject
* to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#ifndef _vg_lite_text_h_
#define _vg_lite_text_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "vg_lite.h"
/* Macros *********************************************************************/
#define MAX_FONT_NAME_LEN (64)
#define VG_LITE_INVALID_FONT (-1)
#define INVALID_FONT_PROPERTY_IDX (-1)
/* Types **********************************************************************/
/*!
@abstract Font Type enumeration
@discussion
This enumeration defines supported high level font type type.
*/
typedef enum eFontType {
eFontTypeVector,
eFontTypeRaster
} eFontType_t;
/*!
@abstract Font weight enumeration
@discussion
This enumeration defines font weight that maps to css specification
*/
typedef enum eFontWeight {
eFontWeightThin = 100, /*! Thin, Hairline, Ultra-light, Extra-light */
eFontWeightLight = 200, /*! Light */
eFontWeightBook = 300, /*! Book */
eFontWeightRegular = 400, /*! Regular, Normal, Plain, Roman, Standard */
eFontWeightMedium = 500, /*! Medium */
eFontWeightSemiBold = 600, /*! Semi-bold, Demi-bold */
eFontWeightBold = 700, /*! Bold */
eFontWeightHeavy = 800, /*! Heavy, Black, Extra-bold */
eFontUltraBlack = 900, /*! Ultra-black, Extra-black, Ultra-bold,
Heavy-black, Fat, Poster */
} eFontWeight_t;
/*!
@abstract Font stretch enumeration
@discussion
This enumeration defines font stretch that maps to css specification
*/
typedef enum eFontStretch {
eFontStretchUltraCondensed = 1, /*! ultra-condensed */
eFontStretchExtraCondensed = 2, /*! extra-condensed */
eFontStretchCondensed = 3, /*! condensed */
eFontStretchSemiCondensed = 4, /*! semi-condensed */
eFontStretchNormal = 5, /*! normal */
eFontStretchSemiExpanded = 6, /*! semi-expanded */
eFontStretchExpanded = 7, /*! expanded */
eFontStretchExtraExpanded = 8, /*! extra-expanded */
eFontStretchUltraExpanded = 9, /*! ultra-expanded */
} eFontStretch_t;
/*!
@abstract Font style enumeration
@discussion
This enumeration defines font style that maps to css specification
*/
typedef enum eFontStyle {
eFontStyleNormal = 1, /*! normal */
eFontStyleItalic = 2, /*! italic, oblique */
} eFontStyle_t;
/*!
@abstract Text alignment enumeration
@discussion
This enumeration defines text alignment that maps to css specification
*/
typedef enum eTextAlign {
eTextAlignLeft,
eTextAlignCenter,
eTextAlignRight,
eTextAlignJustify,
} eTextAlign_t;
/* Structures *****************************************************************/
/*!
@abstract Font parameters
@discussion
This datastructure specifies application font and its data. Application
can register as many font as required using vg_lite_register_font
And lateron refer them in vg_lite_draw_text API
for raster fonts mandatory fields are:
name,
font_weight, font_stretch, font_style, font_height
data, data_len
for vector fonts mandatory fields are:
name,
data, data_len
*/
typedef struct vg_lite_font_params
{
char name[MAX_FONT_NAME_LEN]; /*! font-family name */
eFontType_t font_type; /*! Raster/Vector font */
eFontWeight_t font_weight; /*! Font weight enum value */
eFontStretch_t font_stretch; /*! Font stretch enum value */
eFontStyle_t font_style; /*! Font style enum value */
int font_height; /*! Font height in pixels */
int data_len; /*! Font data buffer length */
void *data; /*! the address where the actual font data is stored; it is the
* responsibility of the user/application to load it there */
} vg_lite_font_params_t;
/*!
@abstract Opaque type for font descriptor
@discussion
This is an index of into font-table. Font table can have atmost
MAX_SYSTEM_FONTS font, registering more font results in an error.
*/
typedef uint32_t vg_lite_font_t;
/*!
@abstract Runtime parameter to render text using given font
@discussion
These parameters controls rendering of text using given font.
*/
typedef struct {
/* Application controllable parameters */
int justify; /*! Equal justify given text in text display area */
int alignment; /*! Ailgn text to left, center or right */
int width; /*! Internal variable computed based on active font */
int height; /*! Internal variable computed based on active font */
unsigned int text_color; /*! Foreground text color */
unsigned int bg_color; /*! Background text color */
int tspan_has_dx_dy; /*! 0 means tspan element has x,y values
1 means tspan element has dx, dy values
so use last_x+dx for x,
last_y+dy for y
*/
int is_vector_font; /*! 1 when active font is vector font, 0 otherwise */
int margin; /*! Left and right margin in pixels that should be skipped
by text rendering engine */
int anchor; /*! Anchor text */
int scale; /*! Flag that indicate if text rendering engine should
scale text */
/* Internal parameters of text rendering engine.
Application code should not modify these parameters
*/
int font_height; /*! Font height in pixels, parameter from svg */
int last_x; /*! Last x position of text element */
int last_y; /*! Last y position of text element */
int last_dx; /*! Horizontal width of text in pixels, for last text */
} vg_lite_font_attributes_t;
/* API Function prototypes ****************************************************/
/*!
@abstract Registers application specific font in vg_ltie driver.
@discussion
Using <code>vg_lite_register_font</code> application can register active
fonts that <code>vg_lite_draw_text</code> uses to render text.
for raster fonts mandatory fields of <code>vg_lite_font_params_t</code> are:
name,
font_weight, font_stretch, font_style, font_height
data, data_len
for vector fonts mandatory fields of <code>vg_lite_font_params_t</code> are:
name,
data, data_len
On successful registeration <code>font</code> poiter will get non-negative
application handle.
@param font
Pointer to font handle
@param params
Pointer to font parameters that are used by <code>vg_lite_find_font</code>
to select specific font for rendering text
@result
Returns the status as defined by <code>vg_lite_error_t</code>.
VG_LITE_SUCCESS when font registation is success
VG_LITE_INVALID_ARGUMENT When parameter pointer is invalid
VG_LITE_ALREADY_EXISTS if font name already exists
VG_LITE_OUT_OF_RESOURCES if active font exceeds MAX_SYSTEM_FONTS
*/
vg_lite_error_t vg_lite_register_font(
vg_lite_font_t *font,
vg_lite_font_params_t *params);
/*!
@abstract Un-registers application specific font in vg_ltie driver.
@discussion
<code>vg_lite_unregister_font</code> unregisters application speciific
font form vg_lite driver. This font can not be used lateron by
<code>vg_lite_draw_text</code> API.
@param font
Pointer to font handle
@result
Returns the status as defined by <code>vg_lite_error_t</code>.
VG_LITE_SUCCESS when font registation is success
VG_LITE_INVALID_ARGUMENT if font handle is invalid
*/
vg_lite_error_t vg_lite_unregister_font(vg_lite_font_t font);
/*!
@abstract Check if given font is vector/raster ?
@discussion
<code>vg_lite_is_vector_font</code> API lookups active fonts in
vg_lite driver and if font it found it return 1 if it points to vector font
otherwise it return 0;
@param font
Pointer to font handle
@result
Returns the status as defined by <code>vg_lite_error_t</code>.
VG_LITE_SUCCESS when font registation is success
VG_LITE_INVALID_ARGUMENT if font handle is invalid
*/
int vg_lite_is_vector_font(vg_lite_font_t font);
/*!
@abstract This API renders text with specified font on render target.
@discussion
This API can reder text using user supplied font. Text rendering can be
controlled by <code>vg_lite_font_attributes_t</code>.
@param target
Pointer to render target
@param text
ASCII text that needs to be rendered on render
@param font
Pointer to font handle
@param x
x position in pixels in X-axis for text rendering
@param y
y position in pixels in Y-axis for text rendering
@param matrix
Translation matrix that is used while rendering text.
@attention Scaling and rotation matrix are not supported.
@param blend
Specifies how text gets blened in text area. Typical value is ELM_BLEND_SRC_OVER
@param attributes
Font attributes that controls how text gets rendered in render buffer.
@result
Returns the status as defined by <code>vg_lite_error_t</code>.
VG_LITE_SUCCESS when font registation is success
VG_LITE_INVALID_ARGUMENT if input parameters have any issue
*/
vg_lite_error_t vg_lite_draw_text(
vg_lite_buffer_t *target,
char *text,
vg_lite_font_t font,
int x,
int y,
vg_lite_matrix_t *matrix,
vg_lite_blend_t blend,
vg_lite_font_attributes_t *attributes);
/*!
@abstract This API searches registered font for given name with
requested rendering capabilities.
@discussion
This API searches registered font for given name with
requested rendering capabilities.
for raster fonts following fields are compared
name,
font_weight, font_stretch, font_style, font_height
for vector fonts following fields are compared
name
@param font_name
Font name
@param font_weight
Font weight value from eFontWeight_t
@param font_stretch
Font stretch value from eFontStretch_t
@param font_style
Font style value from eFontStyle_t
@param font_height
Font height in pixels
If during font lookup a validate font is found then it retuns its handle.
@result
Returns valid font handle or an error code.
Valid font handle if input parameters matches any of registerd font.
INVALID_FONT if input parameters don't match registered fonts.
*/
vg_lite_font_t vg_lite_find_font(
char *font_name,
eFontWeight_t font_weight,
eFontStretch_t font_stretch,
eFontStyle_t font_style,
int font_height);
/*!
@abstract Initializes support for text drawing.
*/
void vg_lite_text_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _vg_lite_text_h_ */

View File

@ -0,0 +1,87 @@
/*
* Copyright 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "vglite_support.h"
#include "fsl_clock.h"
#include "vg_lite.h"
#include "vg_lite_platform.h"
#include "display_support.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define MAX_CONTIGUOUS_SIZE 0x200000
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t registerMemBase = 0x41800000;
static uint32_t gpu_mem_base = 0x0;
/*
* In case custom VGLite memory parameters are used, the application needs to
* allocate and publish the VGLite heap base, its size and the size of the
* command buffer(s) using the following global variables:
*/
extern void *vglite_heap_base;
extern uint32_t vglite_heap_size;
#if (CUSTOM_VGLITE_MEMORY_CONFIG == 0)
/* VGLite driver heap */
AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t contiguous_mem[MAX_CONTIGUOUS_SIZE], FRAME_BUFFER_ALIGN);
void *vglite_heap_base = &contiguous_mem;
uint32_t vglite_heap_size = MAX_CONTIGUOUS_SIZE;
#endif /* CUSTOM_VGLITE_MEMORY_CONFIG */
/*******************************************************************************
* Code
******************************************************************************/
void GPU2D_IRQHandler(void)
{
vg_lite_IRQHandler();
}
static status_t BOARD_InitVGliteClock(void)
{
const clock_root_config_t gc355ClockConfig = {
.clockOff = false,
.mux = kCLOCK_GC355_ClockRoot_MuxVideoPllOut, /*!< 984MHz */
.div = 2,
};
CLOCK_SetRootClock(kCLOCK_Root_Gc355, &gc355ClockConfig);
CLOCK_GetRootClockFreq(kCLOCK_Root_Gc355);
CLOCK_EnableClock(kCLOCK_Gpu2d);
NVIC_SetPriority(GPU2D_IRQn, 3);
EnableIRQ(GPU2D_IRQn);
return kStatus_Success;
}
status_t BOARD_PrepareVGLiteController(void)
{
status_t status;
status = BOARD_InitVGliteClock();
if (kStatus_Success != status)
{
return status;
}
vg_lite_init_mem(registerMemBase, gpu_mem_base, vglite_heap_base, vglite_heap_size);
return kStatus_Success;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2019, 2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _VGLITE_SUPPORT_H_
#define _VGLITE_SUPPORT_H_
#include "fsl_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
#define VG_LITE_COMMAND_BUFFER_SIZE (256 << 10) /* 256 KB */
/* Default tessellation window width and height, in pixels */
#define DEFAULT_VG_LITE_TW_WIDTH 128 /* pixels */
#define DEFAULT_VG_LITE_TW_HEIGHT 128 /* pixels */
status_t BOARD_PrepareVGLiteController(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* _VGLITE_SUPPORT_H_ */

View File

@ -0,0 +1,181 @@
/*
* Copyright 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <rtthread.h>
#include "vglite_support.h"
#include "vg_lite_platform.h"
#include "vglite_window.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#if !DEMO_BUFFER_FIXED_ADDRESS
AT_NONCACHEABLE_SECTION_ALIGN(
static uint8_t s_frameBuffer[APP_BUFFER_COUNT][LCD_HEIGHT][LCD_WIDTH][DEMO_BUFFER_BYTE_PER_PIXEL],
FRAME_BUFFER_ALIGN);
#define DEMO_BUFFER0_ADDR (uint32_t) s_frameBuffer[0]
#if APP_BUFFER_COUNT > 1
#define DEMO_BUFFER1_ADDR (uint32_t) s_frameBuffer[1]
#endif
#if APP_BUFFER_COUNT > 2
#define DEMO_BUFFER2_ADDR (uint32_t) s_frameBuffer[2]
#endif
#endif
static const uint32_t s_frameBufferAddress[APP_BUFFER_COUNT] = {DEMO_BUFFER0_ADDR,
#if APP_BUFFER_COUNT > 1
DEMO_BUFFER1_ADDR,
#endif
#if APP_BUFFER_COUNT > 2
DEMO_BUFFER2_ADDR
#endif
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static vg_lite_buffer_format_t video_format_to_vglite(video_pixel_format_t format)
{
vg_lite_buffer_format_t fmt;
switch (format)
{
case kVIDEO_PixelFormatRGB565:
fmt = VG_LITE_BGR565;
break;
case kVIDEO_PixelFormatBGR565:
fmt = VG_LITE_RGB565;
break;
case kVIDEO_PixelFormatXRGB8888:
fmt = VG_LITE_BGRX8888;
break;
default:
fmt = VG_LITE_RGB565;
break;
}
return fmt;
}
vg_lite_error_t VGLITE_CreateDisplay(vg_lite_display_t *display)
{
if (!display)
return VG_LITE_INVALID_ARGUMENT;
BOARD_PrepareDisplayController();
FBDEV_Open(&display->g_fbdev, &g_dc, 0);
return VG_LITE_SUCCESS;
}
vg_lite_error_t VGLITE_CreateWindow(vg_lite_display_t *display, vg_lite_window_t *window)
{
vg_lite_error_t ret = VG_LITE_SUCCESS;
status_t status;
void *buffer;
vg_lite_buffer_t *vg_buffer;
fbdev_t *g_fbdev = &(display->g_fbdev);
fbdev_fb_info_t *g_fbInfo = &(display->g_fbInfo);
window->bufferCount = APP_BUFFER_COUNT;
window->display = display;
window->width = DEMO_BUFFER_WIDTH;
window->height = DEMO_BUFFER_HEIGHT;
window->current = -1;
FBDEV_GetFrameBufferInfo(g_fbdev, g_fbInfo);
g_fbInfo->bufInfo.pixelFormat = DEMO_BUFFER_PIXEL_FORMAT;
g_fbInfo->bufInfo.startX = DEMO_BUFFER_START_X;
g_fbInfo->bufInfo.startY = DEMO_BUFFER_START_Y;
g_fbInfo->bufInfo.width = window->width;
g_fbInfo->bufInfo.height = window->height;
g_fbInfo->bufInfo.strideBytes = DEMO_BUFFER_STRIDE_BYTE;
g_fbInfo->bufferCount = window->bufferCount;
for (uint8_t i = 0; i < window->bufferCount; i++)
{
vg_buffer = &(window->buffers[i]);
g_fbInfo->buffers[i] = (void *)s_frameBufferAddress[i];
vg_buffer->memory = g_fbInfo->buffers[i];
vg_buffer->address = s_frameBufferAddress[i];
vg_buffer->width = g_fbInfo->bufInfo.width;
vg_buffer->height = g_fbInfo->bufInfo.height;
vg_buffer->stride = g_fbInfo->bufInfo.strideBytes;
vg_buffer->format = video_format_to_vglite(DEMO_BUFFER_PIXEL_FORMAT);
}
status = FBDEV_SetFrameBufferInfo(g_fbdev, g_fbInfo);
if (status != kStatus_Success)
{
while (1)
;
}
buffer = FBDEV_GetFrameBuffer(g_fbdev, 0);
assert(buffer != NULL);
memset(buffer, 0, g_fbInfo->bufInfo.height * g_fbInfo->bufInfo.strideBytes);
FBDEV_SetFrameBuffer(g_fbdev, buffer, 0);
FBDEV_Enable(g_fbdev);
return ret;
}
vg_lite_error_t VGLITE_DestoryWindow(void)
{
return VG_LITE_SUCCESS;
}
vg_lite_error_t VGLITE_DestroyDisplay(void)
{
return VG_LITE_SUCCESS;
}
vg_lite_buffer_t *VGLITE_GetRenderTarget(vg_lite_window_t *window)
{
vg_lite_buffer_t *rt = NULL;
void *memory = FBDEV_GetFrameBuffer(&window->display->g_fbdev, 0);
for (uint8_t i = 0; i < window->bufferCount; i++)
{
rt = &(window->buffers[i]);
if (memory == rt->memory)
{
window->current = i;
return rt;
}
}
return NULL;
}
void VGLITE_SwapBuffers(vg_lite_window_t *window)
{
vg_lite_buffer_t *rt;
if (window->current >= 0 && window->current < window->bufferCount)
rt = &(window->buffers[window->current]);
else
return;
vg_lite_finish();
FBDEV_SetFrameBuffer(&window->display->g_fbdev, rt->memory, 0);
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _VGLITE_WINDOW_H_
#define _VGLITE_WINDOW_H_
#include "fsl_common.h"
#include "vg_lite.h"
#include "vglite_support.h"
#include "display_support.h"
#include "fsl_fbdev.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define APP_BUFFER_COUNT 2
typedef struct vg_lite_display
{
fbdev_t g_fbdev;
fbdev_fb_info_t g_fbInfo;
} vg_lite_display_t;
typedef struct vg_lite_window
{
vg_lite_display_t *display;
vg_lite_buffer_t buffers[APP_BUFFER_COUNT];
int width;
int height;
int bufferCount;
int current;
} vg_lite_window_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
vg_lite_error_t VGLITE_CreateDisplay(vg_lite_display_t *display);
vg_lite_error_t VGLITE_CreateWindow(vg_lite_display_t *display, vg_lite_window_t *window);
vg_lite_error_t VGLITE_DestoryWindow(void);
vg_lite_error_t VGLITE_DestroyDisplay(void);
vg_lite_buffer_t *VGLITE_GetRenderTarget(vg_lite_window_t *window);
void VGLITE_SwapBuffers(vg_lite_window_t *window);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
#endif /* _VGLITE_WINDOW_H_ */

View File

@ -52,6 +52,64 @@ if GetDepend(['RT_USING_CAN']):
if GetDepend(['BSP_USING_FLEXSPI']):
src += ['MIMXRT1176/drivers/fsl_flexspi.c']
if GetDepend(['BSP_USING_VGLITE']):
src += ['MIMXRT1176/drivers/fsl_soc_src.c']
src += ['MIMXRT1176/drivers/fsl_mipi_dsi.c']
src += ['MIMXRT1176/drivers/fsl_video_common.c']
src += ['MIMXRT1176/drivers/display_support.c']
src += ['MIMXRT1176/drivers/fsl_fbdev.c']
src += ['MIMXRT1176/drivers/fsl_mipi_dsi_cmd.c']
if GetDepend(['VGLITE_USING_LCDIFV2']):
src += ['MIMXRT1176/drivers/fsl_dc_fb_lcdifv2.c']
src += ['MIMXRT1176/drivers/fsl_lcdifv2.c']
else:
src += ['MIMXRT1176/drivers/fsl_dc_fb_elcdif.c']
src += ['MIMXRT1176/drivers/fsl_elcdif.c']
if GetDepend(['VGLITE_USING_RK055AHD091']):
src += ['MIMXRT1176/drivers/fsl_rm68200.c']
elif GetDepend(['VGLITE_USING_RK055IQH091']):
src += ['MIMXRT1176/drivers/fsl_rm68191.c']
else:
src += ['MIMXRT1176/drivers/fsl_hx8394.c']
src += ['MIMXRT1176/drivers/mf_bwfont.c']
src += ['MIMXRT1176/drivers/mf_encoding.c']
src += ['MIMXRT1176/drivers/mf_font.c']
src += ['MIMXRT1176/drivers/mf_justify.c']
src += ['MIMXRT1176/drivers/mf_kerning.c']
src += ['MIMXRT1176/drivers/mf_rlefont.c']
src += ['MIMXRT1176/drivers/mf_scaledfont.c']
src += ['MIMXRT1176/drivers/mf_wordwrap.c']
src += ['MIMXRT1176/drivers/buf_reader.c']
src += ['MIMXRT1176/drivers/rle_font_read.c']
src += ['MIMXRT1176/drivers/vft_debug.c']
src += ['MIMXRT1176/drivers/vft_draw.c']
src += ['MIMXRT1176/drivers/vg_lite_text.c']
src += ['MIMXRT1176/drivers/vg_lite_os.c']
src += ['MIMXRT1176/drivers/vg_lite.c']
src += ['MIMXRT1176/drivers/vg_lite_flat.c']
src += ['MIMXRT1176/drivers/vg_lite_image.c']
src += ['MIMXRT1176/drivers/vg_lite_matrix.c']
src += ['MIMXRT1176/drivers/vg_lite_path.c']
src += ['MIMXRT1176/drivers/vglite_support.c']
src += ['MIMXRT1176/drivers/vglite_window.c']
src += ['MIMXRT1176/drivers/vg_lite_hal.c']
src += ['MIMXRT1176/drivers/vg_lite_kernel.c']
if GetDepend(['VGLITE_USING_ELM']):
src += ['MIMXRT1176/drivers/elm_buffer.c']
src += ['MIMXRT1176/drivers/elm_draw.c']
src += ['MIMXRT1176/drivers/elm_init.c']
src += ['MIMXRT1176/drivers/elm_object.c']
src += ['MIMXRT1176/drivers/elm_os.c']
src += ['MIMXRT1176/drivers/elm_text.c']
#fsl os abstract files
src += ['MIMXRT1176/drivers/fsl_os_abstraction_rtthread.c']
src += ['MIMXRT1176/drivers/generic_list.c']