/** @file HL_sys_main.c 
*   @brief Application main file
*   @date 11-Dec-2018
*   @version 04.07.01
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* 
* Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com  
* 
* 
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "HL_sys_common.h"

/* USER CODE BEGIN (1) */
#include "HL_mibspi.h"
#include "HL_sys_dma.h"
#include "HL_sys_core.h"
#include "HL_reg_esm.h"

#define TG_WORDS 128
#define D_SIZE TG_WORDS
#define TOTAL_BYTES 2048
#define TOTAL_WORDS (TOTAL_BYTES / 2U)
#define NUM_CHUNKS (TOTAL_WORDS / D_SIZE)
/* 0 = known-good SW chunk mode, 1 = single HW frame-chain mode */
#define USE_FRAME_CHAIN 1U



uint16 tgPSTART1[8]; //for MibSPI1
g_dmaCTRL g_dmaCTRLPKT_RX, g_dmaCTRLPKT_TX;

#pragma SET_DATA_SECTION(".sharedRAM")
uint16 TXDATA[TOTAL_WORDS];
uint16 RXDATA[TOTAL_WORDS] = {0};

#pragma SET_DATA_SECTION()

volatile uint32 transfer512Done = 0U;
volatile uint32 transfer512Pass = 0U;
volatile uint32 transfer512FailIndex = 0xFFFFFFFFU;
volatile uint32 dmaTimeout = 0U;


void loadDataPattern(uint32 psize, uint16* pptr, uint16 pattern);

void dmaConfigCtrlRxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt);
void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt);
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
/* USER CODE END */

int main(void)
{
/* USER CODE BEGIN (3) */

    uint16 i;
    uint32 tmo;
    uint32 chunk;
    uint32 txAddr;
    uint32 rxAddr;
    uint32 bufid;

    esmREG->SR1[0] = 0xFFFFFFFF;
    esmREG->SR1[1] = 0xFFFFFFFF;
    esmREG->SR1[2] = 0xFFFFFFFF;

    _enable_IRQ_interrupt_();

    mibspiInit();

    /* Polling-based DMA test: keep MibSPI TG interrupt disabled to avoid ISR trapping. */
    mibspiDisableGroupNotification(mibspiREG1, 0U);

    mibspiEnableLoopback(mibspiREG1, Digital_Lbk);
    mibspiREG1->TICKCNT = (0 << 31) | (0<<28) | (0x100);


    mibspiREG1->TGCTRL[0U] = (uint32)((uint32)1U << 30U) /* oneshot */
    | (uint32)((uint32)0U << 29U) /* pcurrent reset */
    | (uint32)((uint32)TRG_ALWAYS<< 20U) /* trigger event */
    | (uint32)((uint32)TRG_DISABLED << 16U) /* trigger source */
    | (uint32)((uint32)0U << 8U); /* start buffer */

    mibspiREG1->TGCTRL[1U] = (uint32)((uint32)1U << 30U) /* oneshot */
    | (uint32)((uint32)0U << 29U) /* pcurrent reset */
    | (uint32)((uint32)TRG_ALWAYS << 20U) /* trigger event */
    | (uint32)((uint32)TRG_DISABLED << 16U) /* trigger source */
    | (uint32)((uint32)D_SIZE << 8U); /* TG1 start; TG0 size = D_SIZE */


    /* MibSPI1 TG0 controls: all TG_WORDS use CS0; hold CS until last word. */
    for (i = 0U; i < (D_SIZE - 1U); i++)
    {
        mibspiRAM1->tx[i].control = (uint16)((uint16)5U << 13U) /* buffer mode */
        | (uint16)((uint16)1U << 12U) /* chip select hold */
        | (uint16)((uint16)0U << 10U) /* enable WDELAY */
        | (uint16)((uint16)0U << 11U) /* lock transmission */
        | (uint16)((uint16)0U << 8U)  /* data format */
        | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU); /* chip select */
    }
    mibspiRAM1->tx[D_SIZE - 1U].control = (uint16)((uint16)5U << 13U) /* buffer mode */
    | (uint16)((uint16)0U << 12U) /* chip select hold off for last word */
    | (uint16)((uint16)0U << 10U) /* enable WDELAY */
    | (uint16)((uint16)0U << 8U)  /* data format */
    | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU); /* chip select */


    tgPSTART1[0] = (mibspiREG1->TGCTRL[0U] >> 8U) & 0xFFU;

    dmaEnable();

    loadDataPattern(TOTAL_WORDS, &TXDATA[0], 0x7000U);
#if (USE_FRAME_CHAIN == 1U)
    /* Restore TG0 baseline setup used by software start. */
    mibspiREG1->TGCTRL[0U] = (mibspiREG1->TGCTRL[0U] & 0x9F00FFFFU)
                           | ((uint32)1U << 30U) | ((uint32)0U << 29U)
                           | ((uint32)TRG_ALWAYS << 20U) | ((uint32)TRG_DISABLED << 16U);

    /* Frame-chain mode: one DMA packet covers all chunks as frames. */
    dmaConfigCtrlTxPacket((uint32)&TXDATA[0], (uint32)&(mibspiRAM1->tx[tgPSTART1[0]].data), D_SIZE, NUM_CHUNKS);
    dmaConfigCtrlRxPacket((uint32)&(mibspiRAM1->rx[tgPSTART1[0]].data), (uint32)&RXDATA[0], D_SIZE, NUM_CHUNKS);
    dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT_TX);
    dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT_RX);

    /* Reset TX/RX RAM address back to TG0 start on each frame. */
    dmaRAMREG->PCP[DMA_CH1].FIOFF = (uint32)(((uint32)((uint16)(0U - (D_SIZE * 4U))) << 16U) | 0U);
    dmaRAMREG->PCP[DMA_CH0].FIOFF = (uint32)((0U << 16U) | (uint32)(uint16)(0U - (D_SIZE * 4U)));

    dmaReqAssign(DMA_CH1, DMA_REQ1); /* TX */
    dmaReqAssign(DMA_CH0, DMA_REQ0); /* RX */

    /* MibSPI TG0 DMA mapping and large-count setup. */
    bufid = tgPSTART1[0U] + D_SIZE - 1U;
    /* Keep oneshot in this restored state. */
    mibspiREG1->DMACTRL[0U] = 0U;
    mibspiREG1->DMACTRL[0U] |= (1U << 20U) | (0U << 16U); /* rx line1, tx line0 */
    mibspiREG1->DMACTRL[0U] |= 0x8000C000U;               /* enable RX/TX DMA events */
    mibspiREG1->DMACTRL[0U] |= (bufid << 24U);
    mibspiREG1->DMACNTLEN = 1U;
    mibspiREG1->DMACOUNT[0U] = (NUM_CHUNKS - 1U) << 16U;

    dmaREG->FTCFLAG = ((uint32)1U << DMA_CH1) | ((uint32)1U << DMA_CH0);
    dmaREG->BTCFLAG = ((uint32)1U << DMA_CH1) | ((uint32)1U << DMA_CH0);
    dmaSetChEnable(DMA_CH1, DMA_HW);
    dmaSetChEnable(DMA_CH0, DMA_HW);

    mibspiREG1->TGINTFLG = (mibspiREG1->TGINTFLG & 0x0000FFFFU) | ((uint32)1U << 16U);
    mibspiTransfer(mibspiREG1, 0U);
    tmo = 2000000U;
    while ((dmaGetInterruptStatus(DMA_CH0, BTC) == false) && (tmo > 0U))
    {
        tmo--;
    }
    if (tmo == 0U)
    {
        dmaTimeout = 1U;
    }
#else
    for (chunk = 0U; chunk < NUM_CHUNKS; chunk++)
    {
        txAddr = (uint32)&TXDATA[chunk * D_SIZE];
        rxAddr = (uint32)&RXDATA[chunk * D_SIZE];

        /* 1) DMA TX: source buffer -> MibSPI TX RAM (16 words) */
        dmaConfigCtrlTxPacket(txAddr, (uint32)&(mibspiRAM1->tx[tgPSTART1[0]].data), D_SIZE, 1U);
        dmaSetCtrlPacket(DMA_CH1, g_dmaCTRLPKT_TX);
        dmaREG->FTCFLAG = (uint32)1U << DMA_CH1;
        dmaSetChEnable(DMA_CH1, DMA_SW);
        tmo = 1000000U;
        while ((dmaGetInterruptStatus(DMA_CH1, FTC) == false) && (tmo > 0U))
        {
            tmo--;
        }
        if (tmo == 0U)
        {
            dmaTimeout = 1U;
            break;
        }

        /* 2) Run one TG0 SPI transfer */
        mibspiREG1->TGINTFLG = (mibspiREG1->TGINTFLG & 0x0000FFFFU) | ((uint32)1U << 16U);
        mibspiTransfer(mibspiREG1, 0U);
        tmo = 1000000U;
        while ((mibspiIsTransferComplete(mibspiREG1, 0U) == false) && (tmo > 0U))
        {
            tmo--;
        }
        if (tmo == 0U)
        {
            dmaTimeout = 1U;
            break;
        }

        /* 3) DMA RX: MibSPI RX RAM -> destination buffer (16 words) */
        dmaConfigCtrlRxPacket((uint32)&(mibspiRAM1->rx[tgPSTART1[0]].data), rxAddr, D_SIZE, 1U);
        dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT_RX);
        dmaREG->FTCFLAG = (uint32)1U << DMA_CH0;
        dmaSetChEnable(DMA_CH0, DMA_SW);
        tmo = 1000000U;
        while ((dmaGetInterruptStatus(DMA_CH0, FTC) == false) && (tmo > 0U))
        {
            tmo--;
        }
        if (tmo == 0U)
        {
            dmaTimeout = 1U;
            break;
        }
    }
#endif

    _dCacheInvalidate_();

    transfer512Pass = 1U;
    for (i = 0U; i < TOTAL_WORDS; i++)
    {
        if (RXDATA[i] != TXDATA[i])
        {
            transfer512Pass = 0U;
            transfer512FailIndex = i;
            break;
        }
    }
    transfer512Done = 1U;

    while(1)
    {
    }
/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */
void loadDataPattern(uint32 psize, uint16* pptr, uint16 pattern)
{
    int i;
    for(i=0;i<psize;i++)
    {
        *(pptr++) = pattern + i;
    }
}


void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
{
    g_dmaCTRLPKT_TX.SADD = sadd; /* source address */
    g_dmaCTRLPKT_TX.DADD = dadd; /* destination address */
    g_dmaCTRLPKT_TX.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT_TX.FRCNT = FrameCnt ; /* frame count */
    g_dmaCTRLPKT_TX.ELCNT = ElmntCnt; /* element count */
    g_dmaCTRLPKT_TX.ELDOFFSET = 4; /* element destination offset */
    g_dmaCTRLPKT_TX.ELSOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT_TX.FRDOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT_TX.FRSOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT_TX.PORTASGN = PORTA_READ_PORTB_WRITE; /* port b */
    g_dmaCTRLPKT_TX.RDSIZE = ACCESS_16_BIT; /* read size */
    g_dmaCTRLPKT_TX.WRSIZE = ACCESS_16_BIT; /* write size */
    g_dmaCTRLPKT_TX.TTYPE = FRAME_TRANSFER ; /* transfer type */
    g_dmaCTRLPKT_TX.ADDMODERD = ADDR_INC1; /* address mode read */
    g_dmaCTRLPKT_TX.ADDMODEWR = ADDR_OFFSET; /* address mode write */
    g_dmaCTRLPKT_TX.AUTOINIT = AUTOINIT_OFF; /* autoinit */

    //return g_dmaCTRLPKT_TX;
}


void dmaConfigCtrlRxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
{
    g_dmaCTRLPKT_RX.SADD = sadd; /* source address */
    g_dmaCTRLPKT_RX.DADD = dadd; /* destination address */
    g_dmaCTRLPKT_RX.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT_RX.FRCNT = FrameCnt; /* frame count */
    g_dmaCTRLPKT_RX.ELCNT = ElmntCnt; /* element count */
    g_dmaCTRLPKT_RX.ELDOFFSET = 0; /* element destination offset */
    g_dmaCTRLPKT_RX.ELSOFFSET = 4; /* element source offset */
    g_dmaCTRLPKT_RX.FRDOFFSET = 0; /* frame destination offset */
    g_dmaCTRLPKT_RX.FRSOFFSET = 0; /* frame source offset */
    g_dmaCTRLPKT_RX.PORTASGN = PORTB_READ_PORTA_WRITE; /* port b */
    g_dmaCTRLPKT_RX.RDSIZE = ACCESS_16_BIT; /* read size */
    g_dmaCTRLPKT_RX.WRSIZE = ACCESS_16_BIT; /* write size */
    g_dmaCTRLPKT_RX.TTYPE = FRAME_TRANSFER ; /* transfer type */
    g_dmaCTRLPKT_RX.ADDMODERD = ADDR_OFFSET; /* address mode read */
    g_dmaCTRLPKT_RX.ADDMODEWR = ADDR_INC1; /* address mode write */
    g_dmaCTRLPKT_RX.AUTOINIT = AUTOINIT_OFF; /* autoinit */

    //return g_dmaCTRLPKT_RX;
}
/* USER CODE END */
