LVGL testing code.
This commit is contained in:
parent
6bfc51062a
commit
4a33a78419
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
20
main.c
20
main.c
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue