#include "lt_fdc2214_iic.h"
#include "stm32l4xx_hal.h"
#include "main.h"

SoftI2C_HandleTypeDef hi2c1 = {
    .SDA_Port = GPIOB,
    .SDA_Pin = IIC_SDA_Pin,
    .SCL_Port = GPIOB,
    .SCL_Pin = IIC_SCL_Pin
};

SoftI2C_HandleTypeDef hi2c2 = {
    
		.SDA_Port = GPIOB,
    .SDA_Pin = IIC_SDA2_Pin,
    .SCL_Port = GPIOB,
    .SCL_Pin = IIC_SCL2_Pin
};


extern TIM_HandleTypeDef htim15;

void SoftI2C_Init(SoftI2C_HandleTypeDef* hi2c)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = hi2c->SCL_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(hi2c->SCL_Port, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = hi2c->SDA_Pin;
    HAL_GPIO_Init(hi2c->SDA_Port, &GPIO_InitStruct);

    HAL_GPIO_WritePin(hi2c->SCL_Port, hi2c->SCL_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(hi2c->SDA_Port, hi2c->SDA_Pin, GPIO_PIN_SET);
}

static void FDC2214_SDA_IN(SoftI2C_HandleTypeDef* hi2c)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = hi2c->SDA_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;  
	HAL_GPIO_Init(hi2c->SDA_Port, &GPIO_InitStruct);
	
}
static void FDC2214_SDA_OUT(SoftI2C_HandleTypeDef* hi2c)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = hi2c->SDA_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	HAL_GPIO_Init(hi2c->SDA_Port, &GPIO_InitStruct);
}

static void SDA_Write(SoftI2C_HandleTypeDef* hi2c, GPIO_PinState state) {
    HAL_GPIO_WritePin(hi2c->SDA_Port, hi2c->SDA_Pin, state);
}

static void SCL_Write(SoftI2C_HandleTypeDef* hi2c, GPIO_PinState state) {
    HAL_GPIO_WritePin(hi2c->SCL_Port, hi2c->SCL_Pin, state);
}

static GPIO_PinState SDA_Read(SoftI2C_HandleTypeDef* hi2c) {
    return HAL_GPIO_ReadPin(hi2c->SDA_Port, hi2c->SDA_Pin);
}

void delay_us(uint32_t us)
{
	uint16_t start = __HAL_TIM_GET_COUNTER(&htim15);
  while((__HAL_TIM_GET_COUNTER(&htim15) - start) < us);
}

void FDC2214_IIC_Start(SoftI2C_HandleTypeDef* hi2c) {
		FDC2214_SDA_OUT(hi2c);
    SDA_Write(hi2c, GPIO_PIN_SET);
    SCL_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SDA_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
}

void FDC2214_IIC_Stop(SoftI2C_HandleTypeDef* hi2c) {
		FDC2214_SDA_OUT(hi2c);
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
    SDA_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SDA_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
}

uint8_t FDC2214_IIC_Wait_Ack(SoftI2C_HandleTypeDef* hi2c) {
    uint8_t waitTime = 0;
		FDC2214_SDA_IN(hi2c);
    SDA_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    while (SDA_Read(hi2c)) {
        waitTime++;
        if (waitTime > 250) {
            FDC2214_IIC_Stop(hi2c);
            return 1;
        }
    }
    SCL_Write(hi2c, GPIO_PIN_RESET);
    return 0;
}

void FDC2214_IIC_Ack(SoftI2C_HandleTypeDef* hi2c) {
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
		FDC2214_SDA_OUT(hi2c);
    SDA_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
}

void FDC2214_IIC_NAck(SoftI2C_HandleTypeDef* hi2c) {
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
		FDC2214_SDA_OUT(hi2c);
    SDA_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_SET);
    delay_us(2);
    SCL_Write(hi2c, GPIO_PIN_RESET);
    delay_us(2);
}

void FDC2214_IIC_Send_Byte(SoftI2C_HandleTypeDef* hi2c, uint8_t dat) {
    
		FDC2214_SDA_OUT(hi2c);
		SCL_Write(hi2c, GPIO_PIN_RESET);
    for (uint8_t t = 0; t < 8; t++) {
				delay_us(2);
        if (dat & 0x80)
            SDA_Write(hi2c, GPIO_PIN_SET);
        else
            SDA_Write(hi2c, GPIO_PIN_RESET);
        dat <<= 1;
        delay_us(2);
        SCL_Write(hi2c, GPIO_PIN_SET);
        delay_us(2);
        SCL_Write(hi2c, GPIO_PIN_RESET);
        delay_us(2);
    }
}

uint8_t FDC2214_IIC_Read_Byte(SoftI2C_HandleTypeDef* hi2c, uint8_t ack) {
    uint8_t receive = 0;
    SDA_Write(hi2c, GPIO_PIN_SET);
		FDC2214_SDA_IN(hi2c);
    for (uint8_t i = 0; i < 8; i++) {
        receive <<= 1;
        SCL_Write(hi2c, GPIO_PIN_RESET);
        delay_us(2);
        SCL_Write(hi2c, GPIO_PIN_SET);
        delay_us(2);
        if (SDA_Read(hi2c)) receive++;
    }
    SCL_Write(hi2c, GPIO_PIN_RESET);
    if (ack)
        FDC2214_IIC_NAck(hi2c);
    else
        FDC2214_IIC_Ack(hi2c);
    return receive;
}

