📄 grlcd.c
字号:
#include "GrLCD.h"
#include "Font8.h"
#include "Font16.h"
#define CONTRAST 48 // user contrast value - you will need to experiment to
// find best value, or write code to let user change it.
/***************************************
lcd display constants
***************************************/
#define NR_COLS 128
#define NR_ROWS 64
#define NR_PAGS 8
#define DISP_COLL 0
#define DISP_COLH 0x10
#define DISP_VRR 0x20 // resistor ratio set
#define DISP_PWR 0x28 // voltage converter control
#define DISP_LIN 0x40 // starting line set
#define DISP_EVS 0x81 // electronic volume set (follow with value 0-63)
#define DISP_ADC 0xA1 // column address reverse direction
#define DISP_APT 0xA5 // all points on
#define DISP_NRM 0xA6 // normal
#define DISP_REV 0xA7 // reverse
#define DISP_OFF 0xAE
#define DISP_ON 0xAF
#define DISP_PAG 0xB0 // page set
#define DISP_COM 0xC0 // common scan dir
#define DISP_RST 0xE2 // soft reset
#define DISP_NOP 0xE3
#ifdef RMW_USED // if RMW support enabled
#define DISP_RMW 0xE0 // read/modify/write mode
#define DISP_END 0xEE // end of RMW mode
#endif
#ifdef SED1565 // Epson SED1565 controller series
#define DISP_BIA 0xA2 // bias setting
#define GR_FIX 0
#endif
#ifdef KS1713 // Samsung KS0713/1713 series
#define DISP_BIA 0xA3 // bias setting
#define GR_FIX 4 // column offset for KS0713 controller
#endif
#define CMD_DELAY 0xFE // do a 10 mS delay during init
#define INIT_END 0xFF
static const BYTE JustTbl[8] = {
0, NR_COLS/4, // L00J,L25J
NR_COLS/3, NR_COLS/2, // L33J,C50J
(NR_COLS*2)/3, (NR_COLS*3)/4, // R66J,R75J
NR_COLS, 0 // R100J,ABSJ
};
BYTE invertflg = 0; // normally 0, to invert data set to 0xFF
BYTE CJ_code = 0; // control/justify code for text display
BYTE contrast = CONTRAST; // user contrast setting
BYTE startcol; // save starting col for later use
BYTE column; // current col
BYTE pagenr;
static const BYTE GrLCDIni[21] = {
DISP_RST, // soft reset
CMD_DELAY, // delay
DISP_ADC, // normal column dir
DISP_COM, // normal common mode
DISP_BIA, // bias
DISP_NRM, // normal video
DISP_VRR+6, // evolume resistor ratio
DISP_EVS, // set evolume
0x20, // arbitrary initial contrast
DISP_PWR+4, // charge pumps on
CMD_DELAY, // delay
DISP_PWR+6, // voltage reg on
CMD_DELAY, // delay
DISP_PWR+7, // follower on
CMD_DELAY, // delay
DISP_ON, // display on
DISP_LIN, // set starting line
DISP_PAG, // set page 0
DISP_COLL, // set column 0
DISP_COLH,
INIT_END
};
/***********************************************************
Check LCD controller busy status. Most graphic controllers
are fast enough that this function is not necessary.
***********************************************************/
static void LCDBusy(void)
{
// here set your LCD data bus port to inputs
LCD_CTRL(RW, 1); // set for read
LCD_CTRL(RS, 0); // set for status
LCD_CTRL(E, 1); // assert enable
while(LCD_DATA & 0x80); // wait for busy bit to go low
LCD_CTRL(E, 0); // de-assert enable
LCD_CTRL(RW, 0); // set for write
// here set your LCD data bus port to outputs
}
/***********************************************************
Write command byte to LCD controller
***********************************************************/
void GrLCDCmd(BYTE arg)
{
LCDBusy(); // wait til not busy, if necessary
LCD_CTRL(RS, 0); // select command entry
LCD_DATA = arg; // put byte on the bus
LCD_CTRL(E, 1); // assert enable
LCD_CTRL(E, 0); // de-assert enable
}
/***********************************************************
Write data byte to LCD controller
***********************************************************/
void GrLCDData(BYTE arg)
{
LCDBusy(); // wait til not busy, if necessary
LCD_CTRL(RS, 1); // select data entry
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW) // if using RMW mode
{
// here set your LCD data bus port to inputs
LCD_CTRL(RW, 1); // set for data read
LCD_CTRL(E, 1); // assert enable for dummy read
LCD_CTRL(E, 0); // de-assert enable
LCD_CTRL(E, 1); // assert enable for actual read
arg |= LCD_DATA; // read display byte
LCD_CTRL(E, 0); // de-assert enable
// here set your LCD data bus port to outputs
LCD_CTRL(RW, 0); // set for write
}
#endif
LCD_DATA = arg ^ invertflg; // put byte on the bus
LCD_CTRL(E, 1); // assert enable for write
LCD_CTRL(E, 0); // de-assert enable
}
/***********************************************************
Initialize display
***********************************************************/
void GrLCDInit(void)
{
const BYTE *bp;
LCD_CTRL(RESET, 1); // assert hardware reset
Sleep(1);
LCD_CTRL(RESET, 0); // de-assert reset
bp = GrLCDIni; // point to init table
while (*bp != INIT_END) // check for end of list
{
if (*bp == CMD_DELAY)
{
Sleep(10);
}
else
{
GrLCDCmd(*bp);
}
bp++;
}
GrLCDClear(); // clear data mamory
Sleep(10); // let voltage charge pump settle
GrLCDCmd(DISP_EVS);
GrLCDCmd(contrast); // set user contrast value
}
/***********************************************************
Clear the display data RAM
***********************************************************/
void GrLCDClear(void)
{
BYTE page, col;
invertflg = 0; // don't invert data
CJ_code = 0; // rmw disabled
for (page = 0; page < NR_PAGS; page++)
{
GrLCDCmd(DISP_PAG + page); // set page number
GrLCDCmd(DISP_COLH); // set column 0
GrLCDCmd(DISP_COLL); // set column 0
for (col = 0; col < NR_COLS + GR_FIX; col++)
{
GrLCDData(0); // write blanx to display
}
}
}
/***********************************************************
Write blank columns to display. Used to clear an area to
update with string of different length, or to blink.
page = starting page
col = starting column
len = number of columns
font = font size (0 = small (1 page), >0 = large (2 page)
***********************************************************/
void GrLCDBlank(BYTE page, BYTE col, BYTE len, BYTE font)
{
BYTE a;
invertflg = 0; // don't invert data
CJ_code = 0; // rmw disabled
GrLCDSetPage(page);
GrLCDSetCol(col);
for (a = 0; a < len; a++)
{
GrLCDData(0); // write blanx to display
}
if (font)
{
GrLCDSetPage(page + 1);
GrLCDSetCol(col);
for (a = 0; a < len; a++)
{
GrLCDData(0); // write blanx to display
}
}
column = col + len; // update current column
}
/***********************************************************
Write a list of strings to the display, list terminated
with a null pointer.
list = pointer to list of String_T pointers
***********************************************************/
void GrLCDList(String_T **list)
{
while (*list != EOL)
{
if (*list == CLEAR) // request to clear display
{
GrLCDClear(); // first in list, if used
}
else
{
GrLCDText(*list); // display the text
}
list++;
}
}
/***********************************************************
Write text string to display.
Sample: String_T str1 = { 2, C50J+FONT16, 0, "Hello World" };
strg = pointer to String_T structure
***********************************************************/
void GrLCDText(String_T *strg)
{
BYTE a, b;
char *cp;
pagenr = strg->page; // save page number
CJ_code = strg->cj_code; // save CJ code
b = CJ_code & JUSTIFY; // isolate justify code
if (b == L00J)
{
column = 0;
}
else if (b == ABSJ)
{
column = strg->abs;
}
else
{
a = GrLCDPixLen(strg->text);// get display length in pixels
if (b != R100J) // if not right justify
{
a /= 2; // use half length for centering
}
column = JustTbl[b] - a; // set starting column
}
if (column >= NR_COLS) // if over/underflow
{
column = 0; // use left justify
}
startcol = column; // save start column
cp = strg->text; // get pointer to the text
while (*cp)
{
if (CJ_code & FONT16) // large font
{
GrLCDLgChar(*cp++);
}
else // small font
{
GrLCDSmChar(*cp++);
}
}
}
/***********************************************************
Write large font character bitmap to display.
***********************************************************/
void GrLCDLgChar(char chr)
{
BYTE len, a;
WORD *bits;
if (chr < firstchr_L) return; // char code out of range
a = chr - firstchr_L;
if (a >= nr_chrs_L) return; // char code out of range
len = lentbl_L[a]; // number of columns
bits = chrtbl_L[a]; // bitmap data pointer
if (len == 0) return;
GrLCDSetPage(pagenr); // set page for first half
GrLCDSetCol(column); // set starting column
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_RMW); // enter RMW mode if needed
}
#endif
for (a = 0; a < len; a++) // do upper half of char
{
GrLCDData(*(bits + a) & 0xFF); // use lower byte of bitmap word
}
if (! (CJ_code & NOSPC))
{
GrLCDData(0); // blank pixel column between chars
}
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_END); // exit RMW mode
}
#endif
GrLCDSetPage(pagenr + 1); // set page for 2nd half
GrLCDSetCol(column); // set starting column
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_RMW); // enter RMW mode if needed
}
#endif
for (a = 0; a < len; a++) // do lower half of char
{
GrLCDData(*(bits + a) >> 8); // upper byte of bitmap word
}
if (! (CJ_code & NOSPC))
{
GrLCDData(0); // blank pixel column between chars
}
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_END); // exit RMW mode
}
#endif
column += len; // update current column
if (! (CJ_code & NOSPC))
{
column++; // include blank between chars
}
}
/***********************************************************
Write small font character bitmap to display.
***********************************************************/
void GrLCDSmChar(char chr)
{
BYTE len, a;
BYTE *bits;
if (chr < firstchr_S) return; // char code out of range
a = chr - firstchr_S;
if (a >= nr_chrs_S) return; // char code out of range
len = lentbl_S[a]; // number of columns
bits = chrtbl_S[a]; // bitmap data pointer
if (len == 0) return;
GrLCDSetPage(pagenr); // set page for first half
GrLCDSetCol(column); // set starting column
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_RMW); // enter RMW mode if needed
}
#endif
for (a = 0; a < len; a++)
{
GrLCDData(*(bits + a)); // bitmap data
}
if (! (CJ_code & NOSPC))
{
GrLCDData(0); // blank pixel column between chars
}
#ifdef RMW_USED // if RMW support enabled
if (CJ_code & USERMW)
{
GrLCDCmd(DISP_END); // exit RMW mode
}
#endif
column += len; // update current column
if (! (CJ_code & NOSPC))
{
column++; // include blank between chars
}
}
/***********************************************************
Write page address to controller
***********************************************************/
void GrLCDSetPage(BYTE page)
{
GrLCDCmd(DISP_PAG + page);
}
/***********************************************************
Write column address to controller
***********************************************************/
void GrLCDSetCol(BYTE col)
{
GrLCDCmd(DISP_COLH + ((col + GR_FIX) >> 4));
GrLCDCmd(DISP_COLL + ((col + GR_FIX) & 0xF));
}
/***********************************************************
Get length of display text, in pixels
***********************************************************/
BYTE GrLCDPixLen(char *chr)
{
BYTE len, first, nrc, *lentbl;
if (CJ_code & FONT16) // large font
{
first = firstchr_L;
lentbl = lentbl_L;
nrc = nr_chrs_L;
}
else // small font
{
first = firstchr_S;
lentbl = lentbl_S;
nrc = nr_chrs_S;
}
len = 0;
while (*chr)
{
if (*chr >= first && ((*chr) - first) < nrc)
{
len += *(lentbl + (*chr) - first);
if (! (CJ_code & NOSPC))
{
len++; // include blank between chars
}
}
chr++;
}
return len;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -