//File : IIC_EEPROM.h
/*------------------------------------------------------*/
/*	IIC EEPROM Read/Write								*/
/*	Sub routine for H8/3664N built in EEPROM			*/
/*  ルネサス　アプリケーションノート j512130_iic.pdf	*/
/*　より、若干の追加と変更を施した 						*/
/*  2008/6/28	by T.AZAMI								*/
/*------------------------------------------------------*/
//#include <machine.h>
//#include "iodefine.H"

#define DEVICE_CODE	0xa0			/* EEPROM DEVICE CODE:101 	*/
#define SLAVE_ADRS	0x00			/* SLAVE ADRS:0 	*/
#define IIC_DATA_W	0x00			/* WRITE_DATA 	*/
#define IIC_DATA_R	0x01			/* READ_DAT 	*/

#define WR_RETRY_CNT 10				/* tWC(1ms)*10=10ms 	*/
#define WR_OK	     11				/* loop break 	*/

unsigned char	Write_data_EEPROM( unsigned char wr_data );
unsigned char	Set_adrs_EEPROM( unsigned short adrs );
unsigned char	Recv_data1_EEPROM( void );
unsigned char	Recv_datan_EEPROM( unsigned char *rd_ptr , unsigned short no );
void			wait_e( unsigned int loop);

// ポートイニシャライズ
void EEPROM_init(){
	IO.PDR5.BIT.B6 = 0;							//　P56,P57がI2C用のバスライン
	IO.PDR5.BIT.B7 = 0;							//　P56,P57のデータは0にしておく
	IO.PCR5 = IO.PCR5 & 0x3F;					//　I2CでEEPROMを使う場合 P56,P57を入力に設定しておく
}

/*--------------------------------------------------------------*/
/*	Read_page_EEPROM	(8byte)				                    */
/*	Argument1: Read address(unsigned short)			            */
/*	Argument2: Storing read data address (unsigned char *)		*/
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)		*/
/*--------------------------------------------------------------*/
unsigned char Read_page_EEPROM( unsigned short adrs , unsigned char *rd_ptr ) {
	unsigned char	i,ack;
	
	IIC.ICCR.BYTE = 0x89;						/* ICE=1 P57,P56->SCL,SDA 	*/
	IIC.ICMR.BYTE = 0x08;
	TSCR.BYTE = 0xfc;
	
	ack = 0;
	while (IIC.ICCR.BIT.BBSY != 0);				/* Bus busy? 	*/
	ack = Set_adrs_EEPROM(adrs);				/* Addressing(dummy write)	*/
	if (ack == 0)	{
		IIC.ICCR.BIT.IRIC = 0;
		IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;	/* Generate stop condition 	*/
		return(0);
	}
	ack = Recv_datan_EEPROM(rd_ptr,8);			/* Data reading of 8 bytes 	*/
	return(ack);
}

/*------------------------------------------------------------------*/
/*	Read_page_EEPROM	(8byte)				                        */
/*	Argument1: Read address (unsigned short)			            */
/*	Argument2: Storing read data address (unsigned char *)		    */
/*	Argument3: Number of read data (unsigned short)			    	*/
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)			*/
/*------------------------------------------------------------------*/
unsigned char Read_n_EEPROM( unsigned short adrs , unsigned char *rd_ptr , unsigned short no ) {
	unsigned char	i,ack;
	
	IIC.ICCR.BYTE = 0x89;						/* ICE=1 P57,P56->SCL,SDA 	*/
	IIC.ICMR.BYTE = 0x08;
	TSCR.BYTE = 0xfc;

	ack = 0;
	while (IIC.ICCR.BIT.BBSY != 0);				/* Bus busy? 	*/
	ack = Set_adrs_EEPROM(adrs);				/* Addressing (dummy write) 	*/
	if (ack == 0) {
		IIC.ICCR.BIT.IRIC = 0;
		IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;	/* Generate stop condition 	*/
		return(0);
	}
	ack = Recv_datan_EEPROM(rd_ptr,no);			/* Data reading of n bytes 	*/
	return(ack);
}

/*------------------------------------------------------------------*/
/*	Write_page_EEPROM	(8byte)				                        */
/*	Argument1: Write address (unsigned short)			            */
/*	Argument2: Storing write data address (unsigned char *)		    */
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)			*/
/*------------------------------------------------------------------*/
unsigned char Write_page_EEPROM( unsigned short adrs , unsigned char *wr_ptr ) {
	unsigned char	loop,i,ack;

	ack = 0;
	loop = 0;
	while (loop <= WR_RETRY_CNT) {
		IIC.ICCR.BYTE = 0x89;					/* ICE=1(P57,P56->SCL,SDA) 	*/
		IIC.ICMR.BYTE = 0x08;
		TSCR.BYTE = 0xfc;
		while (IIC.ICCR.BIT.BBSY != 0);			/* Bus busy? 	*/
			ack = Set_adrs_EEPROM(adrs);		/* Addressing 	*/
			if ( ack == 1 ) {
				loop = WR_OK;
			}else {
				IIC.ICCR.BIT.IRIC = 0;
				IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;
												/* Generation of stop condition 	*/
				wait_e(1000);					/* tWC=1ms 	*/
				loop++;
			}
		}
		if (ack == 1) {
			IIC.ICCR.BIT.IRIC = 0;
			i = 0;
			while ((i < 8) && (ack == 1)) {
				ack = Write_data_EEPROM(*wr_ptr);
												/* Writing of data of 8 bytes 	*/
				wr_ptr++;
				i++;
			}
			IIC.ICCR.BIT.IRIC = 0;
			IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;
												/* Generation of stop condition 	*/
		}
		return(ack);
}

/*----------------------------------------------------------*/
/*	wait_e (Wait sub routine for EEPROM)			        */
/*	Argument1: Number of loops (unsigned short)				*/
/*	Return value: None					                    */
/*----------------------------------------------------------*/
void wait_e( unsigned int loop) {
	unsigned int	i;
	unsigned int 	dummy;
	for (i=0;i < loop;i++) {
		dummy++;
	}
}

/*----------------------------------------------------------*/
/*	Read_byte_EEPROM					                    */
/*	Argument1: Read address (unsigned short)				*/
/*	Return value: Read data (unsigned char)			        */
/*----------------------------------------------------------*/
unsigned char Read_byte_EEPROM( unsigned short adrs ) {
	unsigned char	data,ack;
	
	IIC.ICCR.BYTE = 0x89;						/* ICE=1 P57,P56->SCL,SDA 	*/
	IIC.ICMR.BYTE = 0x08;
	TSCR.BYTE = 0xfc;
	
	while (IIC.ICCR.BIT.BBSY != 0);				/* Bus busy? 	*/
	ack = Set_adrs_EEPROM(adrs);				/* Addressing (dummy write)	*/
	if (ack == 1)	{
		data = Recv_data1_EEPROM();
	}
	IIC.ICCR.BIT.IRIC = 0;
	IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;		/* Generate stop condition	 */
	return(data);
}

/*--------------------------------------------------------------*/
/*	Write_byte_EEPROM					                        */
/*	Argument1: Write address (unsigned short)			        */
/*	Argument2: Write data (unsigned char)			            */
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)		*/
/*--------------------------------------------------------------*/
unsigned char Write_byte_EEPROM( unsigned short adrs , unsigned char wr_data ) {
	unsigned char	loop,ack;
	
	ack = 0;
	loop = 0;
	while (loop <= WR_RETRY_CNT) {
		IIC.ICCR.BYTE = 0x89;					/* ICE=1(P57,P56->SCL,SDA) 	*/
		IIC.ICMR.BYTE = 0x08;
		TSCR.BYTE = 0xfc;
		//wait_e(30);
		while (IIC.ICCR.BIT.BBSY != 0);			/* Bus busy? 	*/
		ack = Set_adrs_EEPROM(adrs);
		if ( ack == 1 ) {
			loop = WR_OK;
		}else {
			IIC.ICCR.BIT.IRIC = 0;
			IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;
												/* Generate stop condition	 */
			wait_e(1000);						/* tWC=1ms 	*/
			loop++;
		}
	}
	if (ack == 1) {
		ack = Write_data_EEPROM(wr_data);
		IIC.ICCR.BIT.IRIC = 0;
		IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;	/* Generate stop condition 	*/
	}
	wait_e(10000);								// ここに10msのディレイを入れることで、正常に働くようになった
	return(ack);
}

/*--------------------------------------------------------------*/
/*	Write_data_EEPROM					                        */
/*	Argument1: Write address (unsigned short)			        */
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)		*/
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
/*  (BYTE WRITE ACTION)					                        */
/*			  <4>      				                            */
/*			  123456789				                            */
/*			  000000000				                            */
/*			  Write data A			                            */
/*--------------------------------------------------------------*/
unsigned char Write_data_EEPROM( unsigned char wr_data ) {

	/* <4> 	*/
	IIC.ICDR = wr_data;									/* <4> Set writing data 	*/
	IIC.ICCR.BIT.IRIC = 0;
	while (IIC.ICCR.BIT.IRIC == 0);						/* <4> Transmission complete? 	*/
	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 	*/
		return(0);
	}
	return(1);
}

/*--------------------------------------------------------------*/
/*	Set_adrs_EEPROM					                            */
/*	Argument1: Write / read address (unsigned short)		    */
/*	Return value: 1: OK / 0: NG EEPROM NOACK(unsigned char)		*/
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
/*  ADDRESS SET ACTION / DUMMY WRITE ACTION) 					*/
/*  <1>		<2> 	<3>											*/
/*  123456789 	123456789 	123456789 							*/
/*  101000000 	000000000 	000000000 							*/
/*  Slave WA 	Address HI A 	Address LO A 					*/
/*--------------------------------------------------------------*/
unsigned char Set_adrs_EEPROM( unsigned short adrs ) {
	unsigned char	ret;
	
	IIC.ICCR.BYTE |= 0x30;								/* Master transmission setting (MST=1,TRS=1) 	*/
	IIC.ICCR.BYTE = ((IIC.ICCR.BYTE & 0xfe) | 0x04);
														/* Generating of start condition 	*/
	while (IIC.ICCR.BIT.IRIC == 0);						/* Transmission OK? 		*/
														/* <1> 		*/
	IIC.ICDR = (unsigned char)(DEVICE_CODE | SLAVE_ADRS | IIC_DATA_W);
														/* <1>Slave address set 	*/
	IIC.ICCR.BIT.IRIC = 0;
	wait_e(30);

	while (IIC.ICCR.BIT.IRIC == 0);						/* <1> Transmission complete? 	*/

	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 		*/
		return(0);
	}
	wait_e(30);											/* <2> 		*/

	IIC.ICDR = (unsigned char)(adrs >> 8);				/* <2> Upper address set 	*/
	IIC.ICCR.BIT.IRIC = 0;
	wait_e(30);
	
	while (IIC.ICCR.BIT.IRIC == 0)						/* <2> Transmission complete? 	*/
	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 	*/
		return(0);
	}
														/* <3> 		*/
	IIC.ICDR = (unsigned char)(adrs & 0x00ff);			/* <3> Lower address set 	*/
	IIC.ICCR.BIT.IRIC = 0;
	wait_e(30);
	
	while (IIC.ICCR.BIT.IRIC == 0);						/* <3> Transmission complete? 	*/

	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 	*/
		return(0);
	}
	return(1);
}

/*------------------------------------------------------------------*/
/*	Recv_data1_EEPROM												*/
/*	Return value: Read data (unsigned char)							*/
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*  (CURRENT ADDRESS READ ACTION)									*/
/*  <1>		<2>      												*/
/*  123456789 	123456789											*/
/*  101000010 	000000000											*/
/*  Slave RA 	Read data A											*/
/*------------------------------------------------------------------*/
unsigned char Recv_data1_EEPROM( void ) {
	unsigned char	recv;

	IIC.ICCR.BYTE |= 0x30;								/* Master transmission setting (MST=1,TRS=1) 	*/
	IIC.ICCR.BYTE = ((IIC.ICCR.BYTE & 0xfe) | 0x04);
	wait_e(30);											/* Generating of start condition 	*/
	while (IIC.ICCR.BIT.IRIC == 0);						/* Transmission OK? 		*/

	IIC.ICDR = (unsigned char)(DEVICE_CODE | SLAVE_ADRS | IIC_DATA_R);
														/* <1> Slave address set 	*/
	IIC.ICCR.BIT.IRIC = 0;
	wait_e(30);
	
	while (IIC.ICCR.BIT.IRIC == 0);						/* <1> Transmission complete? 	*/

	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 		*/
		return(0);
	}
	wait_e(30);											/* dummy wait 		*/
														/* Master reception setting 	*/
	IIC.ICCR.BIT.TRS = 0;
	IIC.ICMR.BIT.WAIT = 1;
	IIC.ICSR.BIT.ACKB = 0;
	recv = IIC.ICDR;									/* dummy read 	*/
	IIC.ICCR.BIT.IRIC = 0;
	while (IIC.ICCR.BIT.IRIC == 0);						/* Reception complete? 	*/
														/* < The last reception > 	*/
	IIC.ICSR.BIT.ACKB = 1;
	IIC.ICCR.BIT.TRS = 1;
	IIC.ICCR.BIT.IRIC = 0;
	while (IIC.ICCR.BIT.IRIC == 0);						/* Reception complete? 	*/
	IIC.ICMR.BIT.WAIT = 0;
	recv = IIC.ICDR;									/* Received data read 	*/
	return(recv);
}
/*------------------------------------------------------------------*/
/*	Recv_datan_EEPROM												*/
/*	Argument1: Storing read data address (unsigned char *)			*/
/*	Argument2: Read byte number1-512 (unsigned char)				*/
/*	Return value: 1: OK / 0: NG EEPROM NOACK (unsigned char)		*/
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/*  (CURRENT ADDRESS READ ACTION)									*/
/*  <1>		<2>	<3>	<n>      										*/
/*  123456789 	123456789 	123456789   	123456789				*/
/*  101000010 	000000000 	000000000   	000000000				*/
/*  Slave RA 	Read data A 	Read data A   Read data A			*/
/*------------------------------------------------------------------*/
unsigned char Recv_datan_EEPROM( unsigned char *rd_ptr , unsigned short no ) {
	unsigned char	recv;
	
	IIC.ICCR.BYTE |= 0x30;								/* Master transmission setting (MST=1,TRS=1) */
	IIC.ICCR.BYTE = ((IIC.ICCR.BYTE & 0xfe) | 0x04);	/* Generating of start condition 	*/
	while (IIC.ICCR.BIT.IRIC == 0);						/* Transmission OK? 		*/
	IIC.ICDR = (unsigned char)(DEVICE_CODE | SLAVE_ADRS | IIC_DATA_R);
														/* <1> Slave address set	*/
	IIC.ICCR.BIT.IRIC = 0;
	while (IIC.ICCR.BIT.IRIC == 0);						/* <1> Transmission complete? 	*/

	if ( IIC.ICSR.BIT.ACKB != 0 ) {						/* ACK? 		*/
		return(0);
	}
	wait_e(30);											/* dummy wait 		*/
														/* Master reception setting 	*/
	IIC.ICCR.BIT.TRS = 0;
	IIC.ICMR.BIT.WAIT = 1;
	IIC.ICSR.BIT.ACKB = 0;
	
	recv = IIC.ICDR;									/* dummy read 		*/
	IIC.ICCR.BIT.IRIC = 0;	
	while (IIC.ICCR.BIT.IRIC == 0);						/* Reception complete? 	*/
	IIC.ICCR.BIT.IRIC = 0;
	while (1 < no) {
		while (IIC.ICCR.BIT.IRIC == 0);					/* Reception complete? 	*/
		*rd_ptr = IIC.ICDR;								/* Received data read 	*/
		IIC.ICCR.BIT.IRIC = 0;
		while (IIC.ICCR.BIT.IRIC == 0);					/* Reception complete?	*/
		rd_ptr++;										/* Storage address increment 	*/
		no--;
		if (1 < no) {
			IIC.ICCR.BIT.IRIC = 0;
		}
	}
														/* < The last reception >	*/
	IIC.ICSR.BIT.ACKB = 1;
	IIC.ICCR.BIT.TRS = 1;
	IIC.ICCR.BIT.IRIC = 0;
	while (IIC.ICCR.BIT.IRIC == 0)						/* Reception complete? 	*/

	IIC.ICMR.BIT.WAIT = 0;
	*rd_ptr = IIC.ICDR;									/* Received data read 	*/
	IIC.ICCR.BIT.IRIC = 0;
	IIC.ICCR.BYTE = IIC.ICCR.BYTE & 0xfa;				/* Generation of stop condition 	*/
	return(1);
}
