#include "board.h"
#include <stdbool.h>

/* Low-Level I2C Routines */

static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };

static void i2c_delay()
{
	volatile int v;
	int i;

	/* 100 cycles results in SCL peak length of 44us, so it's about
	 * 440ns per cycle here */
	for (i = 0; i < 14; i++) {
		v = 0;
	}
}

void i2c_pin_init(void)
{
	PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
	PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
}

static void set_scl(void)
{
	PIO_Set(&pin_scl);
	i2c_delay();
}

static void set_sda(void)
{
	PIO_Set(&pin_sda);
	i2c_delay();
}

static void clear_scl(void)
{
	PIO_Clear(&pin_scl);
	i2c_delay();
}

static void clear_sda(void)
{
	PIO_Clear(&pin_sda);
	i2c_delay();
}

static bool read_sda(void)
{
	bool ret;

	PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
	if (PIO_Get(&pin_sda_in))
		ret = true;
	else
		ret = false;
	PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));

	return ret;
}

/* Core I2C Routines */

static bool i2c_started = false;

static void i2c_start_cond(void)
{
	if (i2c_started) {
		set_sda();
		set_scl();
	}

	clear_sda();
	i2c_delay();
	clear_scl();
	i2c_started = true;
}

static void i2c_stop_cond(void)
{
	clear_sda();
	set_scl();
	set_sda();
	i2c_delay();
	i2c_started = false;
}

static void i2c_write_bit(bool bit)
{
	if (bit)
		set_sda();
	else
		clear_sda();
	i2c_delay(); // ?
	set_scl();
	clear_scl();
}

static bool i2c_read_bit(void)
{
	bool bit;

	set_sda();
	set_scl();
	bit = read_sda();
	clear_scl();

	return bit;
}

bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
{
	uint8_t bit;
	bool nack;

	if (send_start)
		i2c_start_cond();

	for (bit = 0; bit < 8; bit++) {
		i2c_write_bit((byte & 0x80) != 0);
		byte <<= 1;
	}

	nack = i2c_read_bit();

	if (send_stop)
		i2c_stop_cond();

	return nack;
}

uint8_t i2c_read_byte(bool nack, bool send_stop)
{
	uint8_t byte = 0;
	uint8_t bit;

	for (bit = 0; bit < 8; bit++) {
		byte = (byte << 1) | i2c_read_bit();
	}

	i2c_write_bit(nack);

	if (send_stop)
		i2c_stop_cond();

	return byte;
}


/* EEPROM related code */

int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
	bool nack;

	WDT_Restart(WDT);

	/* Write slave address */
	nack = i2c_write_byte(true, false, slave << 1);
	if (nack)
		goto out_stop;
	nack = i2c_write_byte(false, false, addr);
	if (nack)
		goto out_stop;
	nack = i2c_write_byte(false, true, byte);
	if (nack)
		goto out_stop;

out_stop:
	i2c_stop_cond();
	if (nack)
		return -1;
	else
		return 0;
}

int eeprom_read_byte(uint8_t slave, uint8_t addr)
{
	bool nack;

	WDT_Restart(WDT);

	/* dummy write cycle */
	nack = i2c_write_byte(true, false, slave << 1);
	if (nack)
		goto out_stop;
	nack = i2c_write_byte(false, false, addr);
	if (nack)
		goto out_stop;
	/* Re-start with read */
	nack = i2c_write_byte(true, false, (slave << 1) | 1);
	if (nack)
		goto out_stop;

	return i2c_read_byte(true, true);

out_stop:
	i2c_stop_cond();
	if (nack)
		return -1;
	else
		return 0;
}
