815 lines
24 KiB
C
815 lines
24 KiB
C
#include "led_lyric.h"
|
||
#include "res/resfile.h"
|
||
#include "font/font_all.h"
|
||
#include "system/timer.h"
|
||
#include "board_config.h"
|
||
#include "os/os_api.h"
|
||
#include "ui/ui_style.h"
|
||
#include "system/includes.h"
|
||
#include "fm/fm_manage.h"
|
||
#include "uart_update.h"
|
||
#include "lyrics_api.h"
|
||
|
||
#if LED_LYRICS_ENABLE
|
||
|
||
typedef struct {
|
||
u8 *pixelbuf;
|
||
u8 width;
|
||
u8 height;
|
||
u8 offsetx;
|
||
u16 nbytes;
|
||
} FONT_CHAR_INFO;
|
||
|
||
typedef struct {
|
||
u8 scroll_speed;
|
||
u8 center_offset;
|
||
u16 scroll_offset;
|
||
LRC_FONT_ROTATE rotate;
|
||
LRC_FONT_FLIP flip;
|
||
} FONT_LYRICS_INFO;
|
||
|
||
typedef struct {
|
||
u8 *str;
|
||
u16 len;
|
||
u16 offset;
|
||
u16 sum_width;
|
||
FONT_LYRICS_INFO lyrics_info;
|
||
} LYRICS_UPDATE_INFO;
|
||
|
||
struct lrc_font_header {
|
||
u8 magic[4];
|
||
u32 version;
|
||
u32 timestamp;
|
||
u8 fontsize;
|
||
u8 bitdepth;
|
||
u8 reserved[18];
|
||
};
|
||
|
||
typedef struct {
|
||
u32 width : 6;
|
||
u32 height : 7;
|
||
s32 top : 8;
|
||
u32 size : 11;
|
||
s32 left : 7;
|
||
u32 addr : 25;
|
||
} __attribute__((packed, aligned(1))) LRC_UnicInfo;
|
||
|
||
|
||
#define Font_NumPages 1024
|
||
#define Font_PageSize (0x10000 / Font_NumPages)
|
||
|
||
#define Code_Size 7
|
||
#define Colon_Size 3
|
||
typedef struct {
|
||
u16 charIndex;
|
||
u8 codesMask[Font_PageSize / 8];
|
||
} LRC_Font_PageEntry_t;
|
||
|
||
#define IMAGE_BUF_SIZE ((LED_WIDTH * LED_HEIGHT + 7) / 8)
|
||
static u8 *image_buf = NULL; //整屏点阵缓存buffer
|
||
static u8 *image_buf_out = NULL;
|
||
static u8 lrc_check_online_flag = 1;
|
||
static u8 lrc_sleep_flag = 0;
|
||
|
||
static struct lrc_font_header header = {0};
|
||
static struct font_info f_info;
|
||
static FONT_CHAR_INFO char_info;
|
||
|
||
static u16 font_lyrics_scroll_timer_id = 0;
|
||
static LYRICS_UPDATE_INFO lrc_update_info;
|
||
|
||
static OS_MUTEX mutex;
|
||
static OS_MUTEX show_mutex;
|
||
|
||
static struct lrc_show_status lrc_status = {
|
||
|
||
.lrc_rotate = 0,
|
||
.lrc_flip = 0,
|
||
.lrc_scroll_speed = 100,
|
||
|
||
.lrc_show_status_update_flag = 0,
|
||
.lrc_record_len = 0,
|
||
.lrc_record_str = NULL,
|
||
};
|
||
|
||
void lyrics_show_status_set(u16 scroll_speed, u8 rotate, u8 flip)
|
||
{
|
||
lrc_status.lrc_scroll_speed = scroll_speed;
|
||
lrc_status.lrc_rotate = rotate;
|
||
lrc_status.lrc_flip = flip;
|
||
lrc_status.lrc_show_status_update_flag = 1;
|
||
lyrics_update_font(lrc_status.lrc_record_str, lrc_status.lrc_record_len, NULL);
|
||
}
|
||
|
||
static bool LRC_InitFont_Unicode(struct font_info *info)
|
||
{
|
||
info->pixel.file.fd = fopen(info->pixel.file.name, "r");
|
||
if (!info->pixel.file.fd) {
|
||
info->sta |= FT_ERROR_NOPIXFILE;
|
||
printf("unicode file not open!");
|
||
return FALSE;
|
||
}
|
||
|
||
fseek(info->pixel.file.fd, 0, SEEK_SET);
|
||
fread(info->pixel.file.fd, &header, sizeof(struct lrc_font_header));
|
||
printf("magic : %s\n", header.magic);
|
||
printf("version : 0x%x\n", header.version);
|
||
printf("timestamp : %d\n", header.timestamp);
|
||
printf("fontsize : %d\n", header.fontsize);
|
||
printf("bitdepth : %d\n", header.bitdepth);
|
||
|
||
if (memcmp(header.magic, "unic", 4)) {
|
||
info->sta |= FT_ERROR_NOPIXFILE;
|
||
printf("unicode magic not paired!");
|
||
return FALSE;
|
||
}
|
||
info->pixel.size = header.fontsize;
|
||
|
||
if (header.bitdepth == 0) {
|
||
info->pixel.nbytes = (info->pixel.size * info->pixel.size + 7) / 8;
|
||
} else if (header.bitdepth == 1) {
|
||
info->pixel.nbytes = (info->pixel.size * info->pixel.size * 2 + 7) / 8;
|
||
} else if (header.bitdepth == 2) {
|
||
info->pixel.nbytes = (info->pixel.size * info->pixel.size * 4 + 7) / 8;
|
||
} else { // header.bitdepth == 8
|
||
info->pixel.nbytes = info->pixel.size * info->pixel.size;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/* 获取字符索引 */
|
||
static int LRC_Font_GetCharIndex(struct font_info *info, u16 unicode)
|
||
{
|
||
LRC_Font_PageEntry_t pageEntry;
|
||
|
||
u16 m = unicode / Font_PageSize;
|
||
u16 n = unicode % Font_PageSize;
|
||
u16 i, j;
|
||
|
||
fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + m * sizeof(LRC_Font_PageEntry_t), SEEK_SET);
|
||
fread(info->pixel.file.fd, &pageEntry, sizeof(LRC_Font_PageEntry_t));
|
||
if (!(pageEntry.codesMask[n / 8] & (1 << (n % 8)))) {
|
||
return -1;
|
||
}
|
||
|
||
for (i = j = 0; i < n; i++) {
|
||
if (pageEntry.codesMask[i / 8] & (1 << (i % 8))) {
|
||
j++;
|
||
}
|
||
}
|
||
i = pageEntry.charIndex + j;
|
||
return i;
|
||
}
|
||
|
||
|
||
/* 获取字符宽度 */
|
||
static int LRC_Font_GetCharWidth(struct font_info *info, u16 unicode)
|
||
{
|
||
int charIndex;
|
||
u16 nbytes;
|
||
|
||
if ((charIndex = LRC_Font_GetCharIndex(info, unicode)) < 0) {
|
||
printf("unicode : 0x%x, charIndex = %d, char index not exist!\n", unicode, charIndex);
|
||
return 0;
|
||
}
|
||
|
||
LRC_UnicInfo codeinfo = {0};
|
||
|
||
u32 file_offset = 0;
|
||
fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + Font_NumPages * \
|
||
sizeof(LRC_Font_PageEntry_t) + charIndex * sizeof(LRC_UnicInfo), SEEK_SET);
|
||
fread(info->pixel.file.fd, &codeinfo, sizeof(LRC_UnicInfo));
|
||
|
||
if (unicode == 0x20) {
|
||
codeinfo.width = info->pixel.size / 3;
|
||
codeinfo.height = info->pixel.size / 3;
|
||
}
|
||
|
||
if (unicode == 0x10) {
|
||
codeinfo.width = Code_Size;
|
||
codeinfo.height = Code_Size;
|
||
memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8);
|
||
}
|
||
|
||
if (unicode == 0x11) {
|
||
codeinfo.width = Colon_Size;
|
||
codeinfo.height = Colon_Size;
|
||
memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8);
|
||
}
|
||
u8 width = codeinfo.width;
|
||
char_info.width = codeinfo.width;
|
||
char_info.height = codeinfo.height;
|
||
|
||
return width;
|
||
}
|
||
|
||
/* 获取字符位图数据 */
|
||
static int LRC_Font_GetCharBits(struct font_info *info, u16 unicode)
|
||
{
|
||
int charIndex;
|
||
u16 nbytes, width;
|
||
|
||
if ((charIndex = LRC_Font_GetCharIndex(info, unicode)) < 0) {
|
||
printf("unicode : 0x%x, charIndex = %d, char index not exist!\n", unicode, charIndex);
|
||
return 0;
|
||
}
|
||
LRC_UnicInfo codeinfo = {0};
|
||
|
||
fseek(info->pixel.file.fd, sizeof(struct lrc_font_header) + Font_NumPages * \
|
||
sizeof(LRC_Font_PageEntry_t) + charIndex * sizeof(LRC_UnicInfo), SEEK_SET);
|
||
fread(info->pixel.file.fd, &codeinfo, sizeof(LRC_UnicInfo));
|
||
const u8 bit[] = {1, 2, 4, 8};
|
||
nbytes = (codeinfo.width * codeinfo.height * bit[header.bitdepth] + 7) / 8;
|
||
if (info->pixel.pixelbuf != NULL) {
|
||
if (nbytes > info->pixel.nbytes) {
|
||
puts("error:pixelbuf overlay!\n");
|
||
printf("info.width = %d, info->ascpixel.size = %d, nbytes = %d\n", width, info->pixel.size, nbytes);
|
||
free(info->pixel.pixelbuf);
|
||
info->pixel.pixelbuf = (u8 *)malloc(nbytes);
|
||
info->pixel.nbytes = nbytes;
|
||
|
||
char_info.pixelbuf = info->pixel.pixelbuf;
|
||
char_info.nbytes = info->pixel.nbytes;
|
||
}
|
||
|
||
fseek(info->pixel.file.fd, codeinfo.addr, SEEK_SET);
|
||
fread(info->pixel.file.fd, info->pixel.pixelbuf, nbytes);
|
||
}
|
||
|
||
if (unicode == 0x20) {
|
||
codeinfo.width = info->pixel.size / 3;
|
||
codeinfo.height = info->pixel.size / 3;
|
||
}
|
||
|
||
if (unicode == 0x10) {
|
||
codeinfo.width = Code_Size;
|
||
codeinfo.height = Code_Size;
|
||
memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8);
|
||
}
|
||
|
||
if (unicode == 0x11) {
|
||
codeinfo.width = Colon_Size;
|
||
codeinfo.height = Colon_Size;
|
||
memset(info->pixel.pixelbuf, 0, (codeinfo.width * codeinfo.height + 7) / 8);
|
||
}
|
||
width = codeinfo.width;
|
||
char_info.width = codeinfo.width;
|
||
char_info.height = codeinfo.height;
|
||
char_info.pixelbuf = info->pixel.pixelbuf;
|
||
|
||
return width;
|
||
}
|
||
|
||
bool lyrics_font_init(char *file_name)
|
||
{
|
||
bool ret;
|
||
if (f_info.pixel.file.fd == NULL) {
|
||
f_info.pixel.file.name = file_name;
|
||
f_info.bigendian = 0;
|
||
ret = LRC_InitFont_Unicode(&f_info);
|
||
if (ret == FALSE) {
|
||
return FALSE;
|
||
}
|
||
f_info.pixel.pixelbuf = (u8 *)malloc(f_info.pixel.nbytes);
|
||
char_info.pixelbuf = f_info.pixel.pixelbuf;
|
||
char_info.nbytes = f_info.pixel.nbytes;
|
||
image_buf = (u8 *)malloc(IMAGE_BUF_SIZE);
|
||
image_buf_out = (u8 *)malloc(IMAGE_BUF_SIZE);
|
||
os_mutex_create(&mutex);
|
||
os_mutex_create(&show_mutex);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
void lyrics_font_release()
|
||
{
|
||
if (f_info.pixel.file.fd) {
|
||
fclose(f_info.pixel.file.fd);
|
||
f_info.pixel.file.fd = NULL;
|
||
}
|
||
if (f_info.pixel.pixelbuf) {
|
||
free(f_info.pixel.pixelbuf);
|
||
f_info.pixel.pixelbuf = NULL;
|
||
}
|
||
if (font_lyrics_scroll_timer_id) {
|
||
sys_timer_del(font_lyrics_scroll_timer_id);
|
||
font_lyrics_scroll_timer_id = 0;
|
||
}
|
||
if (lrc_update_info.str) {
|
||
free(lrc_update_info.str);
|
||
lrc_update_info.str = NULL;
|
||
}
|
||
if (image_buf) {
|
||
free(image_buf);
|
||
image_buf = NULL;
|
||
}
|
||
if (image_buf_out) {
|
||
free(image_buf_out);
|
||
image_buf_out = NULL;
|
||
}
|
||
}
|
||
|
||
static void Font_CharBit_to_Image(FONT_CHAR_INFO *info, u8 *image, u8 x, u8 y)
|
||
{
|
||
u8 image_width = LED_WIDTH;
|
||
u8 char_width = info->width;
|
||
u8 char_height = info->height;
|
||
u8 *char_buf = info->pixelbuf;
|
||
u8 char_byte_idx, char_bit_idx;
|
||
u8 image_byte_idx, image_bit_idx;
|
||
u8 inc_ofs = info->offsetx;
|
||
for (u16 i = 0; i < char_height; i++) {
|
||
for (u16 j = 0; j < char_width; j++) {
|
||
if (x + j >= LED_WIDTH) {
|
||
break;
|
||
}
|
||
if (j + inc_ofs >= char_width) {
|
||
break;
|
||
}
|
||
char_byte_idx = (i * char_width + j + inc_ofs) / 8;
|
||
char_bit_idx = (i * char_width + j + inc_ofs) % 8;
|
||
image_byte_idx = ((i + y) * image_width + j + x) / 8;
|
||
image_bit_idx = ((i + y) * image_width + j + x) % 8;
|
||
image[image_byte_idx] |= (((char_buf[char_byte_idx] >> (7 - char_bit_idx)) & 0x1) << (7 - image_bit_idx));
|
||
}
|
||
}
|
||
}
|
||
|
||
static void Font_Char_Rotate_90Reverse(FONT_CHAR_INFO *info)
|
||
{
|
||
u8 *in = info->pixelbuf;
|
||
u8 *out = image_buf_out;
|
||
u8 in_byte_idx, in_bit_idx;
|
||
u8 out_byte_idx, out_bit_idx;
|
||
u8 char_width = info->width;
|
||
u8 char_height = info->height;
|
||
memset(image_buf_out, 0, IMAGE_BUF_SIZE);
|
||
for (u16 h = 0; h < char_height; h++) {
|
||
for (u16 w = 0; w < char_width; w++) {
|
||
in_byte_idx = (h * char_width + w) / 8;
|
||
in_bit_idx = (h * char_width + w) % 8;
|
||
out_byte_idx = ((char_width - 1 - w) * char_height + h) / 8;
|
||
out_bit_idx = ((char_width - 1 - w) * char_height + h) % 8;
|
||
out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx));
|
||
}
|
||
}
|
||
u8 tmp = info->width;
|
||
info->width = info->height;
|
||
info->height = tmp;
|
||
memcpy(info->pixelbuf, image_buf_out, info->nbytes);
|
||
}
|
||
|
||
static void Font_Image_Rotate_180()
|
||
{
|
||
u8 *in = image_buf;
|
||
u8 *out = image_buf_out;
|
||
u8 in_byte_idx, in_bit_idx;
|
||
u8 out_byte_idx, out_bit_idx;
|
||
memset(image_buf_out, 0, IMAGE_BUF_SIZE);
|
||
for (u16 h = 0; h < LED_HEIGHT; h++) {
|
||
for (u16 w = 0; w < LED_WIDTH; w++) {
|
||
in_byte_idx = (h * LED_WIDTH + w) / 8;
|
||
in_bit_idx = (h * LED_WIDTH + w) % 8;
|
||
out_byte_idx = (LED_WIDTH * LED_HEIGHT / 8) - 1 - in_byte_idx;
|
||
out_bit_idx = (7 - in_bit_idx);
|
||
out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx));
|
||
}
|
||
}
|
||
}
|
||
|
||
static void Font_Image_Mirror_Horizontal_Flip(u8 *image)
|
||
{
|
||
u8 *in, *out;
|
||
if (image == image_buf) {
|
||
in = image_buf;
|
||
out = image_buf_out;
|
||
} else {
|
||
in = image_buf_out;
|
||
out = image_buf;
|
||
}
|
||
memset(out, 0, IMAGE_BUF_SIZE);
|
||
u8 in_byte_idx, in_bit_idx;
|
||
u8 out_byte_idx, out_bit_idx;
|
||
u16 in_bit, out_bit;
|
||
for (u16 h = 0; h < LED_HEIGHT; h++) {
|
||
for (u16 w = 0; w < LED_WIDTH; w++) {
|
||
in_bit = h * LED_WIDTH + w;
|
||
out_bit = h * LED_WIDTH + (LED_WIDTH - 1 - w);
|
||
in_byte_idx = in_bit / 8;
|
||
in_bit_idx = in_bit % 8;
|
||
out_byte_idx = out_bit / 8;
|
||
out_bit_idx = out_bit % 8;
|
||
out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx));
|
||
}
|
||
}
|
||
memcpy(in, out, IMAGE_BUF_SIZE);
|
||
}
|
||
|
||
static void Font_Image_Mirror_Vertical_Flip(u8 *image)
|
||
{
|
||
u8 *in, *out;
|
||
if (image == image_buf) {
|
||
in = image_buf;
|
||
out = image_buf_out;
|
||
} else {
|
||
in = image_buf_out;
|
||
out = image_buf;
|
||
}
|
||
memset(out, 0, IMAGE_BUF_SIZE);
|
||
u8 in_byte_idx, in_bit_idx;
|
||
u8 out_byte_idx, out_bit_idx;
|
||
u16 in_bit, out_bit;
|
||
for (u16 h = 0; h < LED_HEIGHT; h++) {
|
||
for (u16 w = 0; w < LED_WIDTH; w++) {
|
||
in_bit = h * LED_WIDTH + w;
|
||
out_bit = (LED_HEIGHT - 1 - h) * LED_WIDTH + w;
|
||
in_byte_idx = in_bit / 8;
|
||
in_bit_idx = in_bit % 8;
|
||
out_byte_idx = out_bit / 8;
|
||
out_bit_idx = out_bit % 8;
|
||
out[out_byte_idx] |= (((in[in_byte_idx] >> (7 - in_bit_idx)) & 0x1) << (7 - out_bit_idx));
|
||
}
|
||
}
|
||
memcpy(in, out, IMAGE_BUF_SIZE);
|
||
}
|
||
|
||
static u16 Font_GetStringWidth(u8 *utf8_buf, u16 len, FONT_LYRICS_INFO *lyrics_info)
|
||
{
|
||
u16 unicode, width;
|
||
u16 utf8_len = len;
|
||
u16 *utf16_buf = zalloc(utf8_len * 2);
|
||
u16 utf16_len = font_utf8toutf16(&f_info, utf8_buf, utf8_len, utf16_buf);
|
||
u16 unic_num = utf16_len / 2;
|
||
u16 sum_width = 0;
|
||
|
||
for (u16 n = 0; n < unic_num; n++) {
|
||
unicode = utf16_buf[n];
|
||
width = LRC_Font_GetCharWidth(&f_info, unicode);
|
||
if (width == 0) {
|
||
continue;
|
||
}
|
||
if (lyrics_info->rotate == LRC_FONT_ROTATE_90 || lyrics_info->rotate == LRC_FONT_ROTATE_270) {
|
||
width = char_info.height;
|
||
}
|
||
sum_width += width;
|
||
}
|
||
free(utf16_buf);
|
||
return sum_width;
|
||
}
|
||
|
||
void lrc_buf_push(u8 *buf, u16 size)
|
||
{
|
||
u8 *uartbuf = malloc(size + 1);
|
||
#if UI_LED_LRC_DECODE_FONT
|
||
uartbuf[0] = CMD_UART_UI_PIXEL_MATRIX;
|
||
#else
|
||
uartbuf[0] = CMD_UART_UI_STRING;
|
||
#endif
|
||
memcpy(uartbuf + 1, buf, size);
|
||
#if MUTIL_CPU_UART_UPDATE_ENABLE
|
||
if (!lrc_sleep_flag) {
|
||
uart_update_tx_packet(0, uartbuf, 0, size + 1, 0);
|
||
}
|
||
#endif
|
||
free(uartbuf);
|
||
}
|
||
|
||
void lrc_show_slepp_push(void)
|
||
{
|
||
u8 buf[1];
|
||
buf[0] = CMD_UART_SLEEP;
|
||
#if MUTIL_CPU_UART_UPDATE_ENABLE
|
||
if (!lrc_sleep_flag) {
|
||
uart_update_tx_packet(0, buf, 0, sizeof(buf), 1);
|
||
}
|
||
#endif
|
||
lrc_sleep_flag = 1;
|
||
}
|
||
|
||
void lrc_wake_up_push(void)
|
||
{
|
||
u8 buf[1];
|
||
buf[0] = 0XFF;
|
||
#if MUTIL_CPU_UART_UPDATE_ENABLE
|
||
uart_update_tx_packet(0, buf, 0, sizeof(buf), 1);
|
||
#endif
|
||
lrc_sleep_flag = 0;
|
||
}
|
||
|
||
#if (AD10X_WITHOUT_FLASH && LED_LYRICS_SH50_CHECK_ONLINE)
|
||
|
||
static u8 lrc_dev_check_online()
|
||
{
|
||
u8 ret = 0;
|
||
u8 packet = CMD_UART_CHECK_ONLINE;
|
||
|
||
#if MUTIL_CPU_UART_UPDATE_ENABLE
|
||
|
||
lrc_check_online_flag = 1;
|
||
if (!lrc_sleep_flag) {
|
||
ret = uart_update_tx_packet(CMD_UART_CHECK_ONLINE, &packet, 0, 1, 1);
|
||
}
|
||
|
||
#endif
|
||
|
||
if (ret != 0) {
|
||
if (!lrc_sleep_flag) {
|
||
ret = uart_update_tx_packet(CMD_UART_CHECK_ONLINE, &packet, 0, 1, 1);
|
||
}
|
||
if (ret != 0) {
|
||
lrc_check_online_flag = 0;
|
||
sh50_isp_up_code();
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
static u16 online_timer_id = 0;
|
||
|
||
void lrc_check_online_timer_init()
|
||
{
|
||
if (online_timer_id == 0) {
|
||
online_timer_id = sys_timer_add(NULL, lrc_dev_check_online, 3000);
|
||
}
|
||
}
|
||
|
||
void lrc_check_online_timer_release()
|
||
{
|
||
if (online_timer_id) {
|
||
sys_timer_del(online_timer_id);
|
||
online_timer_id = 0;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
void lrc_show_mode_push(LRC_SHOW_INFO *show_info)
|
||
{
|
||
u8 buf[5];
|
||
u8 rotate, flip, speed, brightness;
|
||
if (show_info) {
|
||
rotate = show_info->rotate;
|
||
flip = show_info->flip;
|
||
speed = show_info->scroll_speed / 50;
|
||
brightness = show_info->brightness;
|
||
} else {
|
||
rotate = 0;
|
||
flip = 0;
|
||
speed = 3;
|
||
brightness = 0;
|
||
}
|
||
buf[0] = CMD_UART_UI_CMD;
|
||
buf[1] = rotate;
|
||
buf[2] = flip;
|
||
buf[3] = speed;
|
||
buf[4] = brightness;
|
||
#if MUTIL_CPU_UART_UPDATE_ENABLE
|
||
if (!lrc_sleep_flag) {
|
||
uart_update_tx_packet(0, buf, 0, sizeof(buf), 1);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static void Font_GetStringBits(u8 *utf8_buf, u16 len, FONT_LYRICS_INFO *lyrics_info)
|
||
{
|
||
u8 curr_x = lyrics_info->center_offset;
|
||
u8 offset_y = 0;
|
||
u16 unicode, width;
|
||
u16 rec_scr_ofs = 0;
|
||
u8 curr_char_offset = 0;
|
||
u8 *font_ptr = image_buf;
|
||
u16 sum_char_offset = lyrics_info->scroll_offset;
|
||
memset(image_buf, 0, IMAGE_BUF_SIZE);
|
||
u16 utf8_len = len;
|
||
u16 *utf16_buf = zalloc(utf8_len * 2);
|
||
u16 utf16_len = font_utf8toutf16(&f_info, utf8_buf, utf8_len, utf16_buf);
|
||
u16 unic_num = utf16_len / 2;
|
||
|
||
for (u16 n = 0; n < unic_num; n++) {
|
||
unicode = utf16_buf[n];
|
||
width = LRC_Font_GetCharBits(&f_info, unicode);
|
||
if (width == 0) {
|
||
continue;
|
||
}
|
||
if (lyrics_info->rotate == LRC_FONT_ROTATE_0 || lyrics_info->rotate == LRC_FONT_ROTATE_180) {
|
||
curr_char_offset = width;
|
||
} else {
|
||
curr_char_offset = char_info.height;
|
||
}
|
||
rec_scr_ofs += curr_char_offset;
|
||
if (rec_scr_ofs < sum_char_offset) {
|
||
continue;
|
||
}
|
||
if (curr_x == 0) {
|
||
char_info.offsetx = sum_char_offset + curr_char_offset - rec_scr_ofs;
|
||
} else {
|
||
char_info.offsetx = 0;
|
||
}
|
||
if (curr_x > LED_WIDTH) {
|
||
break;
|
||
}
|
||
if (lyrics_info->rotate == LRC_FONT_ROTATE_90 || lyrics_info->rotate == LRC_FONT_ROTATE_270) {
|
||
Font_Char_Rotate_90Reverse(&char_info);
|
||
}
|
||
offset_y = (f_info.pixel.size - char_info.height) / 2;
|
||
Font_CharBit_to_Image(&char_info, image_buf, curr_x, offset_y);
|
||
curr_x += (char_info.width - char_info.offsetx);
|
||
}
|
||
if (lyrics_info->rotate == LRC_FONT_ROTATE_180 || lyrics_info->rotate == LRC_FONT_ROTATE_270) {
|
||
Font_Image_Rotate_180();
|
||
font_ptr = image_buf_out;
|
||
}
|
||
if (lyrics_info->flip == LRC_FONT_HORIZONTAL_FLIP) {
|
||
Font_Image_Mirror_Horizontal_Flip(font_ptr);
|
||
}
|
||
if (lyrics_info->flip == LRC_FONT_VERTICAL_FLIP) {
|
||
Font_Image_Mirror_Vertical_Flip(font_ptr);
|
||
}
|
||
|
||
lrc_buf_push(font_ptr, IMAGE_BUF_SIZE);
|
||
|
||
free(utf16_buf);
|
||
}
|
||
|
||
void lyrics_scroll_timer_del()
|
||
{
|
||
if (font_lyrics_scroll_timer_id) {
|
||
sys_timer_del(font_lyrics_scroll_timer_id);
|
||
font_lyrics_scroll_timer_id = 0;
|
||
}
|
||
}
|
||
|
||
static u8 lyrics_scroll_flag = 1;
|
||
|
||
static void lyrics_scroll_font(void *ptr)
|
||
{
|
||
os_mutex_pend(&show_mutex, 0);
|
||
LYRICS_UPDATE_INFO *info = (LYRICS_UPDATE_INFO *)ptr;
|
||
if (info->lyrics_info.scroll_offset > info->sum_width - LED_WIDTH + 3) {
|
||
info->lyrics_info.scroll_offset = 0;
|
||
/* 不从头滚动 */
|
||
if (info->sum_width > LED_WIDTH) {
|
||
lyrics_scroll_timer_del();
|
||
os_mutex_post(&show_mutex);
|
||
return;
|
||
}
|
||
/* 不从头滚动 */
|
||
}
|
||
Font_GetStringBits((u8 *)(info->str), info->len, &(info->lyrics_info));
|
||
if (info->sum_width > LED_WIDTH && lyrics_scroll_flag) {
|
||
info->lyrics_info.scroll_offset++;
|
||
}
|
||
os_mutex_post(&show_mutex);
|
||
}
|
||
|
||
void lyrics_scroll_control(u8 flag)
|
||
{
|
||
lyrics_scroll_flag = flag;
|
||
}
|
||
|
||
void lyrics_update_font(u8 *str, u16 len, LRC_SHOW_INFO *show_info)
|
||
{
|
||
#if UI_LED_LRC_DECODE_FONT
|
||
if (f_info.pixel.file.fd == NULL) {
|
||
printf("err, font file not open\n");
|
||
return;
|
||
}
|
||
#endif
|
||
u16 str_curr_crc;
|
||
static u16 str_last_crc = 0;
|
||
str_curr_crc = CRC16(str, len);
|
||
if (str_last_crc == str_curr_crc && lrc_status.lrc_show_status_update_flag == 0 && lrc_check_online_flag) {
|
||
return;
|
||
}
|
||
if (len == 0) {
|
||
lrc_status.lrc_show_status_update_flag = 0;
|
||
return;
|
||
}
|
||
os_mutex_pend(&show_mutex, 0);
|
||
/* 记录当前字符串内容和长度,在更新显示参数实时刷新时需要用到 */
|
||
if (lrc_status.lrc_record_str && lrc_status.lrc_show_status_update_flag == 0) {
|
||
free(lrc_status.lrc_record_str);
|
||
lrc_status.lrc_record_str = NULL;
|
||
}
|
||
if (lrc_status.lrc_record_str == NULL) {
|
||
lrc_status.lrc_record_str = zalloc(len);
|
||
}
|
||
lrc_status.lrc_record_len = len;
|
||
memcpy(lrc_status.lrc_record_str, str, len);
|
||
/* 记录当前字符串内容和长度,在更新显示参数实时刷新时需要用到 */
|
||
str_last_crc = str_curr_crc;
|
||
#if (UI_LED_LRC_DECODE_FONT == 0)
|
||
lrc_buf_push(str, len);
|
||
lrc_status.lrc_show_status_update_flag = 0;
|
||
os_mutex_post(&show_mutex);
|
||
return;
|
||
#endif
|
||
u16 scroll_speed;
|
||
u8 rotate, flip;
|
||
os_mutex_pend(&mutex, 0);
|
||
if (show_info == NULL) {
|
||
rotate = lrc_status.lrc_rotate;
|
||
flip = lrc_status.lrc_flip;
|
||
scroll_speed = lrc_status.lrc_scroll_speed;
|
||
} else {
|
||
rotate = show_info->rotate;
|
||
flip = show_info->flip;
|
||
scroll_speed = show_info->scroll_speed;
|
||
}
|
||
if (font_lyrics_scroll_timer_id) {
|
||
sys_timer_del(font_lyrics_scroll_timer_id);
|
||
font_lyrics_scroll_timer_id = 0;
|
||
}
|
||
if (lrc_update_info.str) {
|
||
free(lrc_update_info.str);
|
||
lrc_update_info.str = NULL;
|
||
}
|
||
lrc_update_info.str = malloc(len);
|
||
memcpy(lrc_update_info.str, str, len);
|
||
lrc_update_info.len = len;
|
||
lrc_update_info.lyrics_info.scroll_offset = 0;
|
||
lrc_update_info.lyrics_info.rotate = rotate;
|
||
lrc_update_info.lyrics_info.flip = flip;
|
||
lrc_update_info.sum_width = Font_GetStringWidth(lrc_update_info.str, len, &(lrc_update_info.lyrics_info));
|
||
lrc_update_info.lyrics_info.center_offset = (lrc_update_info.sum_width < LED_WIDTH) ? ((LED_WIDTH - lrc_update_info.sum_width) / 2) : 0;
|
||
|
||
os_mutex_post(&show_mutex);
|
||
if (lrc_update_info.sum_width <= LED_WIDTH) {
|
||
lyrics_scroll_font((void *)&lrc_update_info);
|
||
} else {
|
||
if (font_lyrics_scroll_timer_id == 0) {
|
||
font_lyrics_scroll_timer_id = sys_timer_add((void *)&lrc_update_info, lyrics_scroll_font, scroll_speed);
|
||
}
|
||
}
|
||
lrc_status.lrc_show_status_update_flag = 0;
|
||
os_mutex_post(&mutex);
|
||
}
|
||
|
||
int UnicodeToUtf8(u8 *pInput, u16 in_len, u8 *pOutput)
|
||
{
|
||
int len = 0; //记录转换后的Utf8字符串的字节数
|
||
int unic_cnt = 0;
|
||
while (unic_cnt < in_len) {
|
||
//处理一个unicode字符
|
||
u8 low = *pInput;//取出unicode字符的低8位
|
||
pInput++;
|
||
unic_cnt++;
|
||
u8 high = *pInput;//取出unicode字符的高8位
|
||
u16 w = high << 8;
|
||
u16 wchar = (high << 8) + low; //高8位和低8位组成一个unicode字符,加法运算级别高
|
||
|
||
if (wchar <= 0x7F) { //英文字符
|
||
pOutput[len] = (char)wchar; //取wchar的低8位
|
||
len++;
|
||
} else if (wchar >= 0x80 && wchar <= 0x7FF) { //可以转换成双字节pOutput字符
|
||
pOutput[len] = 0xc0 | ((wchar >> 6) & 0x1f); //取出unicode编码低6位后的5位,填充到110yyyyy 10zzzzzz 的yyyyy中
|
||
len++;
|
||
pOutput[len] = 0x80 | (wchar & 0x3f); //取出unicode编码的低6位,填充到110yyyyy 10zzzzzz 的zzzzzz中
|
||
len++;
|
||
} else if (wchar >= 0x800 && wchar < 0xFFFF) { //可以转换成3个字节的pOutput字符
|
||
pOutput[len] = 0xe0 | ((wchar >> 12) & 0x0f); //高四位填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx
|
||
len++;
|
||
pOutput[len] = 0x80 | ((wchar >> 6) & 0x3f); //中间6位填入1110xxxx 10yyyyyy 10zzzzzz中的yyyyyy
|
||
len++;
|
||
pOutput[len] = 0x80 | (wchar & 0x3f); //低6位填入1110xxxx 10yyyyyy 10zzzzzz中的zzzzzz
|
||
len++;
|
||
}
|
||
|
||
else { //对于其他字节数的unicode字符不进行处理
|
||
return -1;
|
||
}
|
||
pInput ++;//处理下一个unicode字符
|
||
unic_cnt++;
|
||
}
|
||
//utf8字符串后面,有个\0
|
||
pOutput [len] = 0;
|
||
return len;
|
||
}
|
||
|
||
void lyrics_update_unicbuf(u8 *unic, u16 len)
|
||
{
|
||
if (len == 0 || unic == NULL) {
|
||
return;
|
||
}
|
||
u8 *utf8 = (u8 *)zalloc(len * 2);
|
||
int utf8_len = UnicodeToUtf8(unic, len, utf8);
|
||
lyrics_update_font(utf8, utf8_len, NULL);
|
||
free(utf8);
|
||
}
|
||
|
||
void lyrics_update_gbk_to_utf8(u8 *gbk, u16 len)
|
||
{
|
||
if (len == 0 || gbk == NULL) {
|
||
return;
|
||
}
|
||
u8 *utf8 = (u8 *)zalloc(len * 2);
|
||
int utf8_len = gbk_2_utf8(gbk, len, utf8, len * 2);
|
||
lyrics_update_font(utf8, utf8_len, NULL);
|
||
free(utf8);
|
||
}
|
||
|
||
#endif
|
||
|