/* * 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); }