#include "iic.h"

// 宏定义
#define SDA_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET)
#define SDA_LOW()  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET)
#define SCL_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET)
#define SCL_LOW()  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET)
#define SDA_READ() HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)

void I2C_Delay(void) {
    for (volatile int i = 0; i < 120; i++); // 简单延时
}

void I2C_Start(void) {
    SDA_HIGH();
    SCL_HIGH();
    I2C_Delay();
    SDA_LOW();// 当SCL为高电平时，SDA从高变低表示开始信号
    I2C_Delay();
    SCL_LOW();// 开始信号传送完毕，拉低SCL准备数据传输
}

void I2C_Stop(void) {
    SDA_LOW();
    SCL_HIGH();// 当SCL为高电平时，SDA从低变高表示停止信号
    I2C_Delay();
    SDA_HIGH();
    I2C_Delay();
}

void I2C_SendByte(uint8_t byte) {
    for (uint8_t i = 0; i < 8; i++) {
        if (byte & 0x80) {
            SDA_HIGH();
        } else {
            SDA_LOW();
        }
        SCL_HIGH();// 在SCL上升沿时，数据稳定在SDA线上
        I2C_Delay();
        SCL_LOW();// 在SCL下降沿时，SDA可以改变状态
        I2C_Delay();
        byte <<= 1;
    }
}

//uint8_t I2C_ReadByte(void) {
//    uint8_t byte = 0;
//    SDA_HIGH(); // Release SDA for reading

//    for (uint8_t i = 0; i < 8; i++) {
//        SCL_HIGH();
//        I2C_Delay();
//        byte = (byte << 1) | SDA_READ();
//        SCL_LOW();
//        I2C_Delay();
//    }

//    return byte;
//}

uint8_t I2C_WaitAck(void) {
    uint8_t ack;
    SDA_HIGH();  // 释放 SDA 线，准备接收ACK
    SDA_InputMode(); // 切换为输入模式，接收ACK
    SCL_HIGH();
    I2C_Delay();
    ack = SDA_READ(); // 读取ACK信号
    SCL_LOW();
    SDA_OutputMode(); // 恢复 SDA 为输出模式
    return (ack == GPIO_PIN_RESET); // 返回ACK状态
}

void Soft_I2C_Write(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
    I2C_Start();
    I2C_SendByte(devAddr << 1); // 发送设备地址+写位
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_SendByte(regAddr);      // 发送寄存器地址
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_SendByte(data);         // 发送数据
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_Stop();
}

void Soft_I2C_Read(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
    I2C_Start();
    I2C_SendByte(devAddr << 1); // 发送设备地址+写位
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_SendByte(regAddr);      // 发送寄存器地址
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_Start();                // 重启总线
    I2C_SendByte((devAddr << 1) | 1); // 发送设备地址+读位
    if (!I2C_WaitAck()) return; // 等待ACK
    *data = I2C_ReadByte();     // 读取数据
    I2C_Stop();
}

void Soft_I2C_ReadMulti(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t count) {
    I2C_Start();
    I2C_SendByte(devAddr << 1); // 发送设备地址+写位
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_SendByte(regAddr);      // 发送寄存器地址
    if (!I2C_WaitAck()) return; // 等待ACK
    I2C_Start();                // 重启总线
    I2C_SendByte((devAddr << 1) | 1); // 发送设备地址+读位
    if (!I2C_WaitAck()) return; // 等待ACK
    while (count--) {
        *data++ = I2C_ReadByte();  // 读取多字节数据
    }
    I2C_Stop();
}
void SDA_InputMode(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void SDA_OutputMode(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
uint8_t I2C_ReadByte(void) {
    uint8_t byte = 0;
    SDA_InputMode(); // 切换SDA为输入模式

    for (uint8_t i = 0; i < 8; i++) {
        SCL_HIGH();
        I2C_Delay();
        byte = (byte << 1) | SDA_READ();// 从MSB开始读取
        SCL_LOW();
        I2C_Delay();
    }

    SDA_OutputMode(); // 恢复SDA为输出模式
    return byte;
}

