📄 osdcore.c
字号:
/* Copyright 1996, ESS Technology, Inc. *//* SCCSID @(#)osdcore.c 4.8 04/27/04 */ /* * $Log$ */#include "common.h"#include "memmap.h"#include "const.h"#include "display.h"#include "fsosd.h"#include "util.h"#include "mvd.h"#ifdef PLAY20#include "vcd.h"#endif#define EPRINTF(a)/************************************************************************ * Local variables ************************************************************************/static int osd_voffset;static int osd_hoffset = 0;/* * 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. */#ifdef USE_VWCOMP#define DECODE_SIZE 192 /* Bytes */extern int newicon_decomp(uchar *out, uchar *in, uchar *codebook, int width, int height);#else#define DECODE_SIZE 24 /* Bytes */extern void OSD_decompression (int, unsigned char *, unsigned char *, unsigned char *, unsigned short *, int);#endif /* USE_VWCOMP *//* * 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_start + OSD_LINE_NUM(region) * OSD_dram_dx * OSD_CHAR_HEIGHT/2) << 2; for (count = 0; offset < end; ) { unsigned int new_ch, ctmp = osd_new[count]; /* Check if we really need to copy */#ifdef USE_CN_HEADER big = (ctmp == CN_HEADER); if (big) { ctmp = osd_new[count+1]; new_ch = ((current[pos+1] != CN_HEADER) || (current[pos] != ctmp)); } else { new_ch = ((current[pos+1] == CN_HEADER) || (current[pos] != ctmp)); }#else big = (ctmp >= FONT_CSTART); new_ch = (current[pos] != ctmp);#endif if (new_ch) { /* 6Bytes per char width */ dest = head + (offset << 2) + (offset << 1); OSD_copy_one_char(ctmp, big, dest, OSD_dram_dx); current[pos] = ctmp; } count++; pos++; offset++; if (big) {#ifdef USE_CN_HEADER current[pos] = CN_HEADER; /* for checking new char */#else current[pos] = ctmp; /* 'big' uses 2 char positions */#endif 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) */ int new = 1; /* A new character */ unsigned char scratch_buf[DECODE_SIZE];/* To store decompressed dat */ unsigned short *bufend = (unsigned short *) &scratch_buf[DECODE_SIZE]; unsigned char *code_book, *comp_font; unsigned short *offset_tbl; /* * 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); /* * Look up from small (English) font or big (Chinese) font * table? */#ifdef USE_CN_HEADER#ifdef BILINGUAL_OSD if (big) { tmp = 2; /* Chinese font data */ ctmp -= FONT_CSTART; code_book = T_osd_cfonts_code_book; comp_font = T_osd_cfonts_comp_font; offset_tbl = T_osd_cfonts_offset_tbl; } else#endif { tmp = 1; /* English font data */ ctmp -= FONT_START; code_book = T_osd_efonts_code_book; comp_font = T_osd_efonts_comp_font; offset_tbl = T_osd_efonts_offset_tbl; } #else /* * If not USE_CN_HEADER, "small" & "big" are contained in the * same table. */ ctmp -= FONT_START; code_book = T_osd_code_book; comp_font = T_osd_comp_font; offset_tbl = T_osd_offset_tbl;#endif /* USE_CN_HEADER */#ifdef USE_VWCOMP /* Decompress 24B into scratch_buf */ newicon_decomp(scratch_buf, comp_font+offset_tbl[ctmp], code_book, 6*tmp, OSD_CHAR_HEIGHT/2); srcptr = (unsigned short *)scratch_buf;#else srcptr = bufend;#endif /* USE_VWCOMP */ /* Write one small/big character at a time */ for (tmp = 0; tmp < (OSD_CHAR_HEIGHT/2); tmp++) {#ifndef USE_VWCOMP if (srcptr >= bufend) { /* Decompress 24B into scratch_buf */ OSD_decompression(ctmp, scratch_buf, code_book, comp_font, offset_tbl, new); srcptr = (unsigned short *)scratch_buf; new = 0; /* Next 24B are no longer from a new character */ }#endif 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(). */voidOSD_clear_all(int dummy){ int i, j; int osd_size_to_clear; osd_size_to_clear = (OSD_displayed_regions & NPOSD_MASK) ? OSD_AREA1_SIZE : OSD_size; dram_clear(OSD_start, osd_size_to_clear); /* 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_scheduled_regions = OSD_update_regions = OSD_suppressed_regions = 0; OSD_displayed_regions &= NPOSD_MASK; } /***************************************************************************** Vertical shift *****************************************************************************/void OSD_vertical_shift(int offset){ osd_voffset = offset;}/***************************************************************************** Horizontal shift *****************************************************************************/void OSD_horizontal_shift(int offset){ osd_hoffset = offset;}/* Called in display interrupt service */void OSD_setup(int field) { int dy; int ystart, ysize; mvd[vid_scn_osd_hstart] = OSD_HORZ_POS + osd_hoffset; mvd[vid_scn_osd_hend] = OSD_HORZ_POS+(OSD_dram_dx<<4)+osd_hoffset; if (field == -1) { mvd[vid_scn_osd_vstart] = vid_scn_osd_vstart2 + osd_voffset; mvd[vid_scn_osd_vend] = vid_scn_osd_vend2 + osd_voffset; } else { mvd[vid_scn_osd_vstart] = vid_scn_osd_vstart1 + osd_voffset; mvd[vid_scn_osd_vend] = vid_scn_osd_vend1 + osd_voffset; if (OSD_displayed_regions) { dy = OSD_dram_dy;#ifdef NON_PLAY_OSD if (OSD_displayed_regions & NPOSD_MASK) { dy += NPOSD_DRAM_DY; }#endif buscon_xfer(ysn, BDMA_USEDX, OSD_start, dy, OSD_dram_dx); mvd[vid_scn_osd_misc] = (OSD_total_areas == 2) ? 0x9 : 0x1; } } }#ifdef EQUALIZER/* * OSD_paint_rect(): * Paint a specified OSD region (inclusive) * * Inputs: * X * +------> * | (x1,y1) pixel * | +-------------------------- --- * Y | | | ^ * V | (color) | height(in dram) * | | v * --------------------------+ --- * * |<-------- width --------->| * * Limits: * - x1 >= 0, (x1+width) <= 480 (24 * OSD_MAX_CHAR) * - y1 >= 0, (y1+height) <= 80 (16 * OSD_MAX_LINES) */#define PIXELS_IN_DW 16 /* 16 for 2b-OSD, 8 for 4b-OSD */void OSD_paint_rect(int x1, int y1, int width, int height, unsigned int color){ int i, tmp, offset, dw_offset, ndw, dest; unsigned int *dptr, *hstart; unsigned int data, mask, end_mask; unsigned short OSD_masks[] = { 0xffff,0x3fff,0x0fff,0x03ff, 0x00ff,0x003f,0x000f,0x0003#if 0 /*for 4bit osd*/ 0xffff,0x0fff,0x00ff,0x000f#endif }; /* Beware of limits above..only rudimentary checks here */ if (x1 < 0 || (x1 + width) > 480 || y1 < 0 || (y1 + height) > 80) return; if ((width<PIXELS_IN_DW) || (height<=0)) return; /* "color" == 16 pixel length of index of OSD_palette_2b[] */ data = (color<<16) | color; /* 16 pixel length of color */ /* dram start */ dw_offset = (x1/PIXELS_IN_DW); offset = x1 - (dw_offset * PIXELS_IN_DW); dest = OSD_start + y1*OSD_dram_dx + dw_offset; /* for buscon */ dptr = (unsigned int *)dram(dest); /* 0 <= offset <= 15 */ mask = (offset < PIXELS_IN_DW/2) ? (unsigned int) ((OSD_masks[offset]<<16) | 0xffff) : (unsigned int) (OSD_masks[offset-PIXELS_IN_DW/2]); /* currently only used for EQ (width over one DW)..save some code */ hstart = dptr; tmp = width - (PIXELS_IN_DW-offset); ndw = (tmp/PIXELS_IN_DW); offset = tmp - (ndw*PIXELS_IN_DW); /* 0 <= offset <= 15 */ end_mask = (offset < PIXELS_IN_DW/2) ? (unsigned int) ((OSD_masks[offset]<<16) | 0xffff) : (unsigned int) (OSD_masks[offset-PIXELS_IN_DW/2]); for (i = 0; i < height; i++) { *dptr = ((*dptr++ & ~mask) | (data & mask)); tmp = ndw; while (tmp) { *dptr++ = data; tmp--; }; *dptr = ((*dptr & end_mask) | (data & ~end_mask)); dptr = hstart += OSD_dram_dx; }}/* * OSD_put_one_char(): * Put a font at specified location with specified color palette. * * Inputs: * ch_x, ch_y: character location (not pixel location) * ch: single font to display * * NOTE: * - only for 2bit mode. */void OSD_put_one_char(int ch_x, int ch_y, uchar ch){ int i, dest, tmp; /* dram start in byte address */ dest = ((OSD_start + ch_y*OSD_dram_dx*OSD_CHAR_HEIGHT/2)<<2) + (ch_x<<2) + (ch_x<<1); OSD_copy_one_char(ch, 0, dest, OSD_dram_dx);}/* * OSD_paint_spectrum() * Paint the "spectrum level" at specified frequency. * * Inputs: * px, py, py_old: pixel location of top of level/level_old. * level, level_old: 0 =< value <= 23 * * * X * +------> * | (px,py) * | +--------------------------+ --- * Y | | sp_color[i] | ^ * V +--------------------------+ | * | * +--------------------------+ | * | sp_color[i] | | * +--------------------------+ | * | * ~ ~ height (based on level) * ~ ~ | * | * +--------------------------+ | * | sp_color[i] | | * +--------------------------+ | * | * +--------------------------+ | * | sp_color[i] | v * +--------------------------+ --- * * |<------ 22 pixels-------->| * */void OSD_paint_spectrum(int px, int py, int py_old, int level, int level_old){ int i, limit; ushort sp_color[] = {0xaaaa,0x5555}; if (level < level_old) { /* clear old level */ OSD_paint_rect(px, py_old, 22, 2*(level_old-level), 0); } else { for (i=level; i >= level_old ; i--, py+=2) { OSD_paint_rect(px, py, 22, 1, sp_color[i>>4]); } }}#endif EQUALIZER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -