ST773.c

by Marwen Maghrebi
/*
 * ST773.c
 *
 */


#include "ST7735.h"
#include "stdlib.h"

#define TFT_BL_H()  HAL_GPIO_WritePin(ST7735_BL_GPIO_Port, ST7735_BL_Pin, GPIO_PIN_SET)
#define TFT_BL_L()  HAL_GPIO_WritePin(ST7735_BL_GPIO_Port, ST7735_BL_Pin, GPIO_PIN_RESET)
#define TFT_CS_H()  HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_SET)
#define TFT_CS_L()  HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_RESET)
#define TFT_DC_D()  HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET)
#define TFT_DC_C()  HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_RESET)
#define TFT_RES_H() HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_SET)
#define TFT_RES_L() HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_RESET)

#define ST7735_COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
#define SWAP_INT16_T(a, b) { int16_t t = a; a = b; b = t; }
#define DELAY 0x80

#if defined(ST7735_1_8_DEFAULT_ORIENTATION) || defined(ST7735S_1_8_DEFAULT_ORIENTATION)
static uint8_t _data_rotation[4] = { ST7735_MADCTL_MX, ST7735_MADCTL_MY, ST7735_MADCTL_MV, ST7735_MADCTL_RGB };
#endif

#if defined(ST7735_1_44_DEFAULT_ORIENTATION) || defined(ST7735_MINI_DEFAULT_ORIENTATION)
static uint8_t _data_rotation[4] = { ST7735_MADCTL_MX, ST7735_MADCTL_MY, ST7735_MADCTL_MV, ST7735_MADCTL_BGR };
#endif

static uint8_t _value_rotation = 0;
static int16_t _height = ST7735_HEIGHT, _width = ST7735_WIDTH;
static uint8_t _xstart = ST7735_XSTART, _ystart = ST7735_YSTART;

// based on Adafruit ST7735 library for Arduino
static const uint8_t
init_cmds1[] = {                // Init for 7735R, part 1 (red or green tab)
      15,                       // 15 commands in list:
      ST7735_SWRESET, DELAY,    //  1: Software reset, 0 args, w/delay
      150,                      //     150 ms delay
      ST7735_SLPOUT, DELAY,   //  2: Out of sleep mode, 0 args, w/delay
      255,                      //     500 ms delay
      ST7735_FRMCTR1, 3,    //  3: Frame rate ctrl - normal mode, 3 args:
      0x01, 0x2C, 0x2D,         //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
      ST7735_FRMCTR2, 3,      //  4: Frame rate control - idle mode, 3 args:
      0x01, 0x2C, 0x2D,         //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
      ST7735_FRMCTR3, 6,      //  5: Frame rate ctrl - partial mode, 6 args:
      0x01, 0x2C, 0x2D,         //     Dot inversion mode
      0x01, 0x2C, 0x2D,         //     Line inversion mode
      ST7735_INVCTR, 1,     //  6: Display inversion ctrl, 1 arg, no delay:
      0x07,                     //     No inversion
      ST7735_PWCTR1, 3,     //  7: Power control, 3 args, no delay:
      0xA2,
      0x02,                     //     -4.6V
      0x84,                     //     AUTO mode
      ST7735_PWCTR2, 1,     //  8: Power control, 1 arg, no delay:
      0xC5,                     //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
      ST7735_PWCTR3, 2,     //  9: Power control, 2 args, no delay:
      0x0A,                     //     Opamp current small
      0x00,                     //     Boost frequency
      ST7735_PWCTR4, 2,     // 10: Power control, 2 args, no delay:
      0x8A,                     //     BCLK/2, Opamp current small & Medium low
      0x2A,
      ST7735_PWCTR5, 2,     // 11: Power control, 2 args, no delay:
      0x8A, 0xEE,
      ST7735_VMCTR1, 1,     // 12: Power control, 1 arg, no delay:
      0x0E,
      ST7735_INVOFF, 0,     // 13: Don't invert display, no args, no delay
      ST7735_MADCTL, 1,     // 14: Memory access control (directions), 1 arg:
      ST7735_DATA_ROTATION,     //     row addr/col addr, bottom to top refresh
      ST7735_COLMOD, 1,     // 15: set color mode, 1 arg, no delay:
      0x05},                  //     16-bit color

#if (defined(ST7735_IS_128X128) || defined(ST7735_IS_160X128))
init_cmds2[] = {            // Init for 7735R, part 2 (1.44" display)
    2,                  //  2 commands in list:
    ST7735_CASET, 4,    //  1: Column addr set, 4 args, no delay:
    0x00, 0x00,         //     XSTART = 0
    0x00, 0x7F,         //     XEND = 127
    ST7735_RASET, 4,    //  2: Row addr set, 4 args, no delay:
    0x00, 0x00,         //     XSTART = 0
    0x00, 0x7F },       //     XEND = 127
#endif // ST7735_IS_128X128

#ifdef ST7735_IS_160X80
init_cmds2[] = {          // Init for 7735S, part 2 (160x80 display)
    3,                          //  3 commands in list:
    ST7735_CASET, 4,        //  1: Column addr set, 4 args, no delay:
    0x00, 0x00,               //     XSTART = 0
    0x00, 0x4F,               //     XEND = 79
    ST7735_RASET, 4,        //  2: Row addr set, 4 args, no delay:
    0x00, 0x00,               //     XSTART = 0
    0x00, 0x9F ,              //     XEND = 159
    ST7735_INVON, 0 },        //  3: Invert colors
#endif

init_cmds3[] = {                // Init for 7735R, part 3 (red or green tab)
    4,                          //  4 commands in list:
    ST7735_GMCTRP1, 16,     //  1: Magical unicorn dust, 16 args, no delay:
    0x02, 0x1c, 0x07, 0x12,
    0x37, 0x32, 0x29, 0x2d,
    0x29, 0x25, 0x2B, 0x39,
    0x00, 0x01, 0x03, 0x10,
    ST7735_GMCTRN1, 16,     //  2: Sparkles and rainbows, 16 args, no delay:
    0x03, 0x1d, 0x07, 0x06,
    0x2E, 0x2C, 0x29, 0x2D,
    0x2E, 0x2E, 0x37, 0x3F,
    0x00, 0x00, 0x02, 0x10,
    ST7735_NORON, DELAY,    //  3: Normal display on, no args, w/delay
    10,                       //     10 ms delay
    ST7735_DISPON, DELAY,     //  4: Main screen turn on, no args w/delay
    100 };                    //     100 ms delay

static void ST7735_GPIO_Init(void);
static void ST7735_WriteCommand(uint8_t cmd);
static void ST7735_WriteData(uint8_t* buff, size_t buff_size);
static void ST7735_ExecuteCommandList(const uint8_t *addr);
static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
static void ST7735_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor);

static void ST7735_GPIO_Init(void)
{
//  GPIO_InitTypeDef GPIO_InitStruct = {0};
//
//  /* GPIO Ports Clock Enable */
//  __HAL_RCC_GPIOB_CLK_ENABLE();
//
//  /*Configure GPIO pin Output Level */
//  HAL_GPIO_WritePin(GPIOB, ST7735_RES_Pin|ST7735_DC_Pin|ST7735_CS_Pin|ST7735_BL_Pin, GPIO_PIN_RESET);
//
//  /*Configure GPIO pins : ST7735_RES_Pin ST7735_DC_Pin ST7735_CS_Pin ST7735_BL_Pin */
//  GPIO_InitStruct.Pin = ST7735_RES_Pin|ST7735_DC_Pin|ST7735_CS_Pin|ST7735_BL_Pin;
//  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//  GPIO_InitStruct.Pull = GPIO_NOPULL;
//  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
//  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

static void ST7735_Reset()
{
  TFT_RES_L();
  HAL_Delay(20);
  TFT_RES_H();
}

static void ST7735_WriteCommand(uint8_t cmd)
{
  TFT_DC_C();
#ifdef USE_SPI_DMA
  HAL_SPI_Transmit_DMA(&ST7735_SPI_PORT, &cmd, sizeof(cmd));
  //while(hspi1.State == HAL_SPI_STATE_BUSY_TX);
#else
  HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY);
#endif
}

static void ST7735_WriteData(uint8_t* buff, size_t buff_size)
{
  TFT_DC_D();
#ifdef USE_SPI_DMA
  HAL_SPI_Transmit_DMA(&ST7735_SPI_PORT, buff, buff_size);
  while(hspi1.State == HAL_SPI_STATE_BUSY_TX);

#else
  HAL_SPI_Transmit(&ST7735_SPI_PORT, buff, buff_size, HAL_MAX_DELAY);
#endif
}

static void ST7735_ExecuteCommandList(const uint8_t *addr)
{
    uint8_t numCommands, numArgs;
    uint16_t ms;

    numCommands = *addr++;
    while(numCommands--)
    {
      uint8_t cmd = *addr++;
        ST7735_WriteCommand(cmd);

        numArgs = *addr++;
        // If high bit set, delay follows args
        ms = numArgs & DELAY;
        numArgs &= ~DELAY;
        if(numArgs)
        {
            ST7735_WriteData((uint8_t*)addr, numArgs);
            addr += numArgs;
        }

        if(ms)
        {
            ms = *addr++;
            if(ms == 255) ms = 500;
            HAL_Delay(ms);
        }
    }
}

static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    // column address set
    ST7735_WriteCommand(ST7735_CASET);
    uint8_t data[] = { 0x00, x0 + _xstart, 0x00, x1 + _xstart };
    ST7735_WriteData(data, sizeof(data));

    // row address set
    ST7735_WriteCommand(ST7735_RASET);
    data[1] = y0 + _ystart;
    data[3] = y1 + _ystart;
    ST7735_WriteData(data, sizeof(data));

    // write to RAM
    ST7735_WriteCommand(ST7735_RAMWR);
}

static void ST7735_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor)
{
    uint32_t i, b, j;

    ST7735_SetAddressWindow(x, y, x+font.width-1, y+font.height-1);

    for(i = 0; i < font.height; i++)
    {
        b = font.data[(ch - 32) * font.height + i];
        for(j = 0; j < font.width; j++)
        {
            if((b << j) & 0x8000)
            {
                uint8_t data[] = { color >> 8, color & 0xFF };
                ST7735_WriteData(data, sizeof(data));
            }
            else
            {
                uint8_t data[] = { bgcolor >> 8, bgcolor & 0xFF };
                ST7735_WriteData(data, sizeof(data));
            }
        }
    }
}

void ST7735_Init()
{
  ST7735_GPIO_Init();
  TFT_CS_L();
    ST7735_Reset();
    ST7735_ExecuteCommandList(init_cmds1);
    ST7735_ExecuteCommandList(init_cmds2);
    ST7735_ExecuteCommandList(init_cmds3);
    TFT_CS_H();
}

void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color)
{
    if((x >= _width) || (y >= _height))
        return;

    TFT_CS_L();

    ST7735_SetAddressWindow(x, y, x+1, y+1);
    uint8_t data[] = { color >> 8, color & 0xFF };
    ST7735_WriteData(data, sizeof(data));

    TFT_CS_H();
}

void ST7735_DrawString(uint16_t x, uint16_t y, const char* str, FontDef font, uint16_t color, uint16_t bgcolor)
{
  TFT_CS_L();

    while(*str)
    {
        if(x + font.width >= _width)
        {
            x = 0;
            y += font.height;
            if(y + font.height >= _height)
            {
                break;
            }

            if(*str == ' ')
            {
                // skip spaces in the beginning of the new line
                str++;
                continue;
            }
        }

        ST7735_WriteChar(x, y, *str, font, color, bgcolor);
        x += font.width;
        str++;
    }
    TFT_CS_H();
}

void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
{
    // clipping
    if((x >= _width) || (y >= _height)) return;
    if((x + w - 1) >= _width) w = _width - x;
    if((y + h - 1) >= _height) h = _height - y;

    TFT_CS_L();
    ST7735_SetAddressWindow(x, y, x+w-1, y+h-1);

    uint8_t data[] = { color >> 8, color & 0xFF };
    TFT_DC_D();
    for(y = h; y > 0; y--)
    {
        for(x = w; x > 0; x--)
        {
#ifdef USE_SPI_DMA
          HAL_SPI_Transmit_DMA(&ST7735_SPI_PORT, data, sizeof(data));
          //while(hspi1.State == HAL_SPI_STATE_BUSY_TX);
#else
          HAL_SPI_Transmit(&ST7735_SPI_PORT, data, sizeof(data), HAL_MAX_DELAY);
#endif
        }
    }
    TFT_CS_H();
}

void ST7735_FillScreen(uint16_t color)
{
    ST7735_FillRectangle(0, 0, _width, _height, color);
}

void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data)
{
    if((x >= _width) || (y >= _height)) return;
    if((x + w - 1) >= _width) return;
    if((y + h - 1) >= _height) return;

    TFT_CS_L();
    ST7735_SetAddressWindow(x, y, x+w-1, y+h-1);
    ST7735_WriteData((uint8_t*)data, sizeof(uint16_t)*w*h);
    TFT_CS_H();
}

void ST7735_DrawTouchGFX(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data)
{
    if((x >= _width) || (y >= _height)) return;
    if((x + w - 1) >= _width) return;
    if((y + h - 1) >= _height) return;

    TFT_CS_L();
    ST7735_SetAddressWindow(x, y, x+w-1, y+h-1);

    uint32_t size = w * h;
    uint8_t colorBytes[size][2];

    for (uint32_t i = 0; i < size; i++)
  {
    colorBytes[i][0] = (*data & 0xFF00) >> 8;
    colorBytes[i][1] = *data & 0x00FF;
    data++;
  }

    TFT_DC_D();
  ST7735_WriteData((uint8_t*) &colorBytes, size * 2);
    TFT_CS_H();
}

void ST7735_InvertColors(bool invert)
{
  TFT_CS_L();
    ST7735_WriteCommand(invert ? ST7735_INVON : ST7735_INVOFF);
    TFT_CS_H();
}

void ST7735_Backlight_On(void)
{
  TFT_BL_H();
}

void ST7735_Backlight_Off(void)
{
  TFT_BL_L();
}

/***************************************************************************************
** Function name:           drawCircle
** Description:             Draw a circle outline
***************************************************************************************/
void ST7735_DrawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
{
  int16_t f = 1 - r;
  int16_t ddF_x = 1;
  int16_t ddF_y = - r - r;
  int16_t x = 0;

  ST7735_DrawPixel(x0 + r, y0  , color);
  ST7735_DrawPixel(x0 - r, y0  , color);
  ST7735_DrawPixel(x0  , y0 - r, color);
  ST7735_DrawPixel(x0  , y0 + r, color);

  while (x < r)
  {
    if (f >= 0)
    {
      r--;
      ddF_y += 2;
      f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;

    ST7735_DrawPixel(x0 + x, y0 + r, color);
    ST7735_DrawPixel(x0 - x, y0 + r, color);
    ST7735_DrawPixel(x0 - x, y0 - r, color);
    ST7735_DrawPixel(x0 + x, y0 - r, color);

    ST7735_DrawPixel(x0 + r, y0 + x, color);
    ST7735_DrawPixel(x0 - r, y0 + x, color);
    ST7735_DrawPixel(x0 - r, y0 - x, color);
    ST7735_DrawPixel(x0 + r, y0 - x, color);
  }
}

/***************************************************************************************
** Function name:           drawCircleHelper
** Description:             Support function for circle drawing
***************************************************************************************/
void ST7735_DrawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color)
{
  int16_t f     = 1 - r;
  int16_t ddF_x = 1;
  int16_t ddF_y = -2 * r;
  int16_t x     = 0;

  while (x < r)
  {
    if (f >= 0)
    {
      r--;
      ddF_y += 2;
      f     += ddF_y;
    }
    x++;
    ddF_x += 2;
    f     += ddF_x;
    if (cornername & 0x8)
    {
      ST7735_DrawPixel(x0 - r, y0 + x, color);
      ST7735_DrawPixel(x0 - x, y0 + r, color);
    }
    if (cornername & 0x4)
    {
      ST7735_DrawPixel(x0 + x, y0 + r, color);
      ST7735_DrawPixel(x0 + r, y0 + x, color);
    }
    if (cornername & 0x2)
    {
      ST7735_DrawPixel(x0 + r, y0 - x, color);
      ST7735_DrawPixel(x0 + x, y0 - r, color);
    }
    if (cornername & 0x1)
    {
      ST7735_DrawPixel(x0 - x, y0 - r, color);
      ST7735_DrawPixel(x0 - r, y0 - x, color);
    }

  }
}

/***************************************************************************************
** Function name:           fillCircle
** Description:             draw a filled circle
***************************************************************************************/
void ST7735_FillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
{
  ST7735_DrawFastVLine(x0, y0 - r, r + r + 1, color);
  ST7735_FillCircleHelper(x0, y0, r, 3, 0, color);
}

/***************************************************************************************
** Function name:           fillCircleHelper
** Description:             Support function for filled circle drawing
***************************************************************************************/
// Used to do circles and roundrects
void ST7735_FillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color)
{
  int16_t f     = 1 - r;
  int16_t ddF_x = 1;
  int16_t ddF_y = -r - r;
  int16_t x     = 0;

  delta++;
  while (x < r)
  {
    if (f >= 0)
    {
      r--;
      ddF_y += 2;
      f     += ddF_y;
    }
    x++;
    ddF_x += 2;
    f     += ddF_x;

    if (cornername & 0x1)
    {
      ST7735_DrawFastVLine(x0 + x, y0 - r, r + r + delta, color);
      ST7735_DrawFastVLine(x0 + r, y0 - x, x + x + delta, color);
    }
    if (cornername & 0x2)
    {
      ST7735_DrawFastVLine(x0 - x, y0 - r, r + r + delta, color);
      ST7735_DrawFastVLine(x0 - r, y0 - x, x + x + delta, color);
    }
  }
}

/***************************************************************************************
** Function name:           drawEllipse
** Description:             Draw a ellipse outline
***************************************************************************************/
void ST7735_DrawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color)
{
  if (rx < 2) return;
  if (ry < 2) return;
  int16_t x, y;
  int32_t rx2 = rx * rx;
  int32_t ry2 = ry * ry;
  int32_t fx2 = 4 * rx2;
  int32_t fy2 = 4 * ry2;
  int32_t s;

  for (x = 0, y = ry, s = 2 * ry2 + rx2 * (1-2 * ry); ry2 * x <= rx2 * y; x++)
  {
    ST7735_DrawPixel(x0 + x, y0 + y, color);
    ST7735_DrawPixel(x0 - x, y0 + y, color);
    ST7735_DrawPixel(x0 - x, y0 - y, color);
    ST7735_DrawPixel(x0 + x, y0 - y, color);
    if (s >= 0)
    {
      s += fx2 * (1 - y);
      y--;
    }
    s += ry2 * ((4 * x) + 6);
  }

  for (x = rx, y = 0, s = 2 * rx2 + ry2 * (1 - 2 * rx); rx2 * y <= ry2 * x; y++)
  {
    ST7735_DrawPixel(x0 + x, y0 + y, color);
    ST7735_DrawPixel(x0 - x, y0 + y, color);
    ST7735_DrawPixel(x0 - x, y0 - y, color);
    ST7735_DrawPixel(x0 + x, y0 - y, color);
  if (s >= 0)
  {
    s += fy2 * (1 - x);
    x--;
  }
  s += rx2 * ((4 * y) + 6);
  }
}

/***************************************************************************************
** Function name:           fillEllipse
** Description:             draw a filled ellipse
***************************************************************************************/
void ST7735_FillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color)
{
  if (rx < 2) return;
  if (ry < 2) return;
  int16_t x, y;
  int32_t rx2 = rx * rx;
  int32_t ry2 = ry * ry;
  int32_t fx2 = 4 * rx2;
  int32_t fy2 = 4 * ry2;
  int32_t s;

  for (x = 0, y = ry, s = 2 * ry2 + rx2 * (1 - 2 * ry); ry2 * x <= rx2 * y; x++)
  {
    ST7735_DrawFastHLine(x0 - x, y0 - y, x + x + 1, color);
    ST7735_DrawFastHLine(x0 - x, y0 + y, x + x + 1, color);

    if (s >= 0)
    {
      s += fx2 * (1 - y);
      y--;
    }
    s += ry2 * ((4 * x) + 6);
  }

  for (x = rx, y = 0, s = 2 * rx2 + ry2 * (1 - 2 * rx); rx2 * y <= ry2 * x; y++)
  {
    ST7735_DrawFastHLine(x0 - x, y0 - y, x + x + 1, color);
    ST7735_DrawFastHLine(x0 - x, y0 + y, x + x + 1, color);

    if (s >= 0)
    {
      s += fy2 * (1 - x);
      x--;
    }
    s += rx2 * ((4 * y) + 6);
  }

}

/***************************************************************************************
** Function name:           drawRect
** Description:             Draw a rectangle outline
***************************************************************************************/
// Draw a rectangle
void ST7735_DrawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
  ST7735_DrawFastHLine(x, y, w, color);
  ST7735_DrawFastHLine(x, y + h - 1, w, color);
  ST7735_DrawFastVLine(x, y, h, color);
  ST7735_DrawFastVLine(x + w - 1, y, h, color);
}

/***************************************************************************************
** Function name:           drawRoundRect
** Description:             Draw a rounded corner rectangle outline
***************************************************************************************/
// Draw a rounded rectangle
void ST7735_DrawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
  // smarter version
  ST7735_DrawFastHLine(x + r  , y    , w - r - r, color); // Top
  ST7735_DrawFastHLine(x + r  , y + h - 1, w - r - r, color); // Bottom
  ST7735_DrawFastVLine(x    , y + r  , h - r - r, color); // Left
  ST7735_DrawFastVLine(x + w - 1, y + r  , h - r - r, color); // Right
  // draw four corners
  ST7735_DrawCircleHelper(x + r    , y + r    , r, 1, color);
  ST7735_DrawCircleHelper(x + r    , y + h - r - 1, r, 8, color);
  ST7735_DrawCircleHelper(x + w - r - 1, y + r    , r, 2, color);
  ST7735_DrawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
}

/***************************************************************************************
** Function name:           fillRoundRect
** Description:             Draw a rounded corner filled rectangle
***************************************************************************************/
// Fill a rounded rectangle
void ST7735_FillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
{
  // smarter version
  ST7735_FillRectangle(x + r, y, w - r - r, h, color);

  // draw four corners
  ST7735_FillCircleHelper(x + w - r - 1, y + r, r, 1, h - r - r - 1, color);
  ST7735_FillCircleHelper(x + r    , y + r, r, 2, h - r - r - 1, color);
}

/***************************************************************************************
** Function name:           drawTriangle
** Description:             Draw a triangle outline using 3 arbitrary points
***************************************************************************************/
// Draw a triangle
void ST7735_DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
  ST7735_DrawLine(x0, y0, x1, y1, color);
  ST7735_DrawLine(x1, y1, x2, y2, color);
  ST7735_DrawLine(x2, y2, x0, y0, color);
}

/***************************************************************************************
** Function name:           fillTriangle
** Description:             Draw a filled triangle using 3 arbitrary points
***************************************************************************************/
// Fill a triangle - original Adafruit function works well and code footprint is small
void ST7735_FillTriangle( int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
{
  int16_t a, b, y, last;

  // Sort coordinates by Y order (y2 >= y1 >= y0)
  if (y0 > y1)
  {
    SWAP_INT16_T(y0, y1); SWAP_INT16_T(x0, x1);
  }

  if (y1 > y2)
  {
    SWAP_INT16_T(y2, y1); SWAP_INT16_T(x2, x1);
  }

  if (y0 > y1)
  {
    SWAP_INT16_T(y0, y1); SWAP_INT16_T(x0, x1);
  }

  if (y0 == y2)
  { // Handle awkward all-on-same-line case as its own thing
    a = b = x0;
    if (x1 < a)      a = x1;
    else if (x1 > b) b = x1;
    if (x2 < a)      a = x2;
    else if (x2 > b) b = x2;
    ST7735_DrawFastHLine(a, y0, b - a + 1, color);
    return;
  }

  int16_t
  dx01 = x1 - x0,
  dy01 = y1 - y0,
  dx02 = x2 - x0,
  dy02 = y2 - y0,
  dx12 = x2 - x1,
  dy12 = y2 - y1,
  sa   = 0,
  sb   = 0;

  // For upper part of triangle, find scanline crossings for segments
  // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
  // is included here (and second loop will be skipped, avoiding a /0
  // error there), otherwise scanline y1 is skipped here and handled
  // in the second loop...which also avoids a /0 error here if y0=y1
  // (flat-topped triangle).
  if (y1 == y2) last = y1;  // Include y1 scanline
  else         last = y1 - 1; // Skip it

  for (y = y0; y <= last; y++)
  {
    a   = x0 + sa / dy01;
    b   = x0 + sb / dy02;
    sa += dx01;
    sb += dx02;

    if (a > b) SWAP_INT16_T(a, b);
    ST7735_DrawFastHLine(a, y, b - a + 1, color);
  }

  // For lower part of triangle, find scanline crossings for segments
  // 0-2 and 1-2.  This loop is skipped if y1=y2.
  sa = dx12 * (y - y1);
  sb = dx02 * (y - y0);
  for (; y <= y2; y++)
  {
    a   = x1 + sa / dy12;
    b   = x0 + sb / dy02;
    sa += dx12;
    sb += dx02;

    if (a > b) SWAP_INT16_T(a, b);
    ST7735_DrawFastHLine(a, y, b - a + 1, color);
  }
}

/***************************************************************************************
** Function name:           drawLine
** Description:             draw a line between 2 arbitrary points
***************************************************************************************/

// Slower but more compact line drawing function
void ST7735_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
{
  int16_t steep = abs(y1 - y0) > abs(x1 - x0);
  if (steep)
  {
    SWAP_INT16_T(x0, y0);
    SWAP_INT16_T(x1, y1);
  }

  if (x0 > x1)
  {
    SWAP_INT16_T(x0, x1);
    SWAP_INT16_T(y0, y1);
  }

  int16_t dx, dy;
  dx = x1 - x0;
  dy = abs(y1 - y0);

  int16_t err = dx / 2;
  int16_t ystep;

  if (y0 < y1)
  {
    ystep = 1;
  }
  else
  {
    ystep = -1;
  }

  for (; x0<=x1; x0++)
  {
    if (steep)
    {
      ST7735_DrawPixel(y0, x0, color);
    }
    else
    {
      ST7735_DrawPixel(x0, y0, color);
    }
    err -= dy;
    if (err < 0)
    {
      y0 += ystep;
      err += dx;
    }
  }
}

/***************************************************************************************
** Function name:           drawFastVLine
** Description:             draw a vertical line
***************************************************************************************/
void ST7735_DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
  // Rudimentary clipping
  if ((x >= _width) || (y >= _height)) return;
  if ((y + h - 1) >= _height) h = _height - y;

  ST7735_DrawLine(x, y, x, y + h - 1, color);
}

/***************************************************************************************
** Function name:           drawFastHLine
** Description:             draw a horizontal line
***************************************************************************************/
void ST7735_DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
  // Rudimentary clipping
  if ((x >= _width) || (y >= _height)) return;
  if ((x + w - 1) >= _width)  w = _width - x;

  ST7735_DrawLine(x, y, x + w - 1, y, color);
}

/***************************************************************************************
** Function name:           setRotation
** Description:             rotate the screen orientation m = 0-3
***************************************************************************************/
void ST7735_SetRotation(uint8_t m)
{
  _value_rotation = m % 4;

  TFT_CS_L();

  ST7735_WriteCommand(ST7735_MADCTL);

  switch (_value_rotation)
  {
    case 0:
    {
      uint8_t d_r = (_data_rotation[0] | _data_rotation[1] | _data_rotation[3]);
      ST7735_WriteData(&d_r, sizeof(d_r));
        _width  = ST7735_WIDTH;
        _height = ST7735_HEIGHT;
        _xstart = ST7735_XSTART;
    _ystart = ST7735_YSTART;
    }
     break;
    case 1:
    {
      uint8_t d_r = (_data_rotation[1] | _data_rotation[2] | _data_rotation[3]);
      ST7735_WriteData(&d_r, sizeof(d_r));
      _width  = ST7735_HEIGHT;
      _height = ST7735_WIDTH;
      _xstart = ST7735_YSTART;
      _ystart = ST7735_XSTART;
    }
      break;
    case 2:
    {
      uint8_t d_r = _data_rotation[3];
      ST7735_WriteData(&d_r, sizeof(d_r));
      _width  = ST7735_WIDTH;
      _height = ST7735_HEIGHT;
      _xstart = ST7735_XSTART;
      _ystart = ST7735_YSTART;
    }
      break;
    case 3:
    {
      uint8_t d_r = (_data_rotation[0] | _data_rotation[2] | _data_rotation[3]);
      ST7735_WriteData(&d_r, sizeof(d_r));
      _width  = ST7735_HEIGHT;
      _height = ST7735_WIDTH;
      _xstart = ST7735_YSTART;
      _ystart = ST7735_XSTART;
    }
      break;
  }
  TFT_CS_H();
}

uint8_t ST7735_GetRotation(void)
{
  return _value_rotation;
}

int16_t ST7735_GetHeight(void)
{
  return _height;
}

int16_t ST7735_GetWidth(void)
{
  return _width;
}
Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?
-
00:00
00:00
Update Required Flash plugin
-
00:00
00:00