/*******************************************************************************
* 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) 2014 Renesas Electronics Corporation. All rights reserved.
*******************************************************************************/
/*******************************************************************************
* File Name   : sample_scux.c
* Description : This module is sample of audio control.
******************************************************************************/

/******************************************************************************
Includes   <System Includes> , "Project Includes"
******************************************************************************/
#include <stdio.h>
#include "r_typedefs.h"
#include "iodefine.h"
#include "drv_scux_register.h"
#include "Renesas_RZ_A1.h"
#include "drv_scux.h"
#include "dev_drv.h"
#include "dec_scux.h"
#include "audio_dma.h"
#include "cmsis_os.h"
#include "ff.h"
#include "dec.h"
#include "usb_audio.h"

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

/* DMA channel number */
#define DMA_CH_MEM_TO_SCUX             DMA_CHANNEL3         /* Memory(Fixed Audio) to SCUX */
#define DMA_CH_SCUX_TO_MEM             DMA_CHANNEL4         /* SCUX to Memory(Output buffer) */

/* return value of callback function */
#define SCUX_E_USER_PROC         (-10)

enum scux_dma_setting_id
{
    DMA_MEM_TO_SCUX2
    ,DMA_SCUX2_TO_MEM
    ,NUM_DMA_SETTING_ID
};

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

typedef enum scux_intreq_bit_inf
{
    SCUX_DEVCR_BIT_DEVCUF
    ,SCUX_DEVCR_BIT_DEVCOF
    ,SCUX_DEVCR_BIT_DEVCOL
    ,SCUX_DEVCR_BIT_DEVCIUF
    ,SCUX_UEVCR_BIT_UEVCUF
    ,SCUX_UEVCR_BIT_UEVCOF
    ,SCUX_UEVCR_BIT_UEVCOL
    ,SCUX_SEVCR_BIT_EVCUF
    ,SCUX_SEVCR_BIT_EVCOF
    ,SCUX_SEVCR_BIT_EVCWAIT
    ,SCUX_VEVCR_BIT_VEVCZCM7
    ,SCUX_VEVCR_BIT_VEVCZCM6
    ,SCUX_VEVCR_BIT_VEVCZCM5
    ,SCUX_VEVCR_BIT_VEVCZCM4
    ,SCUX_VEVCR_BIT_VEVCZCM3
    ,SCUX_VEVCR_BIT_VEVCZCM2
    ,SCUX_VEVCR_BIT_VEVCZCM1
    ,SCUX_VEVCR_BIT_VEVCZCM0
    ,SCUX_VEVCR_BIT_VEVCVR
    ,NUM_SCUX_INTREQ_BIT_INF
} scux_intreq_bit_inf_t;

typedef struct scux_int
{
    void (* callback)(const uint32_t);       /* Callback interrupt function pointer */
    uint8_t prio;                                           /* Interrupt priority level */
} scux_int_t;

typedef struct scux_dma_setting
{
    uint32_t dma_ch;
    uint32_t direct;                                      /* Transfer direction */
    uint32_t module_name;                           /* Name of Transmit peripheral module */
    bool_t transfer_continue;             /* Transfer continuation */
    fp_type user_trnend_func;                /* Callback Interrupt function */
} scux_dma_setting_t;

typedef enum audio_control_sts
{
    AUDIO_RESET
    ,AUDIO_SETUP
    ,AUDIO_PLAY
    ,AUDIO_PAUSE
    ,AUDIO_ERROR
} audio_control_sts_t;

/******************************************************************************
Imported global variables and functions (from other files)
******************************************************************************/
extern uint8_t * AOUT_Get_SrcOutWriteBuffInfo(uint32_t *buff_size);
extern uint8_t * AOUT_Get_SrcOutReadBuffInfo(uint32_t *buff_size);
extern void AOUT_Set_SrcOutWp(void);
/******************************************************************************
Exported global variables and functions (to be accessed by other files)
******************************************************************************/

/******************************************************************************
Private global variables and functions
******************************************************************************/
/* ==== Prototype declaration ==== */
static void InitParam (void);

/* ---- DMA control Functions ---- */
static int32_t DmaScuxSetup (const uint32_t dma_id, const uint32_t scux_ch);
static int32_t DmaScuxAdsSet (const uint32_t dma_id,
                              volatile const void * const buf,
                              const uint32_t buf_size);
static int32_t DmaScuxTxRegPause (const uint32_t dma_id, const bool_t pause_req);
static int32_t DmaScuxToOutBufStop (const uint32_t dma_id);
static int32_t DmaScuxToOutBufStart (const uint32_t dma_id);
static int32_t DmaFixedToScuxStart (const uint32_t dma_id);

/* ---- Callback Functions from SCUX Driver ---- */
static int32_t CallbackSetScuxInt (const uint32_t scux_ch);
static int32_t CallbackSetScuxDmac (const uint32_t scux_ch);

/* ---- Callback Interrupt Functions ---- */
/* from DMAC */
static void CallbackIntDmaMemToScux(void *vpBuff);
static void CallbackIntDmaScuxToMem(void *vpBuff);
/* from SCUX */
static void CallbackIntSrc0 (const uint32_t int_req);
static void CallbackIntSrc1 (const uint32_t int_req);
static void CallbackIntSrc2 (const uint32_t int_req);
static void CallbackIntSrc3 (const uint32_t int_req);
static void CallbackIntFfd1 (const uint32_t int_req);
static void CallbackIntFfd2 (const uint32_t int_req);
static void CallbackIntFfd3 (const uint32_t int_req);
static void CallbackIntFfu0 (const uint32_t int_req);
static void CallbackIntFfu2 (const uint32_t int_req);
static void CallbackIntFfu3 (const uint32_t int_req);
static void CallbackIntDvu0 (const uint32_t int_req);
static void CallbackIntDvu1 (const uint32_t int_req);
static void CallbackIntDvu2 (const uint32_t int_req);

/* ---- SCUX Error Interrupt Count Functions ---- */
static void ClrScuxErrIntCount (void);
static void SetScuxErrIntCount (const uint32_t scux_ch, const uint32_t err_id, const uint32_t int_req);


/* ==== Global variables ==== */

/* Initial value for DVU Configuration */
static const scux_config_dvu_arg_t scux_config_dvu_init_tbl =
{
    0                                          /* zc_mute */
    ,DVU_PERIOD_1                              /* ramp_vol_up */
    ,DVU_PERIOD_1                              /* ramp_vol_down */
    ,0                                         /* ramp_gain */
    ,SCUX_MIN_RAMP_WAIT                        /* ramp_wait_time */
    ,{0x100000, 0x100000, 0, 0, 0, 0, 0, 0}    /* vol_value */
};

/* Initial value for MIX Configuration */
static const scux_config_mix_arg_t scux_config_mix_init_tbl =
{
    {0, 0, 0, 0}                  /* mix_gain */
};

/* Initial values for setup_arg */
static const scux_setup_arg_t scux_setup_init_tbl =
{
    FFD_SRC2_FFU                      /* pass_select */
    ,NUM_AUDIO_CH_2                   /* audio_channel */
    ,BIT_LENGTH_24                    /* bit_length */
    ,SYNC_SRC                         /* src_mode */
    ,REQ_SIZE_8                       /* ffd_request_size */
    ,REQ_SIZE_8                       /* ffu_request_size */
    ,FS_44100                         /* output_fs */
    ,FS_44100                         /* input_fs */
    ,false                            /* src_bypass_mode */
    ,SCUX_NO_WAIT                     /* wait_time */
    ,LOW_DELAY_NON                    /* low_delay */
    ,SCUX_MIN_FS_RATIO_98             /* min_fs_ratio */
    ,true                             /* dvu_bypass_mode */
    ,false                            /* dvu_zc_mute_mode */
    ,0                                /* dvu_ramp_mode */
    ,false                            /* dvu_vol_mode */
    ,false                            /* src_use_channel_exch */
    ,{0, 0, 0, 0, 0, 0, 0, 0}         /* src_channel_exch */
    ,SELECT_NON                       /* mix_output_select */
    ,VOL_STEP_MIXER                   /* mix_mode */
    ,MIX_PERIOD_1                     /* mix_vol_up */
    ,MIX_PERIOD_1                     /* mix_vol_down */
    ,false                            /* mix_use_channel_exch */
    ,{0, 0, 0, 0, 0, 0, 0, 0}         /* mix_channel_exch */
};




/* DMA setting data table for each Use Case */
static const scux_dma_setting_t scux_dma_setting_tbl[NUM_DMA_SETTING_ID] =
{
    { DMA_CH_MEM_TO_SCUX, DMA_AUDIO_TX, DMA_SCUX, false,  &CallbackIntDmaMemToScux }       /* DMA_MEM_TO_SCUX2 */
    , { DMA_CH_SCUX_TO_MEM, DMA_AUDIO_RX, DMA_SCUX, false, &CallbackIntDmaScuxToMem }      /* DMA_SCUX2_TO_MEM */
};

static scux_setup_arg_t      current_setup_arg;                               /* For usecase 1-6 */
static scux_setup_arg_t      current_setup_arg_ssif;                          /* For SSIF input of Use Case 7  */
static scux_setup_arg_t      current_setup_arg_fixed;                         /* For fixed data input of SCUX Use Case 7 */
static scux_config_dvu_arg_t current_config_dvu_arg;
static scux_config_mix_arg_t current_config_mix_arg;
static uint32_t              scux_err_int_count[NUM_SCUX_CH][NUM_SCUX_ERRINT_ID];

static audio_control_sts_t audio_sts;

/******************************************************************************
* Function Name: SCUX_Init
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_Init (scux_fs_t input_fs, scux_fs_t output_fs)
{
    int32_t ret;
    scux_callback_t scux_callback_func;

    /* ==== Reset SCUX ==== */
    R_SCUX_Reset();

    /* ==== Clear error interrupt counter ==== */
    ClrScuxErrIntCount();

    /* ==== Initialize SCUX Parameter ==== */
    current_config_dvu_arg = scux_config_dvu_init_tbl;
    current_config_mix_arg = scux_config_mix_init_tbl;

    current_setup_arg = scux_setup_init_tbl;
    current_setup_arg.output_fs = output_fs;
    current_setup_arg.input_fs = input_fs;

    /* ==== Set SCUX Callback ==== */
    scux_callback_func.set_int_callback = &CallbackSetScuxInt;
    scux_callback_func.set_dmac_callback = &CallbackSetScuxDmac;
    ret = R_SCUX_RegistCallback(&scux_callback_func);
    if (SCUX_OK == ret)
    {
        ret = SCUX_APP_SUCCESS;
    }
    else
    {
        ret = SCUX_APP_ERROR;
        (void)printf("SAMPLE_ScuxInit Error\n");
    }
    /* ==== Change Audio Status ==== */
    audio_sts = AUDIO_RESET;

    return ret;
}

/******************************************************************************
* Function Name: SCUX_Setup
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_Setup (void)
{
    int32_t ret = DEVDRV_SUCCESS;

    if (AUDIO_RESET != audio_sts)
    {
        ret = SCUX_APP_ERROR;
    }
    else
    {
        /* ==== Setup DMA for the transmission from SCUX to Memory(Output buffer) ==== */
        ret = DmaScuxSetup(DMA_SCUX2_TO_MEM, SCUX_CH_2);

        /* ==== Setup DMA for the transmission from Memory(Fixed Audio) to SCUX ==== */
        if (DEVDRV_SUCCESS == ret)
        {
            ret = DmaScuxSetup(DMA_MEM_TO_SCUX2, SCUX_CH_2);
        }

        /* ==== Setup SCUX ==== */
        if (DEVDRV_SUCCESS == ret)
        {
            ret = R_SCUX_Setup (SCUX_CH_2,
                                &current_setup_arg,
                                &current_config_dvu_arg,
                                &current_config_mix_arg);
            if (SCUX_OK == ret)
            {
                ret = SCUX_APP_SUCCESS;
            }
            else
            {
                ret = SCUX_APP_ERROR;
            }
        }
        else
        {
            ret = SCUX_APP_ERROR;
        }
        /* ==== Change Audio Status ==== */
        if (SCUX_APP_SUCCESS == ret)
        {
               audio_sts = AUDIO_SETUP;
        }
        else
        {
            (void)printf("SAMPLE_ScuxSetup Error\n");
        }
    }

    return ret;
}

/******************************************************************************
* Function Name: SCUX_Play
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_Play (void)
{
    int32_t ret = SCUX_APP_SUCCESS;

    if (AUDIO_SETUP == audio_sts)
    {
        /* ==== Clear initialization bit of SCUX ==== */
        ret = R_SCUX_ClearInit(SCUX_CH_2);
    }
    else if (AUDIO_PAUSE == audio_sts)
    {
        /* DO NOTHING */
    }
    else
    {
        ret = SCUX_APP_ERROR;
    }

    /* ==== Change Audio Status ==== */
    if (SCUX_APP_SUCCESS == ret)
    {
        audio_sts = AUDIO_PLAY;
    }
    else
    {
        (void)printf("SAMPLE_ScuxPlay Error\n");
    }
    return ret;
}

/******************************* Stop SCUX      *******************************/

/******************************************************************************
* Function Name: SCUX_Stop
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_Stop (void)
{
    return R_SCUX_SetInit(SCUX_CH_2, false);
}

/******************************************************************************
* Function Name: SCUX_GetErrIntCount
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
uint32_t SCUX_GetErrIntCount (const uint32_t scux_ch, const uint32_t err_id)
{
    return scux_err_int_count[scux_ch][err_id];
}

/******************************* DMA control Functions              *******************************/

/******************************************************************************
* Function Name: DmaScuxSetup
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaScuxSetup (const uint32_t dma_id, const uint32_t scux_ch)
{
    const scux_dma_setting_t *dma_setting;
    dma_regist_info_t dma_regist;
    uint32_t dma_channel;
    int32_t ret;

    (void)__disable_irq();

    /* ==== Get DMA setting value ==== */
    dma_setting = &scux_dma_setting_tbl[dma_id];

    /* ==== Set DMA parameter ==== */
    dma_channel                  = dma_setting->dma_ch;
    dma_regist.module_name       = dma_setting->module_name;
    dma_regist.module_channel    = scux_ch;
    dma_regist.direct            = dma_setting->direct;
    dma_regist.transfer_continue = dma_setting->transfer_continue;
    dma_regist.user_trnend_func  = dma_setting->user_trnend_func;

    /* ==== Stop DMA ==== */
    ret = DMA_DmaStop(dma_channel);

    /* ==== Setup DMA ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DMA_DmaSetup(dma_channel, &dma_regist);
    }
    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: DmaScuxAdsSet
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaScuxAdsSet (const uint32_t dma_id,
                              volatile const void * const buf,
                              const uint32_t buf_size)
{
    int32_t  ret;
    uint32_t dma_channel;

    (void)__disable_irq();

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[dma_id].dma_ch;

    /* ==== Set DMA address ==== */
    ret = DMA_DmaAdsSet(dma_channel, buf, buf_size, false);

    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: DmaScuxTxRegPause
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaScuxTxRegPause (const uint32_t dma_id, const bool_t pause_req)
{
    int32_t  ret;
    uint32_t dma_channel;

    (void)__disable_irq();

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[dma_id].dma_ch;

    /* ==== Get DMA channel ==== */
    ret = DMA_TxRegPause(dma_channel, pause_req);

    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: DmaScuxToOutBufStop
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaScuxToOutBufStop (const uint32_t dma_id)
{
    int32_t  ret;
    uint32_t dma_channel;

    (void)__disable_irq();

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[dma_id].dma_ch;

    /* ==== Stop DMA ==== */
    ret = DMA_DmaStop(dma_channel);

    /* ==== Clear Transfer queue ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DMA_QueueInit(dma_channel);
    }

    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: DmaScuxToOutBufStart
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaScuxToOutBufStart (const uint32_t dma_id)
{
    int32_t ret;
    uint32_t dma_channel;
    uint8_t * buf_pointer;
    uint32_t buf_size;

    (void)__disable_irq();

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[dma_id].dma_ch;

    /* ==== Initialize DMA RX ==== */
    ret = DMA_DmaRxInit(dma_channel, DMA_TRANSFER_SIZE_32);

    /* ==== Set DMA Address ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        buf_pointer = AOUT_Get_SrcOutWriteBuffInfo(&buf_size);
        ret = DMA_DmaAdsSet(dma_channel, buf_pointer, buf_size, true);
        if (DEVDRV_SUCCESS == ret)
        {
            ret = DMA_RxRegSet(dma_channel, N0_SIDE);
        }
    }

    /* ==== Start DMA ==== */
    if (DEVDRV_SUCCESS == ret)
    {
          ret = DMA_DmaStart(dma_channel);
    }

    /* ==== Set Return Value ==== */
    if (DEVDRV_SUCCESS != ret)
    {
          ret = DEVDRV_ERROR;
    }

    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: SCUX_DmaScuxToOutBufContinue
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_DmaScuxToOutBufContinue (void)
{
    int32_t  ret = DEVDRV_SUCCESS;
    uint8_t  * buf_pointer;
    uint32_t buf_size;

    /* ==== Get DMA channel ==== */
    buf_pointer = AOUT_Get_SrcOutWriteBuffInfo(&buf_size);
    ret = DmaScuxAdsSet(DMA_SCUX2_TO_MEM, buf_pointer, buf_size);

    return ret;
}

/******************************************************************************
* Function Name: DmaFixedToScuxStart
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t DmaFixedToScuxStart (const uint32_t dma_id)
{
    int32_t  ret;
    uint32_t dma_channel;

    (void)__disable_irq();

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[dma_id].dma_ch;

    /* ==== Initialize DMA TX ==== */
    ret = DMA_DmaTxInit(dma_channel, DMA_TRANSFER_SIZE_32);

    /* ==== Set DMA 1st Address ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DMA_DmaAdsSet(dma_channel, (void *)DEC_GetInputBuffAddr(DEC_BUFF_NO_1), DEC_GetInputBuffSize(), true);
        if (DEVDRV_SUCCESS == ret)
        {
            ret = DMA_TxRegSet(dma_channel, N0_SIDE);
        }
    }
    /* ==== Set DMA 2nd Address ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DMA_DmaAdsSet(dma_channel, (void *)DEC_GetInputBuffAddr(DEC_BUFF_NO_2), DEC_GetInputBuffSize(), true);
        if (DEVDRV_SUCCESS == ret)
        {
            ret = DMA_TxRegSet(dma_channel, N1_SIDE);
        }
    }
    /* ==== Start DMA ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DMA_DmaStart(dma_channel);
    }

    /* ==== Set Return Value ==== */
    if (DEVDRV_SUCCESS != ret)
    {
        ret = DEVDRV_ERROR;
    }

    (void)__enable_irq();

    return ret;
}

/******************************************************************************
* Function Name: SCUX_DmaFixedToScuxSetQueue
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_DmaFixedToScuxSetQueue (uint8_t *buffaddr, uint32_t buffsize)
{
    int32_t  ret;

    ret = DmaScuxAdsSet(DMA_MEM_TO_SCUX2, buffaddr, buffsize);

    return ret;
}

/******************************************************************************
* Function Name: SCUX_DmaFixedToScuxContinue
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
int32_t SCUX_DmaFixedToScuxContinue (void)
{
    int32_t  ret = DEVDRV_SUCCESS;
    uint32_t dma_channel;

    /* ==== Get DMA channel ==== */
    dma_channel = scux_dma_setting_tbl[DMA_MEM_TO_SCUX2].dma_ch;
    (void)DMA_DmaReStart (dma_channel);

    return ret;
}

/******************************* Callback Functions from SCUX Driver *******************************/

/******************************************************************************
* Function Name: CallbackSetScuxDmac
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t CallbackSetScuxDmac (const uint32_t scux_ch)
{
    int32_t ret;

    /* ==== Start DMA transfer from SCUX to Memory(Output buffer) ==== */
    ret = DmaScuxToOutBufStart(DMA_SCUX2_TO_MEM);

    /* ==== Start DMA transfer from Memory(Fixed Audio) to SCUX ==== */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = DmaFixedToScuxStart(DMA_MEM_TO_SCUX2);
    }

    /* ==== Set return value for SCUX callback function */
    if (DEVDRV_SUCCESS == ret)
    {
        ret = SCUX_OK;
    }
    else
    {
        ret = SCUX_E_USER_PROC;
    }

    return ret;
}

/******************************************************************************
* Function Name: CallbackSetScuxInt
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static int32_t CallbackSetScuxInt (const uint32_t scux_ch)
{
    /* SCUX Interrupt */
    static const scux_int_t scux_int_inf_tbl[NUM_SCUX_CH][NUM_SCUX_INT_ID_MODULE] =
    {
        {       /* ch0 */
              {&CallbackIntSrc0, 5}    /* SCUX_INT_ID_SRC */
            , {0,                0}    /* SCUX_INT_ID_FFD */
            , {&CallbackIntFfu0, 5}    /* SCUX_INT_ID_FFU */
            , {&CallbackIntDvu0, 5}    /* SCUX_INT_ID_DVU */
        }
        ,{    /* ch1 */
              {&CallbackIntSrc1, 5}    /* SCUX_INT_ID_SRC */
            , {&CallbackIntFfd1, 5}    /* SCUX_INT_ID_FFD */
            , {0,                0}    /* SCUX_INT_ID_FFU */
            , {&CallbackIntDvu1, 5}    /* SCUX_INT_ID_DVU */
        }
        ,{    /* ch2 */
              {&CallbackIntSrc2, 5}    /* SCUX_INT_ID_SRC */
            , {&CallbackIntFfd2, 5}    /* SCUX_INT_ID_FFD */
            , {&CallbackIntFfu2, 5}    /* SCUX_INT_ID_FFU */
            , {&CallbackIntDvu2, 5}    /* SCUX_INT_ID_DVU */
        }
        ,{    /* ch3 */
              {&CallbackIntSrc3, 5}    /* SCUX_INT_ID_SRC */
            , {&CallbackIntFfd3, 5}    /* SCUX_INT_ID_FFD */
            , {&CallbackIntFfu3, 5}    /* SCUX_INT_ID_FFU */
            , {0,                0}    /* SCUX_INT_ID_DVU */
        }
    };

    /* SCUX Interrupt ID table */
    static const uint16_t scux_int_id_tbl[NUM_SCUX_CH][NUM_SCUX_INT_ID_MODULE] =
    {
         { SCUAI0_IRQn, SCUFDI0_IRQn, SCUFUI0_IRQn, SCUDVI0_IRQn }    /* SCUX channel 0 */
        ,{ SCUAI0_IRQn, SCUFDI1_IRQn, SCUFUI1_IRQn, SCUDVI1_IRQn }    /* SCUX channel 1 */
        ,{ SCUAI1_IRQn, SCUFDI2_IRQn, SCUFUI2_IRQn, SCUDVI2_IRQn }    /* SCUX channel 2 */
        ,{ SCUAI1_IRQn, SCUFDI3_IRQn, SCUFUI3_IRQn, SCUDVI3_IRQn }    /* SCUX channel 3 */
    };

    void     (* func)(uint32_t int_sense);
    uint32_t scux_module_loop;
    int32_t  ret = SCUX_OK;

    for (scux_module_loop = SCUX_INT_ID_SRC; scux_module_loop < NUM_SCUX_INT_ID_MODULE; scux_module_loop++)
    {
        if (0 != scux_int_inf_tbl[scux_ch][scux_module_loop].callback)
        {
            /* Set Interupt callback */
            ret = R_SCUX_SetIntCallback(scux_ch, scux_module_loop,
                                        scux_int_inf_tbl[scux_ch][scux_module_loop].callback);
            if (SCUX_OK == ret)
            {
                /* Set Interrupt function */
                func = R_SCUX_GetIntFunc(scux_ch, scux_module_loop);
                (void)InterruptHandlerRegister(scux_int_id_tbl[scux_ch][scux_module_loop], func);

                /* Set Interrupt priority */
                GIC_SetPriority(scux_int_id_tbl[scux_ch][scux_module_loop],
                                scux_int_inf_tbl[scux_ch][scux_module_loop].prio);
                /* Enable Interrupt */
                GIC_EnableIRQ(scux_int_id_tbl[scux_ch][scux_module_loop]);
                /* ==== Set return value for SCUX callback function ==== */
            }

            if (SCUX_OK != ret)
            {
                ret = SCUX_E_USER_PROC;
                break;
            }
        }
    }

    return ret;
}

/******************************* Callback Interrupt Functions       *******************************/
/******************************************************************************
* Function Name: CallbackIntDmaMemToScux
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntDmaMemToScux(void *vpBuff)
{
    if (vpBuff == (void *)DEC_GetInputBuffAddr(DEC_BUFF_NO_1))
    {
        (void)DEC_ReqDec(DEC_BUFF_NO_1);
    }
    else if (vpBuff == (void *)DEC_GetInputBuffAddr(DEC_BUFF_NO_2))
    {
        (void)DEC_ReqDec (DEC_BUFF_NO_2);
    }
    else
    {
       (void) AOUT_End_Music();
    }
}

/******************************************************************************
* Function Name: CallbackIntDmaScuxToMem
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntDmaScuxToMem(void *vpBuff)
{
    uint8_t  *Wp;
    uint8_t  *Rp;
    uint32_t         Wbuf_size;
    uint32_t         Rbuf_size;

    (void)AOUT_Set_SrcOutWp();
    Wp = AOUT_Get_SrcOutWriteBuffInfo(&Wbuf_size);
    Rp = AOUT_Get_SrcOutReadBuffInfo(&Rbuf_size);

    if (Wp != Rp)
    {
        (void)DmaScuxAdsSet(DMA_SCUX2_TO_MEM, Wp, Wbuf_size);
    }
    else
    {
        (void)AOUT_Buff_Full();
    }
}

/******************************************************************************
* Function Name: CallbackIntSrc0
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntSrc0 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_0, ERRINT_SRC_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_0, ERRINT_SRC_OVERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntSrc1
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntSrc1 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_SRC_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_SRC_OVERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntSrc2
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntSrc2 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_SRC_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_SRC_OVERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntSrc3
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntSrc3 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_SRC_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_SRC_OVERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfd1
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfd1 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_FFD_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_FFD_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_FFD_OVERLAP, int_req);
    SetScuxErrIntCount(SCUX_CH_1, ERRINT_FFD_INIT_UNDERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfd2
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfd2 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFD_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFD_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFD_OVERLAP, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFD_INIT_UNDERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfd3
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfd3 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFD_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFD_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFD_OVERLAP, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFD_INIT_UNDERFLOW, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfu0
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfu0 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_0, ERRINT_FFU_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_0, ERRINT_FFU_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_0, ERRINT_FFU_OVERLAP, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfu2
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfu2 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFU_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFU_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_2, ERRINT_FFU_OVERLAP, int_req);
}

/******************************************************************************
* Function Name: CallbackIntFfu3
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntFfu3 (const uint32_t int_req)
{
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFU_UNDERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFU_OVERFLOW, int_req);
    SetScuxErrIntCount(SCUX_CH_3, ERRINT_FFU_OVERLAP, int_req);
}

/******************************************************************************
* Function Name: CallbackIntDvu0
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntDvu0 (const uint32_t int_req)
{
}

/******************************************************************************
* Function Name: CallbackIntDvu1
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntDvu1 (const uint32_t int_req)
{
}

/******************************************************************************
* Function Name: CallbackIntDvu2
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void CallbackIntDvu2 (uint32_t int_req)
{
}

/******************************************************************************
* Function Name: ClrScuxErrIntCount
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void ClrScuxErrIntCount (void)
{
    uint32_t scux_ch_loop;
    uint32_t scux_err_id_loop;

    for (scux_ch_loop = 0; scux_ch_loop < NUM_SCUX_CH; scux_ch_loop++)
    {
        for (scux_err_id_loop = 0; scux_err_id_loop < NUM_SCUX_ERRINT_ID; scux_err_id_loop++)
        {
            scux_err_int_count[scux_ch_loop][scux_err_id_loop] = 0;
        }
    }
}

/******************************************************************************
* Function Name: SetScuxErrIntCount
* Description  : 
* Arguments    : 
* Return Value : 
******************************************************************************/
static void SetScuxErrIntCount (const uint32_t scux_ch, const uint32_t err_id, const uint32_t int_req)
{
    uint32_t bit_inf;
    /* SCUX Error Interrupt ID to Register Table ID table */
    static const scux_intreq_bit_inf_t scux_errint_bit_tbl[NUM_SCUX_ERRINT_ID] =
    {
         SCUX_DEVCR_BIT_DEVCUF       /* ERRINT_FFD_UNDERFLOW                    */
        ,SCUX_DEVCR_BIT_DEVCOF       /* ERRINT_FFD_OVERFLOW                      */
        ,SCUX_DEVCR_BIT_DEVCOL       /* ERRINT_FFD_OVERLAP                         */
        ,SCUX_DEVCR_BIT_DEVCIUF    /* ERRINT_FFD_INIT_UNDERFLOWF       */
        ,SCUX_UEVCR_BIT_UEVCUF       /* ERRINT_FFU_UNDERFLOW                    */
        ,SCUX_UEVCR_BIT_UEVCOF       /* ERRINT_FFU_OVERFLOW                      */
        ,SCUX_UEVCR_BIT_UEVCOL       /* ERRINT_FFU_OVERLAP                         */
        ,SCUX_SEVCR_BIT_EVCUF         /* ERRINT_SRC_UNDERFLOW                    */
        ,SCUX_SEVCR_BIT_EVCOF         /* ERRINT_SRC_OVERFLOW                      */
    };
    /* SCUX Interrupt Request Bit table */
    static const uint32_reg_bit_inf_t scux_intreq_bit_inf_tbl[NUM_SCUX_INTREQ_BIT_INF] =
    {
         { 0x80000000u, 31 }       /* SCUX_DEVCR_BIT_DEVCUF   */
        ,{ 0x40000000u, 30 }       /* SCUX_DEVCR_BIT_DEVCOF   */
        ,{ 0x20000000u, 29 }       /* SCUX_DEVCR_BIT_DEVCOL   */
        ,{ 0x10000000u, 28 }       /* SCUX_DEVCR_BIT_DEVCIUF  */
        ,{ 0x80000000u, 31 }       /* SCUX_UEVCR_BIT_UEVCUF   */
        ,{ 0x40000000u, 30 }       /* SCUX_UEVCR_BIT_UEVCOF   */
        ,{ 0x20000000u, 29 }       /* SCUX_UEVCR_BIT_UEVCOL   */
        ,{ 0x80000000u, 31 }       /* SCUX_SEVCR_BIT_EVCUF    */
        ,{ 0x40000000u, 30 }       /* SCUX_SEVCR_BIT_EVCOF    */
        ,{ 0x00004000u, 14 }       /* SCUX_SEVCR_BIT_EVCWAIT  */
        ,{ 0x80000000u, 31 }       /* SCUX_VEVCR_BIT_VEVCZCM7 */
        ,{ 0x40000000u, 30 }       /* SCUX_VEVCR_BIT_VEVCZCM6 */
        ,{ 0x20000000u, 29 }       /* SCUX_VEVCR_BIT_VEVCZCM5 */
        ,{ 0x10000000u, 28 }       /* SCUX_VEVCR_BIT_VEVCZCM4 */
        ,{ 0x08000000u, 27 }       /* SCUX_VEVCR_BIT_VEVCZCM3 */
        ,{ 0x04000000u, 26 }       /* SCUX_VEVCR_BIT_VEVCZCM2 */
        ,{ 0x02000000u, 25 }       /* SCUX_VEVCR_BIT_VEVCZCM1 */
        ,{ 0x01000000u, 24 }       /* SCUX_VEVCR_BIT_VEVCZCM0 */
        ,{ 0x00008000u, 15 }       /* SCUX_VEVCR_BIT_VEVCVR   */
    };

    bit_inf = scux_errint_bit_tbl[err_id];
    scux_err_int_count[scux_ch][err_id] += COMMON_Get32BitMaskRShift(int_req, &scux_intreq_bit_inf_tbl[bit_inf]);
}

/* End of File */
