#include "stdio.h"

#include "i2c.h"
  
void
i2c_port::Initialize(unsigned paddr, unsigned iaddr)
{
  par_port::Initialize(paddr);
  i2c_addr = iaddr;
#ifdef debug
  printf("i2cport Initialize. Port: %04x i2c: %02x\n", paddr, iaddr);
#endif
  SetSCL(true);
  SetSDA(true);
}

void
i2c_port::SetSDA(bool state)
{
  SetDataBit(I2C_SDAOUT, state ^ I2C_INV_SDAOUT);
}

bool
i2c_port::GetSDA(void)
{
  return GetStatusBit(I2C_SDAIN) ^ I2C_INV_SDAIN;
}

void
i2c_port::SetSCL(bool state)
{
  SetControlBit(I2C_SCLOUT, state ^ I2C_INV_SCLOUT);
}

bool i2c_port::GetSCL(void)
{
  return GetStatusBit(I2C_SCLIN) ^ I2C_INV_SCLIN;
}

void i2c_port::Start(void)
{
  SetSDA(false);
  SetSCL(false);
}

void i2c_port::Stop(void)
{
  SetSDA(false);
  SetSCL(true);
  SetSDA(true);
}

bool i2c_port::ByteSent(unsigned char b)
{
  int bit;

#ifdef debug
  printf("ByteSent: %02x\n", b);
#endif
  for (bit = 7; bit >= 0; bit--) {
    SetSDA((b & (1 << bit)) != 0);
    SetSCL(true);
    SetSCL(false);
#ifdef debug
    printf("%d", (b and (1 << bit)) != 0);
#endif
  }
#ifdef debug
  printf("\n");
#endif
  SetSDA(true);
  SetSCL(true);
  SetSCL(false);
  return !GetSDA();
}

bool i2c_port::ByteReceived(unsigned char *b)
{
  int bit;
  unsigned char data;

  *b = 0;
  SetSDA(true);			// Be sure to float the SDA line
  for (bit = 0; bit <=7; bit++) {
    SetSCL(true);
    *b = (*b << 1);
    if (GetSDA())
      data = data | 1;
    SetSCL(false);
  }
  SetSDA(false);		// Send ACK to peripheral
  SetSCL(true);
  SetSCL(false);
  return true;
}

bool
i2c_port::Responds(void)
{
  bool ok = false;
  Start();
  if (ByteSent(i2c_addr + I2C_READ))
    ok = true;
  Stop();

  return ok;
}


unsigned
i2c_port::Geti2cAddr(void)
{
  return i2c_addr;
}
