#ifndef HW_LIB_ST7735_H
#define HW_LIB_ST7735_H

#ifdef __cplusplus
extern "C" {
#endif

#define WHITE             0xFFFF
#define BLACK             0x0000
#define BLUE             0x001F
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE             0X07FF
#define RED             0xF800
#define MAGENTA         0xF81F
#define GREEN             0x07E0
#define CYAN             0x7FFF
#define YELLOW             0xFFE0
#define BROWN             0XBC40 //棕色
#define BRRED             0XFC07 //棕红色
#define GRAY             0X8430 //灰色
#define DARKBLUE         0X01CF    //深蓝色
#define LIGHTBLUE         0X7D7C    //浅蓝色
#define GRAYBLUE         0X5458 //灰蓝色


/**
  * @brief  ST7735 Registers
  */
#define ST7735_NOP                          0x00U  /* No Operation: NOP                           */
#define ST7735_SW_RESET                     0x01U  /* Software reset: SWRESET                     */
#define ST7735_READ_ID                      0x04U  /* Read Display ID: RDDID                      */
#define ST7735_READ_STATUS                  0x09U  /* Read Display Statu: RDDST                   */
#define ST7735_READ_POWER_MODE              0x0AU  /* Read Display Power: RDDPM                   */
#define ST7735_READ_MADCTL                  0x0BU  /* Read Display: RDDMADCTL                     */
#define ST7735_READ_PIXEL_FORMAT            0x0CU  /* Read Display Pixel: RDDCOLMOD               */
#define ST7735_READ_IMAGE_MODE              0x0DU  /* Read Display Image: RDDIM                   */
#define ST7735_READ_SIGNAL_MODE             0x0EU  /* Read Display Signal: RDDSM                  */
#define ST7735_SLEEP_IN                     0x10U  /* Sleep in & booster off: SLPIN               */
#define ST7735_SLEEP_OUT                    0x11U  /* Sleep out & booster on: SLPOUT              */
#define ST7735_PARTIAL_DISPLAY_ON           0x12U  /* Partial mode on: PTLON                      */
#define ST7735_NORMAL_DISPLAY_OFF           0x13U  /* Partial off (Normal): NORON                 */
#define ST7735_DISPLAY_INVERSION_OFF        0x20U  /* Display inversion off: INVOFF               */
#define ST7735_DISPLAY_INVERSION_ON         0x21U  /* Display inversion on: INVON                 */
#define ST7735_GAMMA_SET                    0x26U  /* Gamma curve select: GAMSET                  */
#define ST7735_DISPLAY_OFF                  0x28U  /* Display off: DISPOFF                        */
#define ST7735_DISPLAY_ON                   0x29U  /* Display on: DISPON                          */
#define ST7735_CASET                        0x2AU  /* Column address set: CASET                   */
#define ST7735_RASET                        0x2BU  /* Row address set: RASET                      */
#define ST7735_WRITE_RAM                    0x2CU  /* Memory write: RAMWR                         */
#define ST7735_RGBSET                       0x2DU  /* LUT for 4k,65k,262k color: RGBSET           */
#define ST7735_READ_RAM                     0x2EU  /* Memory read: RAMRD                          */
#define ST7735_PTLAR                        0x30U  /* Partial start/end address set: PTLAR        */
#define ST7735_TE_LINE_OFF                  0x34U  /* Tearing effect line off: TEOFF              */
#define ST7735_TE_LINE_ON                   0x35U  /* Tearing effect mode set & on: TEON          */
#define ST7735_MADCTL                       0x36U  /* Memory data access control: MADCTL          */
#define ST7735_IDLE_MODE_OFF                0x38U  /* Idle mode off: IDMOFF                       */
#define ST7735_IDLE_MODE_ON                 0x39U  /* Idle mode on: IDMON                         */
#define ST7735_COLOR_MODE                   0x3AU  /* Interface pixel format: COLMOD              */
#define ST7735_FRAME_RATE_CTRL1             0xB1U  /* In normal mode (Full colors): FRMCTR1       */
#define ST7735_FRAME_RATE_CTRL2             0xB2U  /* In Idle mode (8-colors): FRMCTR2            */
#define ST7735_FRAME_RATE_CTRL3             0xB3U  /* In partial mode + Full colors: FRMCTR3      */
#define ST7735_FRAME_INVERSION_CTRL         0xB4U  /* Display inversion control: INVCTR           */
#define ST7735_DISPLAY_SETTING              0xB6U  /* Display function setting                    */
#define ST7735_PWR_CTRL1                    0xC0U  /* Power control setting: PWCTR1               */
#define ST7735_PWR_CTRL2                    0xC1U  /* Power control setting: PWCTR2               */
#define ST7735_PWR_CTRL3                    0xC2U  /* In normal mode (Full colors): PWCTR3        */
#define ST7735_PWR_CTRL4                    0xC3U  /* In Idle mode (8-colors): PWCTR4             */
#define ST7735_PWR_CTRL5                    0xC4U  /* In partial mode + Full colors: PWCTR5       */
#define ST7735_VCOMH_VCOML_CTRL1            0xC5U  /* VCOM control 1: VMCTR1                      */
#define ST7735_VMOF_CTRL                    0xC7U  /* Set VCOM offset control: VMOFCTR            */
#define ST7735_WRID2                        0xD1U  /* Set LCM version code: WRID2                 */
#define ST7735_WRID3                        0xD2U  /* Customer Project code: WRID3                */
#define ST7735_NV_CTRL1                     0xD9U  /* NVM control status: NVCTR1                  */
#define ST7735_READ_ID1                     0xDAU  /* Read ID1: RDID1                             */
#define ST7735_READ_ID2                     0xDBU  /* Read ID2: RDID2                             */
#define ST7735_READ_ID3                     0xDCU  /* Read ID3: RDID3                             */
#define ST7735_NV_CTRL2                     0xDEU  /* NVM Read Command: NVCTR2                    */
#define ST7735_NV_CTRL3                     0xDFU  /* NVM Write Command: NVCTR3                   */
#define ST7735_PV_GAMMA_CTRL                0xE0U  /* Set Gamma adjustment (+ polarity): GAMCTRP1 */
#define ST7735_NV_GAMMA_CTRL                0xE1U  /* Set Gamma adjustment (- polarity): GAMCTRN1 */
#define ST7735_EXT_CTRL                     0xF0U  /* Extension command control                   */
#define ST7735_PWR_CTRL6                    0xFCU  /* In partial mode + Idle mode: PWCTR6         */
#define ST7735_VCOM4_LEVEL                  0xFFU  /* VCOM 4 level control                        */

/**
  * @brief  ST7735 ID
  */
#define  ST7735_ID              0x5CU

/**
  * @brief  ST7735 1.8 inch Size
  */
#define  ST7735_1_8_WIDTH           128U
#define  ST7735_1_8_HEIGHT          160U
/**
  * @brief  ST7735 0.9 inch Size
  */
#define  ST7735_0_9_WIDTH           80U
#define  ST7735_0_9_HEIGHT          160U
/**
 *  @brief LCD_OrientationTypeDef
 *  Possible values of Display Orientation
 */
#define ST7735_ORIENTATION_PORTRAIT 0x00U /* 液晶屏纵向选择 */
#define ST7735_ORIENTATION_PORTRAIT_ROT180 0x01U /* 纵向旋转 180° 方向 液晶屏选择 */
#define ST7735_ORIENTATION_LANDSCAPE 0x02U /* 液晶屏横向选择 */
#define ST7735_ORIENTATION_LANDSCAPE_ROT180 0x03U /* 横向旋转 180° 方向 液晶屏选择 */

/**
 *  @brief  Possible values of pixel data format (ie color coding)
 */
#define ST7735_FORMAT_RBG444                0x03U /* Pixel format chosen is RGB444 : 12 bpp */
#define ST7735_FORMAT_RBG565                0x05U /* Pixel format chosen is RGB565 : 16 bpp */
#define ST7735_FORMAT_RBG666                0x06U /* Pixel format chosen is RGB666 : 18 bpp */
#define ST7735_FORMAT_DEFAULT               ST7735_FORMAT_RBG565

/**
 *  @brief  LCD_Type_Define
 */
#define ST7735_1_8_inch_screen                            0x00U
#define ST7735_0_9_inch_screen                            0x01U
#define ST7735_1_8a_inch_screen                            0x02U
/**
 *  @brief  LCD_Panel
 */
#define HannStar_Panel                                            0x00U
#define BOE_Panel                                                        0x01U

/**
 *  @brief  LCD RGB or BGR
 */
#define ST7735_RGB                                                        0x00U
#define ST7735_BGR                                                        0x08U


#define ST7735_DELAY 120
#define ST7735_PANEL HannStar_Panel
#define ST7735_TYPE ST7735_0_9_inch_screen


#if ST7735_TYPE == ST7735_0_9_inch_screen        //0.96 ST7735
#if ST7735_PANEL == HannStar_Panel
#define ST7735_X_OFFSET 26
#define ST7735_Y_OFFSET 1
#else		//BOE Panel
#define ST7735_X_OFFSET 24
#define ST7735_Y_OFFSET 0
#endif
#endif

#if ST7735_TYPE == ST7735_1_8a_inch_screen
#if ST7735_PANEL == BOE_Panel
#define ST7735_X_OFFSET 2
#define ST7735_Y_OFFSET 1
#endif
#endif

#if ST7735_PANEL == HannStar_Panel
#define ST7735_DIR_MASK(dir) st7735dirTab[dir][1] | ST7735_BGR;
#else
#define ST7735_DIR_MASK(dir) st7735dirTab[dir][1] | ST7735_RGB;
#endif

const uint8_t st7735initcmd[] = {
        0x81, ST7735_SW_RESET,
        0x81, ST7735_SW_RESET,
        2, ST7735_SLEEP_OUT, 0x00,
        4, ST7735_FRAME_RATE_CTRL1, 0x01, 0x2C, 0x2D,
        4, ST7735_FRAME_RATE_CTRL2, 0x01, 0x2C, 0X2D,
        7, ST7735_FRAME_RATE_CTRL3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D,
        2, ST7735_FRAME_INVERSION_CTRL, 0x07,
        4, ST7735_PWR_CTRL1, 0xA2, 0x02, 0x84,
        2, ST7735_PWR_CTRL2, 0xC5,
        3, ST7735_PWR_CTRL3, 0x0A, 0X00,
        3, ST7735_PWR_CTRL4, 0x8A, 0x2A,
        3, ST7735_PWR_CTRL5, 0x8A, 0xEE,
        2, ST7735_VCOMH_VCOML_CTRL1, 0x0E,
        1, ST7735_DISPLAY_INVERSION_ON,//HannStar_Panel
//    1,ST7735_DISPLAY_INVERSION_OFF,//BOE_Panel
        2, ST7735_COLOR_MODE, ST7735_FORMAT_RBG565,
        17, ST7735_PV_GAMMA_CTRL, 0x02, 0x1C, 0x07U, 0x12U, 0x37U, 0x32U, 0x29U, 0x2DU, 0x29U, 0x25U, 0x2BU, 0x39U,
        0x00U, 0x01U, 0x03U, 0x10U,
        17, ST7735_NV_GAMMA_CTRL, 0x03, 0x1DU, 0x07U, 0x06U, 0x2EU, 0x2CU, 0x29U, 0x2DU, 0x2EU, 0x2EU, 0x37U, 0x3FU,
        0x00U, 0x00U, 0x02U, 0x10U,
        2, ST7735_DISPLAY_OFF, 0x00,
        2, ST7735_DISPLAY_ON, 0x00
};
const uint8_t st7735dirTab[4][2] =
        {
                {0x40U, 0xC0U}, /* 液晶屏纵向选择 */
                {0x80U, 0x00U}, /* 液晶屏纵向旋转 180° 方向选择 */
                {0x20U, 0x60U}, /* 液晶屏横向选择 */
                {0xE0U, 0xA0U}, /* 液晶屏横向旋转 180° 方向选择 */
        };

#define ST7735_ReadID(dev, id) do{\
    if (dev->id==ST7735_ID){                 \
    uint8_t tmp[3] = {};\
    dev->writeReg(ST7735_READ_ID1,&tmp[0],1);\
    dev->writeReg(ST7735_READ_ID2,&tmp[1],1);\
    dev->writeReg(ST7735_READ_ID3,&tmp[2],1);\
    id = ((uint32_t) tmp[2]) << 0 | ((uint32_t) tmp[1]) << 8 | ((uint32_t) tmp[0]) << 16;}\
}while(0)
#if ST7735_TYPE == ST7735_0_9_inch_screen
#define ST7735_SetDir(dev, dir)  do{\
    if (dev->id==ST7735_ID){                             \
    if((dir == ST7735_ORIENTATION_PORTRAIT) || (dir == ST7735_ORIENTATION_PORTRAIT_ROT180))\
    {\
        dev->width  = ST7735_0_9_WIDTH;\
        dev->height = ST7735_0_9_HEIGHT;\
    }\
    else\
    {\
        dev->width  =  ST7735_0_9_HEIGHT;\
        dev->height =  ST7735_0_9_WIDTH;\
    }                             \
    tmp = ST7735_DIR_MASK(dir);\
    dev->writeReg(ST7735_MADCTL,&tmp,1);}               \
}while(0)
#endif
#if ST7735_TYPE == ST7735_1_8_inch_screen || ST7735_TYPE == ST7735_1_8a_inch_screen
#define ST7735_SetDir(dev,dir) do{\
    if (dev->id==ST7735_ID){\
    if((dir == ST7735_ORIENTATION_PORTRAIT) || (dir == ST7735_ORIENTATION_PORTRAIT_ROT180))\
    {\
        dev->width  = ST7735_1_8_WIDTH;\
        dev->height = ST7735_1_8_HEIGHT;\
    }\
    else\
    {\
        dev->width  =  ST7735_1_8_HEIGHT;\
        dev->height =  ST7735_1_8_WIDTH;\
    }\
    }\
}while(0)
#endif

#define ST7735_OFFSET(dev, x, y) do{ \
    if (dev->id==ST7735_ID){\
    if (dev->dir <= LONGITUDINAL_180) { \
        x += ST7735_X_OFFSET;\
        y += ST7735_Y_OFFSET;\
    } else {\
        x += ST7735_Y_OFFSET;\
        y += ST7735_X_OFFSET;\
    }\
    }\
}while(0)

#define ST7735_ReadRam(dev, rec) do{ \
    if(dev->id==ST7735_ID){                    \
        dev->readReg(ST7735_READ_RAM,&tmp,1);\
        dev->recvData(&tmp,1);\
        dev->recvData(&pixel_lsb,1);\
        dev->recvData(&pixel_msb,1);\
        rec.color=((uint32_t)(pixel_lsb)) + ((uint32_t)(pixel_msb) << 8);\
    }\
}while(0)

#ifdef __cplusplus
}
#endif
#endif //HW_LIB_ST7735_H