LVGL testing code.

This commit is contained in:
imi415 2021-01-24 12:08:57 +00:00
parent 6bfc51062a
commit 4a33a78419
13 changed files with 235 additions and 52 deletions

View File

@ -7,8 +7,10 @@ set(CMAKE_C_STANDARD 11)
set(SOURCES
main.c
st75256_impl.c
st75256_lvgl_impl.c
user_tasks.c
tasks/task_lvgl.c
tasks/task_hello.c
lib/st75256_lcd/st75256_lcd.c
lib/LittleVGL/src/lv_themes/lv_theme.c
lib/LittleVGL/src/lv_themes/lv_theme_empty.c

View File

@ -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 108 /*[px]*/
/* The the real width of the display changes some default values:
* default object sizes, layout of examples, etc.
@ -80,7 +80,7 @@ typedef int16_t lv_coord_t;
#define LV_MEM_CUSTOM 1
#if LV_MEM_CUSTOM == 0
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
# define LV_MEM_SIZE (32U * 1024U)
# define LV_MEM_SIZE (128U * 1024U)
/* Compiler prefix for a big array declaration */
# define LV_MEM_ATTR
@ -215,7 +215,7 @@ typedef void * lv_fs_drv_user_data_t;
#endif
/*1: Add a `user_data` to drivers and objects*/
#define LV_USE_USER_DATA 0
#define LV_USE_USER_DATA 1
/*1: Show CPU usage and FPS count in the right bottom corner*/
#define LV_USE_PERF_MONITOR 0
@ -408,8 +408,8 @@ 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_8 1
#define LV_FONT_UNSCII_16 1
/* Optionally declare your custom fonts here.
* You can use these fonts as default font too
@ -473,14 +473,14 @@ typedef void * lv_font_user_data_t;
#define LV_USE_THEME_MONO 1
#define LV_THEME_DEFAULT_INCLUDE <stdint.h> /*Include a header for the init. function*/
#define LV_THEME_DEFAULT_INIT lv_theme_material_init
#define LV_THEME_DEFAULT_INIT lv_theme_mono_init
#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_FLAG 0
#define LV_THEME_DEFAULT_FONT_SMALL &lv_font_unscii_16
#define LV_THEME_DEFAULT_FONT_NORMAL &lv_font_unscii_16
#define LV_THEME_DEFAULT_FONT_SUBTITLE &lv_font_unscii_16
#define LV_THEME_DEFAULT_FONT_TITLE &lv_font_unscii_16
/*=================
* Text settings

View File

@ -0,0 +1,12 @@
#ifndef __ST75256_LVGL_IMPL_H
#define __ST75256_LVGL_IMPL_H
#include "st75256_lcd.h"
#include "lvgl.h"
void _st75256_lv_impl_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area);
void _st75256_lv_impl_set_px(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa);
void _st75256_lv_impl_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
#endif

View File

@ -14,4 +14,9 @@ void *lvgl_tick_thread(void *arguments);
extern pthread_t lvgl_task_thread_handle;
void *lvgl_task_thread(void *arguments);
int hello_task_init(void);
int hello_task_deinit(void);
extern pthread_t hello_thread_handle;
void *hello_thread(void *arguments);
#endif

View File

@ -1,20 +1,21 @@
#include "st75256_lcd.h"
uint8_t jlx_25664_init_sequence[] = {
0x00, 0x30,
0x00, 0x94,
0x00, 0x31,
0x01, 0xD7, 0x9F,
0x03, 0x32, 0x00, 0x01, 0x03,
0x10, 0x20, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x10, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F,
0x00, 0x30,
0x02, 0x75, 0x00, 0x14,
0x02, 0x15, 0x00, 0xFF,
0x02, 0xBC, 0x00, 0xA6,
0x03, 0xCA, 0x00, 0x9F, 0x20,
0x01, 0xF0, 0x10,
0x02, 0x81, 0x36, 0x04,
0x01, 0x20, 0x0B
0x00, 0x30, // Extension command EXT[1:0] = 0,0
0x00, 0x94, // Set power save mode, SLP = 0
0x00, 0x31, // Extension command EXT[1:0] = 0,1
0x01, 0xD7, 0x9F, // Set auto-read instruction, XARD = 1
0x03, 0x32, 0x00, 0x01, 0x03, // 32 - Set analog circuit, BE[1:0] = 0,1; BS[2:0] = 0,1,1
0x10, 0x20, 0x00, 0x00, 0x00, 0x0B, 0x0B, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, // 31 - Set grey scale level
0x04, 0xF0, 0x0D, 0x0D, 0x0D, 0x0D, // Frame rate, 0x0C - 69.0Hz
0x00, 0x30, // Extension command EXT[1:0] = 0,0
0x02, 0x75, 0x00, 0x14, // 7 - Set page address, YS = 0x00, YE = 0x14
0x02, 0x15, 0x00, 0xFF, // 8 - Set column address, XS = 0x00, XE = 0xFF
0x01, 0xBC, 0x00, // 9 - Data scan direction, MV = 0, MX = 0, MY = 0
0x03, 0xCA, 0x00, 0x9F, 0x20, // 5 - Display control, CLD = 0(not divide), DT = 0x9F(128), LF[4:0] = 1,0,0,0,0(16); FL = 0
0x01, 0xF0, 0x10, // 28 - Display mode: DM = 0(Mono)
0x02, 0x81, 0x36, 0x04, // 21 - Set VOP, VOP = 0x136
0x01, 0x20, 0x0B // 20 - Power control, VB = 1, VF = 1, VR = 1
};
st75256_ret_t _st75256_hardware_reset(st75256_t *lcd) {
@ -34,8 +35,21 @@ st75256_ret_t _st75256_init_seq(st75256_t *lcd) {
}
st75256_ret_t _st75256_display_on(st75256_t *lcd) {
uint8_t cmd = 0xAF;
uint8_t cmd = 0x30;
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd, 0x01));
cmd = 0xAF;
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd, 0x01));
return ST75256_OK;
}
st75256_ret_t _st75256_cursor(st75256_t *lcd, uint8_t column_start, uint8_t column_end, uint8_t page_start, uint8_t page_end) {
uint8_t cmd[] = { 0x30, 0x15, column_start, column_end, 0x75, page_start, page_end };
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, cmd, 0x01)); // Extension command EXT[1:0] = 0,0
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd[1], 0x03));
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd[4], 0x03));
return ST75256_OK;
}
st75256_ret_t st75256_init(st75256_t *lcd) {
@ -67,6 +81,37 @@ st75256_ret_t st75256_set_mode(st75256_t *lcd, st75256_mode_t mode) {
return ST75256_OK;
}
st75256_ret_t st75256_cursor(st75256_t *lcd, uint8_t x_start, uint8_t x_end, uint8_t y_start, uint8_t y_end) {
st75256_ret_t st75256_upload_data(st75256_t *lcd, uint8_t *data, uint8_t x_start, uint8_t x_end, uint8_t y_start, uint8_t y_end) {
uint8_t cmd = 0x30;
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd, 0x01)); // Ext. Command 1
uint32_t bytes_to_transfer = 0x00;
uint8_t page_offset = (lcd->mode == ST75256_GREY ? 8 : 4);
uint8_t page_start = page_offset;
uint8_t page_end = page_offset;
if(lcd->mode == ST75256_GREY) {
if(y_start % 4 != 0 || (y_end + 1) % 4 != 0) {
return ST75256_ERROR;
}
bytes_to_transfer = (x_end - x_start + 1) * (y_end - y_start + 1) / 4;
page_start += y_start / 4;
page_end += y_end / 4;
}
else {
if(y_start % 8 != 0 || (y_end + 1) % 8 != 0) {
return ST75256_ERROR;
}
bytes_to_transfer = (x_end - x_start + 1) * (y_end - y_start + 1) / 8;
page_start += y_start / 8;
page_end += y_end / 8;
}
ST75256_ERROR_CHECK(_st75256_cursor(lcd, x_start, x_end, page_start, page_end));
cmd = 0x5C;
ST75256_ERROR_CHECK(lcd->cb.write_cmd_cb(lcd->user_data, &cmd, 0x01)); // Write data
ST75256_ERROR_CHECK(lcd->cb.write_data_cb(lcd->user_data, data, (uint16_t)bytes_to_transfer));
return ST75256_OK;
}

View File

@ -33,5 +33,6 @@ typedef struct {
st75256_ret_t st75256_init(st75256_t *lcd);
st75256_ret_t st75256_set_contrast(st75256_t *lcd, uint16_t contrast);
st75256_ret_t st75256_set_mode(st75256_t *lcd, st75256_mode_t mode);
st75256_ret_t st75256_upload_data(st75256_t *lcd, uint8_t *data, uint8_t x_start, uint8_t x_end, uint8_t y_start, uint8_t y_end);
#endif

View File

20
main.c
View File

@ -1,27 +1,9 @@
#include <stdio.h>
#include <string.h>
#include "st75256_lcd.h"
#include "st75256_impl.h"
#include "user_tasks.h"
st75256_t g_lcd = {
.user_data = NULL,
.cb = {
.write_cmd_cb = _lcd_impl_write_cmd,
.write_data_cb = _lcd_impl_write_data,
.reset_cb = _lcd_impl_reset,
.delay_cb = _lcd_impl_delay
}
};
int main() {
g_lcd.user_data = _lcd_impl_init();
if(g_lcd.user_data == NULL) return -1;
st75256_init(&g_lcd);
st75256_set_contrast(&g_lcd, 305);
st75256_set_mode(&g_lcd, ST75256_GREY);
user_tasks_init();
user_tasks_loop();
user_tasks_deinit();

View File

@ -1,7 +1,9 @@
#include "st75256_impl.h"
#define SPIDEV_MAX_LEN 4096
_st75256_impl_t *_lcd_impl_init(void) {
int spi_fd = open(CONFIG_SPIDEV_FILENAME, O_RDWR);
int spi_fd = open(CONFIG_SPIDEV_FILENAME, O_RDWR | O_SYNC);
if(spi_fd < 0) return NULL;
uint32_t spi_mode = 0; // Nothing to be set in default mode.
@ -109,8 +111,20 @@ st75256_ret_t _lcd_impl_write_data(void *handle, uint8_t *data, uint16_t len) {
.bits_per_word = 8
};
ret = ioctl(impl->spi_fd, SPI_IOC_MESSAGE(1), &data_tr);
if(ret < len) return ST75256_ERROR;
uint32_t transfer_times = (len / SPIDEV_MAX_LEN) + ((len % SPIDEV_MAX_LEN != 0) ? 1 : 0); // Linux SPI can transfer some bytes each time.
for(uint32_t i = 0; i < transfer_times; i++) {
if(i == transfer_times - 1) {
data_tr.len = len - SPIDEV_MAX_LEN * i;
}
else {
data_tr.len = SPIDEV_MAX_LEN;
}
data_tr.tx_buf = (unsigned long)(&data[SPIDEV_MAX_LEN * i]);
ret = ioctl(impl->spi_fd, SPI_IOC_MESSAGE(1), &data_tr);
if(ret < data_tr.len) return ST75256_ERROR;
}
return ST75256_OK;
}

48
st75256_lvgl_impl.c Normal file
View File

@ -0,0 +1,48 @@
#include "st75256_lvgl_impl.h"
void _st75256_lv_impl_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area) {
st75256_t *lcd = disp_drv->user_data;
if(lcd->mode == ST75256_MONO) {
area->y1 = (area->y1 / 8) * 8;
area->y2 = (area->y2 / 8) * 8 + 7;
}
else {
area->y1 = (area->y1 / 4) * 4;
area->y2 = (area->y2 / 4) * 4 + 3;
}
}
void _st75256_lv_impl_set_px(lv_disp_drv_t *disp_drv, uint8_t *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) {
st75256_t *lcd = disp_drv->user_data;
uint16_t byte_index;
uint8_t bit_index;
if(lcd->mode == ST75256_MONO) {
byte_index = x + (y / 8) * buf_w;
bit_index = 7 - (y & 7);
if(color.full) {
buf[byte_index] |= 1U << bit_index;
}
else {
buf[byte_index] &= ~(1U << bit_index);
}
}
else {
byte_index = x + (y / 4) * buf_w;
bit_index = 6 - ((y & 3) * 2);
buf[byte_index] &= ~(3U << bit_index);
if(color.full) {
buf[byte_index] |= (3U << bit_index);
}
}
}
void _st75256_lv_impl_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
st75256_t *lcd = disp_drv->user_data;
st75256_upload_data(lcd, (uint8_t *)color_p, area->x1, area->x2, area->y1, area->y2);
lv_disp_flush_ready(disp_drv);
printf("FLUSH %d\n", area->y1);
}

33
tasks/task_hello.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdint.h>
#include <unistd.h>
#include "lvgl.h"
#include "user_tasks.h"
extern uint8_t g_running;
extern pthread_mutex_t g_lvgl_mutex;
int hello_task_init(void) {
int ret = pthread_create(&hello_thread_handle, NULL, hello_thread, NULL);
ret = pthread_setname_np(hello_thread_handle, "HELLO_THR");
}
int hello_task_deinit(void) {
}
pthread_t hello_thread_handle;
void *hello_thread(void *arguments) {
pthread_mutex_lock(&g_lvgl_mutex);
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_label_set_anim_speed(label2, 3);
lv_obj_set_width(label2, 256);
lv_label_set_text(label2, "It is a circularly scrolling text. ");
lv_obj_align(label2, NULL, LV_ALIGN_IN_TOP_MID, 0, 30);
pthread_mutex_unlock(&g_lvgl_mutex);
while(g_running) {
sleep(1);
}
}

View File

@ -4,15 +4,54 @@
#include "lvgl.h"
#include "st75256_impl.h"
#include "st75256_lvgl_impl.h"
#include "user_tasks.h"
extern uint8_t g_running;
pthread_mutex_t g_lvgl_mutex = PTHREAD_MUTEX_INITIALIZER;
st75256_t g_lcd = {
.user_data = NULL,
.cb = {
.write_cmd_cb = _lcd_impl_write_cmd,
.write_data_cb = _lcd_impl_write_data,
.reset_cb = _lcd_impl_reset,
.delay_cb = _lcd_impl_delay
}
};
#define LCD_BUF_SIZE (256 * 10)
lv_disp_buf_t g_lcd_disp_buf;
lv_color_t g_lcd_buf[LCD_BUF_SIZE];
int lvgl_task_init(void) {
int ret;
g_lcd.user_data = _lcd_impl_init();
if(g_lcd.user_data == NULL) return -1;
st75256_init(&g_lcd);
st75256_set_contrast(&g_lcd, 310);
st75256_set_mode(&g_lcd, ST75256_GREY);
lv_init();
lv_disp_buf_init(&g_lcd_disp_buf, g_lcd_buf, NULL, LCD_BUF_SIZE);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.buffer = &g_lcd_disp_buf;
disp_drv.set_px_cb = _st75256_lv_impl_set_px;
disp_drv.flush_cb = _st75256_lv_impl_flush;
disp_drv.rounder_cb = _st75256_lv_impl_rounder;
disp_drv.user_data = &g_lcd;
lv_disp_drv_register(&disp_drv);
ret = pthread_create(&lvgl_tick_thread_handle, NULL, lvgl_tick_thread, NULL);
if(ret) return ret;
ret = pthread_create(&lvgl_task_thread_handle, NULL, lvgl_task_thread, NULL);
@ -29,7 +68,7 @@ int lvgl_task_deinit(void) {
pthread_t lvgl_tick_thread_handle;
void *lvgl_tick_thread(void *arguments) {
while(g_running) {
usleep(30 * 1000);
usleep(29 * 1000);
pthread_mutex_lock(&g_lvgl_mutex);
lv_tick_inc(30);
pthread_mutex_unlock(&g_lvgl_mutex);
@ -39,7 +78,7 @@ void *lvgl_tick_thread(void *arguments) {
pthread_t lvgl_task_thread_handle;
void *lvgl_task_thread(void *arguments) {
while(g_running) {
usleep(10 * 1000);
usleep(17 * 1000);
pthread_mutex_lock(&g_lvgl_mutex);
lv_task_handler();
pthread_mutex_unlock(&g_lvgl_mutex);

View File

@ -19,6 +19,7 @@ void user_tasks_init(void) {
}
lvgl_task_init();
hello_task_init();
}
void user_tasks_loop(void) {
@ -28,5 +29,6 @@ void user_tasks_loop(void) {
}
void user_tasks_deinit(void) {
hello_task_deinit();
lvgl_task_deinit();
}