#ifdef CO_30_DIAGS

/*********************************************************/
/*                  INCLUDE FILES                        */
/*********************************************************/
#include <stdio.h>
#include <vxWorks.h>
#include <diags_defines.h>

int testPIORead1 (int BmeNum, unsigned long addr);
void testPIOWrite (int BmeNum, unsigned long addr, unsigned long data);


/* bit definition */
#define BIT(n)			(1 << n)

#define BIT0			(BIT(0))
#define BIT1			(BIT(1))
#define BIT2			(BIT(2))
#define BIT3			(BIT(3))
#define BIT4			(BIT(4))
#define BIT5			(BIT(5))
#define BIT6			(BIT(6))
#define BIT7			(BIT(7))
#define BIT8			(BIT(8))
#define BIT9			(BIT(9))
#define BIT10			(BIT(10))
#define BIT11   		(BIT(11))
#define BIT12			(BIT(12))
#define BIT13   		(BIT(13))
#define BIT14   		(BIT(14))
#define BIT15			(BIT(15))
#define BIT16   		(BIT(16))
#define BIT17			(BIT(17))
#define BIT18   		(BIT(18))
#define BIT19			(BIT(19))
#define BIT20			(BIT(20))
#define BIT21   		(BIT(21))
#define BIT22			(BIT(22))
#define BIT23   		(BIT(23))
#define BIT24   		(BIT(24))
#define BIT25   		(BIT(25))
#define BIT26   		(BIT(26))
#define BIT27   		(BIT(27))
#define BIT28   		(BIT(28))
#define BIT29   		(BIT(29))
#define BIT30   		(BIT(30))
#define BIT31   		(BIT(31))



#define s8				INT8
#define u8				UINT8
#define s16				INT16
#define u16				UINT16
#define s32				INT32
#define u32				UINT32



// GPIO

#define GPIO_WDR                0xE00A6000  /* GL       GPIO Write Data Register            */
#define GPIO_PDR                0xE00A6004  /* GL       GPIO Pin Direction Register         */
#define GPIO_RDR                0xE00A6008  /* GL       GPIO Read Data Register             */



void hld_strobe(int bmeNum, int port);


/*
=====================================================================
Functions for Use the GPIO bit banging to write/read the CO5 HLD
=====================================================================
*/

//
//Use shadow register to improve timing when gpio access is queued up at PIO controller
//
u32 gGpioRegVal = 0;	 //32 bit GPIO shadow register


void WRITE_GPIO0(bmeNum, bit)                                  
{                                                         
    (bit>0)? (gGpioRegVal|=BIT0) : (gGpioRegVal&=~BIT0);  
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};


void WRITE_GPIO1(bmeNum, bit)                                  
{                                                         
    (bit>0)? (gGpioRegVal|=BIT1) : (gGpioRegVal&=~BIT1);  
	
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};


void WRITE_GPIO2(bmeNum, bit)                                  
{                                                         
    (bit>0)? (gGpioRegVal|=BIT2) : (gGpioRegVal&=(~BIT2));
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};

void WRITE_GPIO3(bmeNum, bit)                                  
{                                                             
    (bit>0)? (gGpioRegVal|=BIT3) : (gGpioRegVal&=(~BIT3));    
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};

void WRITE_GPIO4(bmeNum, bit)                          
{                                                       
    (bit>0)? (gGpioRegVal|=BIT4) : (gGpioRegVal&=(~BIT4)); 
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};


void WRITE_GPIO5(bmeNum, bit)                          
{                                                         
    (bit>0)? (gGpioRegVal|=BIT5) : (gGpioRegVal&=(~BIT5));
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};

void WRITE_GPIO6(bmeNum, bit)                                  
{                                                            
    (bit>0)? (gGpioRegVal|=BIT6) : (gGpioRegVal&=(~BIT6));   
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};

void WRITE_GPIO7(bmeNum, bit)                                  
{                                                           
    (bit>0)? (gGpioRegVal|=BIT7) : (gGpioRegVal&=(~BIT7));  
	testPIOWrite(bmeNum,GPIO_WDR , gGpioRegVal);		  
};

// Not:  gGpioRegVal =  *((volatile int *) (GPIO_RDR)); 
// If we use the above to make sure gpio state before write, undesired clk/data waveform may happen
// because when clock write read previous GPIO register value, the previous Write is NOT guaranteed to complete even with volatile.


//#define READ_GPIO3()           ( (*((volatile int *)(GPIO_RDR))& BIT3)> 0 ? 1 : 0 ) 
//#define READ_GPIO5()           ( (*((volatile int *)(GPIO_RDR))& BIT5)> 0 ? 1 : 0 ) 

int READ_GPIO3(bmeNum) 
{								
	return (testPIORead1 (bmeNum,GPIO_RDR) & BIT3) >> 3;
}

int READ_GPIO5(bmeNum) 
{								
	return (testPIORead1 (bmeNum,GPIO_RDR) & BIT5) >> 5;
};



void SIO_SC4_0(int bmeNum, int a)
{
	WRITE_GPIO0(bmeNum, a);  //Read/Write signal
}

void SIO_SC4_1(int bmeNum, int a)
{
	WRITE_GPIO1(bmeNum, a);  //Read/Write signal
}
void SIO_SC4_2(int bmeNum, int a)
{
	WRITE_GPIO2(bmeNum, a);  //Read/Write signal
}

void SIO_SC4_3(int bmeNum, int a)
{
	WRITE_GPIO3(bmeNum, a);  //Read/Write signal
}



void SIO_CLOCK(int bmeNum, int a)
{
	WRITE_GPIO4(bmeNum, a);  //Read/Write signal
}

void SIO_DATA(int bmeNum, int a)
{
	WRITE_GPIO5(bmeNum, a);  //Read/Write signal
}


void SIO_STROB(int bmeNum, int a)
{
	WRITE_GPIO6(bmeNum, a);  //Read/Write signal
}

void SIO_STROB2(int bmeNum, int a)
{
	WRITE_GPIO7(bmeNum, a);  //Read/Write signal
}


int SIO_READ_DATA(bmeNum)  
{
	return READ_GPIO5(bmeNum);  //SC3 Common data read for all 4 HLD      
}




static void SIO_DELAY_LOOP( u8 delay)  //check if this need to be macro
{
	register u8 d = delay;
	while (d)
		d--;
}



/*
Write to the HLD via CO5 GPIO.

*/

void sio_writeHLD(int bmeNum, int port, u16 inData)
{ 
	register short int numBit;
	register u16 data = inData;


	testPIOWrite(bmeNum,GPIO_PDR , 0xff);         \
	testPIOWrite(bmeNum,GPIO_WDR , 0);        \


	gGpioRegVal = 0; //shaddow register value

	SIO_DELAY_LOOP(5);

	for ( numBit=0; numBit<12; numBit++)
	{
		SIO_DELAY_LOOP(1);
		SIO_CLOCK(bmeNum,0);
		SIO_DATA(bmeNum, ((data>>numBit)&1) );
		SIO_DELAY_LOOP(0);
		SIO_CLOCK(bmeNum,1);
	}
	SIO_DELAY_LOOP(2);
	SIO_CLOCK(bmeNum,0);


	// hold time at the end set clk gpio down for at least 3x clock period
	//Not nessessary if use AFE strob SIO_DELAY_LOOP(30); 

	//Strobe is done outside of this functions
	// strob the correct HLD for at least 1 clock period 
}





/*
 This function is to be used in debug and diag phase only. It's not suppose to be used in gernal operation.
 Hence a relaxed clock rate can be used. In this case we choosed a clock of around 1KHz.
 
 History
 + changed to read the first bit at the first clock and the last bit after the last clock.
*/

u16 sio_readHLD(int bmeNum, int port)
{ 
	register u8 numBit;
	register u16 readData = 0;


	//hard code the port for now
	//port = port;

	testPIOWrite(bmeNum,GPIO_PDR , 0xdf);         
	testPIOWrite(bmeNum,GPIO_WDR , 0);        


	gGpioRegVal = 0; //shaddow register value
	SIO_DELAY_LOOP(120);


	//Assert the correct SC4 according to port input:
	switch (port)
	{
	case 0:
	case 1: 
		SIO_SC4_0(bmeNum,1);
		break;
	case 2:
	case 3:
		SIO_SC4_1(bmeNum,1);
		break;
	case 4:
	case 5:
		SIO_SC4_2(bmeNum,1);
		break;
	case 6:
	case 7:
		SIO_SC4_3(bmeNum,1);
		break;
	default:
		printf("invalide port!");
		break;
	}


	//Wait at least 3 clock period.
	SIO_DELAY_LOOP(200);
	SIO_DELAY_LOOP(200);


	//readData |= SIO_READ_DATA();  //take in bit zero

	//Clock SC2 for 11 Clocks.
	for ( numBit=0; numBit<11; numBit++)
	{
		SIO_CLOCK(bmeNum,0);
		SIO_DELAY_LOOP(50);
		SIO_CLOCK(bmeNum,1);
		readData |= ((SIO_READ_DATA(bmeNum)) << numBit);
		SIO_DELAY_LOOP(50);
	}

	SIO_CLOCK(bmeNum,0);

	SIO_DELAY_LOOP(50);
	SIO_DELAY_LOOP(5);

	//the 12th bit here
	readData |= ((SIO_READ_DATA(bmeNum)) << numBit);



	//Wait at least 3 clock period.
	SIO_DELAY_LOOP(200);
	SIO_DELAY_LOOP(200);

	//put the read/write back.
	switch (port)
	{
	case 0:
	case 1: 
		SIO_SC4_0(bmeNum, 0);
		break;
	case 2:
	case 3:
		SIO_SC4_1(bmeNum, 0);
		break;
	case 4:
	case 5:
		SIO_SC4_2(bmeNum, 0);
		break;
	case 6:
	case 7:
		SIO_SC4_3(bmeNum, 0);
		break;
	default:
		printf("invalide port!");
		break;
	}



	return(readData);
}




//----------------------------------------------------------------------
//      CO5 GPIO Hld Write and Read
//----------------------------------------------------------------------





//
//Write Hld through GPIO
//

void gpioHldWrite(int bmeNum, int port, u16 inData)
{
	sio_writeHLD(bmeNum, port, inData);                             

	// Do the data strobe to the correct HLD here
	// This is a dummy write to a IFE through AFE CO3. It generates a CS signal.
	//port 0-3 AFE1  4-7 AFE2
	hld_strobe(bmeNum, port);
}

//
//Read HLD, also convert the bit invert data to the correct format for the higher layer
//
u32 gpioHldRead(int bmeNum, int port)
{
	u32 rtv;

	rtv = (~sio_readHLD(bmeNum, port) & 0xfff);

	return( rtv);
}


int gpioHldTest(int bmeNum, int port)
{
#define MAX_FAILURE 10

	unsigned short int dataPattern = 0x35;
	unsigned int readPattern;


	gpioHldWrite(bmeNum, port, dataPattern);

	taskDelay(5);

	readPattern = gpioHldRead(bmeNum, port);

	taskDelay(5);

	if (readPattern != dataPattern)
	{
		printf("HLD Write/read verify Failed Port %d\n", port);
		return ERROR;
	}
	else
	{
		printf("HLD Write/read verify Passed Port %d\n", port);
		return 0;
	}

}

void gpioHldTestAll (int bmeNum)
{
	int i;
	int err = 0;

	for (i = 0;i < 8;i++)
		err |= gpioHldTest(bmeNum, i);
	if (err)
	{
		printf("HLD TEST Failed");
	}
	else
		printf("HLD TEST Passed");


}
//----------------------------------------------------------------------
//      Above: CO5 GPIO Hld Write and Read
//----------------------------------------------------------------------



#endif
