#include "dr7f701441.dvf.h"
#include "r_dev_api.h"

#include "IIS_MAX98357.h"
#include "GPIO.h"

/*SSICR*/
/*the number of channels in each system word*/
#define IIS_PER_SYS_WORD_CHANNEL_1 (0X00U << 22U)
#define IIS_PER_SYS_WORD_CHANNEL_2 (0X01U << 22U)
#define IIS_PER_SYS_WORD_CHANNEL_3 (0X02U << 22U)
#define IIS_PER_SYS_WORD_CHANNEL_4 (0X03U << 22U)

/*Data Word Length*/
#define IIS_DATA_WORD_LEN_8 (0X00U << 19U)
#define IIS_DATA_WORD_LEN_16 (0X01U << 19U)
#define IIS_DATA_WORD_LEN_18 (0X02U << 19U)
#define IIS_DATA_WORD_LEN_20 (0X03U << 19U)
#define IIS_DATA_WORD_LEN_22 (0X04U << 19U)
#define IIS_DATA_WORD_LEN_24 (0X05U << 19U)
#define IIS_DATA_WORD_LEN_32 (0X06U << 19U)

/* System Word Length */
#define IIS_SYS_WORD_LEN_8 (0X00U << 16U)
#define IIS_SYS_WORD_LEN_16 (0X01U << 16U)
#define IIS_SYS_WORD_LEN_24 (0X02U << 16U)
#define IIS_SYS_WORD_LEN_32 (0X03U << 16U)
#define IIS_SYS_WORD_LEN_48 (0X04U << 16U)
#define IIS_SYS_WORD_LEN_64 (0X05U << 16U)
#define IIS_SYS_WORD_LEN_128 (0X06U << 16U)
#define IIS_SYS_WORD_LEN_256 (0X07U << 16U)
/*Serial Bit Clock Direction*/
#define IIS_BIT_CLK_DIR_IN (0X00U << 15U)
#define IIS_BIT_CLK_DIR_OUT (0X01U << 15U)
/*Serial Bit Clock Polarity*/
#define IIS_BIT_CLK_FALLING (0X00U << 13U)
#define IIS_BIT_CLK_RISING (0X01U << 13U)
/*Serial WS Direction*/
#define IIS_WS_DIR_IN (0X00U << 14U)
#define IIS_WS_DIR_OUT (0X01U << 14U)
/*Serial WS Polarity*/
#define IIS_WS_FIRST_CH_LOW (0X00U << 12U)
#define IIS_WS_FIRST_CH_HIGH (0X01U << 12U)

/*Serial Oversampling Clock Division Ratio*/
#define IIS_OVERSAMPLING_DIV_0 (0X00U << 4U)
#define IIS_OVERSAMPLING_DIV_2 (0X01U << 4U)
#define IIS_OVERSAMPLING_DIV_4 (0X02U << 4U)
#define IIS_OVERSAMPLING_DIV_8 (0X03U << 4U)
#define IIS_OVERSAMPLING_DIV_16 (0X04U << 4U)
#define IIS_OVERSAMPLING_DIV_32 (0X05U << 4U)
#define IIS_OVERSAMPLING_DIV_64 (0X06U << 4U)
#define IIS_OVERSAMPLING_DIV_128 (0X07U << 4U)
#define IIS_OVERSAMPLING_DIV_6 (0X08U << 4U)
#define IIS_OVERSAMPLING_DIV_12 (0X09U << 4U)
#define IIS_OVERSAMPLING_DIV_24 (0X0AU << 4U)
#define IIS_OVERSAMPLING_DIV_48 (0X0BU << 4U)
#define IIS_OVERSAMPLING_DIV_96 (0X0CU << 4U)

/*Transmit Enable*/
#define IIS_TR_DISABLE (0X00U)
#define IIS_TR_ENABLE (0X02U)

/*SSIFCR*/

/*Transmit Data Trigger Number*/
#define IIS_TR_DATA_TRIGGER_NUM_7 (0X00U << 6U)
#define IIS_TR_DATA_TRIGGER_NUM_6 (0X01U << 6U)
#define IIS_TR_DATA_TRIGGER_NUM_4 (0X02U << 6U)
#define IIS_TR_DATA_TRIGGER_NUM_2 (0X03U << 6U)
/*Transmit Interrupt*/
#define IIS_TR_INTERRUPT_DISABLE (0X00U << 3U)
#define IIS_TR_INTERRUPT_ENABLE (0X01U << 3U)

/*SSITDMR*/
/*WS Continue Mode*/
#define IIS_WS_CON_ENABLE (0X01U << 8U)
#define IIS_WS_CON_DISABLE (0X00U << 8U)
/*TDM Mode*/
#define IIS_TDM_MODE_ENABLE (0X01U)
#define IIS_TDM_MODE_DISABLE (0X00U)
/*
---------------------------------------------------------------------------------
*/
IIS_Control_st_t g_stIISControl;
uint32_t u32IISNopCount = 0U;
IIS_Volume_en_t enIISVolumeLevel = IIS_VOLUME_ERROR;

void IIS_Reset(void)
{
    /*SSICR Control Register*/
    SSIF0SSICR_0 = 0x00000000U;
    SSIF1SSICR_1 = 0x00000000U;
    /*status*/
    /* SSIF0SSISR_0 = 0x02000013U;
     SSIF1SSISR_1 = 0x02000013U;*/
    /*FIFO control */
    SSIF0SSIFCR_0 = 0x00000000U;
    SSIF1SSIFCR_1 = 0x00000000U;
    /*FIFO status*/
    SSIF0SSIFSR_0 = 0x00010000U;
    SSIF1SSIFSR_1 = 0x00010000U;
    /*Transmit FIFO Data Register*/
    SSIF0SSIFTDR_0 = 0x00000000U;
    SSIF1SSIFTDR_1 = 0x00000000U;
    /*Receive FIFO Data Register
    SSIF0SSIFRDR_0
    SSIF1SSIFRDR_1*/
    /*TDM Mode Register*/
    SSIF0SSITDMR_0 = 0x00000000U;
    SSIF1SSITDMR_1 = 0x00000000U;
    /*SSIF Clock Setting Register*/
    SELBSSIFCLKCFG = 0x00000000U;
}

#define I2S_MAX98357_SD_MODE_PIN SD_MODE_MCU

#define I2S_MAX98357_GAIN_SLOT_100K_PIN GPIO_OUT_PORT16_PIN05
#define I2S_MAX98357_GAIN_SLOT_100K_SET_OUT GPIO_DIR_PORT16_PIN05 = GPIO_DIR_OUT
#define I2S_MAX98357_GAIN_SLOT_100K_SET_IN GPIO_DIR_PORT16_PIN05 = GPIO_DIR_IN
#define I2S_MAX98357_GAIN_SLOT_DIRECT_PIN GPIO_OUT_PORT16_PIN11
#define I2S_MAX98357_GAIN_SLOT_DIRECT_SET_OUT GPIO_DIR_PORT16_PIN11 = GPIO_DIR_OUT
#define I2S_MAX98357_GAIN_SLOT_DIRECT_SET_IN GPIO_DIR_PORT16_PIN11 = GPIO_DIR_IN

void I2S_MAX98357_Volume_Set(IIS_Volume_en_t enIISVolume)
{
    if (enIISVolume != enIISVolumeLevel)
    {
        enIISVolumeLevel = enIISVolume;

        switch (enIISVolumeLevel)
        {
        case IIS_VOLUME_03DB:
        {
            I2S_MAX98357_GAIN_SLOT_DIRECT_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_DIRECT_SET_IN;
            I2S_MAX98357_GAIN_SLOT_100K_SET_OUT;
            I2S_MAX98357_GAIN_SLOT_100K_PIN = 1U;
            break;
        }
        case IIS_VOLUME_06DB:
        {
            I2S_MAX98357_GAIN_SLOT_100K_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_100K_SET_IN;
            I2S_MAX98357_GAIN_SLOT_DIRECT_SET_OUT;
            I2S_MAX98357_GAIN_SLOT_DIRECT_PIN = 1U;
            break;
        }
        default:
        case IIS_VOLUME_09DB:
        {
            I2S_MAX98357_GAIN_SLOT_DIRECT_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_DIRECT_SET_IN;
            I2S_MAX98357_GAIN_SLOT_100K_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_100K_SET_IN;

            break;
        }
        case IIS_VOLUME_12DB:
        {
            I2S_MAX98357_GAIN_SLOT_100K_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_100K_SET_IN;
            I2S_MAX98357_GAIN_SLOT_DIRECT_SET_OUT;
            I2S_MAX98357_GAIN_SLOT_DIRECT_PIN = 0U;
            break;
        }
        case IIS_VOLUME_15DB:
        {
            I2S_MAX98357_GAIN_SLOT_DIRECT_PIN = 0U;
            I2S_MAX98357_GAIN_SLOT_DIRECT_SET_IN;
            I2S_MAX98357_GAIN_SLOT_100K_SET_OUT;
            I2S_MAX98357_GAIN_SLOT_100K_PIN = 0U;
            break;
        }
        }
    }
}

void I2S_MAX98357_Init(void)
{
    I2S_MAX98357_SD_MODE_PIN = 0U;
    SSIF1SSIFTDR_1 = 0U;

    SSIF1SSICR_1 = (IIS_PER_SYS_WORD_CHANNEL_1 | IIS_DATA_WORD_LEN_16 | IIS_SYS_WORD_LEN_16 |
                    IIS_BIT_CLK_DIR_OUT | IIS_BIT_CLK_FALLING | IIS_WS_DIR_OUT |
                    IIS_WS_FIRST_CH_LOW | IIS_OVERSAMPLING_DIV_8 | IIS_TR_ENABLE);

    SSIF1SSIFCR_1 = (IIS_TR_DATA_TRIGGER_NUM_4 | IIS_TR_INTERRUPT_DISABLE);

    SSIF1SSITDMR_1 = (IIS_WS_CON_ENABLE | IIS_TDM_MODE_DISABLE);

    /*SSIACKINT input,
Continues AUDIO,clock,
Continues SSISCK clock,
during debugging*/
    SELBSSIFCLKCFG = 0U;

    SSIF1SSIFTDR_1 = 0U;
    R_DEV_IntEnable(R_DEV_INT_SSIF1TX, 1U); /* Enable interrupt */
    I2S_MAX98357_SD_MODE_PIN = 1U;

    /*  I2S_MAX98357_InternalFlash_CH0_Player(DoorOpen_48K, 78804U , 0xFFFFU);*/
}
/*
pu16Data : The first address of audio  data
u32Len  : The number of bytes of audio data
u32Cycles :Number of times the audio played ,0xFFFF is forever,0 is illicit 
*/
IIS_Start_Status_en_t I2S_MAX98357_InternalFlash_CH0_Player(const uint8_t *pu8Data, uint32_t u32Len, uint32_t u32Cycles)
{
    IIS_Start_Status_en_t enIISStartStatus = IIS_SET_OK;

    if (g_stIISControl.enIISStep != IIS_STEP_IDLE)
    {
        enIISStartStatus = IIS_SET_STATUS_ERROR;
    }
    if (pu8Data == 0U)
    {
        enIISStartStatus = IIS_SET_DATA_ERROR;
    }
    if ((u32Len % 2U) != 0U)
    {
        enIISStartStatus = IIS_SET_LEN_ERROR;
    }
    if (u32Cycles == 0U)
    {
        enIISStartStatus = IIS_SET_NUM_ERROR;
    }
    if (enIISStartStatus == IIS_SET_OK)
    {
        g_stIISControl.pu8IISData = pu8Data;
        g_stIISControl.pu8IISDataBackup = g_stIISControl.pu8IISData;
        g_stIISControl.u16IISPlayCount = u32Cycles;
        g_stIISControl.u32IISTotalCount = u32Len / 2U;
        g_stIISControl.u32IISTotalCountBackup = g_stIISControl.u32IISTotalCount;
        g_stIISControl.u8IISForceStop = 0U;
        g_stIISControl.enIISStep = IIS_STEP_BUSY;

        SSIF1TIE = 1U; //transfer interrupt enable
    }
    return enIISStartStatus;
}

/*  stop play */
/*   channel : 0~~4  */
void I2S_MAX98357_Stop(uint8_t u8Channel)
{
    switch (u8Channel)
    {
    case 0U:
    {
        if (g_stIISControl.enIISStep == IIS_STEP_BUSY)
        {
            g_stIISControl.u8IISForceStop = 1U;
        }
    }
    break;
    case 1U:

        break;
    case 2U:

        break;
    case 3U:

        break;
    case 4U:

        break;

    default:
        break;
    }
}
/*  Returns the state of the specified sound channel */
/*  u8Channel : 0~~4  */
IIS_Play_Status_en_t I2S_MAX98357_GetStatus(uint8_t u8Channel)
{
    IIS_Play_Status_en_t enIISPlayStatus;
    if (u8Channel > 4U)
    {
        enIISPlayStatus = IIS_PLAY_BUSY;
    }
    else
    {
        if (g_stIISControl.enIISStep == IIS_STEP_IDLE)
        {
            enIISPlayStatus = IIS_PLAY_IDLE;
        }
        else
        {
            enIISPlayStatus = IIS_PLAY_BUSY;
        }
    }

    return enIISPlayStatus;
}

//__interrupt void INTSSIF1TX(void)
void I2S_MAX98357_TX(void)
{
    uint8_t i = 0U;
    if (g_stIISControl.enIISStep == IIS_STEP_BUSY)
    {

        g_stIISControl.u8IISOnceCount = 8U - SSIF1TDC;
        if (g_stIISControl.u8IISForceStop == 1U)
        {
            g_stIISControl.u16IISPlayCount = 0U;
            g_stIISControl.u32IISTotalCount = 0U;
            /*g_stIISControl.u8IISForceStop = 0U;*/
        }

        if (g_stIISControl.u32IISTotalCount >= g_stIISControl.u8IISOnceCount)
        {
            for (i = 0U; i < (g_stIISControl.u8IISOnceCount); i++)
            {
                SSIF1SSIFTDR_1 = (((*(g_stIISControl.pu8IISData + 1)) << 24) | ((*g_stIISControl.pu8IISData) << 16) |
                                  ((*(g_stIISControl.pu8IISData + 1)) << 8) | (*g_stIISControl.pu8IISData));

                g_stIISControl.pu8IISData += 2U;
            }

            g_stIISControl.u32IISTotalCount -= g_stIISControl.u8IISOnceCount;
        }
        else
        {
            for (i = 0U; i < (g_stIISControl.u32IISTotalCount); i++)
            {
                SSIF1SSIFTDR_1 = (((*(g_stIISControl.pu8IISData + 1)) << 24) | ((*g_stIISControl.pu8IISData) << 16) |
                                  ((*(g_stIISControl.pu8IISData + 1)) << 8) | (*g_stIISControl.pu8IISData));

                g_stIISControl.pu8IISData += 2U;
            }
            if ((g_stIISControl.u16IISPlayCount != 0xFFFFU) && (g_stIISControl.u16IISPlayCount != 0U))
            {
                g_stIISControl.u16IISPlayCount--;
            }
            if (g_stIISControl.u16IISPlayCount)
            {
                uint8_t u8IISRemainCount = g_stIISControl.u8IISOnceCount - g_stIISControl.u32IISTotalCount;
                g_stIISControl.u32IISTotalCount = g_stIISControl.u32IISTotalCountBackup;
                g_stIISControl.pu8IISData = g_stIISControl.pu8IISDataBackup;

                for (i; i < (g_stIISControl.u8IISOnceCount); i++)
                {

                    SSIF1SSIFTDR_1 = (((*(g_stIISControl.pu8IISData + 1)) << 24) | ((*g_stIISControl.pu8IISData) << 16) |
                                      ((*(g_stIISControl.pu8IISData + 1)) << 8) | (*g_stIISControl.pu8IISData));

                    g_stIISControl.pu8IISData += 2U;
                }
                g_stIISControl.u32IISTotalCount -= u8IISRemainCount;
            }
            else
            {
                SSIF1SSIFTDR_1 = 0U;
                SSIF1TIE = 0U; //transfer interrupt disable

                g_stIISControl.u32IISTotalCount = 0U;
                g_stIISControl.enIISStep = IIS_STEP_IDLE;
            }
        }
    }
    else
    {
        /*error*/
        SSIF1SSIFTDR_1 = 0U;
        SSIF1TIE = 0U; //transfer interrupt disable
        g_stIISControl.u32IISTotalCount = 0U;
        g_stIISControl.enIISStep = IIS_STEP_IDLE;
    }

    SSIF1TDE = 0U;
    u32IISNopCount++;
    u32IISNopCount++;
    u32IISNopCount++;
    u32IISNopCount++;
    u32IISNopCount++;
    u32IISNopCount++;
    u32IISNopCount++;
}