www.pudn.com > emGUI.rar > lcd.c


/* 
 *  LCD Driver for M68VZ328 
 * 
 * 
 *  COPYRIGHT (c) 2001 - 2010. 
 *  emTech System Corporation. 
 * 
 *  The license and distribution terms for this file may be 
 *  found in found in the file LICENSE. 
 */ 
 
/*	Huangf emcore@263.net 
 */ 
  
/* LCD screen routine for M68VZ328  */ 
unsigned short *lcd_base = 0; 
unsigned short lcd_vpw = 0;		/* count in 16 bits byte,  
								 * for 1 bit mode, it is equal to width/16,  
								 * for 2 bit mode, it is equal to width/8, 
								 * for 4 bit mode, it is equal to width/4 
								 */ 
unsigned short 	lcd_xmax = 0; 
unsigned short 	lcd_ymax = 0; 
unsigned long	_LCD_START_ADDR = 0;		 
#define LCD_CURSOR_MODE(x)		(((x) & 0x0c000) >> 14) 
#define LCD_CURSOR_WIDTH(x)		(((x) >> 8) & 0x1f) 
#define LCD_CURSOR_HEIGHT(x)	((x) & 0x1f) 
#define LCD_CURSOR_BLINK_ENABLED(x)	((x) & 0x80) 
unsigned short lcd_cursor_x = 0; 
unsigned short lcd_cursor_y = 0; 
unsigned short lcd_cursor_wh = 0; 
unsigned char lcd_cursor_blink = 0; 
 
#define LSSA	*(unsigned long *)0xFFFFFA00 
#define LVPW	*(unsigned char *)0xFFFFFA05 
#define LXMAX	*(unsigned short *)0xFFFFFA08 
#define LYMAX	*(unsigned short *)0xFFFFFA0A 
#define LCXP	*(unsigned short *)0xFFFFFA18 
#define LCYP	*(unsigned short *)0xFFFFFA1A 
#define LCWCH	*(unsigned short *)0xFFFFFA1C 
#define LBLCK	*(unsigned char *)0xFFFFFA1F 
#define LPICF	*(unsigned char *)0xFFFFFA20 
#define LPOLCF	*(unsigned char *)0xFFFFFA21 
#define LACDRC	*(unsigned char *)0xFFFFFA23 
#define LPXCD	*(unsigned char *)0xFFFFFA25 
#define LCKCON	*(unsigned char *)0xFFFFFA27 
#define LRRA	*(unsigned short *)0xFFFFFA28 
#define LPOSR	*(unsigned char *)0xFFFFFA2D 
#define LGPMR	*(unsigned char *)0xFFFFFA33 
#define PWMR	*(unsigned short *)0xFFFFFA36 
#define RMCR	*(unsigned char *)0xFFFFFA38 
#define DMACR	*(unsigned char *)0xFFFFFA39 
 
unsigned short lcd_pixel_mask_1bit[16] = {0x7fff, 0xbfff, 0xdfff, 0xefff, 0xf7ff, 0xfbff, 0xfdff, 0xfeff, 0xff7f, 0xffbf, 0xffdf, 0xffef, 0xfff7, 0xfffb, 0xfffd, 0xfffe}; 
unsigned short lcd_pixel_mask_2bit[8] = {0x3fff, 0xcfff, 0xf3ff, 0xfcff, 0xff3f, 0xffcf, 0xfff3, 0xfffc}; 
unsigned short lcd_pixel_mask_4bit[4] = {0x0fff, 0xf0ff, 0xff0f, 0xfff0}; 
unsigned short *lcd_pixel_mask = lcd_pixel_mask_1bit; 
 
unsigned char lcd_pixel_shift_1bit[16] = {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x7, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; 
unsigned char lcd_pixel_shift_2bit[8] = {0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x00}; 
unsigned char lcd_pixel_shift_4bit[4] = {0x0C, 0x08, 0x04, 0x00}; 
unsigned char *lcd_pixel_shift = lcd_pixel_shift_1bit; 
 
unsigned short lcd_color_fullword_1bit[2] = {0x0, 0xffff}; 
unsigned short lcd_color_fullword_2bit[4] = {0x0, 0x5555, 0xaaaa, 0xffff}; 
unsigned short lcd_color_fullword_4bit[16] = {0x0, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff}; 
unsigned short *lcd_color_fullword = lcd_color_fullword_1bit; 
 
unsigned char lcd_pixel_color_mask_[3] = {0x01, 0x03, 0x0f}; 
unsigned char lcd_pixel_color_mask = 0x01; 
 
unsigned char lcd_offset_shift_[3] = {0x04, 0x03, 0x02};	/* /16, /8, /4 */ 
unsigned char lcd_offset_shift = 0x04; 
 
unsigned char lcd_color_shift_[3] = {0x03, 0x02, 0x0}; 
unsigned char lcd_color_shift = 0x07; 
 
unsigned char lcd_bits_per_pixel = 1; 
 
#define LCD_PBUS_SIZE		0x02		/* 4 bit panel bus *//* 0x03 for 8 bits panel bus */ 
 
int SysPixelPerByte() 
{ 
	return 8 / lcd_bits_per_pixel; 
} 
 
int SysBytesPerScreen() 
{ 
	return (lcd_xmax * lcd_ymax) / SysPixelPerByte(); 
} 
 
int _lcd_calcmemgcsize( 
	int l, 
	int t, 
	int r, 
	int b 
) 
{ 
	int w, h; 
 
	h = b - t + 1; 
 
	l = l / SysPixelPerByte(); 
	r = (r + SysPixelPerByte() - 1) / SysPixelPerByte(); 
 
	w = r - l; 
	 
	return (w * h); 
} 
 
void _lcd_savescreen( 
	unsigned char *base, 
	unsigned char *dst, 
	int	 l, 
	int	 t, 
	int	 r, 
	int  b 
) 
{ 
	int w, h; 
	int pos; 
 
	pos = (short)t * (short)lcd_vpw * 2; 
	 
	l = l / SysPixelPerByte(); 
	r = (r + SysPixelPerByte() - 1) / SysPixelPerByte(); 
 
	w = r - l; 
	 
	pos += l; 
	 
	for (h = t; h <= b; h++){ 
		memcpy(dst, base + pos, w); 
		dst += w; 
		pos += (lcd_vpw * 2); 
	} 
} 
 
void _lcd_restorescreen( 
	unsigned char *base, 
	unsigned char *dst, 
	int	 l, 
	int	 t, 
	int	 r, 
	int  b 
) 
{ 
	int w, h; 
	int pos; 
 
	pos = (short)t * (short)lcd_vpw * 2; 
	 
	l = l / SysPixelPerByte(); 
	r = (r + SysPixelPerByte() - 1) / SysPixelPerByte(); 
 
	w = r - l; 
	 
	pos += l; 
	 
	for (h = t; h <= b; h++){ 
		memcpy(base + pos, dst, w); 
		dst += w; 
		pos += (lcd_vpw * 2); 
	} 
} 
 
/* it is very difficult to setup LCD, this function using many default parameters to setup LCD, 
 * so only a few parameters needed for setup LCD here 
 */ 
int lcd_setup(unsigned long start_addr, unsigned short width, unsigned short xmax, unsigned short ymax, unsigned short bits_per_pixel) 
{ 
	/* disable LCD first */ 
	LCKCON = 0x00; 
 
	lcd_xmax = xmax; 
	lcd_ymax = ymax; 
	 
	/* setup LSSA */ 
	LSSA = start_addr; 
	{ 
		unsigned char *base = (unsigned char *)start_addr; 
		int i; 
		for (i = 0; i < width * ymax; i++){ 
			*base++ = 0xff; 
		} 
	} 
 
	_LCD_START_ADDR = start_addr; 
	LXMAX = xmax; 
	LYMAX = ymax - 1; 
	 
	switch(bits_per_pixel){ 
		case 1: 
			LVPW = width / 16; 
			LPICF = (LCD_PBUS_SIZE << 2); 
			break; 
		case 2: 
			LVPW = width / 8; 
			LPICF = (LCD_PBUS_SIZE << 2) + 0x01; 
			break; 
		case 4: 
			LVPW = width / 4; 
			LPICF = (LCD_PBUS_SIZE << 2) + 0x10; 
			break; 
		default: 
			LVPW = width / 16; 
			LPICF = (LCD_PBUS_SIZE << 2); 
	} 
	 
	LPOLCF = 0x01; 
	LACDRC = 0x00; 
	LPXCD = 0x02; 
	LRRA = 0x14; 
	LPOSR = 0x00; 
	 
	/* Enable LCD */ 
	LCKCON = 0x00; 
	LCKCON = 0x80; 
	 
	return 0; 
} 
 
void _lcd_switchbase( 
	void *base 
) 
{ 
	lcd_base = base; 
	/* setup LSSA */ 
	LSSA = (unsigned long)base; 
} 
 
int lcd_getdisplay() 
{ 
	lcd_base = 	(unsigned short *)LSSA; 
	lcd_vpw = LVPW; 
	 
	{ 
		unsigned char lpicf = LPICF; 
		 
			 
		switch(lpicf & 0x03){ 
			case 0: 
				lcd_pixel_mask = lcd_pixel_mask_1bit; 
				lcd_pixel_shift = lcd_pixel_shift_1bit; 
				lcd_pixel_color_mask = lcd_pixel_color_mask_[0]; 
				lcd_offset_shift = lcd_offset_shift_[0]; 
				lcd_color_shift = lcd_color_shift_[0]; 
				lcd_color_fullword = lcd_color_fullword_1bit; 
				lcd_bits_per_pixel = 1; 
				break; 
				 
			case 1: 
				lcd_pixel_mask = lcd_pixel_mask_2bit; 
				lcd_pixel_shift = lcd_pixel_shift_2bit; 
				lcd_pixel_color_mask = lcd_pixel_color_mask_[1]; 
				lcd_offset_shift = lcd_offset_shift_[1]; 
				lcd_color_shift = lcd_color_shift_[1]; 
				lcd_color_fullword = lcd_color_fullword_2bit; 
				lcd_bits_per_pixel = 2; 
				break; 
 
			case 2: 
				lcd_pixel_mask = lcd_pixel_mask_4bit; 
				lcd_pixel_shift = lcd_pixel_shift_4bit; 
				lcd_pixel_color_mask = lcd_pixel_color_mask_[2]; 
				lcd_offset_shift = lcd_offset_shift_[2]; 
				lcd_color_shift = lcd_color_shift_[2]; 
				lcd_color_fullword = lcd_color_fullword_4bit; 
				lcd_bits_per_pixel = 4; 
				break; 
				 
			default: 
				lcd_pixel_mask = lcd_pixel_mask_1bit; 
				lcd_pixel_shift = lcd_pixel_shift_1bit; 
				lcd_pixel_color_mask = lcd_pixel_color_mask_[0]; 
				lcd_offset_shift = lcd_offset_shift_[0]; 
				lcd_color_shift = lcd_color_shift_[0]; 
				lcd_color_fullword = lcd_color_fullword_1bit; 
				lcd_bits_per_pixel = 1; 
		} 
	} 
	 
	return 0; 
} 
 
int lcd_getx() 
{ 
	return LXMAX; 
} 
 
int lcd_gety() 
{ 
	return LYMAX; 
} 
 
int lcd_getvx() 
{ 
	return lcd_getx(); 
} 
 
int _lcd_putpixel(unsigned short *_base, short x, short y, unsigned char c, int xorm) 
{ 
	unsigned short oldc; 
	int pos = (short)y * (short)lcd_vpw; 
	pos += (x >> lcd_offset_shift); 
	 
	x -= ((x >> lcd_offset_shift) << lcd_offset_shift);	/* bits in current bytes */ 
 
	/* inverse color */ 
	/* c = 15 - c; */ 
	 
	oldc = _base[pos]; 
	if (xorm){		/* usinf XOR mode */ 
		oldc ^= ((c >> lcd_color_shift) << lcd_pixel_shift[x]); 
	} 
	else{ 
		oldc &= lcd_pixel_mask[x]; 
		oldc |= ((c >> lcd_color_shift) << lcd_pixel_shift[x]); 
	} 
	_base[pos] = oldc; 
	 
	return 0; 
} 
 
int lcd_putpixel(short x, short y, unsigned char c, int xorm) 
{ 
	return _lcd_putpixel( 
		lcd_base, 
		x, 
		y, 
		c, 
		xorm 
	); 
} 
	 
int _lcd_getpixel(unsigned short *_base, short x, short y) 
{ 
	unsigned short oldc; 
	int pos = (short)y * (short)lcd_vpw; 
	pos += (x >> lcd_offset_shift); 
	 
	x -= ((x >> lcd_offset_shift) << lcd_offset_shift);	/* bits in current bytes */ 
	 
	oldc = _base[pos]; 
	oldc >>= lcd_pixel_shift[x]; 
	oldc &= lcd_pixel_color_mask; 
 
	/* inverse color */ 
	return oldc; 
} 
 
int lcd_getpixel( 
	short x,  
	short y 
) 
{ 
	return _lcd_getpixel( 
		lcd_base, 
		x, 
		y 
	); 
} 
 
 
/*	quick method for drawing bitmap 
 */ 
int _lcd_bitmap(unsigned short *_base, short x0, short y0, short width, short height, unsigned char *pcc, int xorm) 
{ 
  unsigned char *src  = pcc; 
  unsigned char *dst  = (unsigned char *)(_base + y0 * lcd_vpw);   
  unsigned short leng = (width + 31) >> 5; 
  unsigned short len  = ((width) >> 3); 
  int i, j; 
   
  dst += (x0 >> (lcd_offset_shift - 1)); 
  leng <<= 2; 
 
  src += leng * (height - 1); 
  for (i = 0; i < height; i++){ 
     
    for (j = 0; j < len; j++){ 
      dst[j] = src[j]; 
    } 
    dst += (lcd_vpw * 2); 
    src -= leng; 
  } 
  return 0;     
} 
 
int lcd_bitmap( 
	short x0,  
	short y0,  
	short width,  
	short height,  
	unsigned char *pcc,  
	int xorm 
) 
{ 
	return _lcd_bitmap( 
		lcd_base, 
		x0, 
		y0, 
		width, 
		height, 
		pcc, 
		xorm 
	); 
}	 
/* quick method for hline */ 
int _lcd_hline(unsigned short *_base, short x1, short y, short x2, unsigned char c, int xorm) 
{ 
	/* a very slow version */ 
	int count; 
	unsigned short oldc; 
	int pos = (short)y * (short)lcd_vpw; 
	int pixels_per_word = 1 << lcd_offset_shift; 
 
	/* inverse */ 
	/* c = 15 - c; */ 
	 
	if (x2 < x1){ 
		int t = x2; 
		x2 = x1; 
		x1 = t; 
	} 
	 
	count = x2 - x1; 
	 
	pos += (x1 >> lcd_offset_shift); 
	 
	x1 -= ((x1 >> lcd_offset_shift) << lcd_offset_shift);	/* bits in current bytes */ 
	if (x1){ 
		/* first part */ 
		oldc = _base[pos]; 
		while((x1 < pixels_per_word) && (count > 0)){ 
			if (xorm){		/* usinf XOR mode */ 
				oldc ^= ((c >> lcd_color_shift) << lcd_pixel_shift[x1]); 
			} 
			else{ 
				oldc &= lcd_pixel_mask[x1]; 
				oldc |= ((c >> lcd_color_shift) << lcd_pixel_shift[x1]); 
			} 
			x1++; 
			count--; 
		} 
		_base[pos++] = oldc; 
	} 
	 
	while(count >= pixels_per_word){ 
		oldc = _base[pos]; 
		if(xorm){ 
			oldc ^= lcd_color_fullword[c >> lcd_color_shift]; 
		} 
		else{ 
			oldc = lcd_color_fullword[c >> lcd_color_shift]; 
		} 
		count -= pixels_per_word; 
		_base[pos++] = oldc; 
	} 
	 
	oldc = _base[pos]; 
	x1 = 0; 
	while(count > 0){ 
		if (xorm){		/* usinf XOR mode */ 
			oldc ^= ((c >> lcd_color_shift) << lcd_pixel_shift[x1]); 
		} 
		else{ 
			oldc &= lcd_pixel_mask[x1]; 
			oldc |= ((c >> lcd_color_shift) << lcd_pixel_shift[x1]); 
		} 
		x1++; 
		count--; 
	} 
	_base[pos] = oldc; 
	 
	return 0; 
/*	 
		 
	for (i = x1; i <= x2; i++){ 
		lcd_putpixel(i, y, c, xorm); 
	} 
	 
	return 0; 
*/	 
} 
 
int lcd_hline( 
	short x1,  
	short y,  
	short x2,  
	unsigned char c,  
	int xorm 
) 
{ 
	return _lcd_hline( 
		lcd_base, 
		x1, 
		y, 
		x2, 
		c, 
		xorm 
	); 
} 
 
/* quick method for vline */ 
int _lcd_vline(unsigned short *_base, short x, short y1, short y2, unsigned char c, int xorm) 
{ 
	/* a very slow version */ 
	int i; 
	int pos; 
	unsigned short oldc, color; 
	if (y2 < y1){ 
		int t = y2; 
		y2 = y1; 
		y1 = t; 
	} 
 
	/* inverse color */ 
	/* c = 15 - c; */ 
	 
	pos = (short)y1 * (short)lcd_vpw; 
	pos += (x >> lcd_offset_shift); 
	x -= ((x >> lcd_offset_shift) << lcd_offset_shift);	/* bits in current bytes */ 
	 
	color = ((c >> lcd_color_shift) << lcd_pixel_shift[x]); 
	for (i = y1; i <= y2; i++){ 
		oldc = _base[pos]; 
		if (xorm){		/* usinf XOR mode */ 
			oldc ^= color; 
		} 
		else{ 
			oldc &= lcd_pixel_mask[x]; 
			oldc |= color; 
		} 
		_base[pos] = oldc; 
		pos += lcd_vpw; 
	} 
	 
	return 0; 
} 
 
int lcd_vline( 
	short x,  
	short y1,  
	short y2,  
	unsigned char c,  
	int xorm 
) 
{ 
	return _lcd_vline( 
		lcd_base, 
		x, 
		y1, 
		y2, 
		c, 
		xorm 
	); 
} 
 
int _lcd_fillrect(unsigned short *_base, short x1, short y1, short x2, short y2, int c) 
{ 
	 
	int y; 
	 
	if (x2 < x1){ 
		int t = x2; 
		x2 = x1; 
		x1 = t; 
	} 
	 
	if (y2 < y1){ 
		int t = y2; 
		y2 = y1; 
		y1 = t; 
	} 
	 
	for (y = y1; y <= y2; y++){ 
		_lcd_hline( 
			_base, 
			x1,  
			y,  
			x2,  
			c,  
			0 
		); 
	} 
	 
	return 0; 
} 
 
int lcd_fillrect(short x1, short y1, short x2, short y2, int c) 
{ 
	return _lcd_fillrect( 
		lcd_base, 
		x1, 
		y1, 
		x2, 
		y2, 
		c 
	); 
} 
#if 0 
int __main() 
{ 
	return 0; 
}	 
 
main() 
{ 
	lcd_setup(0x200000, 160, 160, 240, 2); 
	lcd_getdisplay(); 
	 
	lcd_fillrect(0, 0, 159, 9, 0); 
	 
	lcd_hline(0, 10, 120, 0, 0); 
	 
	lcd_putpixel(0, 100, 1, 0); 
} 
#endif