/*****************************************************************************/
/* FILE NAME: main.c                            COPYRIGHT (c) Freescale 2010 */
/*                                                       All Rights Reserved */
/*  																		 */
/* MPC5668 Example Projects Suite											 */
/* Low Power Mode - Derived from AN4150										 */
/*																			 */
/* Revision History															 */
/* 		Rev: 1.0 		Author:	Steven McLaughlin  		DATE: 23/07/2010 	 */
/*																			 */
/* Example demonstrates low power sleep mode entry and exit from a pin.    	 */
/* PA0 is used for sleep entry and PB4 is used to exit sleep mode			 */
/*****************************************************************************/

/***************************** Includes **************************************/
#include "mpc5668.h"
#include "typedefs.h"		 		    

/****************************** Global variables ******************************/
int PIN_NUMBER_SLEEP = 16;						
int CLOCK_FREQ = 16000000;

/****************************** Function Prototypes ***************************/
extern void execute_wait(void);
void enter_sleep_mode (void);
void led_on(int time_on, int pin_number);
void led_off(int time_off, int pin_number);
void setup_pin(void);

/********************************* Main ***************************************/
void main(void)
{
	setup_pin();
	CRP.PWKENL.R = 0x00000002; 						/* Enable Positive Edge on PB4 as Wake */
 
	while(1)
	{
		led_off(100,16);
		led_on(100,16);
		
		if (SIU.GPDI[0].R == 1) 					/* PA0 = 1 go to sleep mode */
		{   
			enter_sleep_mode();	
			CRP.PSCR.B.SLEEPF = 0x1;				/* Clear sleep flags to allow pads to operate */
			CRP.PWKSRCF.R = 0x00000002;				/* Clear the wake up flag */
			setup_pin();							/* Reconfig Pins - SIU Reset after Sleep */
		}
	} 
}

/****************************** Enter Sleep Mode ******************************/
void enter_sleep_mode (void)
{

    CRP.PSCR.B.SLEEP = 1;                     		/* Confirm Sleep Mode Required */
    CRP.Z6VEC.B.Z6VECB = 0x40000;                   /* Write Z6VEC register */
    CRP.Z6VEC.B.VLE = 0x0;                       	/* set for non-VLE Wake code */
  
    SIU.HLT0.R = 0x037FFF3D;         				/* Halt all modules except Z6 and Z0 */
    SIU.HLT1.R = 0x18000F3C;            			/* Halt all modules except Z6 and Z0 */
	
    while((SIU.HLTACK0.R != 0x037FFF3D) && (SIU.HLTACK1.R != 0x18000F3C)); /* Wait for Halt to Complete */

    CRP.PSCR.B.RAMSEL = 0x3;	              		/* All RAM maintained in SLEEP */
    CRP.RECPTR.B.FASTREC = 0x1;
    
    CRP.Z0VEC.B.Z0RST = 1;                          /* Put Z0 core into reset */
    SIU.SYSCLK.B.SYSCLKSEL = 0;	         		    /* Switch system clock to 16MHz IRC */
    FMPLL.ESYNCR1.B.CLKCFG = 0;                     /* Disable PLL */
    CRP.PSCR.B.WKCLKSEL = 0x1;               		/* 16MHz IRC Used for wake edge */

    SIU.PCR[16].R = 0x3;             				/* Pull up enabled due to connected LED */

    execute_wait(); 								/* save data to stack and enter sleep mode */
}

/*****************************************************************************/
/* FUNCTION: led_on                                                     	 */
/* PURPOSE : Drives the output pin to 0 (LED on) for a time defined          */
/*		  	 by the parameter "time_on".				     				 */
/*****************************************************************************/
void led_on(int time_on, int pin_number)
{
	int x = 0;

	SIU.GPDO[pin_number].R = 0x0;
	time_on = (CLOCK_FREQ * time_on)/10000;

	for(x=0; x<time_on; x++)
	{
	asm("nop");
	}

	time_on = 0;
}

/*****************************************************************************/
/* FUNCTION : led_off                                                        */
/* PURPOSE  : Drives the output pin to 1 (LED off) for a time defined        */
/*			  by the parameter "time_off".               				 	 */
/*****************************************************************************/
void led_off(int time_off, int pin_number)
{
	int x = 0;
	
	SIU.GPDO[pin_number].R = 0x1;
	time_off = (CLOCK_FREQ * time_off)/10000;
	
	for(x=0; x<time_off; x++)
	{
		asm("nop");
	}
	time_off = 0;
}

/*****************************************************************************/
/* FUNCTION     : setup_pin                                                  */
/* PURPOSE      : Configures the PCR settings for the pins used in this	     */
/*                test.                                                      */
/*****************************************************************************/
void setup_pin()
{   
 SIU.PCR[0].R = 0x0102;							/* PA0 Input for Sleep Entry */
 SIU.PCR[16].R = 0x303;							/* PB0 For signal LED's */
 SIU.PCR[20].R = 0x0100; 						/* PB4 Wake pin IBE = 1 */
}

