/*******************************************************************************
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2005 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 OR ADVISE SUPPLIED TO THE 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     Ladislav
* Version   1.0
* Date      Feb-01-2012
* Classification   General Business Information
* Brief     Test 8x8 CAN filter in loopback mode
********************************************************************************
                 TECHNICAL SUPPORT - SOFTWARE EXAMPLE
********************************************************************************
* Detailed Description:
*
* CAN Rx is solved in interrupt mode
* CAN setup: 125kbps, 1sample/bit, 8MHz ext osc as CAN clock source, 
*            loop  disabled, CAN interface (TJA1040)
* 4x16 bit filter mode is used to present filters
* The CAN receives only extended IDs
* Sleep of the CAN module and MCU STOP mode is presented.
* The MCU is woken up by means of received message.
* Diodes at PT4~7 toggles slowlier before the MCU goes into CAN sleep and MCU
*   STOP modes. After wake up the diode are toggled faster.
*     
* - tested on: TWR-S12G128
* - OSCCLK = 8MHz oscillator, BUSCLK = 24MHz set by means of PLL in PEE mode
* - Reference to documentation: MC9S12GRMV1 Rev.1.01
********************************************************************************
Revision History:
Version  Date         Author  Description of Changes
1.0      Oct-13-2014  Ladislav  Initial version
*******************************************************************************/
                         
#include <hidef.h>       // common defines and macros       
#include "derivative.h"  // derivative-specific definitions 
#include "comdef.h"      // my common definitions           
/*******************************************************************************
* Local function prototypes
*******************************************************************************/
static void delay(ULONG ii);
static void setPEEmodeBUSCLK(UBYTE _synr, UBYTE _refdv, UBYTE _postdiv);
/*******************************************************************************
* Local module variables
*******************************************************************************/
static UBYTE RXmsgIDE,   RXmsglen,   RXmsgRTR;
static ULONG RXmsgid;
static UBYTE RXmsgdata0, RXmsgdata1, RXmsgdata2, RXmsgdata3;
static UBYTE RXmsgdata4, RXmsgdata5, RXmsgdata6, RXmsgdata7;

/*******************************************************************************
Function Name : PLL_LockIsr
Engineer      : Ladislav
Date          : NOV/28/2011
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : The interrupt function used (if necessary) if the PLL lock 
                status has changed
Issues        : NONE
*******************************************************************************/
#pragma CODE_SEG NON_BANKED
interrupt 28 void PLL_LockIsr(void)
{
  if(CPMUFLG_LOCK == 0)  {    /*do something here*/  }
  else                   {    /*do something here*/  }
}
#pragma CODE_SEG DEFAULT
/*******************************************************************************
Function Name : setPEEmodeBUSCLK
Engineer      : Ladislav
Date          : NOV/28/2011
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Changes BUSCLK
Issues        : NONE
*******************************************************************************/
void setPEEmodeBUSCLK(UBYTE _synr, UBYTE _refdv, UBYTE _postdiv)
{
 CPMUSYNR    = _synr;
 CPMUREFDIV  = _refdv;
 CPMUPOSTDIV = _postdiv;   
  
 CPMUOSC_OSCE = 1; //enable external oscillator OSCE
    
 while(!CPMUFLG_UPOSC)
  {
    CPMUARMCOP=0x55;CPMUARMCOP=0xAA; // kick the dog if enabled
  };    
 while(!CPMUFLG_LOCK)
  {
    CPMUARMCOP=0x55;CPMUARMCOP=0xAA; // kick the dog if enabled
  };    
 
  //--- select clocks ------------
 
 CPMUCLKS = 0B10000000;           // bus=fPLL/2; COP is clocked from OSCCLK
 if(CPMUCLKS != 0B10000011)       // After writing CPMUCLKS register, it is 
  {                               // recommended to read back CPMUCLKS register 
                                  // to be sure that write of PLLSEL,RTIOSCSEL,
     asm nop;                     // COPOSCSEL0 and COPOSCSEL1 was successful.
  }
 asm nop;
 //-------------------------------
}
/*******************************************************************************
Function Name : delay
Engineer      : Ladislav
Date          : Oct-13-2014
Parameters    : ULONG ii
Modifies      : NONE
Returns       : NONE
Notes         : Short delay - hard loop.
Issues        : NONE
*******************************************************************************/
static void delay(ULONG ii)
{
  unsigned long i;    
  
  for( i = 0; i < ii; i++ )   asm nop;        
}
/*******************************************************************************
Function Name : CANRx
Engineer      : Ladislav
Date          : Oct/13/2014
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Main function.
Issues        : NONE
*******************************************************************************/
#pragma CODE_SEG NON_BANKED

interrupt 38 void CANRx(void)
{
 ULONG ex;
 
 RXmsgIDE = (CANRXIDR1 & 0x08) >> 3;
 
 // get extended identifier
 ex = *((ULONG *) (&(CANRXIDR0)));// get entire identifier
 RXmsgid    = (ex >> 3) & 0x1FFC0000UL;
 RXmsgid   |= (ex >> 1) & 0x0003FFFFUL;
 RXmsgRTR   = CANRXIDR3 & 0x01;

 RXmsglen   = CANRXDLR & 0x0F;
 RXmsgdata0 = CANRXDSR0;
 RXmsgdata1 = CANRXDSR1;
 RXmsgdata2 = CANRXDSR2;
 RXmsgdata3 = CANRXDSR3;
 RXmsgdata4 = CANRXDSR4;
 RXmsgdata5 = CANRXDSR5;
 RXmsgdata6 = CANRXDSR6;
 RXmsgdata7 = CANRXDSR7;
 
 
 CANRFLG = CANRFLG_RXF_MASK;      // clear flag

}
#pragma CODE_SEG DEFAULT
/*******************************************************************************
Function Name : CANWakeUp
Engineer      : Ladislav
Date          : Oct/13/2014
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Main function.
Issues        : NONE
*******************************************************************************/
#pragma CODE_SEG NON_BANKED

interrupt 36 void CANWakeUp(void)
{
 ULONG ex;
 
 RXmsgIDE = (CANRXIDR1 & 0x08) >> 3;
 
 // get extended identifier
 ex = *((ULONG *) (&(CANRXIDR0)));// get entire identifier
 RXmsgid    = (ex >> 3) & 0x1FFC0000UL;
 RXmsgid   |= (ex >> 1) & 0x0003FFFFUL;
 RXmsgRTR   = CANRXIDR3 & 0x01;

 RXmsglen   = CANRXDLR & 0x0F;
 RXmsgdata0 = CANRXDSR0;
 RXmsgdata1 = CANRXDSR1;
 RXmsgdata2 = CANRXDSR2;
 RXmsgdata3 = CANRXDSR3;
 RXmsgdata4 = CANRXDSR4;
 RXmsgdata5 = CANRXDSR5;
 RXmsgdata6 = CANRXDSR6;
 RXmsgdata7 = CANRXDSR7;
 
 
 CANRFLG = CANRFLG_WUPIF_MASK;      // clear flag

}
#pragma CODE_SEG DEFAULT

/*******************************************************************************
Function Name : main
Engineer      : Ladislav
Date          : Oct-13-2014
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Main function.
Issues        : NONE
*******************************************************************************/
void main(void) 
{
 UWORD i;

 //--- set BUSCLK ----------------
 setPEEmodeBUSCLK(0x02, 0x80, 0x00);// 24MHz BUSCLK from 8 MHZ oscclk, PEE mode
 
 ECLKCTL_NECLK = 0; // BUSCLK visible at PB0

 //--- enable STOP mode ----------
 asm ANDCC #0x7F

 //--- set PORTs -----------------
 DDRT  = 0xF0;                    // PORT T4~7 an output port - diodes
 PTT  |= 0xF0;                    // Toggle diodes at PTT4~7
 PTT  &= 0x0F;

 //--- set CAN -------------------
 //.................................
 // 125kbps, 1sample/bit, 8MHz ext osc as CAN clock source, loop  disabled
 // CAN interface (TJA1040)
 //.................................

 CANCTL0 = CANCTL0_INITRQ_MASK;
 while(!CANCTL1_INITAK);
 
 CANCTL1  = CANCTL1_CANE_MASK;    // Enables MSCAN, Oscillator Clock, 
                                  // Loop Enabled/Disabled and Normal Operation
                                  // WUPM = 0; 0 MSCAN wakes up on any dominant 
                                  // level on the CAN bus
 CANBTR0  = 0xC3;                 //
 CANBTR1  = 0x67;                 //


 CANIDAC  = 0x10;                 // CAN Flilter 4x16
 *((UWORD*)(&CANIDAR0)) = 0x0018; // extended ID flag, SRR=IDE=1
 *((UWORD*)(&CANIDMR0)) = 0xFFE7; // accept extended identif. only, SRR=IDE=1
 *((UWORD*)(&CANIDAR2)) = 0x0018; // extended ID flag, SRR=IDE=1
 *((UWORD*)(&CANIDMR2)) = 0xFFE7; // accept extended identif. only, SRR=IDE=1
 *((UWORD*)(&CANIDAR4)) = 0x0018; // extended ID flag, SRR=IDE=1
 *((UWORD*)(&CANIDMR4)) = 0xFFE7; // accept extended identif. only, SRR=IDE=1
 *((UWORD*)(&CANIDAR6)) = 0x0018; // extended ID flag, SRR=IDE=1
 *((UWORD*)(&CANIDMR6)) = 0xFFE7; // accept extended identif. only, SRR=IDE=1
 
 
 CANCTL0  = 0B00000100;  		  		// restart MSCAN - enable wakeup 
                                  // RXFRM RXACT CSWAI SYNCH
                                  // TIME WUPE SLPRQ INITRQ
 
 while(CANCTL1 & CANCTL1_INITAK_MASK);   // wait for Initialization Mode exit
 while(!(CANCTL0 & CANCTL0_SYNCH_MASK)); // wait for synch. with the CAN bus
 CANRIER_RXFIE = 1;                      // enable can Rx interrupt
 CANRIER_WUPIE = 1;                      // enable can Rx interrupt
 //-------------------------------
 EnableInterrupts;
 //-------------------------------
 for(;;)
  {
   //--- toggle diodes -----------
   for(i=0; i<5; i++)
    {
     PTT  |= 0xF0;                // Toggle diodes at PTT4~7
     delay(0x03FFFFUL);
     PTT  &= 0x0F;
     delay(0x03FFFFUL);
    }

   //--- CAN go to sleeps --------
   CANCTL0_SLPRQ = 1;             // Initialize CAN sleep mode
   while(!CANCTL1_SLPAK);         // Wait while CAN is not in sleep
   
   //--- MCU go to STOP mode -----
   asm STOP;

   //--- toggle diodes faster ----
   for(i=0; i<5; i++)
    {
     PTT  |= 0xF0;                // Toggle diodes at PTT4~7
     delay(0x01FFFFUL);
     PTT  &= 0x0F;
     delay(0x01FFFFUL);
    }
  }
}


/*******************************************************************************
The Answer to the Ultimate Question of Life, the Universe, and Everything is: 42
(Douglas Adams - The Hitchhiker's Guide to the Galaxy)
*******************************************************************************/


















