/*******************************************************************************
* Freescale Semiconductor Inc.
* (c) Copyright 2011 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 August-30-2011
* Classification General Business Information/Internal Use Only/Confidential Proprietary
* Brief Brief description of the file
********************************************************************************
* Detailed Description:
* Software use SCI for receiving character and send them at SPI 
* Example simply receive byte trough SCI, display lower half byte at LEDs and send byte at SPI.
* Tested on: PC9S12G32 0N48A, TWR-S12GN32
* SCK signal at PS6 pin, MOSI signal at PS5 pin
* Clock source:default 1MHz IRCCLK; BUSCLK:6.25MHz
********************************************************************************
Revision History:
Version Date Author Description of Changes
1.0 March/19/2012 b34874 Initial Version
*******************************************************************************/
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */


//******************************************************************************
// TYPE DEFINITIONS
//******************************************************************************
#define     OK                    0
#define     ERROR                 1
#define     MS                    1 //master=1,slave=0
//******************************************************************************

/****************************** Definitions of SPI macros **********************/
//#define AssertSS()                  PTS_PTS7 = 0; // Start of SPI transfer
//#define DeassertSS()                PTS_PTS7 = 1; // End of SPI transfer
#define SPIReadStatReg()           (void)SPI0SR;  // Clear Status reg. 
#define SPIReadDataReg()           (void)SPI0DR;  // Clear Data reg.(Dummy read)
#define SPIWaitReceiveDone()        while (!(SPI0SR_SPIF)); // Wait for full buf  
#define SPIWaitTransferDone()       while (!(SPI0SR_SPTEF));//Wait for buf empty
/*******************************************************************************/

/****************************** Definitions of SCI data variable****************/
volatile unsigned char sc0_data_in;
/*******************************************************************************/

/**********************************************
 * GPIOInit:                                  *
 * Set default state of SPI and PTG pins      *
 **********************************************/
void GPIOInit(void) 
{  
  
  PTS = 0xFF;     // Set default state of SPI pins when SPI not active;
  PTT = 0xFF;     // LED disable
  DDRT =0x3C;     // PT[2..5] as output for leds
}
/*******************************************************************************/

/****************************************************************
 * SPIInit: Initialize the SPI Control and Baud Rate Registers  *
 * Parameters: None                                             *
 * Return : None                                                *
 ****************************************************************/
 
void SPIInit(void)   
{
    
    (void)SPI0SR;     // SPISR init (dummy read)
    
    if (MS) SPI0CR1 = 0x14;   // Master
 		  else  SPI0CR1 = 0x04;   // Slave
                     /*  
                      *  0b00010100
                      *    ||||||||__ SPI serial data transfers start with MSB
                      *    |||||||___ SS is not used as 1-Automaticaly by SPI(0=GPIO)
                      *    ||||||____ First edge occurs at the(1=begining,0=middle) of cycle
                      *    |||||_____ Active-high SPI clock
                      *    ||||______ SPI Configured as Master
                      *    |||_______ SPI Transmit Interrupt Disabled
                      *    ||________ SPI System Enab/Disabled
                      *    |_________ SPI Interrupt Disabled
                      */
    SPI0CR2 = 0x00;   /*  
                      *  0b00000000
                      *    ||||||||__ Separate pins for data input and output.
                      *    |||||||___ SPI clocks operate in wait mode.
                      *    ||||||____ Unimplemented
                      *    |||||_____ SPI data I/O pin acts as an input.
                      *    ||||______ Mode Fault Enab/Disabled
                      *    |||_______ Unimplemented
                      *    ||________ Transfer Width - 8-bit Transfer Width
                      *    |_________ Unimplemented
                      */
    SPI0BR = 0x03;   /*  
                      *  0b00000011
                      *    |||||||| 
                      *    ||||||||
                      *    |||||+++-- Rate Divisor = 1
                      *    |||||_____ Unimplemented
                      *    |||| 
                      *    |||| 
                      *    |+++------ Prescaler Divisor = 0 
                      *    |_________ Unimplemented
                      * 
                      *     Note !!!                     
                      *     BaudRateDivisor = (Prescaler+1)*2^(Rate Divisor+1)
                      *     Baud Rate = BusClock/BaudRateDivisor
                      *     My BaudRate = 6.25Mhz/16 = 390.625kHz 
                      */     
   return;                   
}
/*****************************************************************************/

/**********************************************
 * Wait:                                      *
 * Software Loop, wait between transfers      *
 **********************************************/
void Wait(unsigned int delay)
{
  unsigned int c;
  for(c=0;c<delay;c++) {asm nop;} 
}
/*******************************************************************************/

/**********************************************
 * SPI_enable:                                *
 * Enables the SPI module                     *
 **********************************************/
void SPI_enable(void) 
{
  SPI0CR1 |= 0x40;            // SPICR1_SPE =1  
}
/*******************************************************************************/
/**********************************************
 * SPI_disable:                               *
 * Disables the SPI module                    *
 **********************************************/
void SPI_disable(void) 
{
  SPI0CR1_SPE = 0;            // SPICR1_SPE =0  
}
/*******************************************************************************/



/************************************************************
 * SPI_send_byte:                                           *
 * Parameters: data = data to write                         *
 *                                                          *
 * Return :    None                                         *
 ************************************************************/
void SPI_send_byte(unsigned char data) 
{
  SPIReadStatReg();           // Read status register (possible SPRF, SPTEF)   
  SPIReadDataReg();           // Read receive data register. SPI entirely 
                              // ready for read or write                               
  SPI0DR = data;              // Start transfer - send first (address) byte 
  SPIWaitTransferDone();      // Wait for transfer complete
  SPIWaitReceiveDone();       // You may probably wait too for SPIF flag
  SPIReadStatReg();
  SPIReadDataReg();           // Dummy read data register. SPI                                                              
}
/*******************************************************************************/
/*********************************************
 * SPI_read8_fr8:                            *
 * Parameters: addr = address of register    *
 * Return :    register value                *
 *********************************************/
unsigned char SPI_read_byte()   
{
   unsigned char value=0;      // function cannot directly return register value
   SPIReadStatReg();           // Read status register (possible SPRF, SPTEF)   
   SPIReadDataReg();           // Read receive data register. SPI entirely 
                               // ready for read or write                  
   SPI0DR = 0x00;              // Generate clocks for reading 1 byte of data!
   SPIWaitTransferDone();      // Wait for receive complete
   SPIWaitReceiveDone();       // You may probably wait too for SPIF flag
   value = SPI0DRL;             // read received data and store to result  
   return(value);
}
/*******************************************************************************/


/*********************************************
 * SCIInit:                                *
 * Parameters: None                          *
 * Return :    None                          *
 *********************************************/
void SCIInit(void)
{
   //----- BR = BUSCLK / (16*Baud rate) = 6250000 / (16*9600) = 41 = 0x29 -----      
   SCI0BDH = 0x00;  // prescaller value  
   SCI0BDL = 0x29;  // prescaller = 0x34 
   SCI0CR1 = 0x00;    
   SCI0CR2 = 0x24;  //receive enable, receive interrupt enable
} 
/*******************************************************************************/

/*********************************************
 * SCI0_Interrupt routine:                   *
 * Parameters: None                          *
 * Return :    None                          *
 *********************************************/
#pragma CODE_SEG NON_BANKED
interrupt 20 void SCI0_Isr(void)
{   
 unsigned char scicr2,scisr1;
 scisr1 = SCI0SR1;                          // save status register actual status
 scicr2 = SCI0CR2;                          // save control register actual status

 //if receiver interrupt is enabled and corresponding interrupt flag is set
 if((scicr2 & SCI0CR2_RIE_MASK) && ((scisr1 & (SCI0SR1_OR_MASK | SCI0SR1_RDRF_MASK))))
  {
    if(scisr1 & SCI0SR1_OR_MASK)            // if overrun error do nothing/something
      {
        (void)SCI0DRL;                      // clear interrupt flag 
        // do something
      }
    else
      {
      
        sc0_data_in = SCI0DRL;              // read received character + clear interrupt flag                        
            
        PTT  = ~sc0_data_in<<2;             // display lower half byte at the LED          
        
        SPI_send_byte(sc0_data_in);         // send received data at SPI
      }
  }
}
#pragma CODE_SEG DEFAULT
/*******************************************************************************/


void main(void) {
  /* put your own code here */
  
  GPIOInit();                       // GPIO port settings
  SCIInit();                        // Initialization of SCI
  SPIInit();                        // Initialization of SPI
  SPI_enable();                     // SPI enable
 // Wait(100);                      // Initialization delay for Slave
  EnableInterrupts;

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