#ifndef LCDCONTROLLERSSD196X_HPP
#define LCDCONTROLLERSSD196X_HPP

#include "STM32F4FMC.hpp"
#include <platform/hal/ST/mcu/stm32f4x9/STM32F4HAL.hpp>

#ifdef __cplusplus
extern "C"{
#endif
	/**
		* C functions
		*/
	#include "stm32f4xx.h"
	
#ifdef __cplusplus
}
#endif

//#define USE_TY700TFT800480
#define USE_TY430TFT480272

#if defined (USE_TY430TFT480272)
	/*
	*********************************************************************
	* TIMING PARAMETERS FOR 4.3" TFT PANEL (480x272):
	* PART# TY430TFT480272
	*********************************************************************
	*/
	/*********************************************************************
	* Overview: Horizontal and vertical display resolution
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_HOR_RESOLUTION				480
	#define DISP_VER_RESOLUTION				272
	/*********************************************************************
	* Overview: Image orientation (can be 0, 90, 180, 270 degrees).
	*********************************************************************/
	#define DISP_ORIENTATION				0
	/*********************************************************************
	* Overview: Panel Data Width
	*********************************************************************/
	#define DISP_DATA_WIDTH                 24
	/*********************************************************************
	* Overview: LSHIFT Polarity Swap
	* If defined LSHIFT is a falling trigger
	*********************************************************************/
	//#define DISP_INV_LSHIFT
	/*********************************************************************
	* Overview: Horizontal synchronization timing in pixels
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_HOR_PULSE_WIDTH		41  
	#define DISP_HOR_BACK_PORCH			2
	#define DISP_HOR_FRONT_PORCH		2	
	/*********************************************************************
	* Overview: Vertical synchronization timing in lines
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_VER_PULSE_WIDTH		10
	#define DISP_VER_BACK_PORCH			2	
	#define DISP_VER_FRONT_PORCH		2
	
	/*********************************************************************
	* Definition for SPI interface for SSD1963 
	* Hardware dependent!
	*********************************************************************/
	#define GPIO3 3
	#define GPIO2 2
	#define GPIO1 1
	#define GPIO0 0
	#define LCD_RESET (1<<GPIO0)		//LCD Reset signal (Reset for display panel, NOT ssd1963)
	#define LCD_SPENA	0
	#define LCD_SPCLK	0
	#define LCD_SPDAT	0
	/* End of definition for TY430TFT480272 */
#elif defined (USE_TY700TFT800480)
	/*
	*********************************************************************
	* TIMING PARAMETERS FOR 7" TFT PANEL (800x480) version 2 high lumin
	* PART# TY700TFT800480_R3
	*********************************************************************
	*/
	/*********************************************************************
	* Overview: Horizontal and vertical display resolution
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_HOR_RESOLUTION				800
	#define DISP_VER_RESOLUTION				480
	/*********************************************************************
	* Overview: Image orientation (can be 0, 90, 180, 270 degrees).
	*********************************************************************/
	#define DISP_ORIENTATION				0
	/*********************************************************************
	* Overview: Panel Data Width
	*********************************************************************/
	#define DISP_DATA_WIDTH                 24
	/*********************************************************************
	* Overview: LSHIFT Polarity Swap
	* If defined LSHIFT is a falling trigger
	*********************************************************************/
	//#define DISP_INV_LSHIFT
	/*********************************************************************
	* Overview: Horizontal synchronization timing in pixels
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_HOR_PULSE_WIDTH		3 
	#define DISP_HOR_BACK_PORCH			88
	#define DISP_HOR_FRONT_PORCH		37	


	/*********************************************************************
	* Overview: Vertical synchronization timing in lines
	*                  (from the glass datasheet).
	*********************************************************************/
	#define DISP_VER_PULSE_WIDTH		3
	#define DISP_VER_BACK_PORCH			32	
	#define DISP_VER_FRONT_PORCH		10


	/*********************************************************************
	* Definition for SPI interface for SSD1963 
	* Hardware dependent!
	*********************************************************************/
	#define GPIO3 3
	#define GPIO2 2
	#define GPIO1 1
	#define GPIO0 0
	#define LCD_RESET (1<<GPIO0)		//LCD Reset signal (Reset for display panel, NOT ssd1963)
	#define LCD_SPENA	0
	#define LCD_SPCLK	0
	#define LCD_SPDAT	0
	/* End of definition for DISPLAY_PANEL == TY700TFT800480 */
#endif
	

/**
 * ***************************************************************************************
 * Command set for SSD196x
 * ***************************************************************************************
 */
#define CMD_NOP					0x00	//No operation
#define CMD_SOFT_RESET			0x01	//Software reset
#define CMD_GET_PWR_MODE		0x0A	//Get the current power mode
#define CMD_GET_ADDR_MODE		0x0B	//Get the frame memory to the display panel read order
#define CMD_GET_PIXEL_FORMAT	0x0C	//Get the current pixel format
#define CMD_GET_DISPLAY_MODE	0x0D	//Returns the display mode
#define CMD_GET_SIGNAL_MODE		0x0E	//
#define CMD_GET_DIAGNOSTIC		0x0F
#define CMD_ENT_SLEEP			0x10
#define CMD_EXIT_SLEEP			0x11
#define CMD_ENT_PARTIAL_MODE	0x12
#define CMD_ENT_NORMAL_MODE		0x13
#define CMD_EXIT_INVERT_MODE	0x20
#define CMD_ENT_INVERT_MODE		0x21
#define CMD_SET_GAMMA			0x26
#define CMD_BLANK_DISPLAY		0x28
#define CMD_ON_DISPLAY			0x29
#define CMD_SET_COLUMN			0x2A
#define CMD_SET_PAGE			0x2B
#define CMD_WR_MEMSTART			0x2C
#define CMD_RD_MEMSTART			0x2E
#define CMD_SET_PARTIAL_AREA	0x30
#define CMD_SET_SCROLL_AREA		0x33
#define CMD_SET_TEAR_OFF		0x34	//synchronization information is not sent from the display
#define CMD_SET_TEAR_ON			0x35	//sync. information is sent from the display
#define CMD_SET_ADDR_MODE		0x36	//set fram buffer read order to the display panel
#define CMD_SET_SCROLL_START	0x37
#define CMD_EXIT_IDLE_MODE		0x38
#define CMD_ENT_IDLE_MODE		0x39
#define CMD_SET_PIXEL_FORMAT	0x3A	//defines how many bits per pixel is used
#define CMD_WR_MEM_AUTO			0x3C
#define CMD_RD_MEM_AUTO			0x3E
#define CMD_SET_TEAR_SCANLINE	0x44
#define CMD_GET_SCANLINE		0x45
#define CMD_RD_DDB_START		0xA1
#define CMD_RD_DDB_AUTO			0xA8
#define CMD_SET_PANEL_MODE		0xB0
#define CMD_GET_PANEL_MODE		0xB1
#define CMD_SET_HOR_PERIOD		0xB4
#define CMD_GET_HOR_PERIOD		0xB5
#define CMD_SET_VER_PERIOD		0xB6
#define CMD_GET_VER_PERIOD		0xB7
#define CMD_SET_GPIO_CONF		0xB8
#define CMD_GET_GPIO_CONF		0xB9
#define CMD_SET_GPIO_VAL		0xBA
#define CMD_GET_GPIO_STATUS		0xBB
#define CMD_SET_POST_PROC		0xBC
#define CMD_GET_POST_PROC		0xBD
#define CMD_SET_PWM_CONF		0xBE
#define CMD_GET_PWM_CONF		0xBF
#define CMD_SET_LCD_GEN0		0xC0
#define CMD_GET_LCD_GEN0		0xC1
#define CMD_SET_LCD_GEN1		0xC2
#define CMD_GET_LCD_GEN1		0xC3
#define CMD_SET_LCD_GEN2		0xC4
#define CMD_GET_LCD_GEN2		0xC5
#define CMD_SET_LCD_GEN3		0xC6
#define CMD_GET_LCD_GEN3		0xC7
#define CMD_SET_GPIO0_ROP		0xC8
#define CMD_GET_GPIO0_ROP		0xC9
#define CMD_SET_GPIO1_ROP		0xCA
#define CMD_GET_GPIO1_ROP		0xCB
#define CMD_SET_GPIO2_ROP		0xCC
#define CMD_GET_GPIO2_ROP		0xCD
#define CMD_SET_GPIO3_ROP		0xCE
#define CMD_GET_GPIO3_ROP		0xCF
#define CMD_SET_ABC_DBC_CONF	0xD0
#define CMD_GET_ABC_DBC_CONF	0xD1
#define CMD_SET_DBC_HISTO_PTR	0xD2
#define CMD_GET_DBC_HISTO_PTR	0xD3
#define CMD_SET_DBC_THRES		0xD4
#define CMD_GET_DBC_THRES		0xD5
#define CMD_SET_ABM_TMR			0xD6
#define CMD_GET_ABM_TMR			0xD7
#define CMD_SET_AMB_LVL0		0xD8
#define CMD_GET_AMB_LVL0		0xD9
#define CMD_SET_AMB_LVL1		0xDA
#define CMD_GET_AMB_LVL1		0xDB
#define CMD_SET_AMB_LVL2		0xDC
#define CMD_GET_AMB_LVL2		0xDD
#define CMD_SET_AMB_LVL3		0xDE
#define CMD_GET_AMB_LVL3		0xDF
#define CMD_PLL_START			0xE0	//start the PLL
#define CMD_PLL_STOP			0xE1	//disable the PLL
#define CMD_SET_PLL_MN			0xE2
#define CMD_GET_PLL_MN			0xE3
#define CMD_GET_PLL_STATUS		0xE4	//get the current PLL status
#define CMD_ENT_DEEP_SLEEP		0xE5
#define CMD_SET_PCLK			0xE6	//set pixel clock (LSHIFT signal) frequency
#define CMD_GET_PCLK			0xE7	//get pixel clock (LSHIFT signal) freq. settings
#define CMD_SET_DATA_INTERFACE	0xF0
#define CMD_GET_DATA_INTERFACE	0xF1

/** GPIO pins
* PD2		------> RESET
* PD7		------> Backlight enable
* PA9		------> TE for vsync synchronization
*/
#define LCD_RST_BASE	GPIOD
#define LCD_RST_PIN		GPIO_Pin_2
#define RCC_AHB1Periph_LCD_RST	RCC_AHB1Periph_GPIOD

#define LCD_TE_BASE									GPIOA
#define LCD_TE_PIN									GPIO_Pin_9
#define LCD_TE_EXTI_Line						EXTI_Line9												//this is to match GPIOA9, level shifted by a mosfet from 1.8V -> 3.3V
#define LCD_TE_IRQn									EXTI9_5_IRQn											//this is to match GPIOA9 interrupt handler number to line 5 to 9
#define LCD_EXTI_IRQHandler					EXTI9_5_IRQHandler								//this is to match EXTI_IRQ handler in BoardConfiguration.cpp
#define RCC_AHB1Periph_TE					 	RCC_AHB1Periph_GPIOA
#define LCD_TE_PortSourceGPIO				EXTI_PortSourceGPIOA
#define LCD_TE_PinSource						EXTI_PinSource9

#define LCD_BACKLIGHT_BASE	GPIOD
#define LCD_BACKLIGHT_PIN		GPIO_Pin_7
#define RCC_AHB1Periph_LCD_BACKLIGHT	RCC_AHB1Periph_GPIOD

#ifndef FRAME_BUFFER_START
	#define FRAME_BUFFER_START	(uint32_t)(0xd0000000)
#endif

/**
* @class LCDController
* @brief Interface for LCD controller SSD196x
* 			 Access mode in 8080 16-bit. Inherent from SMT32F4HAL is required to make touch controller work somehow.
*/
class LCDController	: public STM32F4HAL
	{
public :
		LCDController(touchgfx::DMA_Interface& dma, touchgfx::LCD& display, touchgfx::TouchController& tc, uint16_t width, uint16_t height): 
		STM32F4HAL(dma, display, tc, width, height)
		{
			LCDController::init();	//initialize fmc in 16-bit 8080 mode & SSD2805 & S6D04D2
		}
		virtual void init();
		void hardwareReset(bool state);
		void softwareReset();
		void backlightSet(uint8_t intensity);
		void sleepIn();
		void sleepOut();
		void fillRectDirect(const Rect& rect, uint16_t color);
		virtual void flushFrameBuffer();
		virtual void flushFrameBuffer(const Rect& rect);
	
		virtual void disableInterrupts();
		virtual void enableInterrupts();
		virtual void configureInterrupts();
		virtual void enableLCDControllerInterrupt();
protected:
		virtual uint16_t* getTFTFrameBuffer() const;
		virtual void setTFTFrameBuffer(uint16_t* adr)
		{
			//nothing to do for 8080 LCD interface
		}
private:
		void writeReg(uint8_t reg, uint16_t data);
		void setRect(const Rect& rect);
		void gpioWrite(uint8_t pin, bool state);
		void delayMs(__IO uint32_t ms);
	};
#endif
