#include "hdl_lcd.h"

static volatile uint8_t enTxCompleteFlag = 0;
lcd_dma_callback_t lcd_dma_cbs = NULL;
lcd_timer_callback_t lcd_timer_cbs = NULL;

static void hdl_lcd_dma_tcpl_callback(void)
{
    enTxCompleteFlag = SET;
	
	if(lcd_dma_cbs)
	{
		lcd_dma_cbs();
	}
	
    DMA_ClearTransCompleteStatus(LCD_DMA_UNIT, LCD_DMA_TX_INT_CH);
}

static void hdl_lcd_timer_callback(void)
{
	if(lcd_timer_cbs)
	{
		lcd_timer_cbs();
	}
	
	TMR0_ClearStatus(LCD_TIM_UINT, LCD_TIM_CH_FLAG);
}

void hdl_lcd_timer_config(void)
{
	stc_tmr0_init_t stcTmr0Init;
    stc_irq_signin_config_t stcIrqSignConfig;
	
	LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM);

	/* Enable timer0 and AOS clock */
    FCG_Fcg2PeriphClockCmd(LCD_TIM_CLK, ENABLE);
    FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);

    /* TIMER0 configuration */
    (void)TMR0_StructInit(&stcTmr0Init);
    stcTmr0Init.u32ClockSrc     = TMR0_CLK_SRC_INTERN_CLK;	//内部时钟
    stcTmr0Init.u32ClockDiv     = TMR0_CLK_DIV64;			//2分频
    stcTmr0Init.u32Func         = TMR0_FUNC_CMP;			//输出比较
    stcTmr0Init.u16CompareValue = (uint16_t)LCD_TIME_CMP_VALUE;
    (void)TMR0_Init(LCD_TIM_UINT, LCD_TIM_CH, &stcTmr0Init);
    hdl_delay_ms(1U);
    TMR0_HWStopCondCmd(LCD_TIM_UINT, LCD_TIM_CH, ENABLE);
    hdl_delay_ms(1U);
    TMR0_IntCmd(LCD_TIM_UINT, LCD_TIM_CH_INT, ENABLE);

    /* Interrupt configuration */
    stcIrqSignConfig.enIntSrc    = LCD_TIM_INT_SRC;
    stcIrqSignConfig.enIRQn      = LCD_TIM_IRQn;
    stcIrqSignConfig.pfnCallback = &hdl_lcd_timer_callback;
    (void)INTC_IrqSignIn(&stcIrqSignConfig);
    NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
    NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);
	
	TMR0_Start(LCD_TIM_UINT, LCD_TIM_CH);
	
	LL_PERIPH_WP(LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_SRAM);
}

void hdl_lcd_config(void)
{
	stc_spi_init_t stcSpiInit;
    stc_dma_init_t stcDmaInit;
    stc_irq_signin_config_t stcIrqSignConfig;
    stc_gpio_init_t stcGpioInit;
	
	LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM);
	
	/* 引脚设置 */
	GPIO_SetDebugPort(GPIO_PIN_TRST,DISABLE);
	
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinDrv       = PIN_HIGH_DRV;
    (void)GPIO_Init(LCD_SCL_PORT, LCD_SCL_PIN, &stcGpioInit);
    (void)GPIO_Init(LCD_SDA_PORT, LCD_SDA_PIN, &stcGpioInit);

    GPIO_SetFunc(LCD_SCL_PORT, LCD_SCL_PIN, LCD_SCL_FUNC);
    GPIO_SetFunc(LCD_SDA_PORT, LCD_SDA_PIN, LCD_SDA_FUNC);
	
	stcGpioInit.u16PinDir       = PIN_DIR_OUT;
	(void)GPIO_Init(LCD_RES_PORT, LCD_RES_PIN, &stcGpioInit);
    (void)GPIO_Init(LCD_DC_PORT, LCD_DC_PIN, &stcGpioInit);

    /* SPI配置 */
    FCG_Fcg1PeriphClockCmd(LCD_SPI_CLK, ENABLE);
    SPI_StructInit(&stcSpiInit);
    stcSpiInit.u32WireMode          = SPI_3_WIRE;
    stcSpiInit.u32TransMode         = SPI_SEND_ONLY;	
    stcSpiInit.u32MasterSlave       = SPI_MASTER;
    stcSpiInit.u32Parity            = SPI_PARITY_INVD;
    stcSpiInit.u32SpiMode           = SPI_MD_3;
    stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV2;
    stcSpiInit.u32DataBits          = SPI_DATA_SIZE_8BIT;
    stcSpiInit.u32FirstBit          = SPI_FIRST_MSB;
    stcSpiInit.u32FrameLevel        = SPI_1_FRAME;
    (void)SPI_Init(LCD_SPI_UINT, &stcSpiInit);

    /* DMA配置 */
    FCG_Fcg0PeriphClockCmd(LCD_DMA_CLK, ENABLE);
    (void)DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32BlockSize  = 1UL;
    stcDmaInit.u32TransCount = 1;
    stcDmaInit.u32DataWidth  = DMA_DATAWIDTH_8BIT;	//数据位宽
    stcDmaInit.u32SrcAddrInc  = DMA_SRC_ADDR_INC;	//源地址自增
    stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;	//目标地址固定
    stcDmaInit.u32SrcAddr     = (uint32_t)(0);
    stcDmaInit.u32DestAddr    = (uint32_t)(&LCD_SPI_UINT->DR);
	stcDmaInit.u32IntEn       = DMA_INT_ENABLE;
    if (LL_OK != DMA_Init(LCD_DMA_UNIT, LCD_DMA_TX_CH, &stcDmaInit)) {
        for (;;) {
        }
    }
    AOS_SetTriggerEventSrc(LCD_DMA_TX_TRIG_CH, LCD_SPI_TX_EVT_SRC);	//DMA发送触发源
	
	/* DMA 中断配置 */
	DMA_TransCompleteIntCmd(LCD_DMA_UNIT, DMA_INT_BTC_CH0, DISABLE);
	
	stcIrqSignConfig.enIntSrc    = LCD_DMA_TX_INT_SRC;
    stcIrqSignConfig.enIRQn      = LCD_DMA_TX_IRQ_NUM;
    stcIrqSignConfig.pfnCallback = &hdl_lcd_dma_tcpl_callback;
    (void)INTC_IrqSignIn(&stcIrqSignConfig);
    NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
    NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_14);
    NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);
	
	LL_PERIPH_WP(LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_SRAM);
	
	DMA_Cmd(LCD_DMA_UNIT, ENABLE);
    DMA_ChCmd(LCD_DMA_UNIT, LCD_DMA_TX_CH, ENABLE);
}

static void hdl_lcd_write_byte(uint8_t dat)
{
	SPI_Cmd(LCD_SPI_UINT, ENABLE);
	while (RESET == SPI_GetStatus(LCD_SPI_UINT, SPI_FLAG_TX_BUF_EMPTY)){}
	SPI_WriteData(LCD_SPI_UINT, (uint32_t)dat);
	while (RESET == SPI_GetStatus(LCD_SPI_UINT, SPI_FLAG_IDLE)){}
	SPI_Cmd(LCD_SPI_UINT, DISABLE);
}

void hdl_lcd_send(uint8_t *data, uint16_t len)
{
	LCD_DC_SET();//写数据
	enTxCompleteFlag = RESET;
	
	DMA_SetSrcAddr(LCD_DMA_UNIT, LCD_DMA_TX_CH, (uint32_t)(data)); // 重新设置源地址和发送的数据
    DMA_SetTransCount(LCD_DMA_UNIT, LCD_DMA_TX_CH, len); //设置传输次数,传输一次，计数器减到0停止

    DMA_ChCmd(LCD_DMA_UNIT, LCD_DMA_TX_CH, ENABLE); //使能DMA1通道
	SPI_Cmd(LCD_SPI_UINT, ENABLE);	//使能SPI
	
	while (RESET == enTxCompleteFlag) {
    }
	
	SPI_Cmd(LCD_SPI_UINT, DISABLE); //失能SPI
}

void hdl_lcd_dma_callback_register(lcd_dma_callback_t pCBS)
{
	if(lcd_dma_cbs == 0)
	{
		lcd_dma_cbs = pCBS;
	}
}

void hdl_lcd_timer_callback_register(lcd_timer_callback_t pCBS)
{
	if(lcd_timer_cbs == 0)
	{
		lcd_timer_cbs = pCBS;
	}
}

/******************************************************************************
      函数说明：LCD写入数据
      入口数据：dat 写入的数据
      返回值：  无
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
	LCD_DC_SET();//写数据
	
	hdl_lcd_write_byte(dat);
}


/******************************************************************************
      函数说明：LCD写入数据
      入口数据：dat 写入的数据
      返回值：  无
******************************************************************************/
void LCD_WR_DATA(uint16_t dat)
{
	LCD_DC_SET();//写数据
	
	hdl_lcd_write_byte(dat>>8);
	hdl_lcd_write_byte(dat);
}

/******************************************************************************
      函数说明：LCD写入命令
      入口数据：dat 写入的命令
      返回值：  无
******************************************************************************/
void LCD_WR_REG(uint8_t dat)
{
	LCD_DC_CLR();//写命令
	
	hdl_lcd_write_byte(dat);
}

/******************************************************************************
      函数说明：设置起始和结束地址
      入口数据：x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值：  无
******************************************************************************/
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
	LCD_WR_REG(0x2a);//列地址设置
	LCD_WR_DATA(x1);
	LCD_WR_DATA(x2);
	LCD_WR_REG(0x2b);//行地址设置
	LCD_WR_DATA(y1);
	LCD_WR_DATA(y2);
	LCD_WR_REG(0x2c);//储存器写
}

void hdl_lcd_fill(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint8_t *color)
{
	LCD_Address_Set(x1,y1,x2,y2);//设置显示范围
	
	hdl_lcd_send(color, (x2-x1+1)*(y2-y1+1)*2);
}

void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color)
{
	LCD_Address_Set(x,y,x,y);//设置光标位置 
	LCD_WR_DATA(color);
} 

void hdl_lcd_init(void)
{
	hdl_lcd_config();
	hdl_lcd_timer_config();
	
	LCD_RES_CLR();//复位
	hdl_delay_ms(100);
	LCD_RES_SET();
	hdl_delay_ms(100);
	
	LCD_WR_REG(0xEF);
	LCD_WR_REG(0xEB);
	LCD_WR_DATA8(0x14); 
	
	LCD_WR_REG(0xFE);			 
	LCD_WR_REG(0xEF); 

	LCD_WR_REG(0xEB);	
	LCD_WR_DATA8(0x14); 

	LCD_WR_REG(0x84);			
	LCD_WR_DATA8(0x40); 

	LCD_WR_REG(0x85);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x86);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x87);			
	LCD_WR_DATA8(0xFF);

	LCD_WR_REG(0x88);			
	LCD_WR_DATA8(0x0A);

	LCD_WR_REG(0x89);			
	LCD_WR_DATA8(0x21); 

	LCD_WR_REG(0x8A);			
	LCD_WR_DATA8(0x00); 

	LCD_WR_REG(0x8B);			
	LCD_WR_DATA8(0x80); 

	LCD_WR_REG(0x8C);			
	LCD_WR_DATA8(0x01); 

	LCD_WR_REG(0x8D);			
	LCD_WR_DATA8(0x01); 

	LCD_WR_REG(0x8E);			
	LCD_WR_DATA8(0xFF); 

	LCD_WR_REG(0x8F);			
	LCD_WR_DATA8(0xFF); 


	LCD_WR_REG(0xB6);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x20);

	LCD_WR_REG(0x36);
	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
	else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8);
	else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x68);
	else LCD_WR_DATA8(0xA8);

	LCD_WR_REG(0x3A);			
	LCD_WR_DATA8(0x05); 


	LCD_WR_REG(0x90);			
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08); 

	LCD_WR_REG(0xBD);			
	LCD_WR_DATA8(0x06);
	
	LCD_WR_REG(0xBC);			
	LCD_WR_DATA8(0x00);	

	LCD_WR_REG(0xFF);			
	LCD_WR_DATA8(0x60);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0x04);

	LCD_WR_REG(0xC3);			
	LCD_WR_DATA8(0x13);
	LCD_WR_REG(0xC4);			
	LCD_WR_DATA8(0x13);
	LCD_WR_REG(0xC9);			
	LCD_WR_DATA8(0x22);

	LCD_WR_REG(0xBE);			
	LCD_WR_DATA8(0x11); 

	LCD_WR_REG(0xE1);			
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x0E);

	LCD_WR_REG(0xDF);			
	LCD_WR_DATA8(0x21);
	LCD_WR_DATA8(0x0c);
	LCD_WR_DATA8(0x02);

	LCD_WR_REG(0xF0);   
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x26);
 	LCD_WR_DATA8(0x2A);

 	LCD_WR_REG(0xF1);    
 	LCD_WR_DATA8(0x43);
 	LCD_WR_DATA8(0x70);
 	LCD_WR_DATA8(0x72);
 	LCD_WR_DATA8(0x36);
 	LCD_WR_DATA8(0x37);  
 	LCD_WR_DATA8(0x6F);


 	LCD_WR_REG(0xF2);   
 	LCD_WR_DATA8(0x45);
 	LCD_WR_DATA8(0x09);
 	LCD_WR_DATA8(0x08);
 	LCD_WR_DATA8(0x08);
 	LCD_WR_DATA8(0x26);
 	LCD_WR_DATA8(0x2A);

 	LCD_WR_REG(0xF3);   
 	LCD_WR_DATA8(0x43);
 	LCD_WR_DATA8(0x70);
 	LCD_WR_DATA8(0x72);
 	LCD_WR_DATA8(0x36);
 	LCD_WR_DATA8(0x37); 
 	LCD_WR_DATA8(0x6F);

	LCD_WR_REG(0xED);	
	LCD_WR_DATA8(0x1B); 
	LCD_WR_DATA8(0x0B); 

	LCD_WR_REG(0xAE);			
	LCD_WR_DATA8(0x77);
	
	LCD_WR_REG(0xCD);			
	LCD_WR_DATA8(0x63);		


	LCD_WR_REG(0x70);			
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x04);
	LCD_WR_DATA8(0x0E); 
	LCD_WR_DATA8(0x0F); 
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x07);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x03);

	LCD_WR_REG(0xE8);			
	LCD_WR_DATA8(0x34);

	LCD_WR_REG(0x62);			
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x0D);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xED);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x0F);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xEF);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);

	LCD_WR_REG(0x63);			
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x11);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);
	LCD_WR_DATA8(0x18);
	LCD_WR_DATA8(0x13);
	LCD_WR_DATA8(0x71);
	LCD_WR_DATA8(0xF3);
	LCD_WR_DATA8(0x70); 
	LCD_WR_DATA8(0x70);

	LCD_WR_REG(0x64);			
	LCD_WR_DATA8(0x28);
	LCD_WR_DATA8(0x29);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0xF1);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x07);

	LCD_WR_REG(0x66);			
	LCD_WR_DATA8(0x3C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0xCD);
	LCD_WR_DATA8(0x67);
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x45);
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);

	LCD_WR_REG(0x67);			
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x3C);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x01);
	LCD_WR_DATA8(0x54);
	LCD_WR_DATA8(0x10);
	LCD_WR_DATA8(0x32);
	LCD_WR_DATA8(0x98);

	LCD_WR_REG(0x74);			
	LCD_WR_DATA8(0x10);	
	LCD_WR_DATA8(0x85);	
	LCD_WR_DATA8(0x80);
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x4E);
	LCD_WR_DATA8(0x00);					
	
	LCD_WR_REG(0x98);			
	LCD_WR_DATA8(0x3e);
	LCD_WR_DATA8(0x07);

	LCD_WR_REG(0x35);	
	LCD_WR_REG(0x21);

	LCD_WR_REG(0x11);
	hdl_delay_ms(120);
	LCD_WR_REG(0x29);
	hdl_delay_ms(20);
}
