/*******************************************************************************
* Freescale Semiconductor Inc.
* (c) Copyright 2012 Freescale Semiconductor, Inc.
* ALL RIGHTS RESERVED.
********************************************************************************
Services performed by FREESCALE in this matter are performed AS IS and without
any warranty. CUSTOMER retains the final decision relative to the total design
and functionality of the end product. FREESCALE neither guarantees nor will be
held liable by CUSTOMER for the success of this project.
FREESCALE DISCLAIMS ALL WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY INCLUDING,
BUT NOT LIMITED TO, IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
A PARTICULAR PURPOSE ON ANY HARDWARE, SOFTWARE ORE ADVISE SUPPLIED TO A PROJECT
BY FREESCALE, AND OR NAY PRODUCT RESULTING FROM FREESCALE SERVICES. IN NO EVENT
SHALL FREESCALE BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THIS AGREEMENT.
CUSTOMER agrees to hold FREESCALE harmless against any and all claims demands or
actions by anyone on account of any damage, or injury, whether commercial,
contractual, or tortuous, rising directly or indirectly as a result of an advise
or assistance supplied CUSTOMER in connection with product, services or goods
supplied under this Agreement.
********************************************************************************
* File main.c
* Owner b34874
* Version 1.0 // version 0.x is reserved for development phase and
// should not be placed in the repository
* Date Oct-15-2012
* Classification General Business Information/Internal Use Only/Confidential Proprietary
* Brief Brief description of the file
********************************************************************************
* Detailed Description:
* Software trimming APICLK to 10kHz 
* Tested on: S12G240, TWR-S12G240, 
* CLK source:1MHz IRCCLK; BUSCLK:8MHz
********************************************************************************
Revision History:
Version Date Author Description of Changes
1.0 Oct/15/2012 b34874 Initial Version
*******************************************************************************/
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */


// TIM_Init
//==============================================================================
void TIM_Init(void)
{ 
  // int osc clock = 1MHz
  // bus clock = 8MHz     
  //timer clk = bus clk / prescaler = 8Mhz / 8 = 
  // 1 timer clock == 1us  
  TIOS = 0x01;    //channel 0 as output compare  
  TSCR2 = 0x03;   //prescaler = 8
  TSCR1 = 0xA0;   //timer enabled
}

//==============================================================================
//Start_interval
//==============================================================================
void Start_interval(unsigned int interval)
{
  TC0 = TCNT + interval;  //set required interval  
}

//==============================================================================
// API_Init
//==============================================================================
void API_Init(void)
{  
  CPMUAPIR = 49;         //10ms interval  
  CPMUACLKTR = 0x00;     //initial trim value
  CPMUAPICTL = 0x09;     //API osc is source of clock, interrupt disable, 
                         //clear flag if set
  CPMUAPICTL_APIFE = 1;  //API enable
}

//==============================================================================
// API_ISR
//==============================================================================
#pragma CODE_SEG NON_BANKED
interrupt 59 void API_ISR(void)
{  
  PTT_PTT7 = ~PTT_PTT7;  //toggle LED => half frequency, period = 20ms, frequency = 50Hz
  CPMUAPICTL_APIF = 1;   //clear flag
}
#pragma CODE_SEG DEFAULT

//==============================================================================
// Main
//==============================================================================
void main(void) {
  
  unsigned int i;
  unsigned char mask_decrease = 0;
  unsigned char mask_increase = 0;
  unsigned char mask_final = 0;
  
  ECLKCTL_NECLK=0;       //enable ECLK signal at pin PB0
  
  DDRT_DDRT7 = 1;        //LED output
	
//===============================================================================
// PLL settings for 8MHz
    
  CPMUSYNR = 0x0F;
  CPMUREFDIV = 0x00;              
  CPMUPOSTDIV = 0x01;     
  
  //writing into CPMUSYNR or CPMUREFDIV will unlock the PLL.
  //While PLL is unlocked fpll is fvco/4 to protect the system from high
  //core clock frequencies during the PLL stabilization time. 
  
  //wait until PLL clocks are within the desired tolerance of target frequency
  while(!CPMUFLG_LOCK);  
  
//=============================================================================
  
  TIM_Init();
  
  API_Init();
  
  //============================================================================
  //bit APITR5 increases the API period
  //this part of code will find out if the API period must be increased or not
  
  while(CPMUAPICTL_APIF == 0);   //wait for API event
  CPMUAPICTL_APIF = 1;           //clear API flag
  
  Start_interval(10000);        //start interval 10ms (Timer is set as: 1 Timer clock == 1us)
  
  while(CPMUAPICTL_APIF == 0);   //wait for API event
 
  if(TFLG1_C0F == 0)        //make a decision on the basis of timer if the period must be increased                                   
    mask_increase = 0x80;       //increase API period by bit APITR5
  
  CPMUAPICTL_APIF = 1;           //clear API flag  
  while(TFLG1_C0F == 0);    //wait also for timer
  TFLG1 = 0x01;             //and clear Timer flag...
  

  //============================================================================
  //bits APITR4-APITR0 decreases the period
    
  mask_decrease = 0b01000000;   //set the mask that will be shifted step by step
                                //from MSB (APITR4) to LSB (APITR0)        
    
  for(i=0; i<5; i++)
  {
    CPMUACLKTR = mask_increase | mask_decrease | mask_final; //set the trimming register
    
    while(CPMUAPICTL_APIF == 0); //wait for API event
    CPMUAPICTL_APIF = 1;         //clear API flag
  
    Start_interval(10000);      //start interval 10ms 
  
    while(CPMUAPICTL_APIF == 0); //wait for API event    
    
    if(TFLG1_C0F == 1)      //make a decision on the basis of timer if the period must be decreased                                  
      mask_final |= mask_decrease;  //yes, the period must be decreased     
    else    
      while(TFLG1_C0F == 0);//just wait for timer
    
    CPMUAPICTL_APIF = 1;         //clear API flag
    TFLG1 = 0x01;           //and clear Timer flag...      
    
    mask_decrease = mask_decrease >> 1; //shift the mask for next round
            
  } 
  
  mask_final |= mask_increase;  //this is the final number that can be stored somewhere
                                //to the flash. After reset we can load this value to 
                                //CPMUACLKTR without trimming procedure.  
  
  CPMUACLKTR = mask_final;       //write the final value to trimming register
  
  CPMUAPICTL_APIES = 1;          //Show API_EXTCLK signal at PB1 pin
  CPMUAPICTL_APIEA = 1;          //
  
	
	CPMUAPICTL_APIE = 1;           //interrutp enable
  
  EnableInterrupts;


  for(;;) {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}
