//###########################################################################
// Edited: WW   08/08/2019
// FILE:    HFB_Control_28379D_cpu02.c
//
// TITLE:   SPI communication running on CPU 02
//
//! This file is used for SPI communication using CPU 2 in order to release the computational resources on CPU 1
//! if
//!
//###############################################################################

//.............................Included Files.....................................
//
#include "F28x_Project.h"
#include "math.h"
#include "shared_var_longmax_28379D.h"
//#include "Function_define_WW_HFB_28379D.h"

extern volatile struct SPI_REGS* SPIs[3];
//###############################################################################
//........  IPC .............//
struct readIPC{                                                               // structure for read IPC function
    Uint32 command;
    Uint32 address;
    Uint32 data;
};
Uint32 wordlength = 0;                                                       // define word length for IPC, received from IPC data transfered from CPU 1
// Received measurements in the shared memory from CPU 1
float           V1_meas_avg_r      = 0.0;
float           V2_meas_avg_r      = 0.0;
float           I1_meas_avg_r      = 0.0;
float           I2_meas_avg_r      = 0.0;
float           V_LV_meas_avg_r    = 0.0;
float           I_LV_meas_avg_r    = 0.0;
float           IDC_meas_avg_r     = 0.0;

// Small segment can be stored in 'SHARERAMGS0_x'
//#pragma DATA_SECTION(sample_num,"SHARERAMGS0_0");
//#pragma DATA_SECTION(V1_meas_avg_r,"SHARERAMGS0_1");  // Note that the SHARERAMGS0_X is customized in the RAM_Ink_shared_cpu1_reallocateHFB.cmd
//#pragma DATA_SECTION(V2_meas_avg_r,"SHARERAMGS0_2");
//#pragma DATA_SECTION(I1_meas_avg_r,"SHARERAMGS0_3");
//#pragma DATA_SECTION(I2_meas_avg_r,"SHARERAMGS0_4");
//#pragma DATA_SECTION(V_LV_meas_avg_r,"SHARERAMGS0_5");
//#pragma DATA_SECTION(I_LV_meas_avg_r,"SHARERAMGS0_6");
//#pragma DATA_SECTION(IDC_meas_avg_r,"SHARERAMGS0_7");

// or big chunk with continuous address can be put into a big portion
#pragma DATA_SECTION(sData_32,"SHARERAMGS0_REST");
#pragma DATA_SECTION(tData,"SHARERAMGS1");                                 //JNIE_1206
//####################################################################################
//....................................... Interruption PIE.........................
__interrupt void spiTxFifoIsr(void);
__interrupt void spiRxFifoIsr(void);
__interrupt void local_D_INTCH5_ISR(void);
__interrupt void local_D_INTCH6_ISR(void);
//####################################################################################
void main(void)
{
//* Step 1. Initialize System Control:
//* PLL, WatchDog, enable Peripheral Clocks
//* This example function is found in the F2837xS_SysCtrl.c file.
    EALLOW;
    InitSysCtrl();
    InitIpc();
    EDIS;




//* Step 2. Initialize GPIO:
//* GPIO initialization is covered by CPU initialization
//* it's skipped here


//* Step 3. Clear all interrupTsample and initialize PIE vector table:
//* Disable CPU interrupTsample

    DINT;

//* Initialize the PIE control registers to their default state.
//* The default state is all PIE interrupTsample disabled and flags
//* are cleared.
//* This function is found in the F2837xS_PieCtrl.c file.

    InitPieCtrl();

//* Disable CPU interrupTsample and clear all CPU interrupt flags:

    IER = 0x0000;
    IFR = 0x0000;


//* Initialize the PIE vector table with pointers to the shell Interrupt
//* Service Routines (ISR).
//* This will populate the entire table, even if the interrupt
//* is not used in this example.  This is useful for debug purposes.
//* The shell ISR routines are found in F2837xS_DefaultIsr.c.
//* This function is found in F2837xS_PieVect.c.

    InitPieVectTable();


//* InterrupTsample that are used in this example are re-mapped to
//* ISR functions found within this file.

    EALLOW; // This is needed to write to EALLOW protected registers
        if (EN_SPI_DMA == 1)
        {
           PieVectTable.DMA_CH5_INT = &local_D_INTCH5_ISR;                // Interrupt service routine for DMA SPI transmitting update
           PieVectTable.DMA_CH6_INT = &local_D_INTCH6_ISR;                // Interrupt service routine for DMA SPI receiving update
        }

        else /* change SPI regs if different SPI is wanted */
        {
            if (SPI_use == 1)
            {
               PieVectTable.SPIB_RX_INT = &spiRxFifoIsr;                      // Interrupt service routine for SPIB FIFO Receiver
               PieVectTable.SPIB_TX_INT = &spiTxFifoIsr;                      // Interrupt service routine for SPIB FIFO Transmitter
            }
            else if (SPI_use == 0)
            {
               PieVectTable.SPIA_RX_INT = &spiRxFifoIsr;                   // Interrupt service routine for SPIA FIFO Receiver
               PieVectTable.SPIA_TX_INT = &spiTxFifoIsr;                   // Interrupt service routine for SPIA FIFO Transmitter
            }

//
        }
    EDIS;                                                                                // This is needed to disable write to EALLOW protected registers


//* Step 4. Initialize the Device Peripherals:
    if (EN_SPI_DMA == 1)
        dma_init(*sData_32, *rData_32 ,burst_tx, burst_rx, transfer);                          // Set up DMA for SPI configuration
    else
    {
        spi_fifo_init(SPI_use,fifo_rxlvl, fifo_txlvl, SPI_delay);                        // Initialize the SPI FIFO, FIFO is a buffer between TX and DTA
        Initspi(SPI_use,SLAVE,DIS_LOOPBACK,SPI_CPOL,SPI_CPHA,WORD_BIT);                  // Configure SPIA properties on 28379D
//        Initspi(SPI_use,MASTER,EN_LOOPBACK,SPI_CPOL,SPI_CPHA,WORD_BIT);                // Configure SPIA properties on 28379D
    }



    EALLOW;                                                                             //  Allow CPU to write to protected control regs
       if (EN_SPI_DMA == 1)
            CpuSysRegs.SECMSEL.bit.PF2SEL               = 1;                            //  Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)

    EDIS;                                                                               //  Protect the control regs again






//* Step 5. User specific code, enable interrupTsample:
//* Initialize counters:

    if (EN_SPI_DMA == 1)
        IER |= M_INT7;                                                    //  Enable INT group 7 where DMA interrupTsample locate
    else
        IER |= M_INT6;                                                    //  Enable INT group 6 where SPI FIFO interrupTsample belong to

    PieCtrlRegs.PIECTRL.bit.ENPIE     = 1;                                //  Enable the PIE block
    if (EN_SPI_DMA == 0)                                                  // Using SPI only
    {
        if (SPI_use == 1)
        {
            PieCtrlRegs.PIEIER6.bit.INTx3     = 1;                            //  Enable PIE Group 6, INT 1 SPIA RX, INT 3 SPIB RX
            PieCtrlRegs.PIEIER6.bit.INTx4     = 1;                            //  Enable PIE Group 6, INT 2 SPIA TX, INT 4 SPIB TX
        }
        else if (SPI_use == 0)
        {
            PieCtrlRegs.PIEIER6.bit.INTx1     = 1;                            //  Enable PIE Group 6, INT 1 SPIA RX, INT 3 SPIB RX
            PieCtrlRegs.PIEIER6.bit.INTx2     = 1;                            //  Enable PIE Group 6, INT 2 SPIA TX, INT 4 SPIB TX
        }

    }
    else                                                                  // Enable DMA for SPI
    {
        PieCtrlRegs.PIEIER7.bit.INTx5     = 1;                            //  Enable PIE Group 7, INT 5 (DMA CH5)
        PieCtrlRegs.PIEIER7.bit.INTx6     = 1;                            //  Enable PIE Group 7, INT 6 (DMA CH6)
    }







//    HRPWM_Config(10);

//* Step 6. IDLE loop. Just sit and loop forever (optional):
    if (EN_SPI_DMA == 1)                                                  // Enable DMA for SPI
    {
        StartDMACH6();                                                    // Start SPI RX DMA channel
        StartDMACH5();                                                    // Start SPI TX DMA channel
    }

    int i = 0;
    // Transmitting data initialization
    //
    for (i=0;i<ADC_trans_num;i++)
        sData_32[i] = 0;



    // assign the pointer to sData address to send via IPC
    sData_IPC = &sData_16;

    /*
     * Main loop
     */

    //* Enable global InterrupTsample and higher priority real-time debug evenTsample:
    EINT;                                                                 // Enable Global interrupt INTM
    ERTM;                                                                 // Enable Global realtime interrupt DBGM

    led_flag = led_default;               //JNIE_1206

    while(1)
    {
//        struct readIPC readIPCresult;
//
//        WaitForIpcAck(5);                                                     // Wait for IPC5 to be set -> ready to pick up
//        readIPCresult = ReadIpcCommand();                                     // read the command, word length, address
//
//        wordlength = (readIPCresult.command == IPC_command_wrdlen) ? readIPCresult.data : 0;
//
//
//        // Fetch data from CPU1
//        RecvIpcData(sData_IPC, wordlength);
//        AckIpcFlag(5);

    }

}
// ####################################################################################


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// ISR functions ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//
// spiTxFifoIsr - ISR for SPI transmit FIFO
//
//__interrupt void spiTxFifoIsr(void)
//{
//    Uint16 i;
//    sData[0]            =   sample_num;                                 // first column of the data is the sampling index
//
//
//    for(i=0;i<ADC_trans_num;i++)
//    {
//       SpibRegs.SPITXBUF=sData[i];                                      // Send data
////       rData[i]=SpiaRegs.SPIRXBUF;                                    // Read data
//    }
//    sample_num ++;                                                    // increase the index for next SPI fetch
////    for(i=0;i<7;i++)                                                  // Increment data for next cycle
////    {
////       sData[i] = sData[i] + 1;
////    }
//
//    SpibRegs.SPIFFTX.bit.TXFFINTCLR=1;                                  // Clear Interrupt flag for TX
////    SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;                                // Clear Overflow flag for RX
////    SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;                                // Clear Interrupt flag for RX
//
//    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP6;                              // Issue PIE ACK
//
//}

__interrupt void spiTxFifoIsr(void)
{
    Uint16 i;

//    WaitForIpcFlag(5);                       // wait for CPU1 release writing on the shared memory
    if (IpcRegs.IPCSTS.bit.IPC5 == 1)
    {
        //     Rearrange the 32-bit data to 2 16-bit data in order to send it through spitxbuf
        for (i = 0; i<ADC_trans_num*2; i+=2)
        {
            sData_16[i]   = (Uint16) (sData_32[i/2] >> 16);                   // pick the higher 16 bit from sData_32
            sData_16[i+1] = (Uint16) sData_32[i/2];                           // pick the lower 16 bit from sData_32

        }

        AckIpcFlag(5);                          // let CPU1 know data is fetched, can be modified now
                                                // read the shared memory and assign to SPITX buffer
                                                                                //if it's not updating
    }



    // Send received data to buffer
    for(i=0;i<ADC_trans_num*2;i++)
    {
//        sData_16[i] = i;                                                        // test
       (*SPIs[SPI_use]).SPITXBUF=sData_16[i];                                      // Send data
    }


    (*SPIs[SPI_use]).SPIFFTX.bit.TXFFINTCLR=1;                                  // Clear Interrupt flag for TX

    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP6;                              // Issue PIE ACK

//    {

//        readIPCresult = ReadIpcCommand();                                     // read the command, word length, address
//
//        wordlength = (readIPCresult.command == IPC_command_wrdlen) ? readIPCresult.data : 0;
//
//
//        // Fetch data from CPU1
//        RecvIpcData(sData_IPC, wordlength);

//    }
//    WaitForIpcAck(5);                                                     // Wait for IPC5 to be set -> ready to pick up
                                        // Indicating the CPU 2 finishes reading data, CPU 1 can put more data







}
//
// spiRxFifoIsr - ISR for SPI receive FIFO
//
//__interrupt void spiRxFifoIsr(void)
//{
//    Uint16 i;
//
//    for(i=0; i<ADC_trans_num; i++)
//    {
//        rData[i]=SpibRegs.SPIRXBUF;                                     // Read data
//    }
//
////    for(i=0; i<2; i++)                                                // Check received data
////    {
////        if(rData[i] != rData_point+i)
////        {
////            error();
////        }
////    }
//
////    rData_point++;
//    SpibRegs.SPIFFRX.bit.RXFFOVFCLR=1;                                  // Clear Overflow flag
//    SpibRegs.SPIFFRX.bit.RXFFINTCLR=1;                                  // Clear Interrupt flag
//    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP6;                              // Issue PIE ack
//}
__interrupt void spiRxFifoIsr(void)
{
    Uint16 i;

    for(i=0; i<ADC_trans_num*2; i++)
    {
        rData_16[i] = (*SPIs[SPI_use]).SPIRXBUF;
    }
    if(IpcRegs.IPCSTS.bit.IPC6==1){
        for(i=0; i<ADC_trans_num*2; i+=2)
        {
            Uint32 rData_high = (Uint32) (rData_16[i] << 16);
            Uint32 rData_low = (Uint32) (rData_16[i+1]);
            rData_32[i/2] = rData_high | rData_low;
        }
        AckIpcFlag(6);
        //memcpy(&tData[0],&rData_32[0], sizeofIPC);
        for(i=0; i<ADC_trans_num; i+=1)   //JNIE_1206
            if(rData_32[i] != led_default && rData_32[i] != led_flag)
            {
                led_flag = rData_32[i];
                if(led_flag>led_off){
                    memcpy(&tData[1],&led_flag, sizeofIPC);
                    tData[1]=tData[1]-10000.0;
                }
                else{
                    memcpy(&tData[0],&led_flag, sizeofIPC);
                }
            }
    }
//    for(i=0; i<2; i++)                                                // Check received data
//    {
//        if(rData[i] != rData_point+i)
//        {
//            error();
//        }
//    }

//    rData_point++;
    (*SPIs[SPI_use]).SPIFFRX.bit.RXFFOVFCLR=1;                                  // Clear Overflow flag
    (*SPIs[SPI_use]).SPIFFRX.bit.RXFFINTCLR=1;                                  // Clear Interrupt flag
    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP6;                              // Issue PIE ack
}


//
// local_D_INTCH5_ISR - DMA Channel 5 ISR
//
__interrupt void local_D_INTCH5_ISR(void)
{
    EALLOW;                                                             // NEED TO EXECUTE EALLOW INSIDE ISR !!!
        DmaRegs.CH5.CONTROL.bit.HALT    =1;
        PieCtrlRegs.PIEACK.all          = PIEACK_GROUP7;                // ACK to receive more interrupTsample from this PIE group
    EDIS;
    return;
}

//
// local_D_INTCH6_ISR - DMA Channel 6 ISR
//
__interrupt void local_D_INTCH6_ISR(void)
{

    EALLOW;                                                             // NEED TO EXECUTE EALLOW INSIDE ISR !!!
        DmaRegs.CH6.CONTROL.bit.HALT = 1;
        PieCtrlRegs.PIEACK.all       = PIEACK_GROUP7;                   // ACK to receive more interrupTsample from this PIE group
    EDIS;

    return;
}





