#include "IIC2_Software.h"

//#define _IIC2_MAX_FREQ_ //350Khz

#ifdef _IIC2_MAX_FREQ_
#define IIC2_SPEED 0
#endif

//{Freq}: 96Mhz
//#define IIC2_SPEED   7    //800khz
#define IIC2_SPEED   10    //600khz
//#define IIC2_SPEED   13    //500khz
//#define IIC2_SPEED   18    //400khz
//#define IIC2_SPEED   25   //300kHz
//#define IIC2_SPEED   43   //200khz
//#define IIC2_SPEED   80   //110khz

u8 iic2_speed_us = 0; //235kHz 默认
//修改IIC speed
void IIC2_Set_Speed(u8 i2c_speed)
{
    //修改IIC延时时间
    iic2_speed_us = i2c_speed;
}
void IIC2_sf_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );

    GPIO_InitStructure.GPIO_Pin = MS1826_SDA | MS1826_SCL;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    IIC2_SCL(1);
    IIC2_SDA(1);
    IIC2_Set_Speed(IIC2_SPEED);
    //PRINT("IIC2 Speed:%d\n", iic2_speed_us);
    //PRINT("IIC Speed: %d Khz\n", 350); //fix
    //test();
}

void IIC2_Delay(u8 time)
{
    u8 i;
    for (i = 0; i < time; i++)
    {__NOP();}
}

//产生IIC start 信号
void IIC2_Start(void)
{
    SDA2_OUT();     //sda output
    IIC2_SDA(1);
    IIC2_SCL(1);
    IIC2_Delay(iic2_speed_us);
    IIC2_SDA(0);//START:when CLK is high,DATA change form high to low
    IIC2_Delay(iic2_speed_us);
    IIC2_SCL(0);//钳住IIC总线，准备发送或接收data
}

//产生IIC stop信号
void IIC2_Stop(void)
{
    SDA2_OUT();//sda output
    IIC2_SCL(0);
    IIC2_SDA(0);//STOP:when CLK is high DATA change form low to high
    IIC2_Delay(iic2_speed_us); //至少4us 表示空闲
    IIC2_SCL(1);
    IIC2_SDA(1);//send IIC 总线 stop 信号
    IIC2_Delay(iic2_speed_us); //至少4us 表示空闲
}

//wait 应答信号到来
//返回值：1，接收应答失败
//       0，接收应答成功
u8 IIC2_Wait_Ack(void)
{
    u8 ucErrTime=0;
    SDA2_IN();      //SDA input
    IIC2_SDA(1);IIC2_Delay(iic2_speed_us);
    IIC2_SCL(1);IIC2_Delay(iic2_speed_us);
    while(READ2_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC2_Stop();//等待从机应答超时，send stop
            return 1;
        }
    }
    IIC2_SCL(0);//scl output 0
    return 0;
}

//产生ACK应答
void IIC2_Ack(void)
{
    IIC2_SCL(0);
    SDA2_OUT();
    IIC2_SDA(0);
    IIC2_Delay(iic2_speed_us);
    IIC2_SCL(1);
    IIC2_Delay(iic2_speed_us);
    IIC2_SCL(0);
}

//不产生ACK应答
void IIC2_NAck(void)
{
    IIC2_SCL(0);
    SDA2_OUT();
    IIC2_SDA(1);
    IIC2_Delay(iic2_speed_us);
    IIC2_SCL(1);
    IIC2_Delay(iic2_speed_us);
    IIC2_SCL(0);
}

//IIC send one byte
//返回从机有无应答：1，有应答 0，无应答
#pragma GCC optimize(1)
void IIC2_Send_Byte(u8 txd)
{
    u8 t;
    SDA2_OUT();
    IIC2_SCL(0);//拉低scl开始data传输
    for(t=0;t<8;t++)
    {
        if((txd<<t)&0x80)
            IIC2_SDA(1);
        else
            IIC2_SDA(0);
        //IIC2_Delay(2);   //某些器件延时是必须的
        #ifdef _IIC2_MAX_FREQ_
            __NOP();
        #else
            IIC2_Delay(iic2_speed_us);
        #endif
        IIC2_SCL(1);
        //IIC2_Delay(2);
        #ifdef _IIC2_MAX_FREQ_
            __NOP();
        #else
            IIC2_Delay(iic2_speed_us);
        #endif
        IIC2_SCL(0);
        //IIC2_Delay(2);
    }
}

//read one byte, ack = 1, send ACK, ack = 0, send NACK
u8 IIC2_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA2_IN();//set SDA input
    for(i=0;i<8;i++ )
    {
        IIC2_SCL(0);
        #ifdef _IIC2_MAX_FREQ_
            __NOP();
        #else
            IIC2_Delay(iic2_speed_us);
        #endif
        IIC2_SCL(1);
        receive<<=1;
        if(READ2_SDA)receive++;
        #ifdef _IIC2_MAX_FREQ_
            __NOP();
        #else
            IIC2_Delay(iic2_speed_us);
        #endif
    }
    if (!ack)
        IIC2_NAck();//send NACK
    else
        IIC2_Ack(); //send ACK
    return receive;
}

//check IIC address: 1, 成功 0, 失败
u8 IIC2_Check_Address(u8 Address)
{
    IIC2_Start();
    IIC2_Send_Byte(Address);
    if(IIC2_Wait_Ack())
    {
        IIC2_Stop();
        return (0);
    }
    IIC2_Stop();
    return (1);
}

//send many bytes: 8bit address + 8bit register + n bytes data
u8 IIC2_Send_8bitMultiBytes(u8 address, u8 reg, u8 *str, u8 num)
{
    u8 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg);
    if(IIC2_Wait_Ack()) return (0);

    for(i=0; i<num; i++)
    {
        IIC2_Send_Byte(*str);
        if(IIC2_Wait_Ack()) return (0);
        str++;
    }
    IIC2_Stop();
    return (1);
}

//read many bytes: 8bit address + 8bit register + n bytes data
u8 IIC2_Read_8bitMultiBytes(u8 address, u8 reg, u8 *str, u8 num)
{
    u8 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg);
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Start();
    IIC2_Send_Byte(address+1);
    if(IIC2_Wait_Ack()) return (0);
    for(i=0; i<num; i++)
    {
        *str = IIC2_Read_Byte(i == (num-1) ? 0 : 1);
        str++;
    }

    IIC2_Stop();
    return (1);
}

//send many bytes(send low byte first): 8bit address + 16bit register + n bytes data
u8 IIC2_Send_16bit_LE_MultiBytes(u8 address, u16 reg, u8 *str, u16 num)
{
    u16 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Send_Byte(reg & 0xFF); // Send the low byte of reg
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg >> 8);   // Send the high byte of reg
    if(IIC2_Wait_Ack()) return (0);

    for(i=0; i<num; i++)
    {
        IIC2_Send_Byte(*str);
        if(IIC2_Wait_Ack()) return (0);
        str++;
    }
    IIC2_Stop();
    return (1);
}

//read many bytes(send low byte first): 8bit address + 16bit register + n bytes data
u8 IIC2_Read_16bit_LE_MultiBytes(u8 address, u16 reg, u8 *str, u8 num)
{
    u8 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Send_Byte(reg & 0xFF); // Send the low byte of reg
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg >> 8);   // Send the high byte of reg
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Start();
    IIC2_Send_Byte(address+1);
    if(IIC2_Wait_Ack()) return (0);
    for(i=0; i<num; i++)
    {
        *str = IIC2_Read_Byte(i == (num-1) ? 0 : 1);
        str++;
    }

    IIC2_Stop();
    return (1);
}

//send many bytes(send high byte first): 8bit address + 16bit register + n bytes data
u8 IIC2_Send_16bit_BE_MultiBytes(u8 address, u16 reg, u8 *str, u8 num)
{
    u8 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Send_Byte(reg >> 8);   // Send the high byte of reg
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg & 0xFF); // Send the low byte of reg
    if(IIC2_Wait_Ack()) return (0);

    for(i=0; i<num; i++)
    {
        IIC2_Send_Byte(*str);
        if(IIC2_Wait_Ack()) return (0);
        str++;
    }
    IIC2_Stop();
    return (1);
}

//read many bytes(send high byte first): 8bit address + 16bit register + n bytes data
u8 IIC2_Read_16bit_BE_MultiBytes(u8 address, u16 reg, u8 *str, u8 num)
{
    u8 i;
    IIC2_Start();
    IIC2_Send_Byte(address);
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Send_Byte(reg >> 8);   // Send the high byte of reg
    if(IIC2_Wait_Ack()) return (0);
    IIC2_Send_Byte(reg & 0xFF); // Send the low byte of reg
    if(IIC2_Wait_Ack()) return (0);

    IIC2_Start();
    IIC2_Send_Byte(address+1);
    if(IIC2_Wait_Ack()) return (0);
    for(i=0; i<num; i++)
    {
        *str = IIC2_Read_Byte(i == (num-1) ? 0 : 1);
        str++;
    }

    IIC2_Stop();
    return (1);
}

