osdcore.c

来自「一个不错的硬盘播放器程序,包含VFD显示程序,红外线遥控程序,硬盘读写程序,及解」· C语言 代码 · 共 280 行

C
280
字号
/* Copyright 1996, ESS Technology, Inc.					*/
/* SCCSID @(#)osdcore.c	1.26 2/24/98 */

/*
 * $Log$
 */

#include "common.h"
#include "const.h"
#include "display.h"
#include "fsosd.h"
#include "util.h"
#include "mvd.h"
#include "vcd.h"

#define EPRINTF(a) 

#ifdef OSD_COMPRESS
extern void OSD_decompression (int, unsigned char *, unsigned char *,
			       unsigned char *, unsigned short *, int);
#endif /* OSD_COMPRESS */

/*
 * The following OSD routine is marginally time critical, so it can 
 * either be in SRAM or ROM. If there is still space in SRAM, then it
 * should be included in SRAM; otherwise, it can sit in ROM.
 */


/*
 * Actual updating of DRAM for OSD data.
 *
 * Input:
 *	clean_up:
 *		 0 = Normal OSD operation.
 *		 1 = Flag to use OSD_new to clear DRAM for Time/Track.
 *		-1 = Flag to use OSD_blink_msg to simulate blinking.
 */
void OSD_copy_data(int clean_up)
{
    int pos, dest;
    OSD_Region 	*osd_region;
    unsigned short  	region_mask;
    int     		count, end, region, size;
    unsigned char    	*current, *osd_new;

    int big;			/* Is the font single/big		*/
    unsigned int head;		/* Region offset (in byte)		*/
    int offset;			/* Position offset in a region.		*/
    

    while (OSD_update_regions)
    {
        if ((OSD_update_regions & (OSD_TIME_REGION_MASK|OSD_TRACK_REGION_MASK))
	    )
        { 
	    if (OSD_update_regions & OSD_TIME_REGION_MASK) {        
		region = OSD_TIME_REGION;
		region_mask = OSD_TIME_REGION_MASK;                            
		osd_new = OSD_new_time;            
		size = OSD_TIME_SIZE;   
	    }
	    else { /* Track region */
		region = OSD_TRACK_REGION;
		region_mask = OSD_TRACK_REGION_MASK;                            
		osd_new = OSD_new_track;
		size = OSD_TRACK_SIZE;
	    }
            current = OSD_lines[OSD_LINE_NUM(region)];
	    osd_region = &(OSD_regions[region - 1]);

            if (clean_up == 1) {
                end = OSD_MAX_CHAR; /* we're in clearAllOsd() */
                osd_new = OSD_new;  /* use 'blanks' */          
            }    
            else 
                end = osd_region->end = osd_region->start + size;

            OSD_update_regions &= ~region_mask;
        }
        else 
        {   /* let's find region that needs updating */
	    for (region = 0; region < OSD_MAX_REGIONS; region++)
	    {
                region_mask = ptrLshift[region];
		if (OSD_update_regions & region_mask)
		{
		    OSD_update_regions &= ~region_mask;
		    break;
		}
	    }

            osd_region = &(OSD_regions[region]);
	    region++;  /* now holds region number..previously held index */
    
            end = (int)(osd_region->end);
            current = OSD_lines[OSD_LINE_NUM(region)];
            	osd_new = OSD_new;            
        }


	/* 
	 * pos:		Character position in current[]
	 * count:	Character position in osd_new[]
	 * offset:	offset*6 is OSD offset (in bytes) w.r.t. 
	 *		the beginning of the specific OSD line.
	 * head:	DRAM offset for between of OSD (in DWORD)
	 * big:		"Big" character (i.e. each of them is twice
	 *		the size of small character)
	 * odd:		If "offset" is odd
	 */
	offset = pos = (int)(osd_region->start); 
	head = (OSD_DRAM_START +
		OSD_LINE_NUM(region) * OSD_DRAM_DX*OSD_MAX_CHAR/2 * 
	        OSD_CHAR_HEIGHT/2) << 2;

        for (count = 0; offset < end; ) {
	    unsigned int ctmp = osd_new[count];

	    big = (ctmp >= FONT_CSTART);
	    if (current[pos] != ctmp) {
		/* Starting data offset (in byte); i.e. head+offset*6 */
		dest = head + (offset << 2) + (offset << 1);
		OSD_copy_one_char(ctmp, big, dest, 
				  OSD_DRAM_DX*(OSD_MAX_CHAR/2));
		current[pos] = ctmp;
	    }
		
	    count++; pos++; offset++;
	    if (big) {
		current[pos] = osd_new[count];
		count++;
		offset++;
		pos++;
	    }
	}
    }
}


/*
 * Put the given character (ctmp) into the destination DRAM (dest).
 *
 * Inputs:
 *	ctmp:	Target character
 *	big:	Is it a big (double width) or small (single width) character
 *	dest:	Destination DRAM offset (byte offset)
 *	width:	Width of a OSD line (in DWORDS)
 */
void OSD_copy_one_char(ctmp, big, dest, width)
unsigned int ctmp;
int big, dest, width;
{
    int tmp;
    unsigned short *srcptr;
    unsigned int *lptr;
    unsigned int * dptr;
    unsigned int odd;		/* Is it odd/even WORD boundary?	*/
    unsigned int mem;		/* Memory data (on DWORD access)	*/
#ifdef OSD_COMPRESS
    int new = 1;		/* A new character			*/
    unsigned char scratch_buf[24];	/* To store decompressed data	*/
    unsigned short *bufend = (unsigned short *) &scratch_buf[24];
#endif

    /* 
     * Look up from small (English) font or big (Chinese) font
     * table?
     */
#ifdef OSD_COMPRESS
    /* 
     * For compressed data, "small" & "big" are contained in the same table.
     *
     * Set ctmp to the offset of T_osd_offset_tbl.
     */
    ctmp -= FONT_START;
#else
    if (ctmp < FONT_CSTART) {
    tmp = ctmp - FONT_START;
	tmp *= (OSD_CHAR_HEIGHT/2) * OSD_SM_WIDTH;
	srcptr = &osd_font[tmp];
    } else {
	tmp = ctmp - FONT_CSTART;
	tmp *= (OSD_CHAR_HEIGHT/2) * OSD_LG_WIDTH;
	srcptr = &osd_cfont[tmp];
    }
#endif /* OSD_COMPRESS */

    /*
     * If the offset is in WORD boundary (instead of DWORD
     * boundary), then drop the last 2b, so it is always
     * DWORD aligned from here.
     */
    odd = 0;
    if (dest & 0x2) {
	odd = 1;
	dest &= ~2;
    }
    /* Translate it to non-cachable DRAM offset */
    dptr = (int *) (x12000000 + dest);
    
#ifdef OSD_COMPRESS
    srcptr = bufend;
#endif
    /* Write one small/big character at a time */
    for (tmp = 0; tmp < (OSD_CHAR_HEIGHT/2); tmp++) {
#ifdef OSD_COMPRESS
	if (srcptr >= bufend) {
	    /* Decompress 24B into scratch_buf */
	    OSD_decompression(ctmp, scratch_buf, T_osd_code_book,
			      T_osd_comp_font, T_osd_offset_tbl, new);
	    srcptr = (unsigned short *)scratch_buf;
	    new = 0;	/* Next 24B are no longer from a new character	*/
	}
#endif /* OSD_COMPRESS */

	if (odd) {
	    /* Target DRAM starts from WORD boundary */
	    mem = *dptr & 0xffff0000;
	    *dptr = *srcptr | mem;
	    *(dptr+1) = *(srcptr+1) << 16 | *(srcptr+2);
	    if (big) {
		*(dptr+2) = *(srcptr+3) << 16 | *(srcptr+4);
		mem = *(dptr+3) & 0xffff;
		*(dptr+3) = *(srcptr+5) << 16 | mem;
		srcptr += 3;
	    }
	} else {
	    /* Target DRAM starts from DWORD boundary */
	    if (big) {
		lptr = (unsigned int *) srcptr;
		*dptr = *lptr;
		*(dptr+1) = *(lptr+1);
		*(dptr+2) = *(lptr+2);
		srcptr += 3;
	    } else {
		*dptr = (*srcptr << 16) | *(srcptr+1);
		mem = *(dptr+1) & 0xffff;
		*(dptr+1) = (*(srcptr+2) << 16) | mem;
	    }
	}

	srcptr += 3;
	dptr += width;
    }
}

/*
 *  OSD_clear_all():
 *  This function is used to clear all of the OSD regions at once. 
 *  Calling this function is much more efficient than clearing fifteen 
 *  regions with repeated calls to OSD_clear_region().
 */
void
OSD_clear_all(void)
{
    int i, j;


    {
	dram_clear(OSD_DRAM_START, OSD_DRAM_SIZE); 
    }

    /* Establish difference so that OSD_copy_data() will update */
    for (i = 0; i < OSD_MAX_LINES; i++) 
    {
	for (j = 0; j < OSD_MAX_CHAR; j ++) 
	{
	    OSD_lines[i][j] = FONT_SPACE;
	}
    }

    /* Clearing status bits */
    OSD_displayed_regions =
    OSD_scheduled_regions =
    OSD_update_regions = 
    OSD_suppressed_regions = 0;

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?