/**
 * \file  timerCounter.c
 *
 * \brief Sample application for timer.
 */

/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://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.
*/

#include "uart.h"
#include "hw_uart.h"
#include "interrupt.h"
#include "soc_C6748.h"
#include "hw_syscfg0_C6748.h"
#include "timer.h"
#include "lcdkC6748.h"
#include "uartStdio.h"
#include "gpio.h"
#include "psc.h"
#include"hw_types.h"
#include "hw_psc_C6748.h"
#include "edma_event.h"
#include "edma.h"
#include "spi.h"
#include <stddef.h>
#include <stdio.h>                     /* This ert_main.c example uses printf/fflush */
#include "mcasp.h"

#ifndef _TMS320C6X
#include "cpu.h"
#endif

/******************************************************************************
**                      INTERNAL MACRO DEFINITIONS
*******************************************************************************/
#define STR_LEN                        (13)
#define TMR_PERIOD_LSB32               (0x0000037a)
//#define TMR_PERIOD_LSB32               (0x00000dfa)

//#define TMR_PERIOD_LSB32               (0x0F424000)
//#define TMR_PERIOD_LSB32               (0x00B71B00)
#define TMR_PERIOD_MSB32               (0x0)

/******************************************************************************
**                      INTERNAL FUNCTION PROTOTYPES
*******************************************************************************/

static void TimerIsr(void);
static void TimerSetUp64Bit(void);
//static void TimerIntrSetUp(void);

/******************************************************************************
**                      INTERNAL VARIABLE DEFINITIONS
*******************************************************************************/

/******************************************************************************
**                          FUNCTION DEFINITIONS
*******************************************************************************/

#define PINMUX11_GPIO5_8_ENABLE    (SYSCFG_PINMUX11_PINMUX11_31_28_GPIO5_8  << \
                                    SYSCFG_PINMUX11_PINMUX11_31_28_SHIFT)

void  GPIOBank6Pin13PinMuxSetup();

volatile int dummy=0;
volatile int intflag=0;
volatile int flag1=0;

volatile char toggle_val;
static void (*cb_Fxn[EDMA3_NUM_TCC]) (unsigned int tcc, unsigned int status);
static void EDMA3Initialize(void);
static void SetupInt(void);
static void edma3ComplHandler(unsigned int baseAdd, unsigned int regionNum);
static void Edma3ComplHandlerIsr(void);
static void edma3CCErrHandler(unsigned int baseAdd);
static void Edma3CCErrHandlerIsr();
static void ConfigureIntEDMA3(void);
static void callback(unsigned int tccNum, unsigned int status);
static void SPITransmitData(unsigned int tccNum, unsigned int chNum,volatile char*);

void GPIOBank5Pin8PinMuxSetup();

#define EVT_QUEUE_NUM  0

volatile char toggle_val1[8];
volatile char toggle_val2[8];
int i=0;

#pragma DATA_ALIGN (toggle_val,256);
#pragma DATA_ALIGN (toggle_val1,256);
#pragma DATA_ALIGN (toggle_val2,256);

/************************spi PORTION******************/

#define SIMO_SOMI_CLK_CS        0x00000E08
#define CHAR_LENGTH             0x8
static void SPIConfigDataFmtReg(unsigned int dataFormat);
static void SetUpSPI(void);
int delay=0;

//int*dummyptr=(SOC_SPI_1_REGS+0x38);
int *dummyptr;
int dummy_var=0;
/******************************************************/
int main(void)
{
    //HWREG(0x01C11100)|=0x00000001;                          //Enabling PLLCTL
    HWREG(0x01C11100) =0x00000051;
   // HWREG(0x01C11110)=                                                   //PLLM
    HWREG(0x01C11128)= 0x0008000;                                                  //POSTDIV

   //HWREG(0x01e1a100)|=0x00000001;                          //Enabling PLLCTL
  HWREG(0x01e1a100)=0x00000051;
   //HWREG(0x01e1a110)=                                                   //PLLM
   HWREG(0x01e1a128)= 0x0008000;                                         //POSTDIV

//   for(i=0;i<8;i++)
//toggle_val[i]=0x00;

for(i=0;i<8;i++)
     toggle_val1[i]=(char)i;

for(i=0;i<8;i++)
     toggle_val2[i]=(char)(i+8);

dummyptr=(int*)(SOC_SPI_0_REGS+0x38);

EDMA3Initialize();

/* The Local PSC number for GPIO is 3. GPIO belongs to PSC1 module.*/
        PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON,
                 PSC_MDCTL_NEXT_ENABLE);

/*******************SPI***************************************************/

        PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_SPI0, PSC_POWERDOMAIN_ALWAYS_ON,
                            PSC_MDCTL_NEXT_ENABLE);
        SPIPinMuxSetup(0);
        SPI0CSPinMuxSetup(4);
        SetUpSPI();

/*********************************SPI*************************************/

//while(1)
//{
//    SPITransmitData1(SOC_SPI_0_REGS, 0x55);
//    for(delay=0;delay<345;delay++);
//}

/* Pin Multiplexing of pin 8 of GPIO Bank 5.*/
GPIOBank5Pin8PinMuxSetup();

/* Sets the pin 89 (GP6[13]) as output.*/
 GPIODirModeSet(SOC_GPIO_0_REGS, 89, GPIO_DIR_OUTPUT);

/****************SPI setup*************************************/

/* Set up the Timer3 peripheral */
 TimerSetUp64Bit();
 /* Enable the timer interrupt */

 //   HWREG(0x01f0d044)|=0x00000001;   //enable int
    EDMA3RequestChannel(SOC_EDMA31CC_0_REGS , EDMA3_CHANNEL_TYPE_DMA,
                        EDMA3_TIMER2_T12CMPEVT0,EDMA3_TIMER2_T12CMPEVT0 ,
                        EVT_QUEUE_NUM);

    cb_Fxn[EDMA3_TIMER2_T12CMPEVT0 ] = &callback;

    //HWREG(0x01e38140)=0x00000004;  //read rate for TC

    SPITransmitData(EDMA3_TIMER2_T12CMPEVT0 ,EDMA3_TIMER2_T12CMPEVT0 ,&toggle_val1);

#ifndef _TMS320C6X
    /* Switch to non privileged mode; This is done for demonstration purpose */
    CPUSwitchToUserMode();
#endif

    /* Start the timer. Characters from cntArr will be sent from the ISR */

    HWREG((SOC_TMR_2_REGS) + 0x60)=0x00000037a;
    HWREG(SOC_TMR_2_REGS+0x64)=0x0;
    HWREG(SOC_TMR_2_REGS+0x68)=0x0;
    HWREG(SOC_TMR_2_REGS+0x6c)=0x0;
    HWREG(SOC_TMR_2_REGS+0x70)=0x0;
    HWREG(SOC_TMR_2_REGS+0x74)=0x0;
    HWREG(SOC_TMR_2_REGS+0x78)=0x0;
    HWREG(SOC_TMR_2_REGS+0x7c)=0x0;

    TimerEnable(SOC_TMR_2_REGS, TMR_TIMER_BOTH, TMR_ENABLE_CONT);

    while(1)
    {

        dummy_var=*(dummyptr);

    }

}

/*
** Timer Interrupt Service Routine
*/
static void SPITransmitData(unsigned int tccNum, unsigned int chNum,volatile char*buffer)
{
        EDMA3CCPaRAMEntry paramSet;

        EDMA3CCPaRAMEntry paramSet1;
        EDMA3CCPaRAMEntry paramSet2;

        paramSet1.srcAddr = (unsigned int)&toggle_val1;
       // paramSet1.destAddr =(unsigned int)&toggle_val;//0x01e26064;
        paramSet1.destAddr =(unsigned int)(SOC_SPI_0_REGS+0x38);
        paramSet1.aCnt = (unsigned short)1;
        paramSet1.bCnt = (unsigned short)4;
        paramSet1.cCnt = (unsigned short)1;

       /* The src index should increment for every byte being transferred. */
       paramSet1.srcBIdx = (short) 1u;

       /* The dst index should not be increment since it is a h/w register*/
       paramSet1.destBIdx = (short) 0u;

       /* A sync Transfer Mode */
       paramSet1.srcCIdx = (short) 0u;
       paramSet1.destCIdx = (short) 0u;
       paramSet1.linkAddr = 0x01e34220;
       paramSet1.bCntReload = (unsigned short)0u;
       paramSet1.opt =0x00100002;
       EDMA3SetPaRAM(SOC_EDMA31CC_0_REGS, 16, &paramSet1);

       paramSet2.srcAddr = (unsigned int)&toggle_val2;
    //  paramSet2.destAddr =(unsigned int)&toggle_val;//0x01e26064;
       paramSet2.destAddr =(unsigned int)(SOC_SPI_0_REGS+0x38);
       paramSet2.aCnt = (unsigned short)1;
       paramSet2.bCnt = (unsigned short)4;
       paramSet2.cCnt = (unsigned short)1;

       /* The src index should increment for every byte being transferred. */
       paramSet2.srcBIdx = (short) 1u;

       /* The dst index should not be increment since it is a h/w register*/
       paramSet2.destBIdx = (short) 0u;

       /* A sync Transfer Mode */
       paramSet2.srcCIdx = (short)0u;
       paramSet2.destCIdx = (short) 0u;
       paramSet2.linkAddr = 0x01e34200;
       paramSet2.bCntReload = (unsigned short)0u;
       paramSet2.opt =0x00100002;
       EDMA3SetPaRAM(SOC_EDMA31CC_0_REGS, 17, &paramSet2);

        /* Fill the PaRAM Set with transfer specific information */
        paramSet.srcAddr = (unsigned int)(&toggle_val1);
       // paramSet.destAddr =(unsigned int)&toggle_val;//0x01e26064;
        paramSet.destAddr =(unsigned int)(SOC_SPI_1_REGS+0x38);
        paramSet.aCnt = (unsigned short)1;
        paramSet.bCnt = (unsigned short)4;
        paramSet.cCnt = (unsigned short)1;

        /* The src index should increment for every byte being transferred. */
        paramSet.srcBIdx = (short) 1u;

        /* The dst index should not be increment since it is a h/w register*/
        paramSet.destBIdx = (short) 0u;

        /* A sync Transfer Mode */
        paramSet.srcCIdx = (short) 0u;
        paramSet.destCIdx = (short) 0u;
        paramSet.linkAddr = 0x01e34220;
       paramSet.bCntReload = (unsigned short)0u;
       paramSet.opt =0x00100002;

        /* Now write the PaRAM Set */
        EDMA3SetPaRAM(SOC_EDMA31CC_0_REGS, chNum, &paramSet);

        EDMA3EnableTransfer(SOC_EDMA31CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);
}

/*
** Setup the timer for 64 bit mode
*/
static void TimerSetUp64Bit(void)
{
    /* Configuration of Timer */
  //  TimerConfigure(SOC_TMR_3_REGS, TMR_CFG_64BIT_CLK_EXT);
   TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_32BIT_UNCH_CLK_BOTH_INT );

    /* Set the 64 bit timer period */
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);

   // HWREG(SOC_TMR_3_REGS + 0x20)|=0x02000200;                   //using external clock
}

void GPIOBank5Pin8PinMuxSetup()                 //HEADER J14 PIN 29
{
    unsigned int savePinmux = 0;

    /*
    ** Clearing the bit in context and retaining the other bit values
    ** in PINMUX13 register.
    */
    savePinmux = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(11)) &
    ~(SYSCFG_PINMUX11_PINMUX11_31_28));

    /* Setting the pins corresponding to GP6[13] in PINMUX13 register.*/
    HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(11)) =
    (PINMUX11_GPIO5_8_ENABLE | savePinmux);
}
/***************************** End Of File ***********************************/

/* Function used to Initialize EDMA3 */
static void EDMA3Initialize(void)
{
    /* Enabling the PSC for EDMA3CC_0.*/
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_CC1, PSC_POWERDOMAIN_ALWAYS_ON,
             PSC_MDCTL_NEXT_ENABLE);

    /* Enabling the PSC for EDMA3TC_0.*/
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_TC2, PSC_POWERDOMAIN_ALWAYS_ON,
             PSC_MDCTL_NEXT_ENABLE);

    /* Initialization of EDMA3 */
    EDMA3Init(SOC_EDMA31CC_0_REGS, EVT_QUEUE_NUM);

    /*
    ** Enable AINTC to handle interuppts. Also enable IRQ interuppt in
    ** ARM processor.
    */
    SetupInt();

    /* Register EDMA3 Interrupts */
    ConfigureIntEDMA3();
}

/* Function used to Setup ARM Interuppt Controller */
static void SetupInt(void)
{
#ifdef _TMS320C6X
    // Initialize the DSP Interrupt controller
    IntDSPINTCInit();

    // Enable DSP interrupts globally
    IntGlobalEnable();
#else
    /*Initialize the ARM Interrupt Controller(AINTC). */
    IntAINTCInit();

    /* Enable IRQ in CPSR.*/
    IntMasterIRQEnable();

    /* Enable the interrupts in GER of AINTC.*/
    IntGlobalEnable();

    /* Enable the interrupts in HIER of AINTC.*/
    IntIRQEnable();
#endif
}

/* EDMA3 Completion Handler */
static void edma3ComplHandler(unsigned int baseAdd, unsigned int regionNum)
{

#ifdef _TMS320C6X
    IntEventClear(SYS_INT_EDMA3_1_CC0_INT1);

#else
    IntSystemStatusClear(SYS_INT_CCINT0);
#endif

    HWREG(SOC_EDMA31CC_0_REGS + 0x1070) = 0x00000001;
    (*cb_Fxn[0])(0, EDMA3_XFER_COMPLETE);

 // TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);

}

static void Edma3ComplHandlerIsr(void)
{
 //  TimerIntDisable(SOC_TMR_3_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
 //   HWREG(0x01f0d044)|=0x00000010;   //enable int
#ifdef _TMS320C6X
    // Invoke Completion Handler ISR
    edma3ComplHandler(SOC_EDMA31CC_0_REGS, 1);
#else
    /* Invoke Completion Handler ISR */
    edma3ComplHandler(SOC_EDMA31CC_0_REGS, 0);
#endif
}

/* EDMA3 Error Handler */
static void edma3CCErrHandler(unsigned int baseAdd)
{
    volatile unsigned int pendingIrqs = 0;
    unsigned int regionNum = 0;
    unsigned int evtqueNum = 0;
    unsigned int index = 1;
    unsigned int Cnt = 0;

#ifdef _TMS320C6X
    IntEventClear(SYS_INT_EDMA3_1_CC0_ERRINT);
#else
    IntSystemStatusClear(SYS_INT_CCERRINT);
#endif

    if((HWREG(baseAdd + EDMA3CC_EMR) != 0 ) || \
       (HWREG(baseAdd + EDMA3CC_QEMR) != 0) || \
       (HWREG(baseAdd + EDMA3CC_CCERR) != 0))
    {
        /* Loop for EDMA3CC_ERR_HANDLER_RETRY_COUNT number of time, breaks
           when no pending interrupt is found */
        while ((Cnt < EDMA3CC_ERR_HANDLER_RETRY_COUNT) && (index != 0u))
        {
            index = 0u;
            pendingIrqs = HWREG(baseAdd + EDMA3CC_EMR);
            while (pendingIrqs)
            {
                /*Process all the pending interrupts*/
                if((pendingIrqs & 1u)==TRUE)
                {
                    /* Write to EMCR to clear the corresponding EMR bits.*/
                    HWREG(baseAdd + EDMA3CC_EMCR) = (1u<<index);
                    /*Clear any SER*/
                    HWREG(baseAdd + EDMA3CC_S_SECR(regionNum)) = (1u<<index);
                }
                ++index;
                pendingIrqs >>= 1u;
            }
            index = 0u;
            pendingIrqs = HWREG(baseAdd + EDMA3CC_QEMR);
            while (pendingIrqs)
            {
                /*Process all the pending interrupts*/
                if((pendingIrqs & 1u)==TRUE)
                {
                    /* Here write to QEMCR to clear the corresponding QEMR bits*/
                    HWREG(baseAdd + EDMA3CC_QEMCR) = (1u<<index);
                    /*Clear any QSER*/
                    HWREG(baseAdd + EDMA3CC_S_QSECR(0)) = (1u<<index);
                }
                ++index;
                pendingIrqs >>= 1u;
            }
            index = 0u;
            pendingIrqs = HWREG(baseAdd + EDMA3CC_CCERR);
    if (pendingIrqs != 0u)
    {
        /* Process all the pending CC error interrupts. */
        /* Queue threshold error for different event queues.*/
        for (evtqueNum = 0u; evtqueNum < EDMA3_0_NUM_EVTQUE; evtqueNum++)
        {
            if((pendingIrqs & (1u << evtqueNum)) != 0u)
            {
                /* Clear the error interrupt. */
                HWREG(baseAdd + EDMA3CC_CCERRCLR) = (1u << evtqueNum);
            }
         }

         /* Transfer completion code error. */
         if ((pendingIrqs & (1 << EDMA3CC_CCERR_TCCERR_SHIFT)) != 0u)
         {
             HWREG(baseAdd + EDMA3CC_CCERRCLR) = \
                  (0x01u << EDMA3CC_CCERR_TCCERR_SHIFT);
         }
         ++index;
    }
    Cnt++;
        }
    }
}

static void Edma3CCErrHandlerIsr()
{
    /* Invoke CC Error Handler ISR */
    edma3CCErrHandler(SOC_EDMA31CC_0_REGS);
}

/* Function to register EDMA3 Interuppts */
static void ConfigureIntEDMA3(void)
{
    /* Register Interrupts Here */

#ifdef _TMS320C6X
    IntRegister(C674X_MASK_INT4, Edma3ComplHandlerIsr);
    //IntRegister(C674X_MASK_INT6, Edma3ComplHandlerIsr1);
 //   IntRegister(C674X_MASK_INT5, Edma3CCErrHandlerIsr);
  //  IntRegister(C674X_MASK_INT6, TimerIsr);

    IntEventMap(C674X_MASK_INT4, SYS_INT_EDMA3_1_CC0_INT1);
    //IntEventMap(C674X_MASK_INT6, SYS_INT_EDMA3_0_CC0_INT2);
  //  IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_1_CC0_ERRINT);
  //  IntEventMap(C674X_MASK_INT6, SYS_INT_T64P3_TINTALL);

    IntEnable(C674X_MASK_INT4);
  //  IntEnable(C674X_MASK_INT5);
  //  IntEnable(C674X_MASK_INT6);

    #else
    IntRegister(SYS_INT_CCINT0, Edma3ComplHandlerIsr);

    IntChannelSet(SYS_INT_CCINT0, 2);

    IntSystemEnable(SYS_INT_CCINT0);

    IntRegister(SYS_INT_CCERRINT, Edma3CCErrHandlerIsr);

    IntChannelSet(SYS_INT_CCERRINT, 2);

    IntSystemEnable(SYS_INT_CCERRINT);
#endif
}

/*
** This function is used as a callback from EDMA3 Completion Handler.
** UART in DMA Mode is Disabled over here.
*/
static void callback(unsigned int tccNum, unsigned int status)
{
if(dummy_var<32)
    dummy_var++;
else
    dummy_var=0;
*(dummyptr)=dummy_var;

}

static void SetUpSPI(void)
{
    unsigned char cs  = 0x08;
    unsigned char dcs = 0x00;
    unsigned int  val = SIMO_SOMI_CLK_CS;
    SPIReset(SOC_SPI_0_REGS);

    SPIOutOfReset(SOC_SPI_0_REGS);

    SPIModeConfigure(SOC_SPI_0_REGS, SPI_MASTER_MODE);

    //SPIClkConfigure(SOC_SPI_1_REGS, 150000000, 20000000, SPI_DATA_FORMAT0);
    SPIClkConfigure(SOC_SPI_0_REGS, 228000000, 1000000, SPI_DATA_FORMAT0);

    SPIPinControl(SOC_SPI_0_REGS, 0, 0, &val);

//  SPIDefaultCSSet(SOC_SPI_0_REGS, 0x08);

    /* Configures SPI Data Format Register */
    SPIConfigDataFmtReg(SPI_DATA_FORMAT0);

     /* Selects the SPI Data format register to used and Sets CSHOLD
      * to assert CS pin(line)
      */
//  SPIDat1Config(SOC_SPI_0_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0xfb);

   // *ptr_spidat1=0x00f70000;
  //  *ptr_spidef=0x000000ff;

     /* map interrupts to interrupt line INT1 */
   // SPIIntLevelSet(SOC_SPI_0_REGS, SPI_RECV_INTLVL | SPI_TRANSMIT_INTLVL);

    /* Enable SPI communication */
    SPIEnable(SOC_SPI_0_REGS);

   // SPIIntEnable(SOC_SPI_0_REGS,SPI_TRANSMIT_INT);
}

static void SPIConfigDataFmtReg(unsigned int dataFormat)
{
    /* Configures the polarity and phase of SPI clock */
    /*
    SPIConfigClkFormat(SOC_SPI_1_REGS,
                       (SPI_CLK_POL_HIGH | SPI_CLK_INPHASE),
                       dataFormat);
    */
    SPIConfigClkFormat(SOC_SPI_1_REGS,
                       (SPI_CLK_POL_LOW | SPI_CLK_INPHASE),
                       dataFormat);

    /* Configures SPI to transmit MSB bit First during data transfer */
    SPIShiftMsbFirst(SOC_SPI_1_REGS, dataFormat);

    /* Sets the Charcter length */
    SPICharLengthSet(SOC_SPI_1_REGS, CHAR_LENGTH, dataFormat);
}