📄 lcd6963.c
字号:
//#include "lpc210x_ver200.h" // SFR declarations
#include "lcd6963.h"
#include "fonts.h"
/* pixel level bit masks for display */
/* this array is setup to map the order */
/* of bits in a byte to the vertical order */
/* of bits at the LCD controller */
const unsigned char l_mask_array[8] =
{0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
/* the LCD display image memory */
/* buffer arranged so page memory is sequential in RAM */
unsigned char l_display_array[Y_BYTES][X_BYTES];
/*
**
** Low level LCD Controller Interface Support Routines
** The LCD Controller interfaces to the microcontroller
** using the connections as shown below.
**
** P2^0 \
** to +- Eight bit Data Bus to/from the LCD controller
** P2^7 /
** P3^0 LCD Controller Chip Select (CE) signal
** P3^1 LCD Controller Ctl/Data Select (C/D) signal
** P3^2 LCD Controller Write (WR/) signal
** P3^3 LCD Controller Read (RD/) signal
** P3^4 LCD Controller Reset (RST/) signal
**
*/
/*
**
** routine to initialize the operation of the LCD display subsystem
**
*/
void lcd_delay(U32 delval) {
// 80 micro sec for 1000
while (delval) {delval--;}
}
void lcd_init(void)
{
IODIR0 |= LCD_CONTROL; // all selected as outputs
IODIR0 |= (LCD_BUSALL);
/* initialize the port control lines to the LCD module */
IOSET0= LCD_CE; /* set chip select high off output */
IOSET0= LCD_RST; /* set RST signal high off output */
IOCLR0= LCD_CD; /* set the CD line low as output */
IOSET0= LCD_RD; /* set RD line high as output */
IOSET0= LCD_WR; /* set WR line high as output */
/* reset the LCD controller chip */
IOCLR0= LCD_RST; /* set the reset line low */
lcd_delay(100000);
IOSET0=LCD_RST; /* release reset to back high */
/* program the controller mode of operation to graphics only mode */
lcd_cmd_2(0x42,0); /* set graphics start at zero */
lcd_cmd_2(0x43,30); /* set number of bytes in horz raster */
lcd_cmd_2(0x40,30*64); /* set text area after the graphics memory */
lcd_cmd_2(0x41,40); /* set number of text characters on row @6 bits */
lcd_cmd(0x81); /* setup mode set for text / graphics XOR */
lcd_cmd(0x98); /* enable graphics only mode / no text no cursor */
lcd_cmd_2(0x24,0); /* setup the AP to 0 */
}
/*
**
** low level routine to send a byte value out port 2 bus
** to the LCD controller data register. entry argument
** is the data to output.
**
*/
void lcd_out_dat(char dat)
{
IODIR0 |= (LCD_BUSALL);
IOCLR0 = (U32)(LCD_BUSALL); /* all low */
IOSET0=LCD_RD; /* make sure the RD/ line is high */
IOCLR0= LCD_CD; /* clr the CD line low to data */
IOSET0 = (U32)(dat<<LCD_BUSPIN0);
IOCLR0=LCD_CE; /* enable chip select */
IOCLR0=LCD_WR; /* set the WR/ line low */
lcd_delay(1);
IOCLR0=LCD_WR; /* extra delay for pulse width */
IOSET0=LCD_WR; /* set the WR/ line back high */
IOSET0= LCD_CE; /* force the CE back high */
IOCLR0 = (U32)(LCD_BUSALL); /* all low */
}
/*
**
** low level routine to send a byte value out port 2 bus
** to the LCD controller control register. entry argument is
** the data to output.
**
*/
void lcd_out_ctl(char dat)
{
IODIR0 |= (LCD_BUSALL);
IOCLR0 = (LCD_BUSALL); /* all low */
IOSET0=LCD_RD; /* make sure the RD/ line is high */
IOSET0= LCD_CD; /* clr the CD line low to data */
IOSET0 = (U32)(dat<<LCD_BUSPIN0);
IOCLR0=LCD_CE; /* enable chip select */
IOCLR0=LCD_WR; /* set the WR/ line low */
lcd_delay(1);
IOCLR0=LCD_WR; /* extra delay for pulse width */
IOSET0=LCD_WR; /* set the WR/ line back high */
IOSET0= LCD_CE; /* force the CE back high */
IOCLR0 = (LCD_BUSALL); /* all low */
}
/*
**
** low level routine to read a byte value from the LCD
** controller data register in via the port 2 bus.
**
*/
char lcd_in_dat(void)
{
char dat;
IODIR0 |= (LCD_BUSALL);
IOCLR0 = (U32)(LCD_BUSALL); /* all low */
IODIR0 &= ~(LCD_BUSALL);
IOSET0= LCD_WR; /* make sure the WR/ line is high */
IOCLR0= LCD_CD; /* clr the CD line low to data */
IOCLR0= LCD_CE; /* enable chip select */
IOCLR0= LCD_RD; /* set the RD/ line low */
lcd_delay(1);
IOCLR0= LCD_RD; /* extra read delay */
dat=(unsigned char)(IOPIN0>>LCD_BUSPIN0); /* fetch in the data */
IOSET0= LCD_RD; /* set the RD/ line back high */
IOSET0= LCD_CE; /* force the CE back high */
return(dat);
}
/*
**
** low level routine to read a byte value from the LCD
** controller status register in via the data bus. the
** entry argument is the interrupt thread mode.
**
*/
char lcd_in_sta(void)
{
char dat;
IODIR0 |= (LCD_BUSALL);
IOCLR0 = (LCD_BUSALL); /* all low */
IODIR0 &= ~(LCD_BUSALL);
IOSET0= LCD_WR; /* make sure the WR/ line is high */
IOSET0= LCD_CD; /* clr the CD line low to data */
IOCLR0= LCD_CE; /* enable chip select */
IOCLR0= LCD_RD; /* set the RD/ line low */
lcd_delay(1);
IOCLR0= LCD_RD; /* extra read delay */
dat=(unsigned char)(IOPIN0>>LCD_BUSPIN0); /* fetch in the data */
IOSET0= LCD_RD; /* set the RD/ line back high */
IOSET0= LCD_CE; /* force the CE back high */
return(dat);
}
/*
**
** low level routine to poll the LCD till the status bits STA0 and STA1
** both report back as 1's to indicate that the chip is ready to take
** a command.
**
*/
void lcd_busy_wait(void)
{
char dat;
lcd_delay(1000);
do
{
dat=lcd_in_sta();
}
while((dat & 0x03) != 0x03); /* wait till STA1=1 && STA0=1 */
}
/*
**
** low level routine to send a two byte command to the LCD
** controller. the two entry parameters are the command code
** and the two byte parameter.
**
*/
void lcd_cmd_2(char cmd,unsigned int parm)
{
lcd_busy_wait(); /* wait for the status */
lcd_out_dat(parm&0xFF); /* send out the low byte of the data */
lcd_busy_wait(); /* wait again for status */
lcd_out_dat(parm>>8); /* send out the high byte of the data */
lcd_busy_wait(); /* wait for status on command */
lcd_out_ctl(cmd); /* send out the command itself */
}
/*
**
** low level routine to send a one byte command to the LCD
** controller. the two entry parameters are the command code
** and the one byte parameter.
**
*/
void lcd_cmd_1(char cmd,unsigned char parm)
{
lcd_busy_wait(); /* wait for the status */
lcd_out_dat(parm); /* send out the byte of the data */
lcd_busy_wait(); /* wait for status on command */
lcd_out_ctl(cmd); /* send out the command itself */
}
/*
**
** low level routine to send a command with no parameters to the LCD
** controller. the entry parameter is the command code
**
*/
void lcd_cmd(char cmd)
{
lcd_busy_wait(); /* wait for status on command */
lcd_out_ctl(cmd); /* send out the command itself */
}
/*
**
** routine to blank the whole LCD display
**
*/
void lcd_erase(void)
{
int x;
int y;
/* loops to write whole LCD memory to a blank pattern */
lcd_cmd_2(0x24,0); /* setup the AP to 0 */
for(x=0; x<X_BYTES; x++)
{
for(y=0; y<Y_BYTES; y++)
{
lcd_cmd_1(0xC0,0);
}
}
}
/*
**
** routine to test the LCD display by writing a pattern to the LCD controller
** memory and then reading it back to verify the correct operation.
** The entry argument will represent the even/odd checkboard pattern selected
** via a 0/1 value.
**
*/
int lcd_test(char test)
{
unsigned char row,byte;
int err_flag=0;
unsigned char dat;
/* write all of the memory with the pattern data */
for(row=0; row<Y_BYTES; row++)
{
/* set addr ptr to start of line */
lcd_cmd_2(0x24,row*X_BYTES);
for(byte=0; byte<X_BYTES; byte++)
{
if(( (row&0x04) && test) ||
(!(row&0x04) && !test))
{
lcd_cmd_1(0xC0,0x0F);
}
else
{
lcd_cmd_1(0xC0,0xF0);
}
}
}
/* read back the pattern data to verify that it is correct */
for(row=0; row<Y_BYTES; row++)
{
/* set addr ptr to start of line */
lcd_cmd_2(0x24,row*X_BYTES);
for(byte=0; byte<X_BYTES; byte++)
{
if(( (row&0x04) && test) ||
(!(row&0x04) && !test))
{
lcd_cmd(0xC1);
lcd_busy_wait();
dat=lcd_in_dat();
if(dat != 0x0F)
{
err_flag=1; /* show read back failure */
}
}
else
{
lcd_cmd(0xC1);
lcd_busy_wait();
dat=lcd_in_dat();
if(dat != 0xF0)
{
err_flag=1; /* show read back failure */
}
}
}
}
return(err_flag); /* show test result */
}
/*
**
** Clears the display memory starting at the left/top and going to
** the right/bottom . No runtime error checking is performed. It is
** assumed that left is less than right and that top is less than
** bottom
**
*/
void lcd_clear_area(unsigned char left, unsigned char top,
unsigned char right, unsigned char bottom)
{
unsigned char bit_pos;
unsigned char y;
unsigned char byte_offset;
unsigned char x_bits;
unsigned char remaining_bits;
unsigned char mask;
bit_pos = left & 0x07; /* get starting bit offset into byte */
for(y = top; y <= bottom; y++)
{
byte_offset = left >> 3; /* get byte offset into x direction */
x_bits = (right - left) + 1; /* get length in the x direction to write */
remaining_bits = 8 - bit_pos; /* number of bits left in byte */
mask = l_mask_array[bit_pos]; /* get mask for this bit */
while(x_bits) /* while there are still bits to write */
{
if((remaining_bits == 8) && (x_bits > 7))
{
/* here if we are byte aligned and have at least 1 byte to write */
/* do the entire byte at once instead of bit by bit */
while(x_bits > 7) /* while there are at least 8 more bits to do */
{
l_display_array[y][byte_offset] = 0x00;
byte_offset++;
x_bits -= 8;
}
}
else
{
/* here if not byte aligned or an entire byte does not need written */
/* thus do bit by bit */
l_display_array[y][byte_offset] &= ~mask;
if(l_mask_array[0] & 0x80)
{
mask >>= 1;
}
else
{
mask <<= 1;
}
x_bits--;
remaining_bits--;
if(remaining_bits == 0)
{
/* might have bust gotton byte aligned */
/* so reset for beginning of a byte */
remaining_bits = 8;
byte_offset++;
mask = l_mask_array[0];
}
}
}
}
}
/*
**
** Inverts the display memory starting at the left/top and going to
** the right/bottom. No runtime error checking is performed. It is
** assumed that left is less than right and that top is less than
** bottom
**
*/
void lcd_invert_area(unsigned char left, unsigned char top,
unsigned char right, unsigned char bottom)
{
unsigned char bit_pos;
unsigned char y;
unsigned char byte_offset;
unsigned char x_bits;
unsigned char remaining_bits;
unsigned char mask;
bit_pos = left & 0x07; /* get starting bit offset into byte */
for(y = top; y <= bottom; y++)
{
byte_offset = left >> 3; /* get byte offset into x direction */
x_bits = (right - left) + 1; /* get length in the x direction to write */
remaining_bits = 8 - bit_pos; /* number of bits left in byte */
mask = l_mask_array[bit_pos]; /* get mask for this bit */
while(x_bits) /* while there are still bits to write */
{
if((remaining_bits == 8) && (x_bits > 7))
{
/* here if we are byte aligned and have at least 1 byte to write */
/* do the entire byte at once instead of bit by bit */
while(x_bits > 7) /* while there are at least 8 more bits to do */
{
l_display_array[y][byte_offset] ^= 0xFF;
byte_offset++;
x_bits -= 8;
}
}
else
{
/* here if not byte aligned or an entire byte does not need written */
/* thus do bit by bit */
l_display_array[y][byte_offset] ^= mask;
if(l_mask_array[0] & 0x80)
{
mask >>= 1;
}
else
{
mask <<= 1;
}
x_bits--;
remaining_bits--;
if(remaining_bits == 0)
{
/* might have bust gotton byte aligned */
/* so reset for beginning of a byte */
remaining_bits = 8;
byte_offset++;
mask = l_mask_array[0];
}
}
}
}
}
/*
**
** Draws a line into the display memory starting at left going to
** right, on the given row. No runtime error checking is performed.
** It is assumed that left is less than right.
**
*/
void lcd_horz_line(unsigned char left, unsigned char right,
unsigned char row)
{
unsigned char bit_pos;
unsigned char byte_offset;
unsigned char x_bits;
unsigned char remaining_bits;
unsigned char mask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -