📄 lcd.c
字号:
/* LCD driver program and routine
Author Donghua Gu
MKS INST */
#include "S1D13700.h"
#include "common.h"
#include "fonts.h"
const bit_mask[] =
{
0x00, //bit_offset = 0 (0000 0000)
0x80, //bit_offset = 1 (1000 0000)
0xC0, //bit_offset = 2 (1100 0000)
0xE0, //bit_offset = 3 (1110 0000)
0xF0, //bit_offset = 4 (1111 0000)
0xF8, //bit_offset = 5 (1111 1000)
0xFC, //bit_offset = 6 (1111 1100)
0xFE, //bit_offset = 7 (1111 1110)
};
/* routine to initialize the operation of the LCD display subsystem */
/* initLCD */
void initLCD()
{
//UINT16 i,j;
MCF_GPIO_SETTD = Set_LCD_RST;
// Step 1: initialize all registers
//System Set
LCD_out_ctrl(CMD_SYSTEM_SET);
LCD_out_data(REG0000_SYSTEMSET_P1);
LCD_out_data(REG0001_SYSTEMSET_P2);
LCD_out_data(REG0002_SYSTEMSET_P3);
LCD_out_data(REG0003_SYSTEMSET_P4);
LCD_out_data(REG0004_SYSTEMSET_P5);
LCD_out_data(REG0005_SYSTEMSET_P6);
LCD_out_data(REG0006_SYSTEMSET_P7);
LCD_out_data(REG0007_SYSTEMSET_P8);
//Scroll
LCD_out_ctrl(CMD_SCROLL);
LCD_out_data(REG000B_SCROLL_P1);
LCD_out_data(REG000C_SCROLL_P2);
LCD_out_data(REG000D_SCROLL_P3);
LCD_out_data(REG000E_SCROLL_P4);
LCD_out_data(REG000F_SCROLL_P5);
LCD_out_data(REG0010_SCROLL_P6);
LCD_out_data(REG0011_SCROLL_P7);
LCD_out_data(REG0012_SCROLL_P8);
LCD_out_data(REG0013_SCROLL_P9);
LCD_out_data(REG0014_SCROLL_P10);
//HDOT SCR
LCD_out_ctrl(CMD_HDOT_SCR);
LCD_out_data(REG001B_HDOTSCR_P1);
//OVLAY
LCD_out_ctrl(CMD_OVLAY);
LCD_out_data(REG0018_OVLAY_P1);
//Disp OFF
LCD_out_ctrl(CMD_DISPOFF);
LCD_out_data(REG000A_DISPONOFF_P1);
/*//CLEAR FIRST TEXT LAYER
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(REG000B_SCROLL_P1);
LCD_out_data(REG000C_SCROLL_P2);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i <= 1199; i++)
{
LCD_out_data(0x20);
}
*/
LCD_erase();
//CSRFORM
LCD_out_ctrl(CMD_CSRFORM);
LCD_out_data(REG0015_CSRFORM_P1);
LCD_out_data(REG0016_CSRFORM_P2);
//Disp ON
LCD_out_ctrl(CMD_DISPON);
LCD_out_data(REG000A_DISPONOFF_P1);
//CSDIR
LCD_out_ctrl(CMD_CSRDIR_RIGHT);
}
/* low level routine to send a bye value out to LCD controller data register
entry argument is the data to output.
To write data: AO = WR = 0, RD = 1*/
void LCD_out_data(UINT8 dat)
{
//configure Port AN as output
MCF_GPIO_DDRAN = 0xFF;
// now start timing control signal
MCF_GPIO_CLRTC = CLR_LCD_RD; //PRECLEAR RD
MCF_GPIO_SETTC = Set_LCD_AO; //PRESET AO
MCF_GPIO_CLRTC = CLR_LCD_CS; //Chip select is active low
MCF_GPIO_PORTAN = dat; // send data
MCF_GPIO_CLRTC = CLR_LCD_AO; // AO is low
MCF_GPIO_CLRTC = CLR_LCD_WR; //WRITE IS LOW
MCF_GPIO_SETTC = Set_LCD_RD; //RD line is high
// MCF_GPIO_PORTAN = dat; // send data
MCF_GPIO_CLRTC = CLR_LCD_RD; //pull back RD
// MCF_GPIO_CLRTC = CLR_LCD_RD; //wait an extra cycle
MCF_GPIO_SETTC = Set_LCD_WR; //FORCE IT BACK TO HIGH
MCF_GPIO_SETTC = Set_LCD_CS; // Deselect chip select
MCF_GPIO_SETTC = Set_LCD_AO; // pull back A0
MCF_GPIO_PORTAN = 0xFF;
MCF_GPIO_SETTC = Set_LCD_RD;
}
/* low level routine to send a byte value out to LCD controller control register
entry argument is the data to output
to write command A0 = RD = 1, WR = 0 */
void LCD_out_ctrl(UINT8 dat)
{
//configure Port AN as output
MCF_GPIO_DDRAN = 0
| MCF_GPIO_DDRAN_DDRAN0
| MCF_GPIO_DDRAN_DDRAN1
| MCF_GPIO_DDRAN_DDRAN2
| MCF_GPIO_DDRAN_DDRAN3
| MCF_GPIO_DDRAN_DDRAN4
| MCF_GPIO_DDRAN_DDRAN5
| MCF_GPIO_DDRAN_DDRAN6
| MCF_GPIO_DDRAN_DDRAN7;
//now start timing the control signal
MCF_GPIO_CLRTC = CLR_LCD_AO; //PRE-CLEAR AO
MCF_GPIO_CLRTC = CLR_LCD_RD;
MCF_GPIO_CLRTC = CLR_LCD_CS; // chip select is active low
MCF_GPIO_PORTAN = dat; // send data
MCF_GPIO_SETTC = Set_LCD_AO; // AO is HIGH
MCF_GPIO_CLRTC = CLR_LCD_WR; //WRITE IS LOW
// MCF_GPIO_CLRTC = CLR_LCD_WR; //wait an extra cycle
MCF_GPIO_SETTC = Set_LCD_RD; // rd is high
//MCF_GPIO_PORTAN = dat; // send data
// MCF_GPIO_CLRTC = CLR_LCD_RD; //pull back RD
MCF_GPIO_CLRTC = CLR_LCD_RD; //wait an extra cycle
MCF_GPIO_SETTC = Set_LCD_WR; //FORCE IT BACK TO HIGH
MCF_GPIO_SETTC = Set_LCD_CS; // Deselect chip select
MCF_GPIO_CLRTC = CLR_LCD_AO; // pull back A0
MCF_GPIO_PORTAN = 0xFF;
MCF_GPIO_SETTC = Set_LCD_RD;
}
/* low level routine to read a byte value from the LCD controller data register */
char LCD_in_dat(void)
{
char dat;
// configure Port AN as input
MCF_GPIO_PANPAR = 0;
MCF_GPIO_DDRAN = 0;
//now start timing the control signal
MCF_GPIO_CLRTC = CLR_LCD_AO; //PRE-CLEAR AO
MCF_GPIO_CLRTC = CLR_LCD_RD;
MCF_GPIO_CLRTC = CLR_LCD_WR;
MCF_GPIO_CLRTC = CLR_LCD_CS; // chip select is active low
MCF_GPIO_SETTC = Set_LCD_AO; // AO is HIGH
MCF_GPIO_SETTC = Set_LCD_WR; //READ IS HIGH
MCF_GPIO_SETTC = Set_LCD_RD; // rd is high
// dat = MCF_GPIO_SETAN;; // read data
MCF_GPIO_CLRTC = CLR_LCD_RD; // rd falling edge trigger read
dat = MCF_GPIO_SETAN;; // read data
MCF_GPIO_CLRTC = CLR_LCD_WR; //FORCE IT BACK TO LOW
MCF_GPIO_CLRTC = CLR_LCD_AO; // pull back A0
MCF_GPIO_SETTC = Set_LCD_CS; // Deselect chip select
//MCF_GPIO_PORTAN = 0xFF;
MCF_GPIO_SETTC = Set_LCD_RD;
return(dat);
}
/*low level routine to read a byte value from the LCD controller status register */
/*char LCD_in_sta(void)
{
char dat;
return(dat);
}
*/
/* low level routine to poll the LCD till the status bits indicate the chip is ready to take a command */
/*void LCD_busy_wait(void)
{
char dat;
}
*/
/* low level routine to erase the whole LCD screen
set up to erase 2 layer, graph+graph mode
*/
void LCD_erase(void)
{
UINT16 i;
/*//CLEAR FIRST TEXT LAYER
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(REG000B_SCROLL_P1);
LCD_out_data(REG000C_SCROLL_P2);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i <= 1199; i++)
{
LCD_out_data(0x20);
}
*/
//CLEAR FIRST GARPH LAYER
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(REG000B_SCROLL_P1);
LCD_out_data(REG000C_SCROLL_P2);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i <9600; i++)
{
LCD_out_data(0x00);
}
//CLEAR SECOND GRAPH LAYER
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(REG000E_SCROLL_P4);
LCD_out_data(REG000F_SCROLL_P5);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i < 9600; i++)
{
LCD_out_data(0x00);
}
}
/* Clears the display memory starting at the left/top and going to the right/bottom. */
/* left, right need to be within 320, top/bottom need to be within 240 */
void LCD_clear_area(UINT8 left,UINT8 top, UINT8 right, UINT8 bottom)
{
UINT8 bit_pos;
UINT16 byte_offset;
UINT8 width, height;
UINT8 i, j;
UINT8 SADL;
UINT8 SADH;
UINT16 Abs_addr;
bit_pos = left & 0x07; // get starting bit offset into byte
byte_offset = left >> 3; // find the byte address offset within that row
byte_offset = top * 40 + byte_offset; // left/top address relate to p1,p2
width = (right - left) >> 3; // how many bytes in width
height = bottom - top; // how many lines in height
//Layer 1
Abs_addr = REG000C_SCROLL_P2 << 8 + REG000B_SCROLL_P1;
for (j = 0; j < height; j++)
{
SADL = (Abs_addr + byte_offset + j * 40) & 0xFF;
SADH = (Abs_addr + byte_offset + j * 40) >> 8;
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(SADL);
LCD_out_data(SADH);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i < width; i++)
{
LCD_out_data(0x00);
}
}
//Layer 2
Abs_addr = REG000F_SCROLL_P5 << 8 + REG000E_SCROLL_P4;
for (j = 0; j < height; j++)
{
SADL = (Abs_addr + byte_offset + j * 40) & 0xFF;
SADH = (Abs_addr + byte_offset + j * 40) >> 8;
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(SADL);
LCD_out_data(SADH);
LCD_out_ctrl(CMD_MWRITE);
for (i = 0; i < width; i++)
{
LCD_out_data(0x00);
}
}
}
/* Write a glyph to the display at location x,y
arguments are:
column -x coordinate of the left part of glyph
raw -y coordinate of the top part of glyph
width -size in pixels of the width of the glyph
height -size in pixels of the height of the glyph
glyph - an unsigned char pointer to the plyph pixels to write assumed to be of length "width"
*/
void lcd_glyph(UINT16 left, UINT8 top, UINT8 width, UINT8 height, UINT8 *glyph, UINT8 store_width)
{
UINT8 bit_offset;
UINT8 byte_offset;
UINT8 y_bits;
UINT8 remaining_bits;
UINT8 mask;
UINT8 char_mask;
UINT8 x;
UINT8 *glyph_scan;
UINT8 glyph_offset = 0;
UINT16 Abs_addr;
UINT16 temp_Abs_addr;
UINT8 SADL;
UINT8 SADH;
UINT8 oldchar;
UINT8 newchar;
UINT8 i,j;
bit_offset = left & 0x07; // get the bit offset into a byte */
byte_offset = (left >> 3); // get the byte offset
// remaining_bits = (width + left) & 0x07;
if ((store_width << 3) >= (bit_offset + width))
{
remaining_bits = 0;
}
else
{
remaining_bits = bit_offset + width - (store_width << 3);
}
Abs_addr = REG000C_SCROLL_P2 << 8 + REG000B_SCROLL_P1;
for (i = 0; i < height; i++)
{
//calculate the abs address at that position (left, top) layer 1
temp_Abs_addr = Abs_addr + byte_offset + (top + i) * 40;
SADL = temp_Abs_addr & 0xFF;
SADH = temp_Abs_addr >> 8;
//set cursor to the right position
LCD_out_ctrl(CMD_CSRW);
LCD_out_data(SADL);
LCD_out_data(SADH);
//read data at that position
LCD_out_ctrl(CMD_MREAD);
oldchar = LCD_in_dat();
LCD_out_ctrl(CMD_CSRW);//read automatically moved cursor, need to set it back
LCD_out_data(SADL);
LCD_out_data(SADH);
for(j = 0; j < store_width; j++)
{
if(j == 0)
{
newchar = oldchar & bit_mask[bit_offset]; //chop off the left side to write new char
}
else
{
newchar = oldchar << (8 - bit_offset);
}
glyph_scan = glyph + glyph_offset; //pointer to data to write
x = *glyph_scan; //for debug to see what is the data
//x = *glyph_scan >> (8 - bit_offset); //for debug to see what is the data
x = *glyph_scan >> bit_offset;
//newchar = newchar | *glyph_scan >> (8 - bit_offset);
newchar = newchar | *glyph_scan >> bit_offset;
LCD_out_ctrl(CMD_MWRITE);
LCD_out_data(newchar);
oldchar = *glyph_scan;
glyph_offset++;
}
if (remaining_bits != 0) //means the program need to write the shift chars
{
newchar = oldchar << bit_offset;
LCD_out_ctrl(CMD_MWRITE);
LCD_out_data(newchar);
}
}
glyph_offset = 0; // start at left side of the glyph rasters
}
/* PRINTS THE GIVEN STRING AT LOCATION X,Y IN THE SPECIFIED FONT. PRINTS EACH CHARACTER GIVEN VIA CALLS
TO lcd-GLYPH. THE ENTRY STRING IS NULL TERMINATED AND NON 0x20 -> 0x7E CHARACTERS ARE IGNORED
ARGUMENTS ARE
left coordinate of left start of the string
top coordinate of top of string
font font number to use for display
str text string to display
*/
void LCD_text(UINT16 left, UINT8 top, UINT8 font, char *str)
{
UINT16 x = left;
UINT8 glyph;
UINT8 width;
UINT8 height;
UINT8 store_width;
unsigned char *glyph_ptr;
while (*str != 0x00)
{
glyph = (UINT8) *str;
// check to make sure the symbol is a legal one
// if not, replace it with a "." character
if ((glyph < ASCII_BOT) || (glyph > ASCII_TOP))
{
glyph = '.';
}
//the fonts start at ASCII_BOT, so to get the index into the font array, subtrace ASCII_bot from the glyph
glyph -= ASCII_BOT;
width = fonts[font].fixed_width; // check if it is a fixed width */
if(width == 0)
{
width = fonts[font].width_table[glyph]; //get the variable width istead
}
height = fonts[font].glyph_height;
store_width = fonts[font].store_width;
glyph_ptr = fonts[font].glyph_table + (glyph * store_width * height);
lcd_glyph(x,top,width,height,glyph_ptr,store_width); //plug symbol into buffer
x +=width; //move right for next character
str++; // point to next character in string
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -