/******************************************************************************************************** 
   u8SCI_init 
_________________________________________________________________________________________________________
input parameters:   port          char  (1, 2)
                    baudrate      long  (0-115200)
                    data length   char  (8=0, 9!=0)
                    parity        char  (none=0, even=1, odd=2)
                    TX mode       char  (disabled=0, not inverted=1, inverted = 2)
                    RX mode       char  (disabled=0, not inverted=1, inverted = 2)
                    pin option    char  (default=0, altarnative!=0)
                    *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
                    =                                                                                 =
                    * SCI1: default pins.- TX: PTA1, RX: PTA2 / alternative pins.- TX: PTD6, RX: PTD7 *
                    = SCI2: default pins.- TX: PTE5, RX: PTR6 / alternative pins.- TX: PTF2, RX: PTF1 =
                    *                                                                                 *
                    =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
                    
       
output parameters:  char  (OK=0)
                          (invalid port=1)
                          (baudrate error=2)
                          (parity error=3)
                          (TXmode error=4)
                          (RXmode error=5)
                                              
***check it!!***    Busclock must be defined as SYSTEM_CLOCK                         
                    Interrupt events must be handled by the user              
********************************************************************************************************/

#include "FslTypes.h"
#include "MC9S08JE128.h"
#include "XTWR-S08JE.h"
#include "infrared.h"

UINT8 u8SCI_init(UINT8 port, UINT32 baudrate, UINT8 length, UINT8 parity, UINT8 TXmode, UINT8 RXmode, UINT8 pin_option) 
{
  
    if (0<RXmode>2) return 5;
    if (0<TXmode>2) return 4;
    if (0<parity>2) return 3;
    if (1<baudrate>115200) return 2;
    if (u8Set_baudrate(port, baudrate)) return 1;
    
    
   switch (port) 
   {
    case 1: 
    {
      //setting data length
      if (!length) SCI1C1_M = 0;
      else SCI1C1_M = 1;    
    
      //setting parity
      switch (parity) 
      {
        case 0: 
        {
          SCI1C1_PE = 0;  //parity disabled  
        }break;
        
        case 1: 
        {
          SCI1C1_PE = 1; //parity enabled
          SCI1C1_PT = 0; //even parity  
        }break;
        
        case 2: 
        {
          SCI1C1_PE = 1;  //parity enabled
          SCI1C1_PT = 1;  //odd parity    
        }break;
      }
    
      //transmission data mode
      switch (TXmode) 
      {
        case 0: 
        {
          SCI1C2_TE = 0;      //tx disabled
        }break;
        
        case 1: 
        {
          SCI1C2_TE = 1;      //tx enabled
          SCI1C3_TXINV = 0;   //tx not inverted
        }break;
        
        case 2: 
        {
          SCI1C2_TE = 1;      //tx enabled
          SCI1C3_TXINV = 1;   //tx inverted
        }break;
      }
      
      //reception data mode
      switch (RXmode) 
      {
        case 0: 
        {
          SCI1C2_RE = 0;      //rx disabled
        }break;
        
        case 1: 
        {
          SCI1C2_RE = 1;      //rx enabled
          SCI1S2_RXINV = 0;   //rx not inverted
        }break;
        
        case 2: 
        {
          SCI1C2_RE = 1;      //rx enabled
          SCI1S2_RXINV = 1;   //rx inverted
        }break;
      }
      
      //setting pin options
      if (!pin_option) SOPT3_SCI1PS = 0;
      else SOPT3_SCI1PS = 1;
      
      //starting SCI1 clock
      SCGC1_SCI1 = 1;
    
    }break;

    
    case 2: 
    {
      //setting data length
      if (!length) SCI2C1_M = 0;
      else SCI2C1_M = 1;    
    
      //setting parity
      switch (parity) 
      {
        case 0: 
        {
          SCI2C1_PE = 0;  //parity disabled  
        }break;
        
        case 1: 
        {
          SCI2C1_PE = 1; //parity enabled
          SCI2C1_PT = 0; //even parity  
        }break;
        
        case 2: 
        {
          SCI2C1_PE = 1;  //parity enabled
          SCI2C1_PT = 1;  //odd parity    
        }break;
      }
    
      //transmission data mode
      switch (TXmode) 
      {
        case 0: 
        {
          SCI2C2_TE = 0;      //tx disabled
        }break;
        
        case 1: 
        {
          SCI2C2_TE = 1;      //tx enabled
          SCI2C3_TXINV = 0;   //tx not inverted
        }break;
        
        case 2: 
        {
          SCI2C2_TE = 1;      //tx enabled
          SCI2C3_TXINV = 1;   //tx inverted
        }break;
      }
      
      //reception data mode
      switch (RXmode) 
      {
        case 0: 
        {
          SCI2C2_RE = 0;      //rx disabled
        }break;
        
        case 1: 
        {
          SCI2C2_RE = 1;      //rx enabled
          SCI2S2_RXINV = 0;   //rx not inverted
        }break;
        
        case 2: 
        {
          SCI2C2_RE = 1;      //rx enabled
          SCI2S2_RXINV = 1;   //rx inverted
        }break;
      }
           
      //setting pin options
      if (!pin_option) SOPT3_SCI2PS = 0;
      else SOPT3_SCI2PS = 1;
      
      //starting SCI2 clock
      SCGC1_SCI2 = 1;
    
    }break;
      
   }
   return 0;                  //selection ok
}

/*--------------------------------------------------------------------------------------------------*/ 

UINT8 u8Set_baudrate(UINT8 port, UINT32 baudrate) 
{
  //preprocessing to set baudrate
   UINT16 baud_divisor;
   baud_divisor = (UINT16)((BUS_CLOCK)/(baudrate * 16));
  
   if (1<port>2) return 1;                    //port error
   
   if (port==1) SCI1BD = baud_divisor;
   else if (port==2) SCI2BD = baud_divisor;
   return 0;                                  //selection ok
}

/*--------------------------------------------------------------------------------------------------*/


/***************************************************************************************************** 
   u8IR_TX_init 
______________________________________________________________________________________________________
input parameters:   port            char  (1, 2)
                    drive strength  char (no=0, yes=1, toggle=2)
                    mod source      char (none=0, tpm1ch0=1, tpm1ch1=2, tpm2ch0=3, tpmch1=4)
                    tx int enable   char (disabled=0, enabled!=0)
                    ****global interruptions must be enabled!****

                    ***** modulation frequency (timer config) is not included in this driver. 
                          User must define it *****

output parameters:  char  (OK=0)
                          (invalid port=1)
                          (invalid modulation source=2)
                          (invalid selection=3) 
*****************************************************************************************************/


UINT8 u8IR_TX_init(UINT8 port, UINT8 strength, UINT8 modulation, UINT8 tx_ie)
  {
    if (1<port>2) return 1;
    if (u8modulation_set(port, modulation)) return 2;
    if (u8drive_strength_set(port, strength)) return 3;
      
    switch (port)
      {
        case 1:
        {
          //enabling transmission interrupt
          if (tx_ie) SCI1C2_TIE = 1;
          else SCI1C2_TIE = 0;
               
        }break;
        
        case 2:
        {
          //enabling transmission interrupt
          if (tx_ie) SCI2C2_TIE = 1;
          else SCI2C2_TIE = 0;
          
        }break;
        
      }
      return 0;
  }

/*--------------------------------------------------------------------------------------------------*/

UINT8 u8drive_strength_set(UINT8 port, UINT8 strength)
{
   if (1<port>2) return 1;                    //port error
   if (0<strength>2) return 3;                //selection error   
          
   switch (port)
   {
    case 1:
    {
      switch (strength)
      {
        case 0:
        {
           if(!SOPT3_SCI1PS) PTADS_PTADS1 = 0;               
           //Drive Strength on PTA1 disabled
           else PTDDS_PTDDS6 = 0;                  
           //Drive Strength on PTD6 disabled
        }break;
        
        case 1:
        {
           if(!SOPT3_SCI1PS) PTADS_PTADS1 = 1;               
           //Drive Strength on PTA1 enabled
           else PTDDS_PTDDS6 = 1;                  
           //Drive Strength on PTD6 enabled
        }break;
        
        case 2:
        {
           if(!SOPT3_SCI1PS) PTADS_PTADS1 = ~PTADS_PTADS1;               
           //Drive Strength on PTA1 toggled
           else PTDDS_PTDDS6 = ~PTDDS_PTDDS6;                  
           //Drive Strength on PTD6 toggled
        }break;
      }
    }break;
    
    case 2:
    {
      switch (strength)
      {
        case 0:
        {
           if(!SOPT3_SCI2PS) PTEDS_PTEDS5 = 0;               
           //Drive Strength on PTE5 disabled
           else PTFDS_PTFDS2 = 0;                  
           //Drive Strength on PTF2 disabled
        }break;
        
        case 1:
        {
           if(!SOPT3_SCI2PS) PTEDS_PTEDS5 = 1;               
           //Drive Strength on PTE5 enabled
           else PTFDS_PTFDS2 = 1;                  
           //Drive Strength on PTF2 enabled
        }break;
        
        case 2:
        {
           if(!SOPT3_SCI2PS) PTEDS_PTEDS5 = ~PTEDS_PTEDS5;               
           //Drive Strength on PTE5 toggled
           else PTFDS_PTFDS2 = ~PTFDS_PTFDS2;                  
           //Drive Strength on PTF2 toggled
        }break;
      }
    }break;
   
   }
   return 0;
   //selection ok
}

/*--------------------------------------------------------------------------------------------------*/

UINT8 u8modulation_set(UINT8 port, UINT8 modulation)
{
   if (1<port>2) return 1;                    //port error 
   if (0<modulation>4) return 2;              //invalid modulation source
   
   switch (port)
   {
    case 1:
    {
      switch (modulation)
      {
        case 0:
        {
          SIMIPS_MODTX1 = 0;    //modulation disabled
        }break;
            
        case 1:
        {
          SIMIPS_MTBASE1 = 0;   //SCI1 TX modulated by TPM1 ch0
          SIMIPS_MODTX1 = 1;
        }break;
            
        case 2:
        {
          SIMIPS_MTBASE1 = 1;   //SCI1 TX modulated by TPM1 ch1
          SIMIPS_MODTX1 = 1;
        }break;
            
        case 3:
        {
          SIMIPS_MTBASE1 = 2;   //SCI1 TX modulated by TPM2 ch 0
          SIMIPS_MODTX1 = 1;
        }break;
            
        case 4:
        {
          SIMIPS_MTBASE1 = 3;   //SCI1 TX modulated by TPM2 ch 1
          SIMIPS_MODTX1 = 1;
        }break;
      }
    }break;
    
    case 2:
    {
      if (modulation) return 3;  //modulation not supported by SCI2
    }break;
    
   }
   return 0;
}

/*--------------------------------------------------------------------------------------------------*/


/***************************************************************************************************** 
   u8IR_RX_init 
______________________________________________________________________________________________________
input parameters:   port            char (1, 2) ***only port 1 can be connected to ACMP*** 
                    rx pin option   char (default=0, altarnative=!0)
                    cmp level       char (not used=0, used=1-31)
                    rx int enable   char (disabled=0, enabled!=0) 
                    ****global interruptions must be enabled!****
                    
                    *****Comparator level supports internal reference only in this driver*****

output parameters:  char  (OK=0)
                          (invalid port=1)
                          (invalid comparator level=2)
                          (invalid selection=3) 
*****************************************************************************************************/  

UINT8 u8IR_RX_init(UINT8 port, UINT8 cmp_level, UINT8 rx_ie)
  {
    if (0<cmp_level>31) return 2;
    
    switch(port)
      {
        case 1:
        {
          //comparator configuration
          if(!cmp_level) SIMIPS_RX1IN = 0;   //input directly from RX pin
          else
          {

            /***PRACMP1 init***/  
            
            PRACMPCS = 0;            /* ACMP disabled */
            /*PRACMPCS_ACIEN = 1;*/  /* interrupt */
            PRACMPCS_ACOPE = 1;      /* output on ACMPxO */
            PRACMPC0_ACPSEL = 1;     /* external reference */ /* CMPP1 for XTWR */
            PRACMPC0_ACNSEL = 7;     /* internal programmable reference*/ 
            PRACMPC1_PRGINS = 1;     /* using external Vdd reference (probably 3.3V) */
            PRACMPC2 = 0x02;         /* external analog channel 1 is allowed!!! */
            PRACMPC1_PRGEN = 1;      /* start programmable */
            PRACMPCS_ACEN = 1;       /* ACMP enabled */

            /***PRACMP end***/
            
            SIMIPS_RX1IN = 1;                //input from analog comparator 1 output
            PRACMPC1_PRGOS = cmp_level;      //comparator reference level
          }
         
          //enabling reception interrupt
          if (rx_ie) SCI1C2_RIE = 1;
          else SCI1C2_RIE = 0;
          
        }break; 

    
        case 2:
        {
          if(cmp_level) return 3;             //RX through comparator not supported by SCI2
  
          //enabling reception interrupt
          if (rx_ie) SCI2C2_RIE = 1;
          else SCI2C2_RIE = 0;
          
        }break;
      }
         return 0;
      }
