/* Includes ------------------------------------------------------------------*/ #include "st7789.h" #include "stm32_hx8347d_lcd.h" /** @addtogroup BSP * @{ */ /** @addtogroup Components * @{ */ /** @addtogroup st7789v * @brief This file provides a set of functions needed to drive the * st7789v LCD. * @{ */ /** @defgroup st7789v_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup st7789v_Private_Defines * @{ */ /** * @} */ /** @defgroup st7789v_Private_Macros * @{ */ /** * @} */ /** @defgroup st7789v_Private_Variables * @{ */ LCD_DrvTypeDef st7789v_drv = { st7789v_Init, 0, st7789v_DisplayOn, st7789v_DisplayOff, st7789v_SetCursor, st7789_SetRotation, st7789v_WritePixel, 0, st7789v_SetDisplayWindow, st7789v_FillRect, st7789v_DrawHLine, st7789v_DrawVLine, st7789v_GetLcdPixelWidth, st7789v_GetLcdPixelHeight, st7789v_DrawBitmap, 0 }; //static uint8_t Is_st7789v_Initialized = 0; static uint16_t ArrayRGB[280] = {0}; uint16_t st7789v_width = ST7789V_LCD_PIXEL_WIDTH; uint16_t st7789v_height = ST7789V_LCD_PIXEL_HEIGHT; uint8_t st7789v_rotation = 0; /** * @} */ /** @defgroup st7789v_Private_FunctionPrototypes * @{ */ void st7789v_WriteColor(uint16_t color, uint32_t len); /** * @} */ /** @defgroup st7789v_Private_Functions * @{ */ /** * @brief Writes to the selected LCD register. * @param LCDReg: Address of the selected register. * @param LCDRegValue: value to write to the selected register. * @retval None */ void st7789v_WriteRegCmd(uint8_t LCDReg) { LCD_DC_LOW(); LCD_IO_WriteReg(LCDReg); LCD_DC_HIGH(); } /** * @brief Writes to the selected LCD register. * @param LCDReg: Address of the selected register. * @param LCDRegValue: value to write to the selected register. * @retval None */ void st7789v_WriteReg(uint8_t LCDReg, uint8_t LCDRegValue) { LCD_DC_LOW(); LCD_IO_WriteReg(LCDReg); LCD_IO_WriteMultipleData(&LCDRegValue, 1); LCD_DC_HIGH(); } /** * @brief Initialize the st7789v LCD Component. * @param None * @retval None */ void st7789v_Init(void) { /* Initialize st7789v low level bus layer -----------------------------------*/ LCD_IO_Init(); //LCD_CS_LOW(); //CHIP SELECT LCD_RST_LOW(); // CHIP RESET HAL_Delay(100); LCD_RST_HIGH(); HAL_Delay(100); LCD_BL_OFF(); HAL_Delay(100); LCD_BL_ON(); HAL_Delay(100); /* Out of sleep mode, 0 args, no delay */ st7789v_WriteRegCmd(0x11); HAL_Delay(120); st7789v_WriteRegCmd(0x36); if (st7789v_rotation ==0) st7789v_WriteRegCmd(0x00); else if (st7789v_rotation ==1) st7789v_WriteRegCmd(0xC0); if (st7789v_rotation ==2) st7789v_WriteRegCmd(0x70); else st7789v_WriteRegCmd(0xA0); st7789v_WriteReg(0x3A, 0x05); // 16bit color // porch control st7789v_WriteReg(0xB2, 0x0C); st7789v_WriteReg(0xB2, 0x0C); st7789v_WriteReg(0xB2, 0x00); st7789v_WriteReg(0xB2, 0x33); st7789v_WriteReg(0xB2, 0x33); st7789v_WriteReg(0xB7, 0x35); //VGH=13.26V, VGL=-10.43V st7789v_WriteReg(0xBB, 0x32); //VCOM st7789v_WriteReg(0xC2, 0x01); //VDV VRH enable st7789v_WriteReg(0xC3, 0x15); //VAP //5V st7789v_WriteReg(0xC4, 0x20); //VDV st7789v_WriteReg(0xC6, 0x0F); //Frame rate, 60hz st7789v_WriteReg(0xD0, 0xA4); //power control st7789v_WriteReg(0xD0, 0xA1); st7789v_WriteReg(0xE0, 0xD0); st7789v_WriteReg(0xE0, 0x08); st7789v_WriteReg(0xE0, 0x0E); st7789v_WriteReg(0xE0, 0x09); st7789v_WriteReg(0xE0, 0x09); st7789v_WriteReg(0xE0, 0x05); st7789v_WriteReg(0xE0, 0x31); st7789v_WriteReg(0xE0, 0x33); st7789v_WriteReg(0xE0, 0x48); st7789v_WriteReg(0xE0, 0x17); st7789v_WriteReg(0xE0, 0x14); st7789v_WriteReg(0xE0, 0x15); st7789v_WriteReg(0xE0, 0x31); st7789v_WriteReg(0xE0, 0x34); st7789v_WriteReg(0xE1, 0xD0); st7789v_WriteReg(0xE1, 0x08); st7789v_WriteReg(0xE1, 0x0E); st7789v_WriteReg(0xE1, 0x09); st7789v_WriteReg(0xE1, 0x09); st7789v_WriteReg(0xE1, 0x15); st7789v_WriteReg(0xE1, 0x31); st7789v_WriteReg(0xE1, 0x33); st7789v_WriteReg(0xE1, 0x48); st7789v_WriteReg(0xE1, 0x17); st7789v_WriteReg(0xE1, 0x14); st7789v_WriteReg(0xE1, 0x15); st7789v_WriteReg(0xE1, 0x31); st7789v_WriteReg(0xE1, 0x34); st7789v_WriteRegCmd(0x21); st7789v_WriteRegCmd(0x29); } /** * @brief Enables the Display. * @param None * @retval None */ void st7789v_DisplayOn(void) { //uint8_t data = 0; LCD_IO_WriteReg(0x13);/* Partial off (Normal): NORON */ LCD_Delay(10); LCD_IO_WriteReg(0x29);/* Display on: DISPON */ LCD_Delay(10); // LCD_IO_WriteReg(0x36);/* Memory data access control: MADCTL */ // data = 0xC0; // LCD_IO_WriteMultipleData(&data, 1); } /** * @brief Disables the Display. * @param None * @retval None */ void st7789v_DisplayOff(void) { //uint8_t data = 0; LCD_IO_WriteReg(0x13);/* Partial off (Normal): NORON */ LCD_Delay(10); LCD_IO_WriteReg(0x28);/* Display off: DISPOFF */ LCD_Delay(10); //LCD_IO_WriteReg(0x36);/* Memory data access control: MADCTL */ //data = 0xC0; //LCD_IO_WriteMultipleData(&data, 1); } /** * @brief Sets Cursor position. * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @retval None */ void st7789v_SetCursor(uint16_t Xpos, uint16_t Ypos) { uint8_t data = 0; LCD_IO_WriteReg(0x2A);/* Column address set: CASET */ data = (Xpos) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Xpos) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); LCD_IO_WriteReg(0x2B);/* Row address set: RASET */ data = (Ypos+20) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Ypos+20) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); LCD_IO_WriteReg(0x2C);/* Memory write: RAMWR */ } /** * @brief Writes pixel. * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @param RGBCode: the RGB pixel color * @retval None */ void st7789v_WritePixel(uint16_t Xpos, uint16_t Ypos, uint16_t RGBCode) { uint8_t data = 0; if((Xpos > ST7789V_LCD_PIXEL_WIDTH) || (Ypos > ST7789V_LCD_PIXEL_HEIGHT)) { return; } /* Set Cursor */ st7789v_SetCursor(Xpos, Ypos); data = RGBCode >> 8; LCD_IO_WriteMultipleData(&data, 1); data = RGBCode; LCD_IO_WriteMultipleData(&data, 1); } /** * @brief Sets a display window * @param Xpos: specifies the X bottom left position. * @param Ypos: specifies the Y bottom left position. * @param Height: display window height. * @param Width: display window width. * @retval None */ void st7789v_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height) { uint8_t data = 0; /* Column addr set, 4 args, no delay: XSTART = Xpos, XEND = (Xpos + Width - 1) */ LCD_IO_WriteReg(0x2A);/* Column address set: CASET */ data = (Xpos) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Xpos) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); data = (Xpos + Width - 1) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Xpos + Width - 1) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); /* Row addr set, 4 args, no delay: YSTART = Ypos, YEND = (Ypos + Height - 1) */ LCD_IO_WriteReg(0x2B);/* Row address set: RASET */ data = (Ypos) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Ypos) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); data = (Ypos + Height - 1) >> 8; LCD_IO_WriteMultipleData(&data, 1); data = (Ypos + Height - 1) & 0xFF; LCD_IO_WriteMultipleData(&data, 1); } /** * @brief Draws horizontal line. * @param RGBCode: Specifies the RGB color * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @param Length: specifies the line length. * @retval None */ void st7789v_DrawHLine(uint16_t RGBCode, uint16_t Xpos, uint16_t Ypos, uint16_t Length) { uint8_t counter = 0; if(0 == st7789v_rotation || 2 == st7789v_rotation){ if(Xpos + Length > ST7789V_LCD_PIXEL_WIDTH) return; /* Set Cursor */ st7789v_SetCursor(Xpos, Ypos); for(counter = 0; counter < Length; counter++) { ArrayRGB[counter] = RGBCode; } LCD_IO_WriteMultipleData((uint8_t*)&ArrayRGB[0], Length * 2); } else{ if(Xpos + Length > ST7789V_LCD_PIXEL_HEIGHT) return; /* Set Cursor */ st7789v_SetCursor(Xpos, Ypos); for(counter = 0; counter < Length; counter++) { ArrayRGB[counter] = RGBCode; } LCD_IO_WriteMultipleData((uint8_t*)&ArrayRGB[0], Length * 2); } } /** * @brief Draws vertical line. * @param RGBCode: Specifies the RGB color * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @param Length: specifies the line length. * @retval None */ void st7789v_DrawVLine(uint16_t RGBCode, uint16_t Xpos, uint16_t Ypos, uint16_t Length) { uint8_t counter = 0; if(0 == st7789v_rotation || 2 == st7789v_rotation){ if(Ypos + Length > ST7789V_LCD_PIXEL_HEIGHT) return; for(counter = 0; counter < Length; counter++) { st7789v_WritePixel(Xpos, Ypos, RGBCode); } } else { if(Ypos + Length > ST7789V_LCD_PIXEL_WIDTH) return; for(counter = 0; counter < Length; counter++) { st7789v_WritePixel(Xpos, Ypos, RGBCode); } } } /** * @brief Gets the LCD pixel Width. * @param None * @retval The Lcd Pixel Width */ uint16_t st7789v_GetLcdPixelWidth(void) { return ST7789V_LCD_PIXEL_WIDTH; } /** * @brief Gets the LCD pixel Height. * @param None * @retval The Lcd Pixel Height */ uint16_t st7789v_GetLcdPixelHeight(void) { return ST7789V_LCD_PIXEL_HEIGHT; } /** * @brief Displays a bitmap picture loaded in the internal Flash. * @param BmpAddress: Bmp picture address in the internal Flash. * @retval None */ void st7789v_DrawBitmap(uint16_t Xpos, uint16_t Ypos, uint8_t *pbmp) { uint32_t index = 0, size = 0; /* Read bitmap size */ size = *(volatile uint16_t *) (pbmp + 2); size |= (*(volatile uint16_t *) (pbmp + 4)) << 16; /* Get bitmap data address offset */ index = *(volatile uint16_t *) (pbmp + 10); index |= (*(volatile uint16_t *) (pbmp + 12)) << 16; size = (size - index)/2; pbmp += index; /* Set GRAM write direction and BGR = 0 */ /* Memory access control: MY = 0, MX = 1, MV = 0, ML = 0 */ st7789v_WriteReg(0x36, 0x40);// LCD_REG_54 0x36 /* Memory data access control: MADCTL */ /* Set Cursor */ st7789v_SetCursor(Xpos, Ypos); LCD_IO_WriteMultipleData((uint8_t*)pbmp, size*2); /* Set GRAM write direction and BGR = 0 */ /* Memory access control: MY = 1, MX = 1, MV = 0, ML = 0 */ st7789v_WriteReg(0x36, 0xC0);/* Memory data access control: MADCTL */ } /** * @} */ void st7789v_FillRect(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height, uint16_t RGBCode) { if ((Xpos >= st7789v_width) || (Ypos >= st7789v_height)) return; int16_t x2 = Xpos + Width - 1, y2 = Ypos + Height - 1; if ((x2 < 0) || (y2 < 0)) return; // Clip right/bottom if (x2 >= st7789v_width) Width = st7789v_width - Xpos; if (y2 >= st7789v_height) Height = st7789v_height - Ypos; int32_t len = (int32_t)Width * Height; st7789v_SetDisplayWindow(Xpos, Ypos, Width, Height); /* Prepare to write GRAM */ LCD_IO_WriteReg(0x2C); st7789v_WriteColor(RGBCode,len); } void st7789v_WriteColor(uint16_t color, uint32_t len){ //#define TFT_MAX_PIXELS_AT_ONCE 32 uint16_t temp[32] ; size_t blen = (len > 32) ? 32 : len; uint16_t tlen = 0; for(uint32_t t = 0; t < blen; t ++){ temp[t] = color; } while (len) { tlen = (len > blen) ? blen : len; LCD_IO_WriteMultipleData((uint8_t*)temp, tlen*2); len -= tlen; } } /** * @brief Set the Rotation. * @param rotation: 0(0��), 1(90��), 2(180��), 3(270��) * @retval None */ void st7789_SetRotation(uint8_t rotation) { st7789v_rotation = rotation%4; switch(st7789v_rotation){ case 0: /* Memory access control: MY = 0, MX = 0, MV = 0, ML = 0 */ /* */ st7789v_WriteReg(0X2A, 0x01); st7789v_WriteReg(0X2A, 0x02); st7789v_WriteReg(0X2B, 0x01); #if 0 st7789v_WriteReg(0X36, 0x08); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0xEF); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x01); st7789v_WriteReg(0x2B, 0x3F); #endif st7789v_height = ST7789V_LCD_PIXEL_HEIGHT; st7789v_width = ST7789V_LCD_PIXEL_WIDTH; break; case 1: /* Memory access control: MY = 0, MX = 1, MV = 1, ML = 0 */ #if 1 st7789v_WriteReg(0X36, 0x68); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x01); st7789v_WriteReg(0x2A, 0x3F); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0xEF); #endif st7789v_height = ST7789V_LCD_PIXEL_WIDTH; st7789v_width = ST7789V_LCD_PIXEL_HEIGHT; break; case 2: /* Memory access control: MY = 1, MX = 1, MV = 0, ML = 0 */ #if 1 st7789v_WriteReg(0X36, 0xC8); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0xEF); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x01); st7789v_WriteReg(0x2B, 0x3F); #endif st7789v_height = ST7789V_LCD_PIXEL_HEIGHT; st7789v_width = ST7789V_LCD_PIXEL_WIDTH; break; case 3: /* Memory access control: MY = 1, MX = 0, MV = 1, ML = 0 */ #if 1 st7789v_WriteReg(0X36, 0xA8); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x00); st7789v_WriteReg(0x2A, 0x01); st7789v_WriteReg(0x2A, 0x3F); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0x00); st7789v_WriteReg(0x2B, 0xEF); #endif st7789v_height = ST7789V_LCD_PIXEL_WIDTH; st7789v_width = ST7789V_LCD_PIXEL_HEIGHT; break; } } /** * @} */ /** * @} */ /** * @} */