#ifndef __BSP_I2C_SOFT_H
#define __BSP_I2C_SOFT_H
#include "stm32f4xx_hal.h"
#include "main.h"
// #include "sys.h"

// #define SCL_GPIO_PORT GPIOB
// #define SCL_PIN	 GPIO_PIN_6
// #define SDA_GPIO_PORT GPIOB
// #define SDA_PIN	 GPIO_PIN_7 

#define I2C_WRITE (0x00)
#define I2C_READ  (0x01)

typedef enum  {
  IIC_OK           = 0x00,    //IIC工作正常
  IIC_WAIT_ACK_ERR = 0x01,    //slave设备返回ACK错误
  IIC_WRITE_ERR    = 0x02,    //向slave设备写入错误
  IIC_READ_ERR     = 0x04     //从slave设备读取错误
} IIC_STATUS;

typedef enum
{
    I2C_SW_Standard_Mode = 100 * 1000,
    I2C_SW_Fast_Mode = 400 * 1000,
    I2C_SW_Fast_Mode_Plus = 1000 * 1000,
} I2C_SW_Speed_Mode_TypeDef; //i2c速率 unit Hz

typedef enum
{
    I2C_SW_One_Byte = 1,
    I2C_SW_Two_Byte = 2,
    I2C_SW_Four_Byte = 4
} I2C_SW_Data_Width_TypeDef;//数据长度（寄存器地址或者值的数据长度）

typedef enum
{
    I2C_SW_Slave_Address_7Bit,
    I2C_SW_Slave_Address_10Bit,
} I2C_SW_Slave_Address_Width_TypeDef;//i2c slave address的位宽

typedef struct
{
  GPIO_TypeDef	*scl_port;		//定义IIC时钟使用的端口
  uint16_t			scl_pin;			//定义IIC时钟使用的PIN脚
  GPIO_TypeDef	*sda_port;   	//定义IIC数据使用的端口
  uint16_t			sda_pin;			//定义IIC数据使用的PIN脚
  uint8_t			sda_pin_num;   	//SDA Pin ，操作IO Mode
  uint16_t				addr;        	//器件地址， 兼容16bit
  uint32_t			delaytick;   	//定义延时，以适应不同器件对速率的不同要求,具体值要在调试中确定
  I2C_SW_Slave_Address_Width_TypeDef slave_address_width;
  I2C_SW_Data_Width_TypeDef slave_reg_addr_width;
  I2C_SW_Data_Width_TypeDef slave_reg_value_width;
}IIC_SOFT_TypeDef;

//IO方向设置
#define SDA_IN()  {SDA_GPIO_PORT->MODER&=~(3<<(7*2));SDA_GPIO_PORT->MODER|=0<<7*2;}	//PB7输入模式
#define SDA_OUT() {SDA_GPIO_PORT->MODER&=~(3<<(7*2));SDA_GPIO_PORT->MODER|=1<<7*2;} //PB7输出模式


#define		GPIO_WRITE_PIN(PORT,PIN,VALUE)	HAL_GPIO_WritePin(PORT,PIN,(VALUE)?GPIO_PIN_SET:GPIO_PIN_RESET)
#define		GPIO_READ_PIN(PORT,PIN)					HAL_GPIO_ReadPin(PORT,PIN)


//IIC所有操作函数
// void IIC_Init(  );                //初始化IIC的IO口				 

void IIC_Init(const IIC_SOFT_TypeDef *pSoftIIC);                //初始化IIC的IO口		

int IIC_READ_SDA_Pin(const IIC_SOFT_TypeDef *pSoftIIC);
int IIC_SDA_Mode_In(const IIC_SOFT_TypeDef *pSoftIIC);
int IIC_SDA_Mode_Out(const IIC_SOFT_TypeDef *pSoftIIC);

void IIC_Start(const IIC_SOFT_TypeDef *pSoftIIC);				//发送IIC开始信号
void IIC_Stop(const IIC_SOFT_TypeDef *pSoftIIC);	  			//发送IIC停止信号

int IIC_Send_Byte(const IIC_SOFT_TypeDef *pSoftIIC,uint8_t txd);			//IIC发送一个字节
int IIC_Read_Byte( const IIC_SOFT_TypeDef *pSoftIIC);//IIC读取一个字节

int IIC_Send_Slave_Addr(const IIC_SOFT_TypeDef *pSoftIIC,uint8_t r_w);
int IIC_Send_Reg_Addr(const IIC_SOFT_TypeDef *pSoftIIC,uint32_t reg_addr );


int IIC_Wait_Ack(const IIC_SOFT_TypeDef *pSoftIIC); 				//IIC等待ACK信号
void IIC_Ack(const IIC_SOFT_TypeDef *pSoftIIC);					//IIC发送ACK信号
void IIC_NAck(const IIC_SOFT_TypeDef *pSoftIIC);				//IIC不发送ACK信号


int IIC_Read_Buf(const IIC_SOFT_TypeDef *pSoftIIC,  uint32_t reg_addr , uint8_t *buf, uint8_t len);
int IIC_Write_Buf(const IIC_SOFT_TypeDef *pSoftIIC , uint32_t reg_addr, uint8_t *buf, uint8_t len);


int IIC_Device_Check(const IIC_SOFT_TypeDef *pSoftIIC);
#endif


/*
时序
//  * @brief: I2C 开始,SCL为高电平的时候SDA产生一个下降沿信号
 
//           _____
//      *SDA      \_____________
//      *    __________
//      *SCL           \________
//      


//  * @brief: I2C 停止,SCL为高电平的时候SDA产生一个上升沿信号
//                      _______
//      *SDA __________/
//      *          ____________
//      *SCL _____/
 

//  * @brief: I2C 响应
//                  ____
//      *SCL ______/    \______
//      *    ____         _____
//      *SDA     \_______/
//       

//  * @brief: I2C 不响应
 
//                  ____
//      *SCL ______/    \______
//      *    __________________
//      *SDA
//        

十位slave 先发  高位
0xF00 | ((slave_addr>> 8 & 0x03)<<2) | r_w

16bit 寄存器 addr ,先发  (addr>>8)&0xFF ,后发  addr&0xFF



    IIC_SOFT_TypeDef sIIC = {
         GPIOB, GPIO_PIN_6, GPIOB, GPIO_PIN_7,
         7,0x50,1,
         	    I2C_SW_Slave_Address_7Bit,
        I2C_SW_One_Byte,
        I2C_SW_One_Byte,
    };
    IIC_Init( &sIIC  );

    if (!IIC_Device_Check(&sIIC))
        log_i( "hello i2c_address= 0x%02X (7bit) is exist\r\n", sIIC.addr);
 
    IIC_Write_Buf( &sIIC,  0, writein, 1 );
    HAL_Delay( 200 );

    IIC_Read_Buf(&sIIC,  0, readout, 1 );

    log_i("iic test  %02X .... \r\n ", *readout);

*/