Multiple fixes, SPI driver, lcd implementation, etc.

This commit is contained in:
imi415 2021-06-22 01:27:32 +08:00
parent 0bc7fb31fa
commit b33ca6120e
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
14 changed files with 151 additions and 48 deletions

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
project(SystemAgent)
set(ST7789_LCD_DEFINES "ST7789_PANEL_ZJY_240")
set(ST7789_LCD_DEFINES "ST7789_PANEL_ZJY_320")
set(LVGL_DEFINES "LV_CONF_INCLUDE_SIMPLE")
set(C_SOURCES
@ -13,6 +13,7 @@ set(C_SOURCES
"src/impl/user_st7789_impl.c"
"src/impl/user_lvgl_impl.c"
"src/tasks/user_lvgl_task.c"
"src/tasks/user_clock_task.c"
"src/utils/user_log_util.c"
)

View File

@ -10,7 +10,7 @@ typedef struct {
int user_config_init(user_config_t *config, char *config_file);
char *user_config_lookup_string(user_config_t *config, char *path);
int user_config_lookup_int(user_config_t *config, char *path, int *value);
int user_config_lookup_float(user_config_t *config, char *path, float *value);
int user_config_lookup_double(user_config_t *config, char *path, double *value);
int user_config_deinit(user_config_t *config);
#endif

View File

@ -1,7 +1,10 @@
#ifndef __USER_LVGL_IMPL_H
#define __USER_LVGL_IMPL_H
#include "lvgl.h"
void user_lvgl_impl_init(void);
void user_lvgl_impl_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
void user_lvgl_impl_deinit(void);
#endif

View File

@ -20,7 +20,7 @@
*====================*/
/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX (240)
#define LV_HOR_RES_MAX (320)
#define LV_VER_RES_MAX (240)
/* Color depth:
@ -44,7 +44,7 @@
#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/
/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
#define LV_ANTIALIAS 1
#define LV_ANTIALIAS 0
/* Default display refresh period.
* Can be changed in the display driver (`lv_disp_drv_t`).*/
@ -53,7 +53,7 @@
/* Dot Per Inch: used to initialize default sizes.
* E.g. a button with width = LV_DPI / 2 -> half inch wide
* (Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI 130 /*[px]*/
#define LV_DPI 200 /*[px]*/
/* The the real width of the display changes some default values:
* default object sizes, layout of examples, etc.
@ -386,7 +386,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
#define LV_FONT_MONTSERRAT_18 0
#define LV_FONT_MONTSERRAT_20 0
#define LV_FONT_MONTSERRAT_22 0
#define LV_FONT_MONTSERRAT_24 0
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_26 0
#define LV_FONT_MONTSERRAT_28 0
#define LV_FONT_MONTSERRAT_30 0
@ -409,7 +409,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
/*Pixel perfect monospace font
* http://pelulamu.net/unscii/ */
#define LV_FONT_UNSCII_8 0
#define LV_FONT_UNSCII_16 0
#define LV_FONT_UNSCII_16 1
/* Optionally declare your custom fonts here.
* You can use these fonts as default font too
@ -477,10 +477,10 @@ typedef void * lv_font_user_data_t;
#define LV_THEME_DEFAULT_COLOR_PRIMARY lv_color_hex(0x01a2b1)
#define LV_THEME_DEFAULT_COLOR_SECONDARY lv_color_hex(0x44d1b6)
#define LV_THEME_DEFAULT_FLAG LV_THEME_MATERIAL_FLAG_LIGHT
#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_montserrat_24
#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_montserrat_24
#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_montserrat_24
#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_montserrat_24
/*=================
* Text settings

View File

@ -4,4 +4,7 @@
int user_lvgl_task_init(void);
int user_lvgl_task_deinit(void);
int user_clock_task_init(void);
int user_clock_task_deinit(void);
#endif

@ -1 +1 @@
Subproject commit 4df50bb6769fc2113eebd9c2ba4f6ad048e7998b
Subproject commit b0be98b771d6c2bd3452f16998a3897a047c4f30

View File

@ -22,6 +22,10 @@ agent: {
path = "/dev/gpiochip1";
line = 230;
};
blk_pin: {
path = "/dev/gpiochip1";
line = 231;
};
};
};
};

View File

@ -37,7 +37,7 @@ int user_config_lookup_int(user_config_t *config, char *path, int *value) {
return 0;
}
int user_config_lookup_float(user_config_t *config, char *path, float *value) {
int user_config_lookup_double(user_config_t *config, char *path, double *value) {
if(config_lookup_float(config->libconfig_cfg, path, value) == 0) {
return -1;
}

View File

@ -27,7 +27,7 @@ int user_spi_driver_init(user_spi_driver_t *spi, char *path,
spi->speed_hz = speed_hz;
uint32_t mode = SPI_MODE_0;
if(ioctl(spi->spidev_fd, SPI_IOC_WR_MODE32, &mode) == -1) {
if(ioctl(spi->spidev_fd, SPI_IOC_WR_MODE, &mode) == -1) {
USER_LOG(USER_LOG_ERROR, "Failed to set SPI mode.");
return -1;
}
@ -55,31 +55,21 @@ int user_spi_driver_xfer(user_spi_driver_t *spi, uint8_t *tx_buf,
.tx_buf = (unsigned long)tx_buf,
.rx_buf = (unsigned long)rx_buf,
.len = len,
.cs_change = 0,
.speed_hz = spi->speed_hz,
.bits_per_word = 8,
.tx_nbits = 1,
.rx_nbits = 1,
};
USER_LOG(USER_LOG_DEBUG, "SPI 1st byte: 0x%02x.", tx_buf[0]);
while(len > SPIDEV_MAX_TRANSFER_SIZE) {
txn.len = SPIDEV_MAX_TRANSFER_SIZE;
len -= SPIDEV_MAX_TRANSFER_SIZE;
USER_LOG(USER_LOG_DEBUG, "SPI Tx len: %d.", txn.len);
if(ioctl(spi->spidev_fd, SPI_IOC_MESSAGE(1), &txn) < 0) {
USER_LOG(USER_LOG_ERROR, "SPI transaction error.");
return -1;
uint32_t xfer_count = (len / SPIDEV_MAX_TRANSFER_SIZE) + ((len % SPIDEV_MAX_TRANSFER_SIZE) ? 1 : 0);
for(uint32_t i = 0; i < xfer_count; i++) {
if(txn.tx_buf != 0) txn.tx_buf = (unsigned long)&tx_buf[i * SPIDEV_MAX_TRANSFER_SIZE];
if(txn.rx_buf != 0) txn.rx_buf = (unsigned long)&rx_buf[i * SPIDEV_MAX_TRANSFER_SIZE];
if(i == xfer_count - 1) {
txn.len = len % SPIDEV_MAX_TRANSFER_SIZE;
} else {
txn.len = SPIDEV_MAX_TRANSFER_SIZE;
}
}
if(len > 0) {
txn.len = len;
USER_LOG(USER_LOG_DEBUG, "SPI Tx len: %d.", txn.len);
if(ioctl(spi->spidev_fd, SPI_IOC_MESSAGE(1), &txn) < 0) {
USER_LOG(USER_LOG_ERROR, "SPI transaction error.");

View File

@ -1,9 +1,8 @@
#include "lvgl.h"
#include "impl/user_st7789_impl.h"
#include "impl/user_lvgl_impl.h"
#include "utils/user_log_util.h"
user_st7789_impl_t g_lcd_impl;
st7789_lcd_t g_lcd = {
.cb =
@ -14,8 +13,8 @@ st7789_lcd_t g_lcd = {
},
.config =
{
.direction = ST7789_DIR_0,
.pix_fmt = ST7789_RGB888,
.direction = ST7789_DIR_270,
.pix_fmt = ST7789_RGB565,
},
.user_data = &g_lcd_impl,
};
@ -25,6 +24,11 @@ void user_lvgl_impl_init(void) {
st7789_lcd_init(&g_lcd);
}
void user_lvgl_impl_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) {
st7789_lcd_load(&g_lcd, (uint8_t *)color_p, area->x1, area->x2, area->y1, area->y2);
lv_disp_flush_ready(disp_drv);
}
void user_lvgl_impl_deinit(void) {
user_st7789_impl_deinit(&g_lcd_impl);
}

View File

@ -66,13 +66,18 @@ void user_st7789_impl_deinit(void *handle) {
user_st7789_impl_t *impl = handle;
user_gpio_deinit(impl->cs_gpio);
user_gpio_deinit(impl->dc_gpio);
user_gpio_deinit(impl->reset_gpio);
if(impl->cs_gpio) free(impl->cs_gpio);
if(impl->dc_gpio) free(impl->dc_gpio);
if(impl->reset_gpio) free(impl->reset_gpio);
if(impl->cs_gpio) {
user_gpio_deinit(impl->cs_gpio);
free(impl->cs_gpio);
}
if(impl->dc_gpio) {
user_gpio_deinit(impl->dc_gpio);
free(impl->dc_gpio);
}
if(impl->reset_gpio) {
user_gpio_deinit(impl->reset_gpio);
free(impl->reset_gpio);
}
}
st7789_ret_t user_st7789_impl_write_cmd(void *handle, uint8_t *cmd,
@ -83,11 +88,19 @@ st7789_ret_t user_st7789_impl_write_cmd(void *handle, uint8_t *cmd,
if(impl->dc_gpio && (user_gpio_set(impl->dc_gpio, 0) != 0)) return ST7789_ERROR;
if(impl->cs_gpio && (user_gpio_set(impl->cs_gpio, 0) != 0)) return ST7789_ERROR;
// ST7789VW requires parameters to be sent with DC=0.
if(user_spi_driver_xfer(impl->spi_driver, cmd, NULL, len) != 0) {
if(user_spi_driver_xfer(impl->spi_driver, cmd, NULL, 0x01) != 0) {
if(impl->cs_gpio) user_gpio_set(impl->cs_gpio, 1);
return ST7789_ERROR;
}
// ST7789VW requires parameters to be sent with DC=1.
if(len > 1) {
if(impl->dc_gpio && (user_gpio_set(impl->dc_gpio, 1) != 0)) return ST7789_ERROR;
if(user_spi_driver_xfer(impl->spi_driver, &cmd[1], NULL, len - 1) != 0) {
if(impl->cs_gpio) user_gpio_set(impl->cs_gpio, 1);
return ST7789_ERROR;
}
}
if(impl->cs_gpio && (user_gpio_set(impl->cs_gpio, 1) != 0)) return ST7789_ERROR;
return ST7789_OK;
@ -112,9 +125,14 @@ st7789_ret_t user_st7789_impl_reset(void *handle) {
user_st7789_impl_t *impl = handle;
if(&impl->reset_gpio == NULL) return ST7789_OK;
if(impl->reset_gpio == NULL) return ST7789_OK;
if(user_gpio_set(impl->reset_gpio, 0) != 0) return ST7789_ERROR;
usleep(10 * 1000); // Sleep 10ms
usleep(1 * 1000); // Sleep 1ms
if(user_gpio_set(impl->reset_gpio, 1) != 0) return ST7789_ERROR;
if(impl->cs_gpio == NULL) return ST7789_OK;
if(user_gpio_set(impl->cs_gpio, 1) != 0) return ST7789_ERROR;
return ST7789_OK;
}

View File

@ -53,12 +53,14 @@ int main(int argc, const char *argv[]) {
}
user_lvgl_task_init();
user_clock_task_init();
USER_LOG(USER_LOG_INFO, "Initialized, main thread sleeping.");
while(g_running) {
sleep(1);
}
user_clock_task_deinit();
user_lvgl_task_deinit();
user_spi_driver_deinit(&g_spi);

View File

@ -0,0 +1,61 @@
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>
#include "lvgl.h"
#include "utils/user_log_util.h"
extern uint8_t g_running;
extern uint8_t g_lvgl_ready;
pthread_t user_clock_task_thread;
void *user_clock_task(void *arguments);
int user_clock_task_init(void) {
int ret;
ret = pthread_create(&user_clock_task_thread, NULL, user_clock_task, NULL);
if(ret) return ret;
pthread_setname_np(user_clock_task_thread, "CLOCK");
USER_LOG(USER_LOG_INFO, "Clock thread created.");
}
int user_clock_task_deinit(void) {
USER_LOG(USER_LOG_INFO, "CLOCK task_deinit() called.");
pthread_join(user_clock_task_thread, NULL);
USER_LOG(USER_LOG_INFO, "CLOCK tasks joined.");
return 0;
}
void *user_clock_task(void *arguments) {
while(g_running && !g_lvgl_ready) {
sleep(1);
}
lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK); /*Break the long lines*/
lv_label_set_recolor(label1, true); /*Enable re-coloring by commands in the text*/
lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER); /*Center aligned lines*/
lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label "
"and wrap long text automatically.");
lv_obj_set_width(label1, 320);
lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);
lv_obj_t * label2 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC); /*Circular scroll*/
lv_obj_set_width(label2, 320);
lv_label_set_text(label2, "It is a circularly scrolling text. ");
lv_obj_align(label2, NULL, LV_ALIGN_CENTER, 0, 30);
while(g_running) {
sleep(1);
}
}

View File

@ -9,11 +9,18 @@
#include "tasks/user_tasks.h"
#include "impl/user_lvgl_impl.h"
#define PIXBUF_SIZE 320 * 10
extern uint8_t g_running;
uint8_t g_lvgl_ready = 0;
pthread_t user_lv_task_thread;
pthread_t user_lv_tick_thread;
static lv_disp_buf_t s_disp_buf;
static lv_color_t s_pix_buf[2][PIXBUF_SIZE];
void *user_lv_task(void *arguments);
void *user_lv_tick(void *arguments);
@ -26,6 +33,14 @@ int user_lvgl_task_init(void) {
lv_init();
lv_disp_buf_init(&s_disp_buf, s_pix_buf[0], s_pix_buf[1], PIXBUF_SIZE);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.buffer = &s_disp_buf;
disp_drv.flush_cb = user_lvgl_impl_flush_cb;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ret = pthread_create(&user_lv_task_thread, NULL, user_lv_task, NULL);
if(ret) return ret;
ret = pthread_create(&user_lv_tick_thread, NULL, user_lv_tick, NULL);
@ -35,6 +50,8 @@ int user_lvgl_task_init(void) {
pthread_setname_np(user_lv_task_thread, "LV_TASK");
pthread_setname_np(user_lv_tick_thread, "LV_TICK");
g_lvgl_ready = 1;
}
int user_lvgl_task_deinit(void) {