/*************************************************** 
  This is a library for the Adafruit 1.8" SPI display.
  This library works with the Adafruit 1.8" TFT Breakout w/SD card
  ----> http://www.adafruit.com/products/358
  as well as Adafruit raw 1.8" TFT display
  ----> http://www.adafruit.com/products/618
 
  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include "ST7796_t3.h"
#include <limits.h>
#include "pins_arduino.h"
#include "wiring_private.h"
#include <SPI.h>

 
#define ST77XX_MADCTL_MY  0x80
#define ST77XX_MADCTL_MX  0x40
#define ST77XX_MADCTL_MV  0x20
#define ST77XX_MADCTL_ML  0x10
#define ST77XX_MADCTL_RGB 0x00
#define ST77XX_MADCTL_BGR 0x08
#define ST7796S_NOP            0x00
#define ST7796S_SWRESET        0x01

#define ST7796S_RDDID          0x04
#define ST7796S_RDDST          0x09
#define ST7796S_RDMODE         0x0A
#define ST7796S_RDMADCTL       0x0B
#define ST7796S_RDPIXFMT       0x0C
#define ST7796S_RDIMGFMT       0x0D
#define ST7796S_RDSELFDIAG     0x0F

#define ST7796S_SLPIN          0x10
#define ST7796S_SLPOUT         0x11
#define ST7796S_PTLON          0x12
#define ST7796S_NORON          0x13

#define ST7796S_INVOFF         0x20
#define ST7796S_INVON          0x21
//#define ST7796S_GAMMASET       0x26
#define ST7796S_DISPOFF        0x28
#define ST7796S_DISPON         0x29

#define ST7796S_CASET          0x2A
#define ST7796S_PASET          0x2B
#define ST7796S_RAMWR          0x2C
#define ST7796S_RAMRD          0x2E

#define ST7796S_PTLAR          0x30
#define ST7796S_VSCRDEF        0x33
#define ST7796S_MADCTL         0x36
#define ST7796S_VSCRSADD       0x37     /* Vertical Scrolling Start Address */
#define ST7796S_PIXFMT         0x3A     /* COLMOD: Pixel Format Set */

#define ST7796S_RGB_INTERFACE  0xB0     /* RGB Interface Signal Control */
#define ST7796S_FRMCTR1        0xB1
#define ST7796S_FRMCTR2        0xB2
#define ST7796S_FRMCTR3        0xB3
#define ST7796S_INVCTR         0xB4
#define ST7796S_DFUNCTR        0xB6     /* Display Function Control */

#define ST7796S_PWCTR1         0xC0
#define ST7796S_PWCTR2         0xC1
#define ST7796S_PWCTR3         0xC2
#define ST7796S_PWCTR4         0xC3
#define ST7796S_PWCTR5         0xC4
#define ST7796S_VMCTR1         0xC5

#define ST7796S_RDID1          0xDA
#define ST7796S_RDID2          0xDB
#define ST7796S_RDID3          0xDC
#define ST7796S_RDID4          0xDD

#define ST7796S_GMCTRP1        0xE0
#define ST7796S_GMCTRN1        0xE1
#define ST7796S_DGCTR1         0xE2
#define ST7796S_DGCTR2         0xE3

#define ST7796S_CSCON           0xFF

//-----------------------------------------------------------------------------
#define ST7796S_MAD_RGB        0x08
#define ST7796S_MAD_BGR        0x00

#define ST7796S_MAD_VERTICAL   0x20
#define ST7796S_MAD_X_LEFT     0x00
#define ST7796S_MAD_X_RIGHT    0x40
#define ST7796S_MAD_Y_UP       0x80
#define ST7796S_MAD_Y_DOWN     0x00



ST7796_t3::ST7796_t3(uint8_t CS, uint8_t RS, uint8_t SID, uint8_t SCLK, uint8_t RST) : ST7735_t3(CS, RS, SID, SCLK, RST)
  { // Assume the majority of ones.
    tabcolor = INIT_ST7789_TABCOLOR;  // not used so set same as 89
    _screenHeight = 480;
    _screenWidth = 320;

          cursor_y  = cursor_x    = 0;
          textsize_x  = 1;
    textsize_y  = 1;
          textcolor = textbgcolor = 0xFFFF;
          wrap      = true;
          font      = NULL;
          setClipRect();
          setOrigin();
  } // ST7796_t3::ST7796_t3

ST7796_t3::ST7796_t3(uint8_t CS, uint8_t RS, uint8_t RST) : ST7735_t3(CS, RS, RST)
  { tabcolor = INIT_ST7789_TABCOLOR;
    _screenHeight = 480;
    _screenWidth = 320;

    cursor_y = cursor_x = 0;
    textsize_x = 1;
    textsize_y = 1;
    textcolor = textbgcolor = 0xFFFF;
    wrap      = true;
    font      = NULL;
    setClipRect();
    setOrigin();
  } // ST7796_t3::ST7796_t3


void ST7796_t3::setRotation(uint8_t m)
  { beginSPITransaction();
      writecommand(ST7735_MADCTL);
      rotation = m % 4; // can't be higher than 3
      switch (rotation)
        { case 0: writedata_last(ST77XX_MADCTL_MX | ST77XX_MADCTL_BGR);
                  _xstart = _colstart;
                  _ystart = _rowstart;
                  _width = _screenWidth;
                  _height = _screenHeight;
                  break;

          case 1: writedata_last(ST77XX_MADCTL_MV | ST77XX_MADCTL_BGR);
                  _xstart = _rowstart;
                  _ystart = _colstart2;
                  _height = _screenWidth;
                  _width = _screenHeight;
                  break;

         case 2:  writedata_last(ST77XX_MADCTL_MY | ST77XX_MADCTL_BGR);
                  _xstart = _colstart2;
                  _ystart = _rowstart2;
                  _width = _screenWidth;
                  _height = _screenHeight;
                  break;

          case 3: writedata_last(ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_BGR);
                  _xstart = _rowstart2;
                  _ystart = _colstart;
                  _height = _screenWidth;
                  _width = _screenHeight;
                  break;
        } // switch

      _rot = m;
    endSPITransaction();
    //  Serial.printf("Set rotation %d start(%d %d) row: %d, col: %d\n", m, _xstart, _ystart, _rowstart, _colstart);
    setClipRect();
    setOrigin();
    cursor_x = 0;
    cursor_y = 0;
  } // ST7796_t3::setRotation

#define ST796SS_DFC 96
// Probably should use generic names like Adafruit..
#define DELAY 0x80
static const uint8_t PROGMEM
  cmd_ST7796[] =                            // Initialization commands for ST7796 screens
    {
      17,                                   // 9 commands in list:

      ST7735_SWRESET, DELAY,                // 1: Software reset, no args, w/delay
        150,                                //    150 ms delay

      ST7796S_SLPOUT, DELAY,                // sleep exit
        120,

      0xF0, 1, 0xC3,                       // Command Set control Enable extension command 2 partI
      0xF0, 1, 0x96,                       // Command Set control Enable extension command 2 partII
      ST7796S_MADCTL, 1, 0x48,             // Memory Data Access Control MX, MY, RGB mode
                                           // X-Mirror, Top-Left to right-Buttom, RGB

      ST7796S_PIXFMT, 1, 0x55,             // Interface Pixel Format 16 bits

      ST7796S_INVCTR, 1, 0x01,             // 1 dont inversion.
      ST7796S_DFUNCTR,3, 0x80, 0x02, 0x3B, //

      0xE8, 8,                             // Display Output Ctrl Adjust
        0x40, 0x8A, 0x00, 0x00,
        0x29,                              // Source eqaulizing period time= 22.5 us
        0x19,                              // Timing for "Gate start"=25 (Tclk)
        0xA5,                              // Timing for "Gate End"=37 (Tclk), Gate driver EQ function ON
        0x33,

      ST7796S_PWCTR2, 1,                   // Power control2
        0x06,                              // VAP(GVDD)=3.85+( vcom+vcom offset), VAN(GVCL)=-3.85+( vcom+vcom offset)
      ST7796S_PWCTR3, 1,                   // power control 3
        0xA7,                              // Source driving current level=low, Gamma driving current level=High

      ST7796S_VMCTR1, DELAY | 1,           // VCOM Control
        0x18,                              // VCOM=0.9
        120,                               // delay

      ST7796S_GMCTRP1,  14,                // Gamma "+"
        0xF0, 0x09, 0x0b, 0x06,            // ..
        0x04, 0x15, 0x2F, 0x54,            // ..
        0x42, 0x3C, 0x17, 0x14,            // ..
        0x18, 0x1B,                        // ..

      ST7796S_GMCTRN1, DELAY | 14,         // Gamma "-"
        0xE0, 0x09, 0x0B, 0x06,            // ..
        0x04, 0x03, 0x2B, 0x43,            // ..
        0x42, 0x3B, 0x16, 0x14,            // ..
        0x17, 0x1B,                        // ..
        120,                               // .. delay

      0xF0, 1, 0x3C,                       // disable command set part 1

      0xF0, DELAY | 1, 0x69,               // disable command set part 2
        120,                               // delay

      ST7796S_DISPON, DELAY,
        120
    }; // cmd_ST7796[]

void  ST7796_t3::init(uint16_t width, uint16_t height, uint8_t mode)
  { Serial.printf("ST7796_t3::init mode: %x\n", mode);
    commonInit(NULL, mode);
    if ((width == 320) && (height == 480))
      { _colstart = 0;
        _colstart2 = 0;
        _rowstart = 0;
        _rowstart2 = 0;
      }
    else
      { // let's compute it.
        // added support for other sizes
        _rowstart = _rowstart2 = (int)((480 - height) / 2);
        _colstart = _colstart2 = (int)((320 - width) / 2);
      }

    _height = height;
    _width = width;
    _screenHeight = height;
    _screenWidth = width;

    commandList(cmd_ST7796);
    setRotation(0);
    cursor_y  = cursor_x    = 0;
    textsize_x = textsize_y = 1;
    textcolor = textbgcolor = 0xFFFF;
    wrap      = true;
    font      = NULL;
    setClipRect();
    setOrigin();
  } // ST7796_t3::init

