/*******************************************************************************
* 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     R62780
* Version   1.0
* Date      Nov-28-2011
* Classification   General Business Information
* Brief     CAN BUS-OFF test
********************************************************************************
* Detailed Description:
*
* CAN is used without transceiver in connection by Siemens AP2921
* http://www.mikrocontroller.net/attachment/28831/siemens_AP2921.pdf
* connection description:
* CANRX - diode Anode/Cathode - CANTX; CANRX - pullup 3.3k - VDD 5V
* (CANRX primary elevator connector J9 hole 41)
* (CANTXX primary elevator connector J9 hole 42)
* (+5V primary elevator connector J9 hole 1)
*
*
* Rx and Tx arre solved in polling mode
* 8x8 bit filter mode is used to test filters
* The CAN sends messages with all IDs.
* BORM is set in the init_CAN to enable synchro also under user request
* Sent and resevied messages are visualized via SCI @ 9600bps (Hypeterminal)
*     
* - 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      NOV-28-2011  R62780  Initial version
*******************************************************************************/
                         
#include <hidef.h>       /* common defines and macros       */
#include "derivative.h"  /* derivative-specific definitions */
#include "comdef.h"      /* my common definitions           */
#include "homer.h"       /* homer simpson                   */
#include "can.h"  
#include <stdio.h>
/*******************************************************************************
* Local function prototypes
*******************************************************************************/
static void Delay(UWORD ii, UWORD jj);
static void SetPEEmodeBUSCLK(UBYTE _synr, UBYTE _refdv, UBYTE _postdiv);
static void SCI_Init(void);
static void SCI_sendText(SBYTE *str);
/*******************************************************************************
* Local module variables
*******************************************************************************/
static SBYTE txt[255];


/*******************************************************************************
Function Name : SCI_Init
Engineer      : R62780
Date          : NOV/28/2011
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : SCI init at 9600bps @ 32MHz BUSCLK
Issues        : NONE
*******************************************************************************/
#pragma CODE_SEG NON_BANKED
//.........................
interrupt 37 void CAN_ErrorsIsr(void)
{
 UWORD i;

 (void)sprintf(txt,"CANRFLG = 0x%02X\n\r",CANRFLG);
 SCI_sendText(txt);


 CANRFLG = 0xC3; //clear all flags
 asm nop;       
 //----------------------------
 if(CANMISC_BOHOLD)     // is CAN in the BUSSOFF state?
  {                     // note that BORM is set in CANCTL1

    (void)sprintf(txt,"CAN BUSS OFF \n\r");
    SCI_sendText(txt);
    
    CANMISC_BOHOLD = 1; // start synchronization
    i=0xFFFF;
    do
      {
       i--; 
      }
    while(!CANCTL0_SYNCH && i>0); // waits for MSCAN synchro. with the CAN bus
    
    if(!i)
      {
        //timeout, bus not synchronized, if necessary do something
        asm nop;
      }
    else
      {
        //bus synchronized
        asm nop;
      }
  }
 else
  {
    // another event depending on TSTAT and RSTAT setup
    // do something
    asm nop;
  } 
}
//.........................
#pragma CODE_SEG DEFAULT
/*******************************************************************************
Function Name : SCI_Init
Engineer      : R62780
Date          : APR/14/2011
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : SCI init at 9600bps @ 32MHz BUSCLK
Issues        : NONE
*******************************************************************************/
void  SCI_Init(void)
{
 //----- BR = BUSCLK / (16*Baud rate) = 24000000 / (16*9600) = 208 = 0x9C -----
                     //------------------------------------------------------
   SCI0BD  = 0x9C;   // prescaller value (depends on module clock frequency) 
                     // prescaller = 0xD0   9600Bd  (32MHz bus clock is set)
                     //------------------------------------------------------
   SCI0CR1 = 0x44;   // Loops sciswai rsrc   m    wake  ilt   pe    pt       
                     // 0-LOOPS=RSRC=0 => 1 Single-wire mode with Rx input connected to TXD
                     // 1-SCI dis. in wait mode                              
                     // 0-if RSRC=1-RxTx intern. connected if loops=1                  
                     // 0-start+8 data+1 stop bit                          
                     // 0-IDLE mark wake up                                  
                     // 1-idle char. bit count begins after stop bit         
                     // 0-parity fction disabled                             
                     // 0-odd parity                                       
                     //------------------------------------------------------
   SCI0CR2 = 0x08;   // tie   tcie    rie  ilie   te    re   rwu   sbk       
                     // 0-Tx empty intr disabled                             
                     // 0-Tx complete intr disabled                          
                     // 0-Rx full + OverRun interrupts
                     // 0-idle line intr disabled                            
                     // 1-transmitter enabled
                     // 0-receiver disabled
                     // 0-receiver normal operation                                   
                     // 0-no break characters                                
                     //------------------------------------------------------
}
/*******************************************************************************
Function Name : SCI_sendText
Engineer      : R62780
Date          : APR/14/2011
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : send \0 terminated text out through SCI in polling mode
Issues        : NONE
*******************************************************************************/
void SCI_sendText(SBYTE *str)
{
  UBYTE i;
  i=0;
  while(str[i]!='\0')
    {
     while(!SCI0SR1_TC); // write data to SCI (clear TC) 
     SCI0DRL = str[i];
     i++;
    }
}
/*******************************************************************************
Function Name : PLL_LockIsr
Engineer      : R62780
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      : R62780
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 strongly
  {                         // recommended to read back CPMUCLKS register 
                            // to make sure that write of PLLSEL, RTIOSCSEL,
     asm nop;               // COPOSCSEL0 and COPOSCSEL1 was successful.
  }
 asm nop;
 //--------------------------------------
}
/*******************************************************************************
Function Name : Delay
Engineer      : R62780
Date          : Apr/14/2010
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Short delay - hard loop.
Issues        : NONE
*******************************************************************************/
static void Delay(UWORD ii, UWORD jj)
{
  unsigned int i,j;    
  
  for( i = 0; i < ii; i++ )  
    for( j = 0; j < jj; j++) asm nop;        
}
/*******************************************************************************
Function Name : main
Engineer      : R62780
Date          : Apr/14/2010
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Main function.
Issues        : NONE
*******************************************************************************/
void main(void) 
{
 UBYTE data=1;
 ULONG id = 0;
 ULONG tmp;
 volatile UWORD x;
 
 SetPEEmodeBUSCLK(0x02, 0x80, 0x00); // 24MHz BUSCLK from 8 MHZ oscclk, PEE mode
 
 ECLKCTL_NECLK = 0; // BUSCLK visible at PB0
 
  //enabling an external SCI transceiver device MAX3387E
 // *((UBYTE*)0x277) = 0;  // PRR1_PRR1AN; AN10~15 routed to PAD10~15
 DDR0AD_DDR0AD7   = 1;  // set AN15 as an output
 PT0AD_PT0AD7     = 1;  // enable MAX3387E
 
 SCI_Init();                         // 9600 bps @ 32MHz BUSCLK

 homer();                            // homer face through SCI
 
 //-----------------------------------------

 // 8x8bit filter for CAN0
 // 8x8bit filter   ==> 8x               ID10~ID3
 //                 ==> 8xIDAR           XXXX XXXX - filter
 //                 ==> 8xIDMR           XXXX XXXX - mask of the filter
 
 
 canFltr[0].fltrType        = CANFLTR8;// 8x8bit filter


 canFltr[0].fltr.f8.fltr[0] = 0xF0; 
 canFltr[0].fltr.f8.mask[0] = 0xF0; // accept all IDs with ID10~ID3 = xxxx 0000
 canFltr[0].fltr.f8.fltr[1] = 0xE1; 
 canFltr[0].fltr.f8.mask[1] = 0xE1; // accept all IDs with ID10~ID3 = xxx0 000x
 canFltr[0].fltr.f8.fltr[2] = 0xD2; 
 canFltr[0].fltr.f8.mask[2] = 0xD2; // accept all IDs with ID10~ID3 = xx0x 00x0
 canFltr[0].fltr.f8.fltr[3] = 0xC3; 
 canFltr[0].fltr.f8.mask[3] = 0xC3; // accept all IDs with ID10~ID3 = xx00 00xx
 canFltr[0].fltr.f8.fltr[4] = 0xB4; 
 canFltr[0].fltr.f8.mask[4] = 0xB4; // accept all IDs with ID10~ID3 = x0xx 0x00
 canFltr[0].fltr.f8.fltr[5] = 0xA5; 
 canFltr[0].fltr.f8.mask[5] = 0xA5; // accept all IDs with ID10~ID3 = x0x0 0x0x
 canFltr[0].fltr.f8.fltr[6] = 0x96; 
 canFltr[0].fltr.f8.mask[6] = 0x96; // accept all IDs with ID10~ID3 = x00x 0xx0
 canFltr[0].fltr.f8.fltr[7] = 0xF0; 
 canFltr[0].fltr.f8.mask[7] = 0xF0; // accept all IDs with ID10~ID3 = xxxx 0000


 
 init_CAN(0,0xC3, 0x58, 1); // 125 kb/s, loop enabled/disabled=1/0,
 
  //-----------------------------------------
 // setup for bus off test
 //-----------------------------------------
 CANRIER = 0B01010100; // 01 no wake-up, status change isr enable,
                        // 01 bus off trigger
                        // 01 bus off trigger
                        // 00 no overrun isr, no receiver full isr
 CANRFLG = 0xC3;       // clear all flags
  
 EnableInterrupts;
 //-----------------------------------------
 data = 0;
 SCI_sendText((SBYTE*)"\r\n\r\nHELLO, I AM ALIVE....\r\n\r\n");

 for(;;)
  {
   //................................ 
   // send message with standard ID from CAN 
   //(id is variable, one data is being sent)
   //................................ 

   id = id  & 0b11111111111;   // the SW goes through all IDs
   
   (void)sprintf(txt,"CAN0 sent: ID= 0x%03LX data=0x%02x \n\r",(ULONG)id, data);
                      SCI_sendText(txt);

   // prepare message to be sent
   // CAN#=0,id=variable,RTR=0,IDE=0,len=1(number of data,only one data will be 
   // sent),prty=3,d0=data,d1,d2,d3,d4,d5,d6,d7
   createMessage(&canTxMsg[0],id,0,0,1,3,data,0,0,0,0,0,0,0);

   (void) MSCANSendMsg(0,&canTxMsg[0]);  // CAN#,CAN#, buf :send message

   //................................ 
   //........ only delay  ........
   //................................ 
   Delay(1,0xFFFF);                      // only delay 

   //................................ 
   // at this moment the message has to be received at CAN0 so we will check it     
   //................................ 

   if(MSCANCheckRcvdMsg(0)) // get msg at CAN0 if it has already been received
     {
       if(MSCANGetMsg(0, &canRxMsg[0]))  // CAN# :get message
        {
         
         // if necessary get number how many data were recived and all 
         // message members
         tmp=canRxMsg[0].RTR; 
         tmp=canRxMsg[0].IDE; 
         tmp=canRxMsg[0].len; 
         tmp=canRxMsg[0].id; 
         
         //...............
         // show received ID and received data 
         //...............
         (void)sprintf(txt,"CAN0 rcvd: ID= 0x%03LX data=0x%02x IDHIT=%1d \n\r",
                            (ULONG)canRxMsg[0].id, data, CANIDAC_IDHIT);
         SCI_sendText(txt);
         
         (void)sprintf(txt,"\n\n\r");  SCI_sendText(txt);
         Delay(5,0xFFFF);
        }

     }      

   //................................ 
   // change id, increment data
   //................................ 
   data++;
   id++;

  }
 //-----------------------------------------

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


















