#include "SoftI2C.h"

#include "stm32f4xx_hal.h"

void Soft_I2C_Init() {}

void Soft_I2C_Transmit(uint8_t address, uint8_t* databuffer,
                       uint8_t bufferlength) {
  uint8_t nack = 0;

  setSDCLK(); // Generate Start Condition
  bitwait();
  setSDA(0);
  bitwait();

  for (int i = 0; i < 8; i++) // Write I2C-Slave Address
  {
    setSDA((address >> (7 - i) & 0x01));
    bitwait();
    resetSDCLK();
    bitwait();
    setSDCLK();
    bitwait();
  }

  SDA_ReadMode();
  resetSDCLK();
  bitwait();
  nack += readSDA();
  bitwait();
  SDA_WriteMode();
  setSDA(0);
  setSDCLK();
  bitwait();

  for (int n = 0; n < bufferlength; n++) // Write Data
  {

    for (int i = 0; i < 8; i++) {
      setSDA((databuffer[n] >> (7 - i) & 0x01));
      bitwait();
      resetSDCLK();
      bitwait();
      setSDCLK();
      bitwait();
    }

    SDA_ReadMode();
    resetSDCLK();
    bitwait();
    nack += readSDA();
    bitwait();
    SDA_WriteMode();
    setSDA(0);
    setSDCLK();
    bitwait();
  }

  resetSDCLK(); // Generate Stop Condition
  bitwait();
  setSDA(1);
  bitwait();
}

void Soft_I2C_Receive(uint8_t address, uint8_t* databuffer,
                      uint8_t bufferlength) {
  uint8_t nack = 0;

  setSDCLK(); // Generate Start Condition
  bitwait();
  setSDA(0);
  bitwait();

  for (int i = 0; i < 8; i++) // Write I2C-Slave Address
  {
    setSDA((address >> (7 - i) & 0x01));
    bitwait();
    resetSDCLK();
    bitwait();
    setSDCLK();
    bitwait();
  }

  SDA_ReadMode();
  resetSDCLK();
  bitwait();
  nack += readSDA();
  bitwait();

  for (int n = 0; n < bufferlength; n++) {
    databuffer[n] = 0;
    for (int i = 0; i < 8; i++) {
      setSDCLK();
      bitwait();
      resetSDCLK();
      bitwait();
      databuffer[n] |= readSDA() << (7 - i);
      bitwait();
    }

    setSDCLK();
    bitwait();

    SDA_WriteMode();
    setSDA(0);
    bitwait();
    resetSDCLK();
    bitwait();
    SDA_ReadMode();
  }

  resetSDCLK(); // Generate Stop Condition
  bitwait();
  setSDA(1);
  bitwait();
}

void SDA_WriteMode() {}

void SDA_ReadMode() {}

void setSDA(uint8_t state) {}

uint8_t readSDA() {}

void bitwait() {}
void setSDCLK() {}
void resetSDCLK() {}