#include "pca9555.h" 

Pca9555::Pca9555(I2C *i2c) 
{
	i2c_pca9555 = i2c;
	setAllIn(); 
}

uint8_t Pca9555::readPin(uint8_t bank, uint8_t pin)
{
	if(bank == 0)
	{
		pinIo0State = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_INPUT_PORT_0_REG); 
		return getBitUint8(&pinIo0State, pin);	
	}
	else if(bank == 1) 
	{
		pinIo1State = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_INPUT_PORT_1_REG); 
		return getBitUint8(&pinIo1State, pin);	
	}
	else 
	{
		throwError(bankInvalid); 
	}
	throwError(oufOfLoop);
	return 2;
}

void Pca9555::writePin(uint8_t bank, uint8_t pin, uint8_t value)
{
	if(bank == 0)
	{
		pinIo0State = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_OUTPUT_PORT_0_REG); 
		if(value == 0)
		{
			unsetBitUint8(&pinIo0State, pin);	
		}
		else if (value == 1) 
		{
			setBitUint8(&pinIo0State, pin);	
		}
		else 
		{
			throwError(invalidOut);
		}
		
		i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_0_REG,pinIo0State); 
	}
	else if(bank == 1) 
	{
		pinIo1State = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_INPUT_PORT_1_REG); 
		if(value == 0)
		{
			unsetBitUint8(&pinIo1State, pin);	
		}
		else if (value == 1) 
		{
			setBitUint8(&pinIo1State, pin);	
		}
		else 
		{
			throwError(invalidOut);
		}

		i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_1_REG,pinIo1State); 
	}
	else 
	{
		throwError(bankInvalid); 
	}
}

void Pca9555::setPin(uint8_t bank, uint8_t pin, uint8_t direction)
{
	if(bank == 0)
	{
		pinIo0Direction = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_CONFIG_0_REG); 
		if(direction == 0)
		{
			unsetBitUint8(&pinIo0Direction, pin);	
		}
		else if (direction == 1) 
		{
			setBitUint8(&pinIo0Direction, pin);	
		}
		else 
		{
			throwError(invalidDir);
		}
		
		i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_0_REG,pinIo0Direction); 
	}
	else if(bank == 1) 
	{
		pinIo1Direction = i2c_pca9555->readByte(PCA9555_ADDR,PCA9555_CONFIG_1_REG); 
		if(direction == 0)
		{
			unsetBitUint8(&pinIo1Direction, pin);	
		}
		else if (direction == 1) 
		{
			setBitUint8(&pinIo1Direction, pin);	
		}
		else 
		{
			throwError(invalidDir);
		}
		
		i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_1_REG,pinIo1Direction); 
	}
	else 
	{
		throwError(bankInvalid); 
	}
}

void Pca9555::setPinPolarity(uint8_t bank, uint8_t pin, uint8_t polarity)
{

}

uint8_t Pca9555::getInterrupt()
{
	return 0;
}

void Pca9555::setAllOut()
{
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_0_REG,0x00); 
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_1_REG,0x00); 
}

void Pca9555::setAllIn()
{
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_0_REG,0xFF); 
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_CONFIG_1_REG,0xFF); 
}

void Pca9555::setAllHigh()
{
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_0_REG,0xFF); 
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_1_REG,0xFF); 
}
void Pca9555::setAllLow()
{
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_0_REG,0x00); 
	i2c_pca9555->writeWord(PCA9555_ADDR,PCA9555_OUTPUT_PORT_1_REG,0x00); 
}

void Pca9555::throwError(Pca9555::errors error)
{
	#ifdef LINUX
		std::cout << "Linux Pca9555 Error No:" << error << std::endl; 
		exit(1); 
	#endif
}
