📄 png_decoder.c
字号:
*
* DESCRIPTION
* start to parse the first IDAT chunk
*
* PARAMETERS
* len: length of the first IDAT chunk
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_IDAT_Handler(kal_uint32 len)
{
if(!(png_dcb.flags & PNG_HAVE_IHDR))
PNG_RAISE(1);
png_dcb.flags |= PNG_HAVE_IDAT;
png_decode_hw(len);
}
/*************************************************************************
* FUNCTION
* png_decode_process
*
* DESCRIPTION
* start to parse the PNG image.
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_decode_process(void)
{
kal_uint8 buf[8];
PNG_GET_ARRAY(buf,8);
if(kal_mem_cmp(buf, png_signature, 8)!= 0)
PNG_RAISE(1);
while(PNG_IS_EOF()!= KAL_TRUE)
{
kal_uint32 len;
len = PNG_GET_U32();
png_crc_reset();
png_crc_read(buf,4);
if(!kal_mem_cmp(buf,png_IHDR,4))
{
png_IHDR_Handler(len);
}
else if(!kal_mem_cmp(buf,png_PLTE,4))
{
png_PLTE_Handler(len);
}
else if(!kal_mem_cmp(buf,png_tRNS,4))
{
png_tRNS_Handler(len);
}
else if(!kal_mem_cmp(buf,png_IDAT,4))
{
png_IDAT_Handler(len);
return ;
}
else if(!kal_mem_cmp(buf,png_bKGD,4))
{
png_bKGD_Handler(len);
}
else if(!kal_mem_cmp(buf,png_IEND,4))
{
PNG_RAISE(1);
}
else
{
PNG_FLUSH(len+PNG_CRC_LEN);
}
}
PNG_RAISE(1);
//return PNG_FORMAT_ERROR;
}
/*************************************************************************
* FUNCTION
* png_hisr_entry
*
* DESCRIPTION
* 1. hisr entry function of the PNG interrupt
* 2. calling the callback function registered by the caller
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_hisr_entry(void)
{
kal_uint32 status;
png_report_status_enum report;
PNG_STOP_TIMER();
status = DRV_Reg(PNG_IRQ_STATUS);
png_dcb.status = status;
if(status == PNG_IRQ_STATUS_IMG_COMPLETE)
{
//1: check the ADLER checksum
report = PNG_FINISH_IMAGE;
png_state = PNG_STATE_READY;
PNG_RESET();
}
else if(status == PNG_IRQ_STATUS_BLOCK_END)
{
if( DRV_Reg(PNG_DECODE_EN)== 0 )
DRV_WriteReg(PNG_DECODE_EN, 1);
report = PNG_BLOCK_END;
}
else if(status == PNG_IRQ_STATUS_IN_EMPTY)
{
report = PNG_INPUT_EMPTY;
}
else
{
report = PNG_FORMAT_ERROR;
png_state = PNG_STATE_READY;
PNG_RESET();
}
png_dcb.cb(report);
DRVPDN_Enable(DRVPDN_CON3,DRVPDN_CON3_PNG,PDN_PNG);
IRQUnmask(IRQ_PNG_CODE);
}
/*************************************************************************
* FUNCTION
* png_lisr_entry
*
* DESCRIPTION
* lisr entry function of the png interrupt
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void png_lisr_entry(void)
{
IRQMask(IRQ_PNG_CODE);
//kal_activate_hisr(png_hisr);
visual_active_hisr(VISUAL_PNG_HISR_ID);
}
/*************************************************************************
* FUNCTION
* png_init
*
* DESCRIPTION
* Initialization of the driver of the PNG decoder
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
void png_init(void)
{
if(png_hisr == 0)
{
//png_hisr = kal_create_hisr("PNG_HISR",2,512,png_hisr_entry,NULL);
VISUAL_Register_HISR(VISUAL_PNG_HISR_ID,png_hisr_entry);
png_hisr=VISUAL_PNG_HISR_ID;
IRQ_Register_LISR(IRQ_PNG_CODE, png_lisr_entry,"png_lisr");
IRQSensitivity(IRQ_PNG_CODE,LEVEL_SENSITIVE);
}
if(png_gpt_handle == 0)
GPTI_GetHandle(&png_gpt_handle);
png_state = PNG_STATE_READY;
IRQUnmask(IRQ_PNG_CODE);
}
/*************************************************************************
* FUNCTION
* png_decode_start
*
* DESCRIPTION
* 1. start to decode a PNG image (async interface )
* 2. calling the callback function while the PNG interrupt is generated or
* GPT timer is expired
*
* PARAMETERS
* cfg: configuration of the driver of PNG decoder
* info: information of the decoded PNG image
*
* RETURNS
* PNG_DECODING: the driver is decoding the PNG image without any error
* PNG_FORMAT_ERROR: the input PNG image is invalid
*
* GLOBALS AFFECTED
*
*************************************************************************/
png_report_status_enum png_decode_start_hw(png_config_struct *cfg, png_inform_struct *info)
{
png_report_status_enum status;
ASSERT(png_state == PNG_STATE_READY);
png_state = PNG_STATE_BUSY;
ASSERT(cfg->cb != NULL);
kal_mem_set(&png_dcb, 0, sizeof(png_dcb));
png_dcb.cb = cfg->cb;
png_dcb.cfg = cfg;
if(cfg->decode_mode == PNG_DECODE_FILE)
{
// reserve 4 bytes for the partial input limiation
png_dcb.file_size = hw_bytestream_create_file(HW_BYTESTREAM_PNG,
cfg->file_handle,
(kal_uint8*)(cfg->in_buffer_adrs),
cfg->in_buffer_size);
if(png_dcb.file_size)
{
//png_dcb.in_count = png_dcb.file_size;
if(png_dcb.file_size > cfg->in_buffer_size)
png_dcb.partial_en = KAL_TRUE;
}
else
{
png_state = PNG_STATE_READY;
status = PNG_FORMAT_ERROR;
goto end;
}
}
else // the total file is in the memory
{
hw_bytestream_create(HW_BYTESTREAM_PNG,(kal_uint8*)cfg->in_buffer_adrs,cfg->in_buffer_size);
png_dcb.file_size = cfg->in_buffer_size;
// png_dcb.in_count = png_dcb.file_size;
}
png_dcb.timeout_period = cfg->png_timeout_period;
status = PNG_DECODING;
PNG_TRY
png_decode_process();
PNG_CATCH_BEGIN
png_state = PNG_STATE_READY;
status = PNG_FORMAT_ERROR;
PNG_CATCH_END
//if(info->use_work_buf == KAL_TRUE)
//status = PNG_USE_G2D;
kal_mem_cpy(info, &png_dcb.info, sizeof(png_inform_struct) );
end:
return status;
}
/*************************************************************************
* FUNCTION
* png_decode_resume
*
* DESCRIPTION
* 1. keep decoding the remaing PNG images
* 2. calling the callback function while the PNG interrupt is generated or
* GPT timer is expired
*
* PARAMETERS
*
* RETURNS
* PNG_DECODING: the driver is decoding the PNG image without any error
* PNG_FORMAT_ERROR: the input PNG image is invalid
* PNG_FINISH_IMAGE: the total image has been decoded successfully
*
* GLOBALS AFFECTED
*
*************************************************************************/
png_report_status_enum png_decode_resume(void)
{
kal_uint32 status;
png_report_status_enum report;
ASSERT(png_state == PNG_STATE_BUSY);
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_PNG,PDN_PNG);
status = png_dcb.status;
report = PNG_DECODING;
PNG_TRY
if(status == PNG_IRQ_STATUS_BLOCK_END)
{
if(!png_dcb.is_IEND)
{
png_assemble_idat();
DRV_WriteReg32(PNG_IN_START, png_idat_buf);
DRV_WriteReg32(PNG_IN_COUNT, idat_buf_len+4);
if(png_dcb.z_count >= 4)
{
DRV_WriteReg32(PNG_IDAT_COUNT, png_dcb.z_count);
}
else if(png_dcb.z_count > 0)
{
kal_uint32 reg,i;
kal_uint8 *ptr = (kal_uint8*)png_idat_buf;
for(reg=0,i=0; i<png_dcb.z_count; i++)
{
reg |= (ptr[i] << (8*i));
}
DRV_WriteReg32(PNG_IDAT_BUFFER, reg);
DRV_WriteReg32(PNG_IDAT_COUNT, png_dcb.z_count);
}
else
DRV_WriteReg32(PNG_IDAT_COUNT, idat_buf_len);
PNG_RESUME();
}
else
{
PNG_RESET();
png_state = PNG_STATE_READY;
report = PNG_FINISH_IMAGE;
}
}
else if(status == PNG_IRQ_STATUS_IN_EMPTY)
{
PNG_RAISE(1);
}
PNG_CATCH_BEGIN
png_state = PNG_STATE_READY;
report = PNG_FORMAT_ERROR;
PNG_CATCH_END
return report;
}
/*************************************************************************
* FUNCTION
* png_decode_stop
*
* DESCRIPTION
* stop decoding the PNG image (abort in the meddle of the decoding process)
*
* PARAMETERS
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
void png_decode_stop_hw(void)
{
png_state = PNG_STATE_READY;
DRVPDN_Disable(DRVPDN_CON3,DRVPDN_CON3_PNG,PDN_PNG);
IRQMask(IRQ_PNG_CODE);
DRV_WriteReg32(PNG_IRQ_EN, 0);
PNG_RESET();
IRQUnmask(IRQ_PNG_CODE);
DRVPDN_Enable(DRVPDN_CON3,DRVPDN_CON3_PNG,PDN_PNG);
}
#endif //USE_HW_PNG_DECODER_V1
//------------------------------------------------------------------------//
// Unit Test Code //
//------------------------------------------------------------------------//
#if defined (PNG_MODULE_BURN_TEST)
#undef PNG_UNIT_TEST
// --------------------remove --------------------------//
#define MT6228_BURNING_SYSRAM_SIZE 128*1024
#pragma arm section zidata = "SYSRAMZI"
__align(4) kal_uint8 g_burning_sysram[MT6228_BURNING_SYSRAM_SIZE];
#pragma arm section zidata
kal_bool g_burning_sysram_ready = KAL_TRUE;
kal_uint8* drvtest_get_sysram(kal_uint32 *p_size)
{
if(g_burning_sysram_ready == KAL_FALSE)
{
while(1);
}
*p_size = MT6228_BURNING_SYSRAM_SIZE;
g_burning_sysram_ready = KAL_FALSE;
return g_burning_sysram;
}
void drvtest_release_sysram(void)
{
g_burning_sysram_ready = KAL_TRUE;
}
// --------------------remove --------------------------//
kal_eventgrpid my_Events;
png_report_status_enum cb_status;
png_config_struct png_config;
png_inform_struct png_info;
volatile kal_bool png_stop_now = KAL_FALSE;
#define MY_GET_BUF(a,b,c) a = (kal_uint32*)b; b += (c);
#define PNG_OUTPUT_SIZE (sizeof basn6a08_result)
void png_callback(png_report_status_enum status)
{
cb_status = status;
kal_set_eg_events(my_Events,1,KAL_OR);
}
#include "basn6a08.c"
#include "basn6a08_result.c"
kal_bool png_module_burn_test(void)
{
png_config_struct *p = &png_config;
png_report_status_enum status;
kal_uint32 flag,bytes,buf_size;
kal_uint8 *buffer;
extern kal_uint8* drvtest_get_sysram(kal_uint32 *p_size);
extern void drvtest_release_sysram(void);
png_init();
my_Events = kal_create_event_group("my Events");
p->in_buffer_adrs = (kal_uint32)basn6a08;
p->in_buffer_size = sizeof basn6a08 ;
buffer = drvtest_get_sysram(&buf_size);
p->output_buffer_adrs = (kal_uint32)buffer;
buffer += PNG_OUTPUT_SIZE;
p->output_buffer_size = PNG_OUTPUT_SIZE+1024;
MY_GET_BUF(p->hclen, buffer, HCLEN_LEN);
MY_GET_BUF(p->hlen, buffer, HLEN_LEN);
MY_GET_BUF(p->hlit, buffer, HLIT_LEN);
MY_GET_BUF(p->hdist, buffer, HDIST_LEN);
MY_GET_BUF(p->buff0, buffer, BUFF0_LEN);
MY_GET_BUF(p->buff1, buffer, BUFF1_LEN);
MY_GET_BUF(p->LZ77, buffer, LZ77_LEN);
MY_GET_BUF(p->color_table, buffer, 1024);
MY_GET_BUF(p->color_table_t, buffer, 256);
p->shadow_w = 32;
p->shadow_h = 32;
p->clip_x1 = 0;
p->clip_y1 = 0;
p->clip_x2 = 32;
p->clip_y2 = 32;
p->dest_x = 0;
p->dest_y = 0;
p->expect_w = 0;
p->expect_h = 0;
p->clip_en = KAL_FALSE;
p->out_format = RGB888;
p->cb = png_callback;
status = png_decode_start(p, &png_info);
if(status == PNG_FORMAT_ERROR)
goto end;
kal_retrieve_eg_events(my_Events,(1),KAL_OR_CONSUME,&flag,KAL_SUSPEND);
while(1)
{
if (cb_status == PNG_BLOCK_END)
{
if(!png_stop_now)
{
status = png_decode_resume();
if(status == PNG_DECODING)
kal_retrieve_eg_events(my_Events,(1),KAL_OR_CONSUME,&flag,KAL_SUSPEND);
else if(status == PNG_FINISH_IMAGE)
{
goto end;
}
else
{
goto end;
}
}
else
{
png_decode_stop();
goto end;
}
}
else if(cb_status == PNG_INPUT_EMPTY)
{
ASSERT(0);
}
else if(cb_status == PNG_FINISH_IMAGE)
{
ASSERT(0);
goto end;
}
else // PNG_DECODE_TIMEOUT, PNG_FORMAT_ERROR
{
png_decode_stop();
break;
}
}
end:
drvtest_release_sysram();
// compare the result
if(memcmp((kal_uint8*)p->output_buffer_adrs, basn6a08_result, PNG_OUTPUT_SIZE))
{
return KAL_FALSE;
}
else
{
return KAL_TRUE;
}
}
void png_test_main(void)
{
png_module_burn_test();
}
#endif // PNG_MODULE_BURN_TEST
// #define PNG_UINT_TEST
#if defined (PNG_UINT_TEST)
#include "lcd_if.h"
#include "lcd_sw.h"
#include "lcd_sw_inc.h"
#include "msdc_def.h"
#include "sd_def.h"
#include "rtfiles.h"
// unit test code start here
//#define FILE_BUFFER_SIZE (16*1024)
#define FILE_BUFFER_SIZE (16*1024)
#define OUT_BUFFER_SIZE (LCD_WIDTH*LCD_HEIGHT*2)
kal_uint32 hdist[HDIST_LEN/4];
kal_uint32 hlit[HLIT_LEN/4];
kal_uint32 LZ77[LZ77_LEN/4];
kal_uint32 hclen[HCLEN_LEN/4];
kal_uint32 hlen[HLEN_LEN/4];
kal_uint32 buff0[BUFF0_LEN/4];
kal_uint32 buff1[BUFF1_LEN/4];
kal_uint32 color_table[CT_LEN];
kal_uint32 color_table_t[CT_LEN]; // transparent pallete
png_internal_buffer_struct png_buffers = {hclen,
hlen, hlit, hdist, buff0,
buff1,LZ77, color_table, color_table_t};
kal_uint8 in_buffer[FILE_BUFFER_SIZE];
kal_uint16 lcd_buffer[LCD_WIDTH*LCD_HEIGHT];
kal_uint8 file_name[256];
kal_wchar file_name_w[256];
kal_uint32 file_size;
kal_eventgrpid my_Events;
png_report_status_enum cb_status;
png_config_struct png_config;
png_inform_struct png_info;
volatile kal_bool png_stop_now = KAL_FALSE;
static kal_uint32 t1, t2;
void GPT3_Init_my(void)
{
// clear pdn bit of GPT
DRV_Reg(0x80000324) = 1;
// set clock
DRV_Reg(0x80100024) = 0; // 16k Hz
// start free running
DRV_Reg(0x8010001c) = 1;
}
kal_uint32 GPT3_GetCount(void)
{
volatile kal_uint32 t;
t = DRV_Reg(0x80100020);
return t;
}
kal_uint32 GPT3_TimeDiff(kal_uint32 time1)
{
kal_uint32 time2;
time2 = DRV_Reg(0x80100020);
if(time2 >= time1)
return (time2 - time1);
return (0xffff - time1 + time2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -