/*
 * SPI_Driv.c
 *
 *  Created on: 202142
 *      Author: dell
 */

#include "SPI_Driv.h"

XGpioPs psGpioInstancePtr;     //˿
XGpioPs_Config* GpioConfigPtr; //豸ID


extern u32 K7_U0[16];
extern u32 molex_4_bank_3[4];
extern u32 cs_en_bank_3[4];

/******************************************************************************
* Function    : void interface_initial(u32* device,u32 num_wire)
* Description : interface initial
* Parameter   : device   -- CPLD
* 				num_wire -- λ߱
* Return      : void
******************************************************************************/
void interface_initial(u32* device)  //wire_num = cs sck sdi/o
 {
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);

 }

/******************************************************************************
* Function    : void rst_CPLD(u32* device,u32 num_wire)
* Description : CPLD reset
* Parameter   : device   -- CPLD
* 				num_wire -- λ߱
* Return      : void
******************************************************************************/
void rst_CPLD(u32* device,u32 num_wire) //wire_num = cs sck sdi/o
{
	u32	rst_n = *(device+num_wire);

	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 1);
	usleep(2);
	XGpioPs_WritePin(&psGpioInstancePtr, rst_n, 0);
}

/******************************************************************************
* Function    : void spi_write_onewire(char addr, u32 data, char width, u32* device)
* Description : spi onewire write
* Parameter   : addr   -- ַ
* 				data   -- 
* 				width  -- ݳ
* 				device -- CPLD
* Return      : void
******************************************************************************/
void spi_write_onewire(char addr, char *data, char width, u32* device)
{
	char  temp_addr = 0;
	//u32   temp_data = 0;
	u32   temp_data = 0;
	char  i = 0,j=0;
	u32   sck = *(device+0);
	u32	  cs= *(device+1);
	u32   sdi= *(device+2);

	temp_addr = addr;
	///temp_data = data;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs,  0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs,  0);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1);			// w/r־λ    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 8; i++)								// 8bitַ
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

	    if(temp_addr&0x80)
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1); //sck͵ƽ     ݴмͨ
	    else
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    temp_addr = temp_addr<<1;                       //sckߵƽ׼,˴Ϊ׼ڶݣһѾ
	}

	for(j=0;j<width;j++)
	{
		temp_data = *(data+j);
		for(i = 0; i < 8; i++)                             //nbit
		{
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

			if(temp_data&0x80)							//עλnbitҪ[n-1]ȡλ
				XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1);
			else
				XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

			XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
			XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
			temp_data <<=  1;
		}
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	}

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs , 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);
}

/******************************************************************************
* Function    : u32	spi_read_onewire(char addr, char width, u32* device)
* Description : spi onewire read
* Parameter   : addr   -- ַ
* 				data   -- 
* 				width  -- ݳ
* 				device -- CPLD
* Return      : void
******************************************************************************/
u32	spi_read_onewire(char addr, char width, u32* device)
{
	char  temp_addr=0;
	u32	  temp_data=0;
	char  i=0,j=0;
	u32   sck = *(device+0);
	u32	  cs= *(device+1);
	u32   sdi= *(device+2);
	u32   sdo= *(device+3);

	temp_addr = addr;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);		// w/r־λ    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 8; i++)								// 8bitַ
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

	    if(temp_addr&0x80)
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 1); //sck͵ƽ     ݴмͨ
	    else
	    	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);

	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    temp_addr = temp_addr<<1;                       //sckߵƽ׼,˴Ϊ׼ڶݣһѾ
	}

	for(j=0; j<width; j++)
	{
			for(i = 0; i < 8; i++)                             //nbit
			{
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

				temp_data = temp_data << 1;                     //sck͵ƽ׼    ׼λʱ൱ڴұߵFPGAƽMCU(׼м)

				XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

				if(XGpioPs_ReadPin(&psGpioInstancePtr,sdo))    //sckߵƽ     ƥ䵽׼õλȴһ𴫵ݵMCU
					temp_data = temp_data| 0x00000001;
				XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
			}
	}

    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sdi, 0);
	return temp_data;
}

/******************************************************************************
* Function    : void fourwire_write(u8 txdata, u32 sdi0, u32 sdi1, u32 sdi2, u32 sdi3)
* Description : forwire write to reg
* Parameter   : txdata--
* 				sdi0,sdi1,sdi2,sdi3--IO
* Return      : void
******************************************************************************/
void fourwire_write(u8 txdata, u32 sdi0, u32 sdi1, u32 sdi2, u32 sdi3)
{
	switch(txdata & 0x0F)
	{
	   case 0x00:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x01:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x02:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x03:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x04:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x05:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x06:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x07:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 0);
			   break;
		   }
	   case 0x08:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x09:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0A:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0B:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0C:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0D:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0E:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 0);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	   case 0x0F:
		   {
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi0, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi1, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi2, 1);
			   XGpioPs_WritePin(&psGpioInstancePtr, sdi3, 1);
			   break;
		   }
	}
}

/******************************************************************************
* Function    : void spi_write_fourwire(char addr, u16 data, u32* device)
* Description : spi fourwire write
* Parameter   : addr   -- ַ
* 				data   -- 
* 				width  -- ݳ
*  				device -- CPLD
* Return      : void
******************************************************************************/
void spi_write_fourwire(char addr, u16 data, u32* device)
{
	u8    temp_addr = 0;
	u16   temp_data = 0;
	u8	  split_addr[2] = {0};	//8bitֱַ֣4ߴ䣬
	u8	  split_data[4] = {0};	//16bitݲ44bit
	u8    i;
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);
	u32	  sdi0 = *(device+2);
	u32	  sdi1 = *(device+3);
	u32	  sdi2 = *(device+4);
	u32	  sdi3 = *(device+5);

	temp_addr = addr;
	temp_data = data;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	fourwire_write(0x01,sdi0,sdi1,sdi2,sdi3);     			// w/r־λ    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 2;i++)									// 8bitַ ĸ߷δ
	{
		split_addr[i] = (temp_addr>>(4*(1-i)))&0x0F;		//sckߵƽ׼		ݴMCUм
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_addr[i],sdi0,sdi1,sdi2,sdi3);	//sck͵ƽ     ݴмͨ

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}
	for(i = 0; i < 4;i++)									//16bit  4߷Ĵδ
	{
		split_data[i] = (temp_data>>(4*(3-i)))&0x0F;
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_data[i],sdi0,sdi1,sdi2,sdi3);

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    fourwire_write(0x00,sdi0,sdi1,sdi2,sdi3);
    //usleep(20);
}

/******************************************************************************
* Function    : u16	fourwire_read(u32 sdo0, u32 sdo1, u32 sdo2, u32 sdo3)
* Description : forwire read from reg
* Parameter   : sdo0,sdo1,sdo2,sdo3--IO
* Return      : rxdata--
******************************************************************************/
u16	fourwire_read(u32 sdo0, u32 sdo1, u32 sdo2, u32 sdo3)
{
	u32 GPIO_PIN[4];
	u16	rdata[4];
	u16 rxdata = 0;

	GPIO_PIN[0] = sdo0;
	GPIO_PIN[1] = sdo1;
	GPIO_PIN[2] = sdo2;
	GPIO_PIN[3] = sdo3;

	for(u8 i = 0; i < 4 ; i++)
	{
		rdata[i] = XGpioPs_ReadPin(&psGpioInstancePtr,GPIO_PIN[i]);
		//xil_printf("rdata[i] = %x\r\n",rdata[i]);
		rxdata   = ((rdata[i])<<i) + rxdata ;
	}
	return	rxdata;
}

/******************************************************************************
* Function    : void spi_read_fourwire(char addr, u16* rxdata, u32* device)
* Description : spi fourwire read
* Parameter   : addr   -- ַ
* 				rxdata -- 
* 				device -- CPLD
* Return      : void
******************************************************************************/
void spi_read_fourwire(char addr, u16* rxdata, u32* device)   //ʹָ봫ݣն
{
	u8    temp_addr = 0;
	u16   temp_data = 0;
	u8	  split_addr[2] = {0};	//8bitֱַ֣4ߴ䣬
	u16	  split_data[4] = {0};	//16bitݲ44bit
	u8    i = 0;
	u32   sck   = *(device+0);
	u32	  cs    = *(device+1);
	u32	  sdio0 = *(device+2);
	u32	  sdio1 = *(device+3);
	u32	  sdio2 = *(device+4);
	u32	  sdio3 = *(device+5);

	temp_addr = addr;

	split_addr[0] = (temp_addr >> 4)&0x0F;
	split_addr[1] = (temp_addr)&0x0F;

	XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, cs, 0);
	fourwire_write(0x00,sdio0,sdio1,sdio2,sdio3);     			// w/r־λ    1=w 0=r
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	for(i = 0; i < 2; i++)									// 8bitַ ĸ߷δ
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		fourwire_write(split_addr[i],sdio0,sdio1,sdio2,sdio3);	//sck͵ƽ     ݴмͨ

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	}

	for(i = 0; i < 4; i++)
	{
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, *(device+2+i),0);  //input
	}

	for(i = 0; i < 4; i++)									//16bit  4߷Ĵν
	{
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
		XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);

		split_data[i] = fourwire_read(sdio0,sdio1,sdio2,sdio3);	//sck͵ƽ׼     ݴͨߵм

		XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);
	    XGpioPs_WritePin(&psGpioInstancePtr, sck, 1);

	    temp_data = temp_data<<4;
	    temp_data = temp_data + split_data[i];
		//temp_data = (split_data[i]<<(4*(3-i))) + temp_data;		//sckߵƽ     ݴмMCU
//	    xil_printf("split_data[i],temp_data = %x,%x\r\n",split_data[i],temp_data);

	}

	for(i = 0; i < 4; i++)
	{
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, *(device+2+i),1);  //output
	}

    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    XGpioPs_WritePin(&psGpioInstancePtr, sck, 0);
    fourwire_write(0x00,sdio0,sdio1,sdio2,sdio3);
	*rxdata = temp_data;
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);
    XGpioPs_WritePin(&psGpioInstancePtr, cs, 1);//add 2 lines
    //usleep(20);
}

/******************************************************************************
* Function    : void GPIO_dir_set(u32* device,char dir)
* Description : change GPIO direction
* Parameter   : device -- CPLD
* 				dir    -- GPIO_OUT/GPIO_IN
* Return      : void
******************************************************************************/
void GPIO_dir_set_16(u32* device,char dir)
{
	u32   sdio[16] = {0};
	u8    i;

	for(i = 0; i < 16;i++)
	{
		sdio[i] = *(device+i);

		//XGpioPs_SetDirectionPin(&psGpioInstancePtr, sdio[i],1);
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, sdio[i],dir);
	}

}

void GPIO_dir_set_cs_enable(u32* device,u8 dir)
{
	u32   sdio[4] = {0};
	u8    i;
	u8    dir_temp = 0;

	for(i = 0; i < 4;i++)
	{
		sdio[i]  = *(device+i);
		dir_temp =  (((dir >> (3-i))) & 0x01);
		XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, sdio[i],dir_temp);
	}
}


void  rst(char *d)
{
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 0);
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 1);
	usleep(20);
	XGpioPs_WritePin(&psGpioInstancePtr, *d, 0);
}


void func_test(void)
{

	XGpioPs_Write(&psGpioInstancePtr, 0x03, 0x12345678);
}
