LingYun Studio embeded system framwork software, such as thirdparty build shell and lingyun library
guowenxue
2024-08-19 80686e6bc4cb17e9d856647084725203fa63ebe6
Add LCD API examples
13 files added
1293 ■■■■■ changed files
hal/lcd/drm/drm_test.c 154 ●●●●● patch | view | raw | blame | history
hal/lcd/drm/libs/build.sh 44 ●●●●● patch | view | raw | blame | history
hal/lcd/drm/libs/libdrm/build.sh 98 ●●●●● patch | view | raw | blame | history
hal/lcd/drm/makefile 50 ●●●●● patch | view | raw | blame | history
hal/lcd/fb/fbtest.c 396 ●●●●● patch | view | raw | blame | history
hal/lcd/fb/makefile 43 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/libs_lvgl/build.sh 72 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh 55 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch 49 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch 103 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch 92 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/lvgl_demo.c 91 ●●●●● patch | view | raw | blame | history
hal/lcd/lvgl/makefile 46 ●●●●● patch | view | raw | blame | history
hal/lcd/drm/drm_test.c
New file
@@ -0,0 +1,154 @@
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
struct buffer_object {
    uint32_t width;
    uint32_t height;
    uint32_t pitch;
    uint32_t handle;
    uint32_t size;
    uint32_t *vaddr;
    uint32_t fb_id;
};
struct buffer_object buf[3];
static int modeset_create_fb(int fd, struct buffer_object *bo, uint32_t color)
{
    struct drm_mode_create_dumb create = {
    };
     struct drm_mode_map_dumb map = {
    };
    uint32_t i;
    create.width = bo->width;
    create.height = bo->height;
    create.bpp = 32;
    drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
    bo->pitch = create.pitch;
    bo->size = create.size;
    bo->handle = create.handle;
    drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch,
               bo->handle, &bo->fb_id);
    map.handle = create.handle;
    drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
    bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, map.offset);
    for (i = 0; i < (bo->size / 4); i++)
        bo->vaddr[i] = color;
    return 0;
}
static void modeset_destroy_fb(int fd, struct buffer_object *bo)
{
    struct drm_mode_destroy_dumb destroy = {
    };
    drmModeRmFB(fd, bo->fb_id);
    munmap(bo->vaddr, bo->size);
    destroy.handle = bo->handle;
    drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
}
int main(int argc, char **argv)
{
    char             *dri_card="/dev/dri/card0";
    int               fd;
    uint32_t          conn_id;
    uint32_t          crtc_id;
    drmModeConnector *conn;
    drmModeRes       *res;
    if( argc != 2 )
    {
        printf("Usage: %s /dev/dri/card0\n", argv[0]);
        return 1;
    }
    else
    {
        dri_card = argv[1];
    }
    fd = open(dri_card, O_RDWR | O_CLOEXEC);
    if( fd < 0)
    {
        printf("Open '%s' failure: %s\n", dri_card, strerror(errno));
        return 0;
    }
    res = drmModeGetResources(fd);
    if( !res )
    {
        printf("drmModeGetResources() failure\n");
        return 0;
    }
    crtc_id = res->crtcs[0];
    conn_id = res->connectors[0];
    conn = drmModeGetConnector(fd, conn_id);
    if( !conn )
    {
        printf("drmModeGetConnector() failure\n");
        return 0;
    }
    buf[0].width = conn->modes[0].hdisplay;
    buf[0].height = conn->modes[0].vdisplay;
    buf[1].width = conn->modes[0].hdisplay;
    buf[1].height = conn->modes[0].vdisplay;
    buf[2].width = conn->modes[0].hdisplay;
    buf[2].height = conn->modes[0].vdisplay;
    printf("DRM create framebuffer now.\n");
    modeset_create_fb(fd, &buf[0], 0xff0000);
    modeset_create_fb(fd, &buf[1], 0x00ff00);
    modeset_create_fb(fd, &buf[2], 0x0000ff);
    printf("Show red screen on LCD.\n");
    drmModeSetCrtc(fd, crtc_id, buf[0].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
    getchar();
    printf("Show green screen on LCD.\n");
    drmModeSetCrtc(fd, crtc_id, buf[1].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
    getchar();
    printf("Show blue screen on LCD.\n");
    drmModeSetCrtc(fd, crtc_id, buf[2].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
    getchar();
    printf("DRM destroy framebuffer now.\n");
    modeset_destroy_fb(fd, &buf[0]);
    modeset_destroy_fb(fd, &buf[1]);
    modeset_destroy_fb(fd, &buf[2]);
    drmModeFreeConnector(conn);
    return 0;
    drmModeFreeResources(res);
    close(fd);
    return 0;
}
hal/lcd/drm/libs/build.sh
New file
@@ -0,0 +1,44 @@
#!/bin/bash
function do_compile
{
    for dir in `ls`
    do
        if [ -f $dir/build*.sh ] ; then
            cd $dir
               ./build*.sh
            cd -
        fi
    done
}
function do_distclean
{
    for dir in `ls`
    do
        if [ -f $dir/build*.sh ] ; then
            rm -rf ${dir}/${dir}*
        fi
    done
}
if [ $# == 1 ] ; then
    if [ $1 == "clean" ] ; then
        rm -rf install
        exit;
    elif [ $1 == "distclean" ] ; then
        rm -rf install
        do_distclean
        exit;
    fi
    # export cross compiler
    if echo $1 | grep "\-linux\-" > /dev/null 2>&1 ; then
        export CROSS_COMPILE=$1
        echo -e "\033[40;33m --W-- export cross compiler $CROSS_COMPILE \033[0m\n"
    fi
fi
do_compile
hal/lcd/drm/libs/libdrm/build.sh
New file
@@ -0,0 +1,98 @@
#!/bin/bash
#+--------------------------------------------------------------------------------------------
#|Description:  This shell script used download and cross compile open source libs
#|     Author:  GuoWenxue <guowenxue@gmail.com>
#|  ChangeLog:
#|           1, Initialize 1.0.0 on 2011.04.12
#+--------------------------------------------------------------------------------------------
SCRIPT_PATH=`dirname ${BASH_SOURCE[0]}`
PREFIX_PATH=`realpath ${SCRIPT_PATH}/`/../install
CONF_FILE=cross_file.txt
# display in yellow
function pr_warn() {
    echo -e "\033[40;33m --W-- $1 \033[0m\n"
}
function generate_config()
{
cat > $CONF_FILE <<EOF
[binaries]
c = '${CROSS_COMPILE}gcc'
cpp = '${CROSS_COMPILE}g++'
ar = '${CROSS_COMPILE}ar'
strip = '${CROSS_COMPILE}strip'
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'
[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
EOF
}
function compile_libdrm()
{
    SRC_NAME=libdrm-2.4.110
    echo $PREFIX_PATH
    if [ -f ${PREFIX_PATH}/bin/modetest ] ; then
        pr_warn "$SRC_NAME already compile and installed"
        return 0;
    fi
    pr_warn "Start compile $SRC_NAME "
    if [ ! -d $SRC_NAME ] ; then
       if [ ! -f ${SRC_NAME}.tar.xz ] ; then
           wget https://dri.freedesktop.org/libdrm/${SRC_NAME}.tar.xz
       fi
       tar -xJf ${SRC_NAME}.tar.xz
    fi
    cd ${SRC_NAME}
    generate_config
    BUILD_PATH=tmp_build
    rm -rf $BUILD_PATH && mkdir -p $BUILD_PATH && cd $BUILD_PATH
    meson --prefix=$PREFIX_PATH \
          --cross-file=../$CONF_FILE \
          -D amdgpu=false \
          -D cairo-tests=false \
          -D etnaviv=false \
          -D exynos=false \
          -D freedreno=false \
          -D freedreno-kgsl=false \
          -D install-test-programs=true \
          -D intel=false \
          -D libkms=false \
          -D man-pages=false \
          -D nouveau=false \
          -D omap=false \
          -D radeon=false \
          -D tegra=false \
          -D udev=false \
          -D valgrind=false \
          -D vc4=false \
          -D vmwgfx=false
    ninja && ninja install
}
compile_libdrm
hal/lcd/drm/makefile
New file
@@ -0,0 +1,50 @@
#*********************************************************************************
#      Copyright:  (C) 2022 Avnet. All rights reserved.
#         Author:  Guo Wenxue<wenxue.guo@avnet.com>
#
#       Filename:  Makefile
#    Description:  This Makefile used to compile all the C source code file in
#                  current folder to a excutable binary file.
#
#********************************************************************************/
PRJ_PATH=$(shell pwd)
APP_NAME = drm_test
CROSS_COMPILE=arm-linux-gnueabihf-
# C source files in top-level directory
SRCFILES = $(wildcard *.c)
# common CFLAGS for our source code
CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
# CFLAGS and LDFLAGS for opensource library in libs
CFLAGS+=-I ${PRJ_PATH}
CFLAGS+=-I ${PRJ_PATH}/libs/install/include/
CFLAGS+=-I ${PRJ_PATH}/libs/install/include/libdrm
LDFLAGS+=-L ${PRJ_PATH}/libs/install/lib
LDFLAGS+=-L ${PRJ_PATH}/libs/install/lib
LIBS+=-ldrm
.PHONY:libs
all: libs binary
libs:
    cd libs && ./build.sh ${CROSS_COMPILE}
modules:
    @set -e; for d in ${DIRS}; do $(MAKE) CROSS_COMPILE=${CROSS_COMPILE} CFLAGS="${CFLAGS}" -C $${d}; done
binary:  ${SRCFILES}
    $(CROSS_COMPILE)gcc $(CFLAGS) -o ${APP_NAME} $^ ${LDFLAGS} ${LIBS}
    @echo " Compile over"
#set -e; for d in ${DIRS}; do $(MAKE) clean -C $${d}; done
clean:
    @rm -f *.o $(APP_NAME)
distclean: clean
    @rm -rf cscope* tags
    @cd libs && ./build.sh distclean
hal/lcd/fb/fbtest.c
New file
@@ -0,0 +1,396 @@
/********************************************************************************
 *      Copyright:  (C) 2023 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  fbtest.c
 *    Description:  This program used to:
 *                  1, Show framebuffer device information
 *                  2, Show RGB color on LCD full screen
 *                  3, Show BMP file on LCD;
 *
 *        Version:  1.0.0(08/19/23)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "08/19/23 12:56:31"
 *
 ********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fb.h>
#include <sys/mman.h>
#define PROG_VERSION      "1.0.0"
enum
{
    CMD_SHOW_INFO, /* show LCD info  */
    CMD_SHOW_RGB,  /* show RGB color */
    CMD_SHOW_BMP,  /* show BMP file  */
};
typedef struct fb_ctx_s
{
    int                       fd;       /* framebuffer file descriptor */
    char                      dev[64];  /* framebuffer device name */
    long                      fb_size;  /* framebuffer size */
    int                       pix_size; /* lcd screen pix size  */
    struct fb_var_screeninfo  vinfo;    /* framebuffer var information */
    char                     *fbp;      /* framebuffer mmap() address */
} fb_ctx_t;
int fb_init(fb_ctx_t *fb_ctx);
int fb_term(fb_ctx_t *fb_ctx);
int show_rgb(fb_ctx_t *fb_ctx, int times);
int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file);
static void program_usage(char *progname)
{
    printf("Usage: %s [OPTION]...\n", progname);
    printf(" %s is a program to show RGB color or BMP file on LCD screen\n", progname);
    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
    printf(" -d[device  ]  Specify framebuffer device, such as: /dev/fb0\n");
    printf(" -c[color   ]  Display RGB corlor on LCD screen for some times, such as: -c 3\n");
    printf(" -b[bmp     ]  Display BMP file, such as: -b bg.bmp\n");
    printf(" -h[help    ]  Display this help information\n");
    printf(" -v[version ]  Display the program version\n");
    printf("\n%s version %s\n", progname, PROG_VERSION);
    return;
}
int main (int argc, char **argv)
{
    fb_ctx_t                  fb_ctx;
    char                     *progname=NULL;
    char                     *bmp_file=NULL;
    char                     *fb_dev="/dev/fb0";
    int                       cmd = CMD_SHOW_INFO;
    int                       opt, times;
    struct option long_options[] = {
        {"device", required_argument, NULL, 'd'},
        {"color", required_argument, NULL, 'c'},
        {"bmp", required_argument, NULL, 'b'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    progname = (char *)basename(argv[0]);
    /* Parser the command line parameters */
    while ((opt = getopt_long(argc, argv, "d:c:b:vh", long_options, NULL)) != -1)
    {
        switch (opt)
        {
            case 'd': /* Set framebuffer device */
                 fb_dev = optarg;
                break;
            case 'b': /* Set BMP file */
                bmp_file = optarg;
                cmd = CMD_SHOW_BMP;
                break;
            case 'c': /* Show RGB color */
                times = atoi(optarg);
                cmd = CMD_SHOW_RGB;
                break;
            case 'v':  /* Get software version */
                printf("%s version %s\n", progname, PROG_VERSION);
                return 0;
            case 'h':  /* Get help information */
                program_usage(progname);
                return 0;
            default:
                break;
        }
    }
    memset(&fb_ctx, 0, sizeof(fb_ctx));
    strncpy(fb_ctx.dev, fb_dev, sizeof(fb_ctx.dev));
    if( fb_init(&fb_ctx) < 0 )
    {
        printf("ERROR: Initial framebuffer device '%s' failure.\n", fb_ctx.dev);
        return 1;
    }
    switch( cmd )
    {
        case CMD_SHOW_RGB:
            show_rgb(&fb_ctx, times);
            break;
        case CMD_SHOW_BMP:
            show_bmp(&fb_ctx, bmp_file);
            break;
        default:
            break;
    }
    fb_term(&fb_ctx);
    return 0;
}
int fb_get_var_screeninfo(int fd, struct fb_var_screeninfo *vinfo)
{
    if( fd<0 || !vinfo )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    if(ioctl(fd, FBIOGET_VSCREENINFO, vinfo))
    {
        printf("ERROR: ioctl() get variable info failure: %s\n", strerror(errno));
        return -2;
    }
    printf("LCD information : %dx%d, bpp:%d rgba:%d/%d,%d/%d,%d/%d,%d/%d\n", vinfo->xres, vinfo->yres, vinfo->bits_per_pixel,
            vinfo->red.length, vinfo->red.offset, vinfo->green.length, vinfo->green.offset,
            vinfo->blue.length,vinfo->blue.offset, vinfo->transp.length, vinfo->transp.offset);
    return 0;
}
int fb_init(fb_ctx_t *fb_ctx)
{
    struct fb_var_screeninfo    *vinfo;
    if( !fb_ctx || !strlen(fb_ctx->dev) )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    if( (fb_ctx->fd=open(fb_ctx->dev, O_RDWR)) < 0 )
    {
        printf("ERROR: Open framebuffer device '%s' failure: %s\n", fb_ctx->dev, strerror(errno));
        return -2;
    }
    fb_get_var_screeninfo(fb_ctx->fd, &fb_ctx->vinfo);
    vinfo = &fb_ctx->vinfo;
    fb_ctx->fb_size = vinfo->xres * vinfo->yres * vinfo->bits_per_pixel / 8;
    fb_ctx->pix_size = vinfo->xres * vinfo->yres;
    fb_ctx->fbp =(char *)mmap(0, fb_ctx->fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_ctx->fd ,0);
    if ( !fb_ctx->fbp )
    {
        printf ("ERROR: Framebuffer mmap() failure: %s\n", strerror(errno));
        return -2;
    }
    vinfo->xoffset = 0;
    vinfo->yoffset = 0;
    return 0;
}
int fb_term(fb_ctx_t *fb_ctx)
{
    if( !fb_ctx )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    munmap(fb_ctx->fbp, fb_ctx->fb_size);
    close (fb_ctx->fd);
    return 0;
}
int show_rgb_screen(fb_ctx_t *fb_ctx)
{
    struct fb_var_screeninfo    *vinfo;
    char                        *fb_addr;
    int                          interval = 1;
    int                          i, color;
    int                          bpp_bytes;
    if( !fb_ctx )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    vinfo = &fb_ctx->vinfo;
    bpp_bytes = vinfo->bits_per_pixel / 8;
    printf("show full screen on red\n");
    color = (1<<vinfo->red.length-1) << vinfo->red.offset;
    fb_addr = fb_ctx->fbp;
    for(i=0; i<fb_ctx->pix_size; i++)
    {
        memcpy(fb_addr, &color, bpp_bytes);
        fb_addr += bpp_bytes;
    }
    sleep(interval);
    printf("show full screen on green\n");
    color = (1<<vinfo->green.length-1) << vinfo->green.offset;
    fb_addr = fb_ctx->fbp;
    for(i=0; i<fb_ctx->pix_size; i++)
    {
        memcpy(fb_addr, &color, bpp_bytes);
        fb_addr += bpp_bytes;
    }
    sleep(interval);
    printf("show full screen on blue\n");
    color = (1<<vinfo->blue.length-1) << vinfo->blue.offset;
    fb_addr = fb_ctx->fbp;
    for(i=0; i<fb_ctx->pix_size; i++)
    {
        memcpy(fb_addr, &color, bpp_bytes);
        fb_addr += bpp_bytes;
    }
    sleep(interval);
    return 0;
}
int show_rgb(fb_ctx_t *fb_ctx, int times)
{
    int       i;
    if( !fb_ctx )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    for(i=0; i<times; i++)
    {
        show_rgb_screen(fb_ctx);
    }
    return 0;
}
/* BMP format: https://blog.csdn.net/weixin_39756273/article/details/110585675  */
typedef struct bmp_file_head_s
{
    uint8_t  bfType[2];        /* BMP file type: "BM" */
    int32_t bfSize;           /* BMP file size */
    int32_t bfReserved;       /* reserved */
    int32_t bfoffBits;        /* image data offset */
}__attribute__((packed)) bmp_file_head_t;
typedef struct bmp_bitmap_info_s
{
    int32_t biSize;           /* this struture size */
    int32_t biWidth;          /* image width in pix */
    int32_t biHeight;         /* image height in pix */
    uint16_t biPlanes;         /* display planes, always be 1 */
    uint16_t biBitCount;       /* bpp: 1,4,8,16,24,32 */
    int32_t biCompress;       /* compress type */
    int32_t biSizeImage;      /* image size in byte */
    int32_t biXPelsPerMeter;  /* x-res in pix/m */
    int32_t biYPelsPerMeter;  /* y-res in pix/m */
    int32_t biClrUsed;
    int32_t biClrImportant;
}__attribute__((packed)) bmp_bitmap_info_t;
/*
 * BMP image file format:
 * +----------------+------------------+--------------------+---------------+
 * | File Head(14B) | Bitmap Info(40B) | color palette(OPT) |  bitmap data  |
 * +----------------+------------------+--------------------+---------------+
 */
int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file)
{
    struct fb_var_screeninfo    *vinfo;
    char                        *fb_addr;
    bmp_file_head_t            *file_head;
    bmp_bitmap_info_t          *bitmap_info;
    struct stat                 statbuf;
    char                       *f_addr;
    char                       *d_addr;
    char                       *p_addr;
    int                         fd;
    int                         bpp_bytes;
    int                         i, j;
    int                         width, height;
    if( !fb_ctx || !bmp_file )
    {
        printf("ERROR: Invalid input arguments\n");
        return -1;
    }
    if( (fd=open(bmp_file, O_RDONLY)) < 0 )
    {
        printf("ERROR: Open file '%s' failure: %s\n", bmp_file, strerror(errno));
        return -2;
    }
    fstat(fd, &statbuf);
    f_addr =(char *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd ,0);
    if ( !f_addr )
    {
        printf ("ERROR: BMP file mmap() failure: %s\n", strerror(errno));
        return -2;
    }
    /* BMP file header */
    file_head = (bmp_file_head_t *)f_addr;
    if( memcmp(file_head->bfType, "BM", 2) != 0)
    {
        printf("ERROR: It's not a BMP file\n");
        return -3;
    }
    /* BMP bitmap information header */
    bitmap_info = (bmp_bitmap_info_t *)(f_addr+sizeof(bmp_file_head_t));
    /* BMP bitmap data */
    d_addr = f_addr + file_head->bfoffBits;
    vinfo = &fb_ctx->vinfo;
    fb_addr = fb_ctx->fbp;
    bpp_bytes = vinfo->bits_per_pixel / 8;
    width = bitmap_info->biWidth>vinfo->xres ? vinfo->xres : bitmap_info->biWidth;
    height = bitmap_info->biHeight>vinfo->yres ? vinfo->yres : bitmap_info->biHeight;
    printf("BMP file '%s': %dx%d and display %dx%d\n", bmp_file, bitmap_info->biWidth, bitmap_info->biHeight, width, height);
    /* if biHeight is positive, the bitmap is a bottom-up DIB */
    for(i=0; i<height; i++)
    {
        p_addr=d_addr+(height-1-i)*bitmap_info->biWidth*bpp_bytes;
        memcpy(fb_addr, p_addr, bpp_bytes*width);
        fb_addr += bpp_bytes * vinfo->xres;
    }
    munmap(f_addr, statbuf.st_size);
    close (fd);
    return 0;
}
hal/lcd/fb/makefile
New file
@@ -0,0 +1,43 @@
#********************************************************************************
#      Copyright:  (C) 2023 LingYun IoT System Studio
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This file used to compile all the C file to respective binary,
#                  and it will auto detect cross compile or local compile.
#
#        Version:  1.0.0(11/08/23)
#         Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "11/08/23 16:18:43"
#
#*******************************************************************************
PWD=$(shell pwd)
INSTPATH=/tftp
CROSS_COMPILE=arm-linux-gnueabihf-
CC=${CROSS_COMPILE}gcc
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
SRCFILES = $(wildcard *.c)
BINARIES=$(SRCFILES:%.c=%)
all: binaries install
binaries:  ${BINARIES}
%:  %.c
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
install:
    cp $(BINARIES) ${INSTPATH}
clean:
    @rm -f *.o *.lo $(BINARIES)
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
hal/lcd/lvgl/libs_lvgl/build.sh
New file
@@ -0,0 +1,72 @@
#!/bin/bash
PRJ_PATH=`pwd`
BOARD=imx6ull
LYFTP_SRC=http://master.weike-iot.com:2211/src/
LIB_LVGL=lvgl-8.0.2
LIB_LVGL_DRV=lv_drivers-8.0.1
LIB_LVGL_DEMO=lv_demos-8.0.1
LIBS_DIR="lvgl lv_drivers lv_demos"
CROSS_COMPILE=arm-linux-gnueabihf-
if [ $# == 1 ] ; then
   CROSS_COMPILE=$1
fi
set -e
function prepare_lib()
{
    PACK_SUFIX=tar.gz
    PACK_NAME=$1
    DIR_NAME=$2
    if [ ! -d ${DIR_NAME} ] ; then
       if [ ! -s ${PACK_NAME}.${PACK_SUFIX} ] ; then
          wget ${LYFTP_SRC}/${PACK_NAME}.${PACK_SUFIX}
       fi
       tar -xzf ${PACK_NAME}.${PACK_SUFIX}
       patch -p0 < patches/${PACK_NAME}-${BOARD}.patch
       mv ${PACK_NAME} ${DIR_NAME}
       cd ${DIR_NAME}
       sed -i -e "s|.*CMAKE_C_COMPILER.*|set(CMAKE_C_COMPILER \"${CROSS_COMPILE}gcc\")|g" CMakeLists.txt
         temp_file=`ls *_template.h`
         conf_file=`echo ${temp_file/_template/}`
         cp ${temp_file} ../${conf_file}
       cd ${PRJ_PATH}
    fi
}
if [[ $# == 1 && $1 == clean ]] ; then
    rm -rf lv*
    rm -rf libs
    exit;
fi
prepare_lib ${LIB_LVGL} lvgl
prepare_lib ${LIB_LVGL_DRV} lv_drivers
prepare_lib ${LIB_LVGL_DEMO} lv_demos
mkdir -p ${PRJ_PATH}/libs
for lib in ${LIBS_DIR}
do
    if [ -f ${PRJ_PATH}/libs/lib${lib}.a ] ; then
        continue;
    fi
    mkdir -p ${lib}/build
    cd ${lib}/build/
    rm -rf * && cmake .. && make
    cp lib*.a ${PRJ_PATH}/libs/lib${lib}.a
    cd ${PRJ_PATH}
done
hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh
New file
@@ -0,0 +1,55 @@
#!/bin/bash
# Description: This shell script used to generate patch file
#      Author: guowenxue <guowenxue@gmail.com>
#     Version: 1.0.0
PROJ_PATH=`pwd`
PATCH_PATH=${PROJ_PATH}/patches
BOARD=imx6ull
PATCH_SUFFIX=${BOARD}.patch
set -e
if [ $# != 1 ] ; then
    echo "Usage: $0 [src_path]"
    printf "\nExample: \n"
    echo "$0 lvgl-8.0.2"
    exit ;
fi
SRC=`basename $1`
if [ ! -d ${SRC} ] ; then
    printf "\nERROR: ${SRC} source code not exist, exit now\n\n"
    exit
fi
if [ ! -f ${SRC}.tar.gz ] ; then
    printf "\nERROR: ${SRC}.tar.gz packet not exist, exit now\n\n"
    exit
fi
rm -rf ${SRC}/build
# rename new source code
mv ${SRC} ${SRC}-${BOARD}
# decompress orignal soruce code packet
tar -xzf ${SRC}.tar.gz
set +e
# generate patch file
diff -Nuar ${SRC} ${SRC}-${BOARD} > ${SRC}-${PATCH_SUFFIX}
# remove orignal soruce code
rm -rf ${SRC}
# recover new source code
mv ${SRC}-${BOARD} ${SRC}
hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch
New file
@@ -0,0 +1,49 @@
diff -Nuar lv_demos-8.0.1/CMakeLists.txt lv_demos-8.0.1-imx6ull/CMakeLists.txt
--- lv_demos-8.0.1/CMakeLists.txt    2021-06-14 20:00:00.000000000 +0800
+++ lv_demos-8.0.1-imx6ull/CMakeLists.txt    2021-09-27 21:26:45.823935469 +0800
@@ -1,2 +1,5 @@
+set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
+include_directories(..)
+
 file(GLOB_RECURSE SOURCES src/*.c)
 add_library(lv_examples STATIC ${SOURCES})
diff -Nuar lv_demos-8.0.1/lv_demo_conf_template.h lv_demos-8.0.1-imx6ull/lv_demo_conf_template.h
--- lv_demos-8.0.1/lv_demo_conf_template.h    2021-06-14 20:00:00.000000000 +0800
+++ lv_demos-8.0.1-imx6ull/lv_demo_conf_template.h    2021-09-27 20:57:35.667901897 +0800
@@ -7,7 +7,7 @@
  * COPY THIS FILE AS lv_demo_conf.h
  */
-#if 0 /*Set it to "1" to enable the content*/
+#if 1 /*Set it to "1" to enable the content*/
 #ifndef LV_EX_CONF_H
 #define LV_EX_CONF_H
@@ -25,22 +25,22 @@
  *********************/
 /*Show some widget*/
-#define LV_USE_DEMO_WIDGETS        0
+#define LV_USE_DEMO_WIDGETS        1
 #if LV_USE_DEMO_WIDGETS
 #define LV_DEMO_WIDGETS_SLIDESHOW  0
 #endif
 /*Printer demo, optimized for 800x480*/
-#define LV_USE_DEMO_PRINTER     0
+#define LV_USE_DEMO_PRINTER     1
 /*Demonstrate the usage of encoder and keyboard*/
-#define LV_USE_DEMO_KEYPAD_AND_ENCODER     0
+#define LV_USE_DEMO_KEYPAD_AND_ENCODER     1
 /*Benchmark your system*/
-#define LV_USE_DEMO_BENCHMARK   0
+#define LV_USE_DEMO_BENCHMARK   1
 /*Stress test for LVGL*/
-#define LV_USE_DEMO_STRESS      0
+#define LV_USE_DEMO_STRESS      1
 /*Music player demo*/
 #define LV_USE_DEMO_MUSIC      1
hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch
New file
@@ -0,0 +1,103 @@
diff -Nuar lv_drivers-8.0.1/CMakeLists.txt lv_drivers-8.0.1-imx6ull/CMakeLists.txt
--- lv_drivers-8.0.1/CMakeLists.txt    2021-06-14 19:54:20.000000000 +0800
+++ lv_drivers-8.0.1-imx6ull/CMakeLists.txt    2021-09-27 22:20:38.179997474 +0800
@@ -1,2 +1,5 @@
+set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
+include_directories(..)
+
 file(GLOB_RECURSE SOURCES ./*.c)
 add_library(lv_drivers STATIC ${SOURCES})
diff -Nuar lv_drivers-8.0.1/indev/evdev.c lv_drivers-8.0.1-imx6ull/indev/evdev.c
--- lv_drivers-8.0.1/indev/evdev.c    2021-06-14 19:54:20.000000000 +0800
+++ lv_drivers-8.0.1-imx6ull/indev/evdev.c    2021-09-27 22:25:04.172002576 +0800
@@ -115,7 +115,7 @@
  * @param data store the evdev data here
  * @return false: because the points are not buffered, so no more data to be read
  */
-bool evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
+void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
 {
     struct input_event in;
@@ -196,7 +196,7 @@
         }
         evdev_key_val = data->key;
         evdev_button = data->state;
-        return false;
+        return;
         }
         }
     }
@@ -205,10 +205,10 @@
         /* No data retrieved */
         data->key = evdev_key_val;
     data->state = evdev_button;
-    return false;
+    return;
     }
     if(drv->type != LV_INDEV_TYPE_POINTER)
-        return false;
+        return;
     /*Store the collected data*/
 #if EVDEV_CALIBRATE
@@ -225,12 +225,12 @@
       data->point.x = 0;
     if(data->point.y < 0)
       data->point.y = 0;
-    if(data->point.x >= drv->disp->driver.hor_res)
-      data->point.x = drv->disp->driver.hor_res - 1;
-    if(data->point.y >= drv->disp->driver.ver_res)
-      data->point.y = drv->disp->driver.ver_res - 1;
+    if(data->point.x >= drv->disp->driver->hor_res)
+      data->point.x = drv->disp->driver->hor_res - 1;
+    if(data->point.y >= drv->disp->driver->ver_res)
+      data->point.y = drv->disp->driver->ver_res - 1;
-    return false;
+    return;
 }
 /**********************
diff -Nuar lv_drivers-8.0.1/indev/evdev.h lv_drivers-8.0.1-imx6ull/indev/evdev.h
--- lv_drivers-8.0.1/indev/evdev.h    2021-06-14 19:54:20.000000000 +0800
+++ lv_drivers-8.0.1-imx6ull/indev/evdev.h    2021-09-27 22:25:33.424003137 +0800
@@ -57,7 +57,7 @@
  * @param data store the evdev data here
  * @return false: because the points are not buffered, so no more data to be read
  */
-bool evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
+void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
 /**********************
diff -Nuar lv_drivers-8.0.1/lv_drv_conf_template.h lv_drivers-8.0.1-imx6ull/lv_drv_conf_template.h
--- lv_drivers-8.0.1/lv_drv_conf_template.h    2021-06-14 19:54:20.000000000 +0800
+++ lv_drivers-8.0.1-imx6ull/lv_drv_conf_template.h    2021-09-27 22:20:38.183997474 +0800
@@ -7,7 +7,7 @@
  * COPY THIS FILE AS lv_drv_conf.h
  */
-#if 0 /*Set it to "1" to enable the content*/
+#if 1 /*Set it to "1" to enable the content*/
 #ifndef LV_DRV_CONF_H
 #define LV_DRV_CONF_H
@@ -272,7 +272,7 @@
  *  Linux frame buffer device (/dev/fbx)
  *-----------------------------------------*/
 #ifndef USE_FBDEV
-#  define USE_FBDEV           0
+#  define USE_FBDEV           1
 #endif
 #if USE_FBDEV
@@ -386,7 +386,7 @@
  * Mouse or touchpad as evdev interface (for Linux based systems)
  *------------------------------------------------*/
 #ifndef USE_EVDEV
-#  define USE_EVDEV           0
+#  define USE_EVDEV           1
 #endif
 #ifndef USE_BSD_EVDEV
hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch
New file
@@ -0,0 +1,92 @@
diff -Nuar lvgl-8.0.2/CMakeLists.txt lvgl-8.0.2-imx6ull/CMakeLists.txt
--- lvgl-8.0.2/CMakeLists.txt    2021-07-16 23:40:51.000000000 +0800
+++ lvgl-8.0.2-imx6ull/CMakeLists.txt    2021-09-27 22:30:20.360008641 +0800
@@ -1,3 +1,7 @@
+
+set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
+include_directories(..)
+
 if(ESP_PLATFORM)
 file(GLOB_RECURSE SOURCES src/*.c)
diff -Nuar lvgl-8.0.2/lv_conf_template.h lvgl-8.0.2-imx6ull/lv_conf_template.h
--- lvgl-8.0.2/lv_conf_template.h    2021-07-16 23:40:51.000000000 +0800
+++ lvgl-8.0.2-imx6ull/lv_conf_template.h    2021-09-27 22:33:47.448012614 +0800
@@ -7,7 +7,7 @@
  * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER
  */
-#if 0 /*Set it to "1" to enable content*/
+#if 1 /*Set it to "1" to enable content*/
 #ifndef LV_CONF_H
 #define LV_CONF_H
@@ -21,7 +21,7 @@
  *====================*/
 /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
-#define LV_COLOR_DEPTH     32
+#define LV_COLOR_DEPTH     16
 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
 #define LV_COLOR_16_SWAP   0
@@ -42,7 +42,7 @@
 #define LV_MEM_CUSTOM      0
 #if LV_MEM_CUSTOM == 0
 /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
-#  define LV_MEM_SIZE    (32U * 1024U)          /*[bytes]*/
+#  define LV_MEM_SIZE    (128U * 1024U)          /*[bytes]*/
 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
 #  define LV_MEM_ADR          0     /*0: unused*/
@@ -68,9 +68,10 @@
 /*Use a custom tick source that tells the elapsed time in milliseconds.
  *It removes the need to manually update the tick with `lv_tick_inc()`)*/
-#define LV_TICK_CUSTOM     0
+#define LV_TICK_CUSTOM     1
 #if LV_TICK_CUSTOM
-#define LV_TICK_CUSTOM_INCLUDE  "Arduino.h"         /*Header for the system time function*/
+extern uint32_t millis(void);
+#define LV_TICK_CUSTOM_INCLUDE      <stdint.h>      /*Header for the system time function*/
 #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis())     /*Expression evaluating to current system time in ms*/
 #endif   /*LV_TICK_CUSTOM*/
@@ -137,7 +138,7 @@
  *-----------*/
 /*Enable the log module*/
-#define LV_USE_LOG      0
+#define LV_USE_LOG      1
 #if LV_USE_LOG
 /*How important log should be added:
@@ -151,7 +152,7 @@
 /*1: Print the log with 'printf';
  *0: User need to register a callback with `lv_log_register_print_cb()`*/
-#  define LV_LOG_PRINTF   0
+#  define LV_LOG_PRINTF   1
 /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
 #  define LV_LOG_TRACE_MEM            1
@@ -262,13 +263,13 @@
 /*Montserrat fonts with ASCII range and some symbols using bpp = 4
  *https://fonts.google.com/specimen/Montserrat*/
-#define LV_FONT_MONTSERRAT_8     0
-#define LV_FONT_MONTSERRAT_10    0
-#define LV_FONT_MONTSERRAT_12    0
+#define LV_FONT_MONTSERRAT_8     1
+#define LV_FONT_MONTSERRAT_10    1
+#define LV_FONT_MONTSERRAT_12    1
 #define LV_FONT_MONTSERRAT_14    1
-#define LV_FONT_MONTSERRAT_16    0
-#define LV_FONT_MONTSERRAT_18    0
-#define LV_FONT_MONTSERRAT_20    0
+#define LV_FONT_MONTSERRAT_16    1
+#define LV_FONT_MONTSERRAT_18    1
+#define LV_FONT_MONTSERRAT_20    1
 #define LV_FONT_MONTSERRAT_22    0
 #define LV_FONT_MONTSERRAT_24    0
 #define LV_FONT_MONTSERRAT_26    0
hal/lcd/lvgl/lvgl_demo.c
New file
@@ -0,0 +1,91 @@
/*********************************************************************************
 *      Copyright:  (C) 2021 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  lvgl_demo.c
 *    Description:  This file is LVGL demo program.
 *
 *        Version:  1.0.0(2021年09月27日)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2021年09月27日 22时16分52秒"
 *
 ********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include "lvgl/lvgl.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include "lv_demos/lv_demo.h"
#define DISP_BUF_SIZE (128 * 1024)
int main(void)
{
    lv_disp_drv_t               disp_drv;
    lv_indev_drv_t              indev_drv;
    static lv_color_t           buf[DISP_BUF_SIZE]; /* buffer for LVGL to draw the screen's content */
    static lv_disp_draw_buf_t   disp_buf; /* Initialize a descriptor for the buffer */
    /* LVGL context init */
    lv_init();
    /* Linux frame buffer device init */
    fbdev_init();
    /* linux touchscreen device init */
    lv_indev_drv_init(&indev_drv);
    indev_drv.type =LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb =evdev_read;
    lv_indev_drv_register(&indev_drv);
    /* Initialize and register a display driver */
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb = fbdev_flush;
    disp_drv.hor_res    = 800;
    disp_drv.ver_res    = 480;
    lv_disp_drv_register(&disp_drv);
    /* Create a Demo */
    //lv_demo_widgets();
    lv_demo_music();
    //lv_demo_keypad_encoder();
    //lv_demo_stress();
    /* Handle LitlevGL tasks (tickless mode) */
    while(1) {
        lv_task_handler();
        usleep(5000);
    }
    return 0;
}
/* Set in lv_conf.h as LV_TICK_CUSTOM_SYS_TIME_EXPR */
uint32_t millis(void)
{
    static uint64_t start_ms = 0;
    struct timeval tv_start;
    struct timeval tv_now;
    uint64_t now_ms;
    uint32_t time_ms;
    if(start_ms == 0)
    {
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }
    gettimeofday(&tv_now, NULL);
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
    time_ms = now_ms - start_ms;
    return time_ms;
}
hal/lcd/lvgl/makefile
New file
@@ -0,0 +1,46 @@
CROSS_COMPILE=arm-linux-gnueabihf-
CC=${CROSS_COMPILE}gcc
CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
CFLAGS += -O3 -g3 -I./ -I ./libs_lvgl/
LDFLAGS+=-L ./libs_lvgl/libs/ -llv_demos -llv_drivers -llvgl
BIN = lvgl_demo
MAINSRC = lvgl_demo.c
VPATH =
OBJEXT ?= .o
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
MAINOBJ = $(MAINSRC:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
OBJS = $(AOBJS) $(COBJS)
## MAINOBJ -> OBJFILES
all: libs clean default
    cp ${BIN} /tftp
libs:
    cd libs_lvgl && ./build.sh ${CROSS_COMPILE}
%.o: %.c
    @$(CC)  $(CFLAGS) -c $< -o $@
    @echo "CC $<"
default: $(AOBJS) $(COBJS) $(MAINOBJ)
    $(CC) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS)
clean:
    rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)
distclean: clean
    rm -rf cscope* tags
    cd libs_lvgl && ./build.sh clean