pure sdk for main
This commit is contained in:
@@ -0,0 +1,509 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "lib/video/dvp/cmos_sensor/csi.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "hal/lcdc.h"
|
||||
#include "hal/spi.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/string.h"
|
||||
#include "dev/vpp/hgvpp.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "dev/lcdc/hglcdc.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/msgqueue.h"
|
||||
#include "osal/task.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "lib/lcd/gui.h"
|
||||
#include "lib/vef/video_ef.h"
|
||||
#include "stream_frame.h"
|
||||
#include "decode/recv_jpg_yuv_demo.h"
|
||||
#include "decode/jpg_decode_stream.h"
|
||||
#include "app_lcd.h"
|
||||
#include "app_lcd/osd_encode_stream.h"
|
||||
#ifdef LCD_EN
|
||||
|
||||
|
||||
#define LCD_ROTATE_LINE 32
|
||||
|
||||
#define OSD_EN 1
|
||||
struct app_lcd_s lcd_msg_s;
|
||||
|
||||
void lcd_hardware_init565();
|
||||
void lcd_hardware_init666();
|
||||
extern void lcd_register_read_3line(struct spi_device *spi_dev,uint32 code, uint8* buf, uint32 len);
|
||||
extern void lcd_table_init(struct spi_device *spi_dev,uint8_t *lcd_table);
|
||||
extern void lcd_table_init_MCU(struct lcdc_device *lcd_dev,uint8_t (*lcd_table)[2]);
|
||||
|
||||
static void lcd_osd_isr1(uint32 irq_flag,uint32 irq_data,uint32 param1)
|
||||
{
|
||||
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
//struct lcdc_device *p_lcd = (struct lcdc_device *)irq_data;
|
||||
struct app_lcd_s *lcd_s= (struct app_lcd_s *)irq_data;
|
||||
struct lcdc_device *lcd_dev;
|
||||
stream *s = (stream*)lcd_s->encode_osd_s;
|
||||
lcd_dev = lcd_s->lcd_dev;//stream_self_cmd_func(s,0x05,0);
|
||||
//os_printf("lcd_dev:%X\n",lcd_dev);
|
||||
int32_t val = lcdc_get_con(lcd_dev);
|
||||
//硬件没有准备好
|
||||
if(val & BIT(3))
|
||||
{
|
||||
return;
|
||||
}
|
||||
stream_self_cmd_func(s,OSD_HARDWARE_ENCODE_SET_LEN,lcdc_get_osd_enc_dst_len(lcd_dev));
|
||||
stream_self_cmd_func(s,OSD_HARDWARE_REAY_CMD,1);
|
||||
//lcd_sema_up();
|
||||
}
|
||||
|
||||
//暂时没有作处理
|
||||
static void lcd_timeout1(uint32 irq_flag,uint32 irq_data,uint32 param1){
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
struct app_lcd_s *lcd_s= (struct app_lcd_s *)irq_data;
|
||||
struct lcdc_device *lcd_dev = lcd_s->lcd_dev;
|
||||
//lcdc_set_timeout_info(lcd_dev,0,3);
|
||||
//gpio_set_val(PC_7,pc_7);
|
||||
//pc_7 ^= BIT(0);
|
||||
|
||||
lcdc_close(lcd_dev);
|
||||
os_printf("........................................................................................................................lcd_timeout\r\n");
|
||||
//出现timeout,说明可能哪里卡住了,让应用层重新启动
|
||||
lcdc_open(lcd_dev);
|
||||
//lcd_s->hardware_ready = 1;
|
||||
//lcdc_open(lcd_dev);
|
||||
lcdc_set_start_run(lcd_dev);
|
||||
}
|
||||
|
||||
//暂时没有作处理
|
||||
static void lcd_te_isr1(uint32 irq_flag,uint32 irq_data,uint32 param1){
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
struct app_lcd_s *lcd_s= (struct app_lcd_s *)irq_data;
|
||||
struct lcdc_device *lcd_dev;
|
||||
lcd_dev = lcd_s->lcd_dev;
|
||||
os_printf("--------------------------------------------te---------------------------------\r\n");
|
||||
}
|
||||
|
||||
static void lcd_squralbuf_done1(uint32 irq_flag,uint32 irq_data,uint32 param1)
|
||||
{
|
||||
struct app_lcd_s *lcd_s= (struct app_lcd_s *)irq_data;
|
||||
//理论这里只是唤醒信号量之类,由线程来决定是否继续显示
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(lcd_s->hardware_auto_ks)
|
||||
{
|
||||
lcd_s->hardware_ready = 0;
|
||||
//判断是否启动了硬件自动kick
|
||||
if(!lcd_s->get_auto_ks)
|
||||
{
|
||||
//启动自动kick
|
||||
lcd_s->get_auto_ks = 1;
|
||||
lcdc_video_enable_auto_ks(lcd_s->lcd_dev, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lcd_s->get_auto_ks)
|
||||
{
|
||||
lcd_s->get_auto_ks = 0;
|
||||
lcdc_video_enable_auto_ks(lcd_s->lcd_dev, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_s->hardware_ready = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t g_read_hardware_auto_ks()
|
||||
{
|
||||
// os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
return lcd_msg_s.get_auto_ks;
|
||||
}
|
||||
|
||||
uint8_t g_set_hardware_auto_ks(uint8_t en)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t timeout = 0;
|
||||
if(en)
|
||||
{
|
||||
lcd_msg_s.hardware_auto_ks = en;
|
||||
while(!lcd_msg_s.get_auto_ks && (timeout < 100))
|
||||
{
|
||||
timeout++;
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = disable_irq();
|
||||
lcd_msg_s.hardware_auto_ks = en;
|
||||
enable_irq(flags);
|
||||
}
|
||||
|
||||
return lcd_msg_s.get_auto_ks;
|
||||
}
|
||||
|
||||
|
||||
//返回的是osd旋转和w h
|
||||
static void get_osd_w_h(uint16_t *w,uint16_t *h,uint8_t *rotate)
|
||||
{
|
||||
*w = lcdstruct.osd_w;
|
||||
*h = lcdstruct.osd_h;
|
||||
*rotate = lcdstruct.osd_scan_mode;
|
||||
}
|
||||
|
||||
//返回屏幕的size和旋转角度
|
||||
static void get_screen_w_h(uint16_t *screen_w,uint16_t *screen_h,uint8_t *video_rotate)
|
||||
{
|
||||
*screen_w = lcdstruct.screen_w;
|
||||
*screen_h = lcdstruct.screen_h;
|
||||
*video_rotate = lcdstruct.scan_mode;
|
||||
}
|
||||
|
||||
//注意,这部分不同屏以及硬件设计不一样,需要修改
|
||||
void lcd_hardware_init(uint16_t *w,uint16_t *h,uint8_t *rotate,uint16_t *screen_w,uint16_t *screen_h,uint8_t *video_rotate)
|
||||
{
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
if(lcdstruct.color_mode == LCD_MODE_666)
|
||||
{
|
||||
lcd_hardware_init666();
|
||||
}
|
||||
else if(lcdstruct.color_mode == LCD_MODE_565)
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
}
|
||||
else if(lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
|
||||
//返回osd的w和h
|
||||
get_osd_w_h(w,h,rotate);
|
||||
get_screen_w_h(screen_w,screen_h,video_rotate);
|
||||
}
|
||||
|
||||
//主要硬件初始化,但由于存在rgb屏,还是会有部分寄存器需要配置
|
||||
void lcd_hardware_init565()
|
||||
{
|
||||
uint8 pixel_dot_num = 1;
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct spi_device *spi_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
spi_dev = (struct spi_device * )dev_get(HG_SPI0_DEVID);
|
||||
if(PIN_LCD_RESET != 255){
|
||||
gpio_iomap_output(PIN_LCD_RESET,GPIO_IOMAP_OUTPUT);
|
||||
gpio_set_val(PIN_LCD_RESET,0);
|
||||
os_sleep_ms(100);
|
||||
gpio_set_val(PIN_LCD_RESET,1);
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
|
||||
uint8 spi_buf[10];
|
||||
if(lcdstruct.init_table != NULL){
|
||||
spi_open(spi_dev, 1000000, SPI_MASTER_MODE, SPI_WIRE_SINGLE_MODE, SPI_CPOL_1_CPHA_1);
|
||||
spi_ioctl(spi_dev,SPI_SET_FRAME_SIZE,9,0);
|
||||
//lcd spi_cfg
|
||||
_os_printf("read lcd id(%x)\r\n",(unsigned int)spi_dev);
|
||||
lcd_register_read_3line(spi_dev,0xda,spi_buf,4);
|
||||
_os_printf("***ID:%02x %02x %02x %02x\r\n", spi_buf[0], spi_buf[1], spi_buf[2], spi_buf[3]);
|
||||
|
||||
lcd_table_init(spi_dev,(uint8_t *)lcdstruct.init_table);
|
||||
gpio_set_val(PIN_SPI0_CS,1);
|
||||
gpio_iomap_output(PIN_SPI0_CS,GPIO_IOMAP_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
//scale_to_lcd_config();
|
||||
lcdc_init(lcd_dev);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_open(lcd_dev);
|
||||
}
|
||||
lcdc_set_color_mode(lcd_dev,lcdstruct.color_mode);
|
||||
lcdc_set_bus_width(lcd_dev,lcdstruct.bus_width);
|
||||
lcdc_set_interface(lcd_dev,lcdstruct.lcd_bus_type);
|
||||
lcdc_set_colrarray(lcd_dev,lcdstruct.colrarray);
|
||||
pixel_dot_num = lcdstruct.color_mode/lcdstruct.bus_width;
|
||||
lcdc_set_lcd_vaild_size(lcd_dev,lcdstruct.screen_w+lcdstruct.hlw+lcdstruct.hbp+lcdstruct.hfp,lcdstruct.screen_h+lcdstruct.vlw+lcdstruct.vbp+lcdstruct.vfp,pixel_dot_num);
|
||||
lcdc_set_lcd_visible_size(lcd_dev,lcdstruct.screen_w,lcdstruct.screen_h,pixel_dot_num);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_mcu_signal_config(lcd_dev,lcdstruct.signal_config.value);
|
||||
}
|
||||
else if(lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
lcdc_signal_config(lcd_dev,lcdstruct.vs_en,lcdstruct.hs_en,lcdstruct.de_en,lcdstruct.vs_inv,lcdstruct.hs_inv,lcdstruct.de_inv,lcdstruct.pclk_inv);
|
||||
lcdc_set_invalid_line(lcd_dev,lcdstruct.vlw);
|
||||
lcdc_set_valid_dot(lcd_dev,lcdstruct.hlw+lcdstruct.hbp,lcdstruct.vlw+lcdstruct.vbp);
|
||||
lcdc_set_hlw_vlw(lcd_dev,lcdstruct.hlw,0);
|
||||
}
|
||||
lcdc_set_baudrate(lcd_dev,lcdstruct.pclk);
|
||||
lcdc_set_bigendian(lcd_dev,1);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcd_table_init_MCU(lcd_dev,lcdstruct.init_table);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lcd_hardware_init666()
|
||||
{
|
||||
uint8 pixel_dot_num = 1;
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct spi_device *spi_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
spi_dev = (struct spi_device * )dev_get(HG_SPI0_DEVID);
|
||||
if(PIN_LCD_RESET != 255){
|
||||
gpio_iomap_output(PIN_LCD_RESET,GPIO_IOMAP_OUTPUT);
|
||||
gpio_set_val(PIN_LCD_RESET,0);
|
||||
os_sleep_ms(100);
|
||||
gpio_set_val(PIN_LCD_RESET,1);
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
|
||||
uint8 spi_buf[10];
|
||||
if(lcdstruct.init_table != NULL){
|
||||
spi_open(spi_dev, 1000000, SPI_MASTER_MODE, SPI_WIRE_SINGLE_MODE, SPI_CPOL_1_CPHA_1);
|
||||
spi_ioctl(spi_dev,SPI_SET_FRAME_SIZE,9,0);
|
||||
//lcd spi_cfg
|
||||
_os_printf("read lcd id(%x)\r\n",(unsigned int)spi_dev);
|
||||
lcd_register_read_3line(spi_dev,0xda,spi_buf,4);
|
||||
_os_printf("***ID:%02x %02x %02x %02x\r\n", spi_buf[0], spi_buf[1], spi_buf[2], spi_buf[3]);
|
||||
|
||||
lcd_table_init(spi_dev,(uint8_t *)lcdstruct.init_table);
|
||||
gpio_set_val(PIN_SPI0_CS,1);
|
||||
gpio_iomap_output(PIN_SPI0_CS,GPIO_IOMAP_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
//scale_to_lcd_config();
|
||||
lcdc_init(lcd_dev);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_open(lcd_dev);
|
||||
}
|
||||
lcdc_set_color_mode(lcd_dev,lcdstruct.color_mode);
|
||||
lcdc_set_bus_width(lcd_dev,lcdstruct.bus_width);
|
||||
lcdc_set_interface(lcd_dev,lcdstruct.lcd_bus_type);
|
||||
lcdc_set_colrarray(lcd_dev,lcdstruct.colrarray);
|
||||
pixel_dot_num = lcdstruct.color_mode/lcdstruct.bus_width;
|
||||
lcdc_set_lcd_vaild_size(lcd_dev,lcdstruct.screen_w+lcdstruct.hlw+lcdstruct.hbp+lcdstruct.hfp,lcdstruct.screen_h+lcdstruct.vlw+lcdstruct.vbp+lcdstruct.vfp,pixel_dot_num);
|
||||
lcdc_set_lcd_visible_size(lcd_dev,lcdstruct.screen_w,lcdstruct.screen_h,3);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_mcu_signal_config(lcd_dev,lcdstruct.signal_config.value);
|
||||
}
|
||||
else if(lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
lcdc_signal_config(lcd_dev,lcdstruct.vs_en,lcdstruct.hs_en,lcdstruct.de_en,lcdstruct.vs_inv,lcdstruct.hs_inv,lcdstruct.de_inv,lcdstruct.pclk_inv);
|
||||
lcdc_set_invalid_line(lcd_dev,lcdstruct.vlw);
|
||||
lcdc_set_valid_dot(lcd_dev,lcdstruct.hlw+lcdstruct.hbp,lcdstruct.vlw+lcdstruct.vbp);
|
||||
lcdc_set_hlw_vlw(lcd_dev,lcdstruct.hlw,0);
|
||||
}
|
||||
lcdc_set_baudrate(lcd_dev,lcdstruct.pclk);
|
||||
lcdc_set_bigendian(lcd_dev,1);
|
||||
if(lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcd_table_init_MCU(lcd_dev,lcdstruct.init_table);
|
||||
}
|
||||
|
||||
//gamma表之类没有配置,这个考虑是放在其他地方,这个函数专注硬件的初始化好了
|
||||
|
||||
#if 0
|
||||
lcdc_video_enable_gamma(lcd_dev, 1);
|
||||
lcdc_video_enable_ccm(lcd_dev, 1);
|
||||
lcdc_video_enable_constarast(lcd_dev, 1);
|
||||
lcdc_video_set_CCM_COEF0(lcd_dev, 0x00df0100);
|
||||
lcdc_video_set_CCM_COEF1(lcd_dev, 0x0003b3f3);
|
||||
lcdc_video_set_CCM_COEF2(lcd_dev, 0x0df0000d);
|
||||
lcdc_video_set_CCM_COEF3(lcd_dev, 0x00000000);
|
||||
lcdc_video_set_constarast_val(lcd_dev, 0x12);
|
||||
lcdc_video_set_gamma_R(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
lcdc_video_set_gamma_G(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
lcdc_video_set_gamma_B(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
#endif
|
||||
|
||||
lcdc_set_bus_width(lcd_dev,LCD_BUS_WIDTH_6);
|
||||
gpio_iomap_output(LCD_D0, GPIO_IOMAP_OUTPUT);
|
||||
gpio_iomap_output(LCD_D1, GPIO_IOMAP_OUTPUT);
|
||||
gpio_iomap_inout(LCD_D2, GPIO_IOMAP_IN_LCD_D0_IN_MASK1_19,2);
|
||||
gpio_iomap_inout(LCD_D3, GPIO_IOMAP_IN_LCD_D1_IN_MASK1_20,8);
|
||||
gpio_iomap_inout(LCD_D4, GPIO_IOMAP_IN_LCD_D2_IN_MASK1_21,9);
|
||||
gpio_iomap_inout(LCD_D5, GPIO_IOMAP_IN_STMR0_CAP_IN__LCD_D3_IN_MASK1_22,10);
|
||||
gpio_iomap_inout(LCD_D6, GPIO_IOMAP_IN_STMR1_CAP_IN__LCD_D4_IN_MASK1_23,11);
|
||||
gpio_iomap_inout(LCD_D7, GPIO_IOMAP_IN_STMR2_CAP_IN__LCD_D5_IN_MASK1_24,12);
|
||||
|
||||
}
|
||||
|
||||
//lcd相关参数配置,w、h、rotate
|
||||
void lcd_arg_setting(uint16_t w,uint16_t h,uint8_t rotate,uint16_t screen_w,uint16_t screen_h,uint8_t video_rotate)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->w = w;
|
||||
lcd_s->h = h;
|
||||
lcd_s->rotate = rotate;
|
||||
lcd_s->screen_w = screen_w;
|
||||
lcd_s->screen_h = screen_h;
|
||||
lcd_s->video_rotate = video_rotate;
|
||||
}
|
||||
|
||||
//芯片lcd的驱动初始化
|
||||
void lcd_driver_init(void *s1,void *s2,void *s3,void *s4)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->hardware_ready = 1;
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->hardware_auto_ks = 0;
|
||||
lcd_s->get_auto_ks = 0;
|
||||
lcd_s->encode_osd_s = s1;
|
||||
lcd_s->osd_show_s = s2;
|
||||
lcd_s->video_p1_s = s3;
|
||||
lcd_s->video_p0_s = s4;
|
||||
|
||||
|
||||
struct lcdc_device *lcd_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
|
||||
lcd_s->lcd_dev = lcd_dev;
|
||||
|
||||
|
||||
lcdc_set_video_size(lcd_dev,lcdstruct.video_w,lcdstruct.video_h);
|
||||
|
||||
|
||||
lcdc_set_rotate_p0_up(lcd_dev,0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_dev,0,0,0,0);
|
||||
|
||||
|
||||
lcdc_set_rotate_linebuf_num(lcd_dev,LCD_ROTATE_LINE);
|
||||
lcd_s->line_buf_num = LCD_ROTATE_LINE;
|
||||
lcdc_set_video_data_from(lcd_dev,VIDEO_FROM_MEMORY_ROTATE);
|
||||
|
||||
|
||||
lcdc_set_video_start_location(lcd_dev,lcdstruct.video_x,lcdstruct.video_y);
|
||||
lcdc_set_video_en(lcd_dev,0);
|
||||
|
||||
|
||||
//设置默认值,因为这个一定要配置,并且地址与p1的地址范围要一样(就是全部是psram或者全部是sram,所以这里最好都是设置psram)
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
|
||||
lcdc_set_osd_start_location(lcd_dev,lcdstruct.osd_x,lcdstruct.osd_y);
|
||||
lcdc_set_osd_size(lcd_dev,lcdstruct.osd_w,lcdstruct.osd_h);
|
||||
lcdc_set_osd_format(lcd_dev,OSD_RGB_565);
|
||||
|
||||
lcdc_set_osd_alpha(lcd_dev,0x100);
|
||||
lcdc_set_osd_enc_head(lcd_dev,0xFFFFFF,0xFFFBFF);
|
||||
lcdc_set_osd_enc_diap(lcd_dev,0x000000,0x000000);
|
||||
lcdc_set_osd_en(lcd_dev,0);
|
||||
|
||||
lcdc_video_enable_auto_ks(lcd_dev,0);
|
||||
lcdc_set_timeout_info(lcd_dev,1,3);
|
||||
|
||||
lcdc_request_irq(lcd_dev,LCD_DONE_IRQ,(lcdc_irq_hdl )&lcd_squralbuf_done1,(uint32)lcd_s);
|
||||
|
||||
lcdc_request_irq(lcd_dev,OSD_EN_IRQ, (lcdc_irq_hdl )&lcd_osd_isr1,(uint32)lcd_s);
|
||||
lcdc_request_irq(lcd_dev,TIMEOUT_IRQ,(lcdc_irq_hdl )&lcd_timeout1,(uint32)lcd_s);
|
||||
#if (LCD_TE != 255)
|
||||
lcdc_set_te_edge(lcd_dev,1);
|
||||
lcdc_request_irq(lcd_dev,LCD_TE_IRQ,(lcdc_irq_hdl )&lcd_te_isr1,(uint32)lcd_s);
|
||||
#endif
|
||||
lcdc_open(lcd_dev);
|
||||
|
||||
extern void lcd_thread(void *d);
|
||||
lcd_s->thread_hdl = os_task_create("lcd_thread", lcd_thread, lcd_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
|
||||
|
||||
void wait_lcd_exit()
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->thread_exit = 1;
|
||||
while(lcd_s->thread_hdl)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
//重复初始化,一般用于意外断电或者说休眠起来后使用
|
||||
void lcd_driver_reinit()
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->hardware_ready = 1;
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->hardware_auto_ks = 0;
|
||||
lcd_s->get_auto_ks = 0;
|
||||
struct lcdc_device *lcd_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
|
||||
lcd_s->lcd_dev = lcd_dev;
|
||||
|
||||
lcdc_set_video_size(lcd_dev,lcdstruct.video_w,lcdstruct.video_h);
|
||||
|
||||
//VIDEO
|
||||
lcdc_set_rotate_p0_up(lcd_dev,0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_dev,0,0,0,0);
|
||||
//line_buf后续再分配
|
||||
lcdc_set_rotate_linebuf_num(lcd_dev,LCD_ROTATE_LINE);
|
||||
lcdc_set_video_data_from(lcd_dev,VIDEO_FROM_MEMORY_ROTATE);
|
||||
lcdc_set_video_start_location(lcd_dev,lcdstruct.video_x,lcdstruct.video_y);
|
||||
lcdc_set_video_en(lcd_dev,0);
|
||||
|
||||
|
||||
//设置默认值,因为这个一定要配置,并且地址与p1的地址范围要一样(就是全部是psram或者全部是sram,所以这里最好都是设置psram)
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev,(uint32)0x38000000);
|
||||
|
||||
|
||||
|
||||
|
||||
//OSD
|
||||
lcdc_set_osd_start_location(lcd_dev,lcdstruct.osd_x,lcdstruct.osd_y);
|
||||
lcdc_set_osd_size(lcd_dev,lcdstruct.osd_w,lcdstruct.osd_h);
|
||||
lcdc_set_osd_format(lcd_dev,OSD_RGB_565);
|
||||
lcdc_set_osd_alpha(lcd_dev,0x100);
|
||||
lcdc_set_osd_enc_head(lcd_dev,0xFFFFFF,0xFFFBFF);
|
||||
lcdc_set_osd_enc_diap(lcd_dev,0x000000,0x000000);
|
||||
lcdc_set_osd_en(lcd_dev,0);
|
||||
|
||||
|
||||
|
||||
lcdc_video_enable_auto_ks(lcd_dev,0);
|
||||
lcdc_set_timeout_info(lcd_dev,1,3);
|
||||
|
||||
lcdc_request_irq(lcd_dev,LCD_DONE_IRQ,(lcdc_irq_hdl )&lcd_squralbuf_done1,(uint32)lcd_s);
|
||||
|
||||
lcdc_request_irq(lcd_dev,OSD_EN_IRQ, (lcdc_irq_hdl )&lcd_osd_isr1,(uint32)lcd_s);
|
||||
lcdc_request_irq(lcd_dev,TIMEOUT_IRQ,(lcdc_irq_hdl )&lcd_timeout1,(uint32)lcd_s);
|
||||
#if (LCD_TE != 255)
|
||||
lcdc_set_te_edge(lcd_dev,1);
|
||||
lcdc_request_irq(lcd_dev,LCD_TE_IRQ,(lcdc_irq_hdl )&lcd_te_isr1,(uint32)lcd_s);
|
||||
#endif
|
||||
lcdc_open(lcd_dev);
|
||||
//lcdc_set_start_run(lcd_dev);
|
||||
|
||||
|
||||
extern void lcd_thread(void *d);
|
||||
lcd_s->thread_hdl = os_task_create("lcd_thread", lcd_thread, (void*)lcd_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef __APP_LCD_H
|
||||
#define __APP_LCD_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
#include "hal/lcdc.h"
|
||||
#include "hal/spi.h"
|
||||
|
||||
struct app_lcd_s
|
||||
{
|
||||
stream *encode_osd_s;
|
||||
stream *osd_show_s;
|
||||
stream *video_p1_s;
|
||||
stream *video_p0_s;
|
||||
struct lcdc_device *lcd_dev;
|
||||
//只有thread_hdl退出后,才可以休眠
|
||||
void *thread_hdl;
|
||||
void *line_buf;
|
||||
uint16_t w,h;
|
||||
uint16_t screen_w,screen_h;
|
||||
uint8_t line_buf_num;
|
||||
uint8_t rotate;
|
||||
uint8_t video_rotate;
|
||||
uint8_t hardware_auto_ks:1; //由应用层写入,由lcd模块读取
|
||||
uint8_t get_auto_ks:1; //由应用层去读取,由lcd的模块去设置
|
||||
uint8_t hardware_ready:1;
|
||||
uint8_t thread_exit:1;
|
||||
|
||||
|
||||
};
|
||||
extern struct app_lcd_s lcd_msg_s;
|
||||
|
||||
void lcd_arg_setting(uint16_t w,uint16_t h,uint8_t rotate,uint16_t screen_w,uint16_t screen_h,uint8_t video_rotate);
|
||||
void lcd_driver_init(void *s1,void *s2,void *s3,void *s4);
|
||||
void wait_lcd_exit();
|
||||
void lcd_driver_reinit();
|
||||
void lcd_hardware_init(uint16_t *w,uint16_t *h,uint8_t *rotate,uint16_t *screen_w,uint16_t *screen_h,uint8_t *video_rotate);
|
||||
uint8_t g_read_hardware_auto_ks();
|
||||
uint8_t g_set_hardware_auto_ks(uint8_t en);
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/task.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "osal/work.h"
|
||||
|
||||
|
||||
uint32_t rgb_limit(int32_t val)
|
||||
{
|
||||
if(val > 255)
|
||||
return 255;
|
||||
else if(val < 0)
|
||||
return 0;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
void *yuv2rgb(uint8_t *inbuf, uint32_t width, uint32_t height)
|
||||
{
|
||||
uint16_t *outbuf = (uint16_t *)custom_malloc_psram(width*height*2);
|
||||
if(!outbuf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *ybuf = inbuf;
|
||||
uint8_t *ubuf = inbuf+width*height;
|
||||
uint8_t *vbuf = inbuf+width*height+width*height/4;
|
||||
int32_t temp = 0;
|
||||
int16_t y=0;
|
||||
int16_t u,v;
|
||||
uint8_t r,g,b;
|
||||
uint32_t uv_w = width/2;
|
||||
uint32_t uv_w_temp = 0;
|
||||
uint32_t uv_h_temp = 0;
|
||||
|
||||
for(uint32_t i=0; i<height; i++) {
|
||||
for(uint32_t j=0; j<width; j++) {
|
||||
uv_w_temp = j/2;
|
||||
uv_h_temp = i/2;
|
||||
y = ybuf[i*width+j];
|
||||
u = ubuf[uv_h_temp*uv_w+uv_w_temp]-128;
|
||||
v = vbuf[uv_h_temp*uv_w+uv_w_temp]-128;
|
||||
temp = ((y<<10) + 1441*v)>>10;
|
||||
r = (uint8_t)rgb_limit(temp);
|
||||
temp = ((y<<10) - 354*u -734*v)>>10;
|
||||
g = (uint8_t)rgb_limit(temp);
|
||||
temp = ((y<<10) + 1842*u)>>10;
|
||||
b = (uint8_t)rgb_limit(temp);
|
||||
|
||||
outbuf[i*width+j] = ((r&0xF8)<<8)+((g&0xFC)<<3)+((b&0xF8)>>3);
|
||||
}
|
||||
}
|
||||
return outbuf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct jpg_to_rgb_s
|
||||
{
|
||||
struct os_work work;
|
||||
stream *s;
|
||||
};
|
||||
static int32 jpg_to_rgb_work(struct os_work *work)
|
||||
{
|
||||
//static int flag = 0;
|
||||
struct jpg_to_rgb_s *jpg_to_rgb = (struct jpg_to_rgb_s *)work;
|
||||
struct data_structure *data_s;
|
||||
data_s = recv_real_data(jpg_to_rgb->s);
|
||||
if(data_s)
|
||||
{
|
||||
#if 0
|
||||
if(!flag)
|
||||
{
|
||||
flag = 1;
|
||||
//写卡
|
||||
{
|
||||
#if 0
|
||||
void *fp = osal_fopen("0:my.lv","wb");
|
||||
os_printf("%s:%d\tfp:%X\n",__FUNCTION__,__LINE__,fp);
|
||||
if(fp)
|
||||
{
|
||||
osal_fwrite(get_stream_real_data(data_s),1,get_stream_real_data_len(data_s),fp);
|
||||
osal_fclose(fp);
|
||||
}
|
||||
#else
|
||||
void *rgb_buf = yuv2rgb(get_stream_real_data(data_s),64,64);
|
||||
os_printf("%s:%d\trgb_buf:%X\n",__FUNCTION__,__LINE__,rgb_buf);
|
||||
if(rgb_buf)
|
||||
{
|
||||
save_fs_lv_img_lzo("0:my.lv",rgb_buf,64,64,1);
|
||||
custom_free_psram(rgb_buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free_data(data_s);
|
||||
os_printf("!!!!!!!!!!!!!!!!!%s:%d\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = (void*)custom_zalloc(sizeof(struct jpg_to_rgb_s));
|
||||
struct jpg_to_rgb_s *jpg_to_rgb = (struct jpg_to_rgb_s *)s->priv;
|
||||
jpg_to_rgb->s = s;
|
||||
OS_WORK_INIT(&jpg_to_rgb->work, jpg_to_rgb_work, 0);
|
||||
os_run_work_delay(&jpg_to_rgb->work, 1);
|
||||
|
||||
enable_stream(s,1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_RECV_DATA_FINISH:
|
||||
break;
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//os_printf("%s:%d\tdata:%X\n",__FUNCTION__,__LINE__,data);
|
||||
if(GET_DATA_TYPE1(data->type) != YUV || GET_DATA_TYPE2(data->type) != LVGL_JPEG_TO_RGB)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//流接收后,数据包也要检查是否需要过滤或者是不是因为逻辑条件符合需要过滤
|
||||
case STREAM_RECV_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
//os_printf("type1:%d\ttype2:%d\n",GET_DATA_TYPE1(data->type),GET_DATA_TYPE2(data->type));
|
||||
if(GET_DATA_TYPE1(data->type) != YUV)
|
||||
{
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
//先特殊处理一下某些帧不显示,遇到是需要转换rgb的,就不要接收
|
||||
if(GET_DATA_TYPE2(data->type) != LVGL_JPEG_TO_RGB)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
stream *YUV_TO_RGB_stream(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,0,2,opcode_func,NULL);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/work.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "app_lcd.h"
|
||||
#include "decode/recv_jpg_yuv_demo.h"
|
||||
#include "yuv_stream.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
|
||||
//创建一个线程,专门是处理lcd显示
|
||||
struct osd_show_s
|
||||
{
|
||||
struct lcdc_device *lcd_dev;
|
||||
stream *s;
|
||||
struct data_structure *last_show_data_s;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//如果说workqueue确定没有一些耗时的任务,这个也是可以放到workqueue去处理,节省线程的内存
|
||||
void lcd_thread(void *d)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *)d;
|
||||
struct lcdc_device *lcd_dev = lcd_s->lcd_dev;
|
||||
stream *p1_s = lcd_s->video_p1_s;
|
||||
stream *p0_s = lcd_s->video_p0_s;
|
||||
stream *s = lcd_s->osd_show_s;
|
||||
struct osd_show_s *osd_show = (struct osd_show_s *)s->priv;
|
||||
struct recv_jpg_yuv_s *yuv_p1 = (struct recv_jpg_yuv_s *)p1_s->priv;
|
||||
|
||||
struct yuv_stream_s *yuv_p0 = (struct yuv_stream_s *)p0_s->priv;
|
||||
|
||||
struct data_structure *osd_data_s;
|
||||
struct data_structure *video_p1_data_s;
|
||||
struct data_structure *video_p0_data_s;
|
||||
|
||||
uint32_t p0_w=0,p0_h=0,p1_w=0,p1_h=0;
|
||||
struct yuv_arg_s *yuv_msg;
|
||||
uint32_t y_off = 0,uv_off = 0;
|
||||
|
||||
|
||||
//是否要启动显示,只要有osd或者video显示,都要启动硬件模块
|
||||
//如果是mcu屏,内部可以增加其他逻辑,判断显示是否有变化决定是否刷屏
|
||||
//如果是rgb屏,无论内容是否发生变化,都要刷新,否则会有问题
|
||||
uint8_t flag = 0;
|
||||
uint8_t p0_p1_enable = 0;
|
||||
while(!lcd_s->thread_exit)
|
||||
{
|
||||
//ready
|
||||
p0_p1_enable = 0;
|
||||
if(lcd_s->hardware_ready)
|
||||
{
|
||||
//显示osd
|
||||
{
|
||||
osd_data_s = recv_real_data(s);
|
||||
if(osd_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tosd_data_s:%X\n",__FUNCTION__,__LINE__,osd_data_s);
|
||||
if(osd_show->last_show_data_s)
|
||||
{
|
||||
free_data(osd_show->last_show_data_s);
|
||||
osd_show->last_show_data_s = NULL;
|
||||
}
|
||||
osd_show->last_show_data_s = osd_data_s;
|
||||
}
|
||||
else
|
||||
{
|
||||
osd_data_s = osd_show->last_show_data_s;
|
||||
}
|
||||
//os_printf("data_s len:%d\t%X\n",get_stream_real_data_len(osd_data_s),osd_data_s);
|
||||
if(osd_data_s)
|
||||
{
|
||||
lcdc_set_osd_dma_addr(lcd_dev,(uint32)get_stream_real_data(osd_data_s));
|
||||
lcdc_set_osd_dma_len(lcd_dev,get_stream_real_data_len(osd_data_s));
|
||||
lcdc_set_osd_en(lcd_dev,1);
|
||||
//os_printf("encode osd len:%d\n",get_stream_real_data_len(osd_data_s));
|
||||
flag++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcdc_set_osd_en(lcd_dev,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//显示video p1
|
||||
//这里是video_p1的显示
|
||||
{
|
||||
lcd_thread_get_video_p1_again:
|
||||
video_p1_data_s = recv_real_data(p1_s);
|
||||
|
||||
//有新的yuv数据要显示
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tvideo_p1_data_s:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
//移除原来的数据
|
||||
if(yuv_p1->last_data_s)
|
||||
{
|
||||
free_data(yuv_p1->last_data_s);
|
||||
}
|
||||
yuv_p1->last_data_s = video_p1_data_s;
|
||||
}
|
||||
else if(yuv_p1->last_data_s)
|
||||
{
|
||||
video_p1_data_s = yuv_p1->last_data_s;
|
||||
}
|
||||
|
||||
//判断一下显示时间,如果过时的,就不显示了
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
uint32_t show_time =stream_self_cmd_func(p1_s,GET_LVGL_YUV_UPDATE_TIME,(uint32_t)0);
|
||||
if(show_time > get_stream_data_timestamp(video_p1_data_s))
|
||||
{
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
goto lcd_thread_get_video_p1_again;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(video_p1_data_s)
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)stream_self_cmd_func(video_p1_data_s->s,YUV_ARG,(uint32_t)video_p1_data_s);
|
||||
|
||||
//错误的图片,可能不需要显示或者发送错误
|
||||
if(yuv_msg)
|
||||
{
|
||||
|
||||
//需要删除
|
||||
if(yuv_msg->del && *yuv_msg->del)
|
||||
{
|
||||
free_data(video_p1_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
os_printf("%s:%d p1 del:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
goto lcd_thread_get_video_p1_again;
|
||||
}
|
||||
|
||||
p1_w = yuv_msg->out_w;
|
||||
p1_h = yuv_msg->out_h;
|
||||
uint8_t *yuv_buf = get_stream_real_data(video_p1_data_s);
|
||||
if(lcd_s->rotate == LCD_ROTATE_180)
|
||||
{
|
||||
y_off = p1_w*(p1_h-1);
|
||||
uv_off= ((p1_w/2+3)/4)*4 * (p1_h/2-1);
|
||||
}
|
||||
lcdc_set_p1_rotate_y_src_addr(lcd_dev,(uint32)yuv_buf+y_off/**/);
|
||||
lcdc_set_p1_rotate_u_src_addr(lcd_dev,(uint32)yuv_buf+yuv_msg->y_size+uv_off/**/);
|
||||
lcdc_set_p1_rotate_v_src_addr(lcd_dev,(uint32)yuv_buf+yuv_msg->y_size+yuv_msg->y_size/4+uv_off/**/);
|
||||
p0_p1_enable |= BIT(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tlvgl video yuv err\n",__FUNCTION__,__LINE__);
|
||||
os_printf("%s:%d\tvideo_p1_data_s:%X\tname:%s\n",__FUNCTION__,__LINE__,video_p1_data_s,video_p1_data_s->s->name);
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//强行显示一下p0的数据
|
||||
{
|
||||
lcd_thread_get_video_p0_again:
|
||||
video_p0_data_s = recv_real_data(p0_s);
|
||||
//有新的yuv数据要显示
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
//os_printf("%s:%d\tvideo_p1_data_s:%X\n",__FUNCTION__,__LINE__,video_p1_data_s);
|
||||
//移除原来的数据
|
||||
if(yuv_p0->last_data_s)
|
||||
{
|
||||
free_data(yuv_p0->last_data_s);
|
||||
}
|
||||
yuv_p0->last_data_s = video_p0_data_s;
|
||||
}
|
||||
else if(yuv_p0->last_data_s)
|
||||
{
|
||||
video_p0_data_s = yuv_p0->last_data_s;
|
||||
}
|
||||
|
||||
|
||||
//判断一下显示时间,如果过时的,就不显示了
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
uint32_t show_time =stream_self_cmd_func(p0_s,GET_LVGL_YUV_UPDATE_TIME,(uint32_t)0);
|
||||
if(show_time > get_stream_data_timestamp(video_p0_data_s))
|
||||
{
|
||||
free_data(video_p0_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
goto lcd_thread_get_video_p0_again;
|
||||
}
|
||||
}
|
||||
|
||||
if(video_p0_data_s)
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)stream_self_cmd_func(video_p0_data_s->s,YUV_ARG,(uint32_t)video_p0_data_s);
|
||||
if(yuv_msg)
|
||||
{
|
||||
//需要删除
|
||||
if(yuv_msg->del && *yuv_msg->del)
|
||||
{
|
||||
free_data(video_p0_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
os_printf("%s:%d p0 del:%X\n",__FUNCTION__,__LINE__,video_p0_data_s);
|
||||
goto lcd_thread_get_video_p0_again;
|
||||
}
|
||||
uint8_t *p_buf = (uint8_t*)get_stream_real_data(video_p0_data_s);
|
||||
p0_w = yuv_msg->out_w;
|
||||
p0_h = yuv_msg->out_h;
|
||||
if(lcd_s->rotate == LCD_ROTATE_180)
|
||||
{
|
||||
y_off = p0_w*(p0_h-1);
|
||||
uv_off= ((p0_w/2+3)/4)*4 * (p0_h/2-1);
|
||||
}
|
||||
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev,(uint32)p_buf+y_off);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev,(uint32)p_buf+yuv_msg->y_size+uv_off);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev,(uint32)p_buf+yuv_msg->y_size+yuv_msg->y_size/4+uv_off);
|
||||
|
||||
p0_p1_enable |= BIT(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//打开video
|
||||
if(p0_p1_enable)
|
||||
{
|
||||
//检查一下line_buf是否已经申请了,申请空间就是w*line_num的空间(w应该是和屏旋转有关)
|
||||
if(!lcd_s->line_buf)
|
||||
{
|
||||
uint16_t rotate_w;
|
||||
rotate_w = lcd_s->screen_w;
|
||||
lcd_s->line_buf = (void*)custom_malloc(lcd_s->line_buf_num*rotate_w*2);
|
||||
//这里理论要申请到空间,如果申请失败,重新申请一下(否则要就额外处理资源数据)
|
||||
while(!lcd_s->line_buf)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
lcd_s->line_buf = (void*)custom_malloc(lcd_s->line_buf_num*rotate_w*2);
|
||||
}
|
||||
lcdc_set_rotate_linebuf_y_addr(lcd_dev,(uint32)lcd_s->line_buf );
|
||||
lcdc_set_rotate_linebuf_u_addr(lcd_dev,(uint32)lcd_s->line_buf +rotate_w*lcd_s->line_buf_num);
|
||||
lcdc_set_rotate_linebuf_v_addr(lcd_dev,(uint32)lcd_s->line_buf +rotate_w*lcd_s->line_buf_num+(rotate_w/2)*lcd_s->line_buf_num);
|
||||
}
|
||||
lcdc_set_rotate_p0p1_size(lcd_dev,p0_w,p0_h,p1_w,p1_h);
|
||||
lcdc_set_rotate_mirror(lcd_dev,0,lcd_s->video_rotate);
|
||||
lcdc_set_p0p1_enable(lcd_dev,p0_p1_enable&BIT(0),p0_p1_enable&BIT(1));
|
||||
lcdc_set_video_en(lcd_dev,1);
|
||||
flag++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果不需要显示video,则空间释放吧
|
||||
if(lcd_s->line_buf)
|
||||
{
|
||||
custom_free(lcd_s->line_buf);
|
||||
lcd_s->line_buf = NULL;
|
||||
|
||||
}
|
||||
lcdc_set_video_en(lcd_dev,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//lcd模块已经启动,hardware_ready清0
|
||||
if(flag)
|
||||
{
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
lcd_s->hardware_ready = 0;
|
||||
|
||||
lcdc_set_start_run(lcd_dev);
|
||||
flag = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//不需要显示,则休眠1ms重新检查
|
||||
//这里暂时没有用信号量唤醒,主要考虑到osd和video都有可能需要显示,要考虑如何监听osd和video的数据才可以用信号量
|
||||
//这里用sleep,会占用一点点cpu
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free_data(yuv_p0->last_data_s);
|
||||
yuv_p0->last_data_s = NULL;
|
||||
|
||||
free_data(yuv_p1->last_data_s);
|
||||
yuv_p1->last_data_s = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
video_p0_data_s = recv_real_data(p0_s);
|
||||
free_data(video_p0_data_s);
|
||||
os_printf("video_p0_data_s:%X\n",video_p0_data_s);
|
||||
|
||||
}while(video_p0_data_s);
|
||||
|
||||
do
|
||||
{
|
||||
video_p1_data_s = recv_real_data(p1_s);
|
||||
free_data(video_p1_data_s);
|
||||
os_printf("video_p1_data_s:%X\n",video_p1_data_s);
|
||||
|
||||
}while(video_p1_data_s);
|
||||
//相当于退出lcd的线程
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->thread_hdl = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "lvgl_osd_stream.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
//lvgl中osd的流,主要用于copy,效率会低(占用内存少,如果想不copy,可能lvgl内部要用动态内存的buf或者等待压缩完毕后再重复使用对应buf,但需要改动内部实现),psram竞争加大,但为了统一流程
|
||||
//统一发送到压缩流,由压缩流去管理压缩硬件模块
|
||||
//这个是作为源头
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
//osd流去进行编码
|
||||
streamSrc_bind_streamDest(s,R_OSD_ENCODE);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
|
||||
data->priv = (struct encode_data_s_callback*)custom_zalloc_psram(sizeof(struct encode_data_s_callback));
|
||||
}
|
||||
break;
|
||||
|
||||
//使用固定的buf,所以不需要释放,但是要回调函数,通知lvgl已经完成
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct encode_data_s_callback *callback = data->priv;
|
||||
if(callback->finish_cb)
|
||||
{
|
||||
callback->finish_cb(callback->user_data);
|
||||
}
|
||||
if(callback->free_cb)
|
||||
{
|
||||
callback->free_cb(callback->user_data,data->data);
|
||||
}
|
||||
data->data = NULL;
|
||||
callback->finish_cb = NULL;
|
||||
callback->free_cb = NULL;
|
||||
callback->user_data = NULL;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成,可以选择唤醒对应的任务
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
break;
|
||||
|
||||
|
||||
//音频发送之前先拷贝到psram
|
||||
case STREAM_SEND_DATA_START:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//拷贝osd到内存,然后发送出去,使用workqueue去作为任务吧
|
||||
stream *lvgl_osd_stream(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,2,0,opcode_func,NULL);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __LVGL_OSD_STREAM_H
|
||||
#define __LVGL_OSD_STREAM_H
|
||||
#include "stream_frame.h"
|
||||
typedef void (*osd_finish_cb)(void *self);
|
||||
typedef void (*osd_free_cb)(void *self,void *data);
|
||||
struct encode_data_s_callback
|
||||
{
|
||||
osd_finish_cb finish_cb;
|
||||
osd_free_cb free_cb;
|
||||
void *user_data;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,293 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/task.h"
|
||||
#include "decode/jpg_decode_stream.h"
|
||||
#include "osal/string.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "osal_file.h"
|
||||
|
||||
//获取jpeg的w和h,没有做太多容错,所以尽量给的是正确的jpeg,否则可能异常
|
||||
#define GET_16(p) (((p)[0]<<8)|(p)[1])
|
||||
|
||||
int parse_SOF(uint8_t *d,uint32_t *w,uint32_t *h )
|
||||
{
|
||||
if( d[0] != 8 )
|
||||
{
|
||||
printf( "Invalid precision %d in SOF0\n", d[0] );
|
||||
return -1;
|
||||
}
|
||||
*h = GET_16( d + 1 );
|
||||
*w = GET_16( d + 3 );
|
||||
return 0;
|
||||
}
|
||||
int parse_jpg(uint8_t *jpg_buf,uint32_t maxsize,uint32_t *w,uint32_t *h)
|
||||
{
|
||||
uint8_t *buf = jpg_buf;
|
||||
uint32_t i = 0;
|
||||
int res = 1;
|
||||
int blen = 0;
|
||||
for( i = 0; i < maxsize; i += blen + 2 )
|
||||
{
|
||||
if( buf[i] != 0xFF )
|
||||
{
|
||||
printf( "Found %02X at %d, expecting FF\n", buf[i], i );
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
while(buf[i+1] == 0xFF) ++i;
|
||||
if( buf[i + 1] == 0xD8 ) blen = 0;
|
||||
else blen = GET_16( buf + i + 2 );
|
||||
|
||||
switch( buf[i + 1] )
|
||||
{
|
||||
case 0xDB: /* Quantization Table */
|
||||
break;
|
||||
case 0xC0: /* Start of Frame */
|
||||
parse_SOF(buf+i+4,w,h);
|
||||
res = 0;
|
||||
//printf("w:%d\th:%d\n",*w,*h);
|
||||
break;
|
||||
case 0xC4: /* Huffman Table */
|
||||
|
||||
break;
|
||||
case 0xDD: /* DRI */
|
||||
break;
|
||||
case 0xDA: /* Start of Scan */
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
}
|
||||
|
||||
parse_jpg_end:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static stream *lvgl_show_jpg_s = NULL;
|
||||
|
||||
|
||||
//用于获取一些通用命令的接口,也可以加入自定义接口
|
||||
//接口怎么获取数据只有源头知道,这里不同是通用的
|
||||
static uint32_t lvgl_jpg_cmd_func(stream *s,int opcode,uint32_t arg)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case JPG_DECODE_ARG:
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)arg;
|
||||
res = (uint32_t)data_s->priv;
|
||||
}
|
||||
break;
|
||||
//这样返回代表结构体是兼容的
|
||||
case YUV_ARG:
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)arg;
|
||||
res = (uint32_t)data_s->priv;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//out_w:最终显示的w
|
||||
//
|
||||
int lvgl_jpg_send(uint32_t *jpg_data,uint32_t jpg_size,uint32_t out_w,uint32_t out_h,uint32_t jpg_w,uint32_t jpg_h,uint32_t step_w,uint32_t step_h)
|
||||
{
|
||||
int res = 1;
|
||||
struct data_structure *data = get_src_data_f(lvgl_show_jpg_s);
|
||||
if(data)
|
||||
{
|
||||
data->data = (void*)custom_malloc_psram(jpg_size);
|
||||
if(data->data)
|
||||
{
|
||||
//配置显示的参数
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *)data->priv;
|
||||
msg->yuv_arg.out_w = out_w;
|
||||
msg->yuv_arg.out_h = out_h;
|
||||
msg->rotate = 0;
|
||||
msg->decode_w = jpg_w;
|
||||
msg->decode_h = jpg_h;
|
||||
msg->step_w = step_w;
|
||||
msg->step_h = step_h;
|
||||
set_stream_real_data_len(data,jpg_size);
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
data->type = SET_DATA_TYPE(JPEG,LVGL_JPEG);
|
||||
hw_memcpy0(data->data,jpg_data,jpg_size);
|
||||
int success = send_data_to_stream(data);
|
||||
res = 0;
|
||||
os_printf("jpg_size:%d\tsuccess:%d\n",jpg_size,success);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int lvgl_jpg_send_type(uint32_t *jpg_data,uint32_t jpg_size,uint32_t type,uint32_t magic,uint32_t out_w,uint32_t out_h,uint32_t step_w,uint32_t step_h)
|
||||
{
|
||||
int res = 1;
|
||||
struct data_structure *data = get_src_data_f(lvgl_show_jpg_s);
|
||||
if(data)
|
||||
{
|
||||
data->data = (void*)custom_malloc_psram(jpg_size);
|
||||
if(data->data)
|
||||
{
|
||||
hw_memcpy0(data->data,jpg_data,jpg_size);
|
||||
//配置显示的参数
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *)data->priv;
|
||||
msg->yuv_arg.out_w = out_w;
|
||||
msg->yuv_arg.out_h = out_h;
|
||||
msg->rotate = 0;
|
||||
msg->magic = magic;
|
||||
parse_jpg(data->data,jpg_size,&msg->decode_w,&msg->decode_h);
|
||||
|
||||
msg->step_w = step_w;
|
||||
msg->step_h = step_h;
|
||||
set_stream_real_data_len(data,jpg_size);
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
data->type = SET_DATA_TYPE(JPEG,type);
|
||||
|
||||
int success = send_data_to_stream(data);
|
||||
res = 0;
|
||||
os_printf("jpg_size:%d\tsuccess:%d\n",jpg_size,success);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int lvgl_jpg_from_fs_send(uint8_t *filename,uint32_t out_w,uint32_t out_h,uint32_t step_w,uint32_t step_h)
|
||||
{
|
||||
int res = 1;
|
||||
void *fp = osal_fopen((const char *)filename,"rb");
|
||||
if(!fp)
|
||||
{
|
||||
goto lvgl_jpg_from_fs_send_end;
|
||||
return res;
|
||||
}
|
||||
struct data_structure *data = get_src_data_f(lvgl_show_jpg_s);
|
||||
if(data)
|
||||
{
|
||||
uint32_t jpg_size = osal_fsize(fp);
|
||||
data->data = (void*)custom_malloc_psram(jpg_size);
|
||||
if(data->data)
|
||||
{
|
||||
//配置显示的参数
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *)data->priv;
|
||||
msg->yuv_arg.out_w = out_w;
|
||||
msg->yuv_arg.out_h = out_h;
|
||||
msg->rotate = 0;
|
||||
//msg->decode_w = 640;
|
||||
//msg->decode_h = 480;
|
||||
msg->step_w = step_w;
|
||||
msg->step_h = step_h;
|
||||
set_stream_real_data_len(data,jpg_size);
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
data->type = SET_DATA_TYPE(JPEG,LVGL_JPEG);
|
||||
osal_fread(data->data,1,jpg_size,fp);
|
||||
parse_jpg(data->data,jpg_size,&msg->decode_w,&msg->decode_h);
|
||||
os_printf("msg->decode_w:%d\tmsg->decode_h:%d\n",msg->decode_w,msg->decode_h);
|
||||
int success = send_data_to_stream(data);
|
||||
res = 0;
|
||||
os_printf("jpg_size:%d\tsuccess:%d\n",jpg_size,success);
|
||||
}
|
||||
}
|
||||
|
||||
if(fp)
|
||||
{
|
||||
osal_fclose(fp);
|
||||
}
|
||||
lvgl_jpg_from_fs_send_end:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = priv;
|
||||
register_stream_self_cmd_func(s,lvgl_jpg_cmd_func);
|
||||
stream_data_dis_mem_custom(s);
|
||||
streamSrc_bind_streamDest(s,S_JPG_DECODE);
|
||||
enable_stream(s,1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->priv = (void *)custom_zalloc(sizeof(struct jpg_decode_arg_s));
|
||||
data->data = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
os_printf("lvgl show stream %s:%d\n",__FUNCTION__,__LINE__);
|
||||
custom_free_psram(data->data);
|
||||
data->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成,可以选择唤醒对应的任务
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
break;
|
||||
|
||||
|
||||
case STREAM_SEND_DATA_START:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->priv)
|
||||
{
|
||||
custom_free(data->priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//创建lvgl生成jpg的流,用于将jpg发送到解码的地方
|
||||
//然后显示出来
|
||||
void *lvgl_jpg_stream(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name, 5, 0, opcode_func,NULL);
|
||||
lvgl_show_jpg_s = s;
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef __LVGL_SHOW_JPG_H
|
||||
#define __LVGL_SHOW_JPG_H
|
||||
int lvgl_jpg_send(uint32_t *jpg_data,uint32_t jpg_size,uint32_t out_w,uint32_t out_h,uint32_t jpg_w,uint32_t jpg_h,uint32_t step_w,uint32_t step_h);
|
||||
void *lvgl_jpg_stream(const char *name);
|
||||
void lvgl_broadcast_exit();
|
||||
int lvgl_jpg_from_fs_send(uint8_t *filename,uint32_t out_w,uint32_t out_h,uint32_t step_w,uint32_t step_h);
|
||||
#endif
|
||||
@@ -0,0 +1,301 @@
|
||||
#include "osd_encode_stream.h"
|
||||
#include "osal/work.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
|
||||
|
||||
//data申请空间函数
|
||||
#define STREAM_MALLOC custom_malloc_psram
|
||||
#define STREAM_FREE custom_free_psram
|
||||
#define STREAM_ZALLOC custom_zalloc_psram
|
||||
|
||||
//结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC custom_malloc
|
||||
#define STREAM_LIBC_FREE custom_free
|
||||
#define STREAM_LIBC_ZALLOC custom_zalloc
|
||||
|
||||
|
||||
struct lvgl_osd_encode_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct lcdc_device *lcd_dev;
|
||||
stream *s;
|
||||
uint8_t *osd_tmp_buf;
|
||||
uint32_t osd_tmp_buf_size;
|
||||
//如果data_send有,并且useful可用,代表data_send需要发送出去
|
||||
struct data_structure *parent_data_s;
|
||||
uint32_t parent_type;
|
||||
//osd压缩后的数据长度
|
||||
uint32_t data_len;
|
||||
//解码模块是否可用
|
||||
uint8_t hardware_ready;
|
||||
};
|
||||
|
||||
static int32 osd_encode_work(struct os_work *work)
|
||||
{
|
||||
struct lvgl_osd_encode_s *osd_encode = (struct lvgl_osd_encode_s*)work;
|
||||
struct data_structure *data_s = NULL;
|
||||
//static int osd_encode_count = 0;
|
||||
static uint32_t osd_send_times = 0;
|
||||
//先检测一下解码模块是否可用
|
||||
if(osd_encode->hardware_ready)
|
||||
{
|
||||
//os_printf("osd_encode work!!!!!!!!!!!!!!!!\n");
|
||||
//检测一下是否有data_s需要先发送出去
|
||||
if(osd_encode->parent_data_s)
|
||||
{
|
||||
//获取data_s,申请空间,发送数据
|
||||
data_s = get_src_data_f(osd_encode->s);
|
||||
if(data_s)
|
||||
{
|
||||
data_s->type = osd_encode->parent_data_s->type;
|
||||
free_data(osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
|
||||
//为data_s申请空间
|
||||
data_s->data = (void*)STREAM_MALLOC(osd_encode->data_len);
|
||||
if(data_s->data)
|
||||
{
|
||||
|
||||
//os_printf("memcpy buf:%X\n",stream_self_cmd_func(osd_encode->s,OSD_HARDWARE_ENCODE_BUF,0));
|
||||
//拷贝数据
|
||||
hw_memcpy(data_s->data,(void*)stream_self_cmd_func(osd_encode->s,OSD_HARDWARE_ENCODE_BUF,0),(uint32)osd_encode->data_len);
|
||||
sys_dcache_clean_range(data_s->data, osd_encode->data_len);
|
||||
//数据类型保持一致
|
||||
|
||||
set_stream_real_data_len(data_s,osd_encode->data_len);
|
||||
//os_printf("%s:%d\tdata_s:%X\tosd_encode->data_len:%d\n",__FUNCTION__,__LINE__,data_s,osd_encode->data_len);
|
||||
send_data_to_stream(data_s);
|
||||
osd_send_times++;
|
||||
|
||||
}
|
||||
//没有发送成功,则释放data_s先吧,下一次再发送
|
||||
else
|
||||
{
|
||||
force_del_data(data_s);
|
||||
_os_printf("**********************");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//重新检测一下,parent_data_s是否还存在,不存在就去看看是否有需要压缩的osd
|
||||
//会进入中断
|
||||
if(!osd_encode->parent_data_s)
|
||||
{
|
||||
osd_encode->parent_data_s = recv_real_data(osd_encode->s);
|
||||
|
||||
if(osd_encode->parent_data_s)
|
||||
{
|
||||
|
||||
|
||||
//判断一下osd_tmp_buf_size是否足够,如果足够就不需要重新申请空间,否则重新申请一下空间
|
||||
if(osd_encode->osd_tmp_buf_size < get_stream_real_data_len(osd_encode->parent_data_s))
|
||||
{
|
||||
//释放原来空间
|
||||
if(osd_encode->osd_tmp_buf)
|
||||
{
|
||||
STREAM_FREE(osd_encode->osd_tmp_buf);
|
||||
}
|
||||
|
||||
//重新申请一下空间
|
||||
osd_encode->osd_tmp_buf = (uint8_t*)STREAM_MALLOC(get_stream_real_data_len(osd_encode->parent_data_s));
|
||||
//申请失败,不压缩了,丢弃
|
||||
if(!osd_encode->osd_tmp_buf)
|
||||
{
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
free_data(osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
goto osd_encode_work_end;
|
||||
|
||||
}
|
||||
|
||||
osd_encode->osd_tmp_buf_size = get_stream_real_data_len(osd_encode->parent_data_s);
|
||||
}
|
||||
//硬件模块开始被使用,标志置一下
|
||||
stream_self_cmd_func(osd_encode->s,OSD_HARDWARE_REAY_CMD,0);
|
||||
//去压缩
|
||||
//先清除cache
|
||||
sys_dcache_clean_invalid_range((uint32_t *)stream_self_cmd_func(osd_encode->s,OSD_HARDWARE_ENCODE_BUF,0), osd_encode->osd_tmp_buf_size);
|
||||
lcdc_set_osd_enc_src_addr(osd_encode->lcd_dev,(uint32)get_stream_real_data(osd_encode->parent_data_s));
|
||||
lcdc_set_osd_enc_dst_addr(osd_encode->lcd_dev,(uint32)stream_self_cmd_func(osd_encode->s,OSD_HARDWARE_ENCODE_BUF,0));
|
||||
lcdc_set_osd_enc_src_len(osd_encode->lcd_dev,get_stream_real_data_len(osd_encode->parent_data_s));
|
||||
//gpio_set_val(PA_15,1);
|
||||
lcdc_osd_enc_start_run(osd_encode->lcd_dev,1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
osd_encode_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t osd_stream_cmd_func(stream *s,int opcode,uint32_t arg)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
struct lvgl_osd_encode_s *osd_encode = (struct lvgl_osd_encode_s*)s->priv;
|
||||
// uint32_t flags;
|
||||
switch(opcode)
|
||||
{
|
||||
//设置硬件是否准备好
|
||||
case OSD_HARDWARE_REAY_CMD:
|
||||
osd_encode->hardware_ready = arg;
|
||||
break;
|
||||
//设置压缩后的数据长度
|
||||
case OSD_HARDWARE_ENCODE_SET_LEN:
|
||||
osd_encode->data_len = arg;
|
||||
break;
|
||||
case OSD_HARDWARE_ENCODE_GET_LEN:
|
||||
res = osd_encode->data_len;
|
||||
break;
|
||||
//返回压缩的buf
|
||||
case OSD_HARDWARE_ENCODE_BUF:
|
||||
res = (uint32_t)osd_encode->osd_tmp_buf;
|
||||
break;
|
||||
case OSD_HARDWARE_DEV:
|
||||
res = (uint32_t)osd_encode->lcd_dev;
|
||||
break;
|
||||
|
||||
case OSD_HARDWARE_STREAM_RESET:
|
||||
{
|
||||
#if 0
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(osd_encode->parent_data_s)
|
||||
{
|
||||
free_data(osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
}
|
||||
#endif
|
||||
//硬件模块可用
|
||||
osd_encode->hardware_ready = 1;
|
||||
OS_WORK_REINIT(&osd_encode->work);
|
||||
os_run_work(&osd_encode->work);
|
||||
}
|
||||
break;
|
||||
|
||||
//硬件模块停止,workqueue停止
|
||||
case OSD_HARDWARE_STREAM_STOP:
|
||||
//停止硬件模块
|
||||
lcdc_osd_enc_start_run(osd_encode->lcd_dev,0);
|
||||
//workqueue停止
|
||||
os_work_cancle2(&osd_encode->work,1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int opcode_func_r_osd(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
struct lvgl_osd_encode_s *osd_encode = (struct lvgl_osd_encode_s*)STREAM_LIBC_ZALLOC(sizeof(struct lvgl_osd_encode_s));
|
||||
|
||||
if(osd_encode)
|
||||
{
|
||||
osd_encode->lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
osd_encode->hardware_ready = 1;
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
osd_encode->osd_tmp_buf = NULL;
|
||||
|
||||
s->priv = (void*)osd_encode;
|
||||
streamSrc_bind_streamDest(s,R_OSD_SHOW);
|
||||
register_stream_self_cmd_func(s,osd_stream_cmd_func);
|
||||
osd_encode->s = s;
|
||||
OS_WORK_INIT(&osd_encode->work, osd_encode_work, 0);
|
||||
os_run_work_delay(&osd_encode->work, 1);
|
||||
//启动一个任务去管理?或者workqueue都是可行的,就是实时性的问题
|
||||
//先用workqueue实现,如果性能不行再换成任务的形式吧
|
||||
enable_stream(s,1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
STREAM_FREE(data->data);
|
||||
data->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STREAM_DATA_FREE_END:
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成,可以选择唤醒对应的任务
|
||||
case STREAM_SEND_DATA_FINISH:
|
||||
break;
|
||||
|
||||
|
||||
//音频发送之前先拷贝到psram
|
||||
case STREAM_SEND_DATA_START:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_CLOSE_EXIT:
|
||||
{
|
||||
struct lvgl_osd_encode_s *osd_encode = (struct lvgl_osd_encode_s *)s->priv;
|
||||
os_work_cancle2(&osd_encode->work,1);
|
||||
//关闭硬件
|
||||
lcdc_osd_enc_start_run(osd_encode->lcd_dev,0);
|
||||
//释放资源
|
||||
free_data(osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
|
||||
//释放原来空间
|
||||
if(osd_encode->osd_tmp_buf)
|
||||
{
|
||||
STREAM_FREE(osd_encode->osd_tmp_buf);
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
osd_encode->osd_tmp_buf = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_MARK_GC_END:
|
||||
{
|
||||
if(s->priv)
|
||||
{
|
||||
STREAM_FREE(s->priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//osd压缩是一个模块,所以在这里统一管理自己的模块,所有需要压缩的数据都到这里,然后再发出去
|
||||
//然后类型可以跟着父流一致
|
||||
//要预先申请一个空间给到osd压缩,最后再读取寄存器看看要拷贝多少压缩的数据
|
||||
//所以空间是:w*h*2+压缩的size,压缩的size根据不同ui去压缩的,一般不会超过原来的size
|
||||
|
||||
stream *lvgl_R_osd_stream(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,8,8,opcode_func_r_osd,NULL);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef __OSD_ENCODE_STREAM_H
|
||||
#define __OSD_ENCODE_STREAM_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "hal/lcdc.h"
|
||||
|
||||
enum
|
||||
{
|
||||
OSD_HARDWARE_REAY_CMD = CUSTOM_STREAM_CMD+1,
|
||||
OSD_HARDWARE_ENCODE_SET_LEN,
|
||||
OSD_HARDWARE_ENCODE_GET_LEN,
|
||||
OSD_HARDWARE_ENCODE_BUF,
|
||||
OSD_HARDWARE_DEV,
|
||||
OSD_HARDWARE_STREAM_RESET,
|
||||
OSD_HARDWARE_STREAM_STOP,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "osd_show_stream.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "osal/string.h"
|
||||
//这里只是为了给osd创建流,实际内部没有做什么,这个流取到的数据应该是已经压缩过的
|
||||
//接收到就可以配置硬件寄存器了
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = priv;
|
||||
enable_stream(s,1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
stream *osd_show_stream(const char *name)
|
||||
{
|
||||
struct osd_show_s *show = (struct osd_show_s*)custom_zalloc_psram(sizeof(struct osd_show_s));
|
||||
struct lcdc_device *lcd_dev;
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
show->lcd_dev = lcd_dev;
|
||||
stream *s = open_stream_available(name,0,8,opcode_func,show);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef __OSD_SHOW_STREAM_H
|
||||
#define __OSD_SHOW_STREAM_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "hal/lcdc.h"
|
||||
struct osd_show_s
|
||||
{
|
||||
struct lcdc_device *lcd_dev;
|
||||
stream *s;
|
||||
struct data_structure *last_show_data_s;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user