//I2C用制御関数
//作成日：2011/03/20
//作成者：KK
//電子工作の実験室のプログラム「18ctesta.c」参考

#include<p18f4620.h>
#include<delays.h>		//遅延関数ヘッダ
#include<i2c.h>			//I2C用ライブラリヘッダ
#include"i2c_c18.h"		//I2C用ヘッダファイル


/*=====I2C書き込み関数=====*/
//EEPROM 32Kbit〜512Kbitデバイス用。128bit〜16Kbitはアドレス出力部分変更。
//関数名：i2c_write
/*
control・・・コントロールデータ
adress・・・・EEPROMアドレス(2Byte)
data・・・・・・書き込みデータ
*/
unsigned char i2c_write(unsigned char control,unsigned int address,unsigned char data){
	
	IdleI2C();						//アイドル状態確認
	SSPCON2bits.SEN=1;				//Start Condition出力
	while(SSPCON2bits.SEN);			//Start Condition終了待ち
	if(PIR2bits.BCLIF){				//バス衝突フラグチェック
		return(-1);					//衝突エラー
	}
	else{
		SSPBUF=control & 0xFE;		//コントロール書き込みモード出力
		while(SSPSTATbits.BF);		//データ送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-2);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPBUF=address >> 8;		//EEPROMアドレス上位バイト出力
		while(SSPSTATbits.BF);		//送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-3);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPBUF=address;				//EEPROMアドレス下位バイト出力
		while(SSPSTATbits.BF);		//送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-4);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPBUF=data;				//書き込みデータ出力
		while(SSPSTATbits.BF);		//送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-5);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPCON2bits.PEN=1;			//STOP Condition出力
		while(SSPCON2bits.PEN);		//STOP Condition終了待ち
		PIR1bits.SSPIF=0;			//SSPIFクリア
		if(PIR2bits.BCLIF){			//バス衝突チェック
			return(-6);				//衝突エラー発生
		}
		return(0);					//正常終了
	}
}

/*=====I2C読み込み関数=====*/
//EEPROM 32Kbit〜512Kbitデバイス用。128bit〜16Kbitはアドレス出力部分変更。
//関数名：i2c_read
/*
control・・・コントロールデータ
adress・・・・EEPROMアドレス(2Byte)
*/
unsigned int i2c_read(unsigned char control,unsigned int address){
	
	IdleI2C();						//アイドル状態確認
	SSPCON2bits.SEN=1;				//Start Condition出力
	while(SSPCON2bits.SEN);			//Start Condition終了待ち
	if(PIR2bits.BCLIF){				//バス衝突フラグチェック
		return(-1);					//衝突エラー
	}
	else{
		SSPBUF=control & 0xFE;		//コントロール書き込みモード出力
		while(SSPSTATbits.BF);		//データ送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-2);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPBUF=address >> 8;		//EEPROMアドレス上位バイト出力
		while(SSPSTATbits.BF);		//送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-3);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPBUF=address;				//EEPROMアドレス下位バイト出力
		while(SSPSTATbits.BF);		//送信待ち
		IdleI2C();					//アイドル状態確認
		if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
			return(-4);				//ACK無し
		}
		PIR1bits.SSPIF=0;			//SSPIFクリア
		
		SSPCON2bits.RSEN=1;			//RESTART Condition出力
		while(SSPCON2bits.RSEN);	//RESTART Condition送信待ち
		if(PIR2bits.BCLIF){			//バス衝突チェック
			return(-5);				//衝突エラー発生
		}
		else{
			SSPBUF=control & 0xFF;		//コントロール読み込みモード出力
			while(SSPSTATbits.BF);		//送信待ち
			IdleI2C();					//アイドル状態確認
			if(SSPCON2bits.ACKSTAT){	//ACK受信待ち
				return(-6);				//ACK無し
			}
			PIR1bits.SSPIF=0;			//SSPIFクリア	
			
			SSPCON2bits.RCEN=1;			//マスターモード1Byte受信
			while(SSPCON2bits.RCEN);	//受信完了待ち
			SSPCON2bits.ACKDT=1;		//ACKを返信しない
			SSPCON2bits.ACKEN=1;		//バス衝突クリア
			while(SSPCON2bits.ACKEN);	//ACK送信
			PIR1bits.SSPIF=0;			//SSPIFクリア	
		
			SSPCON2bits.PEN=1;			//STOP Condition出力
			while(SSPCON2bits.PEN);		//STOP Condition終了待ち
			PIR1bits.SSPIF=0;			//SSPIFクリア
			if(PIR2bits.BCLIF){			//バス衝突チェック
				return(-7);				//衝突エラー発生
			}
			else{
				return((unsigned int)SSPBUF);	//正常終了
			}	
		}
	}	
}
