#include <stdarg.h>
#include "yc11xx.h"
#include "ycdef.h"
#include "yc11xx_uart.h"
#include "yc11xx_gpio.h"
#include "yc11xx_spi.h"
#define OLED_H_NUM					8
#define OLED_WIDTH					128

typedef struct{
	uint16_t SPID_TX_LEN;
	uint8_t *SPID_TX_ADDR;
	uint16_t SPID_RX_LEN;
	uint8_t * SPID_RX_ADDR;	
}SPI_Buff;

typedef struct{
	uint8_t CLOCK_GPIO_NUM;
	uint8_t MOSI_GPIO_NUM;
	uint8_t MISO_GPIO_NUM;
	uint8_t CS_GPIO_NUM;
}SPI_GPIO;	


#define UNDEF_GPIO									0xFF
#define OLED_C_D_SELECT_GPIO						0x1c		//gpio28

#define GPIO_OLED_CONFIG_RES                        0x1a		//GPIO 26
#define GPIO_OLED_CONFIG_A0                       	0x1d
#define OLED_SH1106_SPI_CLOCK_GPIO					0x18		//GPIO 24
#define OLED_SH1106_SPI_MOSI_GPIO					0x19		//GPIO 25
#define OLED_SH1106_SPI_MISO_GPIO					UNDEF_GPIO	// undefine GPIO 
#define OLED_SH1106_SPI_CS_GPIO						0x17		//GPIO 23

void gpio_output_high_level(uint8_t GPIO_num)
{
	GPIO_SetGpioMultFunction(GPIO_num,GPCFG_OUTPUT_HIGH);
}

void gpio_output_low_level(uint8_t GPIO_num)
{
	GPIO_SetGpioMultFunction(GPIO_num,GPCFG_OUTPUT_LOW);
}
						
#define	GPIO_OLED_CONFIG_CLOCK		GPIO_SetGpioMultFunction(OLED_SH1106_SPI_CLOCK_GPIO , 	GPCFG_SPID_SCK)
#define	GPIO_OLED_CONFIG_MOSI			GPIO_SetGpioMultFunction(OLED_SH1106_SPI_MOSI_GPIO, 		GPCFG_SPID_MOSI)
#define	GPIO_OLED_CONFIG_MISO			GPIO_SetGpioMultFunction(OLED_SH1106_SPI_MISO_GPIO, 		GPCFG_SPID_MISO)
#define	GPIO_OLED_CONFIG_CS			GPIO_SetGpioMultFunction(OLED_SH1106_SPI_CS_GPIO , 		GPCFG_SPID_NCS)

#define 	GPIO_OLED_DISABLE_CLOCK		GPIO_SetGpioMultFunction(OLED_SH1106_SPI_CLOCK_GPIO,	GPCFG_OUTPUT_HIGH )
#define 	GPIO_OLED_DISABLE_MOSI		GPIO_SetGpioMultFunction(OLED_SH1106_SPI_MOSI_GPIO, 		GPCFG_OUTPUT_HIGH )
#define 	GPIO_OLED_DISABLE_MISO		GPIO_SetGpioMultFunction(OLED_SH1106_SPI_MISO_GPIO , 		GPCFG_OUTPUT_HIGH)
#define 	GPIO_OLED_DISABLE_CS			GPIO_SetGpioMultFunction(OLED_SH1106_SPI_CS_GPIO, 		GPCFG_OUTPUT_HIGH)
#define	LCD_RS_CMD		0x00
#define	LCD_RS_DATA		0x01

void clr_a0(void);
void set_a0(void);
void spi_write_data(unsigned char data);
void spi_write_cmd(unsigned char cmd);
void write_byte_lcd(unsigned char data, unsigned char cmd);
void write_bytes_lcd(unsigned char* pdata, unsigned char len, unsigned char cmd);
void clr_screen(void);
void full_screen(void);
void set_xy(unsigned char column, unsigned char page);
void init_lcd(void);
void SPI_LCD_Test(void);

/*************************************SPI_OLED_TEST********************************/


#define IO_TXA  8
#define IO_RXA  9
#define IO_TXB  10
#define IO_RXB  11
#define UARTBUFSIZE 128

void UartxInit(USART_TypeDef UARTx)
{
	USART_InitTypeDef USART_InitStruct ;
	
	USART_InitStruct.USART_BaudRate = UARTE_BAUDRATE_BAUDRATE_Baud115200;
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;	
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	USART_InitStruct.USART_Mode =USART_Mode_duplex;
	USART_InitStruct.USART_Parity = USART_Parity_Even ;
	USART_InitStruct.USART_RXLen = UARTBUFSIZE;
	USART_InitStruct.USART_TXLen = UARTBUFSIZE;

	if(UARTA == UARTx){
	GPIO_SetGpioMultFunction(IO_TXA,GPCFG_UART_TXD);
	GPIO_SetGpioMultFunction(IO_RXA,GPCFG_UART_RXD);
	}else if (UARTB == UARTx){
	GPIO_SetGpioMultFunction(IO_TXB,GPCFG_UARTB_TXD);
	GPIO_SetGpioMultFunction(IO_RXB,GPCFG_UARTB_RXD);
	}

	USART_Init(UARTx,&USART_InitStruct);
}
void debug_print(uint32_t data)
{
	 USART_SendData(UARTB,(data>>24) & 0xff);
	 USART_SendData(UARTB,(data>>16) & 0xff);
	 USART_SendData(UARTB,(data>>8 ) & 0xff);
	 USART_SendData(UARTB,(data>>0 ) & 0xff);
}
void gpio_oled_config()
{
	GPIO_OLED_CONFIG_CLOCK;
	GPIO_OLED_CONFIG_MOSI;
	GPIO_OLED_CONFIG_MISO;
	GPIO_OLED_CONFIG_CS;
}

int main(void)
{
	GPIO_CONFIG(20)= GPCFG_JTAG_SWCLK;
	GPIO_CONFIG(21)= GPCFG_JTAG_SWDAT;
	uint32_t i=0x1000000;
	UartxInit(UARTB); 	//print log 
	while(i--){}
	systick_init();
	printf("/****************spi test start****************/");
	SPI_InitTypeDef SPI_InitStruct;
	SPI_InitStruct.SPI_BaudSpeed = SPI_BAUDSPEED_750KHz;
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_Second_Edge;
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_Active_Low;
	SPI_InitStruct.SPI_Mode = SPI_Mode_Four_Wire;
	SPI_InitStruct.SPI_RXlen = 0x0a;
	SPI_InitStruct.SPI_TXLen = 0x0a;
	gpio_oled_config();
	SPI_Init(&SPI_InitStruct);
	init_lcd();
	SPI_LCD_Test();
	while(1)
	{
		
	}
}

 
 
/**********************************OLED FUN ***********************************/
void clr_a0(void)
{
	gpio_output_low_level(GPIO_OLED_CONFIG_A0);
}

void set_a0(void)
{
	gpio_output_high_level(GPIO_OLED_CONFIG_A0);
}

void spi_write_data(unsigned char data)
{
	set_a0();
	SPI_SendData(data);
}

void spi_write_cmd(unsigned char cmd)
{
	clr_a0();
	SPI_SendData(cmd);
}

void write_byte_lcd(unsigned char data, unsigned char cmd)
{
	if (LCD_RS_CMD  == cmd)
	{
		spi_write_cmd(data); 
	}
	else if (LCD_RS_DATA  == cmd )
	{
		spi_write_data(data); 
	}
}

void write_bytes_lcd(unsigned char* pdata, unsigned char len, unsigned char cmd)
{
	unsigned char m = 0;

	if (LCD_RS_CMD  == cmd )
	{
		for (m = 0;m < len ; m++)
		{
			spi_write_cmd(pdata[m]);		    
		}            	    
	}
	else if (LCD_RS_DATA  == cmd )
	{
		for (m = 0;m < len ; m++)
		{
			spi_write_data((int)(pdata[m]));		    
		}            	    
	}
}

void clr_screen(void)
{
	int i,page;
	for(page=0;page<8;page++)
	{
		spi_write_cmd(0x10);
		spi_write_cmd(0x00);
		spi_write_cmd(page+0xb0);
		
		for (i=0;i<128;i++)
		{
			spi_write_data(0);
		}
	}
}

void full_screen(void)
{
	int i,page;
	
	for(page=0;page<8;page++)
	{
		spi_write_cmd(0x10);
		spi_write_cmd(0x00);
		spi_write_cmd(page+0xb0);
		
		for (i=0;i<128;i++)
		{
			spi_write_data(0xFF);
		}
	}
}

void set_xy(unsigned char column, unsigned char page)
{
	unsigned char cmd[3];

	cmd[0] = 0xb0 | page;
	cmd[1] = 0x10 | (column >> 4);
	cmd[2] = 0x00 | (column & 0x0f);
	write_bytes_lcd(cmd,3,LCD_RS_CMD);
}

void init_lcd(void)
{
	gpio_output_high_level(GPIO_OLED_CONFIG_A0);
	gpio_output_high_level(GPIO_OLED_CONFIG_RES);
	delay_ms(20);
	gpio_output_low_level(GPIO_OLED_CONFIG_RES);
	delay_ms(100);
	gpio_output_high_level(GPIO_OLED_CONFIG_RES);
	delay_ms(10); 
	spi_write_cmd(0xe2);//reset
	delay_ms(10);				
	spi_write_cmd(0xa0);//SEG Direction
	delay_ms(10);
	spi_write_cmd(0xc8);//COM Direction
	delay_ms(10);
	spi_write_cmd(0xa2);//Bias Select
	delay_ms(10);
	spi_write_cmd(0x2f);//Power Control
	delay_ms(10);
	spi_write_cmd(0x24);//Regulation Ratio
	delay_ms(10);
	spi_write_cmd(0x81);//Set EV_1
	delay_ms(10);
	spi_write_cmd(0x2f);//Set EV_2
	delay_ms(10);
	spi_write_cmd(0xaf);//Display ON
	delay_ms(10);
	clr_screen();
	set_xy(100, 1);
	write_byte_lcd(0x00, LCD_RS_DATA);
}

void SPI_LCD_Test(void)
{
	unsigned char i;
	unsigned char Bmp001[24 * 6]={
		0x00,0x00,0x00,0x00,0x00,0xC0,0x40,0x00,0x00,0x00,0x00,0xFE,
		0xFC,0x00,0x00,0x00,0x00,0x00,0xE0,0xC0,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x08,0x0F,0x07,0x00,0x00,0x00,0xC0,0xFC,0x3F,
		0x3F,0xF0,0xC0,0x00,0x0C,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,
		0x00,0x20,0x60,0x70,0x30,0x38,0x1C,0x0E,0x07,0x03,0x00,0x00,
		0x00,0x00,0x03,0x07,0x0E,0x1C,0x18,0x38,0x30,0x70,0x10,0x00
	};

	clr_screen();

	for(i = 0; i < 6; i++)
	{
		set_xy(10,i+2);
		write_bytes_lcd(&Bmp001[24*i], 24, LCD_RS_DATA);
	}
}