Laridium_v35/Core/Src/st7789v.c
Jim Castro 173d815c48 v35
2025-03-20 18:12:02 +05:30

451 lines
9.7 KiB
C

/*
* ili9341.c
*
* Created on: 2019/12/26
* Author: Kotetsu Yamamoto
* Copyright [Kotetsu Yamamoto]
I refer https://github.com/dtnghia2206/TFTLCD/blob/master/TFTLCD/ILI9341/ILI9341_Driver.c
from Original source:
MIT License
Copyright (c) 2019 NghiaDT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation 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
furnished 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 FOR 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 "st7789v.h"
#include "main.h" // Hardware setting
// This function is for compatible HiLetgo ILI9341
typedef enum {
ROTATE_0,
ROTATE_90,
ROTATE_180,
ROTATE_270
} LCD_Horizontal_t;
extern void Error_Handler(void);
extern SPI_HandleTypeDef hspi1;
static __IO uint8_t spiDmaTransferComplete;
void ILI9341_Reset(void);
void ILI9341_SoftReset(void);
void LCD_WR_REG(uint8_t data);
static void LCD_WR_DATA(uint8_t data);
static void LCD_direction(LCD_Horizontal_t direction);
static void RESET_L(void);
static void RESET_H(void);
static void CS_L(void);
static void CS_H(void);
static void DC_L(void);
static void DC_H(void);
// Initialization
void ILI9341_Init(void) //Changed
{
ILI9341_Reset();
ILI9341_SoftReset();
HAL_Delay(120);
LCD_WR_REG(0x11); //Sleep Out
HAL_Delay(120);
//-----------------------ST7789V Frame rate setting-----------------//
//************************************************
LCD_WR_REG(0x3A); //65k mode
LCD_WR_DATA(0x05);
LCD_WR_REG(0xC5); //VCOM
LCD_WR_DATA(0x1A);
LCD_WR_REG(0x36); //According to the original source
LCD_WR_DATA(0x20);
//-------------ST7789V Frame rate setting-----------//
LCD_WR_REG(0xb2); //Porch Setting
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x33);
LCD_WR_DATA(0x33);
//LCD_WR_REG(0xb7); //Gate Control
//LCD_WR_DATA(0x05); //12.2v -10.43v //TODO 21.05.2023 For my display
//--------------ST7789V Power setting---------------//
LCD_WR_REG(0xBB);//VCOM
LCD_WR_DATA(0x3F);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x2c);
LCD_WR_REG(0xC2); //VDV and VRH Command Enable
LCD_WR_DATA(0x01);
LCD_WR_REG(0xC3); //VRH Set
LCD_WR_DATA(0x0F); //4.3+( vcom+vcom offset+vdv)
LCD_WR_REG(0xC4); //VDV Set
LCD_WR_DATA(0x20); //0v
LCD_WR_REG(0xC6); //Frame Rate Control in Normal Mode
LCD_WR_DATA(0X01); //111Hz
LCD_WR_REG(0xd0); //Power Control 1
LCD_WR_DATA(0xa4);
LCD_WR_DATA(0xa1);
LCD_WR_REG(0xE8); //Power Control 1
LCD_WR_DATA(0x03);
LCD_WR_REG(0xE9); //Equalize time control
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x08);
//---------------ST7789V gamma setting-------------//
#if 1 // new
LCD_WR_REG(ILI9341_GAMMASET);
LCD_WR_DATA(0x01);
LCD_WR_REG(ILI9341_GMCTRP1);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x31);
LCD_WR_DATA(0x2B);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x4E);
LCD_WR_DATA(0xF1);
LCD_WR_DATA(0x37);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x00);
LCD_WR_REG(ILI9341_GMCTRN1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x14);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x11);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x31);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0x48);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x31);
LCD_WR_DATA(0x36);
LCD_WR_DATA(0x0F);
#else
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATA(0xD0);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x14);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x33);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x13);
LCD_WR_DATA(0x14);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x30);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATA(0xD0);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x32);
LCD_WR_DATA(0x32);
LCD_WR_DATA(0x3B);
LCD_WR_DATA(0x14);
LCD_WR_DATA(0x13);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x2F);
#endif
LCD_WR_REG(0x20); //destroy
LCD_WR_REG(0x29); // Display turn on
LCD_direction(ROTATE_90);
LCD_WR_REG(0x36);
LCD_WR_DATA(0x28 | 128 | 64);//(0x20);
LCD_WR_REG(0x21);
//-------------------------------
}
void ILI9341_SetWindow(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y)
{
// Set Window
LCD_WR_REG(0x2a);
LCD_WR_DATA(start_x >> 8);
LCD_WR_DATA(0xFF & start_x);
LCD_WR_DATA(end_x >> 8);
LCD_WR_DATA(0xFF & end_x);
LCD_WR_REG(0x2b);
LCD_WR_DATA(start_y >> 8);
LCD_WR_DATA(0xFF & start_y);
LCD_WR_DATA(end_y >> 8);
LCD_WR_DATA(0xFF & end_y);
}
void ILI9341_WritePixel(uint16_t x, uint16_t y, uint16_t color)
{
uint8_t data[2];
data[0] = color >> 8;
data[1] = color;
ILI9341_SetWindow(x, y, x, y);
// Enable to access GRAM
LCD_WR_REG(0x2c);
DC_H();
if (HAL_SPI_Transmit(&hspi1, data, 2, 1000) != HAL_OK) {
Error_Handler();
}
}
static void ConvHL(uint8_t *s, int32_t l)
{
uint8_t v;
while (l > 0) {
v = *(s+1);
*(s+1) = *s;
*s = v;
s += 2;
l -= 2;
}
}
// Call this function after ILI9341_SetWindow
// This function is non blocked
// The variable for Callback is open. User should set by himself
void ILI9341_DrawBitmap(uint16_t w, uint16_t h, uint8_t *s)
{
// Enable to access GRAM
LCD_WR_REG(0x2c);
DC_H();
CS_L();
#if 0
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->CR2 |= SPI_DATASIZE_16BIT; // Set 16 bit mode
__HAL_SPI_ENABLE(&hspi1);
#endif
ConvHL(s, (int32_t)w*h*2);
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)s, w * h *2);
#if 0
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->CR2 &= ~(SPI_DATASIZE_16BIT); // Set 8 bit mode
__HAL_SPI_ENABLE(&hspi1);
#endif
}
// User should call it at callback
void ILI9341_EndOfDrawBitmap(void)
{
#if 0
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->CR2 &= ~(SPI_DATASIZE_16BIT); // Set 8 bit mode
__HAL_SPI_ENABLE(&hspi1);
#endif
}
void ILI9341_Reset(void)
{
RESET_L();
HAL_Delay(50);
RESET_H();
HAL_Delay(10);
}
void ILI9341_SoftReset(void)
{
uint8_t cmd;
cmd = 0x01; //Software reset
DC_L();
CS_L();
if (HAL_SPI_Transmit(&hspi1, &cmd, 1, 1000) != HAL_OK) {
Error_Handler();
}
CS_H();
}
void LCD_WR_REG(uint8_t data) //Changed
{
DC_L();
CS_L();
if (HAL_SPI_Transmit(&hspi1, &data, 1, 1000) != HAL_OK) {
Error_Handler();
}
CS_H();
}
static void LCD_WR_DATA(uint8_t data) //Changed
{
DC_H();
CS_L();
if (HAL_SPI_Transmit(&hspi1, &data, 1, 1000) != HAL_OK) {
Error_Handler();
}
CS_H();
}
void TFT_clear(void) //Changed
{
unsigned int ROW,column;
LCD_WR_REG(0x2a); //Column address set
LCD_WR_DATA(0x00); //start column
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00); //end column
LCD_WR_DATA(0xF0);
LCD_WR_REG(0x2b); //Row address set
LCD_WR_DATA(0x00); //start row
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01); //end row
LCD_WR_DATA(0x40);
LCD_WR_REG(0x2C); //Memory write
for(ROW=0;ROW<320;ROW++) //ROW loop
{
for(column=0;column<240;column++) //column loop
{
LCD_WR_DATA(0xFF);
LCD_WR_DATA(0xFF);
}
}
}
void TFT_full(unsigned int color) //Changed
{
unsigned int ROW,column;
LCD_WR_REG(0x2a); //Column address set
LCD_WR_DATA(0x00); //start column
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01); //end column
LCD_WR_DATA(0x40);
LCD_WR_REG(0x2b); //Row address set
LCD_WR_DATA(0x00); //start row
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00); //end row
LCD_WR_DATA(0xF0);
LCD_WR_REG(0x2C); //Memory write
for(ROW=0;ROW<320;ROW++) //ROW loop
{
for(column=0;column<240 ;column++) //column loop
{
LCD_WR_DATA(color>>8);
LCD_WR_DATA(color);
}
}
}
void LCD_IO_WriteMultipleData(uint8_t *pData, uint32_t Size)
{
/* Swap endianes */
ConvHL(pData, (int32_t)Size*2);
DC_H();
// HAL_SPI_Transmit(&hspi1, (uint8_t*)pData, Size * 2, HAL_MAX_DELAY);
spiDmaTransferComplete = 0;
HAL_SPI_Transmit_DMA(&hspi1, pData, Size*2 );
//HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)pData, Size );
while(spiDmaTransferComplete == 0);
}
/*
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
spiDmaTransferComplete = 1;
}
*/
static void LCD_direction(LCD_Horizontal_t direction)
{
switch (direction) {
case ROTATE_0:
LCD_WR_REG(0x36);
LCD_WR_DATA(0x40);
break;
case ROTATE_90:
LCD_WR_REG(0x36);
LCD_WR_DATA(0x20);
break;
case ROTATE_180:
LCD_WR_REG(0x36);
LCD_WR_DATA(0x80);
break;
case ROTATE_270:
LCD_WR_REG(0x36);
LCD_WR_DATA(0xE0);
break;
}
}
static void RESET_L(void)
{
HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET);
}
static void RESET_H(void)
{
HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_SET);
}
static void CS_L(void)
{
HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
}
static void CS_H(void)
{
HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
}
static void DC_L(void)
{
HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET);
}
static void DC_H(void)
{
HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_SET);
}