/*****************************************************************************/
/* FILE NAME: main.c                            COPYRIGHT (c) Freescale 2010 */
/*                                                       All Rights Reserved */
/*  									     								 */
/* MPC5668 Example Projects Suite					     					 */
/* I2C Examples							            						 */
/*									    									 */
/* Revision History														     */
/*      Rev: 1.0 		Author:	Martin Vaupel	DATE: 12/10/2010    		 */
/*									     									 */
/* Example demonstrates the use of the I2C module. The user will vary the    */
/* blink frequency of an LED using a push button to increase an internal     */
/* counter up to 3. The counter variable is permanently send from I2C module */
/* A to I2C module B end eventually used to vary the frequency of the	     */
/* blinking LED.							    							 */
/*									   									     */
/*****************************************************************************/

/****************************** Includes *************************************/
#include "mpc5668.h"
/***************************** Global variables ******************************/
uint32_t a, b, i, counter;
/****************************** Function Prototypes **************************/
void initI2C(void);
int transmitI2C (int);
void PLLinit(void);

/* I2C parameters */
#define slave_address		  (0x6E)

/********************************* Main *************************************/
void main (void) 
{
	PLLinit();            			/* Init PLL to 128Mhz w 40MHz XTAL */
	initI2C();

	counter= 1;
	b = 100000;

	/* LED and Switch port init */
	SIU.PCR[64].R=0x0100;			/* IBE on PE0 - switch connection */
	SIU.PCR[65].R=0x0200;			/* OBE on PE1 - LED connection */
	
	/* wait a little bit*/
	i = 10000;
	while(i--);
	
	while(1)
	{
	if (SIU.GPDI[64].R == 1)    	/* used to increase internal counter via PE0 */
		{
			counter++;
			if (counter > 3)
			{
				counter=1; 
			}
		}
	
	counter=transmitI2C(counter);	/* send and receive counter via I2C */
	
	for (a=0; a<b*counter; a++);	/* loops to toggle PE1 */
	SIU.GPDO[65].R = 1;		
	for (a=0; a<b*counter; a++);
	SIU.GPDO[65].R = 0x00;
	}
}/* end of main() */

//**************************** Functions*******************************************

void initI2C(void) 
{
    /* Set transmission frequency 0x9C = 100kHz -based on 128Mhz Fsys */
    I2C_A.IBFD.R = 0x9C;

    /* Set module I2C addresses */
    I2C_B.IBAD.R = slave_address;

    /* Configure modules to idle (but active) state */
    I2C_A.IBCR.R = 0;
    I2C_B.IBCR.R = 0;

    /* Configure pads */
    SIU.PCR[78].R = 0x0733;		/* PE14: Alt.F.: 1 -> SCL_A, OBE, IBE, ODE, HYS, WPE, WPS */
    SIU.PCR[79].R = 0x0733;     /* PE15: SDA_A */
    SIU.PCR[100].R = 0x0933;	/* PG4: Alt.F.: 2 -> SCL_B, OBE, IBE, ODE, HYS, WPE, WPS */
    SIU.PCR[101].R = 0x0933;    /* PG5: SDA_B */
}

int transmitI2C (int data_send)
{
	int data_rec;
	I2C_A.IBSR.R |= 0x02;		/* reset interrupt flag */
    
	/* Make sure bus is idle -> IBB must be cleared*/
	while (I2C_A.IBSR.B.IBB);
	
	/* generate start condition by setting transmit and master */
	I2C_A.IBCR.R = 0x30;
	
	/* Wait for IBSR.IBB (bus busy) to be set */
	while (!(I2C_A.IBSR.B.IBB));
		
	/* Put target address into IBDR */
	I2C_A.IBDR.R = slave_address;
	
	/* Wait for address transfer to complete */
	while (!(I2C_A.IBSR.B.IBIF));
	I2C_A.IBSR.R |= 0x02;
	
	/* Dummy read of IBDR to signal the module is ready for the next byte */
	data_rec = I2C_B.IBDR.R;
		
	/* Send data */
	I2C_A.IBDR.R = data_send;

	/* Wait for address transfer to complete */
	while (!(I2C_A.IBSR.B.IBIF));
	I2C_B.IBSR.R |= 0x02;
	
	/* Restore module A to its idle (but active) state */
	I2C_A.IBCR.R = 0;	        /* stop transmission */
	
	/* Wait for IBSR.IBB (bus busy) to be set */
	while (!(I2C_A.IBSR.B.IBB));
	
	data_rec = I2C_B.IBDR.R;
	
	return data_rec;
}

void PLLinit(void)
{  	
	int ERFD = 3;
	int EPREDIV = 9;
	int EMFD = 112;

	/* Select IRC as CLK Source */ 
	SIU.SYSCLK.B.SYSCLKSEL = 0x0;

	/* Configure PLL CTRL Regs */
	FMPLL.ESYNCR1.B.CLKCFG = 0x7; 
	FMPLL.ESYNCR2.B.ERFD = ERFD+2;
	FMPLL.ESYNCR1.B.EPREDIV = EPREDIV;       
	FMPLL.ESYNCR1.B.EMFD = EMFD;         

	/* Wait for PLL to lock */ 
	while(FMPLL.SYNSR.B.LOCK != 1);

	/* Change pll up to final freq */
	FMPLL.ESYNCR2.B.ERFD = ERFD;	

	/* Switch from IRC to PLL */ 
	SIU.SYSCLK.B.SYSCLKSEL = 0x2;
	
} /* End of PLLinit */