#include "sw_i2c.h"
#include "delay.h"	 


//==================================================================
//Name:						IIC_Gpio_Init
//Author:					QD
//Date:						2017-07-06
//Function:				Init GPIO of IIC
//								
//Input:					void
//Output:					void
//option:
//==================================================================
void IIC_Gpio_Init(void)
{
/*	
 	RCC->APB2ENR|=1<<3;				//enable clk of PORTB
	//CSCL--PB5
	//CSDA--PB6
	GPIOB->CRL&=0XF00FFFFF;		//PB5&PB6 as output
	GPIOB->CRL|=0X03300000;	   
	GPIOB->ODR|=0<<5;	    		//PB5 output high
	GPIOB->ODR|=0<<6;	    		//PB6 output high
*/
	GPIO_InitTypeDef  GPIO_InitStructure; 

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

	/*STM32F103C8T6芯片的硬件I2C: PB5 -- SCL; PB6 -- SDA */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//I2C必须开漏输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

//==================================================================
//Name:						IIC_Start
//Author:					QD
//Date:						2017-07-06
//Function:				IIC start
//								
//Input:					void
//Output:					void
//option:
//==================================================================
void IIC_Start(void)
{
	SDA_OUT();
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	//delay_us(IIC_CLK_DELAY);
 	IIC_SDA=0;		//START:when CLK is high,DATA change form high to low 
	//delay_us(IIC_CLK_DELAY);
	IIC_SCL=0;		//hold IIC bus, prepare to send data
}	  


//==================================================================
//Name:						IIC_Stop
//Author:					QD
//Date:						2017-07-06
//Function:				IIC stop
//								
//Input:					void
//Output:					void
//option:
//==================================================================
void IIC_Stop(void)
{
	SDA_OUT();
	IIC_SCL=0;
	IIC_SDA=0;			//STOP:when CLK is high DATA change form low to high
 	delay_us(IIC_CLK_DELAY);
	IIC_SCL=1; 
	IIC_SDA=1;			
	delay_us(IIC_CLK_DELAY);							   	
}


//==================================================================
//Name:						IIC_Wait_Ack
//Author:					QD
//Date:						2017-07-06
//Function:				IIC Wait Ack
//								
//Input:					void
//Output:					void
//option:
//==================================================================
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	IIC_SCL=0;
	delay_us(IIC_CLK_DELAY);	 
	IIC_SDA=1;
	delay_us(IIC_CLK_DELAY);
	SDA_IN();
	IIC_SCL=1;
	delay_us(IIC_CLK_DELAY);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;
	return 0;  
} 


//==================================================================
//Name:						IIC_Ack
//Author:					QD
//Date:						2017-07-06
//Function:				Output Ack to master
//								
//Input:					void
//Output:					void
//option:
//==================================================================
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(IIC_CLK_DELAY);
	IIC_SCL=1;
	delay_us(IIC_CLK_DELAY);
	IIC_SCL=0;
}

//==================================================================
//Name:						IIC_NAck
//Author:					QD
//Date:						2017-07-06
//Function:				Output NAck to master
//								
//Input:					void
//Output:					void
//option:
//==================================================================
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(IIC_CLK_DELAY);
	IIC_SCL=1;
	delay_us(IIC_CLK_DELAY);
	IIC_SCL=0;
}					 				     


void IIC_WriteREG(u8 byte)
{
	IIC_Start();
	IIC_Send_Byte(0x78); //写数据指令
	IIC_Send_Byte(0x00);
	IIC_Send_Byte(byte);
}

void IIC_WriteDAT(u8 byte)
{
	IIC_Start();
	IIC_Send_Byte(0x78); //写数据指令
	IIC_Send_Byte(0x40);
	IIC_Send_Byte(byte);
}


//==================================================================
//Name:						IIC_Send_Byte
//Author:					QD
//Date:						2017-07-06
//Function:				send 1 byte
//								
//Input:					unsigned char txd		//data should be transfer
//Output:					void
//option:
//==================================================================
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
		SDA_OUT();
    IIC_SCL=0;				//hold clk to low
	for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
				//delay_us(IIC_CLK_DELAY);   
				IIC_SCL=1;
				//delay_us(IIC_CLK_DELAY); 
				IIC_SCL=0;	
				//delay_us(IIC_CLK_DELAY);
    }
//	iic_send_test(txd);
		IIC_SCL=1;
		IIC_SCL=0;	

//		IIC_Wait_Ack();
} 	    

void iic_send_test(u8 txd)
{
	if(txd&0x80) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x40) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x20) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x10) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x08) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x04) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x02) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	
	if(txd&0x01) IIC_SDA=1; else	IIC_SDA=0; IIC_SCL=1; IIC_SCL=0;	

}
//==================================================================
//Name:						IIC_Read_Byte
//Author:					QD
//Date:						2017-07-06
//Function:				read 1 byte
//								
//Input:					unsigned char ack		//need ack or nack
//Output:					unsigned char				//received or not
//option:
//==================================================================
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();					//set SDA as input
  for(i=0;i<8;i++ )
	{
		IIC_SCL=0; 
    delay_us(IIC_CLK_DELAY);
		IIC_SCL=1;
    receive<<=1;
    if(READ_SDA)
			receive++;   
		delay_us(IIC_CLK_DELAY); 
  }					 
  if (!ack)
		IIC_NAck();			//reply NAck
  else
		IIC_Ack(); 			//reply Ack
  return receive;
}

