KT26-0607_AC695n-BTE-SDK312/apps/soundbox/ui/led_lyric/led_lyric.c

815 lines
24 KiB
C
Raw Normal View History

2026-06-07 11:38:16 +00:00
#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