⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display.c

📁 嵌入式系统基础课件
💻 C
字号:
/* ============================================================ */
/* File: DISPLAY.C						*/
/*								*/
/* Copyright (C) 2001, Daniel W. Lewis and Prentice-Hall	*/
/*								*/
/* Purpose: Library routines for access to the display.		*/
/* See file LIBEPC.H for function descriptions.			*/
/*								*/
/* Designed for use with the DJGPP port of the GNU C/C++	*/
/* protected mode 386 compiler.					*/
/*								*/
/* Modification History:					*/
/*								*/
/* ============================================================ */

#include "libepc.h"

#define	DISPLAY_ROWS		25
#define	DISPLAY_COLS		80

#define	CHAR_ATTB(ch, attb)	(((attb) << 8) | (ch))

PRIVATE int		Digits(unsigned, int) ;
PRIVATE void		Detect_CRTC(void) ;
PRIVATE void		CR(void) ;
PRIVATE void		LF(void) ;

PRIVATE WORD16 *	_display_buffer = 0 ;
PRIVATE int		_crtc_ndex_port ;
PRIVATE int		_crtc_data_port ;
PRIVATE int		_cursRow = 0 ;
PRIVATE int		_cursCol = 0 ;

#define	MDA_NDEX_PORT	0x3B4
#define	MDA_DATA_PORT	0x3B5

#define	CGA_NDEX_PORT	0x3D4
#define	CGA_DATA_PORT	0x3D5

#define	INDEX_MSB_CURS_POS	0x0E
#define	INDEX_LSB_CURS_POS	0x0F

#define	INDEX_CURS_START	0x0A

/* ------------------------------------------------------------ */
/* Public functions ...						*/
/* ------------------------------------------------------------ */
void SetCursorVisible(BOOL visible)
	{
	BYTE8 top ;

	Detect_CRTC() ;

	PUSHF ;
	CLI ;
	outportb(_crtc_ndex_port, INDEX_CURS_START) ;
	top = inportb(_crtc_data_port) ;
	if (visible) top &= ~0x20 ;
	else top |= 0x20 ;
	outportb(_crtc_ndex_port, INDEX_CURS_START) ;
	outportb(_crtc_data_port, top) ;
	POPF ;
	}

int GetCursorRow(void)
	{
	return _cursRow ;
	}

int GetCursorCol(void)
	{
	return _cursCol ;
	}

void SetCursorPosition(int row, int col)
	{
	WORD16 cursorPos ;

	Detect_CRTC() ;

	_cursRow = row ;
	_cursCol = col ;
	cursorPos = DISPLAY_COLS * row + col ;

	PUSHF ;
	CLI ;
	outportb(_crtc_ndex_port, INDEX_LSB_CURS_POS) ;
	outportb(_crtc_data_port, LSB(cursorPos)) ;
	outportb(_crtc_ndex_port, INDEX_MSB_CURS_POS) ;
	outportb(_crtc_data_port, MSB(cursorPos)) ;
	POPF ;
	}

void ClearScreen(BYTE8 attb)
	{
	WORD16 char_attb = CHAR_ATTB(' ', attb) ;
	WORD16 *p = Cell(0, 0) ;
	int cell ;

	for (cell = 0; cell < DISPLAY_ROWS * DISPLAY_COLS; cell++)
		{
		*p++ = char_attb ;
		}
	}

void PutAttb(BYTE8 attb, int cells)
	{
	BYTE8 *p ;

	p = (BYTE8 *) Cell(_cursRow, _cursCol) ;
	while (cells--)
		{
		p[1] = attb ;
		p += 2 ;
		}
	}

void PutCharAt(char ch, int row, int col)
	{
	*((BYTE8 *) Cell(row, col)) = ch ;
	}

void PutChar(char ch)
	{
	if (ch == '\r') CR() ;
	else if (ch == '\n') LF() ;
	else
		{
		*((BYTE8 *) Cell(_cursRow, _cursCol)) = ch ;
		if (_cursCol >= DISPLAY_COLS - 1) CR(), LF() ;
		else SetCursorPosition(_cursRow, ++_cursCol) ;
		}
	}

void PutString(char *string)
	{
	while (*string) PutChar(*string++) ;
	}

/* ---------------------------------------------------- */
/* Displays at least 'width' digits of a base 'base' 	*/
/* value at the current cursor position, zero-filled on	*/
/* the left.  If 'width' is zero, the number of digits	*/
/* will be the minimum necessary to display the number.	*/
/* ---------------------------------------------------- */
void PutUnsigned(unsigned val, int base, int width)
	{
	char bfr[50] ;
	FormatUnsigned(bfr, val, base, width, '0') ;
	PutString(bfr) ;
	}

/* ---------------------------------------------------- */
/* Converts unsigned to character string. Minimum field	*/
/* width given by 'width'; if negative, number is left-	*/
/* justified within field. Field is filled with 'fill'.	*/
/* ---------------------------------------------------- */
char *FormatUnsigned(char *bfr, unsigned val, int base, int width, char fill)
	{
	int digits = Digits(val, base) ;
	while (digits <  width) digits++, *bfr++ = fill ;
	bfr = Unsigned2Ascii(bfr, val, base) ;
	while (digits < -width) digits++, *bfr++ = fill ;
	*bfr = '\0' ;
	return bfr ;
	}

char *Unsigned2Ascii(char *bfr, unsigned val, int base)
	{
	static char digits[] = "0123456789ABCDEF" ;

	if (base <  2) base = 2 ;
	if (base > 16) base = 16 ;
	if (val >= base) bfr = Unsigned2Ascii(bfr, val / base, base) ;
	*bfr++ = digits[(int) (val % base)] ;
	*bfr = '\0' ;
	return bfr ;
	}

WORD16 *Cell(int row, int col)
	{
	Detect_CRTC() ;
	return &_display_buffer[DISPLAY_COLS * row + col] ;
	}

/* ------------------------------------------------------------ */
/* Private functions ...					*/
/* ------------------------------------------------------------ */
PRIVATE void CR(void)
	{
	SetCursorPosition(_cursRow, 0) ;
	}

PRIVATE void Copy(void *dst, void *src, int bytes)
	{
	register char *fm = src ;
	register char *to = dst ;
	while (bytes--) *to++ = *fm++ ;
	}

PRIVATE void LF(void)
	{
	static int bytes = (DISPLAY_ROWS - 1) * DISPLAY_COLS * sizeof(WORD16);
	static WORD16 char_attb = CHAR_ATTB(' ', 0x07) ;
	WORD16 *p ;
	int col ;

	if (_cursRow < DISPLAY_ROWS)
		{
		SetCursorPosition(++_cursRow, _cursCol) ;
		return ;
		}

	Copy(Cell(0, 0), Cell(1, 0), bytes) ;
	p = Cell(24, 0) ;
	for (col = 0; col < DISPLAY_COLS; col++) *p++ = char_attb ;
	}

PRIVATE void Detect_CRTC(void)
	{
	BYTE8 old, chk55, chkAA ;

	if (_display_buffer) return ;

	PUSHF ;
	CLI ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	old = inportb(CGA_DATA_PORT) ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	outportb(CGA_DATA_PORT, 0x55) ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	chk55 = inportb(CGA_DATA_PORT) ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	outportb(CGA_DATA_PORT, 0xAA) ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	chkAA = inportb(CGA_DATA_PORT) ;

	outportb(CGA_NDEX_PORT, INDEX_LSB_CURS_POS) ;
	outportb(CGA_DATA_PORT, old) ;

	POPF ;

	if (chk55 == 0x55 && chkAA == 0xAA)
		{
		_display_buffer = (WORD16 *) 0xB8000 ;
		_crtc_ndex_port = CGA_NDEX_PORT ;
		_crtc_data_port = CGA_DATA_PORT ;
		}
	else
		{
		_display_buffer = (WORD16 *) 0xB0000 ;
		_crtc_ndex_port = MDA_NDEX_PORT ;
		_crtc_data_port = MDA_DATA_PORT ;
		}
	}

PRIVATE int Digits(unsigned val, int base)
	{
	register int digits ;

	digits = 1 ;
	while (val >= base)
		{
		val /= base ;
		digits++ ;
		}
	return digits ;
	}

⌨️ 快捷键说明

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