/**
******************************************************************************
* @file st7735.c
* @author MCD Application Team
* @brief This file includes the driver for ST7735 LCD mounted on the Adafruit
* 1.8" TFT LCD shield (reference ID 802).
******************************************************************************
* @attention
*
*
© Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include
#include
#include
#include "st7735.h"
#define DRV_DEBUG
#define LOG_TAG "st7735"
#include
#define IS_BOE_PANEL (0)
/** @addtogroup BSP
* @{
*/
/** @addtogroup Components
* @{
*/
/** @addtogroup ST7735
* @brief This file provides a set of functions needed to drive the
* ST7735 LCD.
* @{
*/
/** @defgroup ST7735_Private_Types Private Types
* @{
*/
typedef struct
{
uint32_t Width;
uint32_t Height;
uint32_t Orientation;
} ST7735_Ctx_t;
/**
* @}
*/
/** @defgroup ST7735_Private_Variables Private Variables
* @{
*/
ST7735_LCD_Drv_t ST7735_LCD_Driver =
{
ST7735_Init,
ST7735_DeInit,
ST7735_ReadID,
ST7735_DisplayOn,
ST7735_DisplayOff,
ST7735_SetBrightness,
ST7735_GetBrightness,
ST7735_SetOrientation,
ST7735_GetOrientation,
ST7735_SetCursor,
ST7735_DrawBitmap,
ST7735_FillRGBRect,
ST7735_DrawHLine,
ST7735_DrawVLine,
ST7735_FillRect,
ST7735_GetPixel,
ST7735_SetPixel,
ST7735_GetXSize,
ST7735_GetYSize,
};
/* The below table handle the different values to be set to Memory Data Access Control
depending on the orientation and pbm image writing where the data order is inverted
*/
static uint32_t OrientationTab[4][2] =
{
{0x48U , 0xC8U}, /* Portrait orientation choice of LCD screen */
{0x88U , 0x08U}, /* Portrait rotated 180° orientation choice of LCD screen */
{0x28U , 0x68U}, /* Landscape orientation choice of LCD screen */
{0xE8U , 0xA8U} /* Landscape rotated 180° orientation choice of LCD screen */
};
static ST7735_Ctx_t ST7735Ctx;
/**
* @}
*/
/** @defgroup ST7735_Private_FunctionsPrototypes Private Functions Prototypes
* @{
*/
static int32_t ST7735_SetDisplayWindow(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height);
static int32_t ST7735_ReadRegWrap(void *Handle, uint8_t Reg, uint8_t* pData);
static int32_t ST7735_WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint32_t Length);
static int32_t ST7735_SendDataWrap(void *Handle, uint8_t *pData, uint32_t Length);
static int32_t ST7735_RecvDataWrap(void *Handle, uint8_t *pData, uint32_t Length);
static int32_t ST7735_IO_Delay(ST7735_Object_t *pObj, uint32_t Delay);
/**
* @}
*/
/** @addtogroup ST7735_Exported_Functions
* @{
*/
/**
* @brief Register component IO bus
* @param pObj Component object pointer
* @param pIO Component IO structure pointer
* @retval Component status
*/
int32_t ST7735_RegisterBusIO (ST7735_Object_t *pObj, ST7735_IO_t *pIO)
{
int32_t ret;
if(pObj == NULL)
{
ret = ST7735_ERROR;
}
else
{
pObj->IO.Init = pIO->Init;
pObj->IO.DeInit = pIO->DeInit;
pObj->IO.Address = pIO->Address;
pObj->IO.WriteReg = pIO->WriteReg;
pObj->IO.ReadReg = pIO->ReadReg;
pObj->IO.SendData = pIO->SendData;
pObj->IO.RecvData = pIO->RecvData;
pObj->IO.GetTick = pIO->GetTick;
pObj->Ctx.ReadReg = ST7735_ReadRegWrap;
pObj->Ctx.WriteReg = ST7735_WriteRegWrap;
pObj->Ctx.SendData = ST7735_SendDataWrap;
pObj->Ctx.RecvData = ST7735_RecvDataWrap;
pObj->Ctx.handle = pObj;
if(pObj->IO.Init != NULL)
{
ret = pObj->IO.Init();
}
else
{
ret = ST7735_ERROR;
}
}
return ret;
}
/**
* @brief Initialize the st7735 LCD Component.
* @param pObj Component object
* @param ColorCoding RGB mode
* @param Orientation Display orientation
* @retval Component status
*/
int32_t ST7735_Init(ST7735_Object_t *pObj, uint32_t ColorCoding, uint32_t Orientation)
{
uint8_t tmp;
int32_t ret;
if(pObj == NULL)
{
ret = ST7735_ERROR;
}
else
{
/* Out of sleep mode, 0 args, delay 120ms */
tmp = 0x00U;
ret = st7735_write_reg(&pObj->Ctx, ST7735_SW_RESET, &tmp, 0);
(void)ST7735_IO_Delay(pObj, 120);
/* Out of sleep mode, 0 args, no delay */
tmp = 0x00U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_SLEEP_OUT, &tmp, 1);
/* Frame rate ctrl - normal mode, 3 args:Rate = fosc/(1x2+40) * (LINE+2C+2D)*/
ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL1, &tmp, 0);
tmp = 0x01U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Frame rate control - idle mode, 3 args:Rate = fosc/(1x2+40) * (LINE+2C+2D) */
tmp = 0x01U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL2, &tmp, 1);
tmp = 0x2CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Frame rate ctrl - partial mode, 6 args: Dot inversion mode, Line inversion mode */
tmp = 0x01U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL3, &tmp, 1);
tmp = 0x2CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x01U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Display inversion ctrl, 1 arg, no delay: No inversion */
tmp = 0x07U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_INVERSION_CTRL, &tmp, 1);
/* Power control, 3 args, no delay: -4.6V , AUTO mode */
tmp = 0xA2U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL1, &tmp, 1);
tmp = 0x02U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x84U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Power control, 1 arg, no delay: VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */
tmp = 0xC5U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL2, &tmp, 1);
/* Power control, 2 args, no delay: Opamp current small, Boost frequency */
tmp = 0x0AU;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL3, &tmp, 1);
tmp = 0x00U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Power control, 2 args, no delay: BCLK/2, Opamp current small & Medium low */
tmp = 0x8AU;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL4, &tmp, 1);
tmp = 0x2AU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Power control, 2 args, no delay */
tmp = 0x8AU;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL5, &tmp, 1);
tmp = 0xEEU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Power control, 1 arg, no delay */
tmp = 0x0EU;
ret += st7735_write_reg(&pObj->Ctx, ST7735_VCOMH_VCOML_CTRL1, &tmp, 1);
#if IS_BOE_PANEL
/* Not Invert display, no args, no delay */
ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_INVERSION_OFF, &tmp, 0);
#else
/* Invert display, no args, no delay */
ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_INVERSION_ON, &tmp, 0);
#endif
/* Set color mode, 1 arg, no delay */
ret += st7735_write_reg(&pObj->Ctx, ST7735_COLOR_MODE, (uint8_t*)&ColorCoding, 1);
/* Magical unicorn dust, 16 args, no delay */
tmp = 0x02U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_PV_GAMMA_CTRL, &tmp, 1);
tmp = 0x1CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x07U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x12U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x37U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x32U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x29U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x29U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x25U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2BU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x39U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x00U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x01U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x03U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x10U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Sparkles and rainbows, 16 args, no delay */
tmp = 0x03U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_NV_GAMMA_CTRL, &tmp, 1);
tmp = 0x1DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x07U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x06U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2EU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2CU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x29U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2DU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2EU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x2EU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x37U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x3FU;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x00U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x00U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x02U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = 0x10U;
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Normal display on, no args, no delay */
tmp = 0x00U;
ret += st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 1);
/* Main screen turn on, no delay */
ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_ON, &tmp, 1);
/* Set the display Orientation and the default display window */
ret += ST7735_SetOrientation(pObj, Orientation);
}
if(ret != ST7735_OK)
{
LOG_E("error %d", ret);
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief De-Initialize the st7735 LCD Component.
* @param pObj Component object
* @retval Component status
*/
int32_t ST7735_DeInit(ST7735_Object_t *pObj)
{
(void)(pObj);
return ST7735_OK;
}
/**
* @brief Get the st7735 ID.
* @param pObj Component object
* @param Id Component ID
* @retval The component status
*/
int32_t ST7735_ReadID(ST7735_Object_t *pObj, uint32_t *Id)
{
int32_t ret;
uint8_t tmp[3];
if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID1, &tmp[0]) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID2, &tmp[1]) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID3, &tmp[2]) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
*Id = ((uint32_t)tmp[2])<<0| ((uint32_t)tmp[1])<<8 | ((uint32_t)tmp[0])<<16;
//*Id = __rbit(*Id);
ret = ST7735_OK;
}
return ret;
}
/**
* @brief Enables the Display.
* @param pObj Component object
* @retval The component status
*/
int32_t ST7735_DisplayOn(ST7735_Object_t *pObj)
{
int32_t ret;
uint8_t tmp = 0;
ret = st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 0);
(void)ST7735_IO_Delay(pObj, 10);
ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_ON, &tmp, 0);
(void)ST7735_IO_Delay(pObj, 10);
ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 0);
tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Disables the Display.
* @param pObj Component object
* @retval The component status
*/
int32_t ST7735_DisplayOff(ST7735_Object_t *pObj)
{
int32_t ret;
uint8_t tmp = 0;
ret = st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 0);
(void)ST7735_IO_Delay(pObj, 10);
ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_OFF, &tmp, 0);
(void)ST7735_IO_Delay(pObj, 10);
ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 0);
tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Set the display brightness.
* @param pObj Component object
* @param Brightness display brightness to be set
* @retval Component status
*/
int32_t ST7735_SetBrightness(ST7735_Object_t *pObj, uint32_t Brightness)
{
(void)(pObj);
(void)(Brightness);
/* Feature not supported */
return ST7735_ERROR;
}
/**
* @brief Get the display brightness.
* @param pObj Component object
* @param Brightness display brightness to be returned
* @retval Component status
*/
int32_t ST7735_GetBrightness(ST7735_Object_t *pObj, uint32_t *Brightness)
{
(void)(pObj);
(void)(Brightness);
/* Feature not supported */
return ST7735_ERROR;
}
/**
* @brief Set the Display Orientation.
* @param pObj Component object
* @param Orientation ST7735_ORIENTATION_PORTRAIT, ST7735_ORIENTATION_PORTRAIT_ROT180
* ST7735_ORIENTATION_LANDSCAPE or ST7735_ORIENTATION_LANDSCAPE_ROT180
* @retval The component status
*/
int32_t ST7735_SetOrientation(ST7735_Object_t *pObj, uint32_t Orientation)
{
int32_t ret;
uint8_t tmp;
if((Orientation == ST7735_ORIENTATION_PORTRAIT) || (Orientation == ST7735_ORIENTATION_PORTRAIT_ROT180))
{
ST7735Ctx.Width = ST7735_WIDTH;
ST7735Ctx.Height = ST7735_HEIGHT;
}
else
{
ST7735Ctx.Width = ST7735_HEIGHT;
ST7735Ctx.Height = ST7735_WIDTH;
}
ST7735Ctx.Orientation = Orientation;
ret = ST7735_SetDisplayWindow(pObj, 0U, 0U, ST7735Ctx.Width, ST7735Ctx.Height);
tmp = (uint8_t)OrientationTab[Orientation][1];
ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Set the Display Orientation.
* @param pObj Component object
* @param Orientation ST7735_ORIENTATION_PORTRAIT, ST7735_ORIENTATION_LANDSCAPE
* or ST7735_ORIENTATION_LANDSCAPE_ROT180
* @retval The component status
*/
int32_t ST7735_GetOrientation(ST7735_Object_t *pObj, uint32_t *Orientation)
{
*Orientation = ST7735Ctx.Orientation;
return ST7735_OK;
}
/**
* @brief Set Cursor position.
* @param pObj Component object
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @retval The component status
*/
int32_t ST7735_SetCursor(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos)
{
int32_t ret;
uint8_t tmp;
/* Cursor calibration */
if(ST7735Ctx.Orientation <= ST7735_ORIENTATION_PORTRAIT_ROT180)
{
#if IS_BOE_PANEL
Xpos += 24;
Ypos += 0;
#else
Xpos += 26;
Ypos += 1;
#endif
}
else
{
#if IS_BOE_PANEL
Xpos += 0;
Ypos += 24;
#else
Xpos += 1;
Ypos += 26;
#endif
}
ret = st7735_write_reg(&pObj->Ctx, ST7735_CASET, &tmp, 0);
tmp = (uint8_t)(Xpos >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)(Xpos & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
ret += st7735_write_reg(&pObj->Ctx, ST7735_RASET, &tmp, 0);
tmp = (uint8_t)(Ypos >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)(Ypos & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
ret += st7735_write_reg(&pObj->Ctx, ST7735_WRITE_RAM, &tmp, 0);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Displays a bitmap picture.
* @param pObj Component object
* @param Xpos Bmp X position in the LCD
* @param Ypos Bmp Y position in the LCD
* @param pBmp Bmp picture address.
* @retval The component status
*/
int32_t ST7735_DrawBitmap(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint8_t *pBmp)
{
int32_t ret = ST7735_OK;
uint32_t index, size, width, height, y_pos;
uint8_t pixel_val[2], tmp;
uint8_t *pbmp;
uint32_t counter = 0;
/* Get bitmap data address offset */
index = (uint32_t)pBmp[10] + ((uint32_t)pBmp[11] << 8) + ((uint32_t)pBmp[12] << 16) + ((uint32_t)pBmp[13] << 24);
/* Read bitmap width */
width = (uint32_t)pBmp[18] + ((uint32_t)pBmp[19] << 8) + ((uint32_t)pBmp[20] << 16) + ((uint32_t)pBmp[21] << 24);
/* Read bitmap height */
height = (uint32_t)pBmp[22] + ((uint32_t)pBmp[23] << 8) + ((uint32_t)pBmp[24] << 16) + ((uint32_t)pBmp[25] << 24);
/* Read bitmap size */
size = (uint32_t)pBmp[2] + ((uint32_t)pBmp[3] << 8) + ((uint32_t)pBmp[4] << 16) + ((uint32_t)pBmp[5] << 24);
size = size - index;
pbmp = pBmp + index;
/* Remap Ypos, st7735 works with inverted X in case of bitmap */
/* X = 0, cursor is on Top corner */
y_pos = ST7735Ctx.Height - Ypos - height;
if(ST7735_SetDisplayWindow(pObj, Xpos, y_pos, width, height) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
/* Set GRAM write direction and BGR = 0 */
tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][0];
if(st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1) != ST7735_OK)
{
ret = ST7735_ERROR;
}/* Set Cursor */
else if(ST7735_SetCursor(pObj, Xpos, y_pos) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
do
{
pixel_val[0] = *(pbmp + 1);
pixel_val[1] = *(pbmp);
if(st7735_send_data(&pObj->Ctx, pixel_val, 2U) != ST7735_OK)
{
ret = ST7735_ERROR;
break;
}
counter +=2U;
pbmp += 2;
}while(counter < size);
tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
if(st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
if(ST7735_SetDisplayWindow(pObj, 0U, 0U, ST7735Ctx.Width, ST7735Ctx.Height) != ST7735_OK)
{
ret = ST7735_ERROR;
}
}
}
}
return ret;
}
/**
* @brief Draws a full RGB rectangle
* @param pObj Component object
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @param pData pointer to RGB data
* @param Width specifies the rectangle width.
* @param Height Specifies the rectangle height
* @retval The component status
*/
int32_t ST7735_FillRGBRect(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint8_t *pData, uint32_t Width, uint32_t Height)
{
int32_t ret = ST7735_OK;
static uint8_t pdata[640];
uint8_t *rgb_data = pData;
uint32_t i, j;
if(((Xpos + Width) > ST7735Ctx.Width) || ((Ypos + Height) > ST7735Ctx.Height))
{
ret = ST7735_ERROR;
}/* Set Cursor */
else
{
for(j = 0; j < Height; j++)
{
if(ST7735_SetCursor(pObj, Xpos, Ypos+j) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
for(i = 0; i < Width; i++)
{
pdata[2U*i] = (uint8_t)(*(rgb_data));
pdata[(2U*i) + 1U] = (uint8_t)(*(rgb_data + 1));
rgb_data +=2;
}
if(st7735_send_data(&pObj->Ctx, (uint8_t*)&pdata[0], 2U*Width) != ST7735_OK)
{
ret = ST7735_ERROR;
}
}
}
}
return ret;
}
/**
* @brief Draw Horizontal line.
* @param pObj Component object
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @param Length specifies the Line length.
* @param Color Specifies the RGB color in RGB565 format
* @retval The component status
*/
int32_t ST7735_DrawHLine(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Length, uint32_t Color)
{
int32_t ret = ST7735_OK;
uint32_t i;
static uint8_t pdata[640];
if((Xpos + Length) > ST7735Ctx.Width)
{
ret = ST7735_ERROR;
}/* Set Cursor */
else if(ST7735_SetCursor(pObj, Xpos, Ypos) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
for(i = 0; i < Length; i++)
{
/* Exchange LSB and MSB to fit LCD specification */
pdata[2U*i] = (uint8_t)(Color >> 8);
pdata[(2U*i) + 1U] = (uint8_t)(Color);
// pdata[(2U*i) + 1U] = (uint8_t)(Color >> 8);
// pdata[2U*i] = (uint8_t)(Color);
}
if(st7735_send_data(&pObj->Ctx, (uint8_t*)&pdata[0], 2U*Length) != ST7735_OK)
{
ret = ST7735_ERROR;
}
}
return ret;
}
/**
* @brief Draw vertical line.
* @param pObj Component object
* @param Color Specifies the RGB color
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @param Length specifies the Line length.
* @retval The component status
*/
int32_t ST7735_DrawVLine(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Length, uint32_t Color)
{
int32_t ret = ST7735_OK;
uint32_t counter;
if((Ypos + Length) > ST7735Ctx.Height)
{
ret = ST7735_ERROR;
}
else
{
for(counter = 0; counter < Length; counter++)
{
if(ST7735_SetPixel(pObj, Xpos, Ypos + counter, Color) != ST7735_OK)
{
ret = ST7735_ERROR;
break;
}
}
}
return ret;
}
/**
* @brief Fill rectangle
* @param pObj Component object
* @param Xpos X position
* @param Ypos Y position
* @param Width Rectangle width
* @param Height Rectangle height
* @param Color Draw color
* @retval Component status
*/
int32_t ST7735_FillRect(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height, uint32_t Color)
{
int32_t ret = ST7735_OK;
uint32_t i, y_pos = Ypos;
for(i = 0; i < Height; i++)
{
if(ST7735_DrawHLine(pObj, Xpos, y_pos, Width, Color) != ST7735_OK)
{
ret = ST7735_ERROR;
break;
}
y_pos++;
}
return ret;
}
/**
* @brief Write pixel.
* @param pObj Component object
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @param Color the RGB pixel color in RGB565 format
* @retval The component status
*/
int32_t ST7735_SetPixel(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Color)
{
int32_t ret = ST7735_OK;
uint16_t color;
/* Exchange LSB and MSB to fit LCD specification */
color = (uint16_t)((uint16_t)Color << 8);
color |= (uint16_t)((uint16_t)(Color >> 8));
if((Xpos >= ST7735Ctx.Width) || (Ypos >= ST7735Ctx.Height))
{
ret = ST7735_ERROR;
}/* Set Cursor */
else if(ST7735_SetCursor(pObj, Xpos, Ypos) != ST7735_OK)
{
ret = ST7735_ERROR;
}
else
{
/* Write RAM data */
if(st7735_send_data(&pObj->Ctx, (uint8_t*)&color, 2) != ST7735_OK)
{
ret = ST7735_ERROR;
}
}
return ret;
}
/**
* @brief Read pixel.
* @param pObj Component object
* @param Xpos specifies the X position.
* @param Ypos specifies the Y position.
* @param Color the RGB pixel color in RGB565 format
* @retval The component status
*/
int32_t ST7735_GetPixel(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t *Color)
{
int32_t ret;
uint8_t pixel_lsb, pixel_msb;
uint8_t tmp;
/* Set Cursor */
ret = ST7735_SetCursor(pObj, Xpos, Ypos);
/* Prepare to read LCD RAM */
ret += st7735_read_reg(&pObj->Ctx, ST7735_READ_RAM, &tmp); /* RAM read data command */
/* Dummy read */
ret += st7735_recv_data(&pObj->Ctx, &tmp, 1);
/* Read first part of the RGB888 data */
ret += st7735_recv_data(&pObj->Ctx, &pixel_lsb, 1);
/* Read first part of the RGB888 data */
ret += st7735_recv_data(&pObj->Ctx, &pixel_msb, 1);
*Color = ((uint32_t)(pixel_lsb)) + ((uint32_t)(pixel_msb) << 8);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Get the LCD pixel Width.
* @param pObj Component object
* @retval The Lcd Pixel Width
*/
int32_t ST7735_GetXSize(ST7735_Object_t *pObj, uint32_t *XSize)
{
(void)pObj;
*XSize = ST7735Ctx.Width;
return ST7735_OK;
}
/**
* @brief Get the LCD pixel Height.
* @param pObj Component object
* @retval The Lcd Pixel Height
*/
int32_t ST7735_GetYSize(ST7735_Object_t *pObj, uint32_t *YSize)
{
(void)pObj;
*YSize = ST7735Ctx.Height;
return ST7735_OK;
}
/**
* @}
*/
/** @defgroup ST7735_Private_Functions Private Functions
* @{
*/
/**
* @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 Component status
*/
static int32_t ST7735_SetDisplayWindow(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height)
{
int32_t ret;
uint8_t tmp;
/* Cursor calibration */
if(ST7735Ctx.Orientation <= ST7735_ORIENTATION_PORTRAIT_ROT180)
{
#if IS_BOE_PANEL
Xpos += 24;
Ypos += 0;
#else
Xpos += 26;
Ypos += 1;
#endif
}
else
{
#if IS_BOE_PANEL
Xpos += 0;
Ypos += 24;
#else
Xpos += 1;
Ypos += 26;
#endif
}
/* Column addr set, 4 args, no delay: XSTART = Xpos, XEND = (Xpos + Width - 1) */
ret = st7735_write_reg(&pObj->Ctx, ST7735_CASET, &tmp, 0);
tmp = (uint8_t)(Xpos >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)(Xpos & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)((Xpos + Width - 1U) >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)((Xpos + Width - 1U) & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
/* Row addr set, 4 args, no delay: YSTART = Ypos, YEND = (Ypos + Height - 1) */
ret += st7735_write_reg(&pObj->Ctx, ST7735_RASET, &tmp, 0);
tmp = (uint8_t)(Ypos >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)(Ypos & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)((Ypos + Height - 1U) >> 8U);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
tmp = (uint8_t)((Ypos + Height - 1U) & 0xFFU);
ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
if(ret != ST7735_OK)
{
ret = ST7735_ERROR;
}
return ret;
}
/**
* @brief Wrap component ReadReg to Bus Read function
* @param Handle Component object handle
* @param Reg The target register address to write
* @param pData The target register value to be written
* @retval Component error status
*/
static int32_t ST7735_ReadRegWrap(void *Handle, uint8_t Reg, uint8_t* pData)
{
ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
return pObj->IO.ReadReg(Reg, pData);
}
/**
* @brief Wrap component WriteReg to Bus Write function
* @param handle Component object handle
* @param Reg The target register address to write
* @param pData The target register value to be written
* @param Length buffer size to be written
* @retval Component error status
*/
static int32_t ST7735_WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint32_t Length)
{
ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
return pObj->IO.WriteReg(Reg, pData, Length);
}
/**
* @brief Wrap component SendData to Bus Write function
* @param handle Component object handle
* @param pData The target register value to be written
* @retval Component error status
*/
static int32_t ST7735_SendDataWrap(void *Handle, uint8_t *pData, uint32_t Length)
{
ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
return pObj->IO.SendData(pData, Length);
}
/**
* @brief Wrap component SendData to Bus Write function
* @param handle Component object handle
* @param pData The target register value to be written
* @retval Component error status
*/
static int32_t ST7735_RecvDataWrap(void *Handle, uint8_t *pData, uint32_t Length)
{
ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
return pObj->IO.RecvData(pData, Length);
}
/**
* @brief ST7735 delay
* @param Delay Delay in ms
* @retval Component error status
*/
static int32_t ST7735_IO_Delay(ST7735_Object_t *pObj, uint32_t Delay)
{
rt_thread_mdelay(Delay);
return ST7735_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/