blob: 0cd97f127ec399b1f7bff34f6f979c5dbf19b5b2 [file] [log] [blame]
/*****************************************************************************
* | File : LCD_Driver.c
* | Author : Waveshare team
* | Function : LCD driver
* | Info :
*----------------
* | This version: V1.0
* | Date : 2018-12-18
* | Info :
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
******************************************************************************/
#include "LCD_Driver.h"
#include <string.h>
/*******************************************************************************
function:
Hardware reset
*******************************************************************************/
static void LCD_Reset(void* ctx)
{
DEV_Delay_ms(ctx, 200);
DEV_Digital_Write(ctx, DEV_RST_PIN, 0);
DEV_Delay_ms(ctx, 200);
DEV_Digital_Write(ctx, DEV_RST_PIN, 1);
DEV_Delay_ms(ctx, 200);
}
/*******************************************************************************
function:
Write data and commands
*******************************************************************************/
static void LCD_Write_Command(void* ctx, UBYTE data)
{
DEV_Digital_Write(ctx, DEV_CS_PIN, 0);
DEV_Digital_Write(ctx, DEV_DC_PIN, 0);
DEV_SPI_WRITE(ctx, data);
}
static void LCD_WriteData_Byte(void* ctx, UBYTE data)
{
DEV_Digital_Write(ctx, DEV_CS_PIN, 0);
DEV_Digital_Write(ctx, DEV_DC_PIN, 1);
DEV_SPI_WRITE(ctx, data);
DEV_Digital_Write(ctx, DEV_CS_PIN,1);
}
void LCD_WriteData_Word(void* ctx, UWORD data)
{
DEV_Digital_Write(ctx, DEV_CS_PIN, 0);
DEV_Digital_Write(ctx, DEV_DC_PIN, 1);
DEV_SPI_WRITE(ctx, (data>>8) & 0xff);
DEV_SPI_WRITE(ctx, data);
DEV_Digital_Write(ctx, DEV_CS_PIN, 1);
}
/******************************************************************************
function:
Common register initialization
******************************************************************************/
void LCD_Init(void* ctx)
{
LCD_Reset(ctx);
LCD_Write_Command(ctx, 0x36);
LCD_WriteData_Byte(ctx, 0xA0);
LCD_Write_Command(ctx, 0x3A);
LCD_WriteData_Byte(ctx, 0x05);
LCD_Write_Command(ctx, 0x21);
LCD_Write_Command(ctx, 0x2A);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0x01);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0x3F);
LCD_Write_Command(ctx, 0x2B);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0xEF);
LCD_Write_Command(ctx, 0xB2);
LCD_WriteData_Byte(ctx, 0x0C);
LCD_WriteData_Byte(ctx, 0x0C);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, 0x33);
LCD_WriteData_Byte(ctx, 0x33);
LCD_Write_Command(ctx, 0xB7);
LCD_WriteData_Byte(ctx, 0x35);
LCD_Write_Command(ctx, 0xBB);
LCD_WriteData_Byte(ctx, 0x1F);
LCD_Write_Command(ctx, 0xC0);
LCD_WriteData_Byte(ctx, 0x2C);
LCD_Write_Command(ctx, 0xC2);
LCD_WriteData_Byte(ctx, 0x01);
LCD_Write_Command(ctx, 0xC3);
LCD_WriteData_Byte(ctx, 0x12);
LCD_Write_Command(ctx, 0xC4);
LCD_WriteData_Byte(ctx, 0x20);
LCD_Write_Command(ctx, 0xC6);
LCD_WriteData_Byte(ctx, 0x0F);
LCD_Write_Command(ctx, 0xD0);
LCD_WriteData_Byte(ctx, 0xA4);
LCD_WriteData_Byte(ctx, 0xA1);
LCD_Write_Command(ctx, 0xE0);
LCD_WriteData_Byte(ctx, 0xD0);
LCD_WriteData_Byte(ctx, 0x08);
LCD_WriteData_Byte(ctx, 0x11);
LCD_WriteData_Byte(ctx, 0x08);
LCD_WriteData_Byte(ctx, 0x0C);
LCD_WriteData_Byte(ctx, 0x15);
LCD_WriteData_Byte(ctx, 0x39);
LCD_WriteData_Byte(ctx, 0x33);
LCD_WriteData_Byte(ctx, 0x50);
LCD_WriteData_Byte(ctx, 0x36);
LCD_WriteData_Byte(ctx, 0x13);
LCD_WriteData_Byte(ctx, 0x14);
LCD_WriteData_Byte(ctx, 0x29);
LCD_WriteData_Byte(ctx, 0x2D);
LCD_Write_Command(ctx, 0xE1);
LCD_WriteData_Byte(ctx, 0xD0);
LCD_WriteData_Byte(ctx, 0x08);
LCD_WriteData_Byte(ctx, 0x10);
LCD_WriteData_Byte(ctx, 0x08);
LCD_WriteData_Byte(ctx, 0x06);
LCD_WriteData_Byte(ctx, 0x06);
LCD_WriteData_Byte(ctx, 0x39);
LCD_WriteData_Byte(ctx, 0x44);
LCD_WriteData_Byte(ctx, 0x51);
LCD_WriteData_Byte(ctx, 0x0B);
LCD_WriteData_Byte(ctx, 0x16);
LCD_WriteData_Byte(ctx, 0x14);
LCD_WriteData_Byte(ctx, 0x2F);
LCD_WriteData_Byte(ctx, 0x31);
LCD_Write_Command(ctx, 0x21);
LCD_Write_Command(ctx, 0x11);
LCD_Write_Command(ctx, 0x29);
}
/******************************************************************************
function: Set the cursor position
parameter :
Xstart: Start UWORD x coordinate
Ystart: Start UWORD y coordinate
Xend : End UWORD coordinates
Yend : End UWORD coordinatesen
******************************************************************************/
void LCD_SetWindow(void* ctx, UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend)
{
LCD_Write_Command(ctx, 0x2a);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, Xstart & 0xff);
LCD_WriteData_Byte(ctx, (Xend - 1) >> 8);
LCD_WriteData_Byte(ctx, (Xend - 1) & 0xff);
LCD_Write_Command(ctx, 0x2b);
LCD_WriteData_Byte(ctx, 0x00);
LCD_WriteData_Byte(ctx, Ystart & 0xff);
LCD_WriteData_Byte(ctx, (Yend - 1) >> 8);
LCD_WriteData_Byte(ctx, (Yend - 1) & 0xff);
LCD_Write_Command(ctx, 0x2C);
}
/******************************************************************************
function: Settings window
parameter :
Xstart: Start UWORD x coordinate
Ystart: Start UWORD y coordinate
******************************************************************************/
void LCD_SetCursor(void* ctx, UWORD X, UWORD Y)
{
LCD_Write_Command(ctx, 0x2a);
LCD_WriteData_Byte(ctx, X >> 8);
LCD_WriteData_Byte(ctx, X);
LCD_WriteData_Byte(ctx, X >> 8);
LCD_WriteData_Byte(ctx, X);
LCD_Write_Command(ctx, 0x2b);
LCD_WriteData_Byte(ctx, Y >> 8);
LCD_WriteData_Byte(ctx, Y);
LCD_WriteData_Byte(ctx, Y >> 8);
LCD_WriteData_Byte(ctx, Y);
LCD_Write_Command(ctx, 0x2C);
}
/******************************************************************************
function: Clear screen function, refresh the screen to a certain color
parameter :
Color : The color you want to clear all the screen
******************************************************************************/
void LCD_Clear(void* ctx, UWORD Color)
{
unsigned int i,j;
LCD_SetWindow(ctx, 0, 0, LCD_WIDTH, LCD_HEIGHT);
DEV_Digital_Write(ctx, DEV_DC_PIN, 1);
for(i = 0; i < LCD_WIDTH; i++){
for(j = 0; j < LCD_HEIGHT; j++){
DEV_SPI_WRITE(ctx, (Color>>8)&0xff);
DEV_SPI_WRITE(ctx, Color);
}
}
}
void LCD_ClearToBuffer(void* ctx, uint16_t* buffer)
{
LCD_SetWindow(ctx, 0, 0, LCD_WIDTH, LCD_HEIGHT);
DEV_Digital_Write(ctx, DEV_DC_PIN, 1);
DEV_SPI_BLOCK_WRITE(ctx, (const uint8_t*)buffer, LCD_WIDTH * LCD_HEIGHT * sizeof(uint16_t));
}
void LCD_ClearToBufferWindow(void* ctx, uint16_t* buffer, UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend) {
LCD_SetWindow(ctx, Xstart, Ystart, Xend, Yend);
DEV_Digital_Write(ctx, DEV_DC_PIN, 1);
DEV_SPI_BLOCK_WRITE(ctx, (const uint8_t*)buffer, (Xend - Xstart) * (Yend - Ystart) * sizeof(uint16_t));
}
/******************************************************************************
function: Refresh a certain area to the same color
parameter :
Xstart: Start UWORD x coordinate
Ystart: Start UWORD y coordinate
Xend : End UWORD coordinates
Yend : End UWORD coordinates
color : Set the color
******************************************************************************/
void LCD_ClearWindow(void* ctx, UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend,UWORD color)
{
UWORD i,j;
LCD_SetWindow(ctx, Xstart, Ystart, Xend-1,Yend-1);
for(i = Ystart; i <= Yend-1; i++){
for(j = Xstart; j <= Xend-1; j++){
LCD_WriteData_Word(ctx, color);
}
}
}
/******************************************************************************
function: Draw a point
parameter :
X : Set the X coordinate
Y : Set the Y coordinate
Color : Set the color
******************************************************************************/
void LCD_DrawPaint(void* ctx, UWORD x, UWORD y, UWORD Color)
{
LCD_SetCursor(ctx, x, y);
LCD_WriteData_Word(ctx, Color);
}
// ===== GUI_Paint.cpp
#define IMAGE_BACKGROUND WHITE
#define FONT_FOREGROUND BLACK
#define FONT_BACKGROUND WHITE
void Paint_NewImage(PAINT* Paint, UWORD Width, UWORD Height, UWORD Rotate, UWORD Color)
{
Paint->WidthMemory = Width;
Paint->HeightMemory = Height;
Paint->Color = Color;
Paint->WidthByte = Width;
Paint->HeightByte = Height;
// printf("WidthByte = %d, HeightByte = %d\r\n", Paint->WidthByte, Paint->HeightByte);
Paint->Rotate = Rotate;
Paint->Mirror = MIRROR_NONE;
if(Rotate == ROTATE_0 || Rotate == ROTATE_180) {
Paint->Width = Width;
Paint->Height = Height;
} else {
Paint->Width = Height;
Paint->Height = Width;
}
}
void Paint_SetPixel(PAINT* Paint, UWORD Xpoint, UWORD Ypoint, UWORD Color)
{
if(Xpoint > Paint->Width || Ypoint > Paint->Height){
// Debug("Exceeding display boundaries\r\n");
return;
}
UWORD X, Y;
switch(Paint->Rotate) {
case 0:
X = Xpoint;
Y = Ypoint;
break;
case 90:
X = Paint->WidthMemory - Ypoint - 1;
Y = Xpoint;
break;
case 180:
X = Paint->WidthMemory - Xpoint - 1;
Y = Paint->HeightMemory - Ypoint - 1;
break;
case 270:
X = Ypoint;
Y = Paint->HeightMemory - Xpoint - 1;
break;
default:
return;
}
switch(Paint->Mirror) {
case MIRROR_NONE:
break;
case MIRROR_HORIZONTAL:
X = Paint->WidthMemory - X - 1;
break;
case MIRROR_VERTICAL:
Y = Paint->HeightMemory - Y - 1;
break;
case MIRROR_ORIGIN:
X = Paint->WidthMemory - X - 1;
Y = Paint->HeightMemory - Y - 1;
break;
default:
return;
}
// printf("x = %d, y = %d\r\n", X, Y);
if(X > Paint->WidthMemory || Y > Paint->HeightMemory){
// Debug("Exceeding display boundaries\r\n");
return;
}
// UDOUBLE Addr = X / 8 + Y * Paint->WidthByte;
// LCD_DrawPaint(X,Y, Color);
Paint->Image[Y * LCD_WIDTH + X] = Color;
}
void Paint_DrawChar(PAINT* Paint, UWORD Xpoint, UWORD Ypoint, const char Acsii_Char,
sFONT* Font, UWORD Color_Background, UWORD Color_Foreground)
{
UWORD Page, Column;
if (Xpoint > Paint->Width || Ypoint > Paint->Height) {
// Debug("Paint_DrawChar Input exceeds the normal display range\r\n");
return;
}
uint32_t Char_Offset = (Acsii_Char - ' ') * Font->Height * (Font->Width / 8 + (Font->Width % 8 ? 1 : 0));
const unsigned char *ptr = &Font->table[Char_Offset];
for (Page = 0; Page < Font->Height; Page ++ ) {
for (Column = 0; Column < Font->Width; Column ++ ) {
//To determine whether the font background color and screen background color is consistent
if (FONT_BACKGROUND == Color_Background) { //this process is to speed up the scan
if (*ptr & (0x80 >> (Column % 8)))
Paint_SetPixel(Paint, Xpoint + Column, Ypoint + Page, Color_Foreground);
// Paint_DrawPoint(Xpoint + Column, Ypoint + Page, Color_Foreground, DOT_PIXEL_DFT, DOT_STYLE_DFT);
} else {
if (*ptr & (0x80 >> (Column % 8))) {
Paint_SetPixel(Paint, Xpoint + Column, Ypoint + Page, Color_Foreground);
// Paint_DrawPoint(Xpoint + Column, Ypoint + Page, Color_Foreground, DOT_PIXEL_DFT, DOT_STYLE_DFT);
} else {
Paint_SetPixel(Paint, Xpoint + Column, Ypoint + Page, Color_Background);
// Paint_DrawPoint(Xpoint + Column, Ypoint + Page, Color_Background, DOT_PIXEL_DFT, DOT_STYLE_DFT);
}
}
//One pixel is 8 bits
if (Column % 8 == 7)
ptr++;
}// Write a line
if (Font->Width % 8 != 0)
ptr++;
}// Write all
}
void Paint_DrawString_EN(PAINT* Paint, UWORD Xstart, UWORD Ystart, const char * pString,
sFONT* Font, UWORD Color_Background, UWORD Color_Foreground )
{
UWORD Xpoint = Xstart;
UWORD Ypoint = Ystart;
if (Xstart > Paint->Width || Ystart > Paint->Height) {
// Debug("Paint_DrawString_EN Input exceeds the normal display range\r\n");
return;
}
while (* pString != '\0') {
//if X direction filled , reposition to(Xstart,Ypoint),Ypoint is Y direction plus the Height of the character
if ((Xpoint + Font->Width ) > Paint->Width ) {
Xpoint = Xstart;
Ypoint += Font->Height;
}
// If the Y direction is full, reposition to(Xstart, Ystart)
if ((Ypoint + Font->Height ) > Paint->Height ) {
Xpoint = Xstart;
Ypoint = Ystart;
}
Paint_DrawChar(Paint, Xpoint, Ypoint, * pString, Font, Color_Background, Color_Foreground);
//The next character of the address
pString ++;
//The next word of the abscissa increases the font of the broadband
Xpoint += Font->Width;
}
}