/******************************************************************************
�� �� ����TFT_LCD.c
����������TFT��ɫҺ����ʾ�����ƺ������ļ�
��    �ߣ�����
��    ����V1.0
��    �ڣ�2017.4.8
******************************************************************************/

#include "TFT_LCD.h"

TFTLCDLayerStatusStruct   TFTLCDLayerStatus[YVC_LYR_NUM_CPU];
TFTLCDLayerBufferStruct   TFTLCDLayer[YVC_LYR_NUM_CPU];

TFTLCDUpdateCtrlStruct    TFTLCDUpdateCtrl;

/******************************************************************************
��������TFT_LCD_Display_Sprite
��  �ܣ���TFT��ɫҺ����ʾ������ͼ
��  ����LyrId   ��ͼ���� 0 - YVC_LYR_NUM_CPU(��YvcConfig.h������)
        SpriteID��ͼƬ���(����)
        PosX    ��ͼƬ��ʾ����ʾ���ϵ�x����
        PosY    ��ͼƬ��ʾ����ʾ���ϵ�y����
        Scale   : ͼƬ���ű���,����Ϊ0.015625(1 / 64),����Ϊ64ʱͼƬΪԭʼ����
����ֵ����
******************************************************************************/
void TFT_LCD_Display_Sprite(uint16_t LyrId, uint16_t SpriteID, uint16_t PosX, uint16_t PosY, uint8_t Scale)
{
  if (TFTLCDUpdateCtrl.Enable == 0)
    return;

  if (TFTLCDLayerStatus[LyrId].LyrEn)                 //�����ͼ���Ѿ�ʹ��
  {
    if ((TFTLCDLayerStatus[LyrId].SpriteID == SpriteID) && \
        (TFTLCDLayerStatus[LyrId].PosX == PosX) && \
        (TFTLCDLayerStatus[LyrId].PosY == PosY) && \
        (TFTLCDLayerStatus[LyrId].Scale == Scale))    //���ͼ������ʾ��ͼ���뵱ǰҪ���һ��
      return;                                           //��ֱ�ӷ���
  }

  TFT_LCD_Update_Layer_Buffer(LyrId, SpriteID, PosX, PosY, Scale);

  TFTLCDLayerStatus[LyrId].LyrEn = 1;
  TFTLCDLayerStatus[LyrId].SpriteID = SpriteID;
  TFTLCDLayerStatus[LyrId].PosX = PosX;
  TFTLCDLayerStatus[LyrId].PosY = PosY;
  TFTLCDLayerStatus[LyrId].Scale = Scale;
}

/******************************************************************************
��������TFT_LCD_Clear_Layer
��  �ܣ����ָ��ͼ���ϵ�ͼƬ��ʾ
��  ����LyrId��ͼ���� 0 - YVC_LYR_NUM_CPU(��YvcConfig.h������)
����ֵ����
******************************************************************************/
void TFT_LCD_Clear_Layer(uint16_t LyrId)
{
  uint8_t i;

  if (TFTLCDUpdateCtrl.Enable == 0)
    return;

  if (TFTLCDLayerStatus[LyrId].LyrEn)
  {
    //1.�����Buffer֮ǰ�Ƚ�ֹ���䵱ǰ��Buffer�е����ݵ�YGV642
    TFTLCDLayer[LyrId].UpdateCnt = 0;

    //2.�����Buffer����
    for (i = 0; i < 12; i++)
      TFTLCDLayer[LyrId].Buffer[i] = TFTLCDBlankLayer[i];

    //3.���ò�Buffer�е�������Ҫ���µ�YGV642�еĴ���
    TFTLCDLayer[LyrId].UpdateCnt = 2;                   //YGV642ǰ̨��̨��������ʾ������Ҫ����

    TFTLCDLayerStatus[LyrId].LyrEn = 0;
  }
}

/******************************************************************************
��������TFT_LCD_Clear_Multi_Layer
��  �ܣ����ָ���Ķ��ͼ���ϵ�ͼƬ��ʾ
��  ����LyrIdLo����ʼͼ���� 0 - YVC_LYR_NUM_CPU(��YvcConfig.h������)
        LyrIdHi������ͼ���� 0 - YVC_LYR_NUM_CPU(��YvcConfig.h������)
����ֵ����
******************************************************************************/
void TFT_LCD_Clear_Multi_Layer(uint16_t LyrIdLo, uint16_t LyrIdHi)
{
  uint16_t LyrId;

  for (LyrId = LyrIdLo; LyrId <= LyrIdHi; LyrId++)
    TFT_LCD_Clear_Layer(LyrId);
}

/******************************************************************************
��������TFT_LCD_Startup
��  �ܣ�����TFT��ɫҺ����ʾ��
��  ������
����ֵ����
******************************************************************************/
void TFT_LCD_Startup(void)
{
  uint8_t i;
  
  YMA_CTL = 1;    //----hyq--20180317
  YGV642_Wait_ms(200);
  
  //1.������Դǰȷ����λ�ź�Ϊ���ұ���ر�
  TFT_nRST = 0;
  LCD_BL   = 0;

  //2.��TFT����YGV642�ĵ�Դ
  //PWR_nVIOEN = 1;   //Power up VDD5 and then power up VDDIN.    �����ܽ�
  PWR_3V3EN  = 1;

  //3.��ʱ10ms
  wdt_reset();
  YGV642_Wait_ms(200);

  //4.�ͷŸ�λ�ź�
  TFT_nRST = 1;

  //5.��ʼ��YGV642
  LCD_Init();
  YGV642_Init();
  //LCD_Init();   
  /*--- Transparent Color output (͸��ɫ����) ---*/
  //͸��ɫ������ֵӦ��XFL converter�����ļ�ʱTransparent color����ɫֵ���Ӧ
  YGV642_Set_Transparent_Color(0xFF, 0x00, 0xFF);

  /*--- Border Color output (�߿�ɫ����)---*/
  YGV642_Set_Border_Color(0x00, 0x00, 0x00);

  /*--- Host layer enable ---*/
  YGV642_Enable_Host_Controlled_Layer();

  //6.��ʼ�����ݱ�־
  for (i = 0; i < YVC_LYR_NUM_CPU; i++)
  {
    TFTLCDLayerStatus[i].LyrEn = 0;
    TFTLCDLayer[i].UpdateCnt   = 0;
  }

  TFTLCDUpdateCtrl.TblUpdate   = 0;
  TFTLCDUpdateCtrl.LyrBaseAddr = YGV642_Get_Updateable_Table();
  TFTLCDUpdateCtrl.Timer       = 0;
  TFTLCDUpdateCtrl.State       = 0;
  TFTLCDUpdateCtrl.Brightness  = 0;
  TFTLCDUpdateCtrl.Enable      = 1;

  //7.��ʼ��Һ����
  //LCD_Init();
  TFT_STB =1;
  PWM_Channel_Init(5, PWM_CLOCK_SA, PWM_POL_POS, PWM_LEFT_ALIGN, PWM5_PM1);
  PWM_Channel_Set_Freq(5, 500);
  PWM_Channel_Set_Duty_Cycle(5, 0);   //��ʼ��Ϊ����ر�,�ɺ���Ӧ�ó�����
  PWM_Channel_Start(5); 
 }

void TFT_LCD_Shutdown(void)
{
  PWM_Channel_Stop(4);
  LCD_BL   = 0;
  TFT_STB = 0;
  TFTLCDUpdateCtrl.Enable = 0;
  //YMA_CTL = 0;
}

/******************************************************************************
��������TFT_LCD_Set_Brightness
��  �ܣ�TFT��ɫҺ���������ȿ���
��  ����Br�����ȵȼ� 0(�) - 100(����)
����ֵ����
******************************************************************************/
void TFT_LCD_Set_Brightness(uint8_t Br)
{
  if (TFTLCDUpdateCtrl.Enable == 0)
    return;

  if (Br > 100)
    Br = 100;

  if (Br != TFTLCDUpdateCtrl.Brightness)
  {
    TFTLCDUpdateCtrl.Brightness = Br;
    PWM_Channel_Set_Duty_Cycle(4, Br);
  }
}

/******************************************************************************
��������TFT_LCD_Display_Update_Service
��  �ܣ�TFT��ɫҺ����ʾ����ʾ���·���
��  ������
����ֵ����
*******************************************************************************
ע  �⣺�÷���������ÿ2ms������һ��
******************************************************************************/
void TFT_LCD_Display_Update_Service(void)
{
  if (TFTLCDUpdateCtrl.Enable == 0)
    return;

  if (TFTLCDUpdateCtrl.Timer < 0xFF)
    TFTLCDUpdateCtrl.Timer++;

  switch (TFTLCDUpdateCtrl.State)
  {
  case 0  :
    if (YGV642_Get_Table_Flip_Status() == YVC1_TBL_FLIP_COMPLETE)
      TFTLCDUpdateCtrl.State  = 1;
    break;

  case 1  :
    TFT_LCD_Start_Update_General_Table();
    TFTLCDUpdateCtrl.State  = 2;
    break;

  case 2  :
    if ((TFT_LCD_Get_General_Table_Update_Status() == 0) && \
        (TFTLCDUpdateCtrl.Timer >= 10))
    {
      TFTLCDUpdateCtrl.LyrBaseAddr = YGV642_Flip_Table();
      TFTLCDUpdateCtrl.Timer = 0;
      TFTLCDUpdateCtrl.State = 0;
    }
    break;

  default :
    TFTLCDUpdateCtrl.TblUpdate   = 0;
    TFTLCDUpdateCtrl.LyrBaseAddr = YGV642_Get_Updateable_Table();
    TFTLCDUpdateCtrl.Timer       = 0;
    TFTLCDUpdateCtrl.State       = 0;
    break;
  }
}

/******************************************************************************
��������TFT_LCD_Update_Layer_Buffer
��  �ܣ�����TFT��ɫҺ����ʾ����ʾ����
��  ����LyrId   ��ͼ���� 0 - YVC_LYR_NUM_CPU(��YvcConfig.h������)
        SpriteID��ͼƬ���(����)
        PosX    ��ͼƬ��ʾ����ʾ���ϵ�x����
        PosY    ��ͼƬ��ʾ����ʾ���ϵ�y����
        Scale   : ͼƬ���ű���,����Ϊ0.015625(1 / 64),����Ϊ64ʱͼƬΪԭʼ����
����ֵ����
******************************************************************************/
#pragma CONST_SEG __GPAGE_SEG DEFAULT
void TFT_LCD_Update_Layer_Buffer(uint16_t LyrId, uint16_t SpriteID, uint16_t PosX, uint16_t PosY, uint8_t Scale)
{
  uint8_t i;

  T_Y642_LYR_SPRTATTR  LyrSprtAttr;

  //1.ȡ����ӦͼƬ��12�ֽ�������
  for (i = 0; i < 12; i++)
    LyrSprtAttr.BYTE[i] = tVc1hPatternData[SpriteID].SpriteAttributeData[i];

  //2.�޸�ͼƬ��x,y����
  LyrSprtAttr.BIT.DOX_0 = (uint8_t)( PosX       & 0x00FF);
  LyrSprtAttr.BIT.DOX_8 = (uint8_t)((PosX >> 8) & 0x0007);
  LyrSprtAttr.BIT.DOY_0 = (uint8_t)( PosY       & 0x00FF);
  LyrSprtAttr.BIT.DOY_8 = (uint8_t)((PosY >> 8) & 0x0007);

  //3.����ͼƬ���ű���
  LyrSprtAttr.BIT.MAGX  = Scale;
  LyrSprtAttr.BIT.MAGY  = Scale;

  //LyrSprtAttr.BIT.ALPHA_1  = 1;
  //LyrSprtAttr.BIT.ALPHA_0  = 0;

  //4.���²�Buffer֮ǰ�Ƚ�ֹ���䵱ǰ��Buffer�е����ݵ�YGV642
  TFTLCDLayer[LyrId].UpdateCnt = 0;

  //5.���²�Buffer����
  for (i = 0; i < 12; i++)
    TFTLCDLayer[LyrId].Buffer[i] = LyrSprtAttr.BYTE[i];

  //6.���ò�Buffer�е�������Ҫ���µ�YGV642�еĴ���
  TFTLCDLayer[LyrId].UpdateCnt = 2;                   //YGV642ǰ̨��̨��������ʾ������Ҫ����
}
#pragma CONST_SEG DEFAULT

/******************************************************************************
��������TFT_LCD_Start_Update_General_Table
��  �ܣ���ʼ����ͼ�ο���оƬ�ڵ���ʾ���ݱ�
��  ������
����ֵ����
******************************************************************************/
void TFT_LCD_Start_Update_General_Table(void)
{
  TFTLCDUpdateCtrl.TblUpdate  = 1;
  TFTLCDUpdateCtrl.CurrentLyr = 0;
  TFTLCDUpdateCtrl.Step       = 0;
}

/******************************************************************************
��������TFT_LCD_Get_General_Table_Update_Status
��  �ܣ���ȡͼ�ο���оƬ�ڵ���ʾ���ݱ��ĸ���״̬
��  ������
����ֵ��0 - ��ǰû���ڸ���
        1 - ��ǰ���ڸ���
******************************************************************************/
uint8_t TFT_LCD_Get_General_Table_Update_Status(void)
{
  return TFTLCDUpdateCtrl.TblUpdate;
}

/******************************************************************************
��������TFT_LCD_General_Table_Write_Service
��  �ܣ�ͼ�ο���оƬ�ڵ���ʾ���ݱ����ݸ��·���
��  ������
����ֵ����
*******************************************************************************
ע  �⣺�÷���������ÿ��ϵͳ����ʱʵʱ����
******************************************************************************/
void TFT_LCD_General_Table_Write_Service(void)
{
  uint8_t   i;
  uint16_t  TblAddr;

  if (TFTLCDUpdateCtrl.Enable == 0)
    return;

  if (TFTLCDUpdateCtrl.TblUpdate)
  {
    switch (TFTLCDUpdateCtrl.Step)
    {
      //Step 0  ��׼������
    case 0  :
      if(TFTLCDUpdateCtrl.CurrentLyr < YVC_LYR_NUM_CPU)
      {
        if (TFTLCDLayer[TFTLCDUpdateCtrl.CurrentLyr].UpdateCnt)
        {
          TblAddr = TFTLCDUpdateCtrl.LyrBaseAddr + TFTLCDUpdateCtrl.CurrentLyr * Y642_LYR_SIZE;
          TFTLCDUpdateCtrl.AddrBuffer[0] = (uint8_t)(TblAddr >> 8);
          TFTLCDUpdateCtrl.AddrBuffer[1] = (uint8_t)TblAddr;

          for (i = 0; i < 12; i++)
            TFTLCDUpdateCtrl.Data[i] = TFTLCDLayer[TFTLCDUpdateCtrl.CurrentLyr].Buffer[i];

          TFTLCDLayer[TFTLCDUpdateCtrl.CurrentLyr].UpdateCnt--;
          TFTLCDUpdateCtrl.Step = 1;
        }
      }
      else
        TFTLCDUpdateCtrl.TblUpdate = 0;
      TFTLCDUpdateCtrl.CurrentLyr++;
      break;

      //Step  1������nCS
    case 1  :
      YGV642_SPI_nCS_Low();
      TFTLCDUpdateCtrl.Step = 2;
      break;

      //Step  2��ѡ��Ĵ�����ַ�˿�
    case 2  :
      YGV642_SPI_Byte_Write(YVC1_PORT_REG_SEL);
      TFTLCDUpdateCtrl.Step = 3;
      break;

      //Step  3��28H�Ĵ���(General Table��ַ)+��ַ����
    case 3  :
      YGV642_SPI_Byte_Write(REG_R28H | YVC1REG_AIRG);
      TFTLCDUpdateCtrl.Step = 4;
      break;

      //Step  4������nCS
    case 4  :
      YGV642_SPI_nCS_High();
      TFTLCDUpdateCtrl.Step = 5;
      break;

      //Step  5������nCS
    case 5  :
      YGV642_SPI_nCS_Low();
      TFTLCDUpdateCtrl.BytePtr = 0;
      TFTLCDUpdateCtrl.Step = 6;
      break;

      //Step  6��ѡ��Ĵ������ݶ˿�
    case 6  :
      YGV642_SPI_Byte_Write(YVC1_PORT_REG_DATA);
      TFTLCDUpdateCtrl.Step = 7;
      break;

      //Step  7��дGeneral Table��ַ
    case 7  :
      YGV642_SPI_Byte_Write(TFTLCDUpdateCtrl.AddrBuffer[TFTLCDUpdateCtrl.BytePtr]);
      TFTLCDUpdateCtrl.BytePtr++;
      if (TFTLCDUpdateCtrl.BytePtr >= 2)
        TFTLCDUpdateCtrl.Step = 8;
      break;


      //Step  8������nCS
    case 8  :
      YGV642_SPI_nCS_High();
      TFTLCDUpdateCtrl.Step = 9;
      break;

      //Step  9������nCS
    case 9  :
      YGV642_SPI_nCS_Low();
      TFTLCDUpdateCtrl.BytePtr = 0;
      TFTLCDUpdateCtrl.Step = 10;
      break;

      //Step 10��ѡ��General Table���ݶ˿�
    case 10 :
      YGV642_SPI_Byte_Write(Y642_PORT_GENTBL_DATA);
      TFTLCDUpdateCtrl.Step = 11;
      break;

      //Step 11��дGeneral Table����
    case 11 :
      YGV642_SPI_Byte_Write(TFTLCDUpdateCtrl.Data[TFTLCDUpdateCtrl.BytePtr]);
      TFTLCDUpdateCtrl.BytePtr++;
      if (TFTLCDUpdateCtrl.BytePtr >= 12)
        TFTLCDUpdateCtrl.Step = 12;
      break;

      //Step 12������nCS
    case 12 :
      YGV642_SPI_nCS_High();
      TFTLCDUpdateCtrl.Step = 0;
      break;

    default :
      TFTLCDUpdateCtrl.TblUpdate = 0;
      break;
    }
  }
}