/******************************************************************************
文 件 名：TFT_LCD.c
功能描述：TFT彩色液晶显示屏控制函数库文件
作    者：张暄
版    本：V1.0
日    期：2017.4.8
******************************************************************************/

#include "TFT_LCD.h"
uint8_t TFTLCDFlashChecked = 0;
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;
  uint16_t Checksum;
  //1.开启电源前确保复位信号为低且背光关闭
  LCD_BL_EN = 1 ; //61194 使能 
  TFT_nRST = 0;
  LCD_BL   = 0;   //61194 使能PWM 
  
  //2.开TFT屏和YGV642的电源
  //PWR_nVIOEN = 0;   //Power up VDD5 and then power up VDDIN.   8550 低使能
  PWR_nVIOEN = 1;     //----hyq--20180801 9013 高使能
  PWR_3V3EN  = 1;
  //AUDIOEN = 1;       //语音芯片
  //3.延时10ms
  wdt_reset();
  YGV642_Wait_ms(200);
  
  //4.释放复位信号
  TFT_nRST = 1;
  
  //5.初始化YGV642
  YGV642_Init();
  
  /***********************/   
  STB_LCD_MCU = 1;
  
  YGV642_Wait_ms(50);
  
  LCD_1530EN = 1;
  /***********************/
    
  /*--- 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.Enable      = 1;

    if (TFTLCDFlashChecked == 0)      //20200717
  {
    wdt_reset();
    Checksum = YGV642_Calc_Pattern_Memory_CheckSum(ROMDATA_STARTADDR, ROMDATA_ENDADDR);
    if (Checksum != ROMDATA_CHECKSUM)
    {
      YGV642_Set_Border_Color(0xFF, 0x00, 0x00);
      //TFTLCDUpdateCtrl.Mode    = TFT_LCD_MODE_FAULT;
      TFTLCDUpdateCtrl.Enable = 0;
    }
  }
  //7.初始化液晶屏
   //LCD_Init();   
   //AUDIOEN = 0;
  
  // PWM_Channel_Init(7, PWM_CLOCK_SB, PWM_POL_POS, PWM_LEFT_ALIGN, PWM7_PM3);
 //  PWM_Channel_Set_Freq(7, 100);
 //  PWM_Channel_Set_Duty_Cycle(7, 0);  //初始化为背光关闭,由后续应用程序开启   
 //  PWM_Channel_Start(7); 
  // DiagnosticReceived=0;
}
 void TFT_LCD_Shutdown(void)    //临时修改
{
  PWM_Channel_Stop(7);
  LCD_BL   = 0;
  TFTLCDUpdateCtrl.Enable = 0;

  /***********************/  
  STB_LCD_MCU = 0;
  
  YGV642_Wait_ms(100);
  
  PWR_3V3EN = 0;
  TFT_nRST = 0;  
  
  YGV642_Wait_ms(50);
  
  LCD_1530EN = 0;
}
 /******************************************************************************
函数名：TFT_LCD_Set_Brightness
功  能：TFT彩色液晶背光亮度控制
参  数：Br：亮度等级 0(最暗) - 100(最亮)
返回值：无
******************************************************************************/
/*void Backlight_TFT_Init(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; 
                TFTLCDFlashChecked     = 1;                    
              }
              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_Start_Update_General_Table
功  能：获取图形控制芯片内的显示数据表的更新状态
参  数：无
返回值：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;
    }
  }
}
