#ifndef _I2C_H_
#define _I2C_H_

namespace serial
{
	enum i2c_id
	{
		i2c_ch0, 
		i2c_ch1
	}; 	

	//
	// Base template class
	//

	template<i2c_id id>
	class I2C
	{
		public:
		I2C(const uint8_t& mode); // Mode : Master or Slave
		uint8_t readByte(const uint8_t& address, const uint8_t& reg); 
		uint16_t readWord(const uint8_t& address, const uint8_t& reg); 
		uint8_t writeByte(const uint8_t& address, const uint8_t& data); 
		uint8_t writeWord(const uint8_t& address, const uint8_t& reg, const uint16_t& data);	

		private:
	};
	
	// 
	// Template for channel 0
	//
	template<>
	class I2C <i2c_ch0>
	{
		public:
			I2C(const uint8_t& mode):pImpL(mode)
			{
			}
			uint8_t readByte(const uint8_t& address, const uint8_t& reg)
			{
				return pImpL -> readByte(address, reg); 
			}
			uint16_t readWord(const uint8_t& address, const uint8_t& reg)
			{
				return pImpL -> readWord(address,reg); 
			}
			uint8_t writeByte(const uint8_t& address, const uint8_t& data)
			{
				return pImpL -> writeByte(address, data); 
			}
			uint8_t writeWord(const uint8_t& address, const uint8_t& reg, const uint16_t& data)
			{
				return pImpL -> writeWord(address, reg, data); 
			}

		private:
			class i2c_ch0_pImpL; 
			std::unique_ptr<i2c_ch0_pImpL> pImpL; 
	};
	
	// 
	// Template for channel 1
	//
	template<>
	class I2C <i2c_ch1>
	{
		public:
			I2C(const uint8_t& mode):pImpL(mode)
			{
			}
			uint8_t readByte(const uint8_t& address, const uint8_t& reg)
			{
				return pImpL -> readByte(address, reg); 
			}
			uint16_t readWord(const uint8_t& address, const uint8_t& reg)
			{
				return pImpL -> readWord(address,reg); 
			}
			uint8_t writeByte(const uint8_t& address, const uint8_t& data)
			{
				return pImpL -> writeByte(address, data); 
			}
			uint8_t writeWord(const uint8_t& address, const uint8_t& reg, const uint16_t& data)
			{
				return pImpL -> writeWord(address, reg, data); 
			}

		private:
			class i2c_ch1_pImpL; 
			std::unique_ptr<i2c_ch1_pImpL> pImpL; 
	};

}// Namespace serial


#endif // _I2C_H_
