Fighting with the MMC DMA, work in progress

This commit is contained in:
Th3maz1ng 2022-12-04 20:15:47 +01:00
parent 2ca0d48258
commit 0353e42482
35 changed files with 6294 additions and 105 deletions

View File

@ -4,7 +4,6 @@ sinclude $(TOP_DIR)/tools/w800/conf.mk
ifndef PDIR
GEN_LIBS = libuser$(LIB_EXT)
COMPONENTS_libuser = gfx/libusergfx$(LIB_EXT)
#COMPONENTS_libuser = drivers/libdrivers$(LIB_EXT)
endif
#DEFINES +=

View File

@ -9,10 +9,10 @@
* Define which logs to display :
*/
#define LOG_LEVEL_ERROR (1)
#define LOG_LEVEL_WARNING (1)
#define LOG_LEVEL_INFO (1)
#define LOG_LEVEL_TRACE (1)
#define LOG_LEVEL_DEBUG (1)
#define LOG_ENABLE_ERROR (1)
#define LOG_ENABLE_WARNING (1)
#define LOG_ENABLE_INFO (1)
#define LOG_ENABLE_TRACE (1)
#define LOG_ENABLE_DEBUG (1)
#endif //APPCONFIG_H

View File

@ -4,31 +4,31 @@
#include "app_common.h"
#include "app_config.h"
#if LOG_LEVEL_ERROR
#if LOG_ENABLE_ERROR
#define APP_LOG_ERROR(message, ...) do{printf("[ERROR] %s: " message " (in %s at #%d)"NEW_LINE, __func__, ##__VA_ARGS__, __FILE__, __LINE__);}while(0)
#else
#define APP_LOG_ERROR(message, ...) do{}while(0)
#endif
#if LOG_LEVEL_WARNING
#if LOG_ENABLE_WARNING
#define APP_LOG_WARNING(message, ...) do{printf("[WARNING] %s: " message " (in %s at #%d)"NEW_LINE, __func__, ##__VA_ARGS__, __FILE__, __LINE__);}while(0)
#else
#define APP_LOG_WARNING(message, ...) do{}while(0)
#endif
#if LOG_LEVEL_INFO
#if LOG_ENABLE_INFO
#define APP_LOG_INFO(message, ...) do{printf("[INFO] %s: " message " (in %s at #%d)"NEW_LINE, __func__, ##__VA_ARGS__, __FILE__, __LINE__);}while(0)
#else
#define APP_LOG_INFO(message, ...) do{}while(0)
#endif
#if LOG_LEVEL_TRACE
#if LOG_ENABLE_TRACE
#define APP_LOG_TRACE(message, ...) do{printf("[TRACE] %s: " message " (in %s at #%d)"NEW_LINE, __func__, ##__VA_ARGS__, __FILE__, __LINE__);}while(0)
#else
#define APP_LOG_TRACE(message, ...) do{}while(0)
#endif
#if LOG_LEVEL_DEBUG
#if LOG_ENABLE_DEBUG
#define APP_LOG_DEBUG(message, ...) do{printf("[DEBUG] %s: " message " (in %s at #%d)"NEW_LINE, __func__, ##__VA_ARGS__, __FILE__, __LINE__);}while(0)
#else
#define APP_LOG_DEBUG(message, ...) do{}while(0)

View File

@ -4,6 +4,7 @@ sinclude $(TOP_DIR)/tools/w800/conf.mk
ifndef PDIR
GEN_LIBS = libdrivers$(LIB_EXT)
COMPONENTS_libdrivers = lcd/libdriverslcd$(LIB_EXT)
COMPONENTS_libdrivers = mmc_sdio/libdriversmmc_sdio$(LIB_EXT)
endif
#DEFINES +=

View File

@ -0,0 +1,16 @@
TOP_DIR = ../../..
sinclude $(TOP_DIR)/tools/w800/conf.mk
ifndef PDIR
GEN_LIBS = libdriverslcd$(LIB_EXT)
COMPONENTS_libdriverslcd = ../mmc_sdio/libdriversmmc_sdio$(LIB_EXT)
endif
#DEFINES +=
sinclude $(TOP_DIR)/tools/w800/rules.mk
INCLUDES := $(INCLUDES) -I $(PDIR)include
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

View File

@ -1,70 +0,0 @@
#include "FreeRTOS.h"
#include "lcd.h"
void lcd_config_init(LCDConfig_t * const LCDConfig)
{
if(!LCDConfig) return;
LCDConfig->LCDPWMBacklightPin = -1;
LCDConfig->LCDClockPin = -1;
LCDConfig->LCDDataPin = -1;
LCDConfig->LCDCSPin = -1;
LCDConfig->LCDDataCommandPin = -1;
LCDConfig->LCDResetPin = -1;
}
void lcd_init(LCDConfig_t * const LCDConfig)
{
if(!LCDConfig) return;
// Backlight is controlled using PWM
tls_gpio_cfg(LCDConfig->LCDPWMBacklightPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDCSPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDDataCommandPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDResetPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
// The clock and data line are driven using the MMC peripheral
tls_io_cfg_set(LCDConfig->LCDClockPin, WM_IO_OPTION2);
tls_io_cfg_set(LCDConfig->LCDDataPin, WM_IO_OPTION2);
// We set some of the pins default value
lcd_set_backlight(LCDConfig, 0);
lcd_set_cs(LCDConfig, false);
lcd_set_data_command(LCDConfig, LCD_DATA);
lcd_hardware_reset(LCDConfig);
// Init MMC SDIO peripheral
}
void lcd_set_window(u16 x_start, u16 y_start, u16 x_end, u16 y_end);
void lcd_write_frame(void);
void lcd_set_backlight(LCDConfig_t * const LCDConfig, u8 brightness)
{
if(brightness)
tls_gpio_write(LCDConfig->LCDPWMBacklightPin, 1);
else
tls_gpio_write(LCDConfig->LCDPWMBacklightPin, 1);
}
void lcd_set_cs(LCDConfig_t * const LCDConfig, bool selected)
{
// CS is active low...
tls_gpio_write(LCDConfig->LCDCSPin, !selected);
}
void lcd_set_data_command(LCDConfig_t * const LCDConfig, LCDDataCommand_e dataCommand)
{
tls_gpio_write(LCDConfig->LCDDataCommandPin, dataCommand);
}
void lcd_hardware_reset(LCDConfig_t * const LCDConfig)
{
tls_gpio_write(LCDConfig->LCDResetPin, 0);
tls_os_time_delay(pdMS_TO_TICKS(1));
tls_gpio_write(LCDConfig->LCDResetPin, 1);
}

View File

@ -2,7 +2,7 @@ TOP_DIR = ../../..
sinclude $(TOP_DIR)/tools/w800/conf.mk
ifndef PDIR
GEN_LIBS = libdriverslcd$(LIB_EXT)
GEN_LIBS = libdriversmmc_sdio$(LIB_EXT)
endif
#DEFINES +=

View File

@ -2,6 +2,60 @@
#include "lvgl.h"
#include "FreeRTOS.h"
#include "wm_include.h"
#include "lcd.h"
#include "watch_face.h"
#include "menu_screen.h"
#include "lv_port_indev.h"
static lv_color_t lvgl_draw_buffer[LCD_PIXEL_WIDTH * LCD_PIXEL_HEIGHT / 10];
static lv_disp_draw_buf_t lvgl_draw_buffer_dsc;
static lv_disp_drv_t display_driver;
static LCDConfig_t LCDConfig;
static void lvgl_display_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
lcd_draw_rect_frame(&LCDConfig, area->x1, area->y1, area->x2 - area->x1 + 1, area->y2 - area->y1 + 1, (uint8_t *)color_p);
lv_disp_flush_ready(disp_drv);
}
struct tm temptm = {0};
static void date_time_cb(struct tm * const dateTime)
{
if(!dateTime)return;
/*time_t time_type = time(NULL);
struct tm *tm = localtime(&time_type);*/
//LV_LOG_USER("Time is : %llu, Time : %d:%d:%d", time_type, tm->tm_hour, tm->tm_min, tm->tm_sec);
*dateTime = temptm;
}
static void tick_timer_irq(u8 *arg)
{
lv_tick_inc(1);
}
void lv_create_tick(void)
{
u8 timer_id;
struct tls_timer_cfg timer_cfg;
timer_cfg.unit = TLS_TIMER_UNIT_MS;
timer_cfg.timeout = 1;
timer_cfg.is_repeat = 1;
timer_cfg.callback = (tls_timer_irq_callback)tick_timer_irq;
timer_cfg.arg = NULL;
timer_id = tls_timer_create(&timer_cfg);
tls_timer_start(timer_id);
// printf("timer start\n");
}
WatchFace_t watchFace;
MenuScreen_t menuScreen;
void gfx_task(void *param)
{
@ -10,15 +64,63 @@ void gfx_task(void *param)
/* Initialize the lvgl library*/
lv_init();
lv_create_tick();
/* Create, initialize and register the display driver*/
static lv_disp_drv_t display_driver;
lv_disp_drv_init(&display_driver);
display_driver.hor_res = LCD_PIXEL_WIDTH;
display_driver.ver_res = LCD_PIXEL_HEIGHT;
display_driver.rotated = LV_DISP_ROT_180;
lv_disp_draw_buf_init(&lvgl_draw_buffer_dsc, lvgl_draw_buffer, NULL, LCD_PIXEL_WIDTH * LCD_PIXEL_HEIGHT / 10);
display_driver.draw_buf = &lvgl_draw_buffer_dsc;
display_driver.flush_cb = &(lvgl_display_flush_cb);
/* Initialize the LCD display */
lcd_config_init(&LCDConfig);
#if defined(W800)
LCDConfig.LCDPWMBacklightPin = WM_IO_PA_07;
LCDConfig.LCDClockPin = WM_IO_PB_06;
LCDConfig.LCDDataPin = WM_IO_PB_07;
LCDConfig.LCDChipSelectPin = WM_IO_PB_10;
LCDConfig.LCDDataCommandPin = WM_IO_PB_08;
LCDConfig.LCDResetPin = WM_IO_PB_09;
#elif defined(W801)
LCDConfig.LCDPWMBacklightPin = WM_IO_PA_08;
LCDConfig.LCDClockPin = WM_IO_PA_09;
LCDConfig.LCDDataPin = WM_IO_PA_10;
LCDConfig.LCDChipSelectPin = WM_IO_PA_13;
LCDConfig.LCDDataCommandPin = WM_IO_PA_11;
LCDConfig.LCDResetPin = WM_IO_PA_12;
#endif
lcd_init(&LCDConfig);
if(!lv_disp_drv_register(&display_driver))
{
APP_LOG_ERROR("Failed to register display driver");
}
lv_port_indev_init();
watch_face_init(&watchFace);
menu_screen_init(&menuScreen);
watch_face_register_cb(&watchFace, &(date_time_cb));
watch_face_create(&watchFace);
lv_scr_load(watchFace.display);
for(;;)
{
lv_timer_handler();
tls_os_time_delay_until(&time_ref, pdMS_TO_TICKS(5));
static u32 counter = 0;
if(counter++ % 200 == 0)
APP_LOG_DEBUG("GFX ALIVE");
}
}

View File

@ -4,8 +4,8 @@
#include "wm_include.h"
#define GFX_STACK_SIZE_IN_BYTES (1024 * sizeof(StackType_t))
#define GFX_STACK_PRIORITY (31)
#define GFX_STACK_SIZE_IN_BYTES (4096 * sizeof(StackType_t))
#define GFX_STACK_PRIORITY (5)//(31)
static u8 gfx_task_stack[GFX_STACK_SIZE_IN_BYTES];
tls_os_task_t gfx_task_handle;

View File

@ -0,0 +1,270 @@
#include "FreeRTOS.h"
#include "mmc_sdio.h"
#include "lcd.h"
#include "app_log.h"
static void lcd_write_cmd_data_bytes(LCDConfig_t * const LCDConfig, const u8 *cmdAndData, u32 dataLengthInBytes)
{
// Select the slave CS line and tell him that he will receive a command !
lcd_set_cs(LCDConfig, LCD_SELECTED);
lcd_set_data_command(LCDConfig, LCD_COMMAND);
mmc_sdio_driver_write_one(*cmdAndData++);
if(dataLengthInBytes >= 2)
{
lcd_set_data_command(LCDConfig, LCD_DATA);
for (size_t i = 0; i < dataLengthInBytes - 1; ++i)
mmc_sdio_driver_write_one(*cmdAndData++);
}
// We release the slave CS line and tell him that we are in DATA mode
lcd_set_cs(LCDConfig, LCD_RELEASED);
lcd_set_data_command(LCDConfig, LCD_DATA);
}
// ST7789初始化
const uint8_t st7789_init_seq[] = {
/* len , delay, cmd, data ... */
0x01, 0x14, 0x01, // Software reset
0x01, 0x0A, 0x11, // Exit sleep mode
0x02, 0x02, 0x3A, 0x55, // Set colour mode to 16 bit
0x02, 0x00, 0x36, 0x00, // Set MADCTL: row then column, refresh is bottom to top ????
0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xf0, // CASET: column addresses from 0 to 240 (f0)
0x05, 0x00, 0x2B, 0x00, 0x00, 0x01, 0x40, // RASET: row addresses from 0 to 240 (f0)
0x01, 0x02, 0x21, // Inversion on, then 10 ms delay (supposedly a hack?)
0x01, 0x02, 0x13, // Normal display on, then 10 ms delay
0x01, 0x02, 0x29, // Main screen turn on, then wait 500 ms
0 // Terminate list
};
/**
*
* 使RGB666时lvgl库中配置 #define LV_COLOR_16_SWAP 0
* 使RGB565时lvgl库中配置 #define LV_COLOR_16_SWAP 1
* ILI9488 RGB666
* ST7796S RGB565 RGB666
*/
// ILI9341初始化
const uint8_t ili9341_init_seq[] = {
/* len , delay, cmd, data ... */
0x01, 0x14, 0x01, // Software reset
0x04, 0x00, 0xCF, 0x00, 0xD9, 0x30,
0x05, 0x00, 0xED, 0x64, 0x03, 0x12, 0x81,
0x04, 0x00, 0xE8, 0x85, 0x10, 0x7A,
0x06, 0x00, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
0x02, 0x00, 0xF7, 0x20,
0x03, 0x00, 0xEA, 0x00, 0x00,
0x02, 0x00, 0xC0, 0x1B, // Power control VRH[5:0]
0x02, 0x00, 0xC1, 0x12, // Power control SAP[2:0];BT[3:0] //0x01
0x03, 0x00, 0xC5, 0x26, 0x26, // VCM control 3F 3C
0x02, 0x00, 0xC7, 0xB0, // VCM control2
//0x02, 0x00, 0x36, 0x08, // (1<<3)|(0<<6)|(0<<7) 旋转角度0
0x02, 0x00, 0x36, 0x68, // (1<<3)|(0<<6)|(0<<7) 旋转角度0
0x02, 0x00, 0x3A, 0x55,
0x03, 0x00, 0xB1, 0x00, 0x1A,
0x03, 0x00, 0xB6, 0x0A, 0xA2,
0x02, 0x00, 0xF2, 0x00,
0x02, 0x00, 0x26, 0x01,
0x10, 0x00, 0xE0, 0x1F, 0x24, 0x24, 0x0D, 0x12, 0x09, 0x52, 0xB7, 0x3F, 0x0C, 0x15, 0x06, 0x0E, 0x08, 0x00,
0x10, 0x00, 0xE1, 0x00, 0x1B, 0x1B, 0x02, 0x0E, 0x06, 0x2E, 0x48, 0x3F, 0x03, 0x0A, 0x09, 0x31, 0x37, 0x1F,
0x05, 0x00, 0x2B, 0x00, 0x00, 0x01, 0x3F,
0x05, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xEF,
0x01, 0x02, 0x13,
0x01, 0x78, 0x11, // Exit sleep mode
0x01, 0x02, 0x29,
0
};
// ILI9488初始化
const uint8_t ili9488_init_seq[] = {
/* len , delay, cmd, data ... */
0x05, 0x00, 0xF7, 0xA9, 0x51, 0x2C, 0x82,
0x03, 0x00, 0xC0, 0x11, 0x09,
0x02, 0x00, 0xC1, 0x41,
0x04, 0x00, 0xC5, 0x00, 0x0A, 0x80,
0x03, 0x00, 0xB1, 0xB0, 0x11,
0x02, 0x00, 0xB4, 0x02,
0x03, 0x00, 0xB6, 0x02, 0x42,
0x02, 0x00, 0xB7, 0xC6,
0x03, 0x00, 0xBE, 0x00, 0x04,
0x02, 0x00, 0xE9, 0x00,
0x02, 0x00, 0x36, 0x08, // (1<<3)|(0<<6)|(0<<7) 旋转角度0
0x02, 0x00, 0x3A, 0x66, // Pixel Formath 18bit
0x10, 0x00, 0xE0, 0x00, 0x07, 0x10, 0x09, 0x17, 0x0B, 0x41, 0x89, 0x4B, 0x0A, 0x0C, 0x0E, 0x18, 0x1B, 0x0F,
0x10, 0x00, 0xE1, 0x00, 0x17, 0x1A, 0x04, 0x0E, 0x06, 0x2F, 0x45, 0x43, 0x02, 0x0A, 0x09, 0x32, 0x36, 0x0F,
0x01, 0x78, 0x11,
0x01, 0x02, 0x29,
0
};
// ST7796S初始化
const uint8_t ST7796S_init_seq[] = {
/* len , delay, cmd, data ... */
0x02, 0x00, 0xF0, 0xC3,
0x02, 0x00, 0xF0, 0x96,
0x02, 0x00, 0x36, 0x68,
0x02, 0x00, 0xB0, 0x80,
0x03, 0x00, 0xB6, 0x00, 0x02,
0x05, 0x00, 0xB5, 0x02, 0x03, 0x00, 0x04,
0x03, 0x00, 0xB1, 0x80, 0x10,
0x02, 0x00, 0xB4, 0x00,
0x02, 0x00, 0xB7, 0xC6,
0x02, 0x00, 0xC5, 0x24,
0x02, 0x00, 0xE4, 0x31,
0x09, 0x00, 0xE8, 0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33,
0x02, 0x00, 0xC2, 0xA7,
0x0F, 0x02, 0xE0, 0xF0, 0x09, 0x13, 0x12, 0x12, 0x2B, 0x3C, 0x44, 0x4B, 0x1B, 0x18, 0x17, 0x1D, 0x21,
0x0F, 0x02, 0xE1, 0xF0, 0x09, 0x13, 0x0C, 0x0D, 0x27, 0x3B, 0x44, 0x4D, 0x0B, 0x17, 0x17, 0x1D, 0x21,
#if BSP_LCD_Direction == 0
0x02, 0x00, 0x36, 0x48, //0xEC 横向 0x48纵向
#else
0x02, 0x00, 0x36, 0xEC, //0xEC 横向 0x48纵向
#endif
0x02, 0x00, 0xF0, 0xC3,
0x02, 0x00, 0xF0, 0x69,
0x01, 0x02, 0x13,
0x01, 0x78, 0x11,
0x01, 0x02, 0x29,
#if(COLOR_FORMAT==0)
0x02, 0x00, 0x3A, 0x05, // 0x05 RGB555 0x66 RGB666
#else
0x02, 0x00, 0x3A, 0x66, // 0x05 RGB555 0x66 RGB666
#endif
0
};
void lcd_config_init(LCDConfig_t * const LCDConfig)
{
if(!LCDConfig) return;
LCDConfig->LCDPWMBacklightPin = -1;
LCDConfig->LCDClockPin = -1;
LCDConfig->LCDDataPin = -1;
LCDConfig->LCDChipSelectPin = -1;
LCDConfig->LCDDataCommandPin = -1;
LCDConfig->LCDResetPin = -1;
}
void lcd_init(LCDConfig_t * const LCDConfig)
{
if(!LCDConfig) return;
// Backlight is controlled using PWM
tls_gpio_cfg(LCDConfig->LCDPWMBacklightPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDChipSelectPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDDataCommandPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LCDConfig->LCDResetPin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
// The clock and data line are driven using the MMC peripheral
tls_io_cfg_set(LCDConfig->LCDClockPin, WM_IO_OPTION2);
tls_io_cfg_set(LCDConfig->LCDDataPin, WM_IO_OPTION2);
// We set some of the pins default value
lcd_set_backlight(LCDConfig, 0);
lcd_set_cs(LCDConfig, LCD_RELEASED);
lcd_set_data_command(LCDConfig, LCD_DATA);
lcd_hardware_reset(LCDConfig);
// Init MMC SDIO peripheral
mmc_sdio_driver_periph_init();
#if DISPLAY_CONTROLLER == 0
const u8 *cmd = ili9341_init_seq;
#elif DISPLAY_CONTROLLER == 1
const u8 *cmd = st7789_init_seq;
#endif
// We send the init sequence to the screen :
while(*cmd)
{
lcd_write_cmd_data_bytes(LCDConfig, cmd + 2, *cmd);
tls_os_time_delay(*(cmd + 1));
cmd += *cmd + 2;
}
lcd_set_backlight(LCDConfig, 1);
}
static void lcd_ram_write_mode(LCDConfig_t * const LCDConfig)
{
u8 cmd = 0x2C; // RAMWR
lcd_write_cmd_data_bytes(LCDConfig, &cmd, 1);
}
void lcd_set_window(LCDConfig_t * const LCDConfig, u16 x_start, u16 y_start, u16 x_end, u16 y_end)
{
u8 dataCommand[] =
{
0x2A, x_start>>8, 0x00FF&x_start, x_end>>8, 0x00FF&x_end,
0x2B, y_start>>8, 0x00FF&y_start, y_end>>8, 0x00FF&y_end
};
lcd_write_cmd_data_bytes(LCDConfig, dataCommand, 5);
lcd_write_cmd_data_bytes(LCDConfig, dataCommand + 5, 5);
/*lcd_write_cmd_byte(0x2A);
lcd_write_data_byte(x_start>>8);
lcd_write_data_byte(0x00FF&x_start);
lcd_write_data_byte(x_end>>8);
lcd_write_data_byte(0x00FF&x_end);
lcd_write_cmd_byte(0x2B);
lcd_write_data_byte(y_start>>8);
lcd_write_data_byte(0x00FF&y_start);
lcd_write_data_byte(y_end>>8);
lcd_write_data_byte(0x00FF&y_end);*/
lcd_ram_write_mode(LCDConfig);
}
void lcd_draw_rect_frame(LCDConfig_t * const LCDConfig, u16 x, u16 y, u16 width, u16 height, u8 *data)
{
// First we check if the MMC peripheral is ready to write :
mmc_sdio_driver_wait_write_dma_ready();
// We tell the display where we want to draw the frame as well as it's size
lcd_set_window(LCDConfig, x, y, x + width - 1, y + height - 1);
// We select the screen again :
lcd_set_cs(LCDConfig, LCD_SELECTED);
// We flush the data to the display
mmc_sdio_driver_write_dma_async((u32*) data, width * height * 2);
/*for(uint32_t i = 0; i < width * height * 2; i++)
{
mmc_sdio_driver_write_one(data[i]);
}*/
}
void lcd_set_backlight(LCDConfig_t * const LCDConfig, u8 brightness)
{
if(brightness)
tls_gpio_write(LCDConfig->LCDPWMBacklightPin, 1);
else
tls_gpio_write(LCDConfig->LCDPWMBacklightPin, 1);
}
void lcd_set_cs(LCDConfig_t * const LCDConfig, LCDSelect_e selected)
{
// CS is active low...
tls_gpio_write(LCDConfig->LCDChipSelectPin, selected);
}
void lcd_set_data_command(LCDConfig_t * const LCDConfig, LCDDataCommand_e dataCommand)
{
tls_gpio_write(LCDConfig->LCDDataCommandPin, dataCommand);
}
void lcd_hardware_reset(LCDConfig_t * const LCDConfig)
{
tls_gpio_write(LCDConfig->LCDResetPin, 0);
tls_os_time_delay(/*pdMS_TO_TICKS(1)*/100);
tls_gpio_write(LCDConfig->LCDResetPin, 1);
}

View File

@ -2,12 +2,16 @@
#define LCD_H
#include "wm_include.h"
#include "lv_conf.h"
/* Used SOC : W800 or W801*/
/* Used SOC : W800 or W801 */
#define W800
/* Display drive controller */
#define ILI9341 0
#define ST7789V 1
#define DISPLAY_CONTROLLER ILI9341
//#define DISPLAY_CONTROLLER ST7789V
/* Display properties */
#define LCD_PIXEL_WIDTH 240
#define LCD_PIXEL_HEIGHT 240
typedef enum LCDDataCommand
{
@ -15,12 +19,18 @@ typedef enum LCDDataCommand
LCD_DATA = 1
} LCDDataCommand_e;
typedef enum LCDSelect
{
LCD_SELECTED = 0,
LCD_RELEASED = 1
} LCDSelect_e;
typedef struct LCDConfig
{
enum tls_io_name LCDPWMBacklightPin;
enum tls_io_name LCDClockPin;
enum tls_io_name LCDDataPin;
enum tls_io_name LCDCSPin;
enum tls_io_name LCDChipSelectPin;
enum tls_io_name LCDDataCommandPin;
enum tls_io_name LCDResetPin;
} LCDConfig_t;
@ -32,16 +42,16 @@ void lcd_config_init(LCDConfig_t * const LCDConfig);
void lcd_init(LCDConfig_t * const LCDConfig);
/* Sets the LCD write window area */
void lcd_set_window(u16 x_start, u16 y_start, u16 x_end, u16 y_end);
void lcd_set_window(LCDConfig_t * const LCDConfig, u16 x_start, u16 y_start, u16 x_end, u16 y_end);
/* Writes the frame to display's internal RAM */
void lcd_write_frame(void);
void lcd_draw_rect_frame(LCDConfig_t * const LCDConfig, u16 x, u16 y, u16 width, u16 height, u8 *data);
/* Sets the backlight to the specified brightness value */
void lcd_set_backlight(LCDConfig_t * const LCDConfig, u8 brightness);
/* Sets the chip select pin */
void lcd_set_cs(LCDConfig_t * const LCDConfig, bool selected);
void lcd_set_cs(LCDConfig_t * const LCDConfig, LCDSelect_e selected);
/* Sets the data/command pin state */
void lcd_set_data_command(LCDConfig_t * const LCDConfig, LCDDataCommand_e dataCommand);

View File

@ -0,0 +1,76 @@
#include "lv_port_disp.h"
// #define USE_PSRAM
#ifdef USE_PSRAM
#include "psram.h"
static lv_color_t *lvgl_draw_buff1 = NULL;
#if LVGL_PORT_USE_DOUBLE_BUFF
static lv_color_t *lvgl_draw_buff2 = NULL;
#endif
#else
static lv_color_t lvgl_draw_buff1[LVGL_PORT_BUFF_SIZE];
#if LVGL_PORT_USE_DOUBLE_BUFF
static lv_color_t lvgl_draw_buff2[LVGL_PORT_BUFF_SIZE];
#endif
#endif
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
/* 等待上次传输完成 */
#if !USE_SPI
bsp_lcd_draw_rect_wait();
#endif
/* 启动新的传输 */
bsp_lcd_draw_rect(area->x1,area->y1,area->x2 - area->x1 + 1,area->y2 - area->y1 + 1,(uint8_t *)color_p);
/* 通知lvgl传输已完成 */
lv_disp_flush_ready(disp_drv);
}
void lv_port_disp_init()
{
/* 向lvgl注册缓冲区 */
static lv_disp_draw_buf_t draw_buf_dsc; //需要全程生命周期,设置为静态变量
#ifdef USE_PSRAM
lvgl_draw_buff1 = dram_heap_malloc(LVGL_PORT_BUFF_SIZE*2);
if(lvgl_draw_buff1 == NULL){
printf("---> malloc lvgl_draw_buff1 err\n");
return;
}
#if LVGL_PORT_USE_DOUBLE_BUFF
lvgl_draw_buff2 = dram_heap_malloc(LVGL_PORT_BUFF_SIZE*2);
if(lvgl_draw_buff2 == NULL){
printf("---> malloc lvgl_draw_buff2 err\n");
return;
}
#endif
#endif
#if LVGL_PORT_USE_DOUBLE_BUFF
lv_disp_draw_buf_init(&draw_buf_dsc, lvgl_draw_buff1, lvgl_draw_buff2, LVGL_PORT_BUFF_SIZE);
#else
lv_disp_draw_buf_init(&draw_buf_dsc, lvgl_draw_buff1, NULL, LVGL_PORT_BUFF_SIZE);
#endif
/* 创建并初始化用于在lvgl中注册显示设备的结构 */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); //使用默认值初始化该结构
/* 设置屏幕分辨率 */
disp_drv.hor_res = BSP_LCD_X_PIXELS;
disp_drv.ver_res = BSP_LCD_Y_PIXELS;
disp_drv.rotated = LV_DISP_ROT_180;
/* 初始化LCD总线 */
bsp_lcd_init();
/* 设置显示矩形函数,用于将矩形缓冲区刷新到屏幕上 */
disp_drv.flush_cb = disp_flush;
/* 设置缓冲区 */
disp_drv.draw_buf = &draw_buf_dsc;
/* 注册显示设备 */
lv_disp_drv_register(&disp_drv);
}

View File

@ -0,0 +1,14 @@
#ifndef __LV_PORT_DISP_H__
#define __LV_PORT_DISP_H__
#include "lcd_dirty.h"
#include "lvgl.h"
/* lvgl缓冲区大小单位为像素数 */
#define LVGL_PORT_BUFF_SIZE (BSP_LCD_X_PIXELS*BSP_LCD_Y_PIXELS/10) // 1/10屏幕分辨率
/* 设置是否开启双缓冲 */
#define LVGL_PORT_USE_DOUBLE_BUFF 0
void lv_port_disp_init(void);
#endif

View File

@ -0,0 +1,417 @@
/**
* @file lv_port_indev_templ.c
*
*/
/*Copy this file as "lv_port_indev.c" and set this value to "1" to enable content*/
#if 1
/*********************
* INCLUDES
*********************/
#include "lv_port_indev.h"
#include "touchpad.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void touchpad_init(void);
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);
// static void mouse_init(void);
// static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
// static bool mouse_is_pressed(void);
// static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y);
// static void keypad_init(void);
// static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
// static uint32_t keypad_get_key(void);
// static void encoder_init(void);
// static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
// static void encoder_handler(void);
// static void button_init(void);
// static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
// static int8_t button_get_pressed_id(void);
// static bool button_is_pressed(uint8_t id);
/**********************
* STATIC VARIABLES
**********************/
lv_indev_t * indev_touchpad;
// lv_indev_t * indev_mouse;
// lv_indev_t * indev_keypad;
// lv_indev_t * indev_encoder;
// lv_indev_t * indev_button;
// static int32_t encoder_diff;
// static lv_indev_state_t encoder_state;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_port_indev_init(void)
{
/**
* Here you will find example implementation of input devices supported by LittelvGL:
* - Touchpad
* - Mouse (with cursor support)
* - Keypad (supports GUI usage only with key)
* - Encoder (supports GUI usage only with: left, right, push)
* - Button (external buttons to press points on the screen)
*
* The `..._read()` function are only examples.
* You should shape them according to your hardware
*/
static lv_indev_drv_t indev_drv;
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad if you have*/
touchpad_init();
/*Register a touchpad input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touchpad_read;
indev_touchpad = lv_indev_drv_register(&indev_drv);
// /*------------------
// * Mouse
// * -----------------*/
// /*Initialize your mouse if you have*/
// mouse_init();
// /*Register a mouse input device*/
// lv_indev_drv_init(&indev_drv);
// indev_drv.type = LV_INDEV_TYPE_POINTER;
// indev_drv.read_cb = mouse_read;
// indev_mouse = lv_indev_drv_register(&indev_drv);
// /*Set cursor. For simplicity set a HOME symbol now.*/
// lv_obj_t * mouse_cursor = lv_img_create(lv_scr_act());
// lv_img_set_src(mouse_cursor, LV_SYMBOL_HOME);
// lv_indev_set_cursor(indev_mouse, mouse_cursor);
// /*------------------
// * Keypad
// * -----------------*/
// /*Initialize your keypad or keyboard if you have*/
// keypad_init();
// /*Register a keypad input device*/
// lv_indev_drv_init(&indev_drv);
// indev_drv.type = LV_INDEV_TYPE_KEYPAD;
// indev_drv.read_cb = keypad_read;
// indev_keypad = lv_indev_drv_register(&indev_drv);
// /*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
// *add objects to the group with `lv_group_add_obj(group, obj)`
// *and assign this input device to group to navigate in it:
// *`lv_indev_set_group(indev_keypad, group);`*/
// /*------------------
// * Encoder
// * -----------------*/
// /*Initialize your encoder if you have*/
// encoder_init();
// /*Register a encoder input device*/
// lv_indev_drv_init(&indev_drv);
// indev_drv.type = LV_INDEV_TYPE_ENCODER;
// indev_drv.read_cb = encoder_read;
// indev_encoder = lv_indev_drv_register(&indev_drv);
// /*Later you should create group(s) with `lv_group_t * group = lv_group_create()`,
// *add objects to the group with `lv_group_add_obj(group, obj)`
// *and assign this input device to group to navigate in it:
// *`lv_indev_set_group(indev_encoder, group);`*/
// /*------------------
// * Button
// * -----------------*/
// /*Initialize your button if you have*/
// button_init();
// /*Register a button input device*/
// lv_indev_drv_init(&indev_drv);
// indev_drv.type = LV_INDEV_TYPE_BUTTON;
// indev_drv.read_cb = button_read;
// indev_button = lv_indev_drv_register(&indev_drv);
// /*Assign buttons to points on the screen*/
// static const lv_point_t btn_points[2] = {
// {10, 10}, /*Button 0 -> x:10; y:10*/
// {40, 100}, /*Button 1 -> x:40; y:100*/
// };
// lv_indev_set_button_points(indev_button, btn_points);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad*/
static void touchpad_init(void)
{
/*Your code comes here*/
bsp_touchpad_init();
}
/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static lv_coord_t last_x = 0;
static lv_coord_t last_y = 0;
/*Save the pressed coordinates and the state*/
if(touchpad_is_pressed()) {
touchpad_get_xy(&last_x, &last_y);
data->state = LV_INDEV_STATE_PR;
}
else {
data->state = LV_INDEV_STATE_REL;
}
/*Set the last pressed coordinates*/
data->point.x = last_x;
data->point.y = last_y;
}
/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
/*Your code comes here*/
bool val = bsp_touchpad_is_pressed();
// printf("---> %d\n",val);
return val;
}
/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
/*Your code comes here*/
// (*x) = ;
// (*y) = ;
bsp_touchpad_get_xy(x, y);
// printf("---> x:%d y:%d\n", (*x), (*y));
}
// /*------------------
// * Mouse
// * -----------------*/
// /*Initialize your mouse*/
// static void mouse_init(void)
// {
// /*Your code comes here*/
// }
// /*Will be called by the library to read the mouse*/
// static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
// {
// /*Get the current x and y coordinates*/
// mouse_get_xy(&data->point.x, &data->point.y);
// /*Get whether the mouse button is pressed or released*/
// if(mouse_is_pressed()) {
// data->state = LV_INDEV_STATE_PR;
// }
// else {
// data->state = LV_INDEV_STATE_REL;
// }
// }
// /*Return true is the mouse button is pressed*/
// static bool mouse_is_pressed(void)
// {
// /*Your code comes here*/
// return false;
// }
// /*Get the x and y coordinates if the mouse is pressed*/
// static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y)
// {
// /*Your code comes here*/
// (*x) = 0;
// (*y) = 0;
// }
// /*------------------
// * Keypad
// * -----------------*/
// /*Initialize your keypad*/
// static void keypad_init(void)
// {
// /*Your code comes here*/
// }
// /*Will be called by the library to read the mouse*/
// static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
// {
// static uint32_t last_key = 0;
// /*Get the current x and y coordinates*/
// mouse_get_xy(&data->point.x, &data->point.y);
// /*Get whether the a key is pressed and save the pressed key*/
// uint32_t act_key = keypad_get_key();
// if(act_key != 0) {
// data->state = LV_INDEV_STATE_PR;
// /*Translate the keys to LVGL control characters according to your key definitions*/
// switch(act_key) {
// case 1:
// act_key = LV_KEY_NEXT;
// break;
// case 2:
// act_key = LV_KEY_PREV;
// break;
// case 3:
// act_key = LV_KEY_LEFT;
// break;
// case 4:
// act_key = LV_KEY_RIGHT;
// break;
// case 5:
// act_key = LV_KEY_ENTER;
// break;
// }
// last_key = act_key;
// }
// else {
// data->state = LV_INDEV_STATE_REL;
// }
// data->key = last_key;
// }
// /*Get the currently being pressed key. 0 if no key is pressed*/
// static uint32_t keypad_get_key(void)
// {
// /*Your code comes here*/
// return 0;
// }
// /*------------------
// * Encoder
// * -----------------*/
// /*Initialize your keypad*/
// static void encoder_init(void)
// {
// /*Your code comes here*/
// }
// /*Will be called by the library to read the encoder*/
// static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
// {
// data->enc_diff = encoder_diff;
// data->state = encoder_state;
// }
// /*Call this function in an interrupt to process encoder events (turn, press)*/
// static void encoder_handler(void)
// {
// /*Your code comes here*/
// encoder_diff += 0;
// encoder_state = LV_INDEV_STATE_REL;
// }
// /*------------------
// * Button
// * -----------------*/
// /*Initialize your buttons*/
// static void button_init(void)
// {
// /*Your code comes here*/
// }
// /*Will be called by the library to read the button*/
// static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
// {
// static uint8_t last_btn = 0;
// /*Get the pressed button's ID*/
// int8_t btn_act = button_get_pressed_id();
// if(btn_act >= 0) {
// data->state = LV_INDEV_STATE_PR;
// last_btn = btn_act;
// }
// else {
// data->state = LV_INDEV_STATE_REL;
// }
// /*Save the last pressed button's ID*/
// data->btn_id = last_btn;
// }
// /*Get ID (0, 1, 2 ..) of the pressed button*/
// static int8_t button_get_pressed_id(void)
// {
// uint8_t i;
// /*Check to buttons see which is being pressed (assume there are 2 buttons)*/
// for(i = 0; i < 2; i++) {
// /*Return the pressed button's ID*/
// if(button_is_pressed(i)) {
// return i;
// }
// }
// /*No button pressed*/
// return -1;
// }
// /*Test if `id` button is pressed or not*/
// static bool button_is_pressed(uint8_t id)
// {
// /*Your code comes here*/
// return false;
// }
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

View File

@ -0,0 +1,45 @@
/**
* @file lv_port_indev_templ.h
*
*/
/*Copy this file as "lv_port_indev.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_INDEV_H
#define LV_PORT_INDEV_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lvgl.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_port_indev_init(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_INDEV_TEMPL_H*/
#endif /*Disable/Enable content*/

View File

@ -0,0 +1,22 @@
#include "lv_port_tick.h"
#include "wm_timer.h"
static void tick_timer_irq(u8 *arg)
{
lv_tick_inc(LV_TICK_PERIOD_MS);
}
void lv_create_tick(void)
{
u8 timer_id;
struct tls_timer_cfg timer_cfg;
timer_cfg.unit = TLS_TIMER_UNIT_MS;
timer_cfg.timeout = 1;
timer_cfg.is_repeat = 1;
timer_cfg.callback = (tls_timer_irq_callback)tick_timer_irq;
timer_cfg.arg = NULL;
timer_id = tls_timer_create(&timer_cfg);
tls_timer_start(timer_id);
// printf("timer start\n");
}

View File

@ -0,0 +1,9 @@
#ifndef __LV_PORT_TICK_H__
#define __LV_PORT_TICK_H__
#include "lvgl.h"
#define LV_TICK_PERIOD_MS 1
void lv_create_tick(void);
#endif

View File

@ -0,0 +1,137 @@
#include "lvgl.h"
#include "menu_screen.h"
//#include "config_screen.h"
#include "watch_face.h"
#define array_size(array) (sizeof(array)/sizeof(array[0]))
void watch_item_cb(lv_event_t *e)
{
LV_LOG_USER("Watch btn pressed");
extern WatchFace_t watchFace;
watch_face_create(&watchFace);
lv_scr_load_anim(watchFace.display, LV_SCR_LOAD_ANIM_FADE_ON, 400, 0, true);
}
void settings_item_cb(lv_event_t *e)
{
LV_LOG_USER("Settings btn pressed");
/*extern lv_obj_t *conf_screen;
//config_screen();
lv_scr_load_anim(conf_screen, LV_SCR_LOAD_ANIM_FADE_ON, 400, 0, false);*/
}
static void cleanup_event_cb(lv_event_t * e)
{
MenuScreen_t *menuScreen = e->user_data;
menu_screen_destroy(menuScreen);
LV_LOG_USER("cleanup");
}
void menu_screen_init(MenuScreen_t * const menuScreen)
{
if(!menuScreen)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
memset(menuScreen, 0, sizeof(MenuScreen_t));
}
static void screen_create_header(MenuScreen_t * const menuScreen, const char *title)
{
lv_obj_t *header = lv_obj_create(menuScreen->display);
lv_obj_set_style_bg_color(header, lv_color_make(129, 141,181), LV_PART_MAIN);
lv_obj_set_size(header, 240, 65);
lv_obj_set_style_radius(header, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(header, 0, LV_PART_MAIN);
lv_obj_t *header_title = lv_label_create(header);
lv_label_set_text_static(header_title, title);
lv_obj_set_style_text_color(header_title, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_text_font(header_title, &lv_font_montserrat_30, LV_PART_MAIN);
lv_obj_set_align(header_title, LV_ALIGN_CENTER);
}
static void menu_screen_add_item(lv_obj_t *scroll_item_container, uint8_t position, const lv_img_dsc_t *itemImg,const char *itemTitle, lv_event_cb_t itemClickEventCb)
{
//We add the image button with the icon of the item
lv_obj_t *item_btn = lv_imgbtn_create(scroll_item_container);
lv_obj_set_size(item_btn, itemImg->header.w, itemImg->header.h);
lv_obj_set_pos(item_btn, 42, 52 * position);
lv_imgbtn_set_src(item_btn, LV_IMGBTN_STATE_RELEASED, NULL, itemImg, NULL);
lv_obj_add_event_cb(item_btn, itemClickEventCb, LV_EVENT_CLICKED, NULL);
//We add the click-able label with the title of the item
lv_obj_t *item_label = lv_label_create(scroll_item_container);
lv_label_set_text_static(item_label, itemTitle);
lv_obj_set_style_text_font(item_label, &lv_font_montserrat_16, LV_PART_MAIN);
lv_obj_set_pos(item_label, 84+12, 15 + 52 * position);
lv_obj_set_style_text_color(item_label, lv_color_make(145, 145, 145), LV_PART_MAIN);
lv_obj_set_ext_click_area(item_label, 10);
lv_obj_add_flag(item_label, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(item_label, itemClickEventCb, LV_EVENT_CLICKED , NULL);
}
void menu_screen_create(MenuScreen_t * const menuScreen)
{
if(!menuScreen)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
//We declare all the needed assets by the menu screen:
LV_IMG_DECLARE(watch_menu_clock_icon)
LV_IMG_DECLARE(watch_menu_dialer_icon)
LV_IMG_DECLARE(watch_menu_mail_icon)
LV_IMG_DECLARE(watch_menu_contacts_icon)
LV_IMG_DECLARE(watch_menu_alarm_icon)
LV_IMG_DECLARE(watch_menu_settings_icon)
LV_IMG_DECLARE(watch_menu_messages_icon)
//We create our parent screen :
if(menuScreen->display)
{
LV_LOG_ERROR("display should be NULL here !");
lv_obj_del(menuScreen->display);
menuScreen->display = NULL;
}
menuScreen->display = lv_obj_create(NULL);
screen_create_header(menuScreen, "Menu");
lv_obj_t *scroll_item_container = lv_obj_create(menuScreen->display);
lv_obj_set_style_bg_color(scroll_item_container, lv_color_make(0xFF,0xFF,0xFF), LV_PART_MAIN);
lv_obj_set_size(scroll_item_container, lv_pct(100), 240-65);
lv_obj_set_pos(scroll_item_container, 0, 65);
lv_obj_set_style_pad_all(scroll_item_container, 0, LV_PART_MAIN);
lv_obj_set_style_pad_top(scroll_item_container, 10, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(scroll_item_container, 20, LV_PART_MAIN);
lv_obj_set_style_radius(scroll_item_container, 0, LV_PART_MAIN);
lv_obj_set_style_border_width(scroll_item_container, 0, LV_PART_MAIN);
lv_obj_set_style_pad_right(scroll_item_container, 15, LV_PART_SCROLLBAR);
menu_screen_add_item(scroll_item_container, 0, &watch_menu_clock_icon, "Watch", &(watch_item_cb));
menu_screen_add_item(scroll_item_container, 1, &watch_menu_alarm_icon, "Alarm", NULL);
menu_screen_add_item(scroll_item_container, 2, &watch_menu_messages_icon, "Text messages", NULL);
menu_screen_add_item(scroll_item_container, 3, &watch_menu_mail_icon, "Mails", NULL);
menu_screen_add_item(scroll_item_container, 4, &watch_menu_dialer_icon, "Phone", NULL);
menu_screen_add_item(scroll_item_container, 5,&watch_menu_contacts_icon, "Contacts", NULL);
menu_screen_add_item(scroll_item_container, 6,&watch_menu_settings_icon, "Contacts", &(settings_item_cb));
//We register the event callback to handle the cleanup
lv_obj_add_event_cb(menuScreen->display, &(cleanup_event_cb), LV_EVENT_DELETE, menuScreen);
}
void menu_screen_destroy(MenuScreen_t * const menuScreen)
{
if(!menuScreen)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
menuScreen->display = NULL;
}

View File

@ -0,0 +1,20 @@
#ifndef MENU_SCREEN_H
#define MENU_SCREEN_H
#include "lvgl.h"
typedef struct MenuScreen
{
lv_obj_t *display;
} MenuScreen_t;
/* Initializes the menu screen context object */
void menu_screen_init(MenuScreen_t * const menuScreen);
/* Builds the menu screen graphically */
void menu_screen_create(MenuScreen_t * const menuScreen);
/* Frees all resources used by the MenuScreen object */
void menu_screen_destroy(MenuScreen_t * const menuScreen);
#endif //MENU_SCREEN_H

View File

@ -0,0 +1,175 @@
#include <string.h>
#include "wm_sdio_host.h"
#include "wm_include.h"
#include "app_log.h"
#include "FreeRTOS.h"
static u8 sdio_spi_dma_channel = 0xFF;
static u32 sdio_spi_dma_buf_size = 0;
static u32 *sdio_spi_dma_buf_addr = NULL;
static u32 *sdio_spi_dma_temp_buf = NULL;
static bool sdio_spi_dma_ready = true;
static tls_os_sem_t *sdio_spi_dma_ready_flag = NULL;
void mmc_sdio_driver_periph_init(void)
{
tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_SDIO_MASTER);
// W800 register manual page 67
tls_bitband_write(HR_CLK_RST_CTL, 27, 0);
tls_bitband_write(HR_CLK_RST_CTL, 27, 1);
// Wait until reset is released
while (tls_bitband_read(HR_CLK_RST_CTL, 27) == 0);
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
// W800 register manual page 179
SDIO_HOST->MMC_CARDSEL = 0xC0 | (sysclk.cpuclk / 2 - 1); // enable module, enable mmcclk
APP_LOG_DEBUG("cpu clock : %u, mmc_cardsel reg val,addr : %02X, %p ", sysclk.cpuclk, SDIO_HOST->MMC_CARDSEL, &SDIO_HOST->MMC_CARDSEL);
#if (0) // Clock frequency is 1/2 of system clock
SDIO_HOST->MMC_CTL = 0x542 | 0 << 3; // auto transfer, mmc mode.
#else /* Clock frequency is 1/4 of system clock */
SDIO_HOST->MMC_CTL = 0x542 | (0b001 << 3); // 001
#endif
SDIO_HOST->MMC_INT_MASK = 0x100; //unmask sdio data interrupt.
SDIO_HOST->MMC_CRCCTL = 0x00;
SDIO_HOST->MMC_TIMEOUTCNT = 0;
SDIO_HOST->MMC_BYTECNTL = 0;
// Create a semaphore
tls_os_sem_create(&sdio_spi_dma_ready_flag, 1);
}
static void mmc_sdio_driver_dma_callback(void *arg)
{
(void)arg;
// printf("sdio_dma_callback\n");
// printf("--->buf_size:%d\n", sdio_spi_dma_buf_size);
/*if(sdio_spi_dma_buf_size > 0)
{
sdio_spi_dma_buf_addr += 65532/4;
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_OFF;
DMA_SRCADDR_REG(sdio_spi_dma_channel) = (unsigned int)sdio_spi_dma_buf_addr;
DMA_DESTADDR_REG(sdio_spi_dma_channel) = (unsigned int)SDIO_HOST->DATA_BUF;
u32 bufsize = sdio_spi_dma_buf_size;
if(bufsize > 65532){
bufsize = 65532;
}
sdio_spi_dma_buf_size -= bufsize;
DMA_CTRL_REG(sdio_spi_dma_channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | (bufsize << 8);
DMA_MODE_REG(sdio_spi_dma_channel) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_ON;
SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card
SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
SDIO_HOST->MMC_BYTECNTL = bufsize;
SDIO_HOST->MMC_IO = 0x01;
}
else*/
{
tls_dma_free(sdio_spi_dma_channel);
tls_os_sem_release(sdio_spi_dma_ready_flag);
//tls_mem_free(sdio_spi_dma_temp_buf);
//free(sdio_spi_dma_temp_buf);
// 等待信号量 直到上一次DMA数据发送完成
sdio_spi_dma_ready = true;
// printf("--->tls_os_sem_release [%s:%d]\r\n",__func__,__LINE__);
}
}
static u32 tmpbuff[2880];
void mmc_sdio_driver_write_dma_async(u32 *data, u32 dataLengthInBytes)
{
// Wait for the semaphore until the last DMA data transmission is completed
// printf("--->tls_os_sem_acquire [%s:%d]\r\n",__func__,__LINE__);
tls_os_sem_acquire(sdio_spi_dma_ready_flag, 0);
sdio_spi_dma_ready = false;
// printf("--->%s:%d\r\n",__func__,__LINE__);
// printf("--->w buf_size:%d\n", len);
if (dataLengthInBytes < 4)
{
printf("send err\n");
return;
}
if (dataLengthInBytes % 4)
{
// len += (4 - (len%4)); // DMA send length must be a multiple of 4
dataLengthInBytes -= dataLengthInBytes % 4;
// printf("Len not aligned\n");
}
/*sdio_spi_dma_temp_buf = malloc(dataLengthInBytes);//tls_mem_alloc(dataLengthInBytes);
if (sdio_spi_dma_temp_buf == NULL)
{
printf("---> malloc sdio_spi_dma_temp_buf err\n");
return;
}
memcpy(sdio_spi_dma_temp_buf, data, dataLengthInBytes);
sdio_spi_dma_buf_addr = sdio_spi_dma_temp_buf;*/
memcpy(tmpbuff, data, dataLengthInBytes);
sdio_spi_dma_buf_size = dataLengthInBytes;
while (1)
{
if ((SDIO_HOST->MMC_IO & 0x01) == 0x00)
break;
}
SDIO_HOST->BUF_CTL = 0x4000; // disable dma,
sdio_spi_dma_channel = tls_dma_request(0, 0);
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_OFF;
DMA_SRCADDR_REG(sdio_spi_dma_channel) = (unsigned int)tmpbuff;//sdio_spi_dma_buf_addr;
DMA_DESTADDR_REG(sdio_spi_dma_channel) = (unsigned int)SDIO_HOST->DATA_BUF;
/*u32 bufsize = sdio_spi_dma_buf_size;
if (bufsize > 65532)
{
bufsize = 65532;
}
sdio_spi_dma_buf_size -= bufsize;*/
DMA_CTRL_REG(sdio_spi_dma_channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | (sdio_spi_dma_buf_size << 8);
DMA_MODE_REG(sdio_spi_dma_channel) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
tls_dma_irq_register(sdio_spi_dma_channel, &(mmc_sdio_driver_dma_callback), NULL, TLS_DMA_IRQ_TRANSFER_DONE);
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_ON;
SDIO_HOST->BUF_CTL = 0xC20; // enable dma, write sd card
SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
SDIO_HOST->MMC_BYTECNTL = sdio_spi_dma_buf_size;//bufsize;
SDIO_HOST->MMC_IO = 0x01;
sdio_spi_dma_buf_size = 0;
}
void mmc_sdio_driver_write_one(u8 byte)
{
SDIO_HOST->BUF_CTL = 0x4820;
SDIO_HOST->DATA_BUF[0] = byte;
SDIO_HOST->MMC_BYTECNTL = 1;
SDIO_HOST->MMC_IO = 0x01;
while (1) {
if ((SDIO_HOST->MMC_IO & 0x01) == 0x00)
break;
}
}
void mmc_sdio_driver_wait_write_dma_ready(void)
{
while(!sdio_spi_dma_ready)
{
// Yield some time to FreeRTOS to schedule an other task meanwhile
tls_os_time_delay(pdMS_TO_TICKS(1));
}
}

View File

@ -0,0 +1,18 @@
#ifndef MMC_SDIO_H
#define MMC_SDIO_H
#include "wm_include.h"
/* Inits the MMC peripheral in SDIO mode */
void mmc_sdio_driver_periph_init(void);
/* Sends the data to the slave using DMA in an asynchronous manner */
void mmc_sdio_driver_write_dma_async(u32 *data, u32 dataLengthInBytes);
/* Sends one byte of data to the slave */
void mmc_sdio_driver_write_one(u8 byte);
/* Blocks the current task until the write through DMA is available again */
void mmc_sdio_driver_wait_write_dma_ready(void);
#endif //MMC_SDIO_H

View File

@ -0,0 +1,236 @@
#include "sdio_spi_driver.h"
#include "wm_sdio_host.h"
#include "wm_cpu.h"
#include "wm_dma.h"
#include "wm_pmu.h"
#include <string.h>
#include "sdio_spi_driver.h"
// #define USE_PSRAM
#ifdef USE_PSRAM
#include "psram.h"
#endif
static u8 sdio_spi_dma_channel = 0xFF;
static u32 sdio_spi_dma_buf_size = 0;
static u32 *sdio_spi_dma_buf_addr = NULL;
static u32 *sdio_spi_dma_temp_buf = NULL;
static tls_os_sem_t *sdio_spi_dma_ready_flag = NULL;
static bool sdio_spi_dma_ready = true;
void init_sdio_spi_mode()
{
// tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION1);/*CK*/
// tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION1);/*CMD*/
tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_SDIO_MASTER);
tls_bitband_write(HR_CLK_RST_CTL, 27, 0);
tls_bitband_write(HR_CLK_RST_CTL, 27, 1);
while (tls_bitband_read(HR_CLK_RST_CTL, 27) == 0);
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
SDIO_HOST->MMC_CARDSEL = 0xC0 | (sysclk.cpuclk / 2 - 1); // enable module, enable mmcclk
printf("SDIO_HOST : %02X\ncpu clk : %d\n", SDIO_HOST->MMC_CARDSEL, sysclk.cpuclk);
#if (0) // 时钟频率为系统时钟 1/2
SDIO_HOST->MMC_CTL = 0x542 | 0 << 3;// auto transfer, mmc mode.
#else // 时钟频率为系统时钟 1/4
SDIO_HOST->MMC_CTL = 0x542 | (0b001 << 3); // 001
#endif
SDIO_HOST->MMC_INT_MASK = 0x100; // unmask sdio data interrupt.
SDIO_HOST->MMC_CRCCTL = 0x00;
SDIO_HOST->MMC_TIMEOUTCNT = 0;
SDIO_HOST->MMC_BYTECNTL = 0;
// 创建信号量
tls_os_sem_create(&sdio_spi_dma_ready_flag, 1);
}
static int sdio_spi_dma_cfg(u32*mbuf,u32 bufsize,u8 dir)
{
int ch;
u32 addr_inc = 0;
ch = tls_dma_request(0, 0);
DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_OFF;
if(dir)
{
DMA_SRCADDR_REG(ch) = (unsigned int)mbuf;
DMA_DESTADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF;
addr_inc = DMA_CTRL_SRC_ADDR_INC;
}
else
{
DMA_SRCADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF;
DMA_DESTADDR_REG(ch) = (unsigned int)mbuf;
addr_inc =DMA_CTRL_DEST_ADDR_INC;
}
DMA_CTRL_REG(ch) = addr_inc | DMA_CTRL_DATA_SIZE_WORD | (bufsize << 8);
DMA_MODE_REG(ch) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
// tls_dma_irq_register(ch, (void (*))sdio_dma_callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_ON;
return ch;
}
void sdio_spi_put(u8 d)
{
SDIO_HOST->BUF_CTL = 0x4820;
SDIO_HOST->DATA_BUF[0] = d;
SDIO_HOST->MMC_BYTECNTL = 1;
SDIO_HOST->MMC_IO = 0x01;
while (1) {
if ((SDIO_HOST->MMC_IO & 0x01) == 0x00)
break;
}
}
void write_sdio_spi_dma(u32* data, u32 len)
{
while(1){
if ((SDIO_HOST->MMC_IO & 0x01) == 0x00)
break;
}
u32 offset=0;
while(len>0){
int datalen=len;
if(len>0xfffc)
datalen=0xfffc;
len-=datalen;
SDIO_HOST->BUF_CTL = 0x4000; //disable dma,
sdio_spi_dma_channel = sdio_spi_dma_cfg((u32 *) data+offset, datalen, 1);
SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card
SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
SDIO_HOST->MMC_BYTECNTL = datalen;
SDIO_HOST->MMC_IO = 0x01;
offset+=datalen/4;
while(1){
if ((SDIO_HOST->BUF_CTL & 0x400) == 0x00)
break;
}
tls_dma_free(sdio_spi_dma_channel);
}
}
static void sdio_dma_callback(void)
{
// printf("sdio_dma_callback\n");
// printf("--->buf_size:%d\n", sdio_spi_dma_buf_size);
if(sdio_spi_dma_buf_size > 0)
{
sdio_spi_dma_buf_addr += 65532/4;
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_OFF;
DMA_SRCADDR_REG(sdio_spi_dma_channel) = (unsigned int)sdio_spi_dma_buf_addr;
DMA_DESTADDR_REG(sdio_spi_dma_channel) = (unsigned int)SDIO_HOST->DATA_BUF;
u32 bufsize = sdio_spi_dma_buf_size;
if(bufsize > 65532){
bufsize = 65532;
}
sdio_spi_dma_buf_size -= bufsize;
DMA_CTRL_REG(sdio_spi_dma_channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | (bufsize << 8);
DMA_MODE_REG(sdio_spi_dma_channel) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_ON;
SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card
SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
SDIO_HOST->MMC_BYTECNTL = bufsize;
SDIO_HOST->MMC_IO = 0x01;
}
else
{
tls_dma_free(sdio_spi_dma_channel);
tls_os_sem_release(sdio_spi_dma_ready_flag);
#ifdef USE_PSRAM
dram_heap_free(sdio_spi_dma_temp_buf);
#else
tls_mem_free(sdio_spi_dma_temp_buf);
#endif
// 等待信号量 直到上一次DMA数据发送完成
sdio_spi_dma_ready = true;
// printf("--->tls_os_sem_release [%s:%d]\r\n",__func__,__LINE__);
}
}
void wait_sdio_spi_dma_ready()
{
while(!sdio_spi_dma_ready){
tls_os_time_delay(1);
}
}
void write_sdio_spi_dma_async(u32* data, u32 len)
{
// 等待信号量 直到上一次DMA数据发送完成
// printf("--->tls_os_sem_acquire [%s:%d]\r\n",__func__,__LINE__);
tls_os_sem_acquire(sdio_spi_dma_ready_flag, 0);
sdio_spi_dma_ready = false;
// printf("--->%s:%d\r\n",__func__,__LINE__);
// printf("--->w buf_size:%d\n", len);
if(len<4){
printf("send err\n");
return;
}
if(len%4)
{
//len += (4 - (len%4)); // dma发送长度必须为4的倍数
len -= len%4;
//printf("Len not aligned\n");
}
#ifdef USE_PSRAM
sdio_spi_dma_temp_buf = dram_heap_malloc(len);
#else
sdio_spi_dma_temp_buf = tls_mem_alloc(len);
#endif
if(sdio_spi_dma_temp_buf == NULL){
printf("---> malloc sdio_spi_dma_temp_buf err\n");
return;
}
memcpy(sdio_spi_dma_temp_buf, data, len);
sdio_spi_dma_buf_addr = sdio_spi_dma_temp_buf;
sdio_spi_dma_buf_size = len;
while(1){
if ((SDIO_HOST->MMC_IO & 0x01) == 0x00)
break;
}
SDIO_HOST->BUF_CTL = 0x4000; //disable dma,
sdio_spi_dma_channel = tls_dma_request(0, 0);
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_OFF;
DMA_SRCADDR_REG(sdio_spi_dma_channel) = (unsigned int)sdio_spi_dma_buf_addr;
DMA_DESTADDR_REG(sdio_spi_dma_channel) = (unsigned int)SDIO_HOST->DATA_BUF;
u32 bufsize = sdio_spi_dma_buf_size;
if(bufsize > 65532){
bufsize = 65532;
}
sdio_spi_dma_buf_size -= bufsize;
DMA_CTRL_REG(sdio_spi_dma_channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | (bufsize << 8);
DMA_MODE_REG(sdio_spi_dma_channel) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
tls_dma_irq_register(sdio_spi_dma_channel, (void (*))sdio_dma_callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
DMA_CHNLCTRL_REG(sdio_spi_dma_channel) = DMA_CHNL_CTRL_CHNL_ON;
SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card
SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
SDIO_HOST->MMC_BYTECNTL = bufsize;
SDIO_HOST->MMC_IO = 0x01;
}

View File

@ -0,0 +1,19 @@
#ifndef __SDIO_SPI_DRIVER_H__
#define __SDIO_SPI_DRIVER_H__
#include "wm_include.h"
void init_sdio_spi_mode();
void sdio_spi_put(u8 d);
void write_sdio_spi_dma(u32* data,u32 len);
void write_sdio_spi_dma_async(u32* data,u32 len);
void wait_sdio_spi_dma_ready();
#endif

View File

@ -0,0 +1,220 @@
#include "touchpad.h"
extern void delay_us();
static OS_STK TouchPadTaskStk[TOUCH_TASK_STACK_SIZE];
coord_TypeDef g_Coord;
//===========================================================================
// 静态函数声明
static void tp_gpio_init(void);
bool TP_Update_Coord(void);
static void tp_send_cmd(uint8_t dat);
static u16 _tp_read_coord(uint8_t reg);
void touchpad_task_create(void);
static void tp_gpio_init(void)
{
tls_gpio_cfg(TCLK, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_cfg(TCS, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_cfg(TDIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_cfg(TDOU, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_cfg(TIRQ, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
// tls_gpio_isr_register(TIRQ, tp_gpio_isr_handler, NULL);
// tls_gpio_irq_enable(TIRQ, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE);
}
static void tp_send_cmd(uint8_t dat){
for(uint8_t i=0;i<8;i++){
if(dat & 0x80){
tls_gpio_write(TDIN, 1);
}else{
tls_gpio_write(TDIN, 0);
}
dat <<= 1;
tls_gpio_write(TCLK, 0);
tls_gpio_write(TCLK, 1);
}
}
//============================================================================
// 获取坐标、坐标处理
//============================================================================
static uint16_t _tp_read_coord(uint8_t reg){
uint16_t tmp = 0;
tls_gpio_write(TCLK, 0);
tls_gpio_write(TDIN, 0);
tls_gpio_write(TCS, 0);
tp_send_cmd(reg);
delay_us(6); //busy
tls_gpio_write(TCLK, 0);
delay_us(1);
tls_gpio_write(TCLK, 1);// 给1个时钟清除BUSY
tls_gpio_write(TCLK, 0);
for(uint8_t i=0;i<16;i++){
tmp <<= 1;
tls_gpio_write(TCLK, 0); // 下降沿有效
tls_gpio_write(TCLK, 1);
if(tls_gpio_read(TDOU)){
tmp++;
}
}
tmp >>= 4;
tls_gpio_write(TCS, 1);
return tmp;
}
/*
*
* / 0
*/
#define LOST_CNT 1 //丢弃值
#define BUFF_SIZE 10
static uint16_t tp_read_value(uint8_t xy_reg){
uint16_t tmp = 0;
uint16_t buff[BUFF_SIZE] = {0};
uint32_t sum = 0;
uint8_t errCnt = 0;
for(uint8_t i=0;i<BUFF_SIZE;){
tmp = _tp_read_coord(xy_reg);
if((0xFFF != tmp) && (0 != tmp)){
// 过滤掉错误的值
buff[i] = tmp;
i++;
}else{
// 防止阻塞
errCnt++;
}
if(errCnt > 100){
return 0;
}
}
//升序排序
for(uint8_t i=0;i<BUFF_SIZE-1;i++){
for(uint8_t j=i+1;j<BUFF_SIZE;j++){
if(buff[i] > buff[j]){
tmp = buff[i];
buff[i] = buff[j];
buff[j] = tmp;
}
}
}
//掐头去尾 —— 去掉一个最高值和最低值
for(uint8_t i=LOST_CNT;i<BUFF_SIZE-LOST_CNT;i++){
sum += buff[i];
}
tmp = sum/(BUFF_SIZE-2*LOST_CNT);
return tmp;
}
/*
* x/y
* true: / false
*/
static bool tp_read_coord(uint16_t *x, uint16_t *y)
{
uint16_t xTmp = tp_read_value(CMD_RDX);
uint16_t yTmp = tp_read_value(CMD_RDY);
*x = xTmp;
*y = yTmp;
if(0 == xTmp*yTmp){
return false;
}
return true;
}
//============================================================================
// TouchPad 外部接口
//============================================================================
bool bsp_touchpad_is_pressed()
{
return g_Coord.isPressed;
}
void bsp_touchpad_get_xy(int16_t *x, int16_t *y)
{
(*x) = g_Coord.xCoord;
(*y) = g_Coord.yCoord;
}
void bsp_touchpad_init(void)
{
// memset(&g_Coord, 0, sizeof(coord_TypeDef));
if(true){
//未校准,使用默认校准系数
g_Coord.xOffset = 355; //x轴偏移200
g_Coord.yOffset = 221; //y轴偏移280
g_Coord.xRate = 11.17; //x轴比例系数7.71
g_Coord.yRate = 15.03; //y轴比例系数10.94
}else
{
//已校准从flash中读取校准系数
}
tp_gpio_init();
touchpad_task_create();
}
uint32_t TP_test(void)
{
while (1)
{
TP_Update_Coord();
//printf("---> x:%d y:%d\n", g_Coord.xCoord, g_Coord.yCoord);
tls_os_time_delay(HZ/10);
}
}
bool TP_Update_Coord(void)
{
bool sta = true;
uint16_t x = 0;
uint16_t y = 0;
sta = tp_read_coord(&x, &y);
if(true == sta){
g_Coord.xCoord = (int16_t)((x - g_Coord.xOffset)/g_Coord.xRate) - 80; // -80 : adjust for 240*240 instead of 240*320 !
g_Coord.yCoord = (int16_t)((y - g_Coord.yOffset)/g_Coord.yRate);
g_Coord.xIndev = x;
g_Coord.yIndex = y;
}
return sta;
}
static void touchpad_task_start(void *data)
{
while(1)
{
if(tls_gpio_read(TIRQ) == 0)
{
g_Coord.isPressed = 1;
TP_Update_Coord();
}
else
{
g_Coord.isPressed = 0;
}
//printf("---> x:%d y:%d <-> x:%d y:%d\n", g_Coord.xCoord, g_Coord.yCoord, g_Coord.xIndev, g_Coord.yIndex);
tls_os_time_delay(HZ/100);
}
}
void touchpad_task_create(void)
{
tls_os_task_create(NULL,
"touch",
touchpad_task_start,
NULL,
(void *)TouchPadTaskStk, /* task's stack start address */
TOUCH_TASK_STACK_SIZE, /* task's stack size, unit:byte */
TOUCH_TASK_PRORITY,
0);
}

View File

@ -0,0 +1,63 @@
#ifndef __TOUCHPAD_H__
#define __TOUCHPAD_H__
#include "wm_include.h"
#define TOUCH_TASK_STACK_SIZE 1024
#define TOUCH_TASK_PRORITY 6
#if 0
#define TIRQ WM_IO_PB_01
#define TCLK WM_IO_PB_02
#define TCS WM_IO_PB_04
#define TDIN WM_IO_PB_05
#define TDOU WM_IO_PB_03
#else
/*#define TCLK WM_IO_PA_07
#define TCS WM_IO_PA_06
#define TDIN WM_IO_PA_05
#define TDOU WM_IO_PA_04
#define TIRQ WM_IO_PA_03*/
#define TCLK WM_IO_PB_01
#define TCS WM_IO_PB_02
#define TDIN WM_IO_PB_03
#define TDOU WM_IO_PB_04
#define TIRQ WM_IO_PB_05
#endif
#define ESP_INTR_FLAG_DEFAULT 0
#define CMD_RDX 0X90
#define CMD_RDY 0XD0
typedef struct _coord_t_{
float xRate; //x轴比例系数
float yRate;
int16_t xOffset;//触摸屏与显示屏x轴偏移
int16_t yOffset;
int16_t xCoord; //x轴坐标
int16_t yCoord; //y轴坐标
int16_t xIndev; //触摸屏x轴数据
int16_t yIndex; //触摸屏y轴数据
bool isPressed;//检测触摸是否被按下
}coord_TypeDef;
enum{
CMD_GPIO = 0,
CMD_TMEP,
};
typedef struct _cmt_t_{
uint32_t cmdNum;
uint32_t cmdVal;
uint8_t cmdType;
}cmdTypedef;
bool bsp_touchpad_is_pressed();
void bsp_touchpad_init(void);
void bsp_touchpad_get_xy(int16_t *x, int16_t *y);
#endif

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,244 @@
#include "lvgl.h"
#include "watch_face.h"
#include "menu_screen.h"
#include <stdio.h>
static void gesture_event_cb(lv_event_t * e)
{
WatchFace_t *watchFace = e->user_data;
lv_dir_t gesture;
switch(gesture = lv_indev_get_gesture_dir(lv_indev_get_act()))
{
case LV_DIR_LEFT:
LV_LOG_USER("GESTURE : LEFT");
break;
case LV_DIR_RIGHT:
LV_LOG_USER("GESTURE : RIGHT");
// We delete the timer
lv_timer_del(watchFace->handAnimationTimer);
// We create the menu screen and switch to it
extern MenuScreen_t menuScreen;
menu_screen_create(&menuScreen);
lv_scr_load_anim(menuScreen.display, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 400, 0, true);
break;
case LV_DIR_TOP:
LV_LOG_USER("GESTURE : TOP");
break;
case LV_DIR_BOTTOM:
LV_LOG_USER("GESTURE : BOTTOM");
break;
default:
LV_LOG_USER("GESTURE : %u", gesture);
}
}
static void cleanup_event_cb(lv_event_t * e)
{
WatchFace_t *watchFace = e->user_data;
watch_face_destroy(watchFace);
LV_LOG_USER("cleanup");
}
static void update_watch_hands_angles(WatchFace_t * const watchFace, uint8_t increment)
{
if(!watchFace)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
//We retrieve the current time:
if(watchFace->dateTimeCb)
{
//We compute each hand angle
if(!increment || watchFace->secondHand.handAngle >= 3660)
{
watchFace->dateTimeCb(&watchFace->dateTime);
watchFace->secondHand.handAngle = 60 * watchFace->dateTime.tm_sec;
//Don't forget to update the day date window
sprintf(watchFace->dateWindow.dateWindowText, "%s%d", watchFace->dateTime.tm_mday < 10 ? " " : "", watchFace->dateTime.tm_mday);
lv_obj_invalidate(watchFace->dateWindow.dateWindowWidget);
}
else
{
watchFace->secondHand.handAngle += increment;
}
watchFace->minuteHand.handAngle = 60 * watchFace->dateTime.tm_min + watchFace->secondHand.handAngle / 60;
watchFace->hourHand.handAngle = 300 * watchFace->dateTime.tm_hour + watchFace->minuteHand.handAngle / 12;
watchFace->mediumHand24h.handAngle = watchFace->hourHand.handAngle / 2;
//LV_LOG_USER("angle : %f", watchFace->secondHand.handAngle);
//We update the angle
lv_img_set_angle(watchFace->secondHand.handImg, (uint16_t) watchFace->secondHand.handAngle % 3600);
lv_img_set_angle(watchFace->minuteHand.handImg, (uint16_t) watchFace->minuteHand.handAngle % 3600);
lv_img_set_angle(watchFace->hourHand.handImg, (uint16_t) watchFace->hourHand.handAngle % 3600);
lv_img_set_angle(watchFace->mediumHand24h.handImg, (uint16_t) watchFace->mediumHand24h.handAngle % 3600);
}
else
{
LV_LOG_USER("DateTimeCb is NULL, be sure to register a callback !");
}
}
static void hand_timer_anim_cb(lv_timer_t *timer)
{
WatchFace_t *watchFace = timer->user_data;
update_watch_hands_angles(watchFace, 12);
}
void watch_face_init(WatchFace_t * const watchFace)
{
if(!watchFace)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
memset(watchFace, 0, sizeof(WatchFace_t));
}
void watch_face_register_cb(WatchFace_t * const watchFace, DateTimeCb_t dateTimeCb)
{
if(!watchFace)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
watchFace->dateTimeCb = dateTimeCb;
}
void watch_face_create(WatchFace_t * const watchFace)
{
if(!watchFace)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
//We declare the needed assets for the watch face:
LV_IMG_DECLARE(watch_casio_face_asset)
LV_IMG_DECLARE(watch_casio_hour_hand_asset)
LV_IMG_DECLARE(watch_casio_minute_hand_asset)
LV_IMG_DECLARE(watch_casio_second_hand_asset)
LV_IMG_DECLARE(watch_casio_medium_hand_asset)
LV_IMG_DECLARE(watch_casio_small_hand_asset)
//We create our parent screen :
if(watchFace->display)
{
LV_LOG_ERROR("display should be NULL here !");
lv_obj_del(watchFace->display);
watchFace->display = NULL;
}
watchFace->display = lv_obj_create(NULL);
//We load our assets :
lv_obj_t *watchFaceImg = lv_img_create(watchFace->display);
lv_img_set_src(watchFaceImg, &watch_casio_face_asset);
lv_obj_t *smallHandImg = lv_img_create(watchFace->display);
lv_img_set_src(smallHandImg, &watch_casio_small_hand_asset);
lv_obj_set_pos(smallHandImg, 69, 98);
lv_img_set_pivot(smallHandImg, 4, 20);
if(watchFace->mediumHand24h.handImg)
{
LV_LOG_ERROR("mediumHand24hImg should be NULL here !");
lv_obj_del(watchFace->mediumHand24h.handImg);
watchFace->mediumHand24h.handImg = NULL;
}
watchFace->mediumHand24h.handImg = lv_img_create(watchFace->display);
lv_img_set_src(watchFace->mediumHand24h.handImg, &watch_casio_medium_hand_asset);
lv_obj_set_pos(watchFace->mediumHand24h.handImg, 115, 48);
lv_img_set_pivot(watchFace->mediumHand24h.handImg, 4, 25);
lv_obj_t *mediumHandChronoImg = lv_img_create(watchFace->display);
lv_img_set_src(mediumHandChronoImg, &watch_casio_medium_hand_asset);
lv_obj_set_pos(mediumHandChronoImg, 115, 140);
lv_img_set_pivot(mediumHandChronoImg, 4, 25);
//Date window is created here
if(watchFace->dateWindow.dateWindowWidget)
{
LV_LOG_ERROR("dateWindow should be NULL here !");
lv_obj_del(watchFace->dateWindow.dateWindowWidget);
watchFace->dateWindow.dateWindowWidget = NULL;
}
watchFace->dateWindow.dateWindowWidget = lv_label_create(watchFace->display);
lv_label_set_text_static(watchFace->dateWindow.dateWindowWidget, watchFace->dateWindow.dateWindowText);
lv_obj_set_pos(watchFace->dateWindow.dateWindowWidget, 182,112);
if(watchFace->hourHand.handImg)
{
LV_LOG_ERROR("hourHandImg should be NULL here !");
lv_obj_del(watchFace->hourHand.handImg);
watchFace->hourHand.handImg = NULL;
}
watchFace->hourHand.handImg = lv_img_create(watchFace->display);
lv_img_set_src(watchFace->hourHand.handImg, &watch_casio_hour_hand_asset);
lv_obj_set_pos(watchFace->hourHand.handImg, 112, 60);
lv_img_set_pivot(watchFace->hourHand.handImg, 8, 60);
if(watchFace->minuteHand.handImg)
{
LV_LOG_ERROR("minuteHandImg should be NULL here !");
lv_obj_del(watchFace->minuteHand.handImg);
watchFace->minuteHand.handImg = NULL;
}
watchFace->minuteHand.handImg = lv_img_create(watchFace->display);
lv_img_set_src(watchFace->minuteHand.handImg, &watch_casio_minute_hand_asset);
lv_obj_set_pos(watchFace->minuteHand.handImg, 112, 28);
lv_img_set_pivot(watchFace->minuteHand.handImg, 7, 92);
if(watchFace->secondHand.handImg)
{
LV_LOG_ERROR("secondHandImg should be NULL here !");
lv_obj_del(watchFace->secondHand.handImg);
watchFace->secondHand.handImg = NULL;
}
watchFace->secondHand.handImg = lv_img_create(watchFace->display);
lv_img_set_src(watchFace->secondHand.handImg, &watch_casio_second_hand_asset);
lv_obj_set_pos(watchFace->secondHand.handImg, 115, 28);
lv_img_set_pivot(watchFace->secondHand.handImg, 5, 92);
//We set the appropriate angles to each of the hands
update_watch_hands_angles(watchFace, 0);
//We register the event callback to handle gestures
lv_obj_add_event_cb(watchFace->display, &(gesture_event_cb), LV_EVENT_GESTURE, watchFace);
//We register the event callback to handle the cleanup
lv_obj_add_event_cb(watchFace->display, &(cleanup_event_cb), LV_EVENT_DELETE, watchFace);
//We create the timer to run the watch animations
if(watchFace->handAnimationTimer)
{
LV_LOG_ERROR("handAnimationTimer should be NULL here !");
lv_timer_del(watchFace->handAnimationTimer);
watchFace->handAnimationTimer = NULL;
}
watchFace->handAnimationTimer = lv_timer_create(&(hand_timer_anim_cb), 200, watchFace);
}
void watch_face_destroy(WatchFace_t * const watchFace)
{
if(!watchFace)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
watchFace->display = NULL;
watchFace->handAnimationTimer = NULL;
watchFace->dateWindow.dateWindowWidget = NULL;
watchFace->hourHand.handImg = NULL;
watchFace->minuteHand.handImg = NULL;
watchFace->secondHand.handImg = NULL;
watchFace->mediumHand24h.handImg = NULL;
}

View File

@ -0,0 +1,48 @@
#ifndef WATCH_FACE_H
#define WATCH_FACE_H
#include "lvgl.h"
#include <time.h>
typedef void (*DateTimeCb_t)(struct tm * const dateTime);
typedef struct DateWindow
{
lv_obj_t *dateWindowWidget;
char dateWindowText[3];
} DateWindow_t;
typedef struct WatchHand
{
lv_obj_t *handImg;
float handAngle;
}WatchHand_t;
/* Watch face context object */
typedef struct WatchFace
{
DateTimeCb_t dateTimeCb; //Call back function used to retrieve the date and time needed by the watch face
WatchHand_t hourHand;
WatchHand_t minuteHand;
WatchHand_t secondHand;
WatchHand_t mediumHand24h;
lv_timer_t *handAnimationTimer;
lv_obj_t *display;
DateWindow_t dateWindow;
struct tm dateTime;
} WatchFace_t;
/* Initializes the watch face context object */
void watch_face_init(WatchFace_t * const watchFace);
/* Registers a call back function to retrieve the time and date */
void watch_face_register_cb(WatchFace_t * const watchFace, DateTimeCb_t DateTimeCb);
/* Builds the watch face graphically */
void watch_face_create(WatchFace_t * const watchFace);
/* Frees all resources used by the WatchFace object */
void watch_face_destroy(WatchFace_t * const watchFace);
#endif // WATCH_FACE_H

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "wm_type_def.h"
#include "wm_cpu.h"
#include "wm_uart.h"
#include "wm_gpio.h"
#include "wm_hostspi.h"
@ -89,5 +90,6 @@
#include "wm_rtc.h"
#include "wm_timer.h"
#include "wm_ble.h"
#include "wm_dma.h"
#endif

View File

@ -49,7 +49,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 (48U * 1024U) /*[bytes]*/
#define LV_MEM_SIZE (20 * 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*/
@ -78,10 +78,10 @@
*====================*/
/*Default display refresh period. LVG will redraw changed areas with this period time*/
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
#define LV_DISP_DEF_REFR_PERIOD 16 /*[ms]*/
/*Input device read period in milliseconds*/
#define LV_INDEV_DEF_READ_PERIOD 30 /*[ms]*/
#define LV_INDEV_DEF_READ_PERIOD 16 /*[ms]*/
/*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()`)*/
@ -219,7 +219,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:
@ -233,7 +233,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
@ -354,14 +354,14 @@
#define LV_FONT_MONTSERRAT_10 0
#define LV_FONT_MONTSERRAT_12 0
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 0
#define LV_FONT_MONTSERRAT_16 1
#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_26 0
#define LV_FONT_MONTSERRAT_28 0
#define LV_FONT_MONTSERRAT_30 0
#define LV_FONT_MONTSERRAT_30 1
#define LV_FONT_MONTSERRAT_32 0
#define LV_FONT_MONTSERRAT_34 0
#define LV_FONT_MONTSERRAT_36 0
@ -724,7 +724,7 @@
====================*/
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
#define LV_USE_DEMO_WIDGETS 1
#define LV_USE_DEMO_WIDGETS 0
#if LV_USE_DEMO_WIDGETS
#define LV_DEMO_WIDGETS_SLIDESHOW 0
#endif

View File

@ -103,7 +103,7 @@ void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc
if(letter >= 0x20 &&
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" PRIX32, letter);
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%u", letter);
#if LV_USE_FONT_PLACEHOLDER
/* draw placeholder */

View File

@ -70,14 +70,14 @@
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1 //ʹ<>ÿ<EFBFBD><C3BF>й<EFBFBD><D0B9><EFBFBD>
#define configUSE_TICK_HOOK 1
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 40000000 ) /* =12.0MHz xtal multiplied by 5 using the PLL. *///???????????????
#define configTICK_RATE_HZ ( ( portTickType ) 500u )
#define configMAX_PRIORITIES (63)
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 20 * 1024 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 12 * 1024 )
#define configMAX_TASK_NAME_LEN ( 10 ) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0

View File

@ -44,6 +44,8 @@ INCLUDES += -I $(TOP_DIR)/src/os/rtos/include
INCLUDES += -I $(TOP_DIR)/src/app/factorycmd
INCLUDES += -I $(TOP_DIR)/src/app/bleapp
INCLUDES += -I $(TOP_DIR)/app/app_include
INCLUDES += -I $(TOP_DIR)/app/drivers/lcd
INCLUDES += -I $(TOP_DIR)/app/drivers/mmc_sdio
INCLUDES += -I $(TOP_DIR)/app/gfx
INCLUDES += -I $(TOP_DIR)/app

View File

@ -105,7 +105,7 @@ void lv_draw_sw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc
if(letter >= 0x20 &&
letter != 0xf8ff && /*LV_SYMBOL_DUMMY*/
letter != 0x200c) { /*ZERO WIDTH NON-JOINER*/
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" PRIX32, letter);
LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%u", letter);
#if LV_USE_FONT_PLACEHOLDER
/* draw placeholder */