project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp: Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem. sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately. sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades. sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for fastboot. Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
947 lines
27 KiB
C
947 lines
27 KiB
C
#include <rtthread.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <dfs_posix.h>
|
|
|
|
#include "drv_heap.h"
|
|
#include "drv_display.h"
|
|
#include "image_info.h"
|
|
#include "display.h"
|
|
|
|
#if defined(RT_USING_TOUCH_DRIVERS)
|
|
#include "touch.h"
|
|
#include "touchpanel.h"
|
|
#endif
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
*
|
|
* Macro define
|
|
*
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
//#define CLOCK_MOVE_UPDOWN
|
|
|
|
/* display win layers */
|
|
#define CLOCK_TOP_WIN 0
|
|
#define CLOCK_BOTTOM_WIN 1
|
|
|
|
#define CLOCK_MAX_XRES 320
|
|
#define CLOCK_MAX_YRES 320
|
|
|
|
/* display region define */
|
|
#define CLOCK_REGION_X 0
|
|
#define CLOCK_REGION_Y 20
|
|
|
|
#define CLOCK_BOTTOM_COLOR_DEPTH 16
|
|
#define CLOCK_BOTTOM_XRES 320 // must aligned_32
|
|
#define CLOCK_BOTTOM_YRES 320 // must aligned_32
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
#define CLOCK_BOTTOM_FB_W CLOCK_BOTTOM_XRES
|
|
#define CLOCK_BOTTOM_FB_H (CLOCK_BOTTOM_YRES * 3)
|
|
#else
|
|
#define CLOCK_BOTTOM_FB_W (CLOCK_BOTTOM_XRES * 3)
|
|
#define CLOCK_BOTTOM_FB_H CLOCK_BOTTOM_YRES
|
|
#endif
|
|
|
|
#define CLOCK_TOP_COLOR_DEPTH 16
|
|
#define CLOCK_TOP_XRES 320 // must aligned_32
|
|
#define CLOCK_TOP_YRES 320 // must aligned_32
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
#define CLOCK_TOP_FB_W CLOCK_TOP_XRES
|
|
#define CLOCK_TOP_FB_H (CLOCK_TOP_YRES * 3)
|
|
#else
|
|
#define CLOCK_TOP_FB_W (CLOCK_TOP_XRES * 3)
|
|
#define CLOCK_TOP_FB_H CLOCK_TOP_YRES
|
|
#endif
|
|
|
|
/* Command define */
|
|
#define CMD_CLOCK_REFRESH (0x01UL << 0)
|
|
#define CMD_MOVE_START (0x01UL << 1)
|
|
#define CMD_MOVE_REFRESH (0x01UL << 2)
|
|
#define CMD_MOVE_AUTORUN (0x01UL << 3)
|
|
#define CMD_MOVE_END (0x01UL << 4)
|
|
|
|
/* Event define */
|
|
#define EVENT_CLOCK_UPDATE (0x01UL << 0)
|
|
#define EVENT_REFR_UPDATE (0x01UL << 1)
|
|
#define EVENT_REFR_DONE (0x01UL << 2)
|
|
|
|
#define APPCLK_CLOCK_UPDATE_TICKS (RT_TICK_PER_SECOND)
|
|
#define APPCLK_CLOCK_TEST_TICKS (RT_TICK_PER_SECOND * 3)
|
|
|
|
#if defined(RT_USING_TOUCH_DRIVERS)
|
|
#define TOP_XMOVE_STEP 80
|
|
#define BOTTOM_XMOVE_STEP 80
|
|
#else
|
|
#define TOP_XMOVE_STEP 1
|
|
#define BOTTOM_XMOVE_STEP 1
|
|
#endif
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
*
|
|
* Declaration
|
|
*
|
|
**************************************************************************************************
|
|
*/
|
|
extern image_info_t clock_bkg_info;
|
|
extern image_info_t clock_center_info;
|
|
extern image_info_t clock_sec_info;
|
|
extern image_info_t clock_min_info;
|
|
extern image_info_t clock_hour_info;
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
*
|
|
* Global static struct & data define
|
|
*
|
|
**************************************************************************************************
|
|
*/
|
|
struct clock_whiskey_data
|
|
{
|
|
rt_display_data_t disp;
|
|
rt_event_t disp_event;
|
|
rt_timer_t clock_timer;
|
|
rt_uint32_t cmd;
|
|
|
|
rt_uint32_t ticks;
|
|
rt_uint8_t hour;
|
|
rt_uint8_t minute;
|
|
rt_uint8_t second;
|
|
rt_uint8_t month;
|
|
rt_uint8_t day;
|
|
rt_uint8_t week;
|
|
|
|
rt_uint8_t *bottom_fb;
|
|
rt_uint32_t bottom_fblen;
|
|
rt_uint8_t *top_fb;
|
|
rt_uint32_t top_fblen;
|
|
|
|
rt_int8_t top_id;
|
|
rt_int16_t topmov_dir;
|
|
rt_int16_t topmov_offset;
|
|
|
|
rt_int8_t bottom_id;
|
|
rt_int16_t bottomov_dir;
|
|
rt_int16_t bottomov_offset;
|
|
|
|
rt_timer_t slide_timer;
|
|
rt_int16_t slide_cnt;
|
|
};
|
|
static struct clock_whiskey_data *g_clock_data = RT_NULL;
|
|
|
|
struct clock_bottom_info
|
|
{
|
|
rt_uint16_t w;
|
|
rt_uint16_t h;
|
|
const char *name;
|
|
};
|
|
|
|
#define CLOCK_BOTTOM_NUM_MAX 3
|
|
static struct clock_bottom_info bottomlist[CLOCK_BOTTOM_NUM_MAX] =
|
|
{
|
|
{ 320, 320, "/clock_bkg_320_320_1.dta"},
|
|
{ 320, 320, "/clock_bkg_320_320_2.dta"},
|
|
{ 320, 320, "/clock_bkg_320_320_3.dta"},
|
|
};
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
*
|
|
* Clock_whiskey functions.
|
|
*
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
#if defined(RT_USING_TOUCH_DRIVERS)
|
|
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
#define COORDINATE y_coordinate
|
|
#else
|
|
#define COORDINATE x_coordinate
|
|
#endif
|
|
|
|
#define BKGSLIDE_THRESHOLD_MIN 2
|
|
#define BKGSLIDE_THRESHOLD_MAX 20
|
|
static struct rt_touchpanel_block whiskey_bkg_touch_block;
|
|
struct rt_touch_data pre_point[1];
|
|
|
|
static rt_err_t app_clock_whiskey_bkg_touch_cb(struct rt_touch_data *point, rt_uint8_t num)
|
|
{
|
|
struct clock_whiskey_data *pdata = g_clock_data;
|
|
struct rt_touch_data *p = &point[0];
|
|
struct rt_touch_data *pre_p = &pre_point[0];
|
|
struct rt_touchpanel_block *b = &whiskey_bkg_touch_block;
|
|
|
|
if (RT_EOK != rt_touchpoint_is_valid(p, b))
|
|
{
|
|
return RT_ERROR;
|
|
}
|
|
|
|
switch (b->event)
|
|
{
|
|
case RT_TOUCH_EVENT_DOWN:
|
|
rt_memcpy(pre_p, p, sizeof(struct rt_touch_data));
|
|
|
|
pdata->topmov_dir = 0;
|
|
pdata->bottomov_dir = 0;
|
|
pdata->topmov_offset = 0;
|
|
pdata->bottomov_offset = 0;
|
|
|
|
pdata->cmd = CMD_MOVE_START;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
break;
|
|
|
|
case RT_TOUCH_EVENT_MOVE:
|
|
if (ABS(p->COORDINATE - pre_p->COORDINATE) >= BKGSLIDE_THRESHOLD_MIN)
|
|
{
|
|
pdata->topmov_dir = 1;
|
|
pdata->bottomov_dir = 1;
|
|
if (p->COORDINATE > pre_p->COORDINATE)
|
|
{
|
|
pdata->topmov_dir = -1;
|
|
pdata->bottomov_dir = -1;
|
|
}
|
|
pdata->topmov_offset += (rt_int16_t)(pre_p->COORDINATE - p->COORDINATE);
|
|
pdata->bottomov_offset += (rt_int16_t)(pre_p->COORDINATE - p->COORDINATE);
|
|
rt_memcpy(pre_point, p, sizeof(struct rt_touch_data));
|
|
|
|
pdata->cmd = CMD_MOVE_REFRESH;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
}
|
|
break;
|
|
|
|
case RT_TOUCH_EVENT_UP:
|
|
if (RT_TOUCH_EVENT_MOVE == pre_p->event)
|
|
{
|
|
if (ABS(p->COORDINATE - pre_p->COORDINATE) >= BKGSLIDE_THRESHOLD_MAX)
|
|
{
|
|
pdata->topmov_dir = 1;
|
|
pdata->bottomov_dir = 1;
|
|
if (p->COORDINATE > pre_p->COORDINATE)
|
|
{
|
|
pdata->topmov_dir = -1;
|
|
pdata->bottomov_dir = -1;
|
|
}
|
|
}
|
|
pdata->cmd = CMD_MOVE_AUTORUN;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static void app_clock_whiskey_bkg_touch_init(struct rt_touchpanel_block *block)
|
|
{
|
|
struct rt_device_graphic_info *info = &g_clock_data->disp->info;
|
|
|
|
rt_memset(block, 0, sizeof(struct rt_touchpanel_block));
|
|
|
|
block->w = CLOCK_TOP_XRES;
|
|
block->h = CLOCK_TOP_YRES;
|
|
block->x = CLOCK_REGION_X + ((info->width - block->w) / 2);
|
|
block->y = CLOCK_REGION_Y;// + ((info->height - block->h) / 2);
|
|
block->name = "whiskey";
|
|
block->callback = app_clock_whiskey_bkg_touch_cb;
|
|
}
|
|
|
|
#else
|
|
|
|
// test: test timer
|
|
static void app_clock_slide_timer(void *parameter)
|
|
{
|
|
struct clock_whiskey_data *pdata = (struct clock_whiskey_data *)parameter;
|
|
|
|
if (pdata->slide_cnt < 5)
|
|
{
|
|
pdata->topmov_dir = 1;
|
|
pdata->bottomov_dir = 1;
|
|
}
|
|
else
|
|
{
|
|
pdata->topmov_dir = -1;
|
|
pdata->bottomov_dir = -1;
|
|
}
|
|
|
|
if (++pdata->slide_cnt >= 10)
|
|
{
|
|
pdata->slide_cnt = 0;
|
|
}
|
|
|
|
pdata->cmd = CMD_MOVE_START | CMD_MOVE_AUTORUN;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
}
|
|
|
|
static void app_clock_slide_timer_restart(void *parameter)
|
|
{
|
|
struct clock_whiskey_data *pdata = (struct clock_whiskey_data *)parameter;
|
|
rt_tick_t arg = APPCLK_CLOCK_TEST_TICKS;
|
|
|
|
rt_timer_control(pdata->slide_timer, RT_TIMER_CTRL_SET_TIME, &arg);
|
|
rt_timer_start(pdata->slide_timer);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Display clock demo timer callback.
|
|
*/
|
|
static void app_clock_whiskey_timer(void *parameter)
|
|
{
|
|
struct clock_whiskey_data *pdata = (struct clock_whiskey_data *)parameter;
|
|
|
|
if (++pdata->second >= 60)
|
|
{
|
|
pdata->second = 0;
|
|
if (++pdata->minute == 60)
|
|
{
|
|
pdata->minute = 0;
|
|
if (++pdata->hour >= 24)
|
|
{
|
|
pdata->hour = 0;
|
|
|
|
if (++pdata->week == 7)
|
|
{
|
|
pdata->week = 0;
|
|
}
|
|
|
|
if (++pdata->day > 31)
|
|
{
|
|
pdata->day = 1;
|
|
if (++pdata->month > 12)
|
|
{
|
|
pdata->month = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pdata->cmd |= CMD_CLOCK_REFRESH;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
}
|
|
|
|
/**
|
|
* get clock background resource from file.
|
|
*/
|
|
static rt_err_t app_clock_whiskey_get_bkg(struct clock_bottom_info *info, rt_uint16_t *pbuf, rt_uint16_t w, rt_uint16_t h, rt_uint16_t offset)
|
|
{
|
|
int fd;
|
|
rt_uint32_t flen;
|
|
|
|
fd = open(info->name, O_RDONLY, 0);
|
|
RT_ASSERT(fd >= 0);
|
|
lseek(fd, 0, SEEK_SET);
|
|
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
rt_uint32_t xoffset = (w - info->w) / 2;
|
|
rt_uint32_t yoffset = offset * info->h;
|
|
#else
|
|
rt_uint32_t xoffset = offset * info->w;
|
|
rt_uint32_t yoffset = (h - info->h) / 2;
|
|
#endif
|
|
|
|
for (rt_uint16_t j = yoffset; j < yoffset + info->h; j++)
|
|
{
|
|
flen = read(fd,
|
|
pbuf + j * w + xoffset,
|
|
info->w * sizeof(rt_uint16_t));
|
|
|
|
if (!flen)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* clock dmeo init.
|
|
*/
|
|
static rt_err_t app_clock_whiskey_init(struct clock_whiskey_data *pdata)
|
|
{
|
|
/* top framebuffer malloc */
|
|
pdata->top_fblen = CLOCK_TOP_FB_W * CLOCK_TOP_FB_H * CLOCK_TOP_COLOR_DEPTH / 8;
|
|
pdata->top_fb = (rt_uint8_t *)rt_malloc_psram(pdata->top_fblen);
|
|
RT_ASSERT(pdata->top_fb != RT_NULL);
|
|
rt_memset((void *)pdata->top_fb, 0, pdata->top_fblen);
|
|
|
|
/* bottom framebuffer malloc */
|
|
pdata->bottom_fblen = CLOCK_BOTTOM_FB_W * CLOCK_BOTTOM_FB_H * CLOCK_BOTTOM_COLOR_DEPTH / 8;
|
|
pdata->bottom_fb = (rt_uint8_t *)rt_malloc_psram(pdata->bottom_fblen);
|
|
RT_ASSERT(pdata->bottom_fb != RT_NULL);
|
|
rt_memset((void *)pdata->bottom_fb, 0, pdata->bottom_fblen);
|
|
|
|
/* init background data */
|
|
pdata->bottom_id = 1;
|
|
app_clock_whiskey_get_bkg(&bottomlist[1], (rt_uint16_t *)pdata->bottom_fb, CLOCK_BOTTOM_FB_W, CLOCK_BOTTOM_FB_H, 1);
|
|
|
|
/* variable init */
|
|
pdata->hour = 3;
|
|
pdata->minute = 30;
|
|
pdata->second = 0;
|
|
|
|
/* init timer */
|
|
pdata->clock_timer = rt_timer_create("appclk_timer",
|
|
app_clock_whiskey_timer, (void *)pdata,
|
|
APPCLK_CLOCK_UPDATE_TICKS, RT_TIMER_FLAG_PERIODIC);
|
|
RT_ASSERT(pdata->clock_timer != RT_NULL);
|
|
rt_timer_start(pdata->clock_timer);
|
|
|
|
pdata->cmd |= CMD_CLOCK_REFRESH;
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
|
|
#if defined(RT_USING_TOUCH_DRIVERS)
|
|
app_clock_whiskey_bkg_touch_init(&whiskey_bkg_touch_block);
|
|
rt_touchpanel_block_register(&whiskey_bkg_touch_block);
|
|
#else
|
|
pdata->slide_timer = rt_timer_create("apptst_timer",
|
|
app_clock_slide_timer, (void *)pdata,
|
|
APPCLK_CLOCK_TEST_TICKS + RT_TICK_PER_SECOND / 2,
|
|
RT_TIMER_FLAG_ONE_SHOT);
|
|
RT_ASSERT(pdata->slide_timer != RT_NULL);
|
|
rt_timer_start(pdata->slide_timer);
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* clock demo deinit.
|
|
*/
|
|
static void app_clock_whiskey_deinit(struct clock_whiskey_data *pdata)
|
|
{
|
|
rt_err_t ret;
|
|
|
|
// test: delete test timer
|
|
#if defined(RT_USING_TOUCH_DRIVERS)
|
|
rt_touchpanel_block_unregister(&whiskey_bkg_touch_block);
|
|
#else
|
|
rt_timer_stop(pdata->slide_timer);
|
|
rt_timer_delete(pdata->slide_timer);
|
|
#endif
|
|
|
|
rt_timer_stop(pdata->clock_timer);
|
|
ret = rt_timer_delete(pdata->clock_timer);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
|
|
rt_free_psram((void *)pdata->top_fb);
|
|
rt_free_psram((void *)pdata->bottom_fb);
|
|
}
|
|
|
|
/**
|
|
* draw clock.
|
|
*/
|
|
static rt_err_t app_clock_top_draw(struct clock_whiskey_data *pdata)
|
|
{
|
|
int32_t hour, angle;
|
|
image_info_t *img_info = NULL;
|
|
rt_uint8_t *fb = pdata->top_fb;
|
|
|
|
//clear clock area
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
rt_uint16_t *pbuf = (rt_uint16_t *)pdata->top_fb;
|
|
for (rt_uint16_t j = CLOCK_TOP_YRES; j < CLOCK_TOP_YRES + CLOCK_TOP_YRES; j++)
|
|
{
|
|
for (rt_uint16_t i = 0; i < CLOCK_TOP_XRES; i++)
|
|
{
|
|
pbuf[j * CLOCK_TOP_FB_W + i] = 0;
|
|
}
|
|
}
|
|
#else
|
|
rt_uint16_t *pbuf = (rt_uint16_t *)pdata->top_fb;
|
|
for (rt_uint16_t j = 0; j < CLOCK_TOP_YRES; j++)
|
|
{
|
|
for (rt_uint16_t i = CLOCK_TOP_XRES; i < CLOCK_TOP_XRES + CLOCK_TOP_XRES; i++)
|
|
{
|
|
pbuf[j * CLOCK_TOP_FB_W + i] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//draw clock
|
|
if (1)
|
|
{
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
rt_uint16_t xoffset = (CLOCK_TOP_XRES / 2);
|
|
rt_uint16_t yoffset = (CLOCK_TOP_YRES / 2) + CLOCK_TOP_YRES;
|
|
#else
|
|
rt_uint16_t xoffset = (CLOCK_TOP_XRES / 2) + CLOCK_TOP_XRES;
|
|
rt_uint16_t yoffset = (CLOCK_TOP_YRES / 2);
|
|
#endif
|
|
|
|
//draw hour line
|
|
img_info = &clock_hour_info;
|
|
RT_ASSERT(img_info->w <= CLOCK_TOP_XRES / 2);
|
|
RT_ASSERT(img_info->h <= CLOCK_TOP_YRES / 2);
|
|
|
|
hour = pdata->hour;
|
|
if (hour >= 12)
|
|
{
|
|
hour -= 12;
|
|
}
|
|
angle = hour * (360 / 12) + (pdata->minute * 30) / 60 - 90;
|
|
if (angle < 0)
|
|
{
|
|
angle += 360;
|
|
}
|
|
rt_display_rotate_16bit((float)angle, img_info->w, img_info->h, (unsigned short *)img_info->data,
|
|
(unsigned short *)((uint32_t)fb + 2 * (yoffset * CLOCK_TOP_FB_W + xoffset)),
|
|
CLOCK_TOP_FB_W, 0, img_info->h / 2);
|
|
//draw min line
|
|
img_info = &clock_min_info;
|
|
RT_ASSERT(img_info->w <= CLOCK_TOP_XRES / 2);
|
|
RT_ASSERT(img_info->h <= CLOCK_TOP_YRES / 2);
|
|
|
|
angle = pdata->minute * (360 / 60);
|
|
angle -= 90;
|
|
if (angle < 0)
|
|
{
|
|
angle += 360;
|
|
}
|
|
rt_display_rotate_16bit((float)angle, img_info->w, img_info->h, (unsigned short *)img_info->data,
|
|
(unsigned short *)((uint32_t)fb + 2 * (yoffset * CLOCK_TOP_FB_W + xoffset)),
|
|
CLOCK_TOP_FB_W, 0, img_info->h / 2);
|
|
|
|
//draw second line
|
|
img_info = &clock_sec_info;
|
|
RT_ASSERT(img_info->w <= CLOCK_TOP_XRES / 2);
|
|
RT_ASSERT(img_info->h <= CLOCK_TOP_YRES / 2);
|
|
|
|
angle = pdata->second * (360 / 60);
|
|
angle -= 90;
|
|
if (angle < 0)
|
|
{
|
|
angle += 360;
|
|
}
|
|
rt_display_rotate_16bit((float)angle, img_info->w, img_info->h, (unsigned short *)img_info->data,
|
|
(unsigned short *)((uint32_t)fb + 2 * (yoffset * CLOCK_TOP_FB_W + xoffset)),
|
|
CLOCK_TOP_FB_W, 0, img_info->h / 2);
|
|
|
|
//draw centre
|
|
img_info = &clock_center_info;
|
|
RT_ASSERT(img_info->w <= CLOCK_TOP_XRES);
|
|
RT_ASSERT(img_info->h <= CLOCK_TOP_YRES);
|
|
|
|
yoffset -= img_info->h / 2;
|
|
xoffset -= img_info->w / 2;
|
|
rt_display_img_fill(img_info, fb, CLOCK_TOP_FB_W, xoffset, yoffset);
|
|
}
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* top move
|
|
*/
|
|
static rt_err_t app_clock_top_move_start(struct clock_whiskey_data *pdata)
|
|
{
|
|
rt_uint16_t *pbuf = (rt_uint16_t *)pdata->top_fb;
|
|
|
|
/* move buf2(clock data) to buf1 & buf3
|
|
|<-- buf1 -->|<-- buf2 -->|<-- buf3 -->|
|
|
----------------------------------------
|
|
| | . . . . . | |
|
|
| <-- | . . . . . | --> |
|
|
| | . . . . . | |
|
|
----------------------------------------
|
|
*/
|
|
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
for (rt_uint16_t j = CLOCK_TOP_YRES; j < CLOCK_TOP_YRES + CLOCK_TOP_YRES; j++)
|
|
{
|
|
for (rt_uint16_t i = 0; i < CLOCK_TOP_XRES; i++)
|
|
{
|
|
pbuf[(j - CLOCK_TOP_YRES) * CLOCK_TOP_FB_W + i] = pbuf[j * CLOCK_TOP_FB_W + i];
|
|
pbuf[(j + CLOCK_TOP_YRES) * CLOCK_TOP_FB_W + i] = pbuf[j * CLOCK_TOP_FB_W + i];
|
|
}
|
|
}
|
|
#else
|
|
for (rt_uint16_t j = 0; j < CLOCK_TOP_YRES; j++)
|
|
{
|
|
for (rt_uint16_t i = CLOCK_TOP_XRES; i < CLOCK_TOP_XRES + CLOCK_TOP_XRES; i++)
|
|
{
|
|
pbuf[j * CLOCK_TOP_FB_W + i - CLOCK_TOP_XRES] = pbuf[j * CLOCK_TOP_FB_W + i];
|
|
pbuf[j * CLOCK_TOP_FB_W + i + CLOCK_TOP_XRES] = pbuf[j * CLOCK_TOP_FB_W + i];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static void app_clock_top_move_autorun(struct clock_whiskey_data *pdata)
|
|
{
|
|
pdata->topmov_offset += TOP_XMOVE_STEP * pdata->topmov_dir;
|
|
}
|
|
|
|
static rt_err_t app_clock_top_move_check(struct clock_whiskey_data *pdata)
|
|
{
|
|
if (ABS(pdata->topmov_offset) >= CLOCK_TOP_XRES)
|
|
{
|
|
pdata->topmov_offset = CLOCK_TOP_XRES * pdata->topmov_dir;
|
|
return RT_EEMPTY;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t app_clock_top_move_end(struct clock_whiskey_data *pdata)
|
|
{
|
|
pdata->topmov_offset = 0;
|
|
pdata->topmov_dir = 0;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* top layer refresh.
|
|
*/
|
|
static rt_err_t app_clock_top_refresh(struct clock_whiskey_data *pdata,
|
|
struct rt_display_config *wincfg)
|
|
{
|
|
struct rt_device_graphic_info *info = &pdata->disp->info;
|
|
rt_uint32_t fblen = pdata->top_fblen;
|
|
rt_uint8_t *fb = pdata->top_fb;
|
|
|
|
wincfg->winId = CLOCK_TOP_WIN;
|
|
wincfg->colorkey = COLOR_KEY_EN | 0;
|
|
wincfg->format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
|
|
wincfg->lut = RT_NULL;
|
|
wincfg->lutsize = 0;
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
wincfg->fb = fb + (CLOCK_TOP_YRES + pdata->topmov_offset) * CLOCK_TOP_FB_W * sizeof(rt_uint16_t);
|
|
wincfg->fblen = CLOCK_TOP_YRES * CLOCK_TOP_FB_W * sizeof(rt_uint16_t);
|
|
#else
|
|
wincfg->fb = fb + (CLOCK_TOP_XRES + pdata->topmov_offset) * sizeof(rt_uint16_t);
|
|
wincfg->fblen = fblen - (CLOCK_TOP_XRES + pdata->topmov_offset) * sizeof(rt_uint16_t);
|
|
#endif
|
|
wincfg->xVir = CLOCK_TOP_FB_W;
|
|
wincfg->w = CLOCK_TOP_XRES;
|
|
wincfg->h = CLOCK_TOP_YRES;
|
|
wincfg->x = CLOCK_REGION_X + ((info->width - wincfg->w) / 2);
|
|
wincfg->y = CLOCK_REGION_Y;// + ((info->height - wincfg->h) / 2);
|
|
wincfg->ylast = wincfg->y;
|
|
|
|
RT_ASSERT(((wincfg->w * CLOCK_TOP_COLOR_DEPTH) % 32) == 0);
|
|
RT_ASSERT(((wincfg->y % 2) == 0) && ((wincfg->h % 2) == 0));
|
|
|
|
RT_ASSERT((wincfg->x + wincfg->w) <= info->width);
|
|
RT_ASSERT((wincfg->y + wincfg->h) <= info->height);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* bottom move
|
|
*/
|
|
static rt_err_t app_clock_bottom_move_start(struct clock_whiskey_data *pdata)
|
|
{
|
|
rt_int8_t id;
|
|
|
|
// get left bottom buffer
|
|
id = pdata->bottom_id - 1;
|
|
if (id < 0)
|
|
{
|
|
id = CLOCK_BOTTOM_NUM_MAX - 1;
|
|
}
|
|
app_clock_whiskey_get_bkg(&bottomlist[id], (rt_uint16_t *)pdata->bottom_fb, CLOCK_BOTTOM_FB_W, CLOCK_BOTTOM_FB_H, 0);
|
|
|
|
// get right bottom buffer
|
|
id = pdata->bottom_id + 1;
|
|
if (id >= CLOCK_BOTTOM_NUM_MAX)
|
|
{
|
|
id = 0;
|
|
}
|
|
app_clock_whiskey_get_bkg(&bottomlist[id], (rt_uint16_t *)pdata->bottom_fb, CLOCK_BOTTOM_FB_W, CLOCK_BOTTOM_FB_H, 2);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static void app_clock_bottom_move_autorun(struct clock_whiskey_data *pdata)
|
|
{
|
|
pdata->bottomov_offset += BOTTOM_XMOVE_STEP * pdata->bottomov_dir;
|
|
}
|
|
|
|
static rt_err_t app_clock_bottom_move_check(struct clock_whiskey_data *pdata)
|
|
{
|
|
if (ABS(pdata->bottomov_offset) >= CLOCK_BOTTOM_XRES)
|
|
{
|
|
pdata->bottomov_offset = CLOCK_BOTTOM_XRES * pdata->bottomov_dir;
|
|
return RT_EEMPTY;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t app_clock_bottom_move_end(struct clock_whiskey_data *pdata)
|
|
{
|
|
RT_ASSERT(ABS(pdata->bottomov_dir) == 1);
|
|
|
|
pdata->bottom_id += pdata->bottomov_dir;
|
|
if (pdata->bottom_id < 0)
|
|
{
|
|
pdata->bottom_id = CLOCK_BOTTOM_NUM_MAX - 1;
|
|
}
|
|
else if (pdata->bottom_id >= CLOCK_BOTTOM_NUM_MAX)
|
|
{
|
|
pdata->bottom_id = 0;
|
|
}
|
|
app_clock_whiskey_get_bkg(&bottomlist[pdata->bottom_id], (rt_uint16_t *)pdata->bottom_fb, CLOCK_BOTTOM_FB_W, CLOCK_BOTTOM_FB_H, 1);
|
|
|
|
pdata->bottomov_offset = 0;
|
|
pdata->bottomov_dir = 0;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* bottom layer refresh.
|
|
*/
|
|
static rt_err_t app_clock_bottom_refresh(struct clock_whiskey_data *pdata,
|
|
struct rt_display_config *wincfg)
|
|
{
|
|
struct rt_device_graphic_info *info = &pdata->disp->info;
|
|
|
|
wincfg->winId = CLOCK_BOTTOM_WIN;
|
|
wincfg->format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
|
|
wincfg->lut = RT_NULL;
|
|
wincfg->lutsize = 0;
|
|
wincfg->xVir = CLOCK_BOTTOM_FB_W;
|
|
wincfg->w = CLOCK_BOTTOM_XRES;
|
|
wincfg->h = CLOCK_BOTTOM_YRES;
|
|
#ifdef CLOCK_MOVE_UPDOWN
|
|
wincfg->fb = pdata->bottom_fb + (CLOCK_BOTTOM_YRES + pdata->bottomov_offset) * CLOCK_BOTTOM_FB_W * sizeof(rt_uint16_t);
|
|
wincfg->fblen = CLOCK_BOTTOM_YRES * CLOCK_BOTTOM_FB_W * sizeof(rt_uint16_t);
|
|
#else
|
|
wincfg->fb = pdata->bottom_fb + (CLOCK_BOTTOM_XRES + pdata->bottomov_offset) * sizeof(rt_uint16_t);
|
|
wincfg->fblen = pdata->bottom_fblen - (CLOCK_BOTTOM_XRES + pdata->bottomov_offset) * sizeof(rt_uint16_t);
|
|
#endif
|
|
wincfg->x = CLOCK_REGION_X + ((info->width - wincfg->w) / 2);
|
|
wincfg->y = CLOCK_REGION_Y;// + ((info->height - wincfg->h) / 2);
|
|
wincfg->ylast = wincfg->y;
|
|
|
|
RT_ASSERT(((wincfg->w * CLOCK_BOTTOM_COLOR_DEPTH) % 32) == 0);
|
|
RT_ASSERT(((wincfg->y % 2) == 0) && ((wincfg->h % 2) == 0));
|
|
|
|
RT_ASSERT((wincfg->x + wincfg->w) <= info->width);
|
|
RT_ASSERT((wincfg->y + wincfg->h) <= info->height);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t app_clock_is_move_end(struct clock_whiskey_data *pdata)
|
|
{
|
|
if ((pdata->topmov_dir == 0) && (pdata->bottomov_dir == 0))
|
|
{
|
|
return RT_EOK;
|
|
}
|
|
|
|
return RT_ERROR;
|
|
}
|
|
|
|
/*
|
|
**************************************************************************************************
|
|
*
|
|
* clock demo init & thread
|
|
*
|
|
**************************************************************************************************
|
|
*/
|
|
|
|
/**
|
|
* app clock display refresh request: request send data to LCD pannel.
|
|
*/
|
|
static rt_err_t app_clock_refr_done(void)
|
|
{
|
|
return (rt_event_send(g_clock_data->disp_event, EVENT_REFR_DONE));
|
|
}
|
|
|
|
static rt_err_t app_clock_refr_request(struct rt_display_mq_t *disp_mq)
|
|
{
|
|
rt_err_t ret;
|
|
|
|
//request refresh display data to Pannel
|
|
disp_mq->disp_finish = app_clock_refr_done;
|
|
ret = rt_mq_send(g_clock_data->disp->disp_mq, disp_mq, sizeof(struct rt_display_mq_t));
|
|
RT_ASSERT(ret == RT_EOK);
|
|
|
|
//wait refresh done
|
|
rt_uint32_t event;
|
|
ret = rt_event_recv(g_clock_data->disp_event, EVENT_REFR_DONE,
|
|
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
|
|
RT_WAITING_FOREVER, &event);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* app clock display task.
|
|
*/
|
|
static rt_err_t app_clock_refr_tasks(struct clock_whiskey_data *pdata)
|
|
{
|
|
rt_err_t ret, ret1;
|
|
struct rt_display_mq_t disp_mq;
|
|
|
|
rt_memset(&disp_mq, 0, sizeof(struct rt_display_mq_t));
|
|
disp_mq.win[CLOCK_TOP_WIN].zpos = WIN_TOP_LAYER;
|
|
disp_mq.win[CLOCK_BOTTOM_WIN].zpos = WIN_BOTTOM_LAYER;
|
|
|
|
if ((pdata->cmd & CMD_MOVE_START) == CMD_MOVE_START)
|
|
{
|
|
pdata->cmd &= ~CMD_MOVE_START;
|
|
|
|
app_clock_top_move_start(pdata);
|
|
app_clock_bottom_move_start(pdata);
|
|
}
|
|
|
|
if ((pdata->cmd & CMD_MOVE_AUTORUN) == CMD_MOVE_AUTORUN)
|
|
{
|
|
app_clock_top_move_autorun(pdata);
|
|
app_clock_bottom_move_autorun(pdata);
|
|
|
|
pdata->cmd |= CMD_MOVE_REFRESH;
|
|
}
|
|
|
|
if ((pdata->cmd & CMD_MOVE_REFRESH) == CMD_MOVE_REFRESH)
|
|
{
|
|
pdata->cmd &= ~CMD_MOVE_REFRESH;
|
|
pdata->cmd |= CMD_CLOCK_REFRESH;
|
|
|
|
ret = app_clock_top_move_check(pdata);
|
|
ret1 = app_clock_bottom_move_check(pdata);
|
|
if ((ret != RT_EOK) || (ret1 != RT_EOK))
|
|
{
|
|
pdata->cmd |= CMD_MOVE_END;
|
|
}
|
|
}
|
|
|
|
if ((pdata->cmd & CMD_CLOCK_REFRESH) == CMD_CLOCK_REFRESH)
|
|
{
|
|
pdata->cmd &= ~CMD_CLOCK_REFRESH;
|
|
|
|
if (RT_EOK == app_clock_is_move_end(pdata))
|
|
{
|
|
ret = app_clock_top_draw(pdata);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
}
|
|
|
|
ret = app_clock_top_refresh(pdata, &disp_mq.win[CLOCK_TOP_WIN]);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
disp_mq.cfgsta |= (0x01 << CLOCK_TOP_WIN);
|
|
|
|
ret = app_clock_bottom_refresh(pdata, &disp_mq.win[CLOCK_BOTTOM_WIN]);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
disp_mq.cfgsta |= (0x01 << CLOCK_BOTTOM_WIN);
|
|
}
|
|
|
|
if ((pdata->cmd & CMD_MOVE_END) == CMD_MOVE_END)
|
|
{
|
|
pdata->cmd &= ~CMD_MOVE_END;
|
|
pdata->cmd &= ~CMD_MOVE_AUTORUN;
|
|
|
|
app_clock_top_move_end(pdata);
|
|
app_clock_bottom_move_end(pdata);
|
|
|
|
#ifndef RT_USING_TOUCH_DRIVERS
|
|
app_clock_slide_timer_restart(pdata);
|
|
#endif
|
|
}
|
|
|
|
if (disp_mq.cfgsta)
|
|
{
|
|
app_clock_refr_request(&disp_mq);
|
|
}
|
|
|
|
if (pdata->cmd != 0)
|
|
{
|
|
rt_event_send(pdata->disp_event, EVENT_REFR_UPDATE);
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
/**
|
|
* clock demo thread
|
|
*/
|
|
static void app_clock_thread(void *p)
|
|
{
|
|
rt_err_t ret;
|
|
uint32_t event;
|
|
struct clock_whiskey_data *pdata;
|
|
|
|
g_clock_data = pdata = (struct clock_whiskey_data *)rt_malloc(sizeof(struct clock_whiskey_data));
|
|
RT_ASSERT(pdata != RT_NULL);
|
|
rt_memset((void *)pdata, 0, sizeof(struct clock_whiskey_data));
|
|
|
|
pdata->disp = rt_display_get_disp();
|
|
RT_ASSERT(pdata->disp != RT_NULL);
|
|
|
|
struct rt_device_graphic_info *info = &pdata->disp->info;
|
|
if ((info->width < CLOCK_MAX_XRES) || (info->height < CLOCK_MAX_YRES))
|
|
{
|
|
rt_kprintf("Error: the pannel size(%dx%d) is less than required size(%dx%d)!\n",
|
|
info->width, info->height, CLOCK_MAX_XRES, CLOCK_MAX_YRES);
|
|
RT_ASSERT(!(info->width < CLOCK_MAX_XRES));
|
|
RT_ASSERT(!(info->height < CLOCK_MAX_YRES));
|
|
}
|
|
|
|
ret = rt_display_screen_clear();
|
|
RT_ASSERT(ret == RT_EOK);
|
|
|
|
pdata->disp_event = rt_event_create("display_event", RT_IPC_FLAG_FIFO);
|
|
RT_ASSERT(pdata->disp_event != RT_NULL);
|
|
|
|
ret = app_clock_whiskey_init(pdata);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
|
|
while (1)
|
|
{
|
|
ret = rt_event_recv(pdata->disp_event, EVENT_REFR_UPDATE,
|
|
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
|
|
RT_WAITING_FOREVER, &event);
|
|
if (ret != RT_EOK)
|
|
{
|
|
/* Reserved... */
|
|
}
|
|
|
|
if (event & EVENT_REFR_UPDATE)
|
|
{
|
|
ret = app_clock_refr_tasks(pdata);
|
|
RT_ASSERT(ret == RT_EOK);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Thread deinit */
|
|
app_clock_whiskey_deinit(pdata);
|
|
|
|
rt_event_delete(pdata->disp_event);
|
|
|
|
rt_free(pdata);
|
|
}
|
|
|
|
/**
|
|
* clock demo init
|
|
*/
|
|
int clock_whiskey_init(void)
|
|
{
|
|
rt_thread_t thread;
|
|
|
|
thread = rt_thread_create("clockwhiskey", app_clock_thread, RT_NULL, 2048, 5, 10);
|
|
RT_ASSERT(thread != RT_NULL);
|
|
|
|
rt_thread_startup(thread);
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
INIT_APP_EXPORT(clock_whiskey_init);
|