/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No 
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all 
* applicable laws, including copyright laws. 
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM 
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES 
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS 
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of 
* this software. By using this software, you agree to the additional terms and conditions found by accessing the 
* following link:
* http://www.renesas.com/disclaimer 
*
* Copyright (C) 2016-2017 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
/**********************************************************************************************************************
* File Name    : r_sci_rx.c
* Description  : Functions for using SCI on the RX65N device.
***********************************************************************************************************************
* History : DD.MM.YYYY Version Description
*           01.10.2016 1.00    Initial Release.
*           19.12.2016 1.10    FIT_NO_PTR check added to NULL check.
*                              SCI_CMD_EN_TEI was changed to ineffective, because it is meaningless command.
*           07.03.2017 1.20    Fixed a bug that the interrupt priority level can be changed only in async mode.
***********************************************************************************************************************/

/*****************************************************************************
Includes   <System Includes> , "Project Includes"
******************************************************************************/
#include "platform.h"

#include "r_sci_rx65n_private.h"

/*****************************************************************************
Typedef definitions
******************************************************************************/

/*****************************************************************************
Macro definitions
******************************************************************************/

/*****************************************************************************
Private global variables and functions
******************************************************************************/
#if SCI_CFG_CH0_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci0_txi0_isr, VECT(SCI0,TXI0))
R_PRAGMA_STATIC_INTERRUPT(sci0_rxi0_isr, VECT(SCI0,RXI0))
#endif

#if SCI_CFG_CH1_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci1_txi1_isr, VECT(SCI1,TXI1))
R_PRAGMA_STATIC_INTERRUPT(sci1_rxi1_isr, VECT(SCI1,RXI1))
#endif

#if SCI_CFG_CH2_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci2_txi2_isr, VECT(SCI2,TXI2))
R_PRAGMA_STATIC_INTERRUPT(sci2_rxi2_isr, VECT(SCI2,RXI2))
#endif

#if SCI_CFG_CH3_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci3_txi3_isr, VECT(SCI3,TXI3))
R_PRAGMA_STATIC_INTERRUPT(sci3_rxi3_isr, VECT(SCI3,RXI3))
#endif

#if SCI_CFG_CH4_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci4_txi4_isr, VECT(SCI4,TXI4))
R_PRAGMA_STATIC_INTERRUPT(sci4_rxi4_isr, VECT(SCI4,RXI4))
#endif

#if SCI_CFG_CH5_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci5_txi5_isr, VECT(SCI5,TXI5))
R_PRAGMA_STATIC_INTERRUPT(sci5_rxi5_isr, VECT(SCI5,RXI5))
#endif

#if SCI_CFG_CH6_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci6_txi6_isr, VECT(SCI6,TXI6))
R_PRAGMA_STATIC_INTERRUPT(sci6_rxi6_isr, VECT(SCI6,RXI6))
#endif

#if SCI_CFG_CH7_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci7_txi7_isr, VECT(SCI7,TXI7))
R_PRAGMA_STATIC_INTERRUPT(sci7_rxi7_isr, VECT(SCI7,RXI7))
#endif

#if SCI_CFG_CH8_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci8_txi8_isr, VECT(SCI8,TXI8))
R_PRAGMA_STATIC_INTERRUPT(sci8_rxi8_isr, VECT(SCI8,RXI8))
#endif

#if SCI_CFG_CH9_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci9_txi9_isr, VECT(SCI9,TXI9))
R_PRAGMA_STATIC_INTERRUPT(sci9_rxi9_isr, VECT(SCI9,RXI9))
#endif

#if SCI_CFG_CH10_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci10_txi10_isr, VECT(SCI10,TXI10))
R_PRAGMA_STATIC_INTERRUPT(sci10_rxi10_isr, VECT(SCI10,RXI10))
#endif

#if SCI_CFG_CH11_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci11_txi11_isr, VECT(SCI11,TXI11))
R_PRAGMA_STATIC_INTERRUPT(sci11_rxi11_isr, VECT(SCI11,RXI11))
#endif

#if SCI_CFG_CH12_INCLUDED
R_PRAGMA_STATIC_INTERRUPT(sci12_txi12_isr, VECT(SCI12,TXI12))
R_PRAGMA_STATIC_INTERRUPT(sci12_rxi12_isr, VECT(SCI12,RXI12))
#endif

/*****************************************************************************
* Function Name: sci_mcu_param_check
* Description  : This function parameters check on MCU.
*                 (channel range, interrupt priority, etc...)
* Arguments    : chan -
*                    channel to check
* Return Value : SCI_SUCCESS - 
*                    parameter check all successfully
*                SCI_ERR_BAD_CHAN -
*                    channel number invalid for part
*                SCI_ERR_INVALID_ARG -
*                    interrupt priority out of range
******************************************************************************/
sci_err_t sci_mcu_param_check(uint8_t const chan)
{
    /* channel range parameter check */
    if (SCI_NUM_CH <= chan)
    {
        return SCI_ERR_BAD_CHAN;
    }

    /* interrupt priority configuration parameter check */
    if ((1 > SCI_CFG_ERI_TEI_PRIORITY) || (15 < SCI_CFG_ERI_TEI_PRIORITY))
    {
        return SCI_ERR_INVALID_ARG;
    }

    return SCI_SUCCESS;
} /* End of function sci_mcu_param_check() */

/*****************************************************************************
* Function Name: sci_init_register
* Description  : This function initializes the register for SCI.
* Arguments    : hdl -
*                    handle for channel (ptr to chan control block)
* Return Value : none
******************************************************************************/
void sci_init_register(sci_hdl_t const hdl)
{
    /* SCI transmit enable bit and receive enable bit check & disable */
    while ((0 != hdl->rom->regs->SCR.BIT.TE) || (0 != hdl->rom->regs->SCR.BIT.RE))
    {
        if (0 != hdl->rom->regs->SCR.BIT.TE)
        {
            hdl->rom->regs->SCR.BIT.TE = 0;  // transmit disable
        }
        if (0 != hdl->rom->regs->SCR.BIT.RE)
        {
            hdl->rom->regs->SCR.BIT.RE = 0;  // receive disable
        }
    }

    /* SMR register initialize */
    hdl->rom->regs->SMR.BYTE = 0x00;

    /* SCR register initialize */
    hdl->rom->regs->SCR.BYTE = 0x00;
    
#if SCI_CFG_FIFO_INCLUDED
    if (true == hdl->fifo_ctrl)
    {
        /* SSRFIFO register initialize */
        if (1 == SCI_SSRFIFO_ORER)
        {
            SCI_SSRFIFO_ORER = 0;
        }
        if (1 == SCI_SSRFIFO_PER)
        {
            SCI_SSRFIFO_PER = 0;
        }
        if (1 == SCI_SSRFIFO_FER)
        {
            SCI_SSRFIFO_FER = 0;
        }
        if (1 == SCI_SSRFIFO_RDF)
        {
            hdl->rom->regs->FCR.BIT.RFRST = 0x01;
            SCI_SSRFIFO_RDF = 0;
        }
    }
    else
#endif
    {
        /* SSR register initialize */
        if (1 == SCI_SSR_ORER)
        {
            SCI_SSR_ORER = 0;
        }
        if (1 == SCI_SSR_PER)
        {
            SCI_SSR_PER = 0;
        }
        if (1 == SCI_SSR_FER)
        {
            SCI_SSR_FER = 0;
        }
    }

    /* SCMR register initialize */
    hdl->rom->regs->SCMR.BIT.SMIF = 0;
    hdl->rom->regs->SCMR.BIT.SINV = 0;
    hdl->rom->regs->SCMR.BIT.SDIR = 0;

    /* BRR register initialize */
    hdl->rom->regs->BRR = 0xFF;

    /* SEMR register initialize */
    hdl->rom->regs->SEMR.BIT.BRME    = 0;
    hdl->rom->regs->SEMR.BIT.ABCS    = 0;
    hdl->rom->regs->SEMR.BIT.NFEN    = 0;
    hdl->rom->regs->SEMR.BIT.BGDM    = 0;
    hdl->rom->regs->SEMR.BIT.RXDESEL = 0;

    /* SNFR register initialize */
    hdl->rom->regs->SNFR.BYTE = 0;

    /* SPMR register initialize */
    hdl->rom->regs->SPMR.BIT.CTSE  = 0;
    hdl->rom->regs->SPMR.BIT.CKPOL = 0;
    hdl->rom->regs->SPMR.BIT.CKPH  = 0;

#if SCI_CFG_FIFO_INCLUDED
    if (true == hdl->fifo_ctrl)
    {
        /* FCR register initialize */
        hdl->rom->regs->FCR.BIT.FM    = 0;
        hdl->rom->regs->FCR.BIT.TFRST = 0;
        hdl->rom->regs->FCR.BIT.RFRST = 0;
        hdl->rom->regs->FCR.BIT.TTRG  = 0;
        hdl->rom->regs->FCR.BIT.RTRG  = 8;
    }
#endif

    return;
} /* End of function sci_init_register() */

/*****************************************************************************
* Function Name: sci_init_bit_rate
* Description  : This function determines the best possible settings for the
*                baud rate registers for the specified peripheral clock speed
*                and baud rate. Note that this does not guarantee a low bit 
*                error rate, just the best possible one. The bit rate error is
*                returned in .1% increments. If the hardware cannot support
*                the specified combination, a value of 1000 (100% error) is
*                returned.
*
* NOTE: The transmitter and receiver (TE and RE bits in SCR) must be disabled 
*       prior to calling this function.
*
*       The application must pause for 1 bit time after the BRR register
*       is loaded before transmitting/receiving to allow time for the clock
*       to settle. 
*
* Arguments    : hdl -
*                    Handle for channel (ptr to chan control block)
*                    NOTE: mode element must be already set
*                pclk -
*                    Peripheral clock speed; e.g. 24000000 for 24MHz
*                baud -
*                    Baud rate; 19200, 57600, 115200, etc.
* Return Value : bit error in .1% increments; e.g. 16 = 1.6% bit rate error
*                a value of 1000 denotes 100% error; no registers set
******************************************************************************/
int32_t sci_init_bit_rate(sci_hdl_t const  hdl,
                          uint32_t const   pclk,
                          uint32_t const   baud)
{
    uint32_t i;
    uint32_t num_divisors = 0;
    uint32_t ratio;
    uint32_t tmp;
    baud_divisor_t const *p_baud_info=NULL;

    uint32_t divisor;
    uint32_t int_M;
    float    float_M;
    float    error;
    float    abs_error;

#if SCI_CFG_FIFO_INCLUDED
    uint8_t brr;
#endif

#if SCI_CFG_PARAM_CHECKING_ENABLE
    if ((0 == pclk) || (0 == baud))
    {
        return 1000;
    }
#endif

    /* SELECT PROPER TABLE BASED UPON MODE */
    if (hdl->mode == SCI_MODE_ASYNC)
    {
#if (SCI_CFG_ASYNC_INCLUDED)
        p_baud_info = async_baud;
        num_divisors = NUM_DIVISORS_ASYNC;
#endif
    }
    else
    {   /* SYNC or SSPI */
#if (SCI_CFG_SSPI_INCLUDED || SCI_CFG_SYNC_INCLUDED)
        p_baud_info = sync_baud;
        num_divisors = NUM_DIVISORS_SYNC;
#endif
    }

    /* FIND DIVISOR; table has associated ABCS, BGDM and CKS values */
    /* BRR must be 255 or less */
    /* the "- 1" is ignored in some steps for approximations */
    /* BRR = (PCLK/(divisor * baud)) - 1 */
    /* BRR = (ratio / divisor) - 1 */
    ratio = pclk/baud;
    for(i=0; i < num_divisors; i++)
    {
        if (ratio < (uint32_t)(p_baud_info[i].divisor * 256))
        {
            break;
        }
    }

    /* RETURN IF BRR WILL BE >255 OR LESS THAN 0 */
    if (i == num_divisors)
    {
        return(1000);           // impossible baud rate requested; return 100% error
    }

    divisor = (uint32_t)p_baud_info[i].divisor;
    tmp = ratio/(divisor);      // tmp = PCLK/(baud * divisor) = BRR+1 = N+1
    if(0 == tmp)
    {
        return(1000);            // illegal value; return 100% error
    }

    /* SET BRR, ABCS, BDGM, and CKS */
    tmp = ratio / (divisor/2);  // divide by half the divisor

#if SCI_CFG_FIFO_INCLUDED
    brr = (uint8_t)((tmp & 0x01) ? (tmp/2) : ((tmp/2)-1));
    if (0 == brr)
    {
        if (true == hdl->fifo_ctrl)
        {
            if (1 == hdl->rom->regs->SMR.BIT.CM)
            {
                if (0 == hdl->rom->regs->SMR.BIT.CKS)
                {
                    return(1000);
                }
            }
        }
    }
#endif

    /* if odd, "round up" by ignoring -1; divide by 2 again for rest of divisor */
    hdl->rom->regs->BRR = (uint8_t)((tmp & 0x01) ? (tmp/2) : ((tmp/2)-1));
    hdl->rom->regs->SEMR.BIT.ABCS = p_baud_info[i].abcs;
    hdl->rom->regs->SEMR.BIT.BGDM = p_baud_info[i].bgdm;
    hdl->rom->regs->SMR.BIT.CKS = p_baud_info[i].cks;

    /* CALCULATE BIT RATE ERROR.
     * RETURN IF ERROR LESS THAN 1% OR IF IN SYNCHRONOUS/SSPI MODE.
     */
    tmp = ratio/(divisor);      // tmp = PCLK/(baud * divisor) = BRR+1 = N+1
    error = ( ((float)pclk / ((baud * divisor) * tmp)) - 1) * 100;
    abs_error  = (error < 0) ? (-error) : error;

    if ((abs_error <= 1.0) || (hdl->mode != SCI_MODE_ASYNC))
    {
        hdl->rom->regs->SEMR.BIT.BRME = 0;          // disable MDDR
        return (int32_t)(error*10);
    }

    /* CALCULATE M ASSUMING A 0% ERROR then WRITE REGISTER */
    hdl->rom->regs->BRR = (uint8_t)(tmp-1);
    float_M = ((float)((baud * divisor) * 256) * tmp) / pclk;
    float_M *= 2;
    int_M = (uint32_t)float_M;
    int_M = (int_M & 0x01) ? ((int_M/2) + 1) : (int_M/2);

    hdl->rom->regs->MDDR = (uint8_t)int_M;      // write M
    hdl->rom->regs->SEMR.BIT.BRME = 1;          // enable MDDR
    error = (( (float)(pclk) / (((divisor * tmp) * baud) * ((float)(256)/int_M)) ) - 1) * 100;

    return (int32_t)(error*10);
} /* End of function sci_init_bit_rate() */

/*****************************************************************************
* Function Name: sci_initialize_ints
* Description  : This function sets priority, clears flags, and sets 
*                interrupts in both the ICU and SCI peripheral. These include 
*                RXI, TXI, TEI, and ERI/GROUP12 interrupts.
* Arguments    : hdl - 
*                    handle for channel (ptr to chan control block)
*                priority -
*                    priority for interrupts
* Return Value : none
******************************************************************************/
void sci_initialize_ints(sci_hdl_t const hdl,
                         uint8_t const   priority)
{
    volatile bsp_int_ctrl_t group_priority;

    /* SET PRIORITY FOR INTERRUPTS */
    *hdl->rom->ipr_rxi = priority;          // can set separately using Control()
    *hdl->rom->ipr_txi = priority;

    group_priority.ipl = 0x00000000;
#if ((SCI_CFG_CH0_INCLUDED == 1) || (SCI_CFG_CH1_INCLUDED == 1) || (SCI_CFG_CH2_INCLUDED == 1) || \
     (SCI_CFG_CH3_INCLUDED == 1) || (SCI_CFG_CH4_INCLUDED == 1) || (SCI_CFG_CH5_INCLUDED == 1) || \
     (SCI_CFG_CH6_INCLUDED == 1) || (SCI_CFG_CH7_INCLUDED == 1) || (SCI_CFG_CH12_INCLUDED == 1))
    if (SCI_CFG_ERI_TEI_PRIORITY > IPR(ICU, GROUPBL0))
    {
        group_priority.ipl = (uint32_t)SCI_CFG_ERI_TEI_PRIORITY;
    }
#endif

#if ((SCI_CFG_CH8_INCLUDED == 1) || (SCI_CFG_CH9_INCLUDED == 1))
    if (SCI_CFG_ERI_TEI_PRIORITY > IPR(ICU, GROUPBL1))
    {
        group_priority.ipl = (uint32_t)SCI_CFG_ERI_TEI_PRIORITY;
    }
#endif

#if ((SCI_CFG_CH10_INCLUDED == 1) || (SCI_CFG_CH11_INCLUDED == 1))
    if (SCI_CFG_ERI_TEI_PRIORITY > IPR(ICU, GROUPAL0))
    {
        group_priority.ipl = (uint32_t)SCI_CFG_ERI_TEI_PRIORITY;
    }
#endif

    /* DISABLE INTERRUPTS */
    DISABLE_ERI_INT;
    DISABLE_RXI_INT;
    DISABLE_TXI_INT;
    DISABLE_TEI_INT;

    /* CLEAR INTERRUPT FLAGS */
    *hdl->rom->ir_rxi = 0;
    *hdl->rom->ir_txi = 0;
    (*hdl->rom->icu_grp) &= (~hdl->rom->tei_ch_mask);
    (*hdl->rom->icu_grp) &= (~hdl->rom->eri_ch_mask);

    /* REGISTER GROUP INTERRUPTS WITH BSP */
    #if SCI_CFG_TEI_INCLUDED
    R_BSP_InterruptWrite(hdl->rom->tei_vector, hdl->rom->tei_isr);
    #endif
    R_BSP_InterruptWrite(hdl->rom->eri_vector, hdl->rom->eri_isr);

    /* ENABLE GROUP INTERRUPTS */
    R_BSP_InterruptControl(hdl->rom->eri_vector, BSP_INT_CMD_GROUP_INTERRUPT_ENABLE, (void *)&group_priority);

    /* ENABLE ERI AND RXI INTERRUPTS REQUESTS */
    ENABLE_ERI_INT;
    ENABLE_RXI_INT;

    /* ENABLE INTERRUPTS IN SCI PERIPHERAL */
    /* Note: Enable interrupts after xcvr or will get "extra" interrupt */
    hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;    // enable TE, RE, TXI, and RXI/ERI

    return;    
} /* End of function sci_initialize_ints() */

/*****************************************************************************
* Function Name: sci_disable_ints
* Description  : This function disable interrupts in both the ICU and SCI 
*                peripheral. These include RXI, TXI, TEI, ERI, and group
*                interrupts.
* Arguments    : hdl - 
*                    handle for channel (ptr to chan control block)
* Return Value : none
******************************************************************************/
void sci_disable_ints(sci_hdl_t const hdl)
{
    volatile bsp_int_ctrl_t group_priority;

    /* disable ICU interrupts */
    DISABLE_RXI_INT;
    DISABLE_TXI_INT;
    DISABLE_ERI_INT;
    DISABLE_TEI_INT;
    
    /* disable peripheral interrupts and xcvr (TE and RE) */
    hdl->rom->regs->SCR.BYTE = 0;

    /* disable group interrupts */
    group_priority.ipl = 0x00000000;
    R_BSP_InterruptControl(hdl->rom->eri_vector, BSP_INT_CMD_GROUP_INTERRUPT_DISABLE, (void *)&group_priority);

    return;
} /* End of function sci_disable_ints() */
#if (SCI_CFG_ASYNC_INCLUDED)
/*****************************************************************************
* sciN_txiN_isr 
*  
* Description  : TXI interrupt routines for every SCI channel
******************************************************************************/

#if SCI_CFG_CH0_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci0_txi0_isr(void)
{
    txi_handler(&ch0_ctrl);
} /* End of function sci0_txi0_isr() */
#endif

#if SCI_CFG_CH1_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci1_txi1_isr(void)
{
    txi_handler(&ch1_ctrl);
} /* End of function sci1_txi1_isr() */
#endif

#if SCI_CFG_CH2_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci2_txi2_isr(void)
{
    txi_handler(&ch2_ctrl);
} /* End of function sci2_txi2_isr() */
#endif

#if SCI_CFG_CH3_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci3_txi3_isr(void)
{
    txi_handler(&ch3_ctrl);
} /* End of function sci3_txi3_isr() */
#endif

#if SCI_CFG_CH4_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci4_txi4_isr(void)
{
    txi_handler(&ch4_ctrl);
} /* End of function sci4_txi4_isr() */
#endif

#if SCI_CFG_CH5_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci5_txi5_isr(void)
{
    txi_handler(&ch5_ctrl);
} /* End of function sci5_txi5_isr() */
#endif

#if SCI_CFG_CH6_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci6_txi6_isr(void)
{
    txi_handler(&ch6_ctrl);
} /* End of function sci6_txi6_isr() */
#endif

#if SCI_CFG_CH7_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci7_txi7_isr(void)
{
    txi_handler(&ch7_ctrl);
} /* End of function sci7_txi7_isr() */
#endif

#if SCI_CFG_CH8_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci8_txi8_isr(void)
{
    txi_handler(&ch8_ctrl);
} /* End of function sci8_txi8_isr() */
#endif

#if SCI_CFG_CH9_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci9_txi9_isr(void)
{
    txi_handler(&ch9_ctrl);
} /* End of function sci9_txi9_isr() */
#endif

#if SCI_CFG_CH10_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci10_txi10_isr(void)
{
    txi_handler(&ch10_ctrl);
} /* End of function sci10_txi10_isr() */
#endif

#if SCI_CFG_CH11_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci11_txi11_isr(void)
{
    txi_handler(&ch11_ctrl);
} /* End of function sci11_txi11_isr() */
#endif

#if SCI_CFG_CH12_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci12_txi12_isr(void)
{
    txi_handler(&ch12_ctrl);
} /* End of function sci12_txi12_isr() */
#endif

#endif

#if SCI_CFG_TEI_INCLUDED
/*****************************************************************************
* sciN_teiN_isr 
*  
* Description  : TEI interrupt routines for every SCI channel.
*                BSP gets main group interrupt, then vectors to/calls these
*                "interrupts"/callbacks.
******************************************************************************/

#if SCI_CFG_CH0_INCLUDED
void sci0_tei0_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch0_ctrl);
} /* End of function sci0_tei0_isr() */
#endif

#if SCI_CFG_CH1_INCLUDED
void sci1_tei1_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch1_ctrl);
} /* End of function sci1_tei1_isr() */
#endif

#if SCI_CFG_CH2_INCLUDED
void sci2_tei2_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch2_ctrl);
} /* End of function sci2_tei2_isr() */
#endif

#if SCI_CFG_CH3_INCLUDED
void sci3_tei3_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch3_ctrl);
} /* End of function sci3_tei3_isr() */
#endif

#if SCI_CFG_CH4_INCLUDED
void sci4_tei4_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch4_ctrl);
} /* End of function sci4_tei4_isr() */
#endif

#if SCI_CFG_CH5_INCLUDED
void sci5_tei5_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch5_ctrl);
} /* End of function sci5_tei5_isr() */
#endif

#if SCI_CFG_CH6_INCLUDED
void sci6_tei6_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch6_ctrl);
} /* End of function sci6_tei6_isr() */
#endif

#if SCI_CFG_CH7_INCLUDED
void sci7_tei7_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch7_ctrl);
} /* End of function sci7_tei7_isr() */
#endif

#if SCI_CFG_CH8_INCLUDED
void sci8_tei8_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch8_ctrl);
} /* End of function sci8_tei8_isr() */
#endif

#if SCI_CFG_CH9_INCLUDED
void sci9_tei9_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch9_ctrl);
} /* End of function sci9_tei9_isr() */
#endif

#if SCI_CFG_CH10_INCLUDED
void sci10_tei10_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch10_ctrl);
} /* End of function sci10_tei10_isr() */
#endif

#if SCI_CFG_CH11_INCLUDED
void sci11_tei11_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch11_ctrl);
} /* End of function sci11_tei11_isr() */
#endif

#if SCI_CFG_CH12_INCLUDED
void sci12_tei12_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    tei_handler(&ch12_ctrl);
} /* End of function sci12_tei12_isr() */
#endif

#endif

/*****************************************************************************
* sciN_rxiN_isr
*  
* Description  : RXI interrupt routines for every SCI channel
******************************************************************************/

#if SCI_CFG_CH0_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci0_rxi0_isr(void)
{
    rxi_handler(&ch0_ctrl);
} /* End of function sci0_rxi0_isr() */
#endif

#if SCI_CFG_CH1_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci1_rxi1_isr(void)
{
    rxi_handler(&ch1_ctrl);
} /* End of function sci1_rxi1_isr() */
#endif

#if SCI_CFG_CH2_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci2_rxi2_isr(void)
{
    rxi_handler(&ch2_ctrl);
} /* End of function sci2_rxi2_isr() */
#endif

#if SCI_CFG_CH3_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci3_rxi3_isr(void)
{
    rxi_handler(&ch3_ctrl);
} /* End of function sci3_rxi3_isr() */
#endif

#if SCI_CFG_CH4_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci4_rxi4_isr(void)
{
    rxi_handler(&ch4_ctrl);
} /* End of function sci4_rxi4_isr() */
#endif

#if SCI_CFG_CH5_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci5_rxi5_isr(void)
{
    rxi_handler(&ch5_ctrl);
} /* End of function sci5_rxi5_isr() */
#endif

#if SCI_CFG_CH6_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci6_rxi6_isr(void)
{
    rxi_handler(&ch6_ctrl);
} /* End of function sci6_rxi6_isr() */
#endif

#if SCI_CFG_CH7_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci7_rxi7_isr(void)
{
    rxi_handler(&ch7_ctrl);
} /* End of function sci7_rxi7_isr() */
#endif

#if SCI_CFG_CH8_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci8_rxi8_isr(void)
{
    rxi_handler(&ch8_ctrl);
} /* End of function sci8_rxi8_isr() */
#endif

#if SCI_CFG_CH9_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci9_rxi9_isr(void)
{
    rxi_handler(&ch9_ctrl);
} /* End of function sci9_rxi9_isr() */
#endif

#if SCI_CFG_CH10_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci10_rxi10_isr(void)
{
    rxi_handler(&ch10_ctrl);
} /* End of function sci10_rxi10_isr() */
#endif

#if SCI_CFG_CH11_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci11_rxi11_isr(void)
{
    rxi_handler(&ch11_ctrl);
} /* End of function sci11_rxi11_isr() */
#endif

#if SCI_CFG_CH12_INCLUDED
R_ATTRIB_STATIC_INTERRUPT void sci12_rxi12_isr(void)
{
    rxi_handler(&ch12_ctrl);
} /* End of function sci12_rxi12_isr() */
#endif

/*****************************************************************************
* sciN_eriN_isr 
*  
* Description  : ERI interrupt routines for every SCI channel.
*                BSP gets main group interrupt, then vectors to/calls these
*                "interrupts"/callbacks.
******************************************************************************/

#if SCI_CFG_CH0_INCLUDED
void sci0_eri0_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch0_ctrl);
} /* End of function sci0_eri0_isr() */
#endif

#if SCI_CFG_CH1_INCLUDED
void sci1_eri1_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch1_ctrl);
} /* End of function sci1_eri1_isr() */
#endif

#if SCI_CFG_CH2_INCLUDED
void sci2_eri2_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch2_ctrl);
} /* End of function sci2_eri2_isr() */
#endif

#if SCI_CFG_CH3_INCLUDED
void sci3_eri3_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch3_ctrl);
} /* End of function sci3_eri3_isr() */
#endif

#if SCI_CFG_CH4_INCLUDED
void sci4_eri4_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch4_ctrl);
} /* End of function sci4_eri4_isr() */
#endif

#if SCI_CFG_CH5_INCLUDED
void sci5_eri5_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch5_ctrl);
} /* End of function sci5_eri5_isr() */
#endif

#if SCI_CFG_CH6_INCLUDED
void sci6_eri6_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch6_ctrl);
} /* End of function sci6_eri6_isr() */
#endif

#if SCI_CFG_CH7_INCLUDED
void sci7_eri7_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch7_ctrl);
} /* End of function sci7_eri7_isr() */
#endif

#if SCI_CFG_CH8_INCLUDED
void sci8_eri8_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch8_ctrl);
} /* End of function sci8_eri8_isr() */
#endif

#if SCI_CFG_CH9_INCLUDED
void sci9_eri9_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch9_ctrl);
} /* End of function sci9_eri9_isr() */
#endif

#if SCI_CFG_CH10_INCLUDED
void sci10_eri10_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch10_ctrl);
} /* End of function sci10_eri10_isr() */
#endif

#if SCI_CFG_CH11_INCLUDED
void sci11_eri11_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch11_ctrl);
} /* End of function sci11_eri11_isr() */
#endif

#if SCI_CFG_CH12_INCLUDED
void sci12_eri12_isr(void *cb_args)
{
    R_INTERNAL_NOT_USED(cb_args);
    eri_handler(&ch12_ctrl);
} /* End of function sci12_eri12_isr() */
#endif

#if (SCI_CFG_ASYNC_INCLUDED)
/*****************************************************************************
* Function Name: sci_async_cmds
* Description  : This function configures non-standard UART hardware and
*                performs special software operations.
*
* Arguments    : hdl -
*                    handle for channel (ptr to chan control block)
*                cmd -
*                    command to run
*                p_args -
*                    pointer argument(s) specific to command
* Return Value : SCI_SUCCESS -
*                    Command completed successfully.
*                SCI_ERR_NULL_PTR -
*                    p_args is NULL when required for cmd
*                SCI_ERR_INVALID_ARG -
*                    The cmd value or p_args contains an invalid value.
******************************************************************************/
sci_err_t sci_async_cmds(sci_hdl_t const hdl,
                         sci_cmd_t const cmd,
                         void            *p_args)
{
    sci_err_t   err=SCI_SUCCESS;
    int32_t     bit_err;
    uint32_t    slow_baud;

#if SCI_CFG_PARAM_CHECKING_ENABLE
    if (((NULL == p_args) || (FIT_NO_PTR == p_args))
     && ((SCI_CMD_TX_Q_BYTES_FREE == cmd) || (SCI_CMD_RX_Q_BYTES_AVAIL_TO_READ == cmd)))
    {
        return SCI_ERR_NULL_PTR;
    }
#endif

    switch(cmd)
    {
    case (SCI_CMD_EN_NOISE_CANCEL):
        hdl->rom->regs->SCR.BYTE &= (uint8_t) (~SCI_EN_XCVR_MASK);
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SEMR.BIT.NFEN = 1;      /* enable noise filter */
        hdl->rom->regs->SNFR.BYTE = 0;          /* clock divided by 1 (default) */
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    case (SCI_CMD_OUTPUT_BAUD_CLK):
        hdl->rom->regs->SCR.BYTE &= (uint8_t) (~SCI_EN_XCVR_MASK);
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SCR.BIT.CKE = 0x01;     /* output baud clock on SCK pin */
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    case (SCI_CMD_START_BIT_EDGE):
        hdl->rom->regs->SCR.BYTE &= (uint8_t) (~SCI_EN_XCVR_MASK);
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SEMR.BIT.RXDESEL = 1;   /* detect start bit on falling edge */
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

#if SCI_CFG_TEI_INCLUDED
    case (SCI_CMD_EN_TEI):  /* SCI_CMD_EN_TEI is obsolete command, but it exists only for compatibility with older version. */
    break;
#endif

    case (SCI_CMD_TX_Q_FLUSH):
        DISABLE_TXI_INT;
        R_BYTEQ_Flush(hdl->u_tx_data.que);
        ENABLE_TXI_INT;
    break;

    case (SCI_CMD_RX_Q_FLUSH):
        DISABLE_RXI_INT;
        R_BYTEQ_Flush(hdl->u_rx_data.que);
        ENABLE_RXI_INT;
    break;

    case (SCI_CMD_TX_Q_BYTES_FREE):
        R_BYTEQ_Unused(hdl->u_tx_data.que, (uint16_t *) p_args);
    break;

    case (SCI_CMD_RX_Q_BYTES_AVAIL_TO_READ):
        R_BYTEQ_Used(hdl->u_rx_data.que, (uint16_t *) p_args);
    break;

    case (SCI_CMD_GENERATE_BREAK):

        /* flush transmit queue */
        DISABLE_TXI_INT;
        R_BYTEQ_Flush(hdl->u_tx_data.que);
        ENABLE_TXI_INT;

        /* NOTE: the following steps will abort anything being sent */

        /* set baud rate 1.5x slower */
        slow_baud = (hdl->baud_rate << 1) / 3;
        hdl->rom->regs->SCR.BYTE &= (uint8_t) (~SCI_EN_XCVR_MASK);
        SCI_SCR_DUMMY_READ;
        bit_err = sci_init_bit_rate(hdl, hdl->pclk_speed, slow_baud);
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
        if (1000 == bit_err)
        {
            err = SCI_ERR_INVALID_ARG;
        }
        else
        {   
            /* transmit "0" and wait for completion */
            SCI_TDR(0);
            while (0 == hdl->rom->regs->SSR.BIT.TEND)
            {
                R_NOP();
            }

            /* restore original baud rate */
            hdl->rom->regs->SCR.BYTE &= (uint8_t) (~SCI_EN_XCVR_MASK);
            SCI_SCR_DUMMY_READ;
            sci_init_bit_rate(hdl, hdl->pclk_speed, hdl->baud_rate);
            SCI_IR_TXI_CLEAR;
            hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
        }
    break;

    default:
        err = SCI_ERR_INVALID_ARG;
    break;
    }

    return err;
} /* End of function sci_async_cmds() */
#endif

#if (SCI_CFG_SSPI_INCLUDED || SCI_CFG_SYNC_INCLUDED)
/*****************************************************************************
* Function Name: sci_sync_cmds
* Description  : This function performs special software operations specific
*                to the SSPI and SYNC protocols.
*
* Arguments    : hdl -
*                    handle for channel (ptr to chan control block)
*                cmd -
*                    command to run
*                p_args -
*                    pointer argument(s) specific to command
* Return Value : SCI_SUCCESS -
*                    Command completed successfully.
*                SCI_ERR_NULL_PTR -
*                    p_args is NULL when required for cmd
*                SCI_ERR_INVALID_ARG -
*                    The cmd value or p_args contains an invalid value.
*                    May be due to mode channel is operating in.
******************************************************************************/
sci_err_t sci_sync_cmds(sci_hdl_t const hdl,
                        sci_cmd_t const cmd,
                        void            *p_args)
{
    sci_spi_mode_t  spi_mode;
    sci_cb_args_t   args;
    sci_err_t       err=SCI_SUCCESS;

    switch (cmd)
    {
    case (SCI_CMD_CHECK_XFER_DONE):
        if (hdl->tx_idle == false)
        {
            err = SCI_ERR_XFER_NOT_DONE;
        }
    break;

    case (SCI_CMD_XFER_LSB_FIRST):
        hdl->rom->regs->SCR.BYTE &= ~SCI_EN_XCVR_MASK;
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SCMR.BIT.SDIR = 0;
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    case (SCI_CMD_XFER_MSB_FIRST):
        hdl->rom->regs->SCR.BYTE &= ~SCI_EN_XCVR_MASK;
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SCMR.BIT.SDIR = 1;
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    case (SCI_CMD_INVERT_DATA):
        hdl->rom->regs->SCR.BYTE &= ~SCI_EN_XCVR_MASK;
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SCMR.BIT.SINV ^= 1;
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    case (SCI_CMD_ABORT_XFER):

        /* disable receive interrupts in ICU and peripheral */
        DISABLE_RXI_INT;
        DISABLE_ERI_INT;

        hdl->rom->regs->SCR.BYTE &= ~(SCI_SCR_REI_MASK | SCI_SCR_RE_MASK | SCI_SCR_TE_MASK);

        hdl->tx_cnt = 0;
        hdl->tx_dummy = false;
        hdl->tx_idle = true;

        /* Do callback if available */
        if ((hdl->callback != NULL) && (hdl->callback != FIT_NO_FUNC))
        {
            args.hdl = hdl;
            args.event = SCI_EVT_XFER_ABORTED;
            hdl->callback((void *)&args);
        }

        *hdl->rom->ir_rxi = 0;                  /* clear rxi interrupt flag */
        *hdl->rom->icu_grp &= ~hdl->rom->eri_ch_mask;  /* clear eri interrupt flag */

        ENABLE_ERI_INT;                         /* enable rx err interrupts in ICU */
        ENABLE_RXI_INT;                         /* enable receive interrupts in ICU */

        /* Enable receive interrupt in peripheral after rcvr or will get "extra" interrupt */
        hdl->rom->regs->SCR.BYTE |= SCI_SCR_RE_MASK | SCI_SCR_TE_MASK;
        hdl->rom->regs->SCR.BYTE |= SCI_SCR_REI_MASK;
    break;

    case (SCI_CMD_CHANGE_SPI_MODE):
#if SCI_CFG_PARAM_CHECKING_ENABLE
        spi_mode = *((sci_spi_mode_t *)p_args);

        if (hdl->mode != SCI_MODE_SSPI)
        {
            return SCI_ERR_INVALID_ARG;
        }
        if ((p_args == NULL) || (p_args == FIT_NO_PTR))
        {
            return SCI_ERR_NULL_PTR;
        }
        if ((spi_mode != SCI_SPI_MODE_0) && (spi_mode != SCI_SPI_MODE_1)
          && (spi_mode != SCI_SPI_MODE_2) && (spi_mode != SCI_SPI_MODE_3))
        {
            return SCI_ERR_INVALID_ARG;
        }
#endif
        hdl->rom->regs->SCR.BYTE &= ~SCI_EN_XCVR_MASK;
        SCI_SCR_DUMMY_READ;
        hdl->rom->regs->SPMR.BYTE &= 0x3F;      /* clear previous mode */
        hdl->rom->regs->SPMR.BYTE |= *((uint8_t *)p_args);
        SCI_IR_TXI_CLEAR;
        hdl->rom->regs->SCR.BYTE |= SCI_EN_XCVR_MASK;
    break;

    default:
        err = SCI_ERR_INVALID_ARG;
    break;
    }

    return err;
} /* End of function sci_sync_cmds() */
#endif

