//#pragma LINK_INFO DERIVATIVE "mc9s12G64"

/******************************************************************************
													            Copyright (c) Freescale 2009
File Name    : $RCSfile: main.c,v $

Current Revision :	$Revision: 1.0 $

PURPOSE: main program entry.                       
                                                                          
                                                                       
DESCRIPTION:  function main() providing initial program entry.
              function PutChar() - Transmits a character
              function GetChar() - Receives a character
              function DisplayString() - Transmits a character string
              function EchoGetChar() - Receives a character and echos it back
              function DisplayInt() - Transmits an integer
              function DisplayByte() - Transmits a byte
              function char Number_2_ASCII() - converts a number into ASCII code
              function char ASCII_2_Number() - converst ASCII code into a number
                                                         
                                                                          
UPDATE HISTORY                                                            
REV  AUTHOR    DATE        DESCRIPTION OF CHANGE                          
---  ------    --------    ---------------------                          
1.0  r28318    05/10/09    - initial coding
2.0  b30269    22/06/11    - S12G64 migration and tests changed

     *******************************************************************
     * 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" 

/************************* typedefs ******************************************/

/************************* #defines ******************************************/
/* PORT LOGIC defines */
#define OUTPUT         1
#define INPUT          0
#define ENABLE         1

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

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

unsigned int  BaudRatePrescaler;

/************************* Function prototypes *******************************/
#pragma CODE_SEG DEFAULT

void CPMU_Init(void);
void PutChar (char);
char GetChar(void);
void DisplayString (signed char *textPointer);
char EchoGetChar(void);
void DisplayInt(unsigned int number, unsigned char field );
void DisplayByte (unsigned char displayByte);
unsigned char Number_2_ASCII(unsigned char Nibble);
unsigned char ASCII_2_Number(unsigned char ascii_char);
void Change_BR(unsigned long br);
/************************* Functions *****************************************/
#pragma CODE_SEG DEFAULT


/************************* Macros *****************************************/
#define FF DisplayString("\f")
#define LF DisplayString("\r\n")

/******************************************************************************
Function Name  : main
Engineer       : r28318	
Date           : 09/06/09
Parameters     : NONE
Returns        : NONE
Notes          : main routine called by Startup.c.
                 This routine configures at compilation time, corresponding baud
                 rate speed by changing the initialized value for Baud_Rate 
                 variable.
                 Additional functionality added to receive via terminal one of 
                 10 options to request SCI register value. 
******************************************************************************/


void main(void) 
{
   char          RegisterCase;
   unsigned int  x,y;
   static Bool   LoopForever = TRUE;
   
   
   unsigned long Baud_Rate = 9600;  
   
   
   /* Initialise the system clock - 25MHz Bus CLK, 8MHz Crystal */
   CPMU_Init();

   /* 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;

  		
                      
   /* Calculate the prescaler required to achieve the baud rate */
   

   Change_BR(Baud_Rate);
   
 	 SCI0CR1 = 0x00;  /* 8 Data Bits, 1 Start Bit, 1 Stop Bit, No Parity */

 	 SCI0CR2 = 0x0C;  /* Enable Tx and Rx */

   /* SCIASR1, SCIACR1, SCIACR2, SCISR1, SCISR2, SCIDRH & SCIDRL left at default values */

   while(LoopForever)
   {
      DisplayString("\nTWR-S12G64 Serial Communications Interface Demo");
      LF;
      LF;
      DisplayString("Register Configuration for ");
      DisplayInt((unsigned int)Baud_Rate,0);
      DisplayString(" Baud Rate");
      LF;
      LF;
      DisplayString("Select Register to display");
      LF;
      LF;
      DisplayString("  0 - SCIBDH    1 - SCIBDL");
      LF;
      DisplayString("  2 - SCICR1    3 - SCIASR1");
      LF;
      DisplayString("  4 - SCIACR1   5 - SCIACR2");
      LF;
      DisplayString("  6 - SCICR2    7 - SCISR1");
      LF;
      DisplayString("  8 - SCISR2    9 - SCIDRH");
      LF;
      DisplayString("  A - SCIDRL    B - BR 19200 ");
      LF;
      DisplayString("  C - BR 38400  D - BR 40000 ");
      LF;
      DisplayString("  E - BR 57600  F - BR 9600  ");
      LF;
      LF;
      DisplayString("Choose Options B - F to change SCI baud rate ");
      LF;
      DisplayString("E.g. Enter 'B', change terminal baud, then enter 'y'");
      LF;      
      RegisterCase = EchoGetChar();
      LF;
      LF;
   
      switch (RegisterCase) 
      {
         case '0':
            DisplayString("SCI0BDH = ");
            DisplayByte(SCI0BDH);
            LF;
         break;

         case '1':
            DisplayString("SCI0BDL = ");
            DisplayByte(SCI0BDL);
            LF;
         break;
         
         case '2':
            DisplayString("SCI0CR1 = ");
            DisplayByte(SCI0CR1);
            LF;
         break;
         case '3':
            SCI0SR2_AMAP = 1;
            DisplayString("SCI0ASR1 = ");
            DisplayByte(SCI0ASR1);
            LF;
            SCI0SR2_AMAP = 0;
         break;
         case '4':
            SCI0SR2_AMAP = 1;
            DisplayString("SCI0ACR1 = ");
            DisplayByte(SCI0ACR1);
            LF;
            SCI0SR2_AMAP = 0;
         break;
         case '5':
            SCI0SR2_AMAP = 1;
            DisplayString("SCI0ACR2 = ");
            DisplayByte(SCI0ACR2);
            LF;
            SCI0SR2_AMAP = 0;
         break;
         case '6':
            DisplayString("SCI0CR2 = ");
            DisplayByte(SCI0CR2);
            LF;
         break;
         case '7':
            DisplayString("SCI0SR1 = ");
            DisplayByte(SCI0SR1);
            LF;
         break;
         case '8':
            DisplayString("SCI0SR2 = ");
            DisplayByte(SCI0SR2);
            LF;
         break;
         case '9':
            DisplayString("SCI0DRH = ");
            DisplayByte(SCI0DRH);
            LF;
         break;
         case 'A':
            DisplayString("SCI0DRL = ");
            DisplayByte(SCI0DRL);
            LF;
         break;         
         
/* -------------------- SELECT NEW BAUD RATE --------------------------------*/         
         
         case 'B':                        
            DisplayString("Change your Baud rate to 19200 and enter 'y' when ready ");
            LF;
            DisplayString("Enter: ");
            Baud_Rate = 19200;
            
            Change_BR(Baud_Rate);
            
            while(RegisterCase != 'y')
            {
               RegisterCase = EchoGetChar();  
            }                        

            LF;            
            DisplayString("New Baudrate is ");
            DisplayInt((unsigned int)Baud_Rate,0);
            DisplayString(" Baud Rate");            
            LF;
         break;
         case 'C':
            DisplayString("Change your Baud rate to 38400 and enter 'y' when ready ");
            LF;
            DisplayString("Enter: ");
            Baud_Rate = 38400;
            
            Change_BR(Baud_Rate);
            
            while(RegisterCase != 'y')
            {
               RegisterCase = EchoGetChar();  
            }                        

            LF;            
            DisplayString("New Baudrate is ");
            DisplayInt((unsigned int)Baud_Rate,0);
            DisplayString(" Baud Rate");            
            LF;

         break;
         case 'D':
            DisplayString("Change your Baud rate to 56000 and enter 'y' when ready ");
            LF;
            DisplayString("Enter: ");
            Baud_Rate = 56000;
            
            Change_BR(Baud_Rate);
            
            while(RegisterCase != 'y')
            {
               RegisterCase = EchoGetChar();  
            }                        

            LF;            
            DisplayString("New Baudrate is ");
            DisplayInt((unsigned int)Baud_Rate,0);
            DisplayString(" Baud Rate");                        
            LF;
            
         break;
         case 'E':
            DisplayString("Change your Baud rate to 57600 and enter 'y' when ready ");
            LF;
            DisplayString("Enter: ");
            Baud_Rate = 57600;
            
            Change_BR(Baud_Rate);
            
            while(RegisterCase != 'y')
            {
               RegisterCase = EchoGetChar();  
            }                        

            LF;            
            DisplayString("New Baudrate is ");
            DisplayInt((unsigned int)Baud_Rate,0);
            DisplayString(" Baud Rate");            
            LF;

         break;
         case 'F':
            DisplayString("Change your Baud rate to 9600 and enter 'y' when ready ");
            LF;
            DisplayString("Enter: ");
            Baud_Rate = 9600;
            
            Change_BR(Baud_Rate);
            
            while(RegisterCase != 'y')
            {
               RegisterCase = EchoGetChar();  
            }                        

            LF;            
            DisplayString("New Baudrate is ");
            DisplayInt((unsigned int)Baud_Rate,0);
            DisplayString(" Baud Rate");            
            LF;

         break;
         default:
            DisplayString("Invalid choice. Please try again");
            LF;
       }

         /* Wait to display register contents */
         for (x=0; x<3000; x++)
	 	    {	
 	  		     for (y=0; y<2000; y++)
	 		     {
	 		        ;
	 		     } 
         }

         FF;                
      }
}


/******************************************************************************
Function Name	:	PutChar
Engineer		:	r32151
Date			:	22/01/02

Parameters		:	character to be output to SCI
Returns			:	NONE
Notes			:	Transmits a character on SCI
******************************************************************************/
void PutChar(char ch) 
{
	/* check SCI transmit data register is empty */
	while(SCI0SR1_TDRE == 0)
	{
	}	
	SCI0DRL = ch;	
}

/******************************************************************************
Function Name	:	GetChar
Engineer		:	r32151
Date			:	04/11/02

Parameters		:	NONE
Returns			:	character received by SCI
Notes			:	Receives a character on SCI
******************************************************************************/
char GetChar(void) 
{
	/* check SCI0 transmit data register is empty */
	while(SCI0SR1_RDRF == 0)
	{
	}	
	return(SCI0DRL);	
}

/******************************************************************************
Function Name	:	DisplayString
Engineer		:	r58711
Date			:	14/02/02

Parameters		:	textString[]
Returns			:	NONE
Notes			:	Transmits text string as ASCII to SCI
******************************************************************************/
void DisplayString (signed char *textPointer)
{
		/* while not end of string */
	while(*textPointer != 0)
	{	
			/* write the character to the SCI interface */
		PutChar(*textPointer);
			/* increment to point at the next character in the string */
		textPointer++;
	}	
}

/******************************************************************************
Function Name	:	EchoGetChar
Engineer		:	r32151
Date			:	04/11/02

Parameters		:	NONE
Returns			:	character received by SCI
Notes			:	Receives a character on SCI and transmits it back out
******************************************************************************/
char EchoGetChar(void) 
{
		/* check SCI receive data register is empty */
	while(SCI0SR1_RDRF == 0)
	{
	}	
	/* Echo the received character back */
	PutChar(SCI0DRL);
	/* return the received character */
	return(SCI0DRL);	
}

/******************************************************************************
Function Name	:	DisplayInt
Engineer		:	r32151
Date			:	04/09/02

Parameters		:	int count value to display; unsigned char field width
Returns			:	NONE
Notes			:	Transmits Int variable to SCI after conversion to ASCII
            Effectively performs a number to string conversion and then outputs
            the string.
					  If field width = 0 then the int is displayed left justified with
					  leading zeros supressed.
					  If field width = 1-5 then lowest n digits are displayed with leading 
					  zeros.
					  This routine does not check that the field size is valid.					
******************************************************************************/
void DisplayInt(unsigned int number, unsigned char field ) 
{
	char buf[6];
	char i = 5;

	buf[i] = 0;
			/* for upto 10 digits : max value for long = 4294967296 */
			/* using a do while loop to take care of the number = 0 */
	do
	{
				/* convert least significant character of the int into ascii -> string buffer */
		buf[--i] = (char)(number % 10) + '0';
				/* moves next digit to least significant position */
		number /= 10;
	} while (number != 0); 
				/* if field width is less than number of digits only o/p field width of string */
	if ((field < (5-i)) && (field != 0))
		i = 5 - field;
				/* if field width is more than number of digits add leading zeros */
	if (field > (5-i))
	{
		while ((5-i) < field)
	    {
				/* add leading zeros */ 
		buf[--i] = '0';
		}
	}
	DisplayString(&buf[i] );	
}

/******************************************************************************
Function Name	:	DisplayByte
Engineer		:	r58711
Date			:	14/02/02
Parameters		:	displayByte
Returns			:	NONE
Notes			:	Transmits Byte variable to SCI after conversion to ASCII
******************************************************************************/
void DisplayByte (unsigned char displayByte)
{
   unsigned char upperNibble, lowerNibble;
   /* Split data into nibbles for ASCII conversion */
   upperNibble = ((displayByte & 0xF0)>>4); 
   lowerNibble = (displayByte & 0x0F);
   /* Pass nibbles to SCI after passing for conversion to ASCII */
   PutChar(Number_2_ASCII(upperNibble));
   PutChar(Number_2_ASCII(lowerNibble));
}

/******************************************************************************
Function Name	:	Number_2_ASCII
Engineer		:	r58711
Date			:	15.11.01

Parameters		:	Nibble of binary data (0000 to 1111) (unsigned char)
Returns			:	ASCII code for nibble (unsigned char)
*******************************************************************************/
unsigned char Number_2_ASCII(unsigned char Nibble)
{	
   /* If nibble is less than 9 (ie. a number) */
	 if (Nibble <= 0x09) 
	 /* Return the ASCII code for this number */
	    return (Nibble + 0x30); 
   else
   /* Return the ASCII code for this letter */
      return (Nibble + 0x37); 
} 

/******************************************************************************
Function Name	:	ASCII_2_Number
Engineer		  :	r58711
Date			    :	15.11.01
Parameters		:	ASCII data byte (unsigned char)
Returns			:	numeric equivalent (unsigned char) of ASCII code 
*******************************************************************************/
unsigned char ASCII_2_Number(unsigned char ascii_char)
{
  byte number;	
	/* If character is 9 or less (ie. a number) */
	number = ascii_char - 0x30; 
	/* If character is greater than 9 (ie. hex number A,B,C,D,E,F) */
	if (number > 0x09) number -= 0x07;
	/* If chracter is greater than 9 and lower case (ie. hex number a,b,c,d,e,f) */
  if (number > 0x0F) number -= 0x20;	
  /* If charcter is non-numeric default to 0 */
  if (number > 0x0F) number = 0;
	return (number); 
} 

/******************************************************************************
Function Name  : CPMU_Init
Engineer       : b30269	
Date           : 02/07/11
Parameters     : NONE
Returns        : NONE
Notes          : CPMU configuration to run at 25MHz bus clk.                               
******************************************************************************/
void CPMU_Init(void)
{
   /* 
      Initialise the system clock for Normal mode: 
      - 50MHz VCO, 50MHz PLL, 25MHz Bus CLK, from 8MHz Crystal 
   */
	
   CPMUSYNR    = 0x58;     /* VCOFRQ -> 48MHz < fVCO<= 50MHz SYNDIV = 24  */

   CPMUREFDIV  = 0x07;     /* REFDIV =  7                           */     

   CPMUPOSTDIV = 0x00;     /* POSTDIV = 0, FBus 0 FPLL/2            */

   while(!CPMUFLG_LOCK)
   {
      ;                /* 
                          Wait for VCO to stabilize, if failure occurs 
                          WD will be triggered
                       */
   }			 
 
   CPMUCLKS_PLLSEL = 1;  /* Switch clk to use PLL */
}

/******************************************************************************
Function Name  : Change_BR
Engineer       : b30269	
Date           : 02/07/11
Parameters     : NONE
Returns        : NONE
Notes          : Configure the SCI to Tx and Rx using the defined Baud Rate 
                 Data Bits  = 8     
                 Parity     = None  
                 Start Bits = 1     
                 Stop Bits  = 1
                 Prescaler = Bus Clock / (16 x Baud Rate)                                    
******************************************************************************/
void Change_BR(unsigned long br)
{
  BaudRatePrescaler = (unsigned int)(25000000 / (16 * br));

  

   /* Set the Baud Rate */
   SCI0BDH = (unsigned char)((BaudRatePrescaler>>8));
   SCI0BDL = (unsigned char)(BaudRatePrescaler);   
}