/************************************************************/
/* PROJECT NAME: I2C 	                                    */
/* Project:      LPC2100 Training course                    */
/* Engineer:     T Martin      tmartin@hitex.co.uk          */
/* Filename:     MAIN.C                                     */
/* Language:     C                      	                */
/* Compiler:     Keil ARM	V2.00b		                    */
/* Assembler:    					                        */
/*                                                          */
/************************************************************/
/* COPYRIGHT: Hitex UK Ltd 		2005						*/
/* LICENSE:   THIS VERSION CREATED FOR FREE DISTRIBUTION	*/
/************************************************************/
/* Function:                                                */
/*                                                          */
/* Interrupt driven I2C example for LPC2106                 */
/*															*/
/* The Transfer byte routine starts a single byte transfer  */
/*  on the I2C bus. The development board has two port 		*/
/* expanders one at address 0x42 with a 7 segment LCD a  	*/
/* second at 0x41 with a four switch header. The code reads	*/
/* the switches and writes the pattern to the LED's			*/
/*															*/	
/* Oscillator frequency 12.000 Mhz							*/
/* Target board MCB2100										*/
/************************************************************/

//In this work example no code has been removed just rebuild the code and run the simulation


#include <LPC210x.H> 
#include <stdarg.h>

void I2CISR (void)	__irq ;																			//I2C interrupt routine
void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...);			//Background call to start master send and receive byte transfers

unsigned char 	message[4] = {0x01,0x02,0x03,0x04};													
unsigned char	messageIn[4];
unsigned char 	*I2CData,
			 	I2Counter,
				I2CAddress,
				MemAddress,
				lock;		//Define Function prototypes and Global variables


int main(void)
{

lock = 0;									//Initilise the lock flag

VICVectCntl1 = 0x00000029;  				//select a priority slot for a given interrupt
VICVectAddr1 = (unsigned)I2CISR;			//pass the address of the IRQ into the VIC slot
VICIntEnable = 0x00000200;					//enable interrupt

PINSEL0  	 = 0x50; 						//Switch GPIO to I2C pins

I2SCLH 		 = 0x08;						//Set bit rate 14.7456Mhz/VPBDIV+SCLH+SCLL = 14.7456/4+8+8 = 57.6Khz
I2SCLL 		 = 0x08;

I2CTransferByte(0x40,0,4,message);			//write data to the I2C Memory
I2CTransferByte(0x40,0,0);					//set address to zero
I2CTransferByte(0x41,0,4,messageIn);		//read back data

while(1)
{
;
}
}


void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...)
{
va_list ap;
va_start(ap,count);

while(lock == 1)							//Wait for interrupt to signal end of I2C activity
{
;
}
lock 		= 1;                   			//Set I2C bus as active

I2CAddress 	= I2CAddr;						//Place address and data in Globals to be used by the interrupt
if(count >0)
{
I2CData  	= va_arg(ap,unsigned char *);
}
I2Counter	= count;
MemAddress	= MemAddr;
I2CONCLR 	= 0x000000FF;					//Clear all I2C settings
I2CONSET 	= 0x00000040; 					//Enable the I2C interface
I2CONSET 	= 0x00000020; 					//Start condition
va_end(ap);
}


void I2CISR (void)	__irq						//I2C interrupt routine
{

switch (I2STAT)								//Read result code and switch to next action
{
// Start and Send byte conditions

case ( 0x08):								//Start bit
I2CONCLR 	= 0x20;							//Clear start bit
I2DAT   	= I2CAddress; 					//Send address and write bit
break;

case (0x18):								//Slave address+W, ACK
I2DAT   	= MemAddress;					//Write Mem,ory start address to tx register
break;

case (0x20):								//Salve address +W, Not ACK
I2DAT   	= I2CAddress; 					//Resend address and write bi
break;

case (0x28):
if(I2Counter-->0)								//Data sent, Ack
{
I2DAT   	= *I2CData;						//Write data to tx register
I2CData++;
}
else
{
I2CONSET 	= 0x10;							//Stop condition
lock = 0;                       			//Signal end of I2C activity
}
break;

case (0x30)	:								//Data sent, NOT Ack
I2DAT   	= *I2CData;						//Write data to tx register
break;


//Receive byte conditions

case (0x40) :								//Slave Address +R, ACK
I2CONSET 	= 0x04;							//Enable ACK for data byte
break;

case (0x48) :								//Slave Address +R, Not Ack
I2CONSET 	= 0x20;							//Resend Start condition
break;

case (0x50) :								//Data Received, ACK 
if(--I2Counter>0)
{
*I2CData 	= I2DAT;
I2CData++;
}
else
{
I2CONSET 	= 0x10;							//Stop condition
lock 		= 0;                    		//Signal end of I2C activity							
}
break;

case (0x58):								//Data Received, Not Ack
I2CONSET 	= 0x20;							// Resend Start condition
break;

default :
break;

}

I2CONCLR 	= 0x08;							//Clear I2C interrupt flag
VICVectAddr = 0x00000000;					//Clear interrupt in 

}
