/******************************************************************************
								    Copyright (c) Freescale 2010
File Name    :  main.c

Current Revision :	Revision: 2.0 

PURPOSE: main program entry.                       
                                                                          
DataSheet : MC9S12G64RMV1.0.pdf
                                                                       
DESCRIPTION:  function main() providing initial program entry.
                                                         
                                                                          
UPDATE HISTORY                                                            
REV  AUTHOR    DATE        DESCRIPTION OF CHANGE                          
---  ------    --------    ---------------------                          
1.0  r28318    17/09/09    - initial coding
2.0  b30269    06/30/11    - S12G64 Migration and IRQ feature added. 

 *******************************************************************
 * File created by: Freescale East Kilbride MSG Applications Group *
 *******************************************************************


                                                                          
******************************************************************************/
/*===========================================================================*/
/* Freescale reserves the right to make changes without further notice to any*/
/* product herein to improve reliability, function, or design. Freescale does*/
/* not assume any  liability arising  out  of the  application or use of any */
/* product,  circuit, or software described herein;  neither  does it convey */
/* any license under its patent rights  nor the  rights of others.  Freescale*/
/* products are not designed, intended,  or authorized for use as components */
/* in  systems  intended  for  surgical  implant  into  the  body, or  other */
/* applications intended to support life, or  for any  other application  in */
/* which the failure of the Freescale product  could create a situation where*/
/* personal injury or death may occur. Should Buyer purchase or use Freescale*/
/* products for any such intended  or unauthorized  application, Buyer shall */
/* indemnify and  hold  Freescale  and its officers, employees, subsidiaries,*/
/* affiliates,  and distributors harmless against all claims costs, damages, */
/* and expenses, and reasonable  attorney  fees arising  out of, directly or */
/* indirectly,  any claim of personal injury  or death  associated with such */
/* unintended or unauthorized use, even if such claim alleges that  Freescale*/
/* was negligent regarding the  design  or manufacture of the part. Freescale*/
/* and the Freescale logo* are registered trademarks of Freescale Ltd.       */
/*****************************************************************************/

/************************* Include Files *************************************/
/*general includes */
#include <hidef.h>  /* also includes boolean definitions in stdtypes.h     */
#include "derivative.h"     /* derivative information */
#include "target.h" 
#include "S12_peripherals.h" /* includes peripherals definitions and FSL data types */

/************************* typedefs ******************************************/
typedef enum
{
   RUN_M = 0,
   STOP_M,
   PSEUDO_STOP_M
	 
} CLK_TEST_MODES;

/************************* #defines ******************************************/
#define SW1_RUN_MODE            0xE0
#define SW2_PSEUDO_STOP_MODE    0xD0
#define SW3_STOP_MODE           0xB0
#define SW4_SWITCH_MODE         0x70


#define HIGHER_NIBBLE_MASK      0xF0
#define S_BIT_CLR_MASK          0x7F
#define TRNS_OFF                0x04

/* SCI baud rate = SCI bus clock / (16 * SCInBR[12:0])*/
#define SCI_25MHZ_9600_BR       0x0A2
#define SCI_16MHZ_9600_BR       0x068
#define SCI_08MHZ_9600_BR       0x034
#define SCI_04MHZ_9600_BR       0x01A

#define OUTPUT   1
#define INPUT    0

#define ENABLE   1

/****************** Constants *****************************************/
#pragma CONST_SEG DEFAULT

/************************* Global Variables **********************************/
#pragma DATA_SEG DEFAULT

CLK_TEST_MODES Current_Test_Mode = SW1_RUN_MODE;

/************************* function prototypes *******************************/
#pragma CODE_SEG DEFAULT

/************************* Functions *****************************************/
#pragma CODE_SEG DEFAULT
/******************************************************************************
Function Name  : Service_WD
Engineer       : b30269	
Date           : 14/10/10
Parameters     : NONE
Returns        : NONE
Notes          : COP time-out period is restarted. using sequence stated in: 
                 MC9S12XHY256RMV1.11.pdf, 7.4.1.5 Computer Operating Properly 
                 Watchdog (COP). 
                  
******************************************************************************/
void Service_WD(void)
{
   CPMUARMCOP = 0x55; 
   CPMUARMCOP = 0xAA;
}

/******************************************************************************
Function Name  : main
Engineer       : b30269	
Date           : 14/10/10
Parameters     : NONE
Returns        : NONE
Notes          : main routine called by Startup.c.
                 This function will configure CPMU module in the S12G64 MC to
                 demonstrate the following modes:
                 
                 RUN_MODE
                 PSEUDO_STOP_MODE
                 STOP_MODE
                 SELF_CLK_MODE
                 
                 Previous modes are selected via Reset and Switches.
                  
******************************************************************************/
unsigned int   outer_counter;		
unsigned int   inner_counter;   

void main(void) 
{

   PTP_PTP0       = 1;               /* Initialize PP0 High; turn off LED1                         */
   PTP_PTP3       = 1;               /* Initialize PP3 High; turn off LED4                         */
   DDRP_DDRP0     = OUTPUT;          /* PORTP 0 = output                                           */
   DDRP_DDRP3     = OUTPUT;          /* PORTP 3 = output                                           */

   PER1AD   = (HIGHER_NIBBLE_MASK | TRNS_OFF); /* Enable pull ups on Switches 1-4, and Transceiver Force Off */
   ATDDIENL = HIGHER_NIBBLE_MASK;              /* Enable digital input buffer on ANx pin                     */
     
   /* Configure AD7 "PAD15" port as outputs to drive MAX3387 FORCEOFF pin */        
   DDR0AD_DDR0AD7 = OUTPUT;
   /* Disable all AD port interrupts */
   PIE01AD        = 0x0000;                              
   /* Enable MAX3387 FORCEOFF = 1   */   
   PT0AD_PT0AD7   = ENABLE;
   
   /* Wait for pull ups to come into effect */
   for (outer_counter=0; outer_counter<1000; outer_counter++)
   {	
      for (inner_counter=0; inner_counter<100; inner_counter++)
      {
         ;                      /* Intentionally left empty                                   */ 
      } 
   }

   CPMUCOP   = CPMUCOP_CR_MASK; /* set WD period to max allowed ,                             */
																																									  
   Service_WD();			          /* Refresh WD for first time                                  */
   
   asm ANDCC #S_BIT_CLR_MASK    /* Enable STOP mode, clear S bit                              */

   EnableInterrupts;
   
   switch (PT01AD & HIGHER_NIBBLE_MASK)
   {
      case SW1_RUN_MODE: 

         
         CPMUOSC_OSCE = 1; /* enable ext osc */         
         
         /* 
            Initialise the system clock from a 8 MHz Crystal, 
            25 MHz Bus CLK (50 MHz VCO, 50 MHz PLL)  
         */
                
         CPMUSYNR    = 0x58;     /* SYNDIV = 3, VCO frequency 48 - 80 MHz  */       

         CPMUREFDIV  = 0x07;     /* REFDIV = 07, REFCLK frequency 6-12 MHz */       

         CPMUPOSTDIV = 0x00;     /* POSTDIV = 0 FPLL = FVCO                */

         while(!CPMUFLG_LOCK)
         {
            ;                    /* wait for VCO to stabilize              */
         }			 
         
         Service_WD();
         
         CPMUCLKS_PLLSEL = 1;    /* Switch clk to use PLL                  */

         Current_Test_Mode = RUN_M;		   
         /* Configure the SCI to run at 9600 baud and Tx Clock Mode and Clock speeds */

         SCI_Config(SCI_25MHZ_9600_BR);
         DisplayString("TWR-S12G64 Demo Board Running Normal Mode");
         LF;
         DisplayString("50 MHz VCO Clock, 50 MHz PLL Clock, 25 MHz Bus Clock, from 8 MHz Crystal");
         LF;
         LF;          
    
         break;
      
      case SW2_PSEUDO_STOP_MODE:
      
         
         CPMUOSC_OSCE = 1; /* enable ext osc */
         
         /* 
            Initialise the system clock for Pseudo Stop Mode 
            - 32MHz VCO, 16MHz PLL, 8MHz Bus CLK, from 8MHz Crystal 
         */
				 
         CPMUSYNR    = 0x01;     /* SYNDIV = 1, VCO frequency 32 - 48 MHz         */

         CPMUREFDIV  = 0x80;     /* REFDIV = 10 REFCLK frequency 6-12 MHz         */     

         CPMUPOSTDIV = 0x01;     /* POSTDIV = 1                                   */

         while(!CPMUFLG_LOCK)
         {                        
            ;                    /* wait for VCO to stabilize                     */
         }			 
         
         Service_WD();
         
         CPMUCLKS_PLLSEL = 1;    /* Switch clk to use PLL                         */
       	 
       	 CPMUCLKS_PSTP   = 1;    /* Enable pseudo stop mode                       */
     	 
      	 Current_Test_Mode = PSEUDO_STOP_M;     	 
      	 
      	 /* 
      	    Configure IRQ interrupt to wake MCU 
      	    This requires to have HW set up done for this test: connect IRQ pin to 
      	    VDD, when the MCU enters to sleep after pressing SW4, disconect IRQ pin
      	    from VDD and connect it to GND, this wakes up the MCU, and LED4 starts 
      	    toggling at a 10Hz rate.      	 
      	 */
         IRQCR_IRQE  = 1;         /* Enable IRQ on falling edge */
         IRQCR_IRQEN = 1;         /* Enable IRQ Interrupt       */

      	 Current_Test_Mode = PSEUDO_STOP_M;     	 
      	 
      	 /* 
      	    Configure the SCI to run at 9600 baud and Tx Clock Mode and Clock speeds 
      	 */

         SCI_Config(SCI_08MHZ_9600_BR);
         DisplayString("TWR-S12G64 Demo Board Running PSEUDO STOP Mode");
         LF;
         DisplayString("32 MHz VCO Clock, 16 MHz PLL Clock, 8 MHz Bus Clock, from 8 MHz Crystal");
         LF;
         LF;
         
         DisplayString("Press SW4 to enter to pseudo STOP mode, MCU will get out of pseudo stop mode after IRQ is set to GND");
         LF;
         LF;

         break;
      
      case SW3_STOP_MODE:
                    
         
         CPMUOSC_OSCE = 1; /* enable ext osc */         
         /* 
            Initialise the system clock to Stop mode - 32 MHz VCO, 
            32 MHz PLL Clock, 16 MHz bus CLK, from 8MHz External Clock 
         */
				 
         CPMUSYNR    = 0x01;      /* SYNDIV = 1, VCO frequency 48 - 64 MHz   */

         CPMUREFDIV  = 0x80;      /* REFDIV = 10 REFCLK frequency 6-12MHz    */ 

         CPMUPOSTDIV = 0x00;      /* POSTDIV = 0                             */

         while(!CPMUFLG_LOCK)
         {
            ;                      /* wait for VCO to stabilize              */
         }			 
         
         CPMUCLKS_PLLSEL = 1;      /* Switch clk to use PLL                  */
         
         Service_WD();
         
         Current_Test_Mode = STOP_M;
      	 
      	 CPMUCLKS_PSTP = 0;    /* Disable pseudo stop mode                             */
      	 CPMUCLKS_PCE  = 0;    /* COP stops running during pseudo stop mode            */
       
         
         /* Configure the SCI to run at 9600 baud and Tx Clock Mode and Clock speeds */

         SCI_Config(SCI_16MHZ_9600_BR);
         DisplayString("TWR-S12G64 Demo Board Running User Configured STOP Mode");
         LF;
         
         DisplayString("64 MHz VCO Clock, 32 MHz PLL Clock, 16 MHz Bus Clock, from 8 MHz External Clock");
         LF;
         LF;
         
         DisplayString("Press SW4 to enter to STOP mode, MCU will restart after RESET button is pressed");
         LF;
         LF;
      
         break;
      
      default: /* Run Mode 8MHz Bus Clk */
      {
         
         
         CPMUOSC |= 0x80; /* enable ext osc */
         
         /* 
            Initialise the system clock to Stop mode - 32 MHz VCO, 
            16 MHz PLL freq 8 MHz bus CLK, from 8MHz External Clock 
         */
				 
         CPMUSYNR    = 0x01;  /* SYNDIV = 1, VCO frequency 48 - 64 MHz  */
                    
         CPMUREFDIV  = 0x80;  /* REFDIV = 10 REFCLK frequency 6-12MHz   */ 
                    
         CPMUPOSTDIV = 0x01;  /* POSTDIV = 0                            */

         while(!CPMUFLG_LOCK)
         {
            ;                     /* wait for VCO to stabilize              */
         }			 
         
         CPMUCLKS_PLLSEL = 1;     /* Switch clk to use PLL                  */    	 
         
         
         Service_WD();
         
         Current_Test_Mode = RUN_M;
         /* Configure the SCI to run at 9600 baud and Tx Clock Mode and Clock speeds */
				 SCI_Config(SCI_08MHZ_9600_BR);
         
         DisplayString("TWR-S12G64 Demo Board Running DEFAULT Mode");
         LF;
         
         DisplayString("System clocks are derived from OSCCLK (fBUS = fOSC / 2)");
         LF;
         DisplayString("Loop controlled Pierce Oscillator is selected");
         LF;
         DisplayString("8MHz Bus Clock");
         LF;
         LF;
    
         break;
       
      }/* default */
   }/* switch */
      
   ECLKCTL_NECLK = 0;         /* Enable ECLK = Bus Clock, on PS7                     */                   

   for(;;)
   {
      PTP ^= PTP_PTP0_MASK;
      
      /* Delay to see LED1 toggle */
      for (outer_counter = 0; outer_counter < 2000; outer_counter++)
  	  {	
   		   for (inner_counter = 0; inner_counter < 500; inner_counter++)
  		   {
  		      ;              /* Intentionally left empty */
  		   } 
	    }
      /* SW4 polling to determine if STOP request is needed */
      if((PT01AD & HIGHER_NIBBLE_MASK) == SW4_SWITCH_MODE)
      {        
         if((PSEUDO_STOP_M == Current_Test_Mode) ||
           (STOP_M         == Current_Test_Mode)) 
         {

            PTP_PTP0 = 1;  /* Turn off LED1 */
            PTP_PTP3 = 1;  /* Turn off LED4 */
            
            asm(STOP);
         }
      }
      Service_WD();      
   }/* for */ 		
}/* main */


/******************************************************************************
Function Name  : IRQIsr
Engineer       : b30269	
Date           : 14/10/10
Parameters     : NONE
Returns        : NONE
Notes          : This routine is executed after a Hi-Low transition is detected
                 at IRQ pin.
                 This function will toggle for ever LED4 at a 10Hz rate.
                 To re-start the program and excecute a different case user 
                 must reset the device.
                                   
******************************************************************************/
#pragma CODE_SEG NON_BANKED
#pragma TRAP_PROC
__interrupt VectorNumber_Virq void IRQIsr(void)
{ 
   uint x;

   for(;;)
   {
      PTP ^= PTP_PTP3_MASK; 
      for(x =0; x < 0xffff;x++)
      {
        ;
      }
      Service_WD();
   }
}

#pragma CODE_SEG DEFAULT


