feat(EVE): Add EVE draw unit (#8211)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/benchmark_results_comment/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/filter_docker_logs/test.sh) (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Script Check (scripts/perf/tests/serialize_results/test.sh) (push) Has been cancelled
Hardware Performance Test / Hardware Performance Benchmark (push) Has been cancelled
Hardware Performance Test / HW Benchmark - Save PR Number (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 32b - lv_conf_perf32b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark 64b - lv_conf_perf64b (push) Has been cancelled
Emulated Performance Test / ARM Emulated Benchmark - Save PR Number (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled

Co-authored-by: André Costa <andre_miguel_costa@hotmail.com>
This commit is contained in:
Liam Howatt
2025-08-07 05:09:44 -04:00
committed by GitHub
parent 3fae9b9a10
commit b6061140b8
42 changed files with 9978 additions and 19 deletions
+3
View File
@@ -58,3 +58,6 @@ For the licenses, see the corresponding `LICENSE.txt` file in each librarys f
- src/others/xml
- xmls
**FT800-FT813 (EVE GPU driver)**
- Path src/libs/FT800-FT813
- Source: https://github.com/RudolphRiedel/FT800-FT813
+10
View File
@@ -537,6 +537,16 @@ menu "LVGL configuration"
default n
depends on LV_USE_PPA
config LV_USE_DRAW_EVE
bool "Use EVE FT81X GPU."
default n
config LV_DRAW_EVE_EVE_GENERATION
int "EVE_GEN value"
default 4
range 2 4
depends on LV_USE_DRAW_EVE
endmenu
menu "Feature Configuration"
@@ -1,3 +1,5 @@
.. _ft81x:
=====
FT81x
=====
@@ -0,0 +1,186 @@
=========================
EVE External GPU Renderer
=========================
EVE is a type of external GPU IC which accepts high-level drawing commands over SPI
and outputs the rendered graphics to a display over parallel RGB.
The advantage of using an EVE chip is that the rendering responsibility is removed
from the driving MCU so it can be a lower-spec part or dedicate more of its
processing time to other tasks. The SPI interface is simpler to connect than
parallel RGB especially if the EVE chip is integrated into a display assembly.
LVGL features a renderer for EVE. LVGL UIs can be rendered by EVE
and are effectively indistinguishable from the software renderer is most cases.
See also the :ref:`ft81x` framebuffer driver. It drives the same EVE chips
but is a simpler, more standalone implementation which uses software rendering
and sends all the pixels over SPI so it is much slower.
Limitations
***********
- Image format, size, and count limit.
- Font format, size, and count limit.
- The total number of tasks rendered per refresh has an upper limit.
- Layers are not supported.
Usage
*****
Board Parameters
----------------
Find your display parameters and populate a :cpp:struct:`lv_draw_eve_parameters_t`
struct with them.
Here is an example ``lv_draw_eve_target_parameters.h`` for the Riverdi RVT50HQBNWC00-B
which has a BT817Q --- the EVE chip.
These parameters were taken from the collection of configs provided by the EVE
library supporting this renderer.
`See here <https://github.com/RudolphRiedel/FT800-FT813/blob/ee35fa45c37aed78dc4f1196b874ee1c8f80429f/EVE_config.h#L856-L872>`__.
Check there for your board parameters.
.. code-block:: c
lv_draw_eve_parameters_t params = {
.hor_res = 800,
.ver_res = 480,
.vsync0 = 0,
.vsync1 = 4,
.voffset = 8,
.vcycle = 496,
.hsync0 = 0,
.hsync1 = 4,
.hoffset = 8,
.hcycle = 816,
.pclk = 3,
.pclkpol = 1,
.swizzle = 0,
.cspread = 0,
.has_crystal = true,
.has_gt911 = false,
.backlight_freq = 4000,
.backlight_pwm = 128,
};
EVE Chip IO Implementation
--------------------------
The user is required to implement the GPIO and SPI IO functionality. The LVGL EVE
renderer will call this callback to perform SPI communication with the EVE chip.
.. code-block:: c
static void op_cb(lv_display_t * disp, lv_draw_eve_operation_t operation,
void * data, uint32_t length)
{
/* optional: get the `user_data` parameter you passed to `lv_draw_eve_display_create` */
void * your_user_data = lv_draw_eve_display_get_user_data(disp);
switch(operation) {
case LV_DRAW_EVE_OPERATION_POWERDOWN_SET:
/* setting the pin low powers down the EVE chip */
your_gpio_write(PD_N_PIN, 0);
break;
case LV_DRAW_EVE_OPERATION_POWERDOWN_CLEAR:
/* setting the pin high powers on the EVE chip */
your_gpio_write(PD_N_PIN, 1);
break;
case LV_DRAW_EVE_OPERATION_CS_ASSERT:
/* setting the pin low asserts the EVE chip SPI device */
your_gpio_write(CS_N_PIN, 0);
break;
case LV_DRAW_EVE_OPERATION_CS_DEASSERT:
/* setting the pin high de-asserts the EVE chip SPI device */
your_gpio_write(CS_N_PIN, 1);
break;
case LV_DRAW_EVE_OPERATION_SPI_SEND:
/* `data` is the data to send */
your_spi_transmit(data, length);
break;
case LV_DRAW_EVE_OPERATION_SPI_RECEIVE:
/* `data` is the destination for the data */
your_spi_receive(data, length);
break;
}
}
You will also need to initialize your SPI peripheral and GPIO pins.
22 MHz was the highest SPI speed that worked during testing with the Riverdi board
and the ESP32-S3. You may not have success with this speed so it is
recommended to validate with an ``SPI_SPEED`` value of ``10`` (10 MHz)
and increase experimentally in your testing.
LVGL EVE Display Creation
-------------------------
To create the LVGL display for the EVE renderer, you call
:cpp:expr:`lv_draw_eve_display_create(params, op_cb, your_user_data)` which returns the
created display. ``your_user_data`` can be ``NULL``. It should be called after GPIO and
SPI is initialized. You may choose to initialize your IO
the first time ``op_cb`` is called.
No buffers are required for the LVGL EVE renderer because no pixels
are written to any buffers in the device running LVGL. When something
needs to be drawn, a series of commands are sent to EVE.
Touch Indev Creation
--------------------
:cpp:expr:`lv_draw_eve_touch_create(disp)` creates a touch :ref:`indev` for the display.
You may need to configure the i2c address of the touch controller connected to EVE.
See the section :ref:`eve register access` for more info about register access.
Here is an example of setting the ``REG_TOUCH_CONFIG`` register on a BT817q EVE chip
for a capacitive touch screen with a controller that has the i2c address ``0x15``.
.. code-block:: c
/*
15: 0: capacitive, 1: resistive CAPACITIVE
14: host mode NO
13: reserved
12: ignore short circuit protection NO
11: low-power mode NO
10-4: 7-bit i2c address 0x15
3: reserved
2: suppress 300ms startup NO
1-0: 2-bit sampling clocks val use 1 (the reset default)
*/
lv_draw_eve_memwrite16(disp, LV_EVE_REG_TOUCH_CONFIG, 0x0151);
Display Rotation
----------------
Efficient display rotation is fully supported through :cpp:func:`lv_display_set_rotation`.
Touch input rotation is handled accordingly.
.. _eve register access:
EVE Register Access
-------------------
The functions :cpp:func:`lv_draw_eve_memread8`, :cpp:func:`lv_draw_eve_memread16`, :cpp:func:`lv_draw_eve_memread32`,
:cpp:func:`lv_draw_eve_memwrite8`, :cpp:func:`lv_draw_eve_memwrite16`, are :cpp:func:`lv_draw_eve_memwrite32`
available if needed. They are wrappers around ``EVE_memRead8``, etc.
Register definitions and other EVE enumerations are available when you include
``lvgl.h`` under the prefix namespace ``LV_EVE_``. I.e., ``REG_ID`` is available
as ``LV_EVE_REG_ID`` and ``EVE_ROM_CHIPID`` is available as ``LV_EVE_EVE_ROM_CHIPID``, etc.
Further Reading
---------------
- https://brtchip.com/wp-content/uploads/Support/Documentation/Programming_Guides/ICs/EVE/FT81X_Series_Programmer_Guide.pdf
- https://brtchip.com/wp-content/uploads/2024/06/BRT_AN_033_BT81X-Series-Programming-Guide.pdf
@@ -8,6 +8,7 @@ Renderers and GPUs
sw
arm2d
espressif_ppa
eve
nema_gfx
nxp_pxp
nxp_vglite_gpu
+9
View File
@@ -362,6 +362,15 @@
#if LV_USE_PPA
#define LV_USE_PPA_IMG 0
#endif
/* Use EVE FT81X GPU. */
#define LV_USE_DRAW_EVE 0
#if LV_USE_DRAW_EVE
/* EVE_GEN value: 2, 3, or 4 */
#define LV_DRAW_EVE_EVE_GENERATION 4
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
+1
View File
@@ -123,6 +123,7 @@ extern "C" {
#include "src/draw/lv_draw_buf.h"
#include "src/draw/lv_draw_vector.h"
#include "src/draw/sw/lv_draw_sw_utils.h"
#include "src/draw/eve/lv_draw_eve_target.h"
#include "src/themes/lv_theme.h"
+1
View File
@@ -49,6 +49,7 @@
--exclude=../src/libs/thorvg
--exclude=../src/libs/expat
--exclude=../src/libs/lz4
--exclude=../src/libs/FT800-FT813
--exclude=../src/others/vg_lite_tvg/vg_lite.h
--exclude=../demos/high_res/fonts
--exclude=../tests/unity/unity.c
+4
View File
@@ -263,6 +263,10 @@ typedef struct _lv_global_t {
const char * xml_path_prefix;
#endif
#if LV_USE_DRAW_EVE
lv_draw_eve_unit_t * draw_eve_unit;
#endif
void * user_data;
} lv_global_t;
+173
View File
@@ -0,0 +1,173 @@
/**
* @file lv_draw_eve.c
*
*/
/* Created on: 3 dic 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "../../core/lv_refr.h"
#include "../../display/lv_display_private.h"
#include "../../stdlib/lv_string.h"
#include "lv_draw_eve_ram_g.h"
#include "lv_draw_eve.h"
#include "lv_eve.h"
/*********************
* DEFINES
*********************/
#define DRAW_UNIT_ID_EVE 9
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void eve_execute_drawing(lv_draw_eve_unit_t * u);
static int32_t eve_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
static int32_t eve_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
static void disp_delete_cb(lv_event_t * e);
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_init(void)
{
lv_draw_eve_unit_t * draw_eve_unit = lv_draw_create_unit(sizeof(lv_draw_eve_unit_t));
draw_eve_unit->base_unit.dispatch_cb = eve_dispatch;
draw_eve_unit->base_unit.evaluate_cb = eve_evaluate;
lv_draw_eve_unit_g = draw_eve_unit;
}
void lv_draw_eve_set_display_data(lv_display_t * disp, const lv_draw_eve_parameters_t * params,
lv_draw_eve_operation_cb_t op_cb)
{
if(lv_draw_eve_unit_g == NULL) {
LV_LOG_WARN("lv_draw_eve is not initialized.");
return;
}
lv_draw_eve_unit_g->disp = disp;
lv_draw_eve_unit_g->params = *params; /* make a copy */
lv_draw_eve_unit_g->op_cb = op_cb;
lv_display_add_event_cb(disp, disp_delete_cb, LV_EVENT_DELETE, NULL);
}
/**********************
* STATIC FUNCTIONS
**********************/
static int32_t eve_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{
lv_draw_eve_unit_t * draw_eve_unit = (lv_draw_eve_unit_t *) draw_unit;
lv_draw_task_t * t = NULL;
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_EVE);
if(t == NULL) return LV_DRAW_UNIT_IDLE;
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
draw_eve_unit->task_act = t;
eve_execute_drawing(draw_eve_unit);
draw_eve_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
draw_eve_unit->task_act = NULL;
/*The draw unit is free now. Request a new dispatching as it can get a new task*/
lv_draw_dispatch_request();
return 1;
}
static int32_t eve_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
{
LV_UNUSED(draw_unit);
if(((lv_draw_dsc_base_t *)task->draw_dsc)->user_data == NULL) {
task->preference_score = 0;
task->preferred_draw_unit_id = DRAW_UNIT_ID_EVE;
}
return 0;
}
static void eve_execute_drawing(lv_draw_eve_unit_t * u)
{
lv_draw_task_t * t = u->task_act;
uint8_t coprocessor_status;
do {
coprocessor_status = EVE_busy();
} while(coprocessor_status != E_OK && coprocessor_status != EVE_FIFO_HALF_EMPTY);
EVE_start_cmd_burst();
switch(t->type) {
case LV_DRAW_TASK_TYPE_LINE:
lv_draw_eve_line(t, t->draw_dsc);
break;
case LV_DRAW_TASK_TYPE_BORDER:
lv_draw_eve_border(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_FILL:
lv_draw_eve_fill(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_eve_image(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_LABEL:
lv_draw_eve_label(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_ARC:
lv_draw_eve_arc(t, t->draw_dsc, &t->area);
break;
case LV_DRAW_TASK_TYPE_TRIANGLE:
lv_draw_eve_triangle(t, t->draw_dsc);
break;
default:
break;
}
EVE_end_cmd_burst();
}
static void disp_delete_cb(lv_event_t * e)
{
lv_draw_eve_unit_g->disp = NULL;
lv_draw_eve_unit_g = NULL;
}
#endif /*LV_USE_DRAW_EVE*/
+57
View File
@@ -0,0 +1,57 @@
/**
* @file lv_draw_eve.h
*
*/
/* Created on: 3 dic 2023
* Author: juanj
*
* Modified by LVGL
*/
#ifndef LV_DRAW_EVE_H
#define LV_DRAW_EVE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_DRAW_EVE
#include "lv_draw_eve_target.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_eve_init(void);
void lv_draw_eve_set_display_data(lv_display_t * disp, const lv_draw_eve_parameters_t * params,
lv_draw_eve_operation_cb_t op_cb);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_DRAW_EVE_H */
+323
View File
@@ -0,0 +1,323 @@
/**
* @file lv_draw_eve_arc.c
*
*/
/* Created on: 11 dic 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "../lv_draw_arc.h"
#include "lv_eve.h"
/*********************
* DEFINES
*********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords);
static bool is_same_quadrant(int16_t start_angle, int16_t end_angle) ;
static void draw_rounded_end(lv_point_t center, int32_t radius, int32_t angle, int32_t width);
static void lv_draw_eve_mask_angle(const lv_draw_arc_dsc_t * dsc, int32_t vertex_x, int32_t vertex_y,
int32_t start_angle, int32_t end_angle);
static lv_eve_primitive_t get_mask_direction(int16_t angle);
static int32_t chord_length(int16_t radius, int16_t angle_degrees);
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords)
{
draw_eve_arc(t, dsc, coords);
}
/**********************
* STATIC FUNCTIONS
**********************/
static int32_t chord_length(int16_t radius, int16_t angle_degrees)
{
angle_degrees %= 360;
if(angle_degrees < 0) angle_degrees += 360;
int32_t sin_value = lv_trigo_sin(angle_degrees / 2);
int64_t chord_length = 2 * radius * sin_value / 32768.0;
return (int32_t)chord_length ;
}
static lv_eve_primitive_t get_mask_direction(int16_t angle)
{
if(angle >= 315 || angle < 45) {
return LV_EVE_PRIMITIVE_EDGE_STRIP_R;
}
if(angle >= 45 && angle < 135) {
return LV_EVE_PRIMITIVE_EDGE_STRIP_B;
}
if(angle >= 135 && angle < 225) {
return LV_EVE_PRIMITIVE_EDGE_STRIP_L;
}
if(angle >= 225 && angle < 315) {
return LV_EVE_PRIMITIVE_EDGE_STRIP_A;
}
return 0;
}
static void draw_rounded_end(lv_point_t center, int32_t radius, int32_t angle, int32_t width)
{
int32_t rounded_y = center.y + ((lv_trigo_sin(angle) * radius) >> LV_TRIGO_SHIFT);
int32_t rounded_x = center.x + ((lv_trigo_cos(angle) * radius) >> LV_TRIGO_SHIFT);
lv_eve_draw_circle_simple(rounded_x, rounded_y, width);
}
static bool is_same_quadrant(int16_t start_angle, int16_t end_angle)
{
if(start_angle > end_angle) {
if((start_angle >= 0 && start_angle < 90) && (end_angle >= 0 && end_angle < 90)) {
return true;
}
else if((start_angle >= 90 && start_angle < 180) && (end_angle >= 90 && end_angle < 180)) {
return true;
}
else if((start_angle >= 180 && start_angle < 270) && (end_angle >= 180 && end_angle < 270)) {
return true;
}
else if((start_angle >= 270 && start_angle < 360) && (end_angle >= 270 && end_angle < 360)) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
static void lv_draw_eve_mask_angle(const lv_draw_arc_dsc_t * dsc, int32_t vertex_x, int32_t vertex_y,
int32_t start_angle, int32_t end_angle)
{
/*Constrain the input angles*/
if(start_angle < 0)
start_angle = 0;
else if(start_angle > 359)
start_angle = 359;
if(end_angle < 0)
end_angle = 0;
else if(end_angle > 359)
end_angle = 359;
LV_ASSERT_MSG(start_angle >= 0 && start_angle <= 360, "Unexpected start angle");
int32_t mid_angle_op;
int32_t angle_range;
int32_t mask_dir_start;
int32_t mask_dir_end;
lv_point_t start;
lv_point_t end;
lv_point_t angle_range_op;
if(end_angle > start_angle) {
angle_range = LV_ABS(end_angle - start_angle);
}
else {
angle_range = 360 - start_angle + end_angle;
}
mid_angle_op = (angle_range / 2) + start_angle + 180;
mid_angle_op = mid_angle_op % 360;
mask_dir_end = LV_ABS(((360 - angle_range) / 4) + end_angle);
mask_dir_start = LV_ABS(((360 - angle_range) / 4) + mid_angle_op);
mask_dir_start = mask_dir_start % 360;
mask_dir_end = mask_dir_end % 360;
start.y = (lv_trigo_sin(start_angle) >> 5) + vertex_y;
start.x = (lv_trigo_cos(start_angle) >> 5) + vertex_x;
end.y = (lv_trigo_sin(end_angle) >> 5) + vertex_y;
end.x = (lv_trigo_cos(end_angle) >> 5) + vertex_x;
angle_range_op.y = (lv_trigo_sin(mid_angle_op) >> 5) + vertex_y;
angle_range_op.x = (lv_trigo_cos(mid_angle_op) >> 5) + vertex_x;
if(angle_range <= 180) {
/* Two sides mask and 6 vertex points */
/* Masking end angle */
lv_eve_primitive_t edge = get_mask_direction(mask_dir_end);
lv_eve_primitive(edge); /* Side one */
lv_eve_vertex_2f(angle_range_op.x, angle_range_op.y);
lv_eve_vertex_2f(vertex_x, vertex_y);
lv_eve_vertex_2f(end.x, end.y);
/* Masking start angle */
edge = get_mask_direction(mask_dir_start);
lv_eve_primitive(edge); /* Side two */
lv_eve_vertex_2f(angle_range_op.x, angle_range_op.y);
lv_eve_vertex_2f(vertex_x, vertex_y);
lv_eve_vertex_2f(start.x, start.y);
}
else {
if(is_same_quadrant(start_angle,
end_angle)) { /* "It is not an optimal implementation for the case where both angles (start and end) are in the same quadrant */
/* todo */
lv_point_t end_line_cntr;
lv_point_t start_line_cntr;
lv_point_t end_line_brd;
lv_point_t start_line_brd;
int16_t chord = chord_length(dsc->radius, 360 - angle_range);
int16_t w = ((chord / 4) < 1) ? 1 : chord / 4;
int16_t r_width = w;
end_line_brd.y = vertex_y + ((lv_trigo_sin(end_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
end_line_brd.x = vertex_x + ((lv_trigo_cos(end_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
start_line_brd.y = vertex_y + ((lv_trigo_sin(start_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
start_line_brd.x = vertex_x + ((lv_trigo_cos(start_angle) * dsc->radius) >> LV_TRIGO_SHIFT);
lv_eve_draw_rect_simple(start_line_brd.x, start_line_brd.y, end_line_brd.x, end_line_brd.y, 0);
start_line_brd.y = start_line_brd.y + ((lv_trigo_sin(start_angle - 90) * r_width) >> LV_TRIGO_SHIFT);
start_line_brd.x = start_line_brd.x + ((lv_trigo_cos(start_angle - 90) * r_width) >> LV_TRIGO_SHIFT);
end_line_brd.y = end_line_brd.y + ((lv_trigo_sin(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
end_line_brd.x = end_line_brd.x + ((lv_trigo_cos(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
end_line_cntr.y = vertex_y + ((lv_trigo_sin(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
end_line_cntr.x = vertex_x + ((lv_trigo_cos(end_angle + 90) * r_width) >> LV_TRIGO_SHIFT);
start_line_cntr.y = vertex_y + ((lv_trigo_sin(start_angle + 270) * r_width) >> LV_TRIGO_SHIFT);
start_line_cntr.x = vertex_x + ((lv_trigo_cos(start_angle + 270) * r_width) >> LV_TRIGO_SHIFT);
lv_eve_primitive(LV_EVE_PRIMITIVE_LINE_STRIP);
lv_eve_line_width(r_width * 16);
lv_eve_vertex_2f(start_line_cntr.x, start_line_cntr.y);
lv_eve_vertex_2f(start_line_brd.x, start_line_brd.y);
lv_eve_vertex_2f(end_line_brd.x, end_line_brd.y);
lv_eve_vertex_2f(end_line_cntr.x, end_line_cntr.y);
}
else { /* One side mask and 3 vertex points */
/* Masking end and start angles */
lv_eve_primitive_t edge = get_mask_direction(mid_angle_op);
lv_eve_primitive(edge);
lv_eve_vertex_2f(end.x, end.y);
lv_eve_vertex_2f(vertex_x, vertex_y);
lv_eve_vertex_2f(start.x, start.y);
}
}
}
static void draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->opa <= LV_OPA_MIN)
return;
if(dsc->width == 0)
return;
if(dsc->start_angle == dsc->end_angle)
return;
lv_color_t color = dsc->color;
lv_opa_t opa = dsc->opa;
lv_point_t center = dsc->center;
int32_t width = dsc->width;
uint16_t radius_out = dsc->radius;
uint16_t radius_in = dsc->radius - dsc->width;
int32_t start_angle = (int32_t) dsc->start_angle;
int32_t end_angle = (int32_t) dsc->end_angle;
if(width > radius_out)
width = radius_out;
while(start_angle >= 360)
start_angle -= 360;
while(end_angle >= 360)
end_angle -= 360;
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_save_context();
lv_eve_color(color);
lv_eve_color_opa(opa);
lv_eve_color_mask(0, 0, 0, 1);
lv_eve_stencil_func(EVE_ALWAYS, 0, 1);
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
lv_eve_draw_circle_simple(center.x, center.y, radius_out); /* radius_out */
lv_eve_blend_func(EVE_ONE, EVE_ZERO);
lv_eve_draw_circle_simple(center.x, center.y, radius_in + 2); /* radius_in */
lv_eve_stencil_func(EVE_ALWAYS, 1, 1);
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
lv_eve_blend_func(EVE_ZERO, EVE_ONE_MINUS_SRC_ALPHA);
lv_eve_color_opa(0XFF);
/* Start masking arc */
lv_draw_eve_mask_angle(dsc, center.x, center.y, start_angle, end_angle);
/* End masking arc */
lv_eve_draw_circle_simple(center.x, center.y, radius_in); /* radius_in */
lv_eve_color_mask(1, 1, 1, 1);
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
lv_eve_draw_circle_simple(center.x, center.y, radius_in); /* radius_in */
lv_eve_stencil_func(EVE_NOTEQUAL, 1, 0XFF);
lv_eve_blend_func(EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA);
lv_eve_color_opa(opa);
lv_eve_draw_circle_simple(center.x, center.y, radius_out); /* radius_out */
lv_eve_restore_context();
if(dsc->rounded) {
lv_eve_save_context();
lv_eve_color_opa(opa);
lv_eve_color(color);
int32_t half_width = width / 2;
int32_t adjusted_radius = radius_out - half_width;
draw_rounded_end(center, adjusted_radius, end_angle, half_width);
draw_rounded_end(center, adjusted_radius, start_angle, half_width);
lv_eve_restore_context();
}
}
#endif /*LV_USE_DRAW_EVE*/
+121
View File
@@ -0,0 +1,121 @@
/**
* @file lv_draw_eve_fill.c
*
*/
/* Created on: 27 mar 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "lv_eve.h"
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords)
{
int32_t rad = dsc->radius;
int32_t bg_w = lv_area_get_width(coords);
int32_t bg_h = lv_area_get_height(coords);
int32_t real_radius = LV_MIN3(bg_w / 2, bg_h / 2, rad);
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_save_context();
lv_eve_color(dsc->color);
lv_eve_color_opa(dsc->opa);
if(bg_w == bg_h && rad == LV_RADIUS_CIRCLE) {
lv_eve_draw_circle_simple(coords->x1 + (bg_w / 2), coords->y1 + (bg_h / 2), real_radius);
}
else {
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, real_radius);
}
lv_eve_restore_context();
}
/**********************
* STATIC FUNCTIONS
**********************/
void lv_draw_eve_border(lv_draw_task_t * t, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->opa <= LV_OPA_MIN) return;
if(dsc->width == 0) return;
if(dsc->side == LV_BORDER_SIDE_NONE) return;
int32_t coords_w = lv_area_get_width(coords);
int32_t coords_h = lv_area_get_height(coords);
int32_t rout = dsc->radius;
int32_t short_side = LV_MIN(coords_w, coords_h);
if(rout > short_side >> 1) rout = short_side >> 1;
/*Get the inner area*/
lv_area_t area_inner;
lv_area_copy(&area_inner, coords);
area_inner.x1 += ((dsc->side & LV_BORDER_SIDE_LEFT) ? dsc->width : - (dsc->width));
area_inner.x2 -= ((dsc->side & LV_BORDER_SIDE_RIGHT) ? dsc->width : - (dsc->width));
area_inner.y1 += ((dsc->side & LV_BORDER_SIDE_TOP) ? dsc->width : - (dsc->width));
area_inner.y2 -= ((dsc->side & LV_BORDER_SIDE_BOTTOM) ? dsc->width : - (dsc->width));
int32_t rin = rout - dsc->width;
if(rin < 0) rin = 0;
lv_eve_save_context();
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_color(dsc->color);
lv_eve_color_opa(dsc->opa);
lv_eve_color_mask(0, 0, 0, 1);
lv_eve_stencil_func(EVE_ALWAYS, 0, 1);
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, 0);
lv_eve_blend_func(EVE_ONE, EVE_ZERO);
lv_eve_draw_rect_simple(area_inner.x1 - 2, area_inner.y1 - 1, area_inner.x2 + 1, area_inner.y2 + 2, rin);
lv_eve_stencil_func(EVE_ALWAYS, 1, 1);
lv_eve_stencil_op(EVE_REPLACE, EVE_REPLACE);
lv_eve_blend_func(EVE_ZERO, EVE_ONE_MINUS_SRC_ALPHA);
lv_eve_color_opa(255);
lv_eve_draw_rect_simple(area_inner.x1, area_inner.y1, area_inner.x2, area_inner.y2, rin);
lv_eve_color_mask(1, 1, 1, 1);
if(dsc->side == LV_BORDER_SIDE_FULL) {
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
lv_eve_draw_rect_simple(area_inner.x1, area_inner.y1, area_inner.x2, area_inner.y2, rin);
}
lv_eve_stencil_func(EVE_NOTEQUAL, 1, 255);
lv_eve_blend_func(EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA);
lv_eve_color_opa(dsc->opa);
lv_eve_draw_rect_simple(coords->x1, coords->y1, coords->x2, coords->y2, rout);
lv_eve_restore_context();
}
#endif /*LV_USE_DRAW_EVE*/
+242
View File
@@ -0,0 +1,242 @@
/**
* @file lv_draw_eve_image.c
*
*/
/* Created on: 17 jun 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "../lv_draw_image_private.h"
#include "lv_draw_eve_ram_g.h"
#include "lv_eve.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void convert_row_rgb565a8_to_argb4444(const uint8_t * src, const uint8_t * src_alpha, uint8_t * dst,
uint32_t width);
static void convert_row_argb8888_to_argb4444(const uint8_t * src, uint8_t * dst, uint32_t width);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
#define F16_PIVOT_SHIFT(x) ((int32_t)((((x) >> 1)) * 65536L))
#define F16_SCALE_DIV_256(x) ((int32_t)(((x) / 256.0f) * 65536L))
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords)
{
if(lv_image_src_get_type(draw_dsc->src) != LV_IMAGE_SRC_VARIABLE) {
LV_LOG_WARN("v_draw_eve can only render images from variables (not files or symbols) for now.");
return;
}
const lv_image_dsc_t * img_dsc = draw_dsc->src;
int32_t clip_w = lv_area_get_width(&t->clip_area);
int32_t clip_h = lv_area_get_height(&t->clip_area);
const uint8_t * src_buf = img_dsc->data;
int32_t src_w = img_dsc->header.w;
int32_t src_h = img_dsc->header.h;
int32_t src_stride = img_dsc->header.stride;
lv_color_format_t src_cf = img_dsc->header.cf;
if(src_stride == 0) {
src_stride = src_w * lv_color_format_get_size(src_cf);
}
uint8_t eve_format;
int32_t eve_stride;
uint8_t eve_alignment;
switch(src_cf) {
case LV_COLOR_FORMAT_L8:
eve_format = EVE_L8;
eve_stride = src_stride;
eve_alignment = 1;
break;
case LV_COLOR_FORMAT_RGB565:
eve_format = EVE_RGB565;
eve_stride = src_stride;
eve_alignment = 2;
break;
case LV_COLOR_FORMAT_RGB565A8:
case LV_COLOR_FORMAT_ARGB8888:
eve_format = EVE_ARGB4;
eve_stride = src_w * 2;
eve_alignment = 2;
break;
default :
LV_LOG_WARN("v_draw_eve can only render L8, RGB565, RGB565A8, and ARGB8888 images for now.");
return;
}
int32_t eve_size = eve_stride * src_h;
uint32_t img_addr;
bool img_is_loaded = lv_draw_eve_ramg_get_addr(&img_addr, (uintptr_t) src_buf, eve_size, eve_alignment);
if(!img_is_loaded) { /* New image to load */
if(img_addr == LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
LV_LOG_WARN("Could not load image because space could not be allocated in RAM_G.");
return;
}
/* Load image to RAM_G */
EVE_end_cmd_burst();
switch(src_cf) {
case LV_COLOR_FORMAT_L8 :
case LV_COLOR_FORMAT_RGB565 :
EVE_memWrite_flash_buffer(img_addr, src_buf, eve_size);
break;
case LV_COLOR_FORMAT_RGB565A8 : {
uint8_t * tmp_buf = lv_malloc(eve_stride);
LV_ASSERT_MALLOC(tmp_buf);
const uint8_t * src_alpha_buf = src_buf + src_h * src_stride;
int32_t src_alpha_stride = src_stride / 2;
for(uint32_t y = 0; y < src_h; y++) {
convert_row_rgb565a8_to_argb4444(src_buf + y * src_stride, src_alpha_buf + y * src_alpha_stride, tmp_buf, src_w);
EVE_memWrite_flash_buffer(img_addr + y * eve_stride, tmp_buf, eve_stride);
}
lv_free(tmp_buf);
break;
}
case LV_COLOR_FORMAT_ARGB8888 : {
uint8_t * tmp_buf = lv_malloc(eve_stride);
LV_ASSERT_MALLOC(tmp_buf);
for(uint32_t y = 0; y < src_h; y++) {
convert_row_argb8888_to_argb4444(src_buf + y * src_stride, tmp_buf, src_w);
EVE_memWrite_flash_buffer(img_addr + y * eve_stride, tmp_buf, eve_stride);
}
lv_free(tmp_buf);
break;
}
default :
return;
}
EVE_start_cmd_burst();
}
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_save_context();
if(draw_dsc->recolor_opa > LV_OPA_MIN) {
lv_eve_color_opa(draw_dsc->recolor_opa);
lv_eve_color(draw_dsc->recolor);
}
lv_eve_primitive(LV_EVE_PRIMITIVE_BITMAPS);
EVE_cmd_dl_burst(BITMAP_SOURCE(img_addr));
/*real height and width is mandatory for rotation and scale (Clip Area)*/
EVE_cmd_dl_burst(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, clip_w, clip_h));
EVE_cmd_dl_burst(BITMAP_LAYOUT(eve_format, eve_stride, src_h));
if(draw_dsc->rotation || draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
EVE_cmd_dl_burst(CMD_LOADIDENTITY);
EVE_cmd_translate_burst(F16(coords->x1 - t->clip_area.x1 + draw_dsc->pivot.x),
F16(coords->y1 - t->clip_area.y1 + draw_dsc->pivot.y));
if(draw_dsc->scale_x != LV_SCALE_NONE || draw_dsc->scale_y != LV_SCALE_NONE) {
/*Image Scale*/
EVE_cmd_scale_burst(F16_SCALE_DIV_256(draw_dsc->scale_x), F16_SCALE_DIV_256(draw_dsc->scale_y));
}
if(draw_dsc->rotation != 0) {
/*Image Rotate*/
EVE_cmd_rotate_burst(DEGREES(draw_dsc->rotation));
}
EVE_cmd_translate_burst(-F16(draw_dsc->pivot.x), -F16(draw_dsc->pivot.y));
EVE_cmd_dl_burst(CMD_SETMATRIX);
EVE_cmd_dl_burst(CMD_LOADIDENTITY);
lv_eve_vertex_2f(t->clip_area.x1, t->clip_area.y1);
}
else {
lv_eve_vertex_2f(coords->x1, coords->y1);
}
lv_eve_restore_context();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void convert_row_rgb565a8_to_argb4444(const uint8_t * src, const uint8_t * src_alpha, uint8_t * dst,
uint32_t width)
{
for(uint32_t x = 0; x < width; x++) {
uint16_t rgb565 = ((const uint16_t *) src)[x];
uint8_t r5 = (rgb565 >> 11) & 0x1F;
uint8_t g6 = (rgb565 >> 5) & 0x3F;
uint8_t b5 = rgb565 & 0x1F;
uint8_t alpha = src_alpha[x];
uint8_t r4 = r5 >> 1;
uint8_t g4 = g6 >> 2;
uint8_t b4 = b5 >> 1;
uint8_t a4 = alpha >> 4;
uint16_t argb4444 = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
dst[2 * x] = argb4444 & 0xFF;
dst[2 * x + 1] = (argb4444 >> 8) & 0xFF;
}
}
static void convert_row_argb8888_to_argb4444(const uint8_t * src, uint8_t * dst, uint32_t width)
{
for(uint32_t x = 0; x < width; x++) {
uint8_t blue = src[4 * x];
uint8_t green = src[4 * x + 1];
uint8_t red = src[4 * x + 2];
uint8_t alpha = src[4 * x + 3];
uint8_t r4 = red >> 4;
uint8_t g4 = green >> 4;
uint8_t b4 = blue >> 4;
uint8_t a4 = alpha >> 4;
uint16_t argb4444 = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
dst[2 * x] = argb4444 & 0xFF;
dst[2 * x + 1] = (argb4444 >> 8) & 0xFF;
}
}
#endif /*LV_USE_DRAW_EVE*/
+196
View File
@@ -0,0 +1,196 @@
/**
* @file lv_draw_eve_letter.c
*
*/
/* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "../lv_draw_private.h"
#include "../lv_draw_label_private.h"
#include "../lv_draw_rect.h"
#include "lv_eve.h"
#include "lv_draw_eve_ram_g.h"
#include "../../font/lv_font_fmt_txt.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_eve_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_dsc,
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
static void font_bitmap_to_ramg(uint32_t addr, const uint8_t * src, uint32_t width,
uint32_t height);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
#define GET_NIBBLE_1(w) ((uint8_t) ((w) >> 4))
#define GET_NIBBLE_2(w) ((uint8_t) ((w) & 0xf))
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_label(lv_draw_task_t * t, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords)
{
if(dsc->opa <= LV_OPA_MIN) return;
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_save_context();
lv_eve_primitive(LV_EVE_PRIMITIVE_BITMAPS);
lv_draw_label_iterate_characters(t, dsc, coords, lv_draw_eve_letter_cb);
lv_eve_restore_context();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_draw_eve_letter_cb(lv_draw_task_t * t, lv_draw_glyph_dsc_t * glyph_draw_dsc,
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
{
if(fill_draw_dsc && fill_area) {
/* draw UNDERLINE and STRIKETHROUGH */
lv_eve_draw_rect_simple(fill_area->x1, fill_area->y1, fill_area->x2, fill_area->y2, 0);
}
if(glyph_draw_dsc == NULL)
return; /* Important */
const lv_font_t * font = glyph_draw_dsc->g->resolved_font;
if(font->get_glyph_bitmap != lv_font_get_bitmap_fmt_txt) {
LV_LOG_WARN("lv_draw_eve can only render static fonts for now.");
return;
}
if(glyph_draw_dsc->format != LV_FONT_GLYPH_FORMAT_A4) {
LV_LOG_WARN("lv_draw_eve can only render 4 BPP fonts for now.");
return;
}
const lv_font_fmt_txt_dsc_t * font_dsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
uint32_t gid_index = glyph_draw_dsc->g->gid.index;
const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc = &font_dsc->glyph_dsc[gid_index];
const uint8_t * glyph_bitmap = &font_dsc->glyph_bitmap[glyph_dsc->bitmap_index];
uint16_t g_box_w = glyph_dsc->box_w;
uint16_t g_box_h = glyph_dsc->box_h;
uint16_t g_aligned_stride = (g_box_w + 1) / 2;
/* Only 4 bpp is supported for now. Support for 1 and 8 bpp can be added. (EVE_L1, EVE_L8) */
uint8_t bpp_eve = EVE_L4;
uint32_t glyph_ramg_size = g_aligned_stride * g_box_h;
uint32_t ramg_addr;
uintptr_t glyph_ramg_key = (uintptr_t) glyph_bitmap;
bool font_is_loaded = lv_draw_eve_ramg_get_addr(&ramg_addr, glyph_ramg_key, glyph_ramg_size, 1);
if(!font_is_loaded) { /* If the font is not yet loaded in ramG, load it */
if(ramg_addr == LV_DRAW_EVE_RAMG_OUT_OF_RAMG) {
LV_LOG_WARN("Could not load glyph because space could not be allocated in RAM_G.");
return;
}
font_bitmap_to_ramg(ramg_addr, glyph_bitmap, g_box_w, g_box_h);
}
lv_eve_color_opa(glyph_draw_dsc->opa);
lv_eve_color(glyph_draw_dsc->color);
EVE_cmd_dl_burst(BITMAP_SOURCE(ramg_addr));
EVE_cmd_dl_burst(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, g_box_w, g_box_h));
EVE_cmd_dl_burst(BITMAP_LAYOUT(bpp_eve, g_aligned_stride, g_box_h));
lv_eve_vertex_2f(glyph_draw_dsc->letter_coords->x1, glyph_draw_dsc->letter_coords->y1);
}
static void font_bitmap_to_ramg(uint32_t addr, const uint8_t * src, uint32_t width,
uint32_t height)
{
EVE_end_cmd_burst();
uint32_t stride = (width + 1) / 2;
if(width % 2 == 0) {
uint32_t size = stride * height;
EVE_memWrite_flash_buffer(addr, src, size);
EVE_start_cmd_burst();
return;
}
uint8_t * row_buf = lv_malloc(stride);
LV_ASSERT_MALLOC(row_buf);
uint32_t src_i = 0;
uint8_t nibble_1;
uint8_t nibble_2;
uint8_t key = 0;
/* Iterate through each row of the bitmap*/
for(uint32_t y = 0; y < height; y++) {
/* Iterate through each byte of the row*/
uint32_t row_i;
for(row_i = 0; row_i < (width / 2); ++row_i) {
/*Get the two nibbles from the current byte*/
if(key == 0) {
nibble_1 = GET_NIBBLE_1(src[src_i]);
nibble_2 = GET_NIBBLE_2(src[src_i]);
}
else {
nibble_1 = GET_NIBBLE_2(src[src_i - 1]);
nibble_2 = GET_NIBBLE_1(src[src_i]);
}
/*Combine the nibbles and assign the result to the output byte*/
row_buf[row_i] = (nibble_1 << 4) | nibble_2;
src_i++;
}
/*process the last remaining nibble*/
row_buf[row_i] =
(key == 0) ?
(GET_NIBBLE_1(src[src_i])) << 4 | 0x0 : (GET_NIBBLE_2(src[src_i - 1])) << 4 | 0x0;
key = (key == 0) ? 1 : 0;
src_i += (key == 1) ? 1 : 0;
EVE_memWrite_sram_buffer(addr, row_buf, stride);
addr += stride;
}
lv_free(row_buf);
EVE_start_cmd_burst();
}
#endif /*LV_USE_DRAW_EVE*/
+63
View File
@@ -0,0 +1,63 @@
/**
* @file lv_draw_eve_line.c
*
*/
/* Created on: 8 abr 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "lv_eve.h"
void lv_draw_eve_line(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc)
{
if(dsc->width == 0)
return;
if(dsc->opa <= LV_OPA_MIN)
return;
if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y)
return;
uint32_t line_w = dsc->width * 8;
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_save_context();
lv_eve_color_opa(dsc->opa);
lv_eve_color(dsc->color);
if(dsc->dash_gap || dsc->dash_width) {
LV_LOG_WARN("line dash_gap and dash_width not implemented by EVE yet.");
}
/* Check if it's a vertical or horizontal line without rounding */
bool is_vertical = (dsc->p1.x == dsc->p2.x);
bool is_horizontal = (dsc->p1.y == dsc->p2.y);
bool no_round = (!dsc->round_end || !dsc->round_start);
if((is_vertical || is_horizontal) && no_round) {
lv_eve_primitive(LV_EVE_PRIMITIVE_RECTS);
lv_eve_vertex_2f(dsc->p1.x, dsc->p1.y);
lv_eve_vertex_2f(dsc->p2.x, dsc->p2.y);
}
else {
/* Draw inclined line or line with rounding (not possible without rounding)*/
lv_eve_primitive(LV_EVE_PRIMITIVE_LINE_STRIP);
lv_eve_line_width(line_w);
lv_eve_vertex_2f(dsc->p1.x, dsc->p1.y);
lv_eve_vertex_2f(dsc->p2.x, dsc->p2.y);
}
lv_eve_restore_context();
}
#endif /*LV_USE_DRAW_EVE*/
+99
View File
@@ -0,0 +1,99 @@
/**
* @file lv_draw_eve_private.h
*
*/
/* Author: juanj
*
* Modified by LVGL
*/
#ifndef LV_DRAW_EVE_PRIVATE_H
#define LV_DRAW_EVE_PRIVATE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve.h"
#if LV_USE_DRAW_EVE
#include "lv_draw_eve_target.h"
#include "../lv_draw_private.h"
#include "../../misc/lv_types.h"
#include "../../core/lv_global.h"
#include "../lv_draw_triangle.h"
#include "../lv_draw_line.h"
#include "../lv_draw_label.h"
#include "../lv_draw_arc.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct {
uintptr_t key;
uint32_t addr;
} lv_draw_eve_ramg_hash_table_cell_t;
typedef struct {
uint32_t ramg_addr_end;
uint32_t hash_table_cell_count;
uint32_t hash_table_cells_occupied;
lv_draw_eve_ramg_hash_table_cell_t * hash_table;
} lv_draw_eve_ramg_t;
struct _lv_draw_eve_unit_t {
lv_draw_unit_t base_unit;
lv_draw_task_t * task_act;
lv_display_t * disp;
lv_draw_eve_ramg_t ramg;
lv_draw_eve_parameters_t params;
lv_draw_eve_operation_cb_t op_cb;
};
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_eve_image(lv_draw_task_t * t, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords);
void lv_draw_eve_fill(lv_draw_task_t * t, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_eve_border(lv_draw_task_t * t, const lv_draw_border_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_eve_line(lv_draw_task_t * t, const lv_draw_line_dsc_t * dsc);
void lv_draw_eve_label(lv_draw_task_t * t, const lv_draw_label_dsc_t * dsc,
const lv_area_t * coords);
void lv_draw_eve_arc(lv_draw_task_t * t, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords);
void lv_draw_eve_triangle(lv_draw_task_t * t, const lv_draw_triangle_dsc_t * dsc);
/**********************
* MACROS
**********************/
#define DEGREES(n) ((65536UL * (n)) / 3600)
#define F16(x) ((int32_t)((x) * 65536L))
#define lv_draw_eve_unit_g (LV_GLOBAL_DEFAULT()->draw_eve_unit)
#endif /*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_EVE_PRIVATE_H*/
+221
View File
@@ -0,0 +1,221 @@
/**
* @file lv_draw_eve_ram_g.c
*
*/
/* Created on: 19 nov 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "lv_draw_eve_ram_g.h"
#include "lv_eve.h"
/*********************
* DEFINES
*********************/
#define RAMG_DEBUG 0
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void ramg_init(lv_draw_eve_ramg_t * ramg);
static uint32_t hash_key(uintptr_t key);
static uint32_t fnv_1a_hash(const void * src, size_t len);
static void grow_hash_table(lv_draw_eve_ramg_t * ramg);
#if RAMG_DEBUG
static void ramg_debug(lv_draw_eve_ramg_t * ramg, uint32_t key_hash, uint32_t table_index);
#endif
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
bool lv_draw_eve_ramg_get_addr(uint32_t * addr_dst, uintptr_t key,
uint32_t addr_size, uint32_t addr_align)
{
LV_ASSERT(key != 0);
lv_draw_eve_ramg_t * ramg = &lv_draw_eve_unit_g->ramg;
if(ramg->hash_table_cell_count == 0) {
ramg_init(ramg);
}
uint32_t key_hash = hash_key(key);
uint32_t table_index = key_hash % ramg->hash_table_cell_count;
lv_draw_eve_ramg_hash_table_cell_t * cell;
while(1) {
cell = &ramg->hash_table[table_index];
if(cell->key == key) {
#if RAMG_DEBUG
ramg_debug(ramg, key_hash, table_index);
#endif
*addr_dst = cell->addr;
return true;
}
if(cell->key == 0) {
break;
}
table_index++;
if(table_index >= ramg->hash_table_cell_count) table_index = 0;
}
uint32_t addr_ret = LV_ALIGN_UP(ramg->ramg_addr_end, addr_align);
uint32_t addr_new_end = addr_ret + addr_size;
if(addr_new_end > 1024 * 1024) {
LV_LOG_WARN("EVE on-chip 1 MB RAM_G for images and fonts has run out.");
*addr_dst = LV_DRAW_EVE_RAMG_OUT_OF_RAMG;
return false;
}
ramg->ramg_addr_end = addr_new_end;
ramg->hash_table_cells_occupied++;
cell->key = key;
cell->addr = addr_ret;
*addr_dst = addr_ret;
#if RAMG_DEBUG
ramg_debug(ramg, key_hash, table_index);
#endif
if(ramg->hash_table_cells_occupied > ramg->hash_table_cell_count / 4 * 3) {
grow_hash_table(ramg);
}
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void ramg_init(lv_draw_eve_ramg_t * ramg)
{
ramg->hash_table_cell_count = 32;
ramg->hash_table = lv_calloc(32, sizeof(lv_draw_eve_ramg_hash_table_cell_t));
LV_ASSERT_MALLOC(ramg->hash_table);
}
static uint32_t hash_key(uintptr_t key)
{
return fnv_1a_hash(&key, sizeof(key));
}
static uint32_t fnv_1a_hash(const void * src, size_t len)
{
const uint8_t * src_u8 = src;
uint32_t hash = 2166136261u;
for(size_t i = 0; i < len; i++) {
hash ^= src_u8[i];
hash *= 16777619u;
}
return hash;
}
static void grow_hash_table(lv_draw_eve_ramg_t * ramg)
{
uint32_t old_cell_count = ramg->hash_table_cell_count;
lv_draw_eve_ramg_hash_table_cell_t * old_hash_table = ramg->hash_table;
ramg->hash_table_cell_count += ramg->hash_table_cell_count / 2;
ramg->hash_table = lv_calloc(ramg->hash_table_cell_count,
sizeof(lv_draw_eve_ramg_hash_table_cell_t));
LV_ASSERT_MALLOC(ramg->hash_table);
for(uint32_t i = 0; i < old_cell_count; i++) {
lv_draw_eve_ramg_hash_table_cell_t * old_cell = &old_hash_table[i];
if(old_cell->key == 0) continue;
uint32_t key_hash = hash_key(old_cell->key);
uint32_t new_table_index = key_hash % ramg->hash_table_cell_count;
lv_draw_eve_ramg_hash_table_cell_t * new_cell_dst = &ramg->hash_table[new_table_index];
while(new_cell_dst->key != 0) {
new_table_index++;
if(new_table_index >= ramg->hash_table_cell_count) new_table_index = 0;
new_cell_dst = &ramg->hash_table[new_table_index];
}
*new_cell_dst = *old_cell;
}
lv_free(old_hash_table);
}
#if RAMG_DEBUG
/*
Print tables like this:
113 kB of RAM_G used
================================-==-=====---=---===---=====-=-=-=-==--=======----=-==-==---=--===--=-=-=========================
========^$==========--=-==-=-=--=--=========---=----========-------===--=====----=======--=====--====--=====-=--=-=
'-' unoccupied cells
'=' occupied cells
'^' where the hash pointed to in the table initially and linear probing started
'$' where linear probing ended because a matching or unoccupied cell
was found. This symbol is not shown if the initial guess was correct.
This example has 244 cells. Each cell uses 8 bytes of local RAM, so just under 2 kB.
Each cell represents an allocation in EVE RAM_G. The RAM_G allocation sizes are not
represented in this table, except for the overall "113 kB of RAM_G used" message.
*/
static void ramg_debug(lv_draw_eve_ramg_t * ramg, uint32_t key_hash, uint32_t table_index)
{
uint32_t table_index_initial_guess = key_hash % ramg->hash_table_cell_count;
lv_log("%u kB of RAM_G used\n", (unsigned) ramg->ramg_addr_end / 1024);
for(uint32_t i = 0; i < ramg->hash_table_cell_count; i++) {
if(i != 0 && i % 128 == 0) {
lv_log("\n");
}
if(i == table_index_initial_guess) {
lv_log("^");
}
else if(i == table_index) {
lv_log("$");
}
else if(ramg->hash_table[i].key) {
lv_log("=");
}
else {
lv_log("-");
}
}
lv_log("\n\n");
}
#endif
#endif/*LV_USE_EVE_DRAW*/
+48
View File
@@ -0,0 +1,48 @@
/**
* @file lv_draw_eve_ram_g.h
*
*/
/* Created on: 19 nov 2023
* Author: juanj
*
* Modified by LVGL
*/
#ifndef LV_DRAW_EVE_RAM_G_H
#define LV_DRAW_EVE_RAM_G_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve.h"
#if LV_USE_DRAW_EVE
/*********************
* DEFINES
*********************/
#define LV_DRAW_EVE_RAMG_OUT_OF_RAMG UINT32_MAX
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
bool lv_draw_eve_ramg_get_addr(uint32_t * addr_dst, uintptr_t key,
uint32_t addr_size, uint32_t addr_align);
#endif/*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_DRAW_EVE_RAM_G_H */
+79
View File
@@ -0,0 +1,79 @@
/**
* @file lv_draw_eve_target.h
*
*/
#ifndef LV_DRAW_EVE_TARGET_H
#define LV_DRAW_EVE_TARGET_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../lv_conf_internal.h"
#if LV_USE_DRAW_EVE
#include "../../misc/lv_types.h"
#include LV_STDBOOL_INCLUDE
#include LV_STDINT_INCLUDE
typedef struct {
uint16_t hor_res; /**< active display width */
uint16_t ver_res; /**< active display height */
uint16_t hcycle; /**< total number of clocks per line, incl front/back porch */
uint16_t hoffset; /**< start of active line */
uint16_t hsync0; /**< start of horizontal sync pulse */
uint16_t hsync1; /**< end of horizontal sync pulse */
uint16_t vcycle; /**< total number of lines per screen, including pre/post */
uint16_t voffset; /**< start of active screen */
uint16_t vsync0; /**< start of vertical sync pulse */
uint16_t vsync1; /**< end of vertical sync pulse */
uint8_t swizzle; /**< FT8xx output to LCD - pin order */
uint8_t pclkpol; /**< LCD data is clocked in on this PCLK edge */
uint8_t cspread; /**< helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
uint8_t pclk; /**< 60MHz / pclk = pclk frequency */
bool has_crystal; /**< has an external clock crystal */
bool has_gt911; /**< has a touch controller */
uint8_t backlight_pwm; /**< backlight PWM duty cycle 0 = off, 128 = max */
uint16_t backlight_freq; /**< backlight PWM frequency. try 4000 if unsure */
} lv_draw_eve_parameters_t;
typedef enum {
LV_DRAW_EVE_OPERATION_POWERDOWN_SET, /**< set the "PD_N" pin low */
LV_DRAW_EVE_OPERATION_POWERDOWN_CLEAR, /**< set the "PD_N" pin high */
LV_DRAW_EVE_OPERATION_CS_ASSERT, /**< set the "CS_N" pin low */
LV_DRAW_EVE_OPERATION_CS_DEASSERT, /**< set the "CS_N" pin high */
LV_DRAW_EVE_OPERATION_SPI_SEND, /**< send `length` bytes of `data` over SPI */
LV_DRAW_EVE_OPERATION_SPI_RECEIVE /**< receive `length` bytes into `data` from SPI */
} lv_draw_eve_operation_t;
typedef void (*lv_draw_eve_operation_cb_t)(lv_display_t * disp, lv_draw_eve_operation_t operation, void * data,
uint32_t length);
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_EVE_TARGET_H*/
+127
View File
@@ -0,0 +1,127 @@
/**
* @file lv_draw_eve_triangle.c
*
*/
/* Created on: 10 ene 2024
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_private.h"
#if LV_USE_DRAW_EVE
#include "../../misc/lv_math.h"
#include "../../stdlib/lv_mem.h"
#include "../../misc/lv_area_private.h"
#include "../../misc/lv_color.h"
#include "../../stdlib/lv_string.h"
#include "lv_eve.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_eve_triangle(lv_draw_task_t * t, const lv_draw_triangle_dsc_t * dsc)
{
lv_area_t tri_area;
tri_area.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
tri_area.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
tri_area.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x);
tri_area.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y);
bool is_common;
lv_area_t draw_area;
is_common = lv_area_intersect(&draw_area, &tri_area, &t->clip_area);
if(!is_common) return;
lv_point_t p[3];
/*If there is a vertical side use it as p[0] and p[1]*/
if(dsc->p[0].x == dsc->p[1].x) {
p[0] = lv_point_from_precise(&dsc->p[0]);
p[1] = lv_point_from_precise(&dsc->p[1]);
p[2] = lv_point_from_precise(&dsc->p[2]);
}
else if(dsc->p[0].x == dsc->p[2].x) {
p[0] = lv_point_from_precise(&dsc->p[0]);
p[1] = lv_point_from_precise(&dsc->p[2]);
p[2] = lv_point_from_precise(&dsc->p[1]);
}
else if(dsc->p[1].x == dsc->p[2].x) {
p[0] = lv_point_from_precise(&dsc->p[1]);
p[1] = lv_point_from_precise(&dsc->p[2]);
p[2] = lv_point_from_precise(&dsc->p[0]);
}
else {
p[0] = lv_point_from_precise(&dsc->p[0]);
p[1] = lv_point_from_precise(&dsc->p[1]);
p[2] = lv_point_from_precise(&dsc->p[2]);
/*Set the smallest y as p[0]*/
if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]);
if(p[0].y > p[2].y) lv_point_swap(&p[0], &p[2]);
/*Set the greatest y as p[1]*/
if(p[1].y < p[2].y) lv_point_swap(&p[1], &p[2]);
}
/*Be sure p[0] is on the top*/
if(p[0].y > p[1].y) lv_point_swap(&p[0], &p[1]);
lv_eve_save_context();
lv_eve_scissor(t->clip_area.x1, t->clip_area.y1, t->clip_area.x2, t->clip_area.y2);
lv_eve_color(dsc->color);
lv_eve_color_opa(dsc->opa);
lv_eve_color_mask(0, 0, 0, 0);
lv_eve_stencil_op(EVE_KEEP, EVE_INVERT);
lv_eve_stencil_func(EVE_ALWAYS, 255, 255);
lv_eve_primitive(LV_EVE_PRIMITIVE_EDGE_STRIP_A);
lv_eve_vertex_2f(p[0].x, p[0].y);
lv_eve_vertex_2f(p[1].x, p[1].y);
lv_eve_vertex_2f(p[2].x, p[2].y);
lv_eve_color_mask(1, 1, 1, 1);
lv_eve_stencil_func(EVE_EQUAL, 255, 255) ;
lv_eve_vertex_2f(0, 0);
lv_eve_vertex_2f(1022, 0);
lv_eve_restore_context();
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_EVE*/
+224
View File
@@ -0,0 +1,224 @@
/**
* @file lv_eve.c
*
*/
/* Created on: 8 jun 2023
* Author: juanj
*
* Modified by LVGL
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve.h"
#if LV_USE_DRAW_EVE
#include "lv_eve.h"
#include "../../libs/FT800-FT813/EVE_commands.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static uint16_t scissor_x1 = 0;
static uint16_t scissor_y1 = 0;
static uint16_t scissor_x2 = 0;
static uint16_t scissor_y2 = 0;
static lv_eve_drawing_context_t ct = {
.primitive = LV_EVE_PRIMITIVE_ZERO_VALUE,
.color = {0xff, 0xff, 0xff},
.opa = 255,
.line_width = 1, /* for format(0) */
.point_size = 1,
.color_mask = {1, 1, 1, 1},
.stencil_func = {EVE_ALWAYS, 0, 255},
.stencil_op = {EVE_KEEP, EVE_KEEP},
.blend_func = {EVE_SRC_ALPHA, EVE_ONE_MINUS_SRC_ALPHA},
.scx = 0,
.scy = 0,
};
static lv_eve_drawing_context_t ct_temp;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_eve_save_context(void)
{
EVE_cmd_dl_burst(DL_SAVE_CONTEXT);
ct_temp = ct;
}
void lv_eve_restore_context(void)
{
EVE_cmd_dl_burst(DL_RESTORE_CONTEXT);
ct = ct_temp;
}
void lv_eve_primitive(uint8_t context)
{
if(context != ct.primitive && context != LV_EVE_PRIMITIVE_ZERO_VALUE) {
EVE_cmd_dl_burst(DL_BEGIN | context);
ct.primitive = context;
}
}
void lv_eve_scissor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
if(x1 != scissor_x1 || y1 != scissor_y1) {
int16_t adjusted_x1 = x1 > 0 ? x1 - 1 : 0;
int16_t adjusted_y1 = y1 > 0 ? y1 - 1 : 0;
EVE_cmd_dl_burst(SCISSOR_XY(adjusted_x1, adjusted_y1));
scissor_x1 = x1;
scissor_y1 = y1;
}
if(x2 != scissor_x2 || y2 != scissor_y2) {
uint16_t w = x2 - x1 + 3;
uint16_t h = y2 - y1 + 3;
EVE_cmd_dl_burst(SCISSOR_SIZE(w, h));
scissor_x2 = x2;
scissor_y2 = y2;
}
}
void lv_eve_color(lv_color_t color)
{
if((ct.color.red != color.red) || (ct.color.green != color.green) || (ct.color.blue != color.blue)) {
EVE_cmd_dl_burst(COLOR_RGB(color.red, color.green, color.blue));
ct.color = color;
}
}
void lv_eve_color_mask(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if((ct.color_mask[0] != r) ||
(ct.color_mask[1] != g) ||
(ct.color_mask[2] != b) ||
(ct.color_mask[3] != a)) {
EVE_cmd_dl_burst(COLOR_MASK(r, g, b, a));
ct.color_mask[0] = r;
ct.color_mask[1] = g;
ct.color_mask[2] = b;
ct.color_mask[3] = a;
}
}
void lv_eve_stencil_func(uint8_t func, uint8_t ref, uint8_t mask)
{
if(func != ct.stencil_func[0] || ref != ct.stencil_func[1] || mask != ct.stencil_func[2]) {
EVE_cmd_dl_burst(STENCIL_FUNC(func, ref, mask));
ct.stencil_func[0] = func;
ct.stencil_func[1] = ref;
ct.stencil_func[2] = mask;
}
}
void lv_eve_stencil_op(uint8_t sfail, uint8_t spass)
{
if(sfail != ct.stencil_op[0] || spass != ct.stencil_op[1]) {
EVE_cmd_dl_burst(STENCIL_OP(sfail, spass));
ct.stencil_op[0] = sfail;
ct.stencil_op[1] = spass;
}
}
void lv_eve_blend_func(uint8_t src, uint8_t dst)
{
if(src != ct.blend_func[0] || dst != ct.blend_func[1]) {
EVE_cmd_dl_burst(BLEND_FUNC(src, dst));
ct.blend_func[0] = src;
ct.blend_func[1] = dst;
}
}
void lv_eve_color_opa(lv_opa_t opa)
{
if(opa != ct.opa) {
EVE_cmd_dl_burst(COLOR_A(opa));
ct.opa = opa;
}
}
void lv_eve_line_width(int32_t width)
{
if(width != ct.line_width) {
EVE_cmd_dl_burst(LINE_WIDTH(width));
ct.line_width = width;
}
}
void lv_eve_point_size(uint16_t radius)
{
if(radius != ct.point_size) {
EVE_cmd_dl_burst(POINT_SIZE(radius * 16));
ct.point_size = radius;
}
}
void lv_eve_vertex_2f(int16_t x, int16_t y)
{
EVE_cmd_dl_burst(VERTEX2F(x, y));
}
void lv_eve_draw_circle_simple(int16_t coord_x1, int16_t coord_y1, uint16_t radius_t)
{
lv_eve_primitive(LV_EVE_PRIMITIVE_POINTS);
lv_eve_point_size(radius_t);
lv_eve_vertex_2f(coord_x1, coord_y1);
}
void lv_eve_draw_rect_simple(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, uint16_t radius)
{
lv_eve_primitive(LV_EVE_PRIMITIVE_RECTS);
if(radius > 1) {
lv_eve_line_width(radius * 16);
}
lv_eve_vertex_2f(coord_x1 + radius, coord_y1 + radius);
lv_eve_vertex_2f(coord_x2 - radius, coord_y2 - radius);
}
void lv_eve_mask_round(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, int16_t radius)
{
lv_eve_color_mask(0, 0, 0, 1);
EVE_cmd_dl_burst(CLEAR(1, 1, 1));
lv_eve_draw_rect_simple(coord_x1, coord_y1, coord_x2, coord_y2, radius);
lv_eve_color_mask(1, 1, 1, 0);
lv_eve_blend_func(EVE_DST_ALPHA, EVE_ONE_MINUS_DST_ALPHA);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_EVE*/
+113
View File
@@ -0,0 +1,113 @@
/**
* @file lv_eve.h
*
*/
/* Created on: 8 jun 2023
* Author: juanj
*
* Modified by LVGL
*/
#ifndef LV_EVE_H
#define LV_EVE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve.h"
#if LV_USE_DRAW_EVE
#include "../../misc/lv_types.h"
#include "../../misc/lv_color.h"
#include "../../libs/FT800-FT813/EVE.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_EVE_PRIMITIVE_ZERO_VALUE,
LV_EVE_PRIMITIVE_BITMAPS = 1UL, /* Bitmap drawing primitive */
LV_EVE_PRIMITIVE_POINTS = 2UL, /* Point drawing primitive */
LV_EVE_PRIMITIVE_LINES = 3UL, /* Line drawing primitive */
LV_EVE_PRIMITIVE_LINE_STRIP = 4UL, /* Line strip drawing primitive */
LV_EVE_PRIMITIVE_EDGE_STRIP_R = 5UL, /* Edge strip right side drawing primitive */
LV_EVE_PRIMITIVE_EDGE_STRIP_L = 6UL, /* Edge strip left side drawing primitive */
LV_EVE_PRIMITIVE_EDGE_STRIP_A = 7UL, /* Edge strip above drawing primitive */
LV_EVE_PRIMITIVE_EDGE_STRIP_B = 8UL, /* Edge strip below side drawing primitive */
LV_EVE_PRIMITIVE_RECTS = 9UL, /* Rectangle drawing primitive */
} lv_eve_primitive_t;
typedef struct {
lv_eve_primitive_t primitive;
lv_color_t color;
lv_opa_t opa;
int32_t line_width;
uint16_t point_size;
uint8_t color_mask[4];
uint8_t stencil_func[3];
uint8_t stencil_op[2];
uint8_t blend_func[2];
uint16_t scx;
uint16_t scy;
} lv_eve_drawing_context_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_eve_save_context(void);
void lv_eve_restore_context(void);
void lv_eve_scissor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void lv_eve_primitive(uint8_t context);
void lv_eve_color(lv_color_t color);
void lv_eve_color_opa(lv_opa_t opa);
void lv_eve_line_width(int32_t width);
void lv_eve_point_size(uint16_t radius);
void lv_eve_vertex_2f(int16_t x, int16_t y);
void lv_eve_color_mask(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
void lv_eve_stencil_func(uint8_t func, uint8_t ref, uint8_t mask);
void lv_eve_stencil_op(uint8_t sfail, uint8_t spass);
void lv_eve_blend_func(uint8_t sfail, uint8_t spass);
void lv_eve_draw_circle_simple(int16_t coord_x1, int16_t coord_y1, uint16_t radius_t);
void lv_eve_draw_rect_simple(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2,
uint16_t radius);
void lv_eve_mask_round(int16_t coord_x1, int16_t coord_y1, int16_t coord_x2, int16_t coord_y2, int16_t radius);
/**********************
* EXTERN VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* INLINE FUNCTIONS
**********************/
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_EVE_H */
+19 -18
View File
@@ -28,24 +28,24 @@ extern "C" {
**********************/
typedef struct {
uint16_t hor_res;
uint16_t ver_res;
uint16_t hor_res; /**< active display width */
uint16_t ver_res; /**< active display height */
uint16_t hcycle;
uint16_t hoffset;
uint16_t hsync0;
uint16_t hsync1;
uint16_t vcycle;
uint16_t voffset;
uint16_t vsync0;
uint16_t vsync1;
uint8_t swizzle;
uint8_t pclkpol;
uint8_t cspread;
uint8_t pclk;
uint16_t hcycle; /**< total number of clocks per line, incl front/back porch */
uint16_t hoffset; /**< start of active line */
uint16_t hsync0; /**< start of horizontal sync pulse */
uint16_t hsync1; /**< end of horizontal sync pulse */
uint16_t vcycle; /**< total number of lines per screen, including pre/post */
uint16_t voffset; /**< start of active screen */
uint16_t vsync0; /**< start of vertical sync pulse */
uint16_t vsync1; /**< end of vertical sync pulse */
uint8_t swizzle; /**< FT8xx output to LCD - pin order */
uint8_t pclkpol; /**< LCD data is clocked in on this PCLK edge */
uint8_t cspread; /**< helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
uint8_t pclk; /**< 60MHz / pclk = pclk frequency */
bool has_crystal;
bool is_bt81x;
bool has_crystal; /**< has an external clock crystal */
bool is_bt81x; /**< is a BT series model, not FT */
} lv_ft81x_parameters_t;
typedef enum {
@@ -53,9 +53,10 @@ typedef enum {
LV_FT81X_SPI_OPERATION_CS_DEASSERT,
LV_FT81X_SPI_OPERATION_SEND,
LV_FT81X_SPI_OPERATION_RECEIVE
} lv_ft81x_spi_operation;
} lv_ft81x_spi_operation_t;
typedef void (*lv_ft81x_spi_cb_t)(lv_display_t * disp, lv_ft81x_spi_operation operation, void * data, uint32_t length);
typedef void (*lv_ft81x_spi_cb_t)(lv_display_t * disp, lv_ft81x_spi_operation_t operation, void * data,
uint32_t length);
/**********************
* GLOBAL PROTOTYPES
+204
View File
@@ -0,0 +1,204 @@
/**
* @file lv_draw_eve_display.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_eve_display.h"
#if LV_USE_DRAW_EVE
#include "../../../draw/eve/lv_eve.h"
#include "../../../draw/eve/lv_draw_eve.h"
#include "../../../display/lv_display_private.h"
#include "../../../libs/FT800-FT813/EVE_commands.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
static void resolution_changed_cb(lv_event_t * e);
static void touch_read_cb(lv_indev_t * indev, lv_indev_data_t * data);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_display_t * lv_draw_eve_display_create(const lv_draw_eve_parameters_t * params, lv_draw_eve_operation_cb_t op_cb,
void * user_data)
{
static uint8_t dummy_buf; /* It won't be used as it will send commands instead of draw pixels. */
lv_display_t * disp = lv_display_create(params->hor_res, params->ver_res);
lv_display_set_flush_cb(disp, flush_cb);
lv_display_set_buffers(disp, &dummy_buf, NULL,
params->hor_res * params->ver_res * LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_NATIVE),
LV_DISPLAY_RENDER_MODE_FULL); /* recreate the full display list each refresh */
lv_display_add_event_cb(disp, resolution_changed_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
lv_display_set_driver_data(disp, user_data);
lv_draw_eve_set_display_data(disp, params, op_cb);
EVE_init();
EVE_memWrite8(REG_PWM_DUTY, EVE_BACKLIGHT_PWM); /* 0 = off, 0x80 = max */
EVE_start_cmd_burst();
EVE_cmd_dl_burst(CMD_DLSTART); /* start the display list */
EVE_cmd_dl_burst(DL_CLEAR_COLOR_RGB | 0x000000);
EVE_cmd_dl_burst(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
EVE_cmd_dl_burst(VERTEX_FORMAT(0));
EVE_end_cmd_burst();
return disp;
}
void * lv_draw_eve_display_get_user_data(lv_display_t * disp)
{
return lv_display_get_driver_data(disp);
}
lv_indev_t * lv_draw_eve_touch_create(lv_display_t * disp)
{
lv_indev_t * indev = lv_indev_create();
lv_indev_set_display(indev, disp);
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, touch_read_cb);
return indev;
}
uint8_t lv_draw_eve_memread8(lv_display_t * disp, uint32_t address)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command without a draw_eve display");
return EVE_memRead8(address);
}
uint16_t lv_draw_eve_memread16(lv_display_t * disp, uint32_t address)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command with a non-draw_eve display");
return EVE_memRead16(address);
}
uint32_t lv_draw_eve_memread32(lv_display_t * disp, uint32_t address)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command with a non-draw_eve display");
return EVE_memRead32(address);
}
void lv_draw_eve_memwrite8(lv_display_t * disp, uint32_t address, uint8_t data)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command with a non-draw_eve display");
EVE_memWrite8(address, data);
}
void lv_draw_eve_memwrite16(lv_display_t * disp, uint32_t address, uint16_t data)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command with a non-draw_eve display");
EVE_memWrite16(address, data);
}
void lv_draw_eve_memwrite32(lv_display_t * disp, uint32_t address, uint32_t data)
{
LV_ASSERT_MSG(disp->flush_cb == flush_cb, "tried to use an LVGL EVE command with a non-draw_eve display");
EVE_memWrite32(address, data);
}
/**********************
* STATIC FUNCTIONS
**********************/
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
if(lv_display_flush_is_last(disp)) {
EVE_start_cmd_burst();
EVE_cmd_dl_burst(DL_DISPLAY); /* instruct the co-processor to show the list */
EVE_cmd_dl_burst(CMD_SWAP); /* make this list active */
EVE_end_cmd_burst();
EVE_execute_cmd();
EVE_start_cmd_burst();
EVE_cmd_dl_burst(CMD_DLSTART);
EVE_cmd_dl_burst(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
EVE_cmd_dl_burst(VERTEX_FORMAT(0));
EVE_end_cmd_burst();
}
lv_display_flush_ready(disp);
}
static void resolution_changed_cb(lv_event_t * e)
{
lv_display_t * disp = lv_event_get_target(e);
lv_display_rotation_t rotation = lv_display_get_rotation(disp);
uint32_t cmd_value;
switch(rotation) {
case LV_DISPLAY_ROTATION_0:
cmd_value = 0;
break;
case LV_DISPLAY_ROTATION_90:
cmd_value = 2;
break;
case LV_DISPLAY_ROTATION_180:
cmd_value = 1;
break;
case LV_DISPLAY_ROTATION_270:
cmd_value = 3;
break;
default:
return;
}
/* no need to rotate the touch coordinates with CMD_SETROTATE, as LVGL
* already rotates the input coordinates.
*/
EVE_memWrite8(REG_ROTATE, cmd_value);
}
static void touch_read_cb(lv_indev_t * indev, lv_indev_data_t * data)
{
lv_display_t * disp = lv_indev_get_display(indev);
if(disp == NULL || disp->flush_cb != flush_cb) return;
uint32_t xy = EVE_memRead32(REG_TOUCH_SCREEN_XY);
uint16_t x = xy >> 16;
uint16_t y = xy & 0xffff;
int32_t disp_w = lv_display_get_original_horizontal_resolution(disp);
int32_t disp_h = lv_display_get_original_vertical_resolution(disp);
if(x < disp_w && y < disp_h) {
data->state = LV_INDEV_STATE_PRESSED;
data->point.x = x;
data->point.y = y;
}
else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
#endif /*LV_USE_DRAW_EVE*/
+119
View File
@@ -0,0 +1,119 @@
/**
* @file lv_draw_eve_display.h
*
*/
#ifndef LV_DRAW_EVE_DISPLAY_H
#define LV_DRAW_EVE_DISPLAY_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_EVE
#include "../../../draw/eve/lv_draw_eve_target.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a display for the EVE draw unit.
* @param params Pointer to a struct of display parameters. Can be a temporary variable
* @param op_cb A callback that will be called to perform pin and SPI IO operations with the EVE chip
* @param user_data use `lv_draw_eve_display_get_user_data` to get this pointer inside the `op_cb`
* @return the EVE display
*/
lv_display_t * lv_draw_eve_display_create(const lv_draw_eve_parameters_t * params, lv_draw_eve_operation_cb_t op_cb,
void * user_data);
/**
* Get the `user_data` parameter that was passed to `lv_draw_eve_display_create`. Useful in the operation callback.
* @param disp pointer to the lv_draw_eve display
* @return the `user_data` pointer
*/
void * lv_draw_eve_display_get_user_data(lv_display_t * disp);
/**
* Create a touchscreen indev for the EVE display.
* @param disp pointer to the lv_draw_eve display
* @return the EVE touchscreen indev
*/
lv_indev_t * lv_draw_eve_touch_create(lv_display_t * disp);
/* Low-level EVE control functions */
/**
* Call `EVE_memRead8` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to read from
* @return the read value
*/
uint8_t lv_draw_eve_memread8(lv_display_t * disp, uint32_t address);
/**
* Call `EVE_memRead16` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to read from
* @return the read value
*/
uint16_t lv_draw_eve_memread16(lv_display_t * disp, uint32_t address);
/**
* Call `EVE_memRead32` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to read from
* @return the read value
*/
uint32_t lv_draw_eve_memread32(lv_display_t * disp, uint32_t address);
/**
* Call `EVE_memWrite8` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to write to
* @param data the value to write
*/
void lv_draw_eve_memwrite8(lv_display_t * disp, uint32_t address, uint8_t data);
/**
* Call `EVE_memWrite16` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to write to
* @param data the value to write
*/
void lv_draw_eve_memwrite16(lv_display_t * disp, uint32_t address, uint16_t data);
/**
* Call `EVE_memWrite32` for custom low-level control of the display.
* @param disp the display returned by `lv_draw_eve_display_create`
* @param address the EVE address to write to
* @param data the value to write
*/
void lv_draw_eve_memwrite32(lv_display_t * disp, uint32_t address, uint32_t data);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_EVE*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_EVE_DISPLAY_H*/
File diff suppressed because it is too large Load Diff
+3
View File
@@ -35,6 +35,9 @@ extern "C" {
#include "display/st_ltdc/lv_st_ltdc.h"
#include "display/ft81x/lv_ft81x.h"
#include "draw/eve/lv_draw_eve_display.h"
#include "draw/eve/lv_draw_eve_display_defines.h"
#include "nuttx/lv_nuttx_entry.h"
#include "nuttx/lv_nuttx_fbdev.h"
#include "nuttx/lv_nuttx_touchscreen.h"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+339
View File
@@ -0,0 +1,339 @@
/*
@file EVE_commands.h
@brief contains FT8xx / BT8xx function prototypes
@version 5.0
@date 2023-12-29
@author Rudolph Riedel
@section LICENSE
MIT License
Copyright (c) 2016-2023 Rudolph Riedel
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.
@section History
5.0
- added prototype for EVE_cmd_plkfreq()
- replaced BT81X_ENABLE with "EVE_GEN > 2"
- removed FT81X_ENABLE as FT81x already is the lowest supported chip revision now
- removed the formerly as deprected marked EVE_get_touch_tag()
- changed EVE_color_rgb() to use a 32 bit value like the rest of the color commands
- removed the meta-commands EVE_cmd_point(), EVE_cmd_line() and EVE_cmd_rect()
- removed obsolete functions EVE_get_cmdoffset(void) and EVE_report_cmdoffset(void) - cmdoffset is gone
- renamed EVE_LIB_GetProps() back to EVE_cmd_getprops() since it does not do anything special to justify a special name
- added prototype for helper function EVE_memWrite_sram_buffer()
- added prototypes for EVE_cmd_bitmap_transform() and EVE_cmd_bitmap_transform_burst()
- added prototype for EVE_cmd_playvideo()
- added prototypes for EVE_cmd_setfont_burst() and EVE_cmd_setfont2_burst()
- added prototype for EVE_cmd_videoframe()
- restructured: functions are sorted by chip-generation and within their group in alphabetical order
- reimplementedEVE_cmd_getmatrix() again, it needs to read values, not write them
- added prototypes for EVE_cmd_fontcache() and EVE_cmd_fontcachequery()
- added prototype for EVE_cmd_flashprogram()
- added prototype for EVE_cmd_calibratesub()
- added prototypes for EVE_cmd_animframeram(), EVE_cmd_animframeram_burst(), EVE_cmd_animstartram(),
EVE_cmd_animstartram_burst()
- added prototypes for EVE_cmd_apilevel(), EVE_cmd_apilevel_burst()
- added prototypes for EVE_cmd_calllist(), EVE_cmd_calllist_burst()
- added prototype for EVE_cmd_getimage()
- added prototypes for EVE_cmd_hsf(), EVE_cmd_hsf_burst()
- added prototype for EVE_cmd_linetime()
- added prototypes for EVE_cmd_newlist(), EVE_cmd_newlist_burst()
- added prototypes for EVE_cmd_runanim(), EVE_cmd_runanim_burst()
- added prototype for EVE_cmd_wait()
- removed the history from before 4.0
- added an enum with return codes to have the functions return something more meaningfull
- finally removed EVE_cmd_start() after setting it to deprecatd with the first 5.0 release
- renamed EVE_cmd_execute() to EVE_execute_cmd() to be more consistent, this is is not an EVE command
- added the return-value of EVE_FIFO_HALF_EMPTY to EVE_busy() to indicate there is more than 2048 bytes available
- removed the 4.0 history
- added parameter width to EVE_calibrate_manual()
- changed the varargs versions of cmd_button, cmd_text and cmd_toggle to use an array of uint32_t values to comply with MISRA-C
- fixed some MISRA-C issues
- basic maintenance: checked for violations of white space and indent rules
- more linter fixes for minor issues like variables shorter than 3 characters
- added EVE_color_a() / EVE_color_a_burst()
- removed EVE_cmd_newlist_burst() prototype as the function got removed earlier
- added prototype for EVE_write_display_parameters()
- added EVE_memRead_sram_buffer()
- added EVE_FAULT_RECOVERED to the list of return codes
- added defines for the state of the external flash
- added protype for EVE_get_and_reset_fault_state()
- put E_OK and E_NOT_OK in #ifndef/#endif guards as these are usually defined
already in AUTOSAR projects
- renamed EVE_FAIL_CHIPID_TIMEOUT to EVE_FAIL_REGID_TIMEOUT as suggested by #93 on github
- changed a number of function parameters from signed to unsigned following the
updated BT81x series programming guide V2.4
- commented out EVE_cmd_regread() prototype
- removed prototype for EVE_cmd_hsf_burst()
*/
#ifndef EVE_COMMANDS_H
#define EVE_COMMANDS_H
#include "EVE.h"
#if !defined E_OK
#define E_OK 0U
#endif
#if !defined E_NOT_OK
#define E_NOT_OK 1U
#endif
#define EVE_FAIL_REGID_TIMEOUT 2U
#define EVE_FAIL_RESET_TIMEOUT 3U
#define EVE_FAIL_PCLK_FREQ 4U
#define EVE_FAIL_FLASH_STATUS_INIT 5U
#define EVE_FAIL_FLASH_STATUS_DETACHED 6U
#define EVE_FAIL_FLASHFAST_NOT_SUPPORTED 7U
#define EVE_FAIL_FLASHFAST_NO_HEADER_DETECTED 8U
#define EVE_FAIL_FLASHFAST_SECTOR0_FAILED 9U
#define EVE_FAIL_FLASHFAST_BLOB_MISMATCH 10U
#define EVE_FAIL_FLASHFAST_SPEED_TEST 11U
#define EVE_IS_BUSY 12U
#define EVE_FIFO_HALF_EMPTY 13U
#define EVE_FAULT_RECOVERED 14U
#define EVE_FLASH_STATUS_INIT 0U
#define EVE_FLASH_STATUS_DETACHED 1U
#define EVE_FLASH_STATUS_BASIC 2U
#define EVE_FLASH_STATUS_FULL 3U
/* ##################################################################
helper functions
##################################################################### */
void EVE_cmdWrite(uint8_t const command, uint8_t const parameter);
uint8_t EVE_memRead8(uint32_t const ft_address);
uint16_t EVE_memRead16(uint32_t const ft_address);
uint32_t EVE_memRead32(uint32_t const ft_address);
void EVE_memWrite8(uint32_t const ft_address, uint8_t const ft_data);
void EVE_memWrite16(uint32_t const ft_address, uint16_t const ft_data);
void EVE_memWrite32(uint32_t const ft_address, uint32_t const ft_data);
void EVE_memWrite_flash_buffer(uint32_t const ft_address, const uint8_t *p_data, uint32_t const len);
void EVE_memWrite_sram_buffer(uint32_t const ft_address, const uint8_t *p_data, uint32_t const len);
void EVE_memRead_sram_buffer(uint32_t const ft_address, uint8_t *p_data, uint32_t const len);
uint8_t EVE_busy(void);
uint8_t EVE_get_and_reset_fault_state(void);
void EVE_execute_cmd(void);
/* ##################################################################
commands and functions to be used outside of display-lists
##################################################################### */
/* EVE4: BT817 / BT818 */
#if EVE_GEN > 3
void EVE_cmd_flashprogram(uint32_t dest, uint32_t src, uint32_t num);
void EVE_cmd_fontcache(uint32_t font, uint32_t ptr, uint32_t num);
void EVE_cmd_fontcachequery(uint32_t *p_total, uint32_t *p_used);
void EVE_cmd_getimage(uint32_t *p_source, uint32_t *p_fmt, uint32_t *p_width, uint32_t *p_height, uint32_t *p_palette);
void EVE_cmd_linetime(uint32_t dest);
void EVE_cmd_newlist(uint32_t adr);
uint32_t EVE_cmd_pclkfreq(uint32_t ftarget, int32_t rounding);
void EVE_cmd_wait(uint32_t usec);
#endif /* EVE_GEN > 3 */
/* EVE3: BT815 / BT816 */
#if EVE_GEN > 2
void EVE_cmd_clearcache(void);
void EVE_cmd_flashattach(void);
void EVE_cmd_flashdetach(void);
void EVE_cmd_flasherase(void);
uint32_t EVE_cmd_flashfast(void);
void EVE_cmd_flashspidesel(void);
void EVE_cmd_flashread(uint32_t dest, uint32_t src, uint32_t num);
void EVE_cmd_flashsource(uint32_t ptr);
void EVE_cmd_flashspirx(uint32_t dest, uint32_t num);
void EVE_cmd_flashspitx(uint32_t num, const uint8_t *p_data);
void EVE_cmd_flashupdate(uint32_t dest, uint32_t src, uint32_t num);
void EVE_cmd_flashwrite(uint32_t ptr, uint32_t num, const uint8_t *p_data);
void EVE_cmd_inflate2(uint32_t ptr, uint32_t options, const uint8_t *p_data, uint32_t len);
#endif /* EVE_GEN > 2 */
void EVE_cmd_getprops(uint32_t *p_pointer, uint32_t *p_width, uint32_t *p_height);
uint32_t EVE_cmd_getptr(void);
void EVE_cmd_inflate(uint32_t ptr, const uint8_t *p_data, uint32_t len);
void EVE_cmd_interrupt(uint32_t msec);
void EVE_cmd_loadimage(uint32_t ptr, uint32_t options, const uint8_t *p_data, uint32_t len);
void EVE_cmd_mediafifo(uint32_t ptr, uint32_t size);
void EVE_cmd_memcpy(uint32_t dest, uint32_t src, uint32_t num);
uint32_t EVE_cmd_memcrc(uint32_t ptr, uint32_t num);
void EVE_cmd_memset(uint32_t ptr, uint8_t value, uint32_t num);
void EVE_cmd_memzero(uint32_t ptr, uint32_t num);
void EVE_cmd_playvideo(uint32_t options, const uint8_t *p_data, uint32_t len);
void EVE_cmd_setrotate(uint32_t rotation);
void EVE_cmd_snapshot(uint32_t ptr);
void EVE_cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt);
void EVE_cmd_track(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t tag);
void EVE_cmd_videoframe(uint32_t dest, uint32_t result_ptr);
/*void EVE_cmd_memwrite(uint32_t dest, uint32_t num, const uint8_t *p_data);*/
/*uint32_t EVE_cmd_regread(uint32_t ptr);*/
/* ##################################################################
patching and initialization
##################################################################### */
#if EVE_GEN > 2
uint8_t EVE_init_flash(void);
#endif /* EVE_GEN > 2 */
void EVE_write_display_parameters(void);
uint8_t EVE_init(void);
/* ##################################################################
functions for display lists
##################################################################### */
void EVE_start_cmd_burst(void);
void EVE_end_cmd_burst(void);
/* EVE4: BT817 / BT818 */
#if EVE_GEN > 3
void EVE_cmd_animframeram(int16_t xc0, int16_t yc0, uint32_t aoptr, uint32_t frame);
void EVE_cmd_animframeram_burst(int16_t xc0, int16_t yc0, uint32_t aoptr, uint32_t frame);
void EVE_cmd_animstartram(int32_t chnl, uint32_t aoptr, uint32_t loop);
void EVE_cmd_animstartram_burst(int32_t chnl, uint32_t aoptr, uint32_t loop);
void EVE_cmd_apilevel(uint32_t level);
void EVE_cmd_apilevel_burst(uint32_t level);
void EVE_cmd_calibratesub(uint16_t xc0, uint16_t yc0, uint16_t width, uint16_t height);
void EVE_cmd_calllist(uint32_t adr);
void EVE_cmd_calllist_burst(uint32_t adr);
void EVE_cmd_hsf(uint32_t hsf);
void EVE_cmd_runanim(uint32_t waitmask, uint32_t play);
void EVE_cmd_runanim_burst(uint32_t waitmask, uint32_t play);
#endif /* EVE_GEN > 3 */
/* EVE3: BT815 / BT816 */
#if EVE_GEN > 2
void EVE_cmd_animdraw(int32_t chnl);
void EVE_cmd_animdraw_burst(int32_t chnl);
void EVE_cmd_animframe(int16_t xc0, int16_t yc0, uint32_t aoptr, uint32_t frame);
void EVE_cmd_animframe_burst(int16_t xc0, int16_t yc0, uint32_t aoptr, uint32_t frame);
void EVE_cmd_animstart(int32_t chnl, uint32_t aoptr, uint32_t loop);
void EVE_cmd_animstart_burst(int32_t chnl, uint32_t aoptr, uint32_t loop);
void EVE_cmd_animstop(int32_t chnl);
void EVE_cmd_animstop_burst(int32_t chnl);
void EVE_cmd_animxy(int32_t chnl, int16_t xc0, int16_t yc0);
void EVE_cmd_animxy_burst(int32_t chnl, int16_t xc0, int16_t yc0);
void EVE_cmd_appendf(uint32_t ptr, uint32_t num);
void EVE_cmd_appendf_burst(uint32_t ptr, uint32_t num);
uint16_t EVE_cmd_bitmap_transform(int32_t xc0, int32_t yc0, int32_t xc1, int32_t yc1, int32_t xc2, int32_t yc2, int32_t tx0,
int32_t ty0, int32_t tx1, int32_t ty1, int32_t tx2, int32_t ty2);
void EVE_cmd_bitmap_transform_burst(int32_t xc0, int32_t yc0, int32_t xc1, int32_t yc1, int32_t xc2, int32_t yc2, int32_t tx0,
int32_t ty0, int32_t tx1, int32_t ty1, int32_t tx2, int32_t ty2);
void EVE_cmd_fillwidth(uint32_t pixel);
void EVE_cmd_fillwidth_burst(uint32_t pixel);
void EVE_cmd_gradienta(int16_t xc0, int16_t yc0, uint32_t argb0, int16_t xc1, int16_t yc1, uint32_t argb1);
void EVE_cmd_gradienta_burst(int16_t xc0, int16_t yc0, uint32_t argb0, int16_t xc1, int16_t yc1, uint32_t argb1);
void EVE_cmd_rotatearound(int32_t xc0, int32_t yc0, uint32_t angle, int32_t scale);
void EVE_cmd_rotatearound_burst(int32_t xc0, int32_t yc0, uint32_t angle, int32_t scale);
void EVE_cmd_button_var(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
void EVE_cmd_button_var_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
void EVE_cmd_text_var(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
void EVE_cmd_text_var_burst(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
void EVE_cmd_toggle_var(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t font, uint16_t options, uint16_t state, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
void EVE_cmd_toggle_var_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t font, uint16_t options, uint16_t state, const char *p_text, uint8_t num_args, const uint32_t p_arguments[]);
#endif /* EVE_GEN > 2 */
void EVE_cmd_dl(uint32_t command);
void EVE_cmd_dl_burst(uint32_t command);
void EVE_cmd_append(uint32_t ptr, uint32_t num);
void EVE_cmd_append_burst(uint32_t ptr, uint32_t num);
void EVE_cmd_bgcolor(uint32_t color);
void EVE_cmd_bgcolor_burst(uint32_t color);
void EVE_cmd_button(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_button_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_calibrate(void);
void EVE_cmd_clock(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t hours, uint16_t mins, uint16_t secs, uint16_t msecs);
void EVE_cmd_clock_burst(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t hours, uint16_t mins, uint16_t secs, uint16_t msecs);
void EVE_cmd_dial(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t val);
void EVE_cmd_dial_burst(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t val);
void EVE_cmd_fgcolor(uint32_t color);
void EVE_cmd_fgcolor_burst(uint32_t color);
void EVE_cmd_gauge(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range);
void EVE_cmd_gauge_burst(int16_t xc0, int16_t yc0, uint16_t rad, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range);
void EVE_cmd_getmatrix(int32_t *p_a, int32_t *p_b, int32_t *p_c, int32_t *p_d, int32_t *p_e, int32_t *p_f);
void EVE_cmd_gradcolor(uint32_t color);
void EVE_cmd_gradcolor_burst(uint32_t color);
void EVE_cmd_gradient(int16_t xc0, int16_t yc0, uint32_t rgb0, int16_t xc1, int16_t yc1, uint32_t rgb1);
void EVE_cmd_gradient_burst(int16_t xc0, int16_t yc0, uint32_t rgb0, int16_t xc1, int16_t yc1, uint32_t rgb1);
void EVE_cmd_keys(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_keys_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_number(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, int32_t number);
void EVE_cmd_number_burst(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, int32_t number);
void EVE_cmd_progress(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t range);
void EVE_cmd_progress_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t range);
void EVE_cmd_romfont(uint32_t font, uint32_t romslot);
void EVE_cmd_romfont_burst(uint32_t font, uint32_t romslot);
void EVE_cmd_rotate(uint32_t angle);
void EVE_cmd_rotate_burst(uint32_t angle);
void EVE_cmd_scale(int32_t scx, int32_t scy);
void EVE_cmd_scale_burst(int32_t scx, int32_t scy);
void EVE_cmd_scrollbar(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t size, uint16_t range);
void EVE_cmd_scrollbar_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t size, uint16_t range);
void EVE_cmd_setbase(uint32_t base);
void EVE_cmd_setbase_burst(uint32_t base);
void EVE_cmd_setbitmap(uint32_t addr, uint16_t fmt, uint16_t width, uint16_t height);
void EVE_cmd_setbitmap_burst(uint32_t addr, uint16_t fmt, uint16_t width, uint16_t height);
void EVE_cmd_setfont(uint32_t font, uint32_t ptr);
void EVE_cmd_setfont_burst(uint32_t font, uint32_t ptr);
void EVE_cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar);
void EVE_cmd_setfont2_burst(uint32_t font, uint32_t ptr, uint32_t firstchar);
void EVE_cmd_setscratch(uint32_t handle);
void EVE_cmd_setscratch_burst(uint32_t handle);
void EVE_cmd_sketch(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint32_t ptr, uint16_t format);
void EVE_cmd_sketch_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint32_t ptr, uint16_t format);
void EVE_cmd_slider(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t range);
void EVE_cmd_slider_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t hgt, uint16_t options, uint16_t val, uint16_t range);
void EVE_cmd_spinner(int16_t xc0, int16_t yc0, uint16_t style, uint16_t scale);
void EVE_cmd_spinner_burst(int16_t xc0, int16_t yc0, uint16_t style, uint16_t scale);
void EVE_cmd_text(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_text_burst(int16_t xc0, int16_t yc0, uint16_t font, uint16_t options, const char *p_text);
void EVE_cmd_toggle(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t font, uint16_t options, uint16_t state, const char *p_text);
void EVE_cmd_toggle_burst(int16_t xc0, int16_t yc0, uint16_t wid, uint16_t font, uint16_t options, uint16_t state, const char *p_text);
void EVE_cmd_translate(int32_t tr_x, int32_t tr_y);
void EVE_cmd_translate_burst(int32_t tr_x, int32_t tr_y);
void EVE_color_rgb(uint32_t color);
void EVE_color_rgb_burst(uint32_t color);
void EVE_color_a(uint8_t alpha);
void EVE_color_a_burst(uint8_t alpha);
/* ##################################################################
special purpose functions
##################################################################### */
void EVE_calibrate_manual(uint16_t width, uint16_t height);
#endif /* EVE_COMMANDS_H */
+26
View File
@@ -0,0 +1,26 @@
#ifndef EVE_CONFIG_H
#define EVE_CONFIG_H
#include "../../draw/eve/lv_draw_eve_private.h"
#define EVE_HSIZE (lv_draw_eve_unit_g->params.hor_res)
#define EVE_VSIZE (lv_draw_eve_unit_g->params.ver_res)
#define EVE_VSYNC0 (lv_draw_eve_unit_g->params.vsync0)
#define EVE_VSYNC1 (lv_draw_eve_unit_g->params.vsync1)
#define EVE_VOFFSET (lv_draw_eve_unit_g->params.voffset)
#define EVE_VCYCLE (lv_draw_eve_unit_g->params.vcycle)
#define EVE_HSYNC0 (lv_draw_eve_unit_g->params.hsync0)
#define EVE_HSYNC1 (lv_draw_eve_unit_g->params.hsync1)
#define EVE_HOFFSET (lv_draw_eve_unit_g->params.hoffset)
#define EVE_HCYCLE (lv_draw_eve_unit_g->params.hcycle)
#define EVE_PCLK (lv_draw_eve_unit_g->params.pclk)
#define EVE_PCLKPOL (lv_draw_eve_unit_g->params.pclkpol)
#define EVE_SWIZZLE (lv_draw_eve_unit_g->params.swizzle)
#define EVE_CSPREAD (lv_draw_eve_unit_g->params.cspread)
#define EVE_HAS_CRYSTAL (lv_draw_eve_unit_g->params.has_crystal)
#define EVE_HAS_GT911 (lv_draw_eve_unit_g->params.has_gt911)
#define EVE_GEN LV_DRAW_EVE_EVE_GENERATION
#define EVE_BACKLIGHT_PWM (lv_draw_eve_unit_g->params.backlight_pwm)
#define EVE_BACKLIGHT_FREQ (lv_draw_eve_unit_g->params.backlight_freq)
#endif /* EVE_CONFIG_H */
+145
View File
@@ -0,0 +1,145 @@
#include "../../lv_conf_internal.h"
#if LV_USE_DRAW_EVE
/*
@file EVE_supplemental.h
@brief supplemental functions
@version 5.0
@date 2023-12-23
@author Rudolph Riedel
@section LICENSE
MIT License
Copyright (c) 2016-2023 Rudolph Riedel
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.
@section History
5.0
- added EVE_polar_cartesian()
*/
#include "EVE_suppplemental.h"
/* define NULL if it not already is */
#ifndef NULL
#include <stdio.h>
#endif
#if defined (__AVR__)
#include <avr/pgmspace.h>
#else
#define PROGMEM
#endif
/*
* @brief widget function to draw a circle
*/
void EVE_widget_circle(int16_t xc0, int16_t yc0, uint16_t radius, uint16_t border, uint32_t bgcolor)
{
EVE_cmd_dl_burst(DL_SAVE_CONTEXT);
EVE_cmd_dl(DL_BEGIN | EVE_POINTS);
EVE_cmd_dl(POINT_SIZE(radius));
EVE_cmd_dl(VERTEX2F(xc0, yc0));
EVE_color_rgb(bgcolor);
EVE_cmd_dl(POINT_SIZE(radius - border));
EVE_cmd_dl(VERTEX2F(xc0, yc0));
EVE_cmd_dl(DL_END);
EVE_cmd_dl_burst(DL_RESTORE_CONTEXT);
}
/*
* @brief widget function to draw a rectangle
*/
void EVE_widget_rectangle(int16_t xc0, int16_t yc0, int16_t wid, int16_t hgt, int16_t border, uint16_t linewidth, uint32_t bgcolor)
{
EVE_cmd_dl_burst(DL_SAVE_CONTEXT);
EVE_cmd_dl(DL_BEGIN | EVE_RECTS);
EVE_cmd_dl(LINE_WIDTH(linewidth));
EVE_cmd_dl(VERTEX2F(xc0, yc0));
EVE_cmd_dl(VERTEX2F(xc0 + wid, yc0 + hgt));
EVE_color_rgb(bgcolor);
EVE_cmd_dl(VERTEX2F(xc0 + border, yc0 + border));
EVE_cmd_dl(VERTEX2F(xc0 + wid - border, yc0 + hgt - border));
EVE_cmd_dl(DL_END);
EVE_cmd_dl_burst(DL_RESTORE_CONTEXT);
}
static const int8_t sine_table[360] PROGMEM =
{
0, 2, 4, 7, 9, 11, 13, 15, 18, 20, 22, 24, 26, 29, 31, 33, 35, 37, 39, 41,
43, 46, 48, 50, 52, 54, 56, 58, 60, 62, 63, 65, 67, 69, 71, 73, 75, 76, 78,
80, 82, 83, 85, 87, 88, 90, 91, 93, 94, 96, 97, 99, 100, 101, 103, 104, 105,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 119, 120,
121, 121, 122, 123, 123, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 125,
124, 124, 123, 123, 122, 121, 121, 120, 119, 119, 118, 117, 116, 115, 114,
113, 112, 111, 110, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 94,
93, 91, 90, 88, 87, 85, 83, 82, 80, 78, 76, 75, 73, 71, 69, 67, 65, 63, 62,
60, 58, 56, 54, 52, 50, 48, 46, 43, 41, 39, 37, 35, 33, 31, 29, 26, 24, 22,
20, 18, 15, 13, 11, 9, 7, 4, 2, 0, -2, -4, -7, -9, -11, -13, -15, -18, -20,
-22, -24, -26, -29, -31, -33, -35, -37, -39, -41, -43, -46, -48, -50, -52,
-54, -56, -58, -60, -62, -63, -65, -67, -69, -71, -73, -75, -76, -78, -80,
-82, -83, -85, -87, -88, -90, -91, -93, -94, -96, -97, -99,-100,-101,-103,
-104, -105, -107, -108, -109, -110, -111, -112, -113, -114, -115, -116,
-117, -118, -119, -119, -120, -121, -121, -122, -123, -123, -124, -124,
-125, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127, -127,
-127, -127, -127, -127, -127, -126, -126, -126, -125, -125, -125, -124,
-124, -123, -123, -122, -121, -121, -120, -119, -119, -118, -117, -116,
-115, -114, -113, -112, -111, -110, -109, -108, -107, -105, -104, -103,
-101, -100, -99, -97, -96, -94, -93, -91, -90, -88, -87, -85, -83, -82,
-80, -78, -76, -75, -73, -71, -69, -67, -65, -63, -62, -60, -58, -56, -54,
-52, -50, -48, -46, -43, -41, -39, -37, -35, -33, -31, -29, -26, -24,
-22, -20, -18, -15, -13, -11, -9, -7, -4, -2
};
/**
* @brief Calculate coordinates from an angle and a length.
* @param length distance from coordinate origin (0,0)
* @param angle rotation in degrees
* @return signed X/Y coordinates for use with VERTEX2F
* @note - resolution for angle is 1° and rotation is clockwise
* @note - angle should be limited to a (n*360)-1
*/
void EVE_polar_cartesian(uint16_t length, uint16_t angle, int16_t *p_xc0, int16_t *p_yc0)
{
uint16_t anglev;
anglev = angle % 360U;
if (p_xc0 != NULL)
{
int32_t calc = (int16_t) length;
calc = ((calc * (sine_table[anglev])) + 64) / 128;
*p_xc0 = (int16_t) calc;
}
if (p_yc0 != NULL)
{
anglev = anglev + 270U;
anglev = anglev % 360U;
int32_t calc = (int16_t) length;
calc = ((calc * (sine_table[anglev])) + 64) / 128;
*p_yc0 = (int16_t) calc;
}
}
#endif /*LV_USE_DRAW_EVE*/
+53
View File
@@ -0,0 +1,53 @@
/*
@file EVE_supplemental.h
@brief prototypes for supplemental functions
@version 5.0
@date 2023-12-23
@author Rudolph Riedel
@section LICENSE
MIT License
Copyright (c) 2016-2023 Rudolph Riedel
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.
@section History
5.0
- added EVE_polar_cartesian()
*/
#ifndef EVE_SUPPLEMENTAL_H
#define EVE_SUPPLEMENTAL_H
#include "EVE.h"
#include "EVE_commands.h"
#ifdef __cplusplus
extern "C"
{
#endif
void EVE_widget_circle(int16_t xc0, int16_t yc0, uint16_t radius, uint16_t border, uint32_t bgcolor);
void EVE_widget_rectangle(int16_t xc0, int16_t yc0, int16_t wid, int16_t hgt, int16_t border, uint16_t linewidth, uint32_t bgcolor);
void EVE_polar_cartesian(uint16_t length, uint16_t angle, int16_t *p_xc0, int16_t *p_yc0);
#endif /* EVE_SUPPLEMENTAL_H */
+67
View File
@@ -0,0 +1,67 @@
#ifndef EVE_TARGET_H
#define EVE_TARGET_H
#include "../../draw/eve/lv_draw_eve_private.h"
#include "../../tick/lv_tick.h"
#include "../../misc/lv_utils.h"
static inline void DELAY_MS(uint16_t ms)
{
lv_delay_ms(ms);
}
static inline void EVE_cs_set(void)
{
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_CS_ASSERT, NULL, 0);
}
static inline void EVE_cs_clear(void)
{
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_CS_DEASSERT, NULL, 0);
}
static inline void EVE_pdn_set(void)
{
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_POWERDOWN_SET, NULL, 0);
}
static inline void EVE_pdn_clear(void)
{
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_POWERDOWN_CLEAR, NULL, 0);
}
static inline void spi_transmit(uint8_t data)
{
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_SPI_SEND, &data, 1);
}
static inline void spi_transmit_32(uint32_t data)
{
#if LV_BIG_ENDIAN_SYSTEM
data = lv_swap_bytes_32(data);
#endif
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_SPI_SEND, &data, 4);
}
static inline void spi_transmit_burst(uint32_t data)
{
spi_transmit_32(data);
}
static inline uint8_t spi_receive(uint8_t data)
{
/* `data` is 0 everywhere `spi_receive` is called in the FT800-FT813 library */
LV_UNUSED(data);
uint8_t byte;
lv_draw_eve_unit_g->op_cb(lv_draw_eve_unit_g->disp, LV_DRAW_EVE_OPERATION_SPI_RECEIVE, &byte, 1);
return byte;
}
static inline uint8_t fetch_flash_byte(const uint8_t *p_data)
{
return (*p_data);
}
#endif /* EVE_TARGET_H_ */
+20
View File
@@ -0,0 +1,20 @@
MIT License
Copyright (c) 2016-2024 Rudolph Riedel
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.
+245
View File
@@ -0,0 +1,245 @@
# EVE2 / EVE3 / EVE4 code library
This is a code library for EVE2/EVE3/EVE4 graphics controller ICs from FTDI/Bridgetek:
http://www.ftdichip.com/EVE.htm
http://brtchip.com/eve/
http://brtchip.com/ft81x/
https://brtchip.com/bt81x/
It contains code for and has been used with various micro-controllers and displays.
## Controllers
I have used it so far with:
- 8-Bit AVR, specifically the 90CAN series
- Arduino: Uno R3, mini-pro, ESP8266, ESP32, Metro-M4 (DMA), STM32 Nucleo_F446RE (DMA), XMC1100, Uno R4
- Renesas F1L RH850
- Infineon Aurix TC222
- GD32VF103
- ATSAMC21J18A (DMA)
- ATSAME51J19A (DMA)
- ESP32 (DMA)
- RP2040 Baremetal (DMA) + Arduino (DMA) - Raspberry Pi Pico
- S32K144 (DMA)
- GD32C103CBT6 (DMA)
- STM32G0B1CET6
I have reports of successfully using it with:
- ATSAMV70
- ATSAMD20
- ATSAME4
- MSP430
- MSP432
- some PICs
- ATxmega128A1
- TMS320F28335
## Displays
The TFTs tested so far:
- FT810CB-HY50HD http://www.hotmcu.com/5-graphical-lcd-touchscreen-800x480-spi-ft810-p-286.html
- FT811CB-HY50HD http://www.hotmcu.com/5-graphical-lcd-capacitive-touch-screen-800x480-spi-ft811-p-301.html
- RVT70UQFNWC0x https://riverdi.com/product/rvt70uqfnwc0x/
- RVT50
- ADAM101-LCP-SWVGA-NEW from Glyn, 10.1" 1024x600 cap-touch
- EVE2-38A https://www.matrixorbital.com/eve2-38a
- EVE2-35G https://www.matrixorbital.com/eve2-35g
- EVE2-43G https://www.matrixorbital.com/eve2-43g
- EVE2-50G https://www.matrixorbital.com/eve2-50g
- EVE2-70G https://www.matrixorbital.com/eve2-70g
- NHD-3.5-320240FT-CSXV-CTP
- RVT43ULBNWC00 (RiTFT-43-CAP-UX) https://riverdi.com/product/ritft43capux/
- RVT50AQBNWC00 (RiTFT-50-CAP) https://riverdi.com/product/ritft50cap/
- EVE3-50G https://www.matrixorbital.com/eve3-50g
- PAF90B5WFNWC01 http://www.panadisplay.com/ftdi-intelligent-display/9-inch-lcd-with-touch-with-bt815-board.html
- EVE3-43G https://www.matrixorbital.com/eve3-43g
- EVE3-35G https://www.matrixorbital.com/eve3-35g
- CFAF240400C0-030SC https://www.crystalfontz.com/product/cfaf240400c0030sca11-240x400-eve-touchscreen-tft-ft813
- CFAF320240F-035T https://www.crystalfontz.com/product/cfaf320240f035ttsa11-320x240-eve-tft-lcd-display-kit
- CFAF480128A0-039TC
- CFAF800480E0-050SC https://www.crystalfontz.com/product/cfaf800480e1050sca11-800x480-eve-accelerated-tft
- GEN4-FT813-50CTP-CLB https://4dsystems.com.au/gen4-ft813-50ctp-clb
- RVT101HVBNWC00-B https://riverdi.com/product/rvt101hvbnwc00-b/
- RVT70HSBNWC00-B https://riverdi.com/product/rvt70hsbnwc00-b/
- RVT50HQBNWC00-B https://riverdi.com/product/rvt50hqbnwc00-b/
- CFAF1024600B0-070SC-A1 https://www.crystalfontz.com/product/cfaf1024600b0070sca1-1024x600-7-inch-eve-tft
- Sunflower shield from Cowfish Studios
- GD3X Gameduino shield
## This is version 5
This is version 5 of this code library and there are a couple of changes from V4.
First of all, support for FT80x is gone. The main reason is that this allowed a nice speed improvement modification that only works with FT81x and beyond.
Then there is a hard break from FT80x to FT81x with ony 256k of memory in FT80x but 1MB in FT81x. The memory map is different and all the registers are located elsewhere.
FT810, FT811, FT812, FT813, BT815, BT816, BT817 and BT818 can use the exact same code as long none of the new features of BT81x are used - and there are plenty of modules with these available to choose from
As a side effect all commands are automatically started now.
Second is that there are two sets of display-list building command functions now: EVE_cmd_xxx() and EVE_cmd_xxx_burst().
The EVE_cmd_xxx_burst() functions are optimized for speed, these are pure data transfer functions and do not even check anymore if burst mode is active.
## Structure
This library currently has nine files that I hope are named to make clear what these do:
- EVE.h - this has all defines for FT81x / BT81x itself, so here are options, registers, commands and macros defined
- EVE_commands.c - this has all the API functions that are to be called from an application
- EVE_commands.h - this contains the prototypes for the functions in EVE_commands.c
- EVE_config.h - this has all the parameters for the numerous supported display modules, here is definded which set of parameters is to be used
- EVE_target.c - this has non-portable specific code for a number of supported controllers, mostly to support DMA
- EVE_target.h - this has non-portable pin defines and code as "static inline" functions for all supported controllers
- EVE_target.cpp - this is for Arduino C++ targets
- EVE_cpp_wrapper.cpp - this is for Arduino C++ targets
- EVE_cpp_wrapper.h - this is for Arduino C++ targets
Addtionally there are these two:
- EVE_supplemental.c
- EVE_suppplemental.h
This has the prototype and implementation for extra functions, so far:
- EVE_widget_circle() - widget function to draw a circle
- EVE_widget_rectangle() - widget function to draw a rectangle
- EVE_polar_cartesian() - calculate coordinates from an angle and a length
## Examples
Generate a basic display list and tell EVE to use it:
````
EVE_cmd_dl(CMD_DLSTART); // tells EVE to start a new display-list
EVE_cmd_dl(DL_CLEAR_COLOR_RGB | WHITE); // sets the background color
EVE_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
EVE_color_rgb(BLACK);
EVE_cmd_text(5, 15, 28, 0, "Hello there!");
EVE_cmd_dl(DL_DISPLAY); // put in the display list to mark its end
EVE_cmd_dl(CMD_SWAP); // tell EVE to use the new display list
while (EVE_busy());
````
Note, these commands are executed one by one, for each command chip-select is pulled low, a three byte address is send, the data for the command and its parameters is send and then chip-select is pulled high again which also makes EVE execute the command.
But there is a way to speed things up, we can get away with only sending the address once:
````
EVE_start_cmd_burst();
EVE_cmd_dl_burst(CMD_DLSTART);
EVE_cmd_dl_burst(DL_CLEAR_COLOR_RGB | WHITE);
EVE_cmd_dl_burst(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
EVE_color_rgb_burst(BLACK);
EVE_cmd_text_burst(5, 15, 28, 0, "Hello there!");
EVE_cmd_dl_burst(DL_DISPLAY);
EVE_cmd_dl_burst(CMD_SWAP);
EVE_end_cmd_burst();
while (EVE_busy());
````
This does the same as the first example but faster.
The preceding EVE_start_cmd_burst() either sets chip-select to low and sends out the three byte address.
Or if DMA is available for the target you are compiling for with support code in EVE_target.c / EVE_target.cpp and EVE_target.h, it writes the address to EVE_dma_buffer and sets EVE_dma_buffer_index to 1.
Note the trailing "_burst" in the following functions, these are special versions of these commands that can only be used within an EVE_start_cmd_burst()/EVE_end_cmd_bust() pair.
These functions are optimized to push out data and nothing else.
The final EVE_end_cmd_burst() either pulls back the chip-select to high.
Or if we have DMA it calls EVE_start_dma_transfer() to start pushing out the buffer in the background.
As we have 7 commands for EVE in these simple examples, the second one has the address overhead removed from six commands and therefore needs to transfer 18 bytes less over SPI.
So even with a small 8-bit controller that does not support DMA this is a usefull optimization for building display lists.
Using DMA has one caveat: we need to limit the transfer to <4k as we are writing to the FIFO of EVEs command co-processor. This is usually not an issue though as we can shorten the display list generation with previously generated snippets that we attach to the current list with CMD_APPEND. And when we use widgets like CMD_BUTTON or CMD_CLOCK the generated display list grows by a larger amount than what we need to put into the command-FIFO so we likely reach the 8k limit of the display-list before we hit the 4k limit of the command-FIFO.
It is possible to use two or more DMA transfers to the FIFO to build a single display list, either to get around the 4k limit of the FIFO or in order to distribute the workload better of the time necessary between two display renewals.
You could for example do this, spread over three consecutive calls:
````
EVE_start_cmd_burst();
EVE_cmd_dl_burst(CMD_DLSTART);
EVE_cmd_dl_burst(DL_CLEAR_COLOR_RGB | WHITE);
EVE_end_cmd_burst();
````
````
EVE_start_cmd_burst();
EVE_cmd_dl_burst(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
EVE_color_rgb_burst(BLACK);
EVE_end_cmd_burst();
````
````
EVE_start_cmd_burst();
EVE_cmd_text_burst(5, 15, 28, 0, "Hello there!");
EVE_cmd_dl_burst(DL_DISPLAY);
EVE_cmd_dl_burst(CMD_SWAP);
EVE_end_cmd_burst();
````
But you need to check with EVE_busy() before each of these blocks.
Maybe similar like this never compiled pseudo-code:
thread_1ms_update_display()
{
static uint8_t state = 0;
static uint8_t count = 0;
count++;
if (E_OK == EVE_busy())
{
switch (state)
{
case 0:
update_first();
state = 1;
break;
case 1:
update_second();
state = 2;
break;
case 2:
if (counter > 19)
{
update_last_swap_list();
count = 0;
state = 0;
}
break;
}
}
}
## Remarks
The examples in the "example_projects" drawer are for use with AtmelStudio7.
For Arduino I am using PlatformIO with Visual Studio Code.
The platform the code is compiled for is automatically detected thru compiler flags in EVE_target.h.
The desired TFT is selected by adding a define for it to the build-environment, e.g. -DEVE_EVE3_50G
There is a list of available options at the start of EVE_config.h sorted by chipset.
The pins used for Chip-Select and Power-Down setup in the EVE_target/EVE_target_XXXXX.h file for your target with defines and these defines can be bypassed with defines in the build-environment.
Check the apropriate header file for your desired target.
When compiling for AVR you need to provide the clock it is running at in order to make the _delay_ms() calls used to initialize the TFT work with the intended timing.
For other plattforms you need to provide a DELAY_MS(ms) function that works at least between 1ms and 56ms and is not performing these delays shorter than requested.
The DELAY_MS(ms) is only used during initialization of the FT8xx/BT8xx.
In Addition you need to initialize the pins used for Chip-Select and Power-Down in your hardware correctly to output.
Plus setup the SPI accordingly, mode-0, 8-bit, MSB-first, not more than 11MHz for the initialization.
A couple of targets already have a function EVE_init_spi() in EVE_target.c.
A word of "warning", you have to take care yourself to not send more than 4kiB at once to the command co-processor
or to not generate display lists that are longer than 8kiB.
My library does not check and re-check the command-FIFO on every step.
Also there are no checks for the validity of function arguments.
This is optimized for speed, so the training wheels are off.
## Post questions here
Originally the project went public in the German mikrocontroller.net forum, the thread contains some insight: https://www.mikrocontroller.net/topic/395608
Feel free to add to the discussion with questions or remarks.
New: Github has a discussions feature as well: https://github.com/RudolphRiedel/FT800-FT813/discussions
+2
View File
@@ -48,6 +48,8 @@ extern "C" {
#define LV_SCR_LOAD_ANIM_OUT_TOP LV_SCREEN_LOAD_ANIM_OUT_TOP
#define LV_SCR_LOAD_ANIM_OUT_BOTTOM LV_SCREEN_LOAD_ANIM_OUT_BOTTOM
#define lv_ft81x_spi_operation lv_ft81x_spi_operation_t
#ifdef __cplusplus
} /*extern "C"*/
#endif
+21
View File
@@ -1017,6 +1017,27 @@
#endif
#endif
#endif
/* Use EVE FT81X GPU. */
#ifndef LV_USE_DRAW_EVE
#ifdef CONFIG_LV_USE_DRAW_EVE
#define LV_USE_DRAW_EVE CONFIG_LV_USE_DRAW_EVE
#else
#define LV_USE_DRAW_EVE 0
#endif
#endif
#if LV_USE_DRAW_EVE
/* EVE_GEN value: 2, 3, or 4 */
#ifndef LV_DRAW_EVE_EVE_GENERATION
#ifdef CONFIG_LV_DRAW_EVE_EVE_GENERATION
#define LV_DRAW_EVE_EVE_GENERATION CONFIG_LV_DRAW_EVE_EVE_GENERATION
#else
#define LV_DRAW_EVE_EVE_GENERATION 4
#endif
#endif
#endif
/*=======================
* FEATURE CONFIGURATION
*=======================*/
+1 -1
View File
@@ -149,7 +149,7 @@ extern "C" {
#ifdef CONFIG_LV_MEM_MONITOR_ALIGN_TOP_LEFT
# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_LEFT
#elif defined(CONFIG_LV_USE_MEM_MONITOR_ALIGN_TOP_MID)
#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_MID)
# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_MID
#elif defined(CONFIG_LV_MEM_MONITOR_ALIGN_TOP_RIGHT)
# define CONFIG_LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT
+7
View File
@@ -87,6 +87,9 @@
#if LV_USE_EVDEV
#include "drivers/evdev/lv_evdev_private.h"
#endif
#if LV_USE_DRAW_EVE
#include "draw/eve/lv_draw_eve.h"
#endif
/*********************
* DEFINES
@@ -276,6 +279,10 @@ void lv_init(void)
lv_uefi_platform_init();
#endif
#if LV_USE_DRAW_EVE
lv_draw_eve_init();
#endif
lv_obj_style_init();
/*Initialize the screen refresh system*/
+4
View File
@@ -386,6 +386,10 @@ typedef struct _lv_translation_tag_dsc_t lv_translation_tag_dsc_t;
typedef struct _lv_translation_pack_t lv_translation_pack_t;
#endif
#if LV_USE_DRAW_EVE
typedef struct _lv_draw_eve_unit_t lv_draw_eve_unit_t;
#endif
#endif /*__ASSEMBLY__*/
/**********************