
/*******************************************************************************
  Section: Includes
*/

#include "r_typedefs.h" /* Renesas basic types, e.g. uint32_t */
#include "LCD_BUS.h"
#include "LCBI_DMA.h"
#include "r_dev_int_types.h"
#include "r_dev_api.h"
#include "r_dma_api.h"
#include "LCD_MonoTFT.h"
#include "api_tft.h"

#define DMA_BASE           0xFFFF8000u
#define DMA_CMVC_OFFSET    0x003Cu
#define DMA_CHANNEL_OFFSET 0x40u
#define DMA_CMVC_DEFAULT   3

#define DMA_DSA_OFFSET     0x0400u
#define DMA_DDA_OFFSET     0x0404u
#define DMA_DTC_OFFSET     0x0408u
#define DMA_DTCT_OFFSET    0x040Cu
#define DMA_DRSA_OFFSET    0x0410u
#define DMA_DRDA_OFFSET    0x0414u
#define DMA_DRTC_OFFSET    0x0418u
#define DMA_DTCC_OFFSET    0x041Cu
#define DMA_DCEN_OFFSET    0x0420u
#define DMA_DCST_OFFSET    0x0424u
#define DMA_DCSTS_OFFSET   0x0428u
#define DMA_DCSTC_OFFSET   0x042Cu
#define DMA_DTFR_OFFSET    0x0430u
#define DMA_DTFRRQ_OFFSET  0x0434u
#define DMA_DTFRRQC_OFFSET 0x0438u

#define DMA_DSA_DEFAULT     0
#define DMA_DDA_DEFAULT     0
#define DMA_DTC_DEFAULT     0
#define DMA_DTCT_DEFAULT    0
#define DMA_DRSA_DEFAULT    0
#define DMA_DRDA_DEFAULT    0
#define DMA_DRTC_DEFAULT    0
#define DMA_DTCC_DEFAULT    0
#define DMA_DCEN_DEFAULT    0
#define DMA_DCST_DEFAULT    0
#define DMA_DCSTS_DEFAULT   0
#define DMA_DCSTC_DEFAULT   0xB1u
#define DMA_DTFR_DEFAULT    0
#define DMA_DTFRRQ_DEFAULT  0
#define DMA_DTFRRQC_DEFAULT 1u

#define DIS_INT 0
#define EN_INT  1

static const r_dev_IntSel_t DMA_IntAddress [ 8 ] = {
    R_DEV_INT_DMA0,
    R_DEV_INT_DMA1,
    R_DEV_INT_DMA2,
    R_DEV_INT_DMA3,
    R_DEV_INT_DMA4,
    R_DEV_INT_DMA5,
    R_DEV_INT_DMA6,
    R_DEV_INT_DMA7,
};

typedef union
{
    struct
    {

        uint32_t TRM       : 2;
        uint32_t DS        : 3;
        uint32_t SACM      : 2;
        uint32_t DACM      : 2;
        uint32_t RLD1M     : 2;
        uint32_t RLD2M     : 2;
        uint32_t MLE       : 1;
        uint32_t TCE       : 1;
        uint32_t CCE       : 1;
        uint32_t CHNE      : 2;
        uint32_t CHNSEL    : 3;
        uint32_t Reserved1 : 5;
        uint32_t DRS       : 1;
        uint32_t ESE       : 1;
        uint32_t Reserved0 : 4;
    } bits;
    uint32_t reg;
} DMA_DTCT_t;

typedef union
{
    struct
    {

        uint32_t SR        : 1;
        uint32_t DR        : 1;
        uint32_t Reserved0 : 2;
        uint32_t TC        : 1;
        uint32_t CC        : 1;
        uint32_t Reserved1 : 2;
        uint32_t ER        : 1;
        uint32_t CY        : 1;
        uint32_t Reserved2 : 2;
        uint32_t ERWR      : 1;
        uint32_t Reserved3 : 19;
    } bits;
    uint32_t reg;
} DMA_DCST_t;

uint32_t DMA_SYS_GetDmaBaseAddr(uint32_t ChId)
{
    uint32_t addr;

    addr = (ChId * DMA_CHANNEL_OFFSET) + DMA_BASE;
    return addr;
}

void Lcbi_DMA_init(void)
{
    uint32_t base_addr;
    base_addr = DMA_SYS_GetDmaBaseAddr(0);
    WRITE_REG(32, (DMA_BASE + DMA_CMVC_OFFSET), DMA_CMVC_DEFAULT);

    base_addr = DMA_SYS_GetDmaBaseAddr(0);

    WRITE_REG(32, (base_addr + DMA_DSA_OFFSET), DMA_DSA_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DDA_OFFSET), DMA_DDA_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTC_OFFSET), DMA_DTC_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTCT_OFFSET), DMA_DTCT_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DRSA_OFFSET), DMA_DRSA_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DRDA_OFFSET), DMA_DRDA_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DRTC_OFFSET), DMA_DRTC_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTCC_OFFSET), DMA_DTCC_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTFR_OFFSET), DMA_DTFR_DEFAULT);

    WRITE_REG(32, (base_addr + DMA_DCST_OFFSET), DMA_DCST_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DCSTS_OFFSET), DMA_DCSTS_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTFRRQ_OFFSET), DMA_DTFRRQ_DEFAULT);

    /* Enalbe All DMA interrupt */
    R_DEV_IntEnable(DMA_IntAddress [ 0 ], EN_INT);

    /* clear status */
    WRITE_REG(32, (base_addr + DMA_DCSTC_OFFSET), DMA_DCSTC_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTFRRQC_OFFSET), DMA_DTFRRQC_DEFAULT);

    /* channel operation disable */
    WRITE_REG(32, (base_addr + DMA_DCEN_OFFSET), DMA_DCEN_DEFAULT);
}

DMA_cycle_status_t DMA_GetTransferStatus(void)
{
    DMA_DCST_t         DMA_DCST;
    DMA_cycle_status_t status = notOnGoing;
    uint32_t           base_addr;
    base_addr    = DMA_SYS_GetDmaBaseAddr(0);
    DMA_DCST.reg = READ_REG(32, base_addr + DMA_DCST_OFFSET);
    if ( DMA_DCST.bits.CY )
    {
        status = OnGoing;
    }
    return status;
}

void DMA_LoadChannel(uint32_t dst_addr, uint32_t src_addr, uint32_t len)
{
    uint32_t   ch_id;
    uint32_t   base_addr;
    DMA_DTCT_t DTCT;

    ch_id     = 0;
    base_addr = DMA_SYS_GetDmaBaseAddr(ch_id);

    /* channel operation disable */
    WRITE_REG(32, (base_addr + DMA_DCEN_OFFSET), 0x00000000u);

    /* configure DMA source address register */
    WRITE_REG(32, (base_addr + DMA_DSA_OFFSET), (src_addr & 0xFFFFFFFFu));

    /* configure DMA destination address register */
    WRITE_REG(32, (base_addr + DMA_DDA_OFFSET), (dst_addr & 0xFFFFFFFFu));

    /* configure DMA transfer count register */
    WRITE_REG(32, (base_addr + DMA_DTC_OFFSET), len);

    /* Transfer Count compare value (for the transfer count match interrupt) */
    WRITE_REG(32, (base_addr + DMA_DTCC_OFFSET), len);

    R_DMA_SetIsrCallback(0, 0, DMA_TransferCompletion_isr);

    /* configure DMA transfer control register */
    DTCT.bits.TRM    = 1;    // Block transfer 1
    DTCT.bits.DS     = 0;    // 8 bits
    DTCT.bits.SACM   = 0;    // Increment +
    DTCT.bits.DACM   = 2;    // Fixed
    DTCT.bits.RLD1M  = 1;
    DTCT.bits.RLD2M  = 0;    // disable function2
    DTCT.bits.MLE    = 0;    // Continuous transfer disable
    DTCT.bits.TCE    = 1;    // Transfer completion interrupt enable
    DTCT.bits.CCE    = 0;    //
    DTCT.bits.CHNE   = 0;    // 00: Disabled
    DTCT.bits.CHNSEL = 0;
    DTCT.bits.DRS    = 0;    // 0: Software DMA transfer request
    DTCT.bits.ESE    = 0;
    WRITE_REG(32, (base_addr + DMA_DTCT_OFFSET), DTCT.reg);

    WRITE_REG(32, (base_addr + DMA_DTFR_OFFSET), 0x00000000);

    /* clear status */
    WRITE_REG(32, (base_addr + DMA_DCSTC_OFFSET), DMA_DCSTC_DEFAULT);
    WRITE_REG(32, (base_addr + DMA_DTFRRQC_OFFSET), DMA_DTFRRQC_DEFAULT);

    /* channel operation enable (bit DTE moved from DTS to DCEN)*/
    WRITE_REG(32, (base_addr + DMA_DCEN_OFFSET), 0x00000001u);
}

/*******************************************************************************
  Function: R_G3DMA_SwTrigger

  see: <r_dma_api.h> for details
*/
void DMA_SwTrigger(void)
{
    uint32_t   base_addr;
    DMA_DTCT_t reg_dtct;

    base_addr = DMA_SYS_GetDmaBaseAddr(0);

    /* writable bit SR bit moved from DTS to DCSTS.SRS
        Additionaly, SW is set as source of DMA transfer request in DTCT.DRS */
    reg_dtct.reg = READ_REG(32, (base_addr + DMA_DTCT_OFFSET));
    WRITE_REG(32, (base_addr + DMA_DTCT_OFFSET), reg_dtct.reg);
    WRITE_REG(32, (base_addr + DMA_DCSTS_OFFSET), 0x00000001u);
}

void DMA_SetReloadConfig(uint32_t RelSrc, uint32_t RelDst, uint32_t RelCnt)
{
    uint32_t base_addr;

    base_addr = DMA_SYS_GetDmaBaseAddr(0);
    WRITE_REG(32, (base_addr + DMA_DRSA_OFFSET), RelSrc);
    WRITE_REG(32, (base_addr + DMA_DRDA_OFFSET), RelDst);
    WRITE_REG(32, (base_addr + DMA_DRTC_OFFSET), RelCnt);
}

void DMA_TransferCompletion_isr(void)
{
    Draw_ClearVramFlag(updateVramIndex);
}
