445 lines
12 KiB
C
445 lines
12 KiB
C
|
#include <drv_lcd.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#define SPI_PORT spi1
|
||
|
|
||
|
uint slice_num;
|
||
|
LCD_ATTRIBUTES LCD;
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Hardware reset
|
||
|
parameter:
|
||
|
******************************************************************************/
|
||
|
static void LCD_Reset(void)
|
||
|
{
|
||
|
DEV_Digital_Write(LCD_RST_PIN, 1);
|
||
|
rt_thread_mdelay(100);
|
||
|
DEV_Digital_Write(LCD_RST_PIN, 0);
|
||
|
rt_thread_mdelay(100);
|
||
|
DEV_Digital_Write(LCD_RST_PIN, 1);
|
||
|
rt_thread_mdelay(100);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : send command
|
||
|
parameter:
|
||
|
Reg : Command register
|
||
|
******************************************************************************/
|
||
|
static void LCD_SendCommand(UBYTE Reg)
|
||
|
{
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 0);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
DEV_SPI_WriteByte(Reg);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : send data
|
||
|
parameter:
|
||
|
Data : Write data
|
||
|
******************************************************************************/
|
||
|
static void LCD_SendData_8Bit(UBYTE Data)
|
||
|
{
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
DEV_SPI_WriteByte(Data);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : send data
|
||
|
parameter:
|
||
|
Data : Write data
|
||
|
******************************************************************************/
|
||
|
static void LCD_SendData_16Bit(UWORD Data)
|
||
|
{
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
DEV_SPI_WriteByte((Data >> 8) & 0xFF);
|
||
|
DEV_SPI_WriteByte(Data & 0xFF);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Initialize the lcd register
|
||
|
parameter:
|
||
|
******************************************************************************/
|
||
|
static void LCD_InitReg(void)
|
||
|
{
|
||
|
LCD_SendCommand(0x3A);
|
||
|
LCD_SendData_8Bit(0x05);
|
||
|
|
||
|
LCD_SendCommand(0xB2);
|
||
|
LCD_SendData_8Bit(0x0C);
|
||
|
LCD_SendData_8Bit(0x0C);
|
||
|
LCD_SendData_8Bit(0x00);
|
||
|
LCD_SendData_8Bit(0x33);
|
||
|
LCD_SendData_8Bit(0x33);
|
||
|
|
||
|
LCD_SendCommand(0xB7); // Gate Control
|
||
|
LCD_SendData_8Bit(0x35);
|
||
|
|
||
|
LCD_SendCommand(0xBB); // VCOM Setting
|
||
|
LCD_SendData_8Bit(0x19);
|
||
|
|
||
|
LCD_SendCommand(0xC0); // LCM Control
|
||
|
LCD_SendData_8Bit(0x2C);
|
||
|
|
||
|
LCD_SendCommand(0xC2); // VDV and VRH Command Enable
|
||
|
LCD_SendData_8Bit(0x01);
|
||
|
LCD_SendCommand(0xC3); // VRH Set
|
||
|
LCD_SendData_8Bit(0x12);
|
||
|
LCD_SendCommand(0xC4); // VDV Set
|
||
|
LCD_SendData_8Bit(0x20);
|
||
|
|
||
|
LCD_SendCommand(0xC6); // Frame Rate Control in Normal Mode
|
||
|
LCD_SendData_8Bit(0x01); // 110hz
|
||
|
|
||
|
LCD_SendCommand(0xD0); // Power Control 1
|
||
|
LCD_SendData_8Bit(0xA4);
|
||
|
LCD_SendData_8Bit(0xA1);
|
||
|
|
||
|
LCD_SendCommand(0xE0); // Positive Voltage Gamma Control
|
||
|
LCD_SendData_8Bit(0xD0);
|
||
|
LCD_SendData_8Bit(0x04);
|
||
|
LCD_SendData_8Bit(0x0D);
|
||
|
LCD_SendData_8Bit(0x11);
|
||
|
LCD_SendData_8Bit(0x13);
|
||
|
LCD_SendData_8Bit(0x2B);
|
||
|
LCD_SendData_8Bit(0x3F);
|
||
|
LCD_SendData_8Bit(0x54);
|
||
|
LCD_SendData_8Bit(0x4C);
|
||
|
LCD_SendData_8Bit(0x18);
|
||
|
LCD_SendData_8Bit(0x0D);
|
||
|
LCD_SendData_8Bit(0x0B);
|
||
|
LCD_SendData_8Bit(0x1F);
|
||
|
LCD_SendData_8Bit(0x23);
|
||
|
|
||
|
LCD_SendCommand(0xE1); // Negative Voltage Gamma Control
|
||
|
LCD_SendData_8Bit(0xD0);
|
||
|
LCD_SendData_8Bit(0x04);
|
||
|
LCD_SendData_8Bit(0x0C);
|
||
|
LCD_SendData_8Bit(0x11);
|
||
|
LCD_SendData_8Bit(0x13);
|
||
|
LCD_SendData_8Bit(0x2C);
|
||
|
LCD_SendData_8Bit(0x3F);
|
||
|
LCD_SendData_8Bit(0x44);
|
||
|
LCD_SendData_8Bit(0x51);
|
||
|
LCD_SendData_8Bit(0x2F);
|
||
|
LCD_SendData_8Bit(0x1F);
|
||
|
LCD_SendData_8Bit(0x1F);
|
||
|
LCD_SendData_8Bit(0x20);
|
||
|
LCD_SendData_8Bit(0x23);
|
||
|
|
||
|
LCD_SendCommand(0x21); // Display Inversion On
|
||
|
|
||
|
LCD_SendCommand(0x11); // Sleep Out
|
||
|
|
||
|
LCD_SendCommand(0x29); // Display On
|
||
|
}
|
||
|
|
||
|
/********************************************************************************
|
||
|
function: Set the resolution and scanning method of the screen
|
||
|
parameter:
|
||
|
Scan_dir: Scan direction
|
||
|
********************************************************************************/
|
||
|
static void LCD_SetAttributes(UBYTE Scan_dir)
|
||
|
{
|
||
|
// Get the screen scan direction
|
||
|
LCD.SCAN_DIR = Scan_dir;
|
||
|
UBYTE MemoryAccessReg = 0x00;
|
||
|
|
||
|
// Get GRAM and LCD width and height
|
||
|
if (Scan_dir == HORIZONTAL)
|
||
|
{
|
||
|
LCD.HEIGHT = LCD_WIDTH;
|
||
|
LCD.WIDTH = LCD_HEIGHT;
|
||
|
MemoryAccessReg = 0X70;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LCD.HEIGHT = LCD_HEIGHT;
|
||
|
LCD.WIDTH = LCD_WIDTH;
|
||
|
MemoryAccessReg = 0X00;
|
||
|
}
|
||
|
|
||
|
// Set the read / write scan direction of the frame memory
|
||
|
LCD_SendCommand(0x36); // MX, MY, RGB mode
|
||
|
LCD_SendData_8Bit(MemoryAccessReg); // 0x08 set RGB
|
||
|
}
|
||
|
|
||
|
/********************************************************************************
|
||
|
function : Initialize the lcd
|
||
|
parameter:
|
||
|
********************************************************************************/
|
||
|
void LCD_Init(UBYTE Scan_dir)
|
||
|
{
|
||
|
DEV_SET_PWM(50);
|
||
|
|
||
|
// Hardware reset
|
||
|
LCD_Reset();
|
||
|
|
||
|
// Set the resolution and scanning method of the screen
|
||
|
LCD_SetAttributes(Scan_dir);
|
||
|
|
||
|
// Set the initialization register
|
||
|
LCD_InitReg();
|
||
|
}
|
||
|
|
||
|
void LCD_SetWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend)
|
||
|
{
|
||
|
// set the X coordinates
|
||
|
LCD_SendCommand(0x2A);
|
||
|
LCD_SendData_8Bit((Xstart >> 8) & 0xFF);
|
||
|
LCD_SendData_8Bit(Xstart & 0xFF);
|
||
|
LCD_SendData_8Bit(((Xend - 1) >> 8) & 0xFF);
|
||
|
LCD_SendData_8Bit((Xend - 1) & 0xFF);
|
||
|
|
||
|
// set the Y coordinates
|
||
|
LCD_SendCommand(0x2B);
|
||
|
LCD_SendData_8Bit((Ystart >> 8) & 0xFF);
|
||
|
LCD_SendData_8Bit(Ystart & 0xFF);
|
||
|
LCD_SendData_8Bit(((Yend - 1) >> 8) & 0xFF);
|
||
|
LCD_SendData_8Bit((Yend - 1) & 0xFF);
|
||
|
|
||
|
LCD_SendCommand(0X2C);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Clear screen
|
||
|
parameter:
|
||
|
******************************************************************************/
|
||
|
void LCD_Clear(UWORD Color)
|
||
|
{
|
||
|
UWORD j, i;
|
||
|
UWORD Image[LCD.WIDTH * LCD.HEIGHT];
|
||
|
|
||
|
Color = ((Color << 8) & 0xff00) | (Color >> 8);
|
||
|
|
||
|
for (j = 0; j < LCD.HEIGHT * LCD.WIDTH; j++)
|
||
|
{
|
||
|
Image[j] = Color;
|
||
|
}
|
||
|
|
||
|
LCD_SetWindows(0, 0, LCD.WIDTH, LCD.HEIGHT);
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
for (j = 0; j < LCD.HEIGHT; j++)
|
||
|
{
|
||
|
DEV_SPI_Write_nByte((uint8_t *) &Image[j * LCD.WIDTH], LCD.WIDTH * 2);
|
||
|
}
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Sends the image buffer in RAM to displays
|
||
|
parameter:
|
||
|
******************************************************************************/
|
||
|
void LCD_Display(UWORD *Image)
|
||
|
{
|
||
|
UWORD j;
|
||
|
LCD_SetWindows(0, 0, LCD.WIDTH, LCD.HEIGHT);
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
for (j = 0; j < LCD.HEIGHT; j++)
|
||
|
{
|
||
|
DEV_SPI_Write_nByte((uint8_t *) &Image[j * LCD.WIDTH], LCD.WIDTH * 2);
|
||
|
}
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
LCD_SendCommand(0x29);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Sends the image buffer in RAM to displays
|
||
|
parameter:
|
||
|
Xstart : X direction Start coordinates
|
||
|
Ystart : Y direction Start coordinates
|
||
|
Xend : X direction end coordinates
|
||
|
Yend : Y direction end coordinates
|
||
|
Image : Written content
|
||
|
******************************************************************************/
|
||
|
void LCD_DisplayWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD *Image)
|
||
|
{
|
||
|
// display
|
||
|
UDOUBLE Addr = 0;
|
||
|
|
||
|
UWORD j;
|
||
|
LCD_SetWindows(Xstart, Ystart, Xend, Yend);
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 0);
|
||
|
for (j = Ystart; j < Yend - 1; j++)
|
||
|
{
|
||
|
Addr = Xstart + j * LCD.WIDTH;
|
||
|
DEV_SPI_Write_nByte((uint8_t *) &Image[Addr], (Xend - Xstart) * 2);
|
||
|
}
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function : Change the color of a point
|
||
|
parameter:
|
||
|
X : X coordinates
|
||
|
Y : Y coordinates
|
||
|
Color : Color
|
||
|
******************************************************************************/
|
||
|
void LCD_DisplayPoint(UWORD X, UWORD Y, UWORD Color)
|
||
|
{
|
||
|
LCD_SetWindows(X, Y, X, Y);
|
||
|
LCD_SendData_16Bit(Color);
|
||
|
}
|
||
|
|
||
|
void Handler_LCD(int signo)
|
||
|
{
|
||
|
// System Exit
|
||
|
rt_kprintf("\r\nHandler:Program stop\r\n");
|
||
|
DEV_Module_Exit();
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* GPIO read and write
|
||
|
**/
|
||
|
void DEV_Digital_Write(UWORD Pin, UBYTE Value)
|
||
|
{
|
||
|
gpio_put(Pin, Value);
|
||
|
}
|
||
|
|
||
|
UBYTE DEV_Digital_Read(UWORD Pin)
|
||
|
{
|
||
|
return gpio_get(Pin);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* GPIO Mode
|
||
|
**/
|
||
|
void DEV_GPIO_Mode(UWORD Pin, UWORD Mode)
|
||
|
{
|
||
|
gpio_init(Pin);
|
||
|
if (Mode == 0 || Mode == GPIO_IN)
|
||
|
{
|
||
|
gpio_set_dir(Pin, GPIO_IN);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gpio_set_dir(Pin, GPIO_OUT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* SPI
|
||
|
**/
|
||
|
void DEV_SPI_WriteByte(UBYTE Value)
|
||
|
{
|
||
|
spi_write_blocking(SPI_PORT, &Value, 1);
|
||
|
}
|
||
|
|
||
|
void DEV_SPI_Write_nByte(UBYTE pData[], UDOUBLE Len)
|
||
|
{
|
||
|
spi_write_blocking(SPI_PORT, pData, Len);
|
||
|
}
|
||
|
|
||
|
void DEV_GPIO_Init(void)
|
||
|
{
|
||
|
DEV_GPIO_Mode(LCD_RST_PIN, 1);
|
||
|
DEV_GPIO_Mode(LCD_DC_PIN, 1);
|
||
|
DEV_GPIO_Mode(LCD_CS_PIN, 1);
|
||
|
DEV_GPIO_Mode(LCD_BL_PIN, 1);
|
||
|
|
||
|
DEV_Digital_Write(LCD_CS_PIN, 1);
|
||
|
DEV_Digital_Write(LCD_DC_PIN, 0);
|
||
|
DEV_Digital_Write(LCD_BL_PIN, 1);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************
|
||
|
function: Module Initialize, the library and initialize the pins, SPI protocol
|
||
|
parameter:
|
||
|
Info:
|
||
|
******************************************************************************/
|
||
|
UBYTE DEV_Module_Init(void)
|
||
|
{
|
||
|
// SPI Config
|
||
|
spi_init(SPI_PORT, 80000 * 1000);
|
||
|
gpio_set_function(LCD_CLK_PIN, GPIO_FUNC_SPI);
|
||
|
gpio_set_function(LCD_MOSI_PIN, GPIO_FUNC_SPI);
|
||
|
|
||
|
// GPIO Config
|
||
|
DEV_GPIO_Init();
|
||
|
|
||
|
// PWM Config
|
||
|
gpio_set_function(LCD_BL_PIN, GPIO_FUNC_PWM);
|
||
|
slice_num = pwm_gpio_to_slice_num(LCD_BL_PIN);
|
||
|
pwm_set_wrap(slice_num, 100);
|
||
|
pwm_set_chan_level(slice_num, PWM_CHAN_B, 1);
|
||
|
pwm_set_clkdiv(slice_num, 50);
|
||
|
pwm_set_enabled(slice_num, true);
|
||
|
|
||
|
rt_kprintf("DEV_Module_Init OK \r\n");
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void DEV_SET_PWM(UBYTE Value)
|
||
|
{
|
||
|
if (Value < 0 || Value > 100)
|
||
|
{
|
||
|
rt_kprintf("DEV_SET_PWM Error \r\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pwm_set_chan_level(slice_num, PWM_CHAN_B, Value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UBYTE SPI_Init(void)
|
||
|
{
|
||
|
DEV_Module_Init();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool _swapBytes;
|
||
|
UDOUBLE dma_tx_channel;
|
||
|
dma_channel_config dma_tx_config;
|
||
|
|
||
|
/***************************************************************************************
|
||
|
** Function name: dmaWait
|
||
|
** Description: Wait until DMA is over (blocking!)
|
||
|
***************************************************************************************/
|
||
|
void dmaWait(void)
|
||
|
{
|
||
|
while (dma_channel_is_busy(dma_tx_channel))
|
||
|
;
|
||
|
|
||
|
// For SPI must also wait for FIFO to flush and reset format
|
||
|
while (spi_get_hw(SPI_PORT)->sr & SPI_SSPSR_BSY_BITS)
|
||
|
{
|
||
|
};
|
||
|
spi_set_format(SPI_PORT, 16, (spi_cpol_t) 0, (spi_cpha_t) 0, SPI_MSB_FIRST);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************************
|
||
|
** Function name: pushPixelsDMA
|
||
|
** Description: Push pixels to TFT
|
||
|
***************************************************************************************/
|
||
|
void pushPixelsDMA(UWORD* image, UDOUBLE len)
|
||
|
{
|
||
|
if ((len == 0))
|
||
|
return;
|
||
|
|
||
|
dmaWait();
|
||
|
|
||
|
channel_config_set_bswap(&dma_tx_config, !_swapBytes);
|
||
|
|
||
|
dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_PORT)->dr, (UWORD*) image, len, true);
|
||
|
}
|
||
|
|
||
|
bool initDMA(bool ctrl_cs)
|
||
|
{
|
||
|
dma_tx_channel = dma_claim_unused_channel(true);
|
||
|
dma_tx_config = dma_channel_get_default_config(dma_tx_channel);
|
||
|
|
||
|
channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_16);
|
||
|
channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_PORT) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
|
||
|
|
||
|
return true;
|
||
|
}
|